3 Copyright (c) 2002-2016 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE/SATA/AHCI controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are significantly changed/updated by
41 Alter, Copyright (c) 2002-2014:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2/SATA3) support
51 9. NT 3.51 support (binary compatibility)
65 static const CHAR ver_string
[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR
"\n";
67 static const CHAR uniata_comm_name
[] = UNIATA_COMM_PORT_VENDOR_STR
" \n";
69 UNICODE_STRING SavedRegPath
;
70 WCHAR SavedRegPathBuffer
[256];
74 //UCHAR AtaCommands48[256];
75 //UCHAR AtaCommandFlags[256];
78 ULONG ForceSimplex
= 0;
84 ULONG g_LogToDisplay
= 0;
87 ULONG g_WaitBusyInISR
= 1;
89 ULONG g_opt_WaitBusyResetCount
= 10000; // 20000
90 ULONG g_opt_WaitBusyCount
= 200; // 20000
91 ULONG g_opt_WaitBusyDelay
= 10; // 150
92 ULONG g_opt_WaitDrqDelay
= 10; // 100
93 ULONG g_opt_WaitBusyLongCount
= 2000; // 2000
94 ULONG g_opt_WaitBusyLongDelay
= 250; // 250
95 ULONG g_opt_MaxIsrWait
= 40;
97 ULONG g_opt_DriveSelectNanoDelay
= 0; // 400; // ns
99 BOOLEAN g_opt_AtapiSendDisableIntr
= 0; // 0
100 BOOLEAN g_opt_AtapiDmaRawRead
= 1; // 0
101 BOOLEAN g_opt_AtapiNoDma
= FALSE
;
102 BOOLEAN g_opt_BochsDmaReadWorkaround
= FALSE
;
103 BOOLEAN hasPCI
= FALSE
;
105 ULONG g_opt_VirtualMachine
= 0; // Auto
107 BOOLEAN InDriverEntry
= TRUE
;
108 BOOLEAN g_Dump
= FALSE
;
110 BOOLEAN g_opt_Verbose
= 0;
112 BOOLEAN WinVer_WDM_Model
= FALSE
;
115 //UCHAR EnableDma = FALSE;
116 //UCHAR EnableReorder = FALSE;
122 AtapiResetController__(
123 IN PVOID HwDeviceExtension
,
125 IN UCHAR CompleteType
131 IN PHW_DEVICE_EXTENSION deviceExtension
,
137 UniataUserDeviceReset(
138 PHW_DEVICE_EXTENSION deviceExtension
,
139 PHW_LU_EXTENSION LunExt
,
143 #define RESET_COMPLETE_CURRENT 0x00
144 #define RESET_COMPLETE_ALL 0x01
145 #define RESET_COMPLETE_NONE 0x02
152 IN PVOID HwDeviceExtension
155 #ifdef UNIATA_USE_XXableInterrupts
156 #define RETTYPE_XXableInterrupts BOOLEAN
157 #define RETVAL_XXableInterrupts TRUE
159 #define RETTYPE_XXableInterrupts VOID
160 #define RETVAL_XXableInterrupts
163 RETTYPE_XXableInterrupts
166 IN PVOID HwDeviceExtension
169 RETTYPE_XXableInterrupts
171 AtapiEnableInterrupts__(
172 IN PVOID HwDeviceExtension
178 IN PVOID HwDeviceExtension
,
180 IN PHW_TIMER HwScsiTimer
,
181 IN ULONG MiniportTimerValue
184 SCSI_ADAPTER_CONTROL_STATUS
187 IN PVOID HwDeviceExtension
,
188 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
198 AtapiRegGetStringParameterValue(
199 IN PWSTR RegistryPath
,
205 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
207 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
212 ustr
.MaximumLength
= (USHORT
)MaxLen
;
213 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
215 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
216 parameters
[0].Name
= Name
;
217 parameters
[0].EntryContext
= &ustr
;
218 parameters
[0].DefaultType
= REG_SZ
;
219 parameters
[0].DefaultData
= Str
;
220 parameters
[0].DefaultLength
= MaxLen
;
222 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
223 RegistryPath
, parameters
, NULL
, NULL
);
225 if(!NT_SUCCESS(status
))
230 #undef ITEMS_TO_QUERY
231 } // end AtapiRegGetStringParameterValue()
249 if(!nano
|| !g_Perf
|| !g_PerfDt
)
251 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
256 KeQuerySystemTime(&t0
);
259 } // end UniataNanoSleep()
261 #define AtapiWritePortN_template(_type, _Type, sz) \
264 AtapiWritePort##sz( \
265 IN PHW_CHANNEL chan, \
266 IN ULONGIO_PTR _port, \
271 if(_port >= IDX_MAX_REG) { \
272 res = (PIORES)(_port); \
275 res = &chan->RegTranslation[_port]; \
277 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
281 KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \
282 ASSERT(FALSE); /* We should never get here */ \
285 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
287 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
288 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
293 AtapiWritePortN_template(ULONG
, Ulong
, 4);
294 AtapiWritePortN_template(USHORT
, Ushort
, 2);
295 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
297 #define AtapiWritePortExN_template(_type, _Type, sz) \
300 AtapiWritePortEx##sz( \
301 IN PHW_CHANNEL chan, \
302 IN ULONGIO_PTR _port, \
308 if(_port >= IDX_MAX_REG) { \
309 res = (PIORES)(_port); \
312 res = &chan->RegTranslation[_port]; \
314 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
318 KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
319 ASSERT(FALSE); /* We should never get here */ \
322 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
324 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
325 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
330 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
331 //AtapiWritePortExN_template(USHORT, Ushort, 2);
332 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
334 #define AtapiReadPortN_template(_type, _Type, sz) \
338 IN PHW_CHANNEL chan, \
339 IN ULONGIO_PTR _port \
343 if(_port >= IDX_MAX_REG) { \
344 res = (PIORES)(_port); \
347 res = &chan->RegTranslation[_port]; \
349 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
350 return (_type)(-1); \
353 KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \
354 ASSERT(FALSE); /* We should never get here */ \
357 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
358 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
360 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
361 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
365 AtapiReadPortN_template(ULONG
, Ulong
, 4);
366 AtapiReadPortN_template(USHORT
, Ushort
, 2);
367 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
369 #define AtapiReadPortExN_template(_type, _Type, sz) \
372 AtapiReadPortEx##sz( \
373 IN PHW_CHANNEL chan, \
374 IN ULONGIO_PTR _port, \
379 if(_port >= IDX_MAX_REG) { \
380 res = (PIORES)(_port); \
383 res = &chan->RegTranslation[_port]; \
385 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
386 return (_type)(-1); \
389 KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
390 ASSERT(FALSE); /* We should never get here */ \
393 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
395 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
396 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
400 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
401 //AtapiReadPortExN_template(USHORT, Ushort, 2);
402 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
404 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
407 AtapiReadBuffer##sz( \
408 IN PHW_CHANNEL chan, \
409 IN ULONGIO_PTR _port, \
419 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
421 Buffer = ((_type*)Buffer)+1; \
422 UniataNanoSleep(Timing); \
427 if(_port >= IDX_MAX_REG) { \
428 res = (PIORES)(_port); \
431 res = &chan->RegTranslation[_port]; \
433 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
437 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
438 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
442 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
444 Buffer = ((_type*)Buffer)+1; \
449 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
452 AtapiWriteBuffer##sz( \
453 IN PHW_CHANNEL chan, \
454 IN ULONGIO_PTR _port, \
464 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
465 Buffer = ((_type*)Buffer)+1; \
467 UniataNanoSleep(Timing); \
472 if(_port >= IDX_MAX_REG) { \
473 res = (PIORES)(_port); \
476 res = &chan->RegTranslation[_port]; \
478 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
482 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
483 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
487 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
489 Buffer = ((_type*)Buffer)+1; \
494 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
495 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
497 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
498 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
510 // Assume, proper drive is already seleted
511 WaitOnBusyLong(chan
);
512 for (i
= 0; i
< 0x10000; i
++) {
514 GetStatus(chan
, statusByte
);
515 if (statusByte
& IDE_STATUS_DRQ
) {
516 // Suck out any remaining bytes and throw away.
517 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
518 UniataNanoSleep(PIO0_TIMING
);
524 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
527 } // AtapiSuckPort2()
531 AtapiSuckPortBuffer2(
540 BOOLEAN retry
= FALSE
;
542 // Assume, proper drive is already seleted
543 WaitOnBusyLong(chan
);
544 for (i
= 0; i
< Count
; i
++) {
546 GetStatus(chan
, statusByte
);
547 if (statusByte
& IDE_STATUS_DRQ
) {
548 // Suck out any remaining bytes and throw away.
549 data
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
553 UniataNanoSleep(PIO0_TIMING
);
556 if(i
<Count
&& !retry
) {
557 KdPrint2((PRINT_PREFIX
" wait...\n"));
565 KdPrint2((PRINT_PREFIX
"AtapiSuckPortBuffer2: %#x words\n", i
));
567 AtapiSuckPort2(chan
);
571 } // AtapiSuckPortBuffer2()
577 IN ULONG DeviceNumber
584 if(chan->lun[DeviceNumber] &&
585 (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
586 KdPrint3((" Select %d\n", DeviceNumber));
589 if(chan
->last_devsel
== DeviceNumber
) {
590 //KdPrint3((" Selected %d\n", DeviceNumber));
593 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
); \
594 chan
->last_devsel
= DeviceNumber
? 1 : 0;
595 if(!g_opt_DriveSelectNanoDelay
) {
596 //KdPrint3((" Select %d\n", DeviceNumber));
599 //KdPrint3((" Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
600 UniataNanoSleep(g_opt_DriveSelectNanoDelay
);
602 } // end SelectDrive()
613 GetStatus(chan
, Status
);
614 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
615 if (Status
& IDE_STATUS_BUSY
) {
616 AtapiStallExecution(g_opt_WaitBusyDelay
);
617 GetStatus(chan
, Status
);
624 } // end WaitOnBusy()
635 Status
= WaitOnBusy(chan
);
636 if(!(Status
& IDE_STATUS_BUSY
))
638 for (i
=0; i
<g_opt_WaitBusyLongCount
; i
++) {
639 GetStatus(chan
, Status
);
640 if (Status
& IDE_STATUS_BUSY
) {
641 AtapiStallExecution(g_opt_WaitBusyLongDelay
);
648 } // end WaitOnBusyLong()
657 UCHAR Status
= IDE_STATUS_WRONG
;
658 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
659 GetBaseStatus(chan
, Status
);
660 if (Status
& IDE_STATUS_BUSY
) {
661 AtapiStallExecution(g_opt_WaitBusyDelay
);
668 } // end WaitOnBaseBusy()
679 Status
= WaitOnBaseBusy(chan
);
680 if(!(Status
& IDE_STATUS_BUSY
))
682 for (i
=0; i
<2000; i
++) {
683 GetBaseStatus(chan
, Status
);
684 if (Status
& IDE_STATUS_BUSY
) {
685 AtapiStallExecution(250);
692 } // end WaitOnBaseBusyLong()
697 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
703 if(Status
== IDE_STATUS_WRONG
) {
704 return IDE_STATUS_WRONG
;
706 if(Status
& IDE_STATUS_BUSY
) {
709 // if(deviceExtension->HwFlags & UNIATA_SATA) {
710 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
711 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
715 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
716 if ((Status
& IDE_STATUS_BUSY
) ||
717 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
721 return IDE_STATUS_IDLE
;
722 } // end UniataIsIdle()
733 for (i
=0; i
<20000; i
++) {
734 GetStatus(chan
, Status
);
735 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
736 if(Status2
== IDE_STATUS_WRONG
) {
740 if(Status2
& IDE_STATUS_BUSY
) {
741 AtapiStallExecution(10);
748 } // end WaitForIdleLong()
758 for (i
=0; i
<1000; i
++) {
759 GetStatus(chan
, Status
);
760 if (Status
& IDE_STATUS_BUSY
) {
761 AtapiStallExecution(g_opt_WaitDrqDelay
);
762 } else if (Status
& IDE_STATUS_DRQ
) {
765 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
769 } // end WaitForDrq()
779 for (i
=0; i
<2; i
++) {
780 GetStatus(chan
, Status
);
781 if (Status
& IDE_STATUS_BUSY
) {
782 AtapiStallExecution(g_opt_WaitDrqDelay
);
783 } else if (Status
& IDE_STATUS_DRQ
) {
786 AtapiStallExecution(g_opt_WaitDrqDelay
);
790 } // end WaitShortForDrq()
796 IN ULONG DeviceNumber
799 //ULONG c = chan->lChannel;
801 UCHAR dma_status
= 0;
802 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
803 UCHAR statusByte0
, statusByte2
;
805 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
806 UniataAhciSoftReset(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
);
810 GetBaseStatus(chan
, statusByte2
);
811 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
812 SelectDrive(chan
, DeviceNumber
);
813 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
815 KdPrint2((PRINT_PREFIX
" ESDI/MFM\n"));
816 AtapiStallExecution(10000);
817 for (i
= 0; i
< 1000; i
++) {
818 AtapiStallExecution(999);
821 // Seems to be unnecessary, verified by KtP
823 // original atapi.sys behavior for old ISA-only hardware
824 AtapiStallExecution(10000);
825 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
826 for (i = 0; i < 1000; i++) {
827 AtapiStallExecution(999);
830 AtapiStallExecution(500);
831 GetBaseStatus(chan
, statusByte2
);
832 statusByte0
= statusByte2
;
833 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
835 // Do not wait for BUSY assertion if it was initially set, jump to
836 // BUSY release wait loop
837 if(!(statusByte0
& IDE_STATUS_BUSY
)) {
838 // Wait for BUSY assertion, in some cases delay may occure
839 // 100ms should be enough
840 if(g_opt_VirtualMachine
== VM_BOCHS
) {
845 statusByte2
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
846 while (!(statusByte2
& IDE_STATUS_BUSY
) &&
849 if(!(statusByte0
& IDE_STATUS_ERROR
) && (statusByte2
& IDE_STATUS_ERROR
)) {
850 KdPrint2((PRINT_PREFIX
" Command aborted, statusByte2 %x:\n", statusByte2
));
853 AtapiStallExecution(10);
858 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
859 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
860 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
861 // implementation. (which is around 1 second)
862 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
865 AtapiStallExecution(30);
867 KdPrint2((PRINT_PREFIX
" set DFLAGS_REINIT_DMA\n"));
868 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
871 chan
->last_devsel
= -1; // make sure proper drive would be selected
872 SelectDrive(chan
, DeviceNumber
);
874 GetBaseStatus(chan
, statusByte2
);
875 AtapiStallExecution(500);
877 GetBaseStatus(chan
, statusByte2
);
878 if(chan
&& chan
->DeviceExtension
) {
879 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
880 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
882 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
884 if(dma_status
& BM_STATUS_INTR
) {
885 // bullshit, we have DMA interrupt, but had never initiate DMA operation
886 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
887 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
888 GetBaseStatus(chan
, statusByte2
);
890 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
891 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
892 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
893 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
898 } // end AtapiSoftReset()
903 IN
struct _HW_CHANNEL
* chan
,
904 IN BOOLEAN DisableInterrupts
,
908 KdPrint2((PRINT_PREFIX
"AtapiHardReset: %d, dis=%d\n", Delay
, DisableInterrupts
));
909 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_RESET_CONTROLLER
|
910 (DisableInterrupts
? IDE_DC_DISABLE_INTERRUPTS
: 0));
911 chan
->last_devsel
= -1;
912 AtapiStallExecution(Delay
);
913 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_REENABLE_CONTROLLER
);
914 } // end AtapiHardReset()
917 Send command to device.
918 Translate to 48-Lba form if required
923 IN PHW_DEVICE_EXTENSION deviceExtension
,
924 IN ULONG DeviceNumber
,
933 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
938 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
939 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
941 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
942 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
944 KdPrint3((" (ahci)\n"));
946 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
947 (PSCSI_REQUEST_BLOCK
)NULL
,
955 1000 /* timeout 1 sec */
961 SelectDrive(chan
, DeviceNumber
);
963 statusByte
= WaitOnBusy(chan
);
965 /* ready to issue command ? */
966 if (statusByte
& IDE_STATUS_BUSY
) {
967 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
970 // !!! We should not check ERROR condition here
971 // ERROR bit may be asserted durring previous operation
972 // and not cleared after SELECT
974 //>>>>>> NV: 2006/08/03
975 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
976 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
977 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
978 return IDE_STATUS_ERROR
;
979 //return SRB_STATUS_ERROR;
981 //<<<<<< NV: 2006/08/03
983 /* only use 48bit addressing if needed because of the overhead */
984 if (UniAta_need_lba48(command
, lba
, count
,
985 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
987 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
988 /* translate command into 48bit version */
989 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
990 command
= AtaCommands48
[command
];
992 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
996 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
999 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
1000 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
1001 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
1002 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
1003 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
1004 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
1005 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
1006 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
1007 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
1008 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
1010 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
1011 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
1014 plba
= (PUCHAR
)&lba
; //ktp
1015 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1018 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
1019 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
1021 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
1022 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
1023 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
1024 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
1025 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1026 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
1027 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
1029 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
1030 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
1034 // write command code to device
1035 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
1037 switch (wait_flags
) {
1040 // caller requested wait for interrupt
1043 statusByte
= WaitForDrq(chan
);
1044 if (statusByte
& IDE_STATUS_DRQ
)
1046 AtapiStallExecution(500);
1047 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
1054 // caller requested wait for entering Wait state
1055 for (i
=0; i
<30 * 1000; i
++) {
1057 GetStatus(chan
, statusByte
);
1058 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1059 if(statusByte
== IDE_STATUS_WRONG
) {
1063 if(statusByte
& IDE_STATUS_ERROR
) {
1066 if(statusByte
& IDE_STATUS_BUSY
) {
1067 AtapiStallExecution(100);
1070 if((statusByte
& ~IDE_STATUS_INDEX
) == IDE_STATUS_IDLE
) {
1073 //if(deviceExtension->HwFlags & UNIATA_SATA) {
1074 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1077 AtapiStallExecution(100);
1080 //statusByte |= IDE_STATUS_BUSY;
1083 case ATA_WAIT_READY
:
1084 statusByte
= WaitOnBusyLong(chan
);
1086 case ATA_WAIT_BASE_READY
:
1087 statusByte
= WaitOnBaseBusyLong(chan
);
1090 GetStatus(chan
, statusByte
);
1091 if (statusByte
& IDE_STATUS_ERROR
) {
1092 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
1093 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
1096 KdPrint2((PRINT_PREFIX
" try to continue\n"));
1097 statusByte
&= ~IDE_STATUS_ERROR
;
1100 //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte));
1102 UniataExpectChannelInterrupt(chan
, TRUE
);
1104 InterlockedExchange(&(chan
->CheckIntr
),
1107 statusByte
= IDE_STATUS_SUCCESS
;
1111 //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
1114 } // end AtaCommand48()
1117 Send command to device.
1118 This is simply wrapper for AtaCommand48()
1123 IN PHW_DEVICE_EXTENSION deviceExtension
,
1124 IN ULONG DeviceNumber
,
1135 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
1136 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1138 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1139 count
, feature
, wait_flags
);
1141 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
1142 (PSCSI_REQUEST_BLOCK
)NULL
,
1146 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1149 0 /* ahci flags */ ,
1151 1000 /* timeout 1 sec */
1155 } // end AtaCommand()
1159 AtaPio2Mode(LONG pio
)
1162 default: return ATA_PIO
;
1163 case 0: return ATA_PIO0
;
1164 case 1: return ATA_PIO1
;
1165 case 2: return ATA_PIO2
;
1166 case 3: return ATA_PIO3
;
1167 case 4: return ATA_PIO4
;
1168 case 5: return ATA_PIO5
;
1170 } // end AtaPio2Mode()
1174 AtaPioMode(PIDENTIFY_DATA2 ident
)
1176 if (ident
->PioTimingsValid
) {
1177 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1179 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1181 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1184 if (ident
->PioCycleTimingMode
== 2)
1186 if (ident
->PioCycleTimingMode
== 1)
1188 if (ident
->PioCycleTimingMode
== 0)
1190 return IOMODE_NOT_SPECIFIED
;
1191 } // end AtaPioMode()
1195 AtaWmode(PIDENTIFY_DATA2 ident
)
1197 if (ident
->MultiWordDMASupport
& 0x04)
1199 if (ident
->MultiWordDMASupport
& 0x02)
1201 if (ident
->MultiWordDMASupport
& 0x01)
1203 return IOMODE_NOT_SPECIFIED
;
1208 AtaUmode(PIDENTIFY_DATA2 ident
)
1210 if (!ident
->UdmaModesValid
)
1211 return IOMODE_NOT_SPECIFIED
;
1212 if (ident
->UltraDMASupport
& 0x40)
1214 if (ident
->UltraDMASupport
& 0x20)
1216 if (ident
->UltraDMASupport
& 0x10)
1218 if (ident
->UltraDMASupport
& 0x08)
1220 if (ident
->UltraDMASupport
& 0x04)
1222 if (ident
->UltraDMASupport
& 0x02)
1224 if (ident
->UltraDMASupport
& 0x01)
1226 return IOMODE_NOT_SPECIFIED
;
1231 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1232 if(!ident
->SataCapabilities
||
1233 ident
->SataCapabilities
== 0xffff) {
1234 return IOMODE_NOT_SPECIFIED
;
1236 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1239 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1242 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1245 return IOMODE_NOT_SPECIFIED
;
1246 } // end AtaSAmode()
1253 IN PVOID HwDeviceExtension
1256 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1257 PHW_TIMER HwScsiTimer
;
1259 ULONG MiniportTimerValue
;
1260 BOOLEAN recall
= FALSE
;
1264 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1266 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1267 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1268 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1271 chan
= &(deviceExtension
->chan
[lChannel
]);
1275 HwScsiTimer
= chan
->HwScsiTimer
;
1276 chan
->HwScsiTimer
= NULL
;
1278 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1279 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1283 HwScsiTimer(HwDeviceExtension
);
1285 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1287 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1288 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1289 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1290 deviceExtension
->FirstDpcChan
=
1291 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1295 KeQuerySystemTime(&time
);
1296 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1298 chan
= &deviceExtension
->chan
[lChannel
];
1299 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1301 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1302 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1309 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1310 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1311 if(!MiniportTimerValue
)
1312 MiniportTimerValue
= 1;
1314 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1315 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1322 } // end AtapiTimerDpc()
1325 Wrapper for ScsiPort, that implements smart Dpc
1326 queueing. We need it to allow parallel functioning
1327 of IDE channels with shared interrupt. Standard Dpc mechanism
1328 cancels previous Dpc request (if any), but we need Dpc queue.
1333 IN PVOID HwDeviceExtension
,
1335 IN PHW_TIMER HwScsiTimer
,
1336 IN ULONG MiniportTimerValue
1339 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1341 LARGE_INTEGER time2
;
1343 PHW_CHANNEL prev_chan
;
1345 // BOOLEAN UseRequestTimerCall = TRUE;
1347 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1348 KeQuerySystemTime(&time
);
1350 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1351 time
.QuadPart
+= MiniportTimerValue
*10;
1352 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1354 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1356 i
= deviceExtension
->FirstDpcChan
;
1357 chan
= prev_chan
= NULL
;
1358 while(i
!= CHAN_NOT_SPECIFIED
) {
1360 chan
= &(deviceExtension
->chan
[i
]);
1361 if(chan
->DpcTime
> time
.QuadPart
) {
1364 i
= chan
->NextDpcChan
;
1366 chan
= &(deviceExtension
->chan
[lChannel
]);
1368 deviceExtension
->FirstDpcChan
= lChannel
;
1370 prev_chan
->NextDpcChan
= lChannel
;
1372 chan
->NextDpcChan
= i
;
1373 chan
->HwScsiTimer
= HwScsiTimer
;
1374 chan
->DpcTime
= time
.QuadPart
;
1376 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1377 if(time
.QuadPart
<= time2
.QuadPart
) {
1378 MiniportTimerValue
= 1;
1380 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1383 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1384 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1386 MiniportTimerValue
);
1388 } // end AtapiQueueTimerDpc()
1390 #endif //UNIATA_CORE
1400 UCHAR statusByteAlt
;
1402 GetStatus(chan
, statusByteAlt
);
1403 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1405 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1406 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1407 KdPrint2((PRINT_PREFIX
1408 " Reg_%#x (%#x) = %#x\n",
1410 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1413 if(!chan
->RegTranslation
[IDX_BM_IO
].Addr
) {
1416 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1417 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1418 KdPrint2((PRINT_PREFIX
1419 " BM_%#x (%#x) = %#x\n",
1421 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1425 } // end UniataDumpATARegs()
1431 IN PHW_CHANNEL chan
,
1432 IN ULONG DeviceNumber
,
1433 IN OUT PIDEREGS_EX regs
1436 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1438 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1440 // SATA/PATA, assume drive is selected
1442 UCHAR statusByteAlt
;
1444 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1445 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1446 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1447 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1451 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1452 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1453 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1454 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1455 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1456 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1458 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1462 } // end UniataSnapAtaRegs()
1466 Routine Description:
1468 Issue IDENTIFY command to a device.
1472 HwDeviceExtension - HBA miniport driver's adapter data storage
1473 DeviceNumber - Indicates which device.
1474 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1478 TRUE if all goes well.
1484 IN PVOID HwDeviceExtension
,
1485 IN ULONG DeviceNumber
,
1491 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1492 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1493 ULONG waitCount
= 50000;
1496 //UCHAR statusByte2;
1499 BOOLEAN atapiDev
= FALSE
;
1500 BOOLEAN use_ahci
= FALSE
;
1501 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1503 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1504 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1506 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1507 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1510 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1514 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1515 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1518 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1519 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1524 statusByte
= WaitOnBusyLong(chan
);
1526 if(!chan
->AhciInternalAtaReq
) {
1527 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1531 SelectDrive(chan
, DeviceNumber
);
1532 AtapiStallExecution(10);
1533 statusByte
= WaitOnBusyLong(chan
);
1534 // Check that the status register makes sense.
1535 GetBaseStatus(chan
, statusByte
);
1539 // original atapi.sys behavior for old ISA-only hardware
1540 AtapiStallExecution(100);
1545 if (Command
== IDE_COMMAND_IDENTIFY
) {
1546 // Mask status byte ERROR bits.
1547 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1548 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1549 // Check if register value is reasonable.
1551 if(statusByte
!= IDE_STATUS_IDLE
) {
1553 // No reset here !!!
1554 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1556 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1557 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1558 SelectDrive(chan
, DeviceNumber
);
1559 WaitOnBusyLong(chan
);
1561 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1562 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1564 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1565 signatureHigh
== ATAPI_MAGIC_MSB
) {
1567 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1571 // We really should wait up to 31 seconds
1572 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1573 // (30 seconds for device 1)
1575 // Wait for Busy to drop.
1576 AtapiStallExecution(100);
1577 GetStatus(chan
, statusByte
);
1578 if(statusByte
== IDE_STATUS_WRONG
) {
1579 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1583 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1584 GetBaseStatus(chan
, statusByte
);
1586 SelectDrive(chan
, DeviceNumber
);
1588 GetBaseStatus(chan
, statusByte
);
1590 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1592 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1593 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1595 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1596 signatureHigh
== ATAPI_MAGIC_MSB
) {
1597 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1602 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1603 if (statusByte
!= IDE_STATUS_IDLE
) {
1605 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1610 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1611 if(statusByte
== IDE_STATUS_WRONG
) {
1614 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1615 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1616 statusByte
= WaitForIdleLong(chan
);
1617 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1622 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1624 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1625 (PSCSI_REQUEST_BLOCK
)NULL
,
1626 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1631 0 /* ahci flags */ ,
1633 1000 /* timeout 1 sec */
1635 j
= 9; // AHCI is rather different, skip loop at all
1637 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1638 j
= 9; // don't send IDENTIFY, assume it is not supported
1639 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1640 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1641 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1643 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1644 j
= 4; // skip old-style checks
1648 for (; j
< 4*2; j
++) {
1649 // Send IDENTIFY command.
1651 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1653 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1657 KdPrint2((PRINT_PREFIX
"IssueIdentify: 0-status, not present\n"));
1660 if (statusByte
& IDE_STATUS_DRQ
) {
1661 // Read status to acknowledge any interrupts generated.
1662 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1663 GetBaseStatus(chan
, statusByte
);
1664 // One last check for Atapi.
1665 if (Command
== IDE_COMMAND_IDENTIFY
) {
1666 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1667 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1669 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1670 signatureHigh
== ATAPI_MAGIC_MSB
) {
1671 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1678 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1679 if (Command
== IDE_COMMAND_IDENTIFY
) {
1680 // Check the signature. If DRQ didn't come up it's likely Atapi.
1681 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1682 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1684 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1685 signatureHigh
== ATAPI_MAGIC_MSB
) {
1687 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1691 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1692 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1696 // Device didn't respond correctly. It will be given one more chance.
1697 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1698 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1699 GetBaseStatus(chan
, statusByte
);
1700 AtapiSoftReset(chan
,DeviceNumber
);
1702 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1703 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1705 GetBaseStatus(chan
, statusByte
);
1706 //GetStatus(chan, statusByte);
1707 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1710 // Check for error on really stupid master devices that assert random
1711 // patterns of bits in the status register at the slave address.
1712 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1713 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1718 // everything should already be done by controller
1720 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1721 j
= 9; // don't send IDENTIFY, assume it is not supported
1722 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1723 statusByte
= WaitForDrq(chan
);
1724 statusByte
= WaitOnBusyLong(chan
);
1725 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1726 GetBaseStatus(chan
, statusByte
);
1729 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1730 // Suck out 256 words. After waiting for one model that asserts busy
1731 // after receiving the Packet Identify command.
1732 statusByte
= WaitForDrq(chan
);
1733 statusByte
= WaitOnBusyLong(chan
);
1734 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1736 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1737 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1738 GetBaseStatus(chan
, statusByte
);
1741 GetBaseStatus(chan
, statusByte
);
1742 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1746 j
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
1747 KdPrint3((PRINT_PREFIX
"IssueIdentify: iReason %x\n", j
));
1750 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
1753 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
1754 KdPrint3((PRINT_PREFIX
"IssueIdentify: wCount %x\n", j
));
1759 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1761 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1762 // ATI/SII chipsets with memory-mapped IO hangs when
1763 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1764 // Unfortunately, I don't know yet how to workaround it except
1765 // spacifying manual delay in the way you see below.
1766 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1768 // Work around for some IDE and one model Atapi that will present more than
1769 // 256 bytes for the Identify data.
1770 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1771 statusByte
= AtapiSuckPort2(chan
);
1773 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1774 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1777 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1778 statusByte
= WaitForDrq(chan
);
1779 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1780 GetBaseStatus(chan
, statusByte
);
1782 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1785 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1789 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1790 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1791 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1792 if(g_opt_VirtualMachine
== VM_AUTO
) {
1793 if((deviceExtension
->FullIdentifyData
.FirmwareRevision
[0] == 0 ||
1794 deviceExtension
->FullIdentifyData
.FirmwareRevision
[0] == ' ') &&
1795 (deviceExtension
->FullIdentifyData
.FirmwareRevision
[1] == 0 ||
1796 deviceExtension
->FullIdentifyData
.FirmwareRevision
[1] == ' ')) {
1797 // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
1798 // are declared BOCHS looks like regular PC
1799 if (!atapiDev
&& !AtapiStringCmp ((PCCHAR
)(deviceExtension
->FullIdentifyData
.SerialNumber
), "XBDH00", 6)) {
1800 KdPrint2((PRINT_PREFIX
"IssueIdentify: BOCHS HDD\n"));
1801 g_opt_VirtualMachine
= VM_BOCHS
;
1803 if (atapiDev
&& !AtapiStringCmp ((PCCHAR
)(deviceExtension
->FullIdentifyData
.SerialNumber
), "XBDC00", 6)) {
1804 KdPrint2((PRINT_PREFIX
"IssueIdentify: BOCHS CD\n"));
1805 g_opt_VirtualMachine
= VM_BOCHS
;
1810 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1811 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1812 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1814 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1815 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1816 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1817 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1819 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1820 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1821 deviceExtension
->FullIdentifyData
.SataSupport
,
1822 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1824 LunExt
->LimitedTransferMode
=
1825 LunExt
->OrigTransferMode
=
1826 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1827 LunExt
->TransferMode
=
1828 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1830 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1831 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1832 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1833 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1835 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d\n",
1836 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1839 KdPrint2((PRINT_PREFIX
"PowerMngt %d/%d, APM %d/%d\n",
1840 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.PowerMngt
,
1841 deviceExtension
->FullIdentifyData
.FeaturesSupport
.PowerMngt
,
1842 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.APM
,
1843 deviceExtension
->FullIdentifyData
.FeaturesSupport
.APM
1846 // Check out a few capabilities / limitations of the device.
1847 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1848 // Determine if this drive supports the MSN functions.
1849 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1851 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1852 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1855 // AHCI doesn't recommend using PIO and multiblock
1856 LunExt
->MaximumBlockXfer
= 0;
1858 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1859 // Determine max. block transfer for this device.
1860 LunExt
->MaximumBlockXfer
=
1861 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1863 LunExt
->NumOfSectors
= 0;
1864 if (Command
== IDE_COMMAND_IDENTIFY
) {
1865 ULONGLONG NumOfSectors
=0;
1866 ULONGLONG NativeNumOfSectors
=0;
1867 ULONGLONG cylinders
=0;
1868 ULONGLONG tmp_cylinders
=0;
1870 KdPrint2((PRINT_PREFIX
"PhysLogSectorSize %#x, %#x, offset %#x\n",
1871 deviceExtension
->FullIdentifyData
.PhysLogSectorSize
,
1872 deviceExtension
->FullIdentifyData
.LargeSectorSize
,
1873 deviceExtension
->FullIdentifyData
.LogicalSectorOffset
1876 KdPrint2((PRINT_PREFIX
"NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1877 deviceExtension
->FullIdentifyData
.NVCache_PM_Supported
,
1878 deviceExtension
->FullIdentifyData
.NVCache_PM_Enabled
,
1879 deviceExtension
->FullIdentifyData
.NVCache_Enabled
,
1880 deviceExtension
->FullIdentifyData
.NVCache_PM_Version
,
1881 deviceExtension
->FullIdentifyData
.NVCache_Version
1884 KdPrint2((PRINT_PREFIX
"R-rate %d\n",
1885 deviceExtension
->FullIdentifyData
.NominalMediaRotationRate
1887 KdPrint2((PRINT_PREFIX
"WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
1888 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.WriteCache
,
1889 deviceExtension
->FullIdentifyData
.FeaturesSupport
.WriteCache
,
1890 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.LookAhead
,
1891 deviceExtension
->FullIdentifyData
.FeaturesSupport
.LookAhead
,
1892 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.WriteBuffer
,
1893 deviceExtension
->FullIdentifyData
.FeaturesSupport
.WriteBuffer
,
1894 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.ReadBuffer
,
1895 deviceExtension
->FullIdentifyData
.FeaturesSupport
.ReadBuffer
,
1896 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Queued
,
1897 deviceExtension
->FullIdentifyData
.FeaturesSupport
.Queued
1900 KdPrint2((PRINT_PREFIX
"Protected %d/%d status %#x, rev %#x\n",
1901 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Protected
,
1902 deviceExtension
->FullIdentifyData
.FeaturesSupport
.Protected
,
1903 deviceExtension
->FullIdentifyData
.SecurityStatus
,
1904 deviceExtension
->FullIdentifyData
.MasterPasswdRevision
1907 // Read very-old-style drive geometry
1908 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1909 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1910 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1911 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1913 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1914 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1915 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1916 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1917 // Check for HDDs > 8Gb
1918 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1919 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1920 deviceExtension
->FullIdentifyData
.NumberOfHeads
&&
1921 deviceExtension
->FullIdentifyData
.SectorsPerTrack
&&
1922 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1923 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1925 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1926 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1927 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1929 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1931 NumOfSectors
= cylinders
*
1932 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1933 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1935 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1939 // Check for LBA mode
1940 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1941 KdPrint2((PRINT_PREFIX
"SupportDMA flag %#x\n", deviceExtension
->FullIdentifyData
.SupportDma
));
1942 KdPrint2((PRINT_PREFIX
"SoftReset %#x\n", deviceExtension
->FullIdentifyData
.SoftReset
));
1943 KdPrint2((PRINT_PREFIX
"SupportIordy %#x, DisableIordy %#x\n",
1944 deviceExtension
->FullIdentifyData
.SupportIordy
,
1945 deviceExtension
->FullIdentifyData
.DisableIordy
1947 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1948 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1949 if ( deviceExtension
->FullIdentifyData
.SupportLba
1951 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1952 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1953 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1954 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1955 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1957 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1958 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1959 goto skip_lba_staff
;
1961 // Check for LBA48 support
1962 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1963 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1964 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1965 deviceExtension
->FullIdentifyData
.NumberOfHeads
&&
1966 deviceExtension
->FullIdentifyData
.SectorsPerTrack
&&
1967 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1969 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1971 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1972 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1973 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1975 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1977 NativeNumOfSectors
= cylinders
*
1978 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1979 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1981 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1983 if(NativeNumOfSectors
> NumOfSectors
) {
1984 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1985 NumOfSectors
= NativeNumOfSectors
;
1989 // Check drive capacity report for LBA48-capable drives.
1990 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1991 ULONG hNativeNumOfSectors
;
1992 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1994 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1995 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1997 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1999 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
2001 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
2002 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
2003 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
2005 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
2008 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
2009 NativeNumOfSectors
|=
2010 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
2011 hNativeNumOfSectors
=
2012 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
2013 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
2014 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
2016 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
2018 // Some drives report LBA48 capability while has capacity below 128Gb
2019 // Probably they support large block-counters.
2020 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
2021 // Here we check this
2022 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
2023 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
2025 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
2026 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
2028 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2030 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
2032 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
2033 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
2034 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
2035 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
2036 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
2037 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
2042 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
2043 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
2044 NativeNumOfSectors
= 0;
2048 if(NumOfSectors
<= ATA_MAX_LBA28
&&
2049 NativeNumOfSectors
> NumOfSectors
) {
2051 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
2052 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
2054 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
2055 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
2056 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2057 NumOfSectors
= NativeNumOfSectors
;
2063 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
2064 // check for native LBA size
2065 // some drives report ~32Gb in Identify Block
2066 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
2068 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
2069 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
2071 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2073 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
2075 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
2076 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
2077 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
2078 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
2080 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
2082 if(NativeNumOfSectors
> NumOfSectors
) {
2084 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
2085 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
2087 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
2088 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
2089 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2090 NumOfSectors
= NativeNumOfSectors
;
2096 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
2098 // fill IdentifyData with bogus geometry
2099 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
2100 if(deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
&&
2101 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
) {
2102 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
2103 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
2105 if(deviceExtension
->FullIdentifyData
.SectorsPerTrack
&&
2106 deviceExtension
->FullIdentifyData
.NumberOfHeads
) {
2107 KdPrint2((PRINT_PREFIX
"Current C/H = %#I64x/%#I64x\n",
2108 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
,
2109 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
));
2110 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.SectorsPerTrack
*
2111 deviceExtension
->FullIdentifyData
.NumberOfHeads
);
2115 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
2116 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
2117 // ok, we can keep original values
2118 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2119 LunExt
->opt_GeomType
= GEOM_ORIG
;
2122 tmp_cylinders
= NumOfSectors
/ (255*63);
2123 if(tmp_cylinders
< 0xffff) {
2124 // we can use generic values for H/S for generic geometry approach
2125 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2126 LunExt
->opt_GeomType
= GEOM_STD
;
2129 // we should use UNIATA geometry approach
2130 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2131 LunExt
->opt_GeomType
= GEOM_UNIATA
;
2136 if(!deviceExtension
->FullIdentifyData
.SectorsPerTrack
||
2137 !deviceExtension
->FullIdentifyData
.NumberOfHeads
) {
2138 KdPrint2((PRINT_PREFIX
"Zero S/H -> Force Use GEOM_STD\n"));
2141 if(LunExt
->opt_GeomType
== GEOM_STD
) {
2142 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
2143 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
2145 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
2146 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
2148 cylinders
= NumOfSectors
/ (255*63);
2149 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
2151 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
2152 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
2154 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
2155 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
2156 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
2158 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
2160 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
2161 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
2162 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
2164 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
2166 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
2167 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
2168 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
2170 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
2172 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
2173 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
2174 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
2176 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
2177 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
2178 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
2181 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
2182 cylinders
= tmp_cylinders
;
2184 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
2185 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
2189 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
2190 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
2191 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
2193 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
2194 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
2195 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
2197 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
2198 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
2199 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
2203 LunExt
->NumOfSectors
= NumOfSectors
;
2205 if(deviceExtension
->FullIdentifyData
.MajorRevision
&&
2206 deviceExtension
->FullIdentifyData
.DoubleWordIo
) {
2207 LunExt
->DeviceFlags
|= DFLAGS_DWORDIO_ENABLED
;
2208 KdPrint2((PRINT_PREFIX
"IssueIdentify: DWORDIO supported\n"));
2212 if(deviceExtension
->FullIdentifyData
.MajorRevision
&&
2213 deviceExtension
->FullIdentifyData
.DoubleWordIo
) {
2214 LunExt
->DeviceFlags
|= DFLAGS_DWORDIO_ENABLED
;
2215 KdPrint2((PRINT_PREFIX
"IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
2217 if(deviceExtension
->FullIdentifyData
.AtapiDMA
.DMADirRequired
) {
2218 KdPrint2((PRINT_PREFIX
"DMADirRequired.\n"));
2220 if(deviceExtension
->FullIdentifyData
.AtapiByteCount0
) {
2221 KdPrint2((PRINT_PREFIX
"AtapiByteCount0=%x\n", deviceExtension
->FullIdentifyData
.AtapiByteCount0
));
2225 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
2226 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
2228 InitBadBlocks(LunExt
);
2230 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
2231 (Command
!= IDE_COMMAND_IDENTIFY
)) {
2233 // This device interrupts with the assertion of DRQ after receiving
2234 // Atapi Packet Command
2235 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
2236 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2239 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2242 if(Command
!= IDE_COMMAND_IDENTIFY
) {
2244 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
2246 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
2247 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
2249 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
2250 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
2251 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
2252 // set CD default costs
2253 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
2254 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
2255 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
2256 statusByte
= WaitForDrq(chan
);
2258 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
2259 LunExt
->IdentifyData
.DeviceType
));
2261 KdPrint2((PRINT_PREFIX
"IssueIdentify: AtapiCmdSize %#x\n", deviceExtension
->FullIdentifyData
.AtapiCmdSize
));
2263 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
2266 GetBaseStatus(chan
, statusByte
);
2267 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
2270 } // end IssueIdentify()
2275 Routine Description:
2276 Set drive parameters using the IDENTIFY data.
2279 HwDeviceExtension - HBA miniport driver's adapter data storage
2280 DeviceNumber - Indicates which device.
2283 TRUE if all goes well.
2289 IN PVOID HwDeviceExtension
,
2290 IN ULONG DeviceNumber
,
2294 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2295 PIDENTIFY_DATA2 identifyData
;
2296 PHW_LU_EXTENSION LunExt
;
2301 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2302 identifyData
= &(LunExt
->IdentifyData
);
2304 if(LunExt
->DeviceFlags
&
2305 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2308 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2309 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2311 // Send SET PARAMETER command.
2312 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2313 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2314 (identifyData
->NumberOfHeads
- 1), 0,
2315 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2317 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2318 if(statusByte
& IDE_STATUS_ERROR
) {
2319 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2320 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2321 errorByte
, statusByte
));
2325 if(statusByte
== IDE_STATUS_IDLE
) {
2331 } // end SetDriveParameters()
2336 PHW_LU_EXTENSION LunExt
2339 // keep only DFLAGS_HIDDEN flag
2340 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2341 LunExt
->AtapiReadyWaitDelay
= 0;
2342 } // end UniataForgetDevice()
2347 Routine Description:
2348 Reset IDE controller and/or Atapi device.
2352 HwDeviceExtension - HBA miniport driver's adapter data storage
2361 AtapiResetController(
2362 IN PVOID HwDeviceExtension
,
2366 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2367 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2368 } // end AtapiResetController()
2372 AtapiResetController__(
2373 IN PVOID HwDeviceExtension
,
2375 IN BOOLEAN CompleteType
2378 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2379 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2380 PHW_CHANNEL chan
= NULL
;
2384 PSCSI_REQUEST_BLOCK CurSrb
;
2385 ULONG ChannelCtrlFlags
;
2386 UCHAR dma_status
= 0;
2388 ULONG slotNumber
= deviceExtension
->slotNumber
;
2389 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2390 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2392 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2394 //ULONG RevID = deviceExtension->RevID;
2395 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2399 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2400 KdPrint2((PRINT_PREFIX
"simplexOnly %d, VM %x\n", deviceExtension
->simplexOnly
, g_opt_VirtualMachine
));
2402 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2403 // we shall reset both channels on SimplexOnly devices,
2404 // It's not worth doing so on normal controllers
2406 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2409 numberChannels
= deviceExtension
->NumberChannels
;
2412 for (; j
< numberChannels
; j
++) {
2414 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset lchannel %d[%d]\n", j
, deviceExtension
->Channel
));
2415 chan
= &(deviceExtension
->chan
[j
]);
2416 MaxLuns
= chan
->NumberLuns
;
2417 // Save control flags
2418 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2419 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType
, MaxLuns
, chan
, &chan
, ChannelCtrlFlags
));
2420 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2421 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2423 while((CurSrb
= UniataGetCurRequest(chan
))) {
2425 PHW_LU_EXTENSION LunExt
;
2426 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2428 i
= GET_CDEV(CurSrb
);
2429 KdPrint2((PRINT_PREFIX
" Lun %x\n", i
));
2430 LunExt
= chan
->lun
[i
];
2432 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2433 if(CurSrb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
2434 KdPrint2((PRINT_PREFIX
" was MechStatus\n"));
2436 if(!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)) {
2437 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
2438 KdPrint2((PRINT_PREFIX
" set DFLAGS_CHANGER_INITED\n"));
2441 // Check and see if we are processing an internal srb
2442 if (AtaReq
->OriginalSrb
) {
2443 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2444 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2445 CurSrb
->SrbExtension
= NULL
;
2446 AtaReq
->OriginalSrb
= NULL
;
2447 // NOTE: internal SRB doesn't get to SRB queue !!!
2448 CurSrb
= AtaReq
->Srb
;
2451 // Remove current request from queue
2452 UniataRemoveRequest(chan
, CurSrb
);
2454 // Check if request is in progress.
2455 ASSERT(AtaReq
->Srb
== CurSrb
);
2457 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2458 UCHAR CurPathId
= CurSrb
->PathId
;
2459 UCHAR TargetId
= CurSrb
->TargetId
;
2460 UCHAR Lun
= CurSrb
->Lun
;
2462 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2463 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2465 if (CurSrb
->SenseInfoBuffer
) {
2467 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2468 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer
, chan
, AtaReq
->Flags
));
2470 senseBuffer
->ErrorCode
= 0x70;
2471 senseBuffer
->Valid
= 1;
2472 senseBuffer
->AdditionalSenseLength
= 0xb;
2473 if(CompleteType
== RESET_COMPLETE_ALL
) {
2474 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2475 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2476 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2477 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2479 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2480 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2481 senseBuffer
->AdditionalSenseCode
= 0;
2482 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2486 if(!ATAPI_DEVICE(chan
, i
) && AtaReq
->bcount
&& AtaReq
->retry
< MAX_RETRIES
) {
2487 KdPrint2((PRINT_PREFIX
"Save IDE retry status %d\n", AtaReq
->retry
));
2488 LunExt
->errLastLba
= AtaReq
->lba
;
2489 LunExt
->errBCount
= AtaReq
->bcount
;
2490 LunExt
->errRetry
= AtaReq
->retry
+1;
2491 //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ));
2492 //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION));
2493 //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS));
2494 if(((AtaReq
->Flags
& REQ_FLAG_RW_MASK
) == REQ_FLAG_READ
) &&
2495 (ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) &&
2496 (g_opt_VirtualMachine
== VM_BOCHS
)) {
2497 KdPrint2((PRINT_PREFIX
"set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
2498 g_opt_BochsDmaReadWorkaround
= TRUE
;
2499 g_opt_AtapiNoDma
= TRUE
;
2501 KdPrint2((PRINT_PREFIX
"do nothing\n"));
2504 if(ATAPI_DEVICE(chan
, i
) && AtaReq
->bcount
&& !AtaReq
->retry
) {
2505 KdPrint2((PRINT_PREFIX
"Save ATAPI retry status %d\n", AtaReq
->retry
));
2506 LunExt
->errLastLba
= AtaReq
->lba
;
2507 LunExt
->errBCount
= AtaReq
->bcount
;
2508 LunExt
->errRetry
= AtaReq
->retry
+1;
2509 if(((AtaReq
->Flags
& REQ_FLAG_RW_MASK
) == REQ_FLAG_READ
) &&
2510 (ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) &&
2511 (g_opt_VirtualMachine
== VM_BOCHS
)) {
2512 KdPrint2((PRINT_PREFIX
"set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
2513 //g_opt_BochsDmaReadWorkaround = TRUE;
2514 g_opt_AtapiNoDma
= TRUE
;
2516 KdPrint2((PRINT_PREFIX
"do nothing\n"));
2519 LunExt
->errRetry
= 0;
2522 // Clear request tracking fields.
2523 AtaReq
->WordsLeft
= 0;
2524 AtaReq
->DataBuffer
= NULL
;
2525 AtaReq
->TransferLength
= 0;
2526 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2528 ScsiPortNotification(RequestComplete
,
2532 // Indicate ready for next request.
2533 ScsiPortNotification(NextLuRequest
,
2539 if(CompleteType
!= RESET_COMPLETE_ALL
)
2542 #endif //UNIATA_CORE
2543 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2545 // Clear expecting interrupt flag.
2546 UniataExpectChannelInterrupt(chan
, FALSE
);
2548 chan
->ChannelCtrlFlags
= ChannelCtrlFlags
& CTRFLAGS_PERMANENT
;
2549 InterlockedExchange(&(chan
->CheckIntr
),
2552 for (i
= 0; i
< MaxLuns
; i
++) {
2553 chan
->lun
[i
]->PowerState
= 0;
2556 if(ChipFlags
& UNIATA_AHCI
) {
2557 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2558 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2560 UniataDumpAhciPortRegs(chan
);
2562 AtapiDisableInterrupts(deviceExtension
, j
);
2563 UniataAhciReset(HwDeviceExtension
, j
);
2565 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2569 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2570 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2571 AtapiDisableInterrupts(deviceExtension
, j
);
2572 KdPrint2((PRINT_PREFIX
" done\n"));
2574 case ATA_INTEL_ID
: {
2578 if(!(ChipFlags
& UNIATA_SATA
)) {
2581 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2586 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2587 if(ChipFlags
& UNIATA_AHCI
) {
2590 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2591 GetPciConfig1(0x90, tmp8
);
2599 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2601 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2604 ChangePciConfig2(0x92, a
& ~mask
);
2605 AtapiStallExecution(10);
2606 ChangePciConfig2(0x92, a
| mask
);
2609 /* Wait up to 1 sec for "connect well". */
2610 if (ChipFlags
& (I6CH
| I6CH2
)) {
2616 GetPciConfig2(0x92, tmp16
);
2617 if (((tmp16
>> pshift
) & mask
) == mask
) {
2618 GetBaseStatus(chan
, statusByte
);
2619 if(statusByte
!= IDE_STATUS_WRONG
) {
2623 AtapiStallExecution(10000);
2627 KdPrint2((PRINT_PREFIX
" SIS\n"));
2628 if(!(ChipFlags
& UNIATA_SATA
))
2632 case ATA_NVIDIA_ID
: {
2633 KdPrint2((PRINT_PREFIX
" nVidia\n"));
2634 if(!(ChipFlags
& UNIATA_SATA
))
2638 case ATA_NVIDIA_ID
: {
2640 ULONG Channel
= deviceExtension
->Channel
+ j
;
2641 KdPrint2((PRINT_PREFIX
" nVidia\n"));
2642 if(!(ChipFlags
& UNIATA_SATA
)) {
2645 offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
2647 KdPrint2((PRINT_PREFIX
" disable Phy intr, offs %#x, c %u\n", offs
, Channel
));
2648 /* disable device and PHY state change interrupts */
2649 if(ChipFlags
& NVQ
) {
2650 KdPrint2((PRINT_PREFIX
" NVQ, 32bits reg\n"));
2651 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2652 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) & ((~(ULONG
)0x0000000d) << (!Channel
*16)) );
2654 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2655 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) & ((~(UCHAR
)0x0d) << (!Channel
*4)) );
2657 tmp16
= UniataSataPhyEnable(HwDeviceExtension
, j
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
);
2659 KdPrint2((PRINT_PREFIX
" enable Phy intr, offs %#x\n", offs
));
2660 /* enable device and PHY state change interrupts */
2661 if(ChipFlags
& NVQ
) {
2662 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2663 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) | (((ULONG
)0x0000000d) << (!Channel
*16)) );
2665 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2666 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) | (((UCHAR
)0x0d) << (!Channel
*4)) );
2669 KdPrint2((PRINT_PREFIX
" dev status %#x\n", tmp16
));
2670 if(tmp16
!= IDE_STATUS_WRONG
) {
2675 case ATA_SILICON_IMAGE_ID
: {
2677 ULONG Channel
= deviceExtension
->Channel
+ j
;
2678 if(!(ChipFlags
& UNIATA_SATA
))
2680 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2681 /* disable PHY state change interrupt */
2682 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2684 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2686 /* reset controller part for this channel */
2687 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2688 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2689 AtapiStallExecution(1000);
2690 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2691 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2695 case ATA_PROMISE_ID
: {
2698 if(ChipFlags
& UNIATA_SATA
) {
2699 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2700 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2704 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2705 IDE_DC_RESET_CONTROLLER );
2706 chan->last_devsel = -1;
2707 KdPrint2((PRINT_PREFIX " wait a little\n"));
2708 AtapiStallExecution(10000);
2709 // Disable interrupts
2710 KdPrint2((PRINT_PREFIX " disable intr\n"));
2711 AtapiDisableInterrupts(deviceExtension, j);
2712 AtapiStallExecution(100);
2713 KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2714 AtapiEnableInterrupts(deviceExtension, j);
2715 KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
2716 AtapiStallExecution(100000);
2718 AtapiHardReset(chan
, TRUE
, 100000);
2719 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2720 AtapiDisableInterrupts(deviceExtension
, j
);
2721 AtapiStallExecution(100);
2722 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2723 AtapiEnableInterrupts(deviceExtension
, j
);
2724 KdPrint2((PRINT_PREFIX
" done\n"));
2729 //if(!(ChipFlags & UNIATA_SATA)) {}
2730 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2731 // Reset DMA engine if active
2732 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2733 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2734 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2735 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2736 (dma_status
& BM_STATUS_INTR
)) {
2737 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2742 // all these shall be performed inside AtapiHwInitialize__() ?
2744 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2745 // Do special processing for ATAPI and IDE disk devices.
2746 for (i
= 0; i
< MaxLuns
; i
++) {
2748 // Check if device present.
2749 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2750 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2751 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2752 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2753 if(ChipFlags
& UNIATA_AHCI
) {
2754 // everything is done in UniataAhciReset()
2755 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2761 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2762 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2765 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2769 if(ChipFlags
& UNIATA_AHCI
) {
2770 // everything is done in UniataAhciReset()
2771 KdPrint2((PRINT_PREFIX
" found some device\n"));
2773 if(!IssueIdentify(HwDeviceExtension
,
2775 ATAPI_DEVICE(chan
, i
) ?
2776 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2778 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2779 UniataForgetDevice(chan
->lun
[i
]);
2783 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2784 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2785 UniataForgetDevice(chan
->lun
[i
]);
2790 SelectDrive(chan
, i
);
2791 AtapiStallExecution(10);
2792 statusByte
= WaitOnBusyLong(chan
);
2793 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2794 if(statusByte
== IDE_STATUS_WRONG
) {
2795 KdPrint2((PRINT_PREFIX
2796 "no drive, status %#x\n",
2798 UniataForgetDevice(chan
->lun
[i
]);
2800 // Check for ATAPI disk.
2801 if (ATAPI_DEVICE(chan
, i
)) {
2802 // Issue soft reset and issue identify.
2803 GetStatus(chan
, statusByte
);
2804 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2807 AtapiDisableInterrupts(deviceExtension
, j
);
2808 AtapiSoftReset(chan
, i
);
2809 AtapiEnableInterrupts(deviceExtension
, j
);
2811 GetStatus(chan
, statusByte
);
2813 if(statusByte
!= IDE_STATUS_SUCCESS
) {
2815 k
= UniataAnybodyHome(deviceExtension
, j
, i
);
2816 if(k
== ATA_AT_HOME_HDD
) {
2817 // device reset in progress, perform additional wait
2818 KdPrint2((PRINT_PREFIX
" long reset, wait up to 4.5 s\n"));
2820 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
2823 AtapiStallExecution(150);
2825 KdPrint2((PRINT_PREFIX
" exit after %u loops\n", k
));
2826 GetStatus(chan
, statusByte
);
2829 if(statusByte
== IDE_STATUS_SUCCESS
) {
2831 IssueIdentify(HwDeviceExtension
,
2833 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2836 KdPrint2((PRINT_PREFIX
2837 "AtapiResetController: Status after soft reset %#x\n",
2840 GetBaseStatus(chan
, statusByte
);
2843 // Issue identify and reinit after channel reset.
2845 if (statusByte
!= IDE_STATUS_IDLE
&&
2846 statusByte
!= IDE_STATUS_SUCCESS
&&
2847 statusByte
!= IDE_STATUS_DRDY
) {
2849 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2851 if(!IssueIdentify(HwDeviceExtension
,
2853 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2855 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2857 // Set disk geometry parameters.
2858 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2859 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2861 GetBaseStatus(chan
, statusByte
);
2863 // force DMA mode reinit
2864 KdPrint2((PRINT_PREFIX
" set DFLAGS_REINIT_DMA\n"));
2865 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2869 // Enable interrupts, note, we can have here recursive disable
2870 AtapiStallExecution(10);
2871 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2873 chan
->DisableIntr
));
2874 AtapiEnableInterrupts(deviceExtension
, j
);
2876 // Call the HwInitialize routine to setup multi-block.
2877 AtapiHwInitialize__(deviceExtension
, j
);
2879 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2883 } // end AtapiResetController__()
2888 Routine Description:
2889 This routine maps ATAPI and IDE errors to specific SRB statuses.
2892 HwDeviceExtension - HBA miniport driver's adapter data storage
2893 Srb - IO request packet
2902 IN PVOID HwDeviceExtension
,
2903 IN PSCSI_REQUEST_BLOCK Srb
2906 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2907 ULONG lChannel
= GET_CHANNEL(Srb
);
2908 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2910 UCHAR errorByte
= 0;
2911 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2913 ULONG DeviceNumber
= GET_CDEV(Srb
);
2914 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2916 // Read the error register.
2918 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2919 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2921 errorByte
= AtaReq
->ahci
.in_error
;
2925 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2927 KdPrint2((PRINT_PREFIX
2928 "MapError: Error register is %#x\n",
2931 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2933 switch (errorByte
>> 4) {
2934 case SCSI_SENSE_NO_SENSE
:
2936 KdPrint2((PRINT_PREFIX
2937 "ATAPI: No sense information\n"));
2938 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2939 srbStatus
= SRB_STATUS_ERROR
;
2942 case SCSI_SENSE_RECOVERED_ERROR
:
2944 KdPrint2((PRINT_PREFIX
2945 "ATAPI: Recovered error\n"));
2947 srbStatus
= SRB_STATUS_SUCCESS
;
2950 case SCSI_SENSE_NOT_READY
:
2952 KdPrint2((PRINT_PREFIX
2953 "ATAPI: Device not ready\n"));
2954 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2955 srbStatus
= SRB_STATUS_ERROR
;
2958 case SCSI_SENSE_MEDIUM_ERROR
:
2960 KdPrint2((PRINT_PREFIX
2961 "ATAPI: Media error\n"));
2962 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2963 srbStatus
= SRB_STATUS_ERROR
;
2966 case SCSI_SENSE_HARDWARE_ERROR
:
2968 KdPrint2((PRINT_PREFIX
2969 "ATAPI: Hardware error\n"));
2970 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2971 srbStatus
= SRB_STATUS_ERROR
;
2974 case SCSI_SENSE_ILLEGAL_REQUEST
:
2976 KdPrint2((PRINT_PREFIX
2977 "ATAPI: Illegal request\n"));
2978 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2979 srbStatus
= SRB_STATUS_ERROR
;
2982 case SCSI_SENSE_UNIT_ATTENTION
:
2984 KdPrint2((PRINT_PREFIX
2985 "ATAPI: Unit attention\n"));
2986 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2987 srbStatus
= SRB_STATUS_ERROR
;
2990 case SCSI_SENSE_DATA_PROTECT
:
2992 KdPrint2((PRINT_PREFIX
2993 "ATAPI: Data protect\n"));
2994 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2995 srbStatus
= SRB_STATUS_ERROR
;
2998 case SCSI_SENSE_BLANK_CHECK
:
3000 KdPrint2((PRINT_PREFIX
3001 "ATAPI: Blank check\n"));
3002 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3003 srbStatus
= SRB_STATUS_ERROR
;
3006 case SCSI_SENSE_ABORTED_COMMAND
:
3007 KdPrint2((PRINT_PREFIX
3008 "Atapi: Command Aborted\n"));
3009 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3010 srbStatus
= SRB_STATUS_ERROR
;
3015 KdPrint2((PRINT_PREFIX
3016 "ATAPI: Invalid sense information\n"));
3018 srbStatus
= SRB_STATUS_ERROR
;
3026 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
3027 chan
->ReturningMediaStatus
= errorByte
;
3029 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
3030 KdPrint2((PRINT_PREFIX
3031 "IDE: Media change\n"));
3032 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3033 srbStatus
= SRB_STATUS_ERROR
;
3035 if (Srb
->SenseInfoBuffer
) {
3037 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3039 senseBuffer
->ErrorCode
= 0x70;
3040 senseBuffer
->Valid
= 1;
3041 senseBuffer
->AdditionalSenseLength
= 0xb;
3042 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
3043 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
3044 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3046 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3049 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
3050 KdPrint2((PRINT_PREFIX
3051 "IDE: Command abort\n"));
3052 srbStatus
= SRB_STATUS_ABORTED
;
3053 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3055 if (Srb
->SenseInfoBuffer
) {
3057 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3059 senseBuffer
->ErrorCode
= 0x70;
3060 senseBuffer
->Valid
= 1;
3061 senseBuffer
->AdditionalSenseLength
= 0xb;
3062 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
3063 senseBuffer
->AdditionalSenseCode
= 0;
3064 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3066 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3069 LunExt
->ErrorCount
++;
3071 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
3073 KdPrint2((PRINT_PREFIX
3074 "IDE: End of media\n"));
3075 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3076 srbStatus
= SRB_STATUS_ERROR
;
3078 if (Srb
->SenseInfoBuffer
) {
3080 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3082 senseBuffer
->ErrorCode
= 0x70;
3083 senseBuffer
->Valid
= 1;
3084 senseBuffer
->AdditionalSenseLength
= 0xb;
3085 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
3086 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
3087 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
3088 senseBuffer
->EndOfMedia
= 1;
3090 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3093 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
3094 LunExt
->ErrorCount
++;
3097 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
3099 KdPrint2((PRINT_PREFIX
3100 "IDE: Illegal length\n"));
3101 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
3103 if (Srb
->SenseInfoBuffer
) {
3105 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3107 senseBuffer
->ErrorCode
= 0x70;
3108 senseBuffer
->Valid
= 1;
3109 senseBuffer
->AdditionalSenseLength
= 0xb;
3110 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
3111 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
3112 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
3113 senseBuffer
->IncorrectLength
= 1;
3115 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3118 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
3120 KdPrint2((PRINT_PREFIX
3121 "IDE: Bad block\n"));
3122 srbStatus
= SRB_STATUS_ERROR
;
3123 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3124 if (Srb
->SenseInfoBuffer
) {
3126 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3128 senseBuffer
->ErrorCode
= 0x70;
3129 senseBuffer
->Valid
= 1;
3130 senseBuffer
->AdditionalSenseLength
= 0xb;
3131 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3132 senseBuffer
->AdditionalSenseCode
= 0;
3133 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3135 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3138 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
3140 KdPrint2((PRINT_PREFIX
3141 "IDE: Id not found\n"));
3142 srbStatus
= SRB_STATUS_ERROR
;
3143 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3145 if (Srb
->SenseInfoBuffer
) {
3147 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3149 senseBuffer
->ErrorCode
= 0x70;
3150 senseBuffer
->Valid
= 1;
3151 senseBuffer
->AdditionalSenseLength
= 0xb;
3152 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3153 senseBuffer
->AdditionalSenseCode
= 0;
3154 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3156 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3159 LunExt
->ErrorCount
++;
3161 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
3163 KdPrint2((PRINT_PREFIX
3164 "IDE: Media change\n"));
3165 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3166 srbStatus
= SRB_STATUS_ERROR
;
3168 if (Srb
->SenseInfoBuffer
) {
3170 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3172 senseBuffer
->ErrorCode
= 0x70;
3173 senseBuffer
->Valid
= 1;
3174 senseBuffer
->AdditionalSenseLength
= 0xb;
3175 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
3176 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
3177 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3179 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3182 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
3184 KdPrint2((PRINT_PREFIX
3185 "IDE: Data error\n"));
3186 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3187 srbStatus
= SRB_STATUS_ERROR
;
3189 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
3190 LunExt
->ErrorCount
++;
3193 // Build sense buffer
3194 if (Srb
->SenseInfoBuffer
) {
3196 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3198 senseBuffer
->ErrorCode
= 0x70;
3199 senseBuffer
->Valid
= 1;
3200 senseBuffer
->AdditionalSenseLength
= 0xb;
3201 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3202 senseBuffer
->AdditionalSenseCode
= 0;
3203 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3205 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3209 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
3210 // deviceExtension->DWordIO = FALSE;
3212 KdPrint2((PRINT_PREFIX
3213 "MapError: ErrorCount >= MAX_ERRORS\n"));
3215 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
3216 LunExt
->MaximumBlockXfer
= 0;
3219 KdPrint2((PRINT_PREFIX
3220 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
3223 KdPrint2((PRINT_PREFIX
3224 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
3233 ScsiPortLogError( HwDeviceExtension
,
3241 // Reprogram to not use Multi-sector.
3244 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
3245 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3247 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
3249 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3250 // command was aborted.
3251 if (statusByte
& IDE_STATUS_ERROR
) {
3253 // Read the error register.
3254 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3256 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3260 // Adjust the devExt. value, if necessary.
3261 LunExt
->MaximumBlockXfer
= 0;
3269 // Set SCSI status to indicate a check condition.
3270 Srb
->ScsiStatus
= scsiStatus
;
3279 Routine Description:
3282 HwDeviceExtension - HBA miniport driver's adapter data storage
3286 TRUE - if initialization successful.
3287 FALSE - if initialization unsuccessful.
3293 IN PVOID HwDeviceExtension
3296 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3297 ULONG numberChannels
= deviceExtension
->NumberChannels
;
3300 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
3302 if(WinVer_WDM_Model
) {
3303 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
3305 if(deviceExtension
->MasterDev
) {
3306 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
3307 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
3308 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
3311 /* do extra chipset specific setups */
3312 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
3314 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3315 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3316 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3319 for (c
= 0; c
< numberChannels
; c
++) {
3320 AtapiHwInitialize__(deviceExtension
, c
);
3322 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
3324 } // end AtapiHwInitialize()
3328 AtapiHwInitialize__(
3329 IN PHW_DEVICE_EXTENSION deviceExtension
,
3334 UCHAR statusByte
, errorByte
;
3335 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3336 PHW_LU_EXTENSION LunExt
;
3338 ULONG PreferedMode
= 0xffffffff;
3340 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3341 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
3345 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
3346 FindDevices(deviceExtension
, 0, lChannel
);
3348 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
3350 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
3352 LunExt
= chan
->lun
[i
];
3354 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
3358 AtapiDisableInterrupts(deviceExtension
, lChannel
);
3359 AtapiStallExecution(1);
3361 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3363 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
3364 // Enable media status notification
3365 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
3367 // If supported, setup Multi-block transfers.
3368 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3369 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3370 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
3372 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3373 // command was aborted.
3374 if (statusByte
& IDE_STATUS_ERROR
) {
3376 // Read the error register.
3377 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3379 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3383 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3384 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3385 0, 0, ATA_WAIT_BASE_READY
);
3387 if (statusByte
& IDE_STATUS_ERROR
) {
3388 // Read the error register.
3389 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3391 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3395 // Adjust the devExt. value, if necessary.
3396 LunExt
->MaximumBlockXfer
= 0;
3399 KdPrint2((PRINT_PREFIX
3400 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3402 LunExt
->MaximumBlockXfer
));
3405 if(LunExt
->IdentifyData
.MajorRevision
) {
3407 if(LunExt
->opt_ReadCacheEnable
) {
3408 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3409 // If supported, setup read/write cacheing
3410 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3411 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3412 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3414 // Check for errors.
3415 if (statusByte
& IDE_STATUS_ERROR
) {
3416 KdPrint2((PRINT_PREFIX
3417 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3419 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3421 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3424 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3425 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3426 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3427 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3428 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3430 if(LunExt
->IdentifyData
.FeaturesSupport
.WriteCache
) {
3431 if(LunExt
->opt_WriteCacheEnable
) {
3432 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3433 // If supported & allowed, setup write cacheing
3434 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3435 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3436 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3437 // Check for errors.
3438 if (statusByte
& IDE_STATUS_ERROR
) {
3439 KdPrint2((PRINT_PREFIX
3440 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3442 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3444 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3447 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3448 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3449 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3450 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3451 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3455 if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/
3456 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3458 if(LunExt
->opt_AdvPowerMode
) {
3459 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3461 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3462 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3463 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3464 // Check for errors.
3465 if (statusByte
& IDE_STATUS_ERROR
) {
3466 KdPrint2((PRINT_PREFIX
3467 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3471 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3472 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3473 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3474 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3477 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3478 if(LunExt
->opt_AcousticMode
) {
3479 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3480 // setup acoustic mgmt
3481 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3482 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3483 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3484 // Check for errors.
3485 if (statusByte
& IDE_STATUS_ERROR
) {
3486 KdPrint2((PRINT_PREFIX
3487 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3491 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3492 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3493 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3494 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3497 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3498 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3499 // setup standby timer
3500 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3501 IDE_COMMAND_IDLE
, 0, 0, 0,
3502 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3503 // Check for errors.
3504 if (statusByte
& IDE_STATUS_ERROR
) {
3505 KdPrint2((PRINT_PREFIX
3506 "AtapiHwInitialize: standby timer on Device %d failed\n",
3512 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3515 //BOOLEAN isSanyo = FALSE;
3518 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3520 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3521 for (j
= 0; j
< 26; j
+= 2) {
3523 // Build a buffer based on the identify data.
3524 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3527 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3529 // Inquiry string for older model had a '-', newer is '_'
3530 if (vendorId
[12] == 'C') {
3532 // Torisan changer. Set the bit. This will be used in several places
3533 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3534 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3535 LunExt
->DiscsPresent
= 3;
3541 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3542 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3543 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3544 PreferedMode
= chan
->MaxTransferMode
;
3547 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3548 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3549 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3552 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3553 LunExt
->LimitedTransferMode
=
3554 LunExt
->TransferMode
=
3557 AtapiDmaInit__(deviceExtension
, LunExt
);
3559 LunExt
->LimitedTransferMode
=
3560 LunExt
->TransferMode
;
3561 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3563 // We need to get our device ready for action before
3564 // returning from this function
3566 // According to the atapi spec 2.5 or 2.6, an atapi device
3567 // clears its status BSY bit when it is ready for atapi commands.
3568 // However, some devices (Panasonic SQ-TC500N) are still
3569 // not ready even when the status BSY is clear. They don't react
3570 // to atapi commands.
3572 // Since there is really no other indication that tells us
3573 // the drive is really ready for action. We are going to check BSY
3574 // is clear and then just wait for an arbitrary amount of time!
3576 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3579 // have to get out of the loop sometime!
3580 // 10000 * 100us = 1000,000us = 1000ms = 1s
3582 GetStatus(chan
, statusByte
);
3583 if(statusByte
== IDE_STATUS_WRONG
) {
3586 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3588 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3589 // Wait for Busy to drop.
3590 AtapiStallExecution(100);
3591 GetStatus(chan
, statusByte
);
3595 // 5000 * 100us = 500,000us = 500ms = 0.5s
3596 if(statusByte
!= IDE_STATUS_WRONG
) {
3599 AtapiStallExecution(100);
3600 } while (waitCount
--);
3603 GetBaseStatus(chan
, statusByte
);
3604 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3605 AtapiStallExecution(10);
3610 } // end AtapiHwInitialize__()
3617 AtapiHwInitializeChanger(
3618 IN PVOID HwDeviceExtension
,
3619 IN PSCSI_REQUEST_BLOCK Srb
,
3620 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3622 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3623 ULONG lChannel
= GET_CHANNEL(Srb
);
3624 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3625 ULONG DeviceNumber
= GET_CDEV(Srb
);
3626 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3628 if (MechanismStatus
) {
3629 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3630 if (LunExt
->DiscsPresent
> 1) {
3631 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3635 } // end AtapiHwInitializeChanger()
3640 Routine Description:
3641 This routine will parse the string for a match on the keyword, then
3642 calculate the value for the keyword and return it to the caller.
3645 String - The ASCII string to parse.
3646 KeyWord - The keyword for the value desired.
3649 Zero if value not found
3650 Value converted from ASCII to binary.
3655 AtapiParseArgumentString(
3663 ULONG stringLength
= 0;
3664 ULONG keyWordLength
= 0;
3674 // Calculate the string length and lower case all characters.
3680 // Calculate the keyword length.
3686 if (keyWordLength
> stringLength
) {
3688 // Can't possibly have a match.
3692 // Now setup and start the compare.
3697 // The input string may start with white space. Skip it.
3698 while (*cptr
== ' ' || *cptr
== '\t') {
3702 if (*cptr
== '\0') {
3708 while ((*cptr
== *kptr
) ||
3709 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3710 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3714 if (*cptr
== '\0') {
3720 if (*kptr
== '\0') {
3722 // May have a match backup and check for blank or equals.
3723 while (*cptr
== ' ' || *cptr
== '\t') {
3727 // Found a match. Make sure there is an equals.
3730 // Not a match so move to the next semicolon.
3732 if (*cptr
++ == ';') {
3733 goto ContinueSearch
;
3738 // Skip the equals sign.
3741 // Skip white space.
3742 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3746 if (*cptr
== '\0') {
3747 // Early end of string, return not found
3752 // This isn't it either.
3754 goto ContinueSearch
;
3758 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3759 // Value is in Hex. Skip the "0x"
3761 for (index
= 0; *(cptr
+ index
); index
++) {
3763 if (*(cptr
+ index
) == ' ' ||
3764 *(cptr
+ index
) == '\t' ||
3765 *(cptr
+ index
) == ';') {
3769 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3770 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3772 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3773 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3774 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3775 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3777 // Syntax error, return not found.
3784 // Value is in Decimal.
3785 for (index
= 0; *(cptr
+ index
); index
++) {
3787 if (*(cptr
+ index
) == ' ' ||
3788 *(cptr
+ index
) == '\t' ||
3789 *(cptr
+ index
) == ';') {
3793 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3794 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3797 // Syntax error return not found.
3806 // Not a match check for ';' to continue search.
3808 if (*cptr
++ == ';') {
3809 goto ContinueSearch
;
3815 } // end AtapiParseArgumentString()_
3823 IN PVOID HwDeviceExtension
,
3828 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3829 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3832 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3835 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3836 // If the last command was DSC restrictive, see if it's set. If so, the device is
3837 // ready for a new request. Otherwise, reset the timer and come back to here later.
3839 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3840 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3841 // we shall have no problem with interrupt handler.
3842 if (!srb
|| chan
->ExpectingInterrupt
) {
3843 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3844 chan
->DpcState
= DPC_STATE_TIMER
;
3845 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3846 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3847 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3849 goto ReturnCallback
;
3853 if (!IS_RDP((srb
->Cdb
[0]))) {
3854 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3858 goto ReturnEnableIntr
;
3860 GetStatus(chan
, statusByte
);
3861 if (statusByte
& IDE_STATUS_DSC
) {
3863 UCHAR PathId
= srb
->PathId
;
3864 UCHAR TargetId
= srb
->TargetId
;
3865 UCHAR Lun
= srb
->Lun
;
3867 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3868 AtapiDmaDBSync(chan
, srb
);
3869 UniataRemoveRequest(chan
, srb
);
3870 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3871 // Clear current SRB.
3872 if(!deviceExtension
->simplexOnly
) {
3873 srb
= UniataGetCurRequest(chan
);
3879 // Ask for next request.
3880 ScsiPortNotification(NextLuRequest
,
3885 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3888 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3892 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3895 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3899 goto ReturnCallback
;
3904 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3905 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3906 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3907 #ifdef UNIATA_USE_XXableInterrupts
3908 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3909 // must be called on DISPATCH_LEVEL
3910 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3911 AtapiEnableInterrupts__
);
3913 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3914 InterlockedExchange(&(chan
->CheckIntr
),
3916 // Will raise IRQL to DIRQL
3917 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3918 AtapiEnableInterrupts__
,
3920 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3921 #endif // UNIATA_USE_XXableInterrupts
3923 //ASSERT(!deviceExtension->simplexOnly);
3928 // Check other channel
3929 // In simplex mode no interrupts must appear on other channels
3930 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3931 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3937 chan
= &(deviceExtension
->chan
[c
]);
3939 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3940 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3941 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3943 //ASSERT(!deviceExtension->simplexOnly);
3944 chan
->DpcState
= DPC_STATE_ISR
;
3945 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3946 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3950 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3953 } // end AtapiCallBack__()
3958 IN PVOID HwDeviceExtension
3961 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3962 } // end AtapiCallBack_X()
3964 #endif //UNIATA_CORE
3968 Routine Description:
3970 This is the interrupt service routine for ATAPI IDE miniport driver.
3974 HwDeviceExtension - HBA miniport driver's adapter data storage
3978 TRUE if expecting an interrupt.
3984 IN PVOID HwDeviceExtension
3987 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3989 BOOLEAN status
= FALSE
;
3993 //BOOLEAN checked[AHCI_MAX_PORT];
3997 KdPrint2((PRINT_PREFIX
"Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
3998 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
4000 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4001 // AHCI may generate state change notification, never skip this check
4002 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
4003 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
4007 // assume all non-interrupted ports to be already checked
4009 // assume all not implemented ports to be already checked
4010 checked
|= ~deviceExtension
->AHCI_PI
;
4012 checked
= 0; // assume all ports are not checked
4015 if(!deviceExtension
->ExpectingInterrupt
) {
4016 // if we do not expect interrupt, exit now,
4017 // but keep in mind that it can be unexpected one
4018 // Note: this is just a hint, not exact counter
4019 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
4020 //deviceExtension->ExpectingInterrupt++;
4023 // clear this flag now, it can be set again in sub-calls
4024 deviceExtension
->ExpectingInterrupt
=0;
4027 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4028 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
4032 for(pass
=0; pass
<2; pass
++) {
4033 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
4034 if(status
&& pass
) {
4035 // we catched some expected interrupts now.
4036 // do not touch unexpected until next ISR call
4039 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
4041 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
4043 if((checked
>>c
) & 0x01)
4046 // check non-empty and expecting interrupt channels first
4047 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
4050 checked
|= (ULONG
)1 << c
;
4052 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
4054 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
4055 // we get here on idle channels or when ISR is posted to DPC
4056 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
4059 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
4061 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
4062 // c_state = deviceExtension->chan[c].CheckIntr;
4063 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
4064 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
4067 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4068 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4069 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
4070 if(c_state
== CHECK_INTR_IDLE
) {
4071 // c_state = deviceExtension->chan[c].CheckIntr;
4072 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
4073 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
4076 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4077 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4078 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
4080 } while(c_state
== CHECK_INTR_CHECK
);
4081 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
4082 // check if already serviced
4083 if(c_state
== CHECK_INTR_ACTIVE
) {
4084 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
4088 if((c_state
== CHECK_INTR_DETECTED
) ||
4089 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
4091 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
4092 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
4093 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4098 // disable interrupts on other channel of legacy mode
4099 // ISA-bridged onboard controller
4100 if(deviceExtension
->simplexOnly
/*||
4101 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4102 AtapiDisableInterrupts(deviceExtension
, !c
);
4105 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
4106 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4107 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
4108 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
4111 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
4112 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4115 // re-enable interrupts on other channel
4116 if(deviceExtension
->simplexOnly
/*||
4117 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4118 AtapiEnableInterrupts(deviceExtension
, !c
);
4122 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
4123 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4128 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
4130 deviceExtension
->FirstChannelToCheck
++;
4131 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
4132 deviceExtension
->FirstChannelToCheck
= 0;
4135 } // end AtapiInterrupt()
4143 IN PKINTERRUPT Interrupt
,
4144 IN PVOID Isr2HwDeviceExtension
4147 // This ISR is intended to catch interrupts when we are already in other ISR instance
4148 // for the same device. This may happen when we have multiple channels,
4149 // especially on SMP machines
4151 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
4152 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
4154 BOOLEAN status
= FALSE
;
4160 // we should never get here for ISA/MCA
4161 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
4162 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
4166 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4167 // AHCI may generate state change notification, never skip this check
4168 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
4169 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
4173 // assume all non-interrupted ports to be already checked
4175 // assume all not implemented ports to be already checked
4176 checked
|= ~deviceExtension
->AHCI_PI
;
4179 checked
= 0; // assume all ports are not checked
4181 if(!deviceExtension
->ExpectingInterrupt
) {
4182 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
4183 deviceExtension
->ExpectingInterrupt
++;
4186 //deviceExtension->ExpectingInterrupt = 0;
4188 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4189 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
4191 if((checked
>>c
) & 0x01)
4194 checked
|= (ULONG
)1 << c
;
4196 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
4197 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
4201 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4202 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
4203 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
4205 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
4206 // hunt on unexpected intr (Some devices generate double interrupts,
4207 // some controllers (at least CMD649) interrupt twice with small delay.
4208 // If interrupts are disabled, they queue interrupt and re-issue it later,
4209 // when we do not expect it.
4214 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
4216 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
4217 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
4218 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
4219 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4224 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
4226 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4229 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
4230 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
4231 // there is an active ISR/DPC for one channel, but
4232 // we have an interrupt from another one
4233 // Lets inform current ISR/DPC about new interrupt
4234 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
4238 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
4241 } // end AtapiInterrupt2()
4243 RETTYPE_XXableInterrupts
4246 IN PVOID HwDeviceExtension
4249 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4252 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4253 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
4255 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
4257 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4258 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4259 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
4265 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
4268 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4269 AtapiDisableInterrupts(deviceExtension, lChannel);
4272 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
4273 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4274 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4277 return RETVAL_XXableInterrupts
;
4278 } // end AtapiInterruptDpc()
4281 RETTYPE_XXableInterrupts
4283 AtapiEnableInterrupts__(
4284 IN PVOID HwDeviceExtension
4287 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4288 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
4290 PHW_CHANNEL chan
= NULL
;
4292 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4293 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
4294 chan
= &(deviceExtension
->chan
[c
]);
4296 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
4297 // enable intrs on requested channel
4298 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
4299 AtapiEnableInterrupts(HwDeviceExtension
, c
);
4300 InterlockedExchange(&(chan
->CheckIntr
),
4303 // check if current or other channel(s) interrupted
4304 //AtapiInterrupt(HwDeviceExtension);
4306 if(deviceExtension
->simplexOnly
) {
4310 // check if other channel(s) interrupted
4311 // must do nothing in simplex mode
4312 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
4313 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4314 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
4317 //ASSERT(!deviceExtension->simplexOnly);
4318 chan
->DpcState
= DPC_STATE_ISR
;
4319 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4320 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
4324 // In simplex mode next command must be sent to device here
4325 if(deviceExtension
->simplexOnly
&& chan
) {
4326 PSCSI_REQUEST_BLOCK srb
;
4327 chan
= UniataGetNextChannel(chan
);
4329 srb
= UniataGetCurRequest(chan
);
4334 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
4338 return RETVAL_XXableInterrupts
;
4340 } // end AtapiEnableInterrupts__()
4342 #endif //UNIATA_CORE
4347 AtapiEnableInterrupts(
4348 IN PVOID HwDeviceExtension
,
4352 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4356 if(c
>= deviceExtension
->NumberChannels
) {
4357 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
4360 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
4361 !UniataAhciChanImplemented(deviceExtension
, c
)) {
4362 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
4366 chan
= &(deviceExtension
->chan
[c
]);
4367 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4368 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
4369 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4370 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
4371 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
4372 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
4373 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
4374 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
4376 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
4377 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
4380 //SelectDrive(chan, 0);
4381 //GetBaseStatus(chan, statusByte);
4382 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4383 0 | IDE_DC_A_4BIT
);
4384 //if(chan->NumberLuns) {
4385 // SelectDrive(chan, 1);
4386 // GetBaseStatus(chan, statusByte);
4387 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4389 // SelectDrive(chan, chan->cur_cdev);
4392 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4394 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4395 // keep interrupts disabled
4396 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4398 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4399 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4403 } // end AtapiEnableInterrupts()
4407 AtapiDisableInterrupts(
4408 IN PVOID HwDeviceExtension
,
4412 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4414 if(c
>= deviceExtension
->NumberChannels
) {
4415 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4418 chan
= &(deviceExtension
->chan
[c
]);
4419 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4420 // mark channel as busy
4421 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4422 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4423 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4425 //SelectDrive(chan, 0);
4426 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4427 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4428 //if(chan->NumberLuns) {
4429 // SelectDrive(chan, 1);
4430 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4431 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4432 // SelectDrive(chan, chan->cur_cdev);
4435 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4439 } // end AtapiDisableInterrupts()
4442 UniataExpectChannelInterrupt(
4443 IN
struct _HW_CHANNEL
* chan
,
4444 IN BOOLEAN Expecting
4447 chan
->ExpectingInterrupt
= Expecting
;
4449 chan
->DeviceExtension
->ExpectingInterrupt
++;
4451 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4452 chan
->DeviceExtension
->ExpectingInterrupt
--;
4455 } // end UniataExpectChannelInterrupt()
4458 Check hardware for interrupt state
4462 AtapiCheckInterrupt__(
4463 IN PVOID HwDeviceExtension
,
4464 IN UCHAR c
// logical channel
4467 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4468 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4469 PHW_LU_EXTENSION LunExt
;
4471 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4472 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4475 ULONG pr_status
= 0;
4476 UCHAR dma_status
= 0;
4479 UCHAR statusByte
= 0;
4480 ULONG slotNumber
= deviceExtension
->slotNumber
;
4481 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4482 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4485 BOOLEAN DmaTransfer
= FALSE
;
4486 BOOLEAN OurInterrupt
= FALSE
;
4487 BOOLEAN StatusValid
= FALSE
;
4489 UCHAR interruptReason
;
4490 BOOLEAN EarlyIntr
= FALSE
;
4491 BOOLEAN SingleBlockIntr
= FALSE
;
4493 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4496 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4497 LunExt
= chan
->lun
[chan
->cur_cdev
];
4499 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4500 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4502 if((ChipFlags
& UNIATA_AHCI
) &&
4503 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4505 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4506 return OurInterrupt
;
4509 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4510 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4511 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4512 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4513 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4514 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4515 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4516 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4517 OurInterrupt
= INTERRUPT_REASON_OUR
;
4519 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4520 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4521 OurInterrupt
= INTERRUPT_REASON_OUR
;
4523 if(statusByte
& IDE_STATUS_ERROR
) {
4524 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4525 OurInterrupt
= INTERRUPT_REASON_OUR
;
4527 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4528 OurInterrupt
= INTERRUPT_REASON_OUR
;
4531 return OurInterrupt
;
4534 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4536 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4537 deviceExtension
->Channel
+ c
, c
));
4539 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4540 deviceExtension
->Channel
+ c
, c
));
4541 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4542 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4545 // do controller-specific interrupt servicing staff
4546 if(deviceExtension
->UnknownDev
) {
4547 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4552 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4553 // Such behavior was observed with Intel ICH-xxx chips
4554 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4558 case ATA_PROMISE_ID
: {
4562 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4566 ((Channel
) ? 0x00004000 : 0x00000400))) {
4567 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4568 return INTERRUPT_REASON_IGNORE
;
4572 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4573 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4576 if(!(status
& 0x20)) {
4577 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4578 return INTERRUPT_REASON_IGNORE
;
4582 ULONG stat_reg
= (ChipFlags
& PRG2
) ? 0x60 : 0x6c;
4583 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40);
4584 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40, status
);
4586 if(status
& (1 << (Channel
+1))) {
4589 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4590 return INTERRUPT_REASON_IGNORE
;
4593 if(!(ChipFlags
& UNIATA_SATA
))
4596 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
);
4597 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
, (pr_status
& (0x11 << Channel
)));
4598 if(pr_status
& (0x11 << Channel
)) {
4599 // TODO: reset channel
4600 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4601 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4603 if(!(status
& (0x01 << Channel
))) {
4605 KdPrint2((PRINT_PREFIX
" Promise mio unexpected attach\n"));
4606 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4608 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4609 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4611 return INTERRUPT_REASON_IGNORE
;
4614 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4618 case ATA_NVIDIA_ID
: {
4619 if(!(ChipFlags
& UNIATA_SATA
))
4622 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4624 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4625 ULONG shift
= Channel
* ((ChipFlags
& NVQ
) ? 4 : 16);
4627 /* get and clear interrupt status */
4628 if(ChipFlags
& NVQ
) {
4629 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4630 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4632 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4633 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4635 KdPrint2((PRINT_PREFIX
" pr_status %x, shift %x\n", pr_status
, shift
));
4637 /* check for and handle connect events */
4638 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4639 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4641 /* check for and handle disconnect events */
4642 if((pr_status
& (0x08UL
<< shift
)) &&
4643 !((pr_status
& (0x04UL
<< shift
) &&
4644 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4645 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4647 /* do we have any device action ? */
4648 if(!(pr_status
& (0x01UL
<< shift
))) {
4649 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4650 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4651 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4653 return INTERRUPT_REASON_IGNORE
;
4659 KdPrint2((PRINT_PREFIX
"ATI\n"));
4660 if(ChipType
== SIIMIO
) {
4665 case ATA_SILICON_IMAGE_ID
:
4667 if(ChipType
== SIIMIO
) {
4669 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4670 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4671 if(reg32
== 0xffffffff) {
4672 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4673 return INTERRUPT_REASON_IGNORE
;
4675 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
))) {
4676 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4677 return INTERRUPT_REASON_IGNORE
;
4680 if(ChipFlags
& UNIATA_SATA
) {
4681 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4683 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4684 * controllers continue to assert IRQ as long as
4685 * SError bits are pending. Clear SError immediately.
4687 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4688 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4695 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4696 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4697 return OurInterrupt
;
4699 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4700 goto skip_dma_stat_check
;
4703 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4705 GetPciConfig1(0x71, reg8
);
4706 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4708 (Channel
? 0x08 : 0x04))) {
4709 return INTERRUPT_REASON_IGNORE
;
4712 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4713 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4715 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4722 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4723 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4724 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4725 return INTERRUPT_REASON_IGNORE
;
4727 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4728 AtapiStallExecution(1);
4729 AtapiWritePort1(chan
, IDX_BM_Command
,
4730 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4731 goto skip_dma_stat_check
;
4733 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4734 if(ChipFlags
& UNIATA_AHCI
) {
4737 if(ChipFlags
& UNIATA_SATA
) {
4738 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4739 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4741 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4742 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4743 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4750 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4751 if(ChipFlags
& UNIATA_AHCI
) {
4754 if(ChipFlags
& UNIATA_SATA
) {
4755 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4756 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4762 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4764 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4765 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4766 if(dma_status
& BM_STATUS_ERR
) {
4767 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4768 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4770 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4771 GetStatus(chan
, statusByte
);
4773 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4774 if(statusByte
& IDE_STATUS_ERROR
) {
4775 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4776 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4778 if ((statusByte
& IDE_STATUS_DSC
) &&
4779 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4780 (dma_status
== BM_STATUS_ACTIVE
)) {
4781 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4782 // some devices interrupts on each block transfer even in DMA mode
4783 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4784 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4785 ///* clear interrupt and get status */
4786 //GetBaseStatus(chan, statusByte);
4787 //return INTERRUPT_REASON_IGNORE;
4788 SingleBlockIntr
= TRUE
;
4791 return INTERRUPT_REASON_IGNORE
;
4796 if(dma_status
& BM_STATUS_INTR
) {
4797 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4798 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4799 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4801 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4804 skip_dma_stat_check
:
4805 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4806 AtapiStallExecution(1);
4809 /* if drive is busy it didn't interrupt */
4810 /* the exception is DCS + BSY state of ATAPI devices */
4812 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4813 GetStatus(chan
, statusByte
);
4815 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4816 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4818 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4820 if (statusByte
== IDE_STATUS_WRONG
) {
4821 // interrupt from empty controller ?
4823 if (statusByte
& IDE_STATUS_BUSY
) {
4824 if(!chan
->ExpectingInterrupt
) {
4825 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4826 return OurInterrupt
;
4829 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4830 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4832 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4833 return INTERRUPT_REASON_IGNORE
;
4835 if((statusByte
& ~(IDE_STATUS_DRQ
| IDE_STATUS_INDEX
)) !=
4836 (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4837 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4838 return INTERRUPT_REASON_IGNORE
;
4840 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4841 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4842 return INTERRUPT_REASON_IGNORE
;
4847 if(dma_status
& BM_STATUS_INTR
) {
4848 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4849 /* clear interrupt and get status */
4850 GetBaseStatus(chan
, statusByte
);
4851 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4852 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4854 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4855 return INTERRUPT_REASON_OUR
;
4858 if(g_WaitBusyInISR
) {
4859 GetStatus(chan
, statusByte
);
4860 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4861 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4862 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4863 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4864 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4866 if (statusByte
& IDE_STATUS_BUSY
) {
4867 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4868 return INTERRUPT_REASON_IGNORE
;
4874 /* clear interrupt and get status */
4875 GetBaseStatus(chan
, statusByte
);
4876 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4877 if (statusByte
== IDE_STATUS_WRONG
) {
4878 // interrupt from empty controller ?
4880 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4881 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4882 return OurInterrupt
;
4885 #ifndef UNIATA_PIO_ONLY
4887 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4888 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4890 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4891 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4895 if(SingleBlockIntr
) {
4896 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4898 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4901 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4907 if (!(chan
->ExpectingInterrupt
)) {
4909 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4911 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4912 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4914 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4915 return OurInterrupt
;
4917 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4918 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4919 return OurInterrupt
;
4921 //ASSERT(!chan->queue_depth || chan->cur_req);
4923 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4924 return INTERRUPT_REASON_OUR
;
4926 } // end AtapiCheckInterrupt__()
4932 IN PVOID HwDeviceExtension
,
4936 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4937 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4939 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4940 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4942 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4943 ULONG status
= SRB_STATUS_SUCCESS
;
4944 UCHAR dma_status
= 0;
4947 UCHAR statusByte
= 0,interruptReason
;
4949 BOOLEAN atapiDev
= FALSE
;
4956 BOOLEAN DmaTransfer
= FALSE
;
4958 ULONG TimerValue
= 1000;
4959 ULONG TotalTimerValue
= 0;
4960 #ifdef UNIATA_USE_XXableInterrupts
4961 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4963 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4964 #endif // UNIATA_USE_XXableInterrupts
4965 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4966 // BOOLEAN RestoreUseDpc = FALSE;
4967 BOOLEAN DataOverrun
= FALSE
;
4968 BOOLEAN NoStartIo
= TRUE
;
4969 BOOLEAN NoRetry
= FALSE
;
4971 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4973 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4974 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4980 UCHAR OldReqState
= REQ_STATE_NONE
;
4982 PHW_LU_EXTENSION LunExt
;
4987 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4989 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4992 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4993 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4994 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4996 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
5000 PathId
= srb
->PathId
;
5001 TargetId
= srb
->TargetId
;
5007 goto enqueue_next_req
;
5010 //ldev = GET_LDEV2(PathId, TargetId, Lun);
5011 DeviceNumber
= (UCHAR
)(TargetId
);
5012 LunExt
= chan
->lun
[DeviceNumber
];
5013 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
5014 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
5016 // check if we are in ISR DPC
5018 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
5019 goto ServiceInterrupt
;
5023 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
5026 if (!(chan
->ExpectingInterrupt
)) {
5028 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
5032 // change request state
5034 OldReqState
= AtaReq
->ReqState
;
5035 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
5036 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
5039 // We don't want using DPC for fast operations, like
5040 // DMA completion, sending CDB, short ATAPI transfers, etc.
5042 // We MUST use DPC, because of interprocessor synchronization
5043 // on multiprocessor platforms
5046 goto ServiceInterrupt
;
5048 switch(OldReqState
) {
5049 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
5050 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
5051 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
5052 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
5053 case REQ_STATE_DPC_WAIT_BUSY0
:
5054 case REQ_STATE_DPC_WAIT_BUSY1
:
5055 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
5056 goto ServiceInterrupt
;
5057 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
5058 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
5062 if((!DmaTransfer
&& !atapiDev
) || deviceExtension
->DriverMustPoll
) {
5063 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
5070 goto ServiceInterrupt
;
5072 #ifdef UNIATA_USE_XXableInterrupts
5074 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
5076 // shall never get here
5081 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
5083 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
5084 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
5086 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
5089 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
5090 goto ServiceInterrupt
;
5091 #endif // UNIATA_USE_XXableInterrupts
5096 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
5097 // We always get here when are called from timer callback, which is invoked on DRQL.
5098 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
5100 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
5101 // disable interrupts for this channel,
5102 // but avoid recursion and double-disable
5103 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
5104 UniataExpectChannelInterrupt(chan
, FALSE
);
5105 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5108 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
5110 #ifdef UNIATA_USE_XXableInterrupts
5111 // Will lower IRQL to DISPATCH_LEVEL
5112 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
5113 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
5114 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
5116 // Will raise IRQL to DIRQL
5117 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
5120 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5121 #endif // UNIATA_USE_XXableInterrupts
5126 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
5128 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
5129 // we must block interrupts from this channel
5130 // If device generate new interrupt before we get to DPC,
5131 // ISR will assume, that it is NOT our interrupt
5132 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5133 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
5135 // Will raise IRQL to DIRQL
5136 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
5140 #endif //UNIATA_CORE
5144 if(AtaReq
&& InDpc
) {
5145 switch(AtaReq
->ReqState
) {
5146 case REQ_STATE_DPC_WAIT_DRQ0
:
5148 case REQ_STATE_DPC_WAIT_BUSY
:
5150 case REQ_STATE_DPC_WAIT_DRQ
:
5152 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
5154 case REQ_STATE_DPC_WAIT_BUSY0
:
5155 case REQ_STATE_DPC_WAIT_BUSY1
:
5156 // continue normal execution
5162 #endif //UNIATA_CORE
5164 // make additional delay for old devices (if we are not in DPC)
5165 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
5169 !(deviceExtension->HwFlags & UNIATA_SATA)
5171 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
5172 AtapiStallExecution(10);
5176 /* clear interrupt and get status */
5177 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5178 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
5179 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
5181 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
5182 KdPrint3((PRINT_PREFIX
"Err intr (%#x), SE (%#x)\n",
5183 chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
),
5184 chan
->AhciLastSError
));
5185 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
5186 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
5187 // We have some other error except Overflow
5188 // Just signal ERROR, operation will be aborted in ERROR branch.
5189 statusByte
|= IDE_STATUS_ERROR
;
5190 AtaReq
->ahci
.in_serror
= chan
->AhciLastSError
;
5191 if(chan
->AhciLastSError
& (ATA_SE_HANDSHAKE_ERR
| ATA_SE_LINKSEQ_ERR
| ATA_SE_TRANSPORT_ERR
| ATA_SE_UNKNOWN_FIS
)) {
5192 KdPrint2((PRINT_PREFIX
"Unrecoverable\n"));
5196 // We have only Overflow. Abort operation and continue
5198 UniataDumpAhciPortRegs(chan
);
5200 if(!UniataAhciAbortOperation(chan
)) {
5201 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5204 UniataDumpAhciPortRegs(chan
);
5206 UniataAhciWaitCommandReady(chan
, 10);
5211 GetBaseStatus(chan
, statusByte
);
5214 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
5216 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
5220 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
5226 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5227 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
5229 if (statusByte
& IDE_STATUS_BUSY
) {
5230 if (deviceExtension
->DriverMustPoll
) {
5231 // Crashdump is polling and we got caught with busy asserted.
5232 // Just go away, and we will be polled again shortly.
5233 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
5234 goto ReturnEnableIntr
;
5237 // Ensure BUSY is non-asserted.
5238 // make a very small idle before falling to DPC
5239 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
5241 for (i
= 0; i
< k
; i
++) {
5243 GetBaseStatus(chan
, statusByte
);
5244 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5247 AtapiStallExecution(10);
5250 if (!InDpc
&& UseDpc
&& i
== 2) {
5252 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
5255 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5260 AtapiStallExecution(TimerValue
);
5261 goto ServiceInterrupt
;
5262 #endif //UNIATA_CORE
5264 if (InDpc
&& i
== k
) {
5265 // reset the controller.
5266 KdPrint2((PRINT_PREFIX
5267 " Resetting due to BUSY on entry - %#x.\n",
5269 goto IntrPrepareResetController
;
5274 if(!LunExt
->IdentifyData
.MajorRevision
&&
5277 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
5279 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
5280 //AtapiStallExecution(10);
5282 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5283 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
5285 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5286 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5289 if (statusByte
& IDE_STATUS_BUSY
) {
5290 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
5293 // This is just workaround
5294 // We should DISABLE interrupts before entering WAIT state
5295 UniataExpectChannelInterrupt(chan, TRUE);
5296 #endif //UNIATA_CORE
5298 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
5300 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
5301 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
5302 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
5303 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5306 #endif //UNIATA_CORE
5309 GetBaseStatus(chan
, statusByte
);
5310 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5311 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
5312 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
5313 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5314 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
5317 TotalTimerValue
+= TimerValue
;
5319 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
5321 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
5323 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5325 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
5327 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
5331 if(!LunExt
->AtapiReadyWaitDelay
) {
5332 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5336 #endif //UNIATA_CORE
5339 AtapiStallExecution(TimerValue
);
5342 if(!LunExt
->AtapiReadyWaitDelay
) {
5343 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5344 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
5346 if (statusByte
& IDE_STATUS_BUSY
) {
5347 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
5353 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5354 switch(OldReqState
) {
5355 case REQ_STATE_EARLY_INTR
:
5356 case REQ_STATE_DPC_WAIT_BUSY0
:
5358 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
5359 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
5360 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5367 // Check for error conditions.
5368 if ((statusByte
& IDE_STATUS_ERROR
) ||
5369 (dma_status
& BM_STATUS_ERR
)) {
5371 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5372 error
= AtaReq
->ahci
.in_error
;
5375 UniataDumpAhciPortRegs(chan
);
5377 if(!UniataAhciAbortOperation(chan
)) {
5378 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5380 // clear interrupts again
5381 UniataAhciWaitCommandReady(chan
, 10);
5383 UniataDumpAhciPortRegs(chan
);
5385 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
5387 AtaReq
->retry
+= MAX_RETRIES
;
5388 if(!error
&& (statusByte
& IDE_STATUS_ERROR
)) {
5389 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: force error status\n"));
5390 error
|= IDE_STATUS_ERROR
;
5394 UniataDumpAhciPortRegs(chan
);
5397 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5399 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
5401 if(error & IDE_STATUS_CORRECTED_ERROR) {
5402 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5403 statusByte &= ~IDE_STATUS_ERROR;
5408 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
5410 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
5413 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5414 KdPrint2((PRINT_PREFIX
" no wait ready after error\n"));
5417 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
5418 AtapiStallExecution(100);
5420 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
5421 AtapiStallExecution(10);
5425 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
5426 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
5428 for (k
= atapiDev
? 0 : 200; k
; k
--) {
5429 GetBaseStatus(chan
, statusByte
);
5430 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5431 AtapiStallExecution(50);
5438 /* if this is a UDMA CRC error, reinject request */
5441 if(AtaReq
->retry
< MAX_RETRIES
) {
5442 #ifdef IO_STATISTICS
5443 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5444 #endif //IO_STATISTICS
5446 (error & IDE_ERROR_ICRC)*/) {
5447 KdPrint2((PRINT_PREFIX
"Errors in DMA mode\n"));
5448 if(AtaReq
->retry
< MAX_RETRIES
) {
5450 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5451 //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5452 // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
5453 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5455 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5459 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5462 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5466 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5467 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5469 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
5470 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5473 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
5474 UniataSataClearErr(HwDeviceExtension
, lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 0);
5478 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5479 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5480 if(AtaReq
->retry
< MAX_RETRIES
) {
5482 // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
5483 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5484 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5485 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5486 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5490 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5493 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5497 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5498 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5499 // Fail this request.
5500 status
= SRB_STATUS_ERROR
;
5501 goto CompleteRequest
;
5503 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5506 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5507 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5508 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5510 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5511 #ifdef IO_STATISTICS
5512 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5513 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5515 LunExt
->RecoverCount
[AtaReq
->retry
],
5516 LunExt
->BlockIoCount
5518 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5519 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= LunExt
->BlockIoCount
/3 ||
5520 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5523 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5524 #endif //IO_STATISTICS
5525 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5526 LunExt
->LimitedTransferMode
=
5527 LunExt
->TransferMode
;
5530 #ifdef IO_STATISTICS
5531 if(AtaReq
->bcount
) {
5532 // we need stats for Read/Write operations
5533 LunExt
->BlockIoCount
++;
5536 #endif //IO_STATISTICS
5540 // check reason for this interrupt.
5543 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5546 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5547 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5549 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5551 wordsThisInterrupt
= DEV_BSIZE
/2;
5559 // simulate DRQ for DMA transfers
5560 statusByte
|= IDE_STATUS_DRQ
;
5562 if (statusByte
& IDE_STATUS_DRQ
) {
5565 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5567 if (LunExt
->MaximumBlockXfer
) {
5568 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5571 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5573 interruptReason
= ATAPI_IR_IO_toHost
;
5575 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5576 interruptReason
= ATAPI_IR_IO_toDev
;
5579 status
= SRB_STATUS_ERROR
;
5580 goto CompleteRequest
;
5583 } else if (statusByte
& IDE_STATUS_BUSY
) {
5585 //AtapiEnableInterrupts(deviceExtension, lChannel);
5586 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5591 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq
->WordsLeft
));
5592 if (AtaReq
->WordsLeft
) {
5594 // Funky behaviour seen with PCI IDE (not all, just one).
5596 // The ISR hits with DRQ low, but comes up later.
5597 for (k
= 0; k
< 5000; k
++) {
5598 GetBaseStatus(chan
, statusByte
);
5599 if (statusByte
& IDE_STATUS_DRQ
) {
5604 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5606 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5610 AtapiStallExecution(TimerValue
);
5611 goto ServiceInterrupt
;
5612 #endif //UNIATA_CORE
5614 AtapiStallExecution(100);
5617 // reset the controller.
5618 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5620 IntrPrepareResetController
:
5621 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5622 goto ReturnEnableIntr
;
5625 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5629 // Command complete - verify, write, or the SMART enable/disable.
5630 // Also get_media_status
5631 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5636 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5637 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5638 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5639 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5640 //status = SRB_STATUS_DATA_OVERRUN;
5643 status = SRB_STATUS_SUCCESS;
5645 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5646 AtaReq
->WordsLeft
= 0;
5648 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5650 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5651 // status = SRB_STATUS_DATA_OVERRUN;
5653 status
= SRB_STATUS_SUCCESS
;
5654 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5655 goto CompleteRequest
;
5657 if ((interruptReason
== ATAPI_IR_COD_Cmd
) && (statusByte
& IDE_STATUS_DRQ
)) {
5658 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5659 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, srb
);
5661 // Write the packet.
5662 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5663 // Send CDB to device.
5664 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5665 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5667 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5669 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5670 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5671 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5674 goto ReturnEnableIntr
;
5676 } else if ((interruptReason
== ATAPI_IR_IO_toDev
) && (statusByte
& IDE_STATUS_DRQ
)) {
5681 // Pick up bytes to transfer and convert to words.
5683 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5686 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5688 // Covert bytes to words.
5690 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5692 if (wordCount
!= AtaReq
->WordsLeft
) {
5693 KdPrint2((PRINT_PREFIX
5694 "AtapiInterrupt: %d words requested; %d words xferred\n",
5699 // Verify this makes sense.
5700 if (wordCount
> AtaReq
->WordsLeft
) {
5701 wordCount
= AtaReq
->WordsLeft
;
5702 KdPrint2((PRINT_PREFIX
5703 "AtapiInterrupt: Write underrun\n"));
5709 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5710 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5711 // Transfer only words requested.
5712 wordCount
= AtaReq
->WordsLeft
;
5714 // Transfer next block.
5715 wordCount
= wordsThisInterrupt
;
5720 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5721 //ASSERT(AtaReq->WordsLeft == wordCount);
5722 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5723 KdPrint2((PRINT_PREFIX
5724 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5725 if(AtaReq
->WordsLeft
> wordCount
) {
5726 AtaReq
->WordsLeft
-= wordCount
;
5727 AtaReq
->WordsTransfered
+= wordCount
;
5728 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5729 goto ReturnEnableIntr
;
5731 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5733 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5734 AtaReq
->WordsLeft
= 0;
5735 status
= SRB_STATUS_SUCCESS
;
5736 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5737 goto CompleteRequest
;
5740 // Ensure that this is a write command.
5741 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5743 KdPrint2((PRINT_PREFIX
5744 "AtapiInterrupt: Write interrupt\n"));
5746 statusByte
= WaitOnBusy(chan
);
5748 if (/*atapiDev || */ !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/
5749 || (wordCount
& 1)) {
5754 UniataGetPioTiming(LunExt
));
5758 (PULONG
)(AtaReq
->DataBuffer
),
5760 UniataGetPioTiming(LunExt
));
5764 KdPrint3((PRINT_PREFIX
5765 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5769 // Fail this request.
5770 status
= SRB_STATUS_ERROR
;
5771 if(!wordCount
&& atapiDev
&& (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
)) {
5772 // some devices feel bad after incorrect commands and may need reset
5773 KdPrint2((PRINT_PREFIX
5774 "AtapiInterrupt: Try ATAPI reset\n"));
5776 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5777 AtapiSoftReset(chan
, DeviceNumber
);
5778 AtapiEnableInterrupts(deviceExtension
, lChannel
);
5779 status
= SRB_STATUS_BUS_RESET
;
5780 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5782 // goto IntrPrepareResetController;
5784 goto CompleteRequest
;
5786 // Advance data buffer pointer and bytes left.
5787 AtaReq
->DataBuffer
+= wordCount
;
5788 AtaReq
->WordsLeft
-= wordCount
;
5789 AtaReq
->WordsTransfered
+= wordCount
;
5792 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5795 goto ReturnEnableIntr
;
5797 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5803 // Pick up bytes to transfer and convert to words.
5805 (ULONG
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5806 ((ULONG
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5808 // Convert bytes to words.
5809 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R byteCount %#x\n", wordCount
));
5812 When ATAPI 64k PIO read is requested we may have 0xfffe byte
5813 count reported for 0x10000 bytes in single interrupt.
5814 It is not allowed to read entire 64k block with DwordIo intead of
5817 if (wordCount
!= AtaReq
->WordsLeft
) {
5818 KdPrint2((PRINT_PREFIX
5819 "AtapiInterrupt: %d words requested; %d words xferred\n",
5824 // Verify this makes sense.
5825 if (wordCount
> AtaReq
->WordsLeft
) {
5826 wordCount
= AtaReq
->WordsLeft
;
5832 // Check if words left is at least 256.
5833 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5834 // Transfer only words requested.
5835 wordCount
= AtaReq
->WordsLeft
;
5837 // Transfer next block.
5838 wordCount
= wordsThisInterrupt
;
5843 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5844 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5845 KdPrint2((PRINT_PREFIX
5846 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5847 if(AtaReq
->WordsLeft
> wordCount
) {
5848 AtaReq
->WordsLeft
-= wordCount
;
5849 AtaReq
->WordsTransfered
+= wordCount
;
5850 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5851 goto ReturnEnableIntr
;
5853 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5855 //ASSERT(AtaReq->WordsLeft == wordCount);
5856 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5857 AtaReq
->WordsLeft
= 0;
5858 status
= SRB_STATUS_SUCCESS
;
5859 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5860 goto CompleteRequest
;
5862 // Ensure that this is a read command.
5863 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5866 "AtapiInterrupt: Read interrupt\n"));*/
5868 statusByte
= WaitOnBusy(chan
);
5870 if(wordCount
&1 && atapiDev
&& (g_opt_VirtualMachine
== VM_BOCHS
)) {
5871 KdPrint2((PRINT_PREFIX
5872 "IdeIntr: unaligned ATAPI %#x Words\n", wordCount
));
5874 if(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) {
5875 KdPrint2((PRINT_PREFIX
5876 "IdeIntr: pre-Read %#x Dwords\n", wordCount
/2));
5879 (PULONG
)(AtaReq
->DataBuffer
),
5881 UniataGetPioTiming(LunExt
));
5882 // Advance data buffer pointer and bytes left.
5883 AtaReq
->DataBuffer
+= wordCount
& ~1;
5884 AtaReq
->WordsLeft
-= wordCount
& ~1;
5885 AtaReq
->WordsTransfered
+= wordCount
& ~1;
5889 KdPrint2((PRINT_PREFIX
5890 "IdeIntr: Read %#x words\n", wordCount
));
5895 UniataGetPioTiming(LunExt
));
5898 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5899 //KdDump(AtaReq->DataBuffer, wordCount*2);
5900 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5901 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5904 GetBaseStatus(chan
, statusByte
);
5905 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5908 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5909 AtapiSuckPort2(chan
);
5910 GetBaseStatus(chan
, statusByte
);
5913 if(statusByte
& IDE_STATUS_BUSY
) {
5914 for (i
= 0; i
< 2; i
++) {
5915 AtapiStallExecution(10);
5916 GetBaseStatus(chan
, statusByte
);
5917 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5925 KdPrint3((PRINT_PREFIX
5926 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5930 // Fail this request.
5931 status
= SRB_STATUS_ERROR
;
5932 goto CompleteRequest
;
5934 //continue_atapi_pio_read:
5935 // Advance data buffer pointer and bytes left.
5936 AtaReq
->DataBuffer
+= wordCount
;
5937 AtaReq
->WordsLeft
-= wordCount
;
5938 AtaReq
->WordsTransfered
+= wordCount
;
5940 // Check for read command complete.
5941 if (AtaReq
->WordsLeft
== 0) {
5943 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5946 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
) {
5948 // Work around to make many atapi devices return correct sector size
5949 // of 2048. Also certain devices will have sector count == 0x00, check
5951 if (srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) {
5953 AtaReq
->DataBuffer
-= AtaReq
->WordsTransfered
;
5954 if (AtaReq
->DataBuffer
[0] == 0x00) {
5955 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5958 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5959 AtaReq
->DataBuffer
+= AtaReq
->WordsTransfered
;
5961 #ifndef UNIATA_INIT_CHANGERS
5963 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5965 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5967 AtapiHwInitializeChanger (HwDeviceExtension
,
5969 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5970 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
5971 KdPrint2((PRINT_PREFIX
" set DFLAGS_CHANGER_INITED\n"));
5973 #endif // UNIATA_INIT_CHANGERS
5975 GetStatus(chan
, statusByte
);
5976 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5977 // Assume command is completed if BUSY is cleared
5978 // and all data read
5979 // Optionally, we may receive COMPLETE interrupt later and
5980 // treat it as unexpected
5981 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5983 status
= SRB_STATUS_SUCCESS
;
5984 goto CompleteRequest
;
5990 // Completion for IDE drives.
5991 if (AtaReq->WordsLeft) {
5992 status = SRB_STATUS_DATA_OVERRUN;
5994 status = SRB_STATUS_SUCCESS;
5997 goto CompleteRequest;
5999 status
= SRB_STATUS_SUCCESS
;
6000 goto CompleteRequest
;
6005 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6006 GetStatus(chan
, statusByte
);
6007 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6008 // Assume command is completed if BUSY is cleared
6009 // even if NOT all data read
6010 // Optionally, we may receive COMPLETE interrupt later and
6011 // treat it as unexpected
6012 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
6014 status
= SRB_STATUS_SUCCESS
;
6015 goto CompleteRequest
;
6018 if(!atapiDev
&& !DataOverrun
&& (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) &&
6019 ((statusByte
& ~IDE_STATUS_INDEX
) == (IDE_STATUS_IDLE
| IDE_STATUS_DRQ
))) {
6020 KdPrint2((PRINT_PREFIX
" HDD read data ready \n"));
6021 goto continue_read_drq
;
6026 goto ReturnEnableIntr
;
6028 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
6030 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
6031 // Command complete. We exactly know this because of IReason.
6034 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
6035 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
6036 AtaReq
->WordsLeft
= 0;
6038 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
6040 wordCount
= AtaReq
->WordsLeft
;
6041 // Advance data buffer pointer and bytes left.
6042 AtaReq
->DataBuffer
+= wordCount
;
6043 AtaReq
->WordsLeft
-= wordCount
;
6044 AtaReq
->WordsTransfered
+= wordCount
;
6046 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount
, AtaReq
->WordsTransfered
));
6049 //if (AtaReq->WordsLeft) {
6050 // status = SRB_STATUS_DATA_OVERRUN;
6052 status
= SRB_STATUS_SUCCESS
;
6055 #ifdef UNIATA_DUMP_ATAPI
6057 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6061 PCHAR ModeSelectData
;
6063 PSCSI_REQUEST_BLOCK Srb
= srb
;
6065 Cdb
= (PCDB
)(Srb
->Cdb
);
6066 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6067 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6068 CdbDataLen
= Srb
->DataTransferLength
;
6070 if(CdbDataLen
> 0x1000) {
6071 CdbDataLen
= 0x1000;
6075 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6076 KdPrint2(("P:T:D=%d:%d:%d\n",
6080 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
6083 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
6084 KdPrint(("ModeSense 6\n"));
6085 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6086 ModeSelectData
= CdbData
+4;
6087 KdDump(CdbData
, CdbDataLen
);
6089 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
6090 KdPrint(("ModeSense 10\n"));
6091 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6092 ModeSelectData
= CdbData
+8;
6093 KdDump(CdbData
, CdbDataLen
);
6095 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6096 KdPrint(("Read buffer from device:\n"));
6097 KdDump(CdbData
, CdbDataLen
);
6102 #endif //UNIATA_DUMP_ATAPI
6106 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
6107 // Check and see if we are processing our secret (mechanism status/request sense) srb
6109 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
6110 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
6111 status
= SRB_STATUS_DATA_OVERRUN
;
6114 if (AtaReq
->OriginalSrb
) {
6118 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
6119 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
6120 #ifdef UNIATA_INIT_CHANGERS
6121 // We can get here only when UNIATA_INIT_CHANGERS is defined
6122 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
6123 if (status
== SRB_STATUS_SUCCESS
) {
6125 AtapiHwInitializeChanger (HwDeviceExtension
,
6127 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
6129 // Get ready to issue the original srb
6130 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6131 AtaReq
->OriginalSrb
= NULL
;
6134 // failed! Get the sense key and maybe try again
6135 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
6137 AtaReq
->OriginalSrb
);
6140 // do not enable interrupts in DPC, do not waste time, do it now!
6141 if(UseDpc && chan->DisableIntr) {
6142 AtapiEnableInterrupts(HwDeviceExtension, c);
6144 RestoreUseDpc = TRUE;
6147 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
6149 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
6151 if (srbStatus
== SRB_STATUS_PENDING
) {
6152 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
6153 goto ReturnEnableIntr
;
6157 // restore state on error
6159 AtapiDisableInterrupts(HwDeviceExtension, c);
6163 KdPrint((PRINT_PREFIX
"AtapiInterrupt: ERROR: internal SCSIOP_MECHANISM_STATUS !!!!\n"));
6165 #endif // UNIATA_INIT_CHANGERS
6166 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
6168 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
6172 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
6173 if (status
== SRB_STATUS_DATA_OVERRUN
) {
6174 // Check to see if we at least get mininum number of bytes
6175 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
6176 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
6177 status
= SRB_STATUS_SUCCESS
;
6181 if (status
== SRB_STATUS_SUCCESS
) {
6183 #ifdef UNIATA_INIT_CHANGERS
6184 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
6186 chan
->MechStatusRetryCount
) {
6188 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
6189 // The sense key doesn't say the last request is illegal, so try again
6190 chan
->MechStatusRetryCount
--;
6191 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
6193 AtaReq
->OriginalSrb
);
6195 #endif // UNIATA_INIT_CHANGERS
6197 // Get ready to issue the original srb
6198 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6199 AtaReq
->OriginalSrb
= NULL
;
6201 #endif //UNIATA_CORE
6203 // do not enable interrupts in DPC, do not waste time, do it now!
6204 if(UseDpc && chan->DisableIntr) {
6205 AtapiEnableInterrupts(HwDeviceExtension, c);
6207 RestoreUseDpc = TRUE;
6210 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
6212 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
6214 if (srbStatus
== SRB_STATUS_PENDING
) {
6215 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
6216 goto ReturnEnableIntr
;
6220 // restore state on error
6222 AtapiDisableInterrupts(HwDeviceExtension, c);
6228 // If we get here, it means AtapiSendCommand() has failed
6229 // Can't recover. Pretend the original srb has failed and complete it.
6231 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
6233 if (AtaReq
->OriginalSrb
) {
6234 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6235 AtaReq
->OriginalSrb
= NULL
;
6238 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
6240 // fake an error and read no data
6241 status
= SRB_STATUS_ERROR
;
6242 srb
->ScsiStatus
= 0;
6243 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
6244 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
6247 } else if (status
== SRB_STATUS_ERROR
) {
6249 // Map error to specific SRB status and handle request sense.
6250 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
6251 status
= MapError(deviceExtension
,
6256 } else if(!DmaTransfer
) {
6258 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
6259 // Command complete.
6261 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
6262 // Wait for busy to drop.
6263 for (i
= 0; i
< 5*30; i
++) {
6264 GetBaseStatus(chan
, statusByte
);
6265 if (!(statusByte
& IDE_STATUS_BUSY
)) {
6270 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
6272 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
6276 AtapiStallExecution(TimerValue
);
6277 goto ServiceInterrupt
;
6278 #endif //UNIATA_CORE
6280 AtapiStallExecution(100);
6285 // reset the controller.
6286 KdPrint2((PRINT_PREFIX
6287 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
6289 goto IntrPrepareResetController
;
6291 // Check to see if DRQ is still up.
6292 if(statusByte
& IDE_STATUS_DRQ
) {
6293 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
6295 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6296 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
6298 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
6301 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
6304 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
6306 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
6308 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
6309 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
6310 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
6314 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
6315 //if ((statusByte & IDE_STATUS_DRQ)) {}
6316 if((statusByte
& IDE_STATUS_DRQ
) &&
6317 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
6320 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
6321 for (i
= 0; i
< 200; i
++) {
6322 GetBaseStatus(chan
, statusByte
);
6323 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6328 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
6329 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
6334 AtapiStallExecution(TimerValue
);
6335 goto ServiceInterrupt
;
6336 #endif //UNIATA_CORE
6338 AtapiStallExecution(100);
6342 // reset the controller.
6343 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
6345 goto IntrPrepareResetController
;
6349 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
6350 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
6351 //KdDump(srb->DataBuffer, srb->DataTransferLength);
6353 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
6354 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
6358 // Clear interrupt expecting flag.
6359 UniataExpectChannelInterrupt(chan
, FALSE
);
6360 // clear this flag now, it can be set again in sub-calls
6361 InterlockedExchange(&(chan
->CheckIntr
),
6364 // Sanity check that there is a current request.
6366 // Set status in SRB.
6367 srb
->SrbStatus
= (UCHAR
)status
;
6369 // Check for underflow.
6370 if(AtaReq
->WordsLeft
) {
6372 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
6373 // Subtract out residual words and update if filemark hit,
6374 // setmark hit , end of data, end of media...
6375 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
6376 if (status
== SRB_STATUS_DATA_OVERRUN
) {
6377 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6379 srb
->DataTransferLength
= 0;
6382 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6385 if(status
== SRB_STATUS_SUCCESS
) {
6386 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
6387 // // This should be set in UniataAhciEndTransaction() for AHCI
6388 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
6391 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
6392 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
6393 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6394 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6395 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
6398 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
6399 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6403 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
6406 // Indicate command complete.
6408 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
6411 if (status
== SRB_STATUS_SUCCESS
&&
6412 srb
->SenseInfoBuffer
&&
6413 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
6415 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
6417 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
6418 senseBuffer
->ErrorCode
= 0;
6419 senseBuffer
->Valid
= 1;
6420 senseBuffer
->AdditionalSenseLength
= 0xb;
6421 senseBuffer
->SenseKey
= 0;
6422 senseBuffer
->AdditionalSenseCode
= 0;
6423 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6425 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
6427 AtapiDmaDBSync(chan
, srb
);
6428 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
6429 UniataRemoveRequest(chan
, srb
);
6430 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
6431 ScsiPortNotification(RequestComplete
,
6437 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
6439 if (status
!= SRB_STATUS_SUCCESS
) {
6440 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6441 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
6444 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6446 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6447 // Build the SMART status block depending upon the completion status.
6448 cmdOutParameters
->cBufferSize
= wordCount
;
6449 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
6450 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
6452 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6454 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
6455 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
6458 UniataSnapAtaRegs(chan
, 0, regs
);
6460 regs
->bCommandReg
= SMART_CMD
;
6461 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
6463 cmdOutParameters
->cBufferSize
= 8;
6465 chan
->SmartCommand
= 0; // cleanup after execution
6467 // Indicate command complete.
6468 goto IntrCompleteReq
;
6473 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
6478 for (i
= 0; i
< 5; i
++) {
6479 GetBaseStatus(chan
, statusByte
);
6480 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6481 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
6485 if (statusByte
& IDE_STATUS_DSC
) {
6486 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
6490 AtapiStallExecution(50);
6493 // RDP can be cleared since previous check
6495 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6501 AtapiStallExecution(TimerValue
);
6502 goto ServiceInterrupt
;
6503 #endif //UNIATA_CORE
6506 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6509 srb
= UniataGetCurRequest(chan
);
6514 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6516 ScsiPortNotification(NextRequest
,
6520 ScsiPortNotification(NextLuRequest
,
6525 // in simplex mode next command must NOT be sent here
6526 if(!deviceExtension
->simplexOnly
) {
6527 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6530 // Try to get SRB fron any non-empty queue (later)
6531 if(deviceExtension
->simplexOnly
) {
6534 #endif //UNIATA_CORE
6536 goto ReturnEnableIntr
;
6540 // Unexpected int. Catch it
6541 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6545 if(g_opt_VirtualMachine
== VM_QEMU
) {
6546 if(interruptReason
== ATAPI_IR_IO_toDev
&& !(statusByte
& IDE_STATUS_DRQ
) && !DmaTransfer
) {
6547 statusByte
= WaitForDrq(chan
);
6548 if(statusByte
& IDE_STATUS_DRQ
) {
6554 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6555 AtaReq
->WordsLeft
== 0) {
6556 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6557 status
= SRB_STATUS_SUCCESS
;
6558 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6559 goto CompleteRequest
;
6565 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6566 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6567 deviceExtension
->ExpectingInterrupt
= TRUE
;
6569 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6570 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6571 #ifdef UNIATA_USE_XXableInterrupts
6572 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6573 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6574 // must be called on DISPATCH_LEVEL
6575 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6576 AtapiEnableInterrupts__
);
6578 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6579 InterlockedExchange(&(chan
->CheckIntr
),
6581 // Will raise IRQL to DIRQL
6583 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6584 AtapiEnableInterrupts__
,
6586 #endif // UNIATA_CORE
6587 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6588 #endif // UNIATA_USE_XXableInterrupts
6592 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6593 // in simplex mode next command must be sent here if
6595 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6598 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6599 chan
= UniataGetNextChannel(chan
);
6601 srb
= UniataGetCurRequest(chan
);
6605 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6607 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6610 #endif //UNIATA_CORE
6613 } // end AtapiInterrupt__()
6619 Routine Description:
6621 This routine handles SMART enable, disable, read attributes and threshold commands.
6625 HwDeviceExtension - HBA miniport driver's adapter data storage
6626 Srb - IO request packet
6635 IdeSendSmartCommand(
6636 IN PVOID HwDeviceExtension
,
6637 IN PSCSI_REQUEST_BLOCK Srb
,
6638 IN ULONG targetId
// assume it is always valid
6641 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6642 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6643 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6644 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6645 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6646 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6647 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6652 if (regs
->bCommandReg
!= SMART_CMD
) {
6653 KdPrint2((PRINT_PREFIX
6654 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6655 return SRB_STATUS_INVALID_REQUEST
;
6658 c
= targetId
/ deviceExtension
->NumberLuns
;
6659 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6660 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6662 chan
= &(deviceExtension
->chan
[c
]);
6664 chan
->SmartCommand
= regs
->bFeaturesReg
;
6666 // Determine which of the commands to carry out.
6667 switch(regs
->bFeaturesReg
) {
6668 case READ_ATTRIBUTES
:
6669 case READ_THRESHOLDS
:
6670 case READ_LOG_SECTOR
:
6671 case WRITE_LOG_SECTOR
:
6673 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6674 KdPrint2((PRINT_PREFIX
6675 "IdeSendSmartCommand: wrong buffer size\n"));
6676 return SRB_STATUS_DATA_OVERRUN
;
6679 statusByte
= WaitOnBusy(chan
);
6681 if (statusByte
& IDE_STATUS_BUSY
) {
6682 KdPrint2((PRINT_PREFIX
6683 "IdeSendSmartCommand: Returning BUSY status\n"));
6684 return SRB_STATUS_BUSY
;
6687 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6688 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6690 // Set data buffer pointer and words left.
6691 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6692 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6694 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6696 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6698 regs
->bSectorNumberReg
,
6699 regs
->bSectorCountReg
,
6703 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6704 // Wait for interrupt.
6705 return SRB_STATUS_PENDING
;
6707 return SRB_STATUS_ERROR
;
6711 case RETURN_SMART_STATUS
:
6712 case ENABLE_DISABLE_AUTOSAVE
:
6713 case EXECUTE_OFFLINE_DIAGS
:
6714 case SAVE_ATTRIBUTE_VALUES
:
6717 statusByte
= WaitOnBusy(chan
);
6719 if (statusByte
& IDE_STATUS_BUSY
) {
6720 KdPrint2((PRINT_PREFIX
6721 "IdeSendSmartCommand: Returning BUSY status\n"));
6722 return SRB_STATUS_BUSY
;
6725 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6726 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6728 // Set data buffer pointer and indicate no data transfer.
6729 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6730 AtaReq
->WordsLeft
= 0;
6732 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6734 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6736 regs
->bSectorNumberReg
,
6737 regs
->bSectorCountReg
,
6741 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6742 // Wait for interrupt.
6743 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6744 return SRB_STATUS_PENDING
;
6746 return SRB_STATUS_ERROR
;
6747 } // end switch(regs->bFeaturesReg)
6749 return SRB_STATUS_INVALID_REQUEST
;
6751 } // end IdeSendSmartCommand()
6753 #endif //UNIATA_CORE
6757 UniAtaCalculateLBARegs(
6758 PHW_LU_EXTENSION LunExt
,
6759 ULONGLONG startingSector
,
6763 UCHAR drvSelect
,sectorNumber
;
6767 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6769 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6770 if(LunExt
->DeviceExtension
) {
6771 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6774 return startingSector
;
6776 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6777 LunExt
->IdentifyData
.NumberOfHeads
;
6779 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6783 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6785 cylinder
= (USHORT
)(startingSector
/ tmp
);
6786 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6787 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6788 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6789 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6790 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6793 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6794 } // end UniAtaCalculateLBARegs()
6798 UniAtaCalculateLBARegsBack(
6799 PHW_LU_EXTENSION LunExt
,
6803 ULONG drvSelect
,sectorNumber
;
6807 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6810 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6811 LunExt
->IdentifyData
.NumberOfHeads
;
6813 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6814 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6815 sectorNumber
= (UCHAR
)(lba
& 0xff);
6817 lba
= sectorNumber
-1 +
6818 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6822 } // end UniAtaCalculateLBARegsBack()
6827 Routine Description:
6829 This routine handles IDE read and writes.
6833 HwDeviceExtension - HBA miniport driver's adapter data storage
6834 Srb - IO request packet
6844 IN PVOID HwDeviceExtension
,
6845 IN PSCSI_REQUEST_BLOCK Srb
,
6849 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6850 UCHAR lChannel
= GET_CHANNEL(Srb
);
6851 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6852 PHW_LU_EXTENSION LunExt
;
6853 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6854 //ULONG ldev = GET_LDEV(Srb);
6855 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6856 ULONGLONG startingSector
=0;
6857 ULONG max_bcount
= 0;
6858 ULONG wordCount
= 0;
6859 UCHAR statusByte
,statusByte2
;
6862 BOOLEAN use_dma
= FALSE
;
6865 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6866 LunExt
= chan
->lun
[DeviceNumber
];
6868 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6869 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6871 if(LunExt
->opt_ReadOnly
&&
6872 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6873 if(LunExt
->opt_ReadOnly
== 1) {
6874 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6875 return SRB_STATUS_ERROR
;
6877 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6878 return SRB_STATUS_SUCCESS
;
6882 // Set data buffer pointer and words left.
6883 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6885 if(AtaReq
->WordsTransfered
) {
6886 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6887 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6888 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6889 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6891 AtaReq
->TransferLength
/2,
6892 AtaReq
->WordsTransfered
,
6895 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6896 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6897 // Set up 1st block.
6898 switch(Srb
->Cdb
[0]) {
6901 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6902 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6905 case SCSIOP_WRITE12
:
6906 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6907 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6910 case SCSIOP_WRITE16
:
6911 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6912 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6915 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6917 AtaReq
->TransferLength
/2,
6920 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6923 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6925 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6926 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6928 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6934 if(LunExt
->errRetry
&&
6935 lba
== LunExt
->errLastLba
&&
6936 /* AtaReq->bcount && */ // errRetry can be set only for non-zero bcount
6937 AtaReq
->bcount
== LunExt
->errBCount
) {
6938 KdPrint3((PRINT_PREFIX
"IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n",
6939 LunExt
->errRetry
, LunExt
->errLastLba
, LunExt
->errBCount
));
6940 if(AtaReq
->retry
< MAX_RETRIES
) {
6941 AtaReq
->retry
= LunExt
->errRetry
;
6942 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
6944 LunExt
->errRetry
= 0;
6947 // assume best case here
6948 // we cannot reinit Dma until previous request is completed
6949 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6950 UniataAhciSetupCmdPtr(AtaReq
);
6951 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6952 (PUCHAR
)(AtaReq
->DataBuffer
),
6953 AtaReq
->bcount
* DEV_BSIZE
)) {
6954 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6955 return SRB_STATUS_ERROR
;
6958 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6960 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6961 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6962 (PUCHAR
)(AtaReq
->DataBuffer
),
6963 AtaReq
->bcount
* DEV_BSIZE
)) {
6968 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6969 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6970 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6972 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6973 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6974 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6976 (USHORT
)(AtaReq
->bcount
),
6978 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6982 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6983 return SRB_STATUS_ERROR
;
6986 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6987 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6990 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6992 } else { // exec_only
6993 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6996 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7000 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7002 return SRB_STATUS_PENDING
;
7005 // if this is queued request, reinit DMA and check
7006 // if DMA mode is still available
7007 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7008 if (/*EnableDma &&*/
7009 (LunExt
->TransferMode
>= ATA_DMA
)) {
7012 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7016 // Check if write request.
7017 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7019 // Prepare read command.
7021 cmd
= IDE_COMMAND_READ_DMA
;
7023 if(LunExt
->MaximumBlockXfer
) {
7024 cmd
= IDE_COMMAND_READ_MULTIPLE
;
7026 cmd
= IDE_COMMAND_READ
;
7030 // Prepare write command.
7032 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
7033 cmd
= IDE_COMMAND_WRITE_DMA
;
7035 if (LunExt
->MaximumBlockXfer
) {
7036 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
7038 if (AtaReq
->WordsLeft
< wordCount
) {
7039 // Transfer only words requested.
7040 wordCount
= AtaReq
->WordsLeft
;
7042 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
7045 wordCount
= DEV_BSIZE
/2;
7046 cmd
= IDE_COMMAND_WRITE
;
7051 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
7052 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
7054 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7056 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7059 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7060 // AHCI doesn't distinguish DMA and PIO
7061 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7062 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7063 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
7064 InterlockedExchange(&(chan
->CheckIntr
),
7066 return SRB_STATUS_PENDING
;
7069 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
7072 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
7073 if(g_opt_BochsDmaReadWorkaround
&&
7074 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7075 KdPrint2((PRINT_PREFIX
"CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
7076 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7079 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
7081 (USHORT
)(AtaReq
->bcount
),
7082 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
7084 /* if(statusByte2 != IDE_STATUS_WRONG) {
7085 GetStatus(chan, statusByte2);
7087 if(statusByte2
& IDE_STATUS_ERROR
) {
7088 // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks).
7089 // Because some devices doesn't reset ERR from previous command immediately after getting new one.
7090 // On the other hand we cannot wait here because of possible timeout condition
7091 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7092 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
7093 return SRB_STATUS_ERROR
;
7096 if(!g_opt_BochsDmaReadWorkaround
||
7097 !(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7098 //GetStatus(chan, statusByte2);
7099 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7102 return SRB_STATUS_PENDING
;
7105 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
7107 (USHORT
)(AtaReq
->bcount
),
7108 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
7111 if (!(statusByte
& IDE_STATUS_DRQ
) ||
7112 statusByte
== IDE_STATUS_WRONG
) {
7114 if(statusByte
== IDE_STATUS_WRONG
) {
7115 KdPrint2((PRINT_PREFIX
7116 "IdeReadWrite: error sending command (%#x)\n",
7119 KdPrint2((PRINT_PREFIX
7120 "IdeReadWrite: DRQ never asserted (%#x)\n",
7124 AtaReq
->WordsLeft
= 0;
7126 // Clear interrupt expecting flag.
7127 UniataExpectChannelInterrupt(chan
, FALSE
);
7128 InterlockedExchange(&(chan
->CheckIntr
),
7131 // Clear current SRB.
7132 UniataRemoveRequest(chan
, Srb
);
7134 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
7137 UniataExpectChannelInterrupt(chan
, TRUE
);
7138 InterlockedExchange(&(chan
->CheckIntr
),
7141 // Write next DEV_BSIZE/2*N words.
7142 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) || (wordCount
& 1)) {
7143 KdPrint2((PRINT_PREFIX
7144 "IdeReadWrite: Write %#x words\n", wordCount
));
7149 UniataGetPioTiming(LunExt
));
7153 KdPrint2((PRINT_PREFIX
7154 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
7157 (PULONG
)(AtaReq
->DataBuffer
),
7159 UniataGetPioTiming(LunExt
));
7162 // Adjust buffer address and words left count.
7163 AtaReq
->WordsLeft
-= wordCount
;
7164 AtaReq
->DataBuffer
+= wordCount
;
7165 AtaReq
->WordsTransfered
+= wordCount
;
7167 // Wait for interrupt.
7168 return SRB_STATUS_PENDING
;
7170 } // end IdeReadWrite()
7176 Routine Description:
7177 This routine handles IDE Verify.
7180 HwDeviceExtension - HBA miniport driver's adapter data storage
7181 Srb - IO request packet
7190 IN PVOID HwDeviceExtension
,
7191 IN PSCSI_REQUEST_BLOCK Srb
7194 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7195 UCHAR lChannel
= GET_CHANNEL(Srb
);
7196 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
7197 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7198 PHW_LU_EXTENSION LunExt
;
7199 //ULONG ldev = GET_LDEV(Srb);
7200 ULONG DeviceNumber
= GET_CDEV(Srb
);
7202 ULONGLONG startingSector
=0;
7205 ULONGLONG endSector
;
7206 ULONG sectorCount
=0;
7209 LunExt
= chan
->lun
[DeviceNumber
];
7210 // Drive has these number sectors.
7211 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
7212 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
7213 LunExt
->IdentifyData
.NumberOfHeads
*
7214 LunExt
->IdentifyData
.NumberOfCylinders
;
7217 KdPrint2((PRINT_PREFIX
7218 "IdeVerify: Total sectors %#x\n",
7221 // Get starting sector number from CDB.
7222 switch(Srb
->Cdb
[0]) {
7224 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7225 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7227 case SCSIOP_VERIFY12
:
7228 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
7229 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7231 case SCSIOP_VERIFY16
:
7232 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7233 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7237 KdPrint2((PRINT_PREFIX
7238 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
7242 endSector
= startingSector
+ sectorCount
;
7244 KdPrint2((PRINT_PREFIX
7245 "IdeVerify: Ending sector %#I64x\n",
7248 if (endSector
> sectors
) {
7250 // Too big, round down.
7251 KdPrint2((PRINT_PREFIX
7252 "IdeVerify: Truncating request to %#x blocks\n",
7253 sectors
- startingSector
- 1));
7255 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
7259 // Set up sector count register. Round up to next block.
7260 if (sectorCount
> 0xFF) {
7261 sectorCount
= (USHORT
)0xFF;
7265 // Set data buffer pointer and words left.
7266 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7267 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7269 // Indicate expecting an interrupt.
7270 InterlockedExchange(&(chan
->CheckIntr
),
7273 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
7275 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
7276 IDE_COMMAND_VERIFY
, lba
,
7277 (USHORT
)sectorCount
,
7280 if(!(statusByte
& IDE_STATUS_ERROR
)) {
7281 // Wait for interrupt.
7282 return SRB_STATUS_PENDING
;
7284 return SRB_STATUS_ERROR
;
7286 } // end IdeVerify()
7288 #endif //UNIATA_CORE
7292 Routine Description:
7293 Send ATAPI packet command to device.
7296 HwDeviceExtension - HBA miniport driver's adapter data storage
7297 Srb - IO request packet
7305 IN PVOID HwDeviceExtension
,
7306 IN PSCSI_REQUEST_BLOCK Srb
,
7310 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7311 UCHAR lChannel
= GET_CHANNEL(Srb
);
7312 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
7313 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7314 PHW_LU_EXTENSION LunExt
;
7315 //ULONG ldev = GET_LDEV(Srb);
7316 ULONG DeviceNumber
= GET_CDEV(Srb
);
7318 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
7319 UCHAR interruptReason
;
7320 BOOLEAN use_dma
= FALSE
;
7321 BOOLEAN dma_reinited
= FALSE
;
7322 BOOLEAN retried
= FALSE
;
7326 LunExt
= chan
->lun
[DeviceNumber
];
7328 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
7329 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7330 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7333 #ifdef UNIATA_DUMP_ATAPI
7334 if(CmdAction
& CMD_ACTION_PREPARE
) {
7338 PCHAR ModeSelectData
;
7341 Cdb
= (PCDB
)(Srb
->Cdb
);
7342 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
7343 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
7344 CdbDataLen
= Srb
->DataTransferLength
;
7346 if(CdbDataLen
> 0x1000) {
7347 CdbDataLen
= 0x1000;
7351 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7352 KdPrint2(("P:T:D=%d:%d:%d\n",
7356 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
7359 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
7360 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
7361 Cdb
->WRITE_CD
.LBA
[0],
7362 Cdb
->WRITE_CD
.LBA
[1],
7363 Cdb
->WRITE_CD
.LBA
[2],
7364 Cdb
->WRITE_CD
.LBA
[3]
7367 if(ScsiCommand
== SCSIOP_WRITE12
) {
7368 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
7369 Cdb
->CDB12READWRITE
.LBA
[0],
7370 Cdb
->CDB12READWRITE
.LBA
[1],
7371 Cdb
->CDB12READWRITE
.LBA
[2],
7372 Cdb
->CDB12READWRITE
.LBA
[3]
7375 if(ScsiCommand
== SCSIOP_WRITE16
) {
7376 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
7377 Cdb
->CDB16READWRITE
.LBA
[0],
7378 Cdb
->CDB16READWRITE
.LBA
[1],
7379 Cdb
->CDB16READWRITE
.LBA
[2],
7380 Cdb
->CDB16READWRITE
.LBA
[3],
7381 Cdb
->CDB16READWRITE
.LBA
[4],
7382 Cdb
->CDB16READWRITE
.LBA
[5],
7383 Cdb
->CDB16READWRITE
.LBA
[6],
7384 Cdb
->CDB16READWRITE
.LBA
[7]
7387 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
7388 KdPrint(("ModeSelect 6\n"));
7389 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7390 ModeSelectData
= CdbData
+4;
7391 KdDump(CdbData
, CdbDataLen
);
7393 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
7394 KdPrint(("ModeSelect 10\n"));
7395 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7396 ModeSelectData
= CdbData
+8;
7397 KdDump(CdbData
, CdbDataLen
);
7399 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7400 KdPrint(("Send buffer to device:\n"));
7401 KdDump(CdbData
, CdbDataLen
);
7406 #endif //UNIATA_DUMP_ATAPI
7409 if(CmdAction
== CMD_ACTION_PREPARE
) {
7410 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
7412 switch (Srb
->Cdb
[0]) {
7413 case SCSIOP_RECEIVE
:
7418 case SCSIOP_WRITE12
:
7420 case SCSIOP_WRITE16
:
7423 case SCSIOP_READ_CD
:
7424 case SCSIOP_READ_CD_MSF
:
7425 if(deviceExtension
->opt_AtapiDmaRawRead
) {
7431 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
7432 return SRB_STATUS_BUSY
;
7435 #ifdef UNIATA_INIT_CHANGERS
7436 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7437 !AtaReq
->OriginalSrb
) {
7438 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
7439 return SRB_STATUS_BUSY
;
7441 #endif // UNIATA_INIT_CHANGERS
7445 // standard atapi.sys claims:
7447 // We need to know how many platters our atapi cd-rom device might have.
7448 // Before anyone tries to send a srb to our target for the first time,
7449 // we must "secretly" send down a separate mechanism status srb in order to
7450 // initialize our device extension changer data. That's how we know how
7451 // many platters our target has.
7454 // some devices freeze (sometimes) forever on this command
7455 // Let CD-ROM driver send this command itself, if it find it necessary
7456 // We shall just parse output (if any)
7458 #ifdef UNIATA_INIT_CHANGERS
7459 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7460 !AtaReq
->OriginalSrb
) {
7464 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
7465 // Set this flag now. If the device hangs on the mech. status
7466 // command, we will not have the chance to set it.
7467 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
7469 chan
->MechStatusRetryCount
= 3;
7470 AtaReq
->OriginalSrb
= Srb
;
7471 AtaReq
->Srb
= BuildMechanismStatusSrb (
7475 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
7476 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7477 if (srbStatus
== SRB_STATUS_PENDING
) {
7478 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
7482 // failed! Get the sense key and maybe try again
7483 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
7484 AtaReq
->OriginalSrb
);
7486 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7488 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
7490 if (srbStatus
== SRB_STATUS_PENDING
) {
7491 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7495 // failed again ? should not get here
7496 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
7497 AtaReq
->OriginalSrb
= NULL
;
7501 #endif // UNIATA_INIT_CHANGERS
7502 #endif //UNIATA_CORE
7504 if((CmdAction
& CMD_ACTION_PREPARE
) &&
7505 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
7507 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
7509 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
7510 (Srb
->CdbLength
> 12)) {
7511 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
7512 return SRB_STATUS_INVALID_REQUEST
;
7515 // Set data buffer pointer and words left.
7516 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7517 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7518 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
7519 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7520 // reset this to force PRD init. May be already setup by recursive SRB
7521 AtaReq
->dma_entries
= 0;
7523 // check if reorderable
7524 switch(Srb
->Cdb
[0]) {
7526 case SCSIOP_WRITE16
:
7528 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7529 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7533 case SCSIOP_WRITE12
:
7535 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7541 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7543 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7545 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
7546 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7547 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7548 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7549 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7550 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7553 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7554 if(!AtaReq
->TransferLength
) {
7555 KdPrint((" assume 0-transfer\n"));
7557 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7558 KdPrint((" assume OUT\n"));
7559 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7561 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7562 KdPrint((" assume IN\n"));
7563 AtaReq
->Flags
|= REQ_FLAG_READ
;
7568 // check if DMA read/write
7569 if(g_opt_AtapiNoDma
) {
7570 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n"));
7573 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7574 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7578 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7579 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7583 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7584 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7586 if(AtaReq
->TransferLength
&& !(AtaReq
->TransferLength
& 0x0f)) {
7587 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: try DMA setup\n"));
7588 // try use DMA if TransferLength is 16-byte aligned
7589 switch(Srb
->Cdb
[0]) {
7591 case SCSIOP_WRITE12
:
7592 case SCSIOP_WRITE16
:
7594 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7597 case SCSIOP_RECEIVE
:
7602 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7604 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7605 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7608 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7609 (PUCHAR
)(AtaReq
->DataBuffer
),
7610 Srb
->DataTransferLength
7611 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7613 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7618 case SCSIOP_READ_CD
:
7619 case SCSIOP_READ_CD_MSF
:
7620 if(deviceExtension
->opt_AtapiDmaRawRead
)
7621 goto call_dma_setup
;
7625 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7626 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7631 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7632 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7644 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7645 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7648 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7649 (PUCHAR
)(AtaReq
->DataBuffer
),
7650 Srb
->DataTransferLength
)) {
7651 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7654 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7658 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq
->TransferLength
));
7662 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7664 UniataAhciSetupCmdPtr(AtaReq
);
7666 if(!Srb
->DataTransferLength
) {
7667 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7670 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7671 (PUCHAR
)(AtaReq
->DataBuffer
),
7672 Srb
->DataTransferLength
)) {
7673 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7674 return SRB_STATUS_ERROR
;
7677 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7679 FeatureReg
|= ATA_F_DMA
;
7680 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
) {
7681 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7682 KdPrint2((PRINT_PREFIX
"Set DMADir.\n"));
7683 FeatureReg
|= ATA_F_DMAREAD
;
7688 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7689 // this is done in UniataAhciSetupFIS_H2D()
7690 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7691 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7693 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7694 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7695 IDE_COMMAND_ATAPI_PACKET
/* command */,
7697 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7698 FeatureReg
/* feature */
7702 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7703 return SRB_STATUS_ERROR
;
7706 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7707 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7708 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7709 fis_size
, DeviceNumber
);
7711 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7715 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7716 // if this is queued request, reinit DMA and check
7717 // if DMA mode is still available
7718 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7719 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7720 if (/*EnableDma &&*/
7721 (LunExt
->TransferMode
>= ATA_DMA
)) {
7722 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7725 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7726 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7729 dma_reinited
= TRUE
;
7733 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7734 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7735 return SRB_STATUS_PENDING
;
7737 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7738 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7739 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7742 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7743 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7745 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7746 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7747 } if(AtaReq
->TransferLength
) {
7749 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7750 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7751 if (/*EnableDma &&*/
7752 (LunExt
->TransferMode
>= ATA_DMA
)) {
7755 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7760 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7762 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7763 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7764 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7765 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7768 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7769 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7770 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7773 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7775 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7776 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7778 // Make sure command is to ATAPI device.
7779 flags
= LunExt
->DeviceFlags
;
7780 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7781 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7783 // Indicate no device found at this address.
7784 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7785 return SRB_STATUS_SELECTION_TIMEOUT
;
7787 } else if(Srb
->Lun
> 0) {
7788 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7789 return SRB_STATUS_SELECTION_TIMEOUT
;
7792 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7793 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7794 return SRB_STATUS_SELECTION_TIMEOUT
;
7797 // Select device 0 or 1. Or more for PM
7798 SelectDrive(chan
, DeviceNumber
);
7800 // Verify that controller is ready for next command.
7801 GetStatus(chan
, statusByte
);
7802 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7804 if(statusByte
== IDE_STATUS_WRONG
) {
7805 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7808 if(statusByte
& IDE_STATUS_BUSY
) {
7809 if(statusByte
& IDE_STATUS_DSC
) {
7810 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7812 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7813 // We have to make reset here, since we are expecting device to be available
7814 //return SRB_STATUS_BUSY; // this cause queue freeze
7818 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7820 // Check if command list is free
7821 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7823 // controller is busy, however we expect it to be free
7824 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7828 if(statusByte
& IDE_STATUS_ERROR
) {
7829 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7831 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7832 // Read the error reg. to clear it and fail this request.
7833 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7834 return MapError(deviceExtension
, Srb
);
7836 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7839 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7840 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7841 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7842 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7844 AtapiStallExecution(200);
7845 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7846 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7847 return SRB_STATUS_PENDING
;
7850 if(IS_RDP(Srb
->Cdb
[0])) {
7852 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7856 if(statusByte
& IDE_STATUS_DRQ
) {
7858 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7860 // Try to drain the data that one preliminary device thinks that it has
7861 // to transfer. Hopefully this random assertion of DRQ will not be present
7862 // in production devices.
7863 statusByte
= AtapiSuckPort2(chan
);
7865 for (i = 0; i < 0x10000; i++) {
7866 GetStatus(chan, statusByte);
7867 if(statusByte & IDE_STATUS_DRQ) {
7868 AtapiReadPort2(chan, IDX_IO1_i_Data);
7874 if (statusByte
& IDE_STATUS_DRQ
) {
7875 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte
));
7877 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7879 AtapiSoftReset(chan
, DeviceNumber
);
7881 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7882 // Re-initialize Atapi device.
7883 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7885 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7886 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7888 // Inform the port driver that the bus has been reset.
7889 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7890 // Clean up device extension fields that AtapiStartIo won't.
7891 UniataExpectChannelInterrupt(chan
, FALSE
);
7893 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7896 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7898 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7899 return SRB_STATUS_BUS_RESET;
7902 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7906 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7907 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7908 return SRB_STATUS_SELECTION_TIMEOUT
;
7912 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7913 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7914 Srb
->Cdb
[1] &= ~0xE0;
7915 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7916 // Torisan changer. TUR's are overloaded to be platter switches.
7917 Srb
->Cdb
[7] = Srb
->Lun
;
7924 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7926 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7929 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7930 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7931 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7932 UniataExpectChannelInterrupt(chan
, TRUE
);
7933 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7934 return SRB_STATUS_PENDING
;
7937 statusByte
= WaitOnBusy(chan
);
7938 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7942 FeatureReg
|= ATA_F_DMA
;
7943 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
) {
7944 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7945 FeatureReg
|= ATA_F_DMAREAD
;
7950 // Write transfer byte count to registers.
7951 if (Srb
->DataTransferLength
>= 0x10000) {
7952 byteCountLow
= byteCountHigh
= 0xFF;
7954 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7955 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7958 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg
, byteCountHigh
, byteCountLow
));
7960 if (flags
& DFLAGS_INT_DRQ
) {
7961 // This device interrupts when ready to receive the packet.
7962 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7965 UniataExpectChannelInterrupt(chan
, TRUE
);
7966 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7967 InterlockedExchange(&(chan
->CheckIntr
),
7969 // inform driver that packet command must be sent in ISR
7970 flags
|= DFLAGS_INT_DRQ
;
7972 // This device quickly sets DRQ when ready to receive the packet.
7973 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7976 UniataExpectChannelInterrupt(chan
, TRUE
);
7977 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7978 InterlockedExchange(&(chan
->CheckIntr
),
7981 if(g_opt_AtapiSendDisableIntr
) {
7982 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7984 // remember status. Later we may check if error appeared after cmd packet
7985 statusByte0
= statusByte
;
7988 // must be already selected, experimental for ROS BUG-9119
7989 //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
7990 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_Feature
/*IDX_IO1_o_Feature*/, FeatureReg
);
7991 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0); // experimental for ROS BUG-9119
7992 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0); // experimental for ROS BUG-9119
7993 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7994 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7995 // Write ATAPI packet command.
7996 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_Command
/*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET
);
7998 if (flags
& DFLAGS_INT_DRQ
) {
7999 // Wait for interrupt and send PACKET there
8000 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
8001 return SRB_STATUS_PENDING
;
8007 statusByte = WaitForDrq(chan);
8009 // Need to read status register and clear interrupt (if any)
8010 GetBaseStatus(chan, statusByte);
8012 if (!(statusByte & IDE_STATUS_DRQ)) {
8013 if(g_opt_AtapiSendDisableIntr) {
8014 AtapiEnableInterrupts(deviceExtension, lChannel);
8016 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
8017 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8018 return SRB_STATUS_ERROR;
8021 GetStatus(chan
, statusByte
);
8022 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
8024 //statusByte = WaitOnBaseBusy(chan);
8026 // Indicate expecting an interrupt and wait for it.
8027 UniataExpectChannelInterrupt(chan
, TRUE
);
8029 for(i
=0; i
<5000; i
++) {
8030 if(g_opt_AtapiSendDisableIntr
) {
8031 GetStatus(chan
, statusByte
);
8033 GetBaseStatus(chan
, statusByte
);
8035 interruptReason
= AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
8036 //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
8037 if(((interruptReason
& ATAPI_IR_COD
) == ATAPI_IR_COD_Cmd
) &&
8038 (((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRQ
)) == IDE_STATUS_DRQ
))) {
8041 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
8043 // KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason));
8046 if(((interruptReason
& ATAPI_IR_COD
) != ATAPI_IR_COD_Cmd
) ||
8047 (((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRQ
)) != IDE_STATUS_DRQ
)) ) {
8048 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: no CoD raised, abort cmd\n"));
8049 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x (%d)\n", interruptReason
, i
));
8050 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
8051 if(g_opt_AtapiSendDisableIntr
) {
8052 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8054 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ+CoD never asserted\n"));
8055 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8056 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Err on cmd: (%#x)\n", statusByte
));
8057 if(statusByte
>> 4) {
8058 GetBaseStatus(chan
, statusByte
);
8059 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8060 return MapError(deviceExtension
, Srb
);
8063 // AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8064 // return SRB_STATUS_ERROR;
8066 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason
, i
));
8069 GetBaseStatus(chan
, statusByte
);
8071 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
8072 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
8074 if(g_opt_AtapiSendDisableIntr
) {
8075 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8078 // Send CDB to device.
8081 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
8084 GetStatus(chan
, statusByte
);
8085 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
8087 // When we operate in DMA mode, we should not start transfer when there is an error on entry
8088 // Interrupt may never come in such case.
8089 if(statusByte
& IDE_STATUS_ERROR
) {
8091 GetBaseStatus(chan
, statusByte
);
8092 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
8094 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
8095 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
8097 // TODO: we should check interruptReason and decide what to do now
8099 // Read the error reg. to clear it and fail this request.
8100 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8101 return MapError(deviceExtension
, Srb
);
8103 if(statusByte
& IDE_STATUS_DRQ
) {
8104 // Some devices require this. If error condition is not checked in such a way,
8105 // device may not operate correctly and would be treated as failed
8106 // (and finally invisible for OS)
8107 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ on cmd: (%#x)\n", statusByte
));
8108 // Read the error reg. to clear it and fail this request.
8109 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8110 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Err on cmd: (%#x)\n", statusByte
));
8111 if(statusByte
>> 4) {
8112 GetBaseStatus(chan
, statusByte
);
8113 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8114 return MapError(deviceExtension
, Srb
);
8118 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
8119 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8122 InterlockedExchange(&(chan
->CheckIntr
),
8124 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
8126 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
8128 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
8129 return SRB_STATUS_PENDING
;
8131 } // end AtapiSendCommand()
8138 Routine Description:
8139 Program ATA registers for IDE disk transfer.
8142 HwDeviceExtension - ATAPI driver storage.
8143 Srb - System request block.
8146 SRB status (pending if all goes well).
8151 ULONG check_point
= 0;
8152 #define SetCheckPoint(cp) { check_point = (cp) ; }
8154 #define SetCheckPoint(cp)
8160 IN PVOID HwDeviceExtension
,
8161 IN PSCSI_REQUEST_BLOCK Srb
,
8166 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
8169 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8174 PHW_LU_EXTENSION LunExt
;
8178 UCHAR statusByte
,errorByte
;
8179 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
8182 PMODE_PARAMETER_HEADER modeData
;
8189 //ULONG __ebp__ = 0;
8191 SetCheckPoint(0x20);
8192 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
8197 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
8198 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
8199 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
8200 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
8201 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
8203 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
8204 Srb->SrbExtension));
8205 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
8208 SetCheckPoint(0x30);
8209 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8211 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
8213 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
8215 KdPrint2((PRINT_PREFIX
"** --- **\n"));
8217 lChannel
= GET_CHANNEL(Srb
);
8218 chan
= &(deviceExtension
->chan
[lChannel
]);
8219 //ldev = GET_LDEV(Srb);
8220 DeviceNumber
= GET_CDEV(Srb
);
8221 LunExt
= chan
->lun
[DeviceNumber
];
8223 SetCheckPoint(0x40);
8224 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
8225 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
8227 cdb
= (PCDB
)(Srb
->Cdb
);
8229 if(CmdAction
== CMD_ACTION_PREPARE
) {
8230 switch (Srb
->Cdb
[0]) {
8231 case SCSIOP_SERVICE_ACTION16
:
8232 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8235 goto default_no_prep
;
8238 case SCSIOP_INQUIRY
: // now it requires device access
8240 case SCSIOP_READ_CAPACITY
:
8244 case SCSIOP_WRITE12
:
8246 case SCSIOP_WRITE16
:
8247 case SCSIOP_REQUEST_SENSE
:
8249 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
8255 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
8256 return SRB_STATUS_BUSY
;
8260 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
8261 switch (Srb
->Cdb
[0]) {
8262 case SCSIOP_INQUIRY
:
8264 KdPrint2((PRINT_PREFIX
8265 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
8266 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8267 // Filter out wrong TIDs.
8268 if ((Srb
->Lun
!= 0) ||
8269 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
8270 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
8272 KdPrint2((PRINT_PREFIX
8273 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
8274 // Indicate no device found at this address.
8275 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8280 KdPrint2((PRINT_PREFIX
8281 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
8282 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8283 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
8285 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8287 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
8288 KdPrint2((PRINT_PREFIX
8289 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
8290 // Indicate no device found at this address.
8292 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8296 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
8297 KdPrint2((PRINT_PREFIX
8298 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
8299 // Indicate no device found at this address.
8300 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
8302 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8307 // Zero INQUIRY data structure.
8308 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8310 // Standard IDE interface only supports disks.
8311 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
8313 // Set the removable bit, if applicable.
8314 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
8315 KdPrint2((PRINT_PREFIX
8316 "RemovableMedia\n"));
8317 inquiryData
->RemovableMedia
= 1;
8319 // Set the Relative Addressing (LBA) bit, if applicable.
8320 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
8321 inquiryData
->RelativeAddressing
= 1;
8322 KdPrint2((PRINT_PREFIX
8323 "RelativeAddressing\n"));
8325 // Set the CommandQueue bit
8326 inquiryData
->CommandQueue
= 1;
8328 // Fill in vendor identification fields.
8329 for (i
= 0; i
< 24; i
+= 2) {
8330 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
8333 // Initialize unused portion of product id.
8334 for (i = 0; i < 4; i++) {
8335 inquiryData->ProductId[12+i] = ' ';
8338 // Move firmware revision from IDENTIFY data to
8339 // product revision in INQUIRY data.
8340 for (i
= 0; i
< 4; i
+= 2) {
8341 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
8344 status
= SRB_STATUS_SUCCESS
;
8349 case SCSIOP_REPORT_LUNS
: {
8352 PREPORT_LUNS_INFO_HDR LunInfo
;
8354 KdPrint2((PRINT_PREFIX
8355 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
8356 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8358 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
8365 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
8366 RtlZeroMemory(LunInfo
, 16);
8368 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
8369 Srb
->DataTransferLength
= 16;
8370 status
= SRB_STATUS_SUCCESS
;
8374 case SCSIOP_MODE_SENSE
:
8376 KdPrint2((PRINT_PREFIX
8377 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8378 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8380 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
8381 PMODE_POWER_CONDITION_PAGE modeData
;
8383 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
8384 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
8385 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
8386 status
= SRB_STATUS_DATA_OVERRUN
;
8388 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
8389 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
8391 modeData
->PageLength
= sizeof(MODE_POWER_CONDITION_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8393 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
8395 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
8396 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
8397 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
8398 status
= SRB_STATUS_SUCCESS
;
8401 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
8402 PMODE_CACHING_PAGE modeData
;
8404 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
8405 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
8406 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
8407 status
= SRB_STATUS_DATA_OVERRUN
;
8409 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
8410 modeData
->PageCode
= MODE_PAGE_CACHING
;
8411 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8412 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
8413 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
8414 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
8415 status
= SRB_STATUS_SUCCESS
;
8418 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8420 // This is used to determine if the media is write-protected.
8421 // Since IDE does not support mode sense then we will modify just the portion we need
8422 // so the higher level driver can determine if media is protected.
8424 //SelectDrive(chan, DeviceNumber);
8425 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8426 //statusByte = WaitOnBusy(chan);
8427 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8429 if (!(statusByte
& IDE_STATUS_ERROR
)) {
8431 // no error occured return success, media is not protected
8432 UniataExpectChannelInterrupt(chan
, FALSE
);
8433 InterlockedExchange(&(chan
->CheckIntr
),
8435 status
= SRB_STATUS_SUCCESS
;
8439 // error occured, handle it locally, clear interrupt
8440 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8442 GetBaseStatus(chan
, statusByte
);
8443 UniataExpectChannelInterrupt(chan
, FALSE
);
8444 InterlockedExchange(&(chan
->CheckIntr
),
8446 status
= SRB_STATUS_SUCCESS
;
8448 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
8450 //media is write-protected, set bit in mode sense buffer
8451 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
8453 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
8454 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
8457 status
= SRB_STATUS_SUCCESS
;
8459 status
= SRB_STATUS_INVALID_REQUEST
;
8463 case SCSIOP_TEST_UNIT_READY
:
8465 KdPrint2((PRINT_PREFIX
8466 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
8467 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8468 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8470 // Select device 0 or 1.
8471 //SelectDrive(chan, DeviceNumber);
8472 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8473 // Wait for busy. If media has not changed, return success
8474 //statusByte = WaitOnBusy(chan);
8475 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8477 if (!(statusByte
& IDE_STATUS_ERROR
)){
8478 UniataExpectChannelInterrupt(chan
, FALSE
);
8479 InterlockedExchange(&(chan
->CheckIntr
),
8481 status
= SRB_STATUS_SUCCESS
;
8483 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8484 if (errorByte
== IDE_ERROR_DATA_ERROR
){
8486 // Special case: If current media is write-protected,
8487 // the 0xDA command will always fail since the write-protect bit
8488 // is sticky,so we can ignore this error
8489 GetBaseStatus(chan
, statusByte
);
8490 UniataExpectChannelInterrupt(chan
, FALSE
);
8491 InterlockedExchange(&(chan
->CheckIntr
),
8493 status
= SRB_STATUS_SUCCESS
;
8497 // Request sense buffer to be build
8498 UniataExpectChannelInterrupt(chan
, TRUE
);
8499 InterlockedExchange(&(chan
->CheckIntr
),
8501 status
= SRB_STATUS_PENDING
;
8505 status
= SRB_STATUS_SUCCESS
;
8510 case SCSIOP_READ_CAPACITY
:
8512 KdPrint2((PRINT_PREFIX
8513 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8514 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8515 // Claim 512 byte blocks (big-endian).
8516 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8518 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
8519 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8521 // Calculate last sector.
8522 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
8523 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
8524 LunExt
->IdentifyData
.NumberOfHeads
*
8525 LunExt
->IdentifyData
.NumberOfCylinders
;
8529 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
8530 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
8531 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
8533 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
8535 KdPrint2((PRINT_PREFIX
8536 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
8538 LunExt
->IdentifyData
.SectorsPerTrack
,
8539 LunExt
->IdentifyData
.NumberOfHeads
,
8540 LunExt
->IdentifyData
.NumberOfCylinders
));
8543 status
= SRB_STATUS_SUCCESS
;
8546 case SCSIOP_SERVICE_ACTION16
:
8548 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8549 KdPrint2((PRINT_PREFIX
8550 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8551 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8552 // Claim 512 byte blocks (big-endian).
8553 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8555 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
8556 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8558 // Calculate last sector.
8559 if(!(lba
= LunExt
->NumOfSectors
)) {
8560 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
8561 LunExt
->IdentifyData
.NumberOfHeads
*
8562 LunExt
->IdentifyData
.NumberOfCylinders
;
8565 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
8567 KdPrint2((PRINT_PREFIX
8568 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8570 LunExt
->IdentifyData
.SectorsPerTrack
,
8571 LunExt
->IdentifyData
.NumberOfHeads
,
8572 LunExt
->IdentifyData
.NumberOfCylinders
));
8574 status
= SRB_STATUS_SUCCESS
;
8581 case SCSIOP_VERIFY12
:
8582 case SCSIOP_VERIFY16
:
8584 KdPrint2((PRINT_PREFIX
8585 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8586 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8587 status
= IdeVerify(HwDeviceExtension
,Srb
);
8594 case SCSIOP_WRITE12
:
8596 case SCSIOP_WRITE16
:
8598 KdPrint2((PRINT_PREFIX
8599 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8600 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
8601 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8602 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
8603 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
8604 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
8605 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
8606 status
= IdeReadWrite(HwDeviceExtension
,
8610 case SCSIOP_START_STOP_UNIT
:
8612 KdPrint2((PRINT_PREFIX
8613 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8614 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8615 //Determine what type of operation we should perform
8619 if(cdb
->START_STOP
.FL
||
8620 cdb
->START_STOP
.FormatLayerNumber
||
8621 cdb
->START_STOP
.Reserved2
||
8622 cdb
->START_STOP
.Reserved2_2
||
8623 cdb
->START_STOP
.Reserved3
||
8628 if (cdb
->START_STOP
.PowerConditions
) {
8629 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8630 switch(cdb
->START_STOP
.PowerConditions
) {
8631 case StartStop_Power_Idle
:
8632 command
= IDE_COMMAND_IDLE_IMMED
;
8634 case StartStop_Power_Standby
:
8635 command
= IDE_COMMAND_STANDBY_IMMED
;
8637 case StartStop_Power_Sleep
:
8638 // TODO: we should save power state in order to know
8639 // that RESET sould be issued to revert device into
8642 command
= IDE_COMMAND_SLEEP
;
8647 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8649 if (cdb
->START_STOP
.LoadEject
== 1) {
8650 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8652 // first select device 0 or 1.
8653 //SelectDrive(chan, DeviceNumber);
8654 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8655 command
= IDE_COMMAND_MEDIA_EJECT
;
8657 if (cdb
->START_STOP
.Start
== 0) {
8658 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8659 command
= IDE_COMMAND_STANDBY_IMMED
;
8661 // TODO: we may need to perform hard reset (after sleep) or
8662 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8663 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8665 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8666 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8667 status
= SRB_STATUS_SUCCESS
;
8670 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8671 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8672 command
= IDE_COMMAND_IDLE_IMMED
;
8674 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8675 status
= SRB_STATUS_SUCCESS
;
8680 statusByte
= WaitOnBaseBusy(chan
);
8681 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8682 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8683 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8684 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8688 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8689 if (Srb
->SenseInfoBuffer
) {
8691 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8693 senseBuffer
->ErrorCode
= 0x70;
8694 senseBuffer
->Valid
= 1;
8695 senseBuffer
->AdditionalSenseLength
= 0xb;
8696 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8697 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8698 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8700 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8701 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8703 status
= SRB_STATUS_ERROR
;
8707 case SCSIOP_MEDIUM_REMOVAL
:
8709 cdb
= (PCDB
)Srb
->Cdb
;
8711 if(LunExt
->IdentifyData
.Removable
) {
8712 statusByte
= WaitOnBaseBusy(chan
);
8714 //SelectDrive(chan, DeviceNumber);
8715 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8716 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8717 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8719 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8720 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8722 status
= SRB_STATUS_SUCCESS
;
8724 status
= SRB_STATUS_INVALID_REQUEST
;
8729 // Note: I don't implement this, because NTFS driver too often issues this command
8730 // It causes awful performance degrade. However, if somebody wants, I will implement
8731 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8732 case SCSIOP_FLUSH_BUFFER
:
8733 case SCSIOP_SYNCHRONIZE_CACHE
:
8735 SelectDrive(chan
, DeviceNumber
);
8736 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8737 status
= SRB_STATUS_SUCCESS
;
8738 // status = SRB_STATUS_PENDING;
8739 statusByte
= WaitOnBusy(chan
);
8743 case SCSIOP_REQUEST_SENSE
:
8744 // this function makes sense buffers to report the results
8745 // of the original GET_MEDIA_STATUS command
8747 KdPrint2((PRINT_PREFIX
8748 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8749 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8750 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8751 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8754 status
= SRB_STATUS_INVALID_REQUEST
;
8758 case SCSIOP_ATA_PASSTHROUGH
:
8761 BOOLEAN use_dma
= FALSE
;
8764 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8766 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8767 //lChannel = Srb->TargetId >> 1;
8769 DeviceNumber
= max(DeviceNumber
, 1);
8770 regs
->bDriveHeadReg
&= 0x0f;
8771 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8774 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8776 KdPrint2((PRINT_PREFIX
8777 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8778 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8780 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8781 to_lim
= Srb
->TimeOutValue
;
8783 if(Srb
->TimeOutValue
<= 2) {
8784 to_lim
= Srb
->TimeOutValue
*900;
8786 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8790 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8792 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8794 statusByte
= UniataAhciSendPIOCommandDirect(
8803 if(statusByte
== IDE_STATUS_WRONG
) {
8804 goto passthrough_err
;
8806 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8807 UniataAhciAbortOperation(chan
);
8808 goto passthrough_err
;
8810 goto passthrough_done
;
8814 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8815 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8817 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8818 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8819 (PUCHAR
)(Srb
->DataBuffer
),
8820 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8826 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8827 AtapiStallExecution(10);
8829 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
8832 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8833 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8834 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8835 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8836 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8837 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8839 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8840 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8841 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8842 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8843 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8844 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8845 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8846 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8847 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8848 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8850 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8853 GetBaseStatus(chan
, statusByte
);
8854 if(statusByte
& IDE_STATUS_ERROR
) {
8855 goto passthrough_err
;
8857 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8860 ScsiPortStallExecution(1); // wait for busy to be set
8862 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8863 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8864 GetBaseStatus(chan
, statusByte
);
8865 if(statusByte
& IDE_STATUS_ERROR
) {
8868 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8873 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8875 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8876 goto passthrough_err
;
8880 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8882 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8883 GetBaseStatus(chan
, statusByte
);
8885 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8886 AtapiSuckPort2(chan
);
8888 if (Srb
->SenseInfoBuffer
) {
8890 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8892 senseBuffer
->ErrorCode
= 0x70;
8893 senseBuffer
->Valid
= 1;
8894 senseBuffer
->AdditionalSenseLength
= 0xb;
8895 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8896 senseBuffer
->AdditionalSenseCode
= 0;
8897 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8899 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8900 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8902 status
= SRB_STATUS_ERROR
;
8906 if (statusByte
& IDE_STATUS_DRQ
) {
8907 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8909 (PUSHORT
) Srb
->DataBuffer
,
8910 Srb
->DataTransferLength
/ 2,
8912 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8914 (PUSHORT
) Srb
->DataBuffer
,
8915 Srb
->DataTransferLength
/ 2,
8920 status
= SRB_STATUS_SUCCESS
;
8923 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8925 } else { // read task register
8928 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8930 KdPrint2((PRINT_PREFIX
8931 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8932 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8934 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8935 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8938 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8941 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8942 status
= SRB_STATUS_DATA_OVERRUN
;
8945 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8946 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8947 UniataSnapAtaRegs(chan
, 0, regs
);
8949 status
= SRB_STATUS_SUCCESS
;
8956 KdPrint2((PRINT_PREFIX
8957 "IdeSendCommand: Unsupported command %#x\n",
8960 status
= SRB_STATUS_INVALID_REQUEST
;
8964 if(status
== SRB_STATUS_PENDING
) {
8965 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8966 if(CmdAction
& CMD_ACTION_EXEC
) {
8967 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8968 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8971 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8972 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8977 } // end IdeSendCommand()
8982 Routine Description:
8983 Enables disables media status notification
8986 HwDeviceExtension - ATAPI driver storage.
8993 IN PVOID HwDeviceExtension
,
8995 IN ULONG DeviceNumber
8998 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9000 UCHAR statusByte
,errorByte
;
9002 chan
= &(deviceExtension
->chan
[lChannel
]);
9003 SelectDrive(chan
, DeviceNumber
);
9005 if (EnableMSN
== TRUE
){
9007 // If supported enable Media Status Notification support
9008 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
9011 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9012 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9013 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
9015 if (statusByte
& IDE_STATUS_ERROR
) {
9016 // Read the error register.
9017 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
9019 KdPrint2((PRINT_PREFIX
9020 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
9024 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
9025 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
9026 chan
->ReturningMediaStatus
= 0;
9031 } else { // end if EnableMSN == TRUE
9033 // disable if previously enabled
9034 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
9036 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9037 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9038 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
9039 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
9046 } // end IdeMediaStatus()
9051 Routine Description:
9053 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
9054 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
9057 HwDeviceExtension - ATAPI driver storage.
9058 Srb - System request block.
9062 SRB status (ALWAYS SUCCESS).
9067 IdeBuildSenseBuffer(
9068 IN PVOID HwDeviceExtension
,
9069 IN PSCSI_REQUEST_BLOCK Srb
9072 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9074 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
9075 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
9079 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
9081 senseBuffer
->ErrorCode
= 0x70;
9082 senseBuffer
->Valid
= 1;
9083 senseBuffer
->AdditionalSenseLength
= 0xb;
9084 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
9085 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
9086 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9087 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
9089 senseBuffer
->ErrorCode
= 0x70;
9090 senseBuffer
->Valid
= 1;
9091 senseBuffer
->AdditionalSenseLength
= 0xb;
9092 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
9093 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
9094 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9095 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
9097 senseBuffer
->ErrorCode
= 0x70;
9098 senseBuffer
->Valid
= 1;
9099 senseBuffer
->AdditionalSenseLength
= 0xb;
9100 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
9101 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
9102 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9103 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
9105 senseBuffer
->ErrorCode
= 0x70;
9106 senseBuffer
->Valid
= 1;
9107 senseBuffer
->AdditionalSenseLength
= 0xb;
9108 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
9109 senseBuffer
->AdditionalSenseCode
= 0;
9110 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9112 return SRB_STATUS_SUCCESS
;
9114 return SRB_STATUS_ERROR
;
9116 }// End of IdeBuildSenseBuffer
9120 UniataUserDeviceReset(
9121 PHW_DEVICE_EXTENSION deviceExtension
,
9122 PHW_LU_EXTENSION LunExt
,
9127 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9128 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
9129 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
9130 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
9131 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
9133 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
9134 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
9135 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
9136 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
9139 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9140 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9142 } // end UniataUserDeviceReset()
9147 PHW_DEVICE_EXTENSION deviceExtension
,
9152 BOOLEAN PostReq
= FALSE
;
9154 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
9155 if(chan
->queue_depth
> 0) {
9158 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
9159 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
9160 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
9162 status
= SRB_STATUS_BUSY
;
9171 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
9175 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
9178 } // end UniataNeedQueueing()
9182 Routine Description:
9184 This routine is called from the SCSI port driver synchronized
9185 with the kernel to start an IO request.
9190 HwDeviceExtension - HBA miniport driver's adapter data storage
9191 Srb - IO request packet
9201 IN PVOID HwDeviceExtension
,
9202 IN PSCSI_REQUEST_BLOCK Srb
9205 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
9206 } // end AtapiStartIo()
9211 IN PVOID HwDeviceExtension
,
9212 IN PSCSI_REQUEST_BLOCK Srb
,
9216 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9219 PHW_LU_EXTENSION LunExt
;
9227 PSCSI_REQUEST_BLOCK tmpSrb
;
9228 BOOLEAN PostReq
= FALSE
;
9230 BOOLEAN commPort
= FALSE
;
9232 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
9233 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
9234 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
9235 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9237 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
9239 /* KeBugCheckEx(0xc000000e,
9240 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9242 TopLevel, 0x80000001);
9244 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
9245 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
9246 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
9247 UniAtaClearAtaReq(Srb
->SrbExtension
);
9250 do { // fetch all queued commands for the channel (if valid)
9252 lChannel
= GET_CHANNEL(Srb
);
9253 //ldev = GET_LDEV(Srb);
9256 DeviceNumber
= GET_CDEV(Srb
);
9259 //ASSERT(deviceExtension);
9262 KdPrint2((PRINT_PREFIX
9263 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9264 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
9265 KdPrint2((PRINT_PREFIX
" DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
9267 if(lChannel
== deviceExtension
->NumberChannels
&&
9268 !Srb
->Lun
&& !Srb
->TargetId
&&
9269 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
9270 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
9272 // This is our virtual device
9273 KdPrint2((PRINT_PREFIX
9274 "AtapiStartIo: Communication port\n"));
9275 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
9277 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
9278 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
9279 sizeof(PINQUIRYDATA
) ));
9281 status
= SRB_STATUS_DATA_OVERRUN
;
9285 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
9287 KdPrint2((PRINT_PREFIX
9289 // Zero INQUIRY data structure.
9290 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
9292 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
9294 // Fill in vendor identification fields.
9295 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
9297 status
= SRB_STATUS_SUCCESS
;
9301 /* Pass IOCTL request down */
9303 if(lChannel
>= deviceExtension
->NumberChannels
||
9304 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
9307 if(lChannel
>= deviceExtension
->NumberChannels
) {
9312 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9313 KdPrint3((PRINT_PREFIX
9314 "AtapiStartIo: SRB rejected\n"));
9315 // Indicate no device found at this address.
9316 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9317 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9321 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
9322 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
9327 chan
= &(deviceExtension
->chan
[lChannel
]);
9328 LunExt
= chan
->lun
[DeviceNumber
];
9332 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9338 if(!commPort
&& !LunExt
) {
9340 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
9343 deviceExtension
->NumberChannels
);
9344 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
9345 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
9346 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9347 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
9351 for(i=0; i<1000; i++) {
9352 AtapiStallExecution(3*1000);
9359 // Determine which function.
9360 switch (Srb
->Function
) {
9362 case SRB_FUNCTION_EXECUTE_SCSI
:
9364 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9365 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9366 // let passthrough go
9368 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9372 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9373 KdPrint2((PRINT_PREFIX
9374 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
9375 // Indicate no device found at this address.
9376 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9377 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9382 KdPrint2((PRINT_PREFIX
9383 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
9387 if(Srb->DataTransferLength) {
9389 a = ((PUCHAR)(Srb->DataBuffer))[0];
9392 } __except(EXCEPTION_EXECUTE_HANDLER) {
9393 KdPrint3((PRINT_PREFIX
9394 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
9395 // Indicate no device found at this address.
9396 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
9397 status = SRB_STATUS_ERROR;
9398 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
9403 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9407 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
9409 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
9410 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
9412 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9414 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
9415 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9417 /*KeBugCheckEx(0xc000000e,
9418 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9420 status, 0x80000001);*/
9421 if(status
== SRB_STATUS_BUSY
)
9422 status
= SRB_STATUS_PENDING
;
9423 // Insert requests AFTER they have been initialized on
9424 // CMD_ACTION_PREPARE stage
9425 // we should not check TopLevel here (it is always TRUE)
9426 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9427 UniataQueueRequest(chan
, Srb
);
9429 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9433 // Send command to device.
9434 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
9436 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
9437 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9438 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
9439 //ASSERT(!AtaReq->Flags);
9440 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9441 UniataQueueRequest(chan
, Srb
);
9442 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
9443 //ASSERT(!AtaReq->Flags);
9444 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9445 //ASSERT(!AtaReq->Flags);
9449 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9453 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9454 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
9455 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
9459 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9463 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9472 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
9473 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
9474 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
9475 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9477 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
9482 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
9489 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
9491 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9493 /* KeBugCheckEx(0xc000000e,
9494 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9496 status, 0x80000002);*/
9504 case SRB_FUNCTION_ABORT_COMMAND
:
9506 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
9508 // Verify that SRB to abort is still outstanding.
9509 if((tmpSrb
!= Srb
->NextSrb
) ||
9510 !chan
->queue_depth
) {
9512 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
9514 // Complete abort SRB.
9515 status
= SRB_STATUS_ABORT_FAILED
;
9519 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
9520 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
9521 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
9522 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
9523 // Log reset failure.
9524 KdPrint3((PRINT_PREFIX
9525 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
9526 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9528 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9529 status
= SRB_STATUS_ERROR
;
9532 status
= SRB_STATUS_SUCCESS
;
9535 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
9536 if (tmpSrb
->SenseInfoBuffer
&&
9537 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
9539 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
9541 senseBuffer
->ErrorCode
= 0;
9542 senseBuffer
->Valid
= 1;
9543 senseBuffer
->AdditionalSenseLength
= 0xb;
9544 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
9545 senseBuffer
->AdditionalSenseCode
= 0;
9546 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9548 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
9550 AtapiDmaDBSync(chan
, tmpSrb
);
9551 UniataRemoveRequest(chan
, tmpSrb
);
9552 // Indicate command complete.
9553 ScsiPortNotification(RequestComplete
,
9556 status
= SRB_STATUS_SUCCESS
;
9560 // Abort function indicates that a request timed out.
9561 // Call reset routine. Card will only be reset if
9562 // status indicates something is wrong.
9563 // Fall through to reset code.
9565 case SRB_FUNCTION_RESET_DEVICE
:
9566 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
9568 // Reset single device.
9569 // For now we support only Lun=0
9571 // Note: reset is immediate command, it cannot be queued since it is usually used to
9572 // revert not-responding device to operational state
9573 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
9574 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
9575 status
= SRB_STATUS_SUCCESS
;
9578 case SRB_FUNCTION_RESET_BUS
:
9580 // Reset Atapi and SCSI bus.
9582 // Note: reset is immediate command, it cannot be queued since it is usually used to
9583 // revert not- responding device to operational state
9584 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
9585 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
9586 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
9587 // Log reset failure.
9588 KdPrint3((PRINT_PREFIX
9589 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9590 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9592 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9593 status
= SRB_STATUS_ERROR
;
9596 status
= SRB_STATUS_SUCCESS
;
9601 case SRB_FUNCTION_SHUTDOWN
:
9603 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
9604 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9605 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
9608 // FLUSH ATAPI device - do nothing
9609 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
9611 // FLUSH IDE/ATA device
9612 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9613 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9614 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9615 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9616 // If supported & allowed, reset write cacheing
9617 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9619 // Disable write cache
9620 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9621 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9622 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9623 // Check for errors.
9624 if (status
& IDE_STATUS_ERROR
) {
9625 KdPrint2((PRINT_PREFIX
9626 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9629 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9631 // Re-enable write cache
9632 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9633 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9634 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9635 // Check for errors.
9636 if (status
& IDE_STATUS_ERROR
) {
9637 KdPrint2((PRINT_PREFIX
9638 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9640 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9642 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9646 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9648 status
= SRB_STATUS_SUCCESS
;
9652 case SRB_FUNCTION_FLUSH
:
9654 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9655 status
= SRB_STATUS_SUCCESS
;
9658 case SRB_FUNCTION_IO_CONTROL
: {
9662 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9664 len
= Srb
->DataTransferLength
;
9666 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9668 ULONG targetId
= (ULONG
)(-1);
9670 if(len
< sizeof(SRB_IO_CONTROL
)) {
9671 goto wrong_buffer_size
;
9674 // extract bogus bus address
9675 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9676 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9677 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9679 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9680 goto wrong_buffer_size
;
9683 targetId
= versionParameters
->bIDEDeviceMap
;
9684 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9686 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9687 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9688 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9689 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9690 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9691 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9692 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9693 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9694 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9695 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9696 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9697 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9699 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9701 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9702 goto wrong_buffer_size
;
9705 targetId
= cmdInParameters
->bDriveNumber
;
9706 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9710 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9711 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9712 status
= SRB_STATUS_INVALID_REQUEST
;
9716 // adjust (if necessary) bus address
9717 if(targetId
!= (ULONG
)(-1)) {
9719 // This is done because of how the IOCTL_SCSI_MINIPORT
9720 // determines 'targetid's'. Disk.sys places the real target id value
9721 // in the DeviceMap field. Once we do some parameter checking, the value passed
9722 // back to the application will be determined.
9724 if (deviceExtension
->NumberChannels
== 1) {
9725 // do this for legacy controllers and legacy callers
9726 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9727 DeviceNumber
= (targetId
& 0x01);
9731 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9732 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9733 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9734 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9735 lChannel
= (UCHAR
)targetId
/ 2;
9738 lChannel
= (UCHAR
)(targetId
/ 2);
9739 DeviceNumber
= targetId
& 0x01;
9742 // otherwise assume lChannel and DeviceNumber from Srb are ok
9744 if(lChannel
>= deviceExtension
->NumberChannels
||
9745 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9746 KdPrint2((PRINT_PREFIX
9747 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9749 // Indicate no device found at this address.
9752 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9753 chan
= &(deviceExtension
->chan
[lChannel
]);
9754 LunExt
= chan
->lun
[DeviceNumber
];
9758 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9760 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9765 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9766 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9768 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9769 UCHAR deviceNumberMap
;
9771 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9773 // Version and revision per SMART 1.03
9775 versionParameters
->bVersion
= 1;
9776 versionParameters
->bRevision
= 1;
9777 versionParameters
->bReserved
= 0;
9779 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9780 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9783 goto invalid_request
;
9786 // NOTE: This will only set the bit
9787 // corresponding to this drive's target id.
9788 // The bit mask is as follows:
9794 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9795 deviceNumberMap
= 1 << lChannel
;
9798 if (deviceExtension
->NumberChannels
== 1) {
9799 if (chan
->PrimaryAddress
) {
9800 deviceNumberMap
= 1 << DeviceNumber
;
9802 deviceNumberMap
= 4 << DeviceNumber
;
9805 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9808 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9810 status
= SRB_STATUS_SUCCESS
;
9814 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9816 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9817 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9819 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9820 // Extract the target.
9821 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9823 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9826 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9827 goto invalid_request
;
9833 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9834 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9835 goto invalid_request
;
9838 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9839 // Zero the output buffer
9840 RtlZeroMemory(cmdOutParameters
, len
);
9841 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9842 ((PUCHAR)cmdOutParameters)[i] = 0;
9845 // Build status block.
9846 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9847 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9848 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9850 // Extract the identify data from the device extension.
9851 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9852 cmdOutParameters
->cBufferSize
);
9854 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9855 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9856 // adjust checksum if it is possible
9860 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9861 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9863 cmdOutParameters
->bBuffer
[i
] = -csum
;
9864 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9866 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9868 status
= SRB_STATUS_SUCCESS
;
9872 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9873 cmdInParameters
.irDriveRegs
.bCommandReg
));
9874 status
= SRB_STATUS_INVALID_REQUEST
;
9880 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9881 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9882 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9883 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9884 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9885 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9886 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9887 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9890 // *all* IOCTLs here are SMART
9892 KdPrint2((PRINT_PREFIX
9893 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9896 goto invalid_request
;
9899 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9901 if(PostReq
|| TopLevel
) {
9902 UniataQueueRequest(chan
, Srb
);
9903 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9904 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9909 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9910 status
= SRB_STATUS_PENDING
;
9912 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9915 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9919 // we should not get here, checked above
9921 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9922 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9923 status = SRB_STATUS_INVALID_REQUEST;
9928 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9930 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9931 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9932 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9936 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9937 //chan = &(deviceExtension->chan[lChannel]);
9939 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9940 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9941 goto wrong_buffer_size
;
9944 if(AtaCtl
->addr
.Lun
||
9945 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9946 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9954 lChannel
= AtaCtl
->addr
.PathId
;
9955 chan
= &(deviceExtension
->chan
[lChannel
]);
9956 LunExt
= chan
->lun
[DeviceNumber
];
9959 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9961 /* check for valid LUN */
9962 switch (AtaCtl
->hdr
.ControlCode
) {
9963 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9964 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9965 // this would be BUS reset
9967 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9968 AtaCtl
->addr
.TargetId
!= 0xff ||
9969 AtaCtl
->addr
.Lun
!= 0
9971 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9972 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9973 lChannel
= AtaCtl
->addr
.PathId
;
9974 chan
= &(deviceExtension
->chan
[lChannel
]);
9975 LunExt
= chan
->lun
[DeviceNumber
];
9978 goto handle_bad_ldev
;
9981 lChannel
= AtaCtl
->addr
.PathId
;
9982 chan
= &(deviceExtension
->chan
[lChannel
]);
9985 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9986 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9987 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9988 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9989 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9992 KdPrint2((PRINT_PREFIX
9993 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9994 // Indicate no device found at this address.
9999 /* check if queueing is necessary */
10000 switch (AtaCtl
->hdr
.ControlCode
) {
10001 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
10002 if(!LunExt
->nBadBlocks
) {
10005 goto uata_ctl_queue
;
10006 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
10007 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
10008 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10009 pos
+sizeof(AtaCtl
->SetMode
) ));
10010 goto wrong_buffer_size
;
10012 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
10015 goto uata_ctl_queue
;
10016 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
10017 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
10019 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
10020 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
10022 if(PostReq
|| TopLevel
) {
10023 UniataQueueRequest(chan
, Srb
);
10024 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10025 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
10028 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
10029 status
= SRB_STATUS_PENDING
;
10031 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
10034 } // end switch (AtaCtl->hdr.ControlCode)
10036 /* process request */
10037 switch (AtaCtl
->hdr
.ControlCode
) {
10038 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
10040 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
10042 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
10043 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10044 pos
+sizeof(AtaCtl
->FindDelDev
) ));
10045 goto wrong_buffer_size
;
10047 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
10048 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
10049 if(AtaCtl
->addr
.TargetId
!= 0xff) {
10050 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
10055 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
10056 AtapiStallExecution(1000 * 1000);
10059 FindDevices(HwDeviceExtension
,
10060 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
10061 ? UNIATA_FIND_DEV_UNHIDE
: 0,
10062 AtaCtl
->addr
.PathId
);
10063 status
= SRB_STATUS_SUCCESS
;
10067 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
10069 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
10071 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
10072 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10073 pos
+sizeof(AtaCtl
->FindDelDev
) ));
10074 goto wrong_buffer_size
;
10076 LunExt
->DeviceFlags
= 0;
10077 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
10078 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
10079 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
10080 UniataForgetDevice(LunExt
);
10083 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
10084 AtapiStallExecution(1000 * 1000);
10087 status
= SRB_STATUS_SUCCESS
;
10090 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
10092 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
10094 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
10095 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10096 pos
+sizeof(AtaCtl
->SetMode
) ));
10097 goto wrong_buffer_size
;
10099 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
10100 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
10102 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
10103 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
10104 if(LunExt
->LimitedTransferMode
>
10105 LunExt
->OrigTransferMode
) {
10106 // check for incorrect value
10107 LunExt
->LimitedTransferMode
=
10108 LunExt
->OrigTransferMode
;
10111 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
10113 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
10114 if(AtaCtl
->SetMode
.ApplyImmediately
) {
10115 AtapiDmaInit__(deviceExtension
, LunExt
);
10117 /* LunExt->TransferMode =
10118 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
10119 status
= SRB_STATUS_SUCCESS
;
10122 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
10124 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
10126 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
10127 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10128 pos
+sizeof(AtaCtl
->GetMode
) ));
10129 goto wrong_buffer_size
;
10131 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
10132 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
10133 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
10134 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
10136 status
= SRB_STATUS_SUCCESS
;
10139 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
10141 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
10143 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
10144 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10145 pos
+sizeof(AtaCtl
->Version
) ));
10146 goto wrong_buffer_size
;
10148 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
10149 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
10150 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
10151 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
10152 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
10154 status
= SRB_STATUS_SUCCESS
;
10157 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
10159 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
10161 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
10162 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10163 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
10164 goto wrong_buffer_size
;
10166 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
10168 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
10169 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
10170 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
10171 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
10172 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
10173 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
10174 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
10175 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
10176 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
10177 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
10178 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
10179 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
10180 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
10181 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
10182 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
10183 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
10184 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
10185 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
10186 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
10187 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
10188 if(deviceExtension
->FullDevName
) {
10189 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
10191 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
10192 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
10193 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
10195 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
10198 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
10201 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
10202 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
10203 PHW_CHANNEL cur_chan
;
10204 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
10205 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
10206 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
10207 cur_chan
= &(deviceExtension
->chan
[i
]);
10208 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
10209 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
10210 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
10211 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
10212 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
10213 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
10214 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
10215 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
10216 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
10219 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
10220 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
10223 status
= SRB_STATUS_SUCCESS
;
10226 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
10228 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
10230 ForgetBadBlocks(LunExt
);
10232 status
= SRB_STATUS_SUCCESS
;
10235 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
10237 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
10242 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
10245 status
= SRB_STATUS_SUCCESS
;
10249 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
10250 AtaCtl
->hdr
.ControlCode
));
10251 status
= SRB_STATUS_INVALID_REQUEST
;
10256 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
10257 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
10258 "SCSIDISK", "-UNIATA-"));
10260 status
= SRB_STATUS_INVALID_REQUEST
;
10265 } // end SRB_FUNCTION_IO_CONTROL
10268 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
10269 // Indicate unsupported command.
10270 status
= SRB_STATUS_INVALID_REQUEST
;
10278 PathId
= Srb
->PathId
;
10279 TargetId
= Srb
->TargetId
;
10282 if (status
!= SRB_STATUS_PENDING
) {
10284 KdPrint2((PRINT_PREFIX
10285 "AtapiStartIo: Srb %#x complete with status %#x\n",
10289 // Set status in SRB.
10290 Srb
->SrbStatus
= (UCHAR
)status
;
10293 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
10294 AtapiDmaDBSync(chan
, Srb
);
10296 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
10297 UniataRemoveRequest(chan
, Srb
);
10298 // Indicate command complete.
10299 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
10300 ScsiPortNotification(RequestComplete
,
10304 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
10305 // Remove current Srb & get next one
10306 if((Srb
= UniataGetCurRequest(chan
))) {
10307 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10308 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
10309 // current request is under precessing, thus
10310 // we should do nothing here
10314 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
10316 //ASSERT(TopLevel);
10319 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
10321 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
10323 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
10324 // Indicate ready for next request.
10325 ScsiPortNotification(NextRequest
,
10329 ScsiPortNotification(NextLuRequest
,
10337 } // end AtapiStartIo__()
10342 UniataInitAtaCommands()
10348 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
10350 for(i
=0; i
<256; i
++) {
10355 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
10358 case IDE_COMMAND_READ_DMA48
:
10359 case IDE_COMMAND_READ_DMA_Q48
:
10360 case IDE_COMMAND_READ_STREAM_DMA48
:
10361 case IDE_COMMAND_READ_STREAM48
:
10362 case IDE_COMMAND_WRITE_DMA48
:
10363 case IDE_COMMAND_WRITE_DMA_Q48
:
10364 case IDE_COMMAND_READ_DMA_Q
:
10365 case IDE_COMMAND_READ_DMA
:
10366 case IDE_COMMAND_WRITE_DMA
:
10367 case IDE_COMMAND_WRITE_DMA_Q
:
10368 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10369 case IDE_COMMAND_WRITE_STREAM48
:
10370 case IDE_COMMAND_WRITE_FUA_DMA48
:
10371 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10372 case IDE_COMMAND_READ_LOG_DMA48
:
10373 case IDE_COMMAND_WRITE_LOG_DMA48
:
10374 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10375 case IDE_COMMAND_TRUSTED_SEND_DMA
:
10376 case IDE_COMMAND_DATA_SET_MGMT
:
10377 //KdPrint2((PRINT_PREFIX "DMA "));
10378 flags
|= ATA_CMD_FLAG_DMA
;
10382 case IDE_COMMAND_WRITE_FUA_DMA48
:
10383 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10384 case IDE_COMMAND_WRITE_MUL_FUA48
:
10386 flags
|= ATA_CMD_FLAG_FUA
;
10389 case IDE_COMMAND_READ48
:
10390 case IDE_COMMAND_READ_DMA48
:
10391 case IDE_COMMAND_READ_DMA_Q48
:
10392 case IDE_COMMAND_READ_MUL48
:
10393 case IDE_COMMAND_READ_STREAM_DMA48
:
10394 case IDE_COMMAND_READ_STREAM48
:
10395 case IDE_COMMAND_WRITE48
:
10396 case IDE_COMMAND_WRITE_DMA48
:
10397 case IDE_COMMAND_WRITE_DMA_Q48
:
10398 case IDE_COMMAND_WRITE_MUL48
:
10399 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10400 case IDE_COMMAND_WRITE_STREAM48
:
10401 case IDE_COMMAND_FLUSH_CACHE48
:
10402 case IDE_COMMAND_VERIFY48
:
10404 //KdPrint2((PRINT_PREFIX "48 "));
10405 flags
|= ATA_CMD_FLAG_48
;
10408 case IDE_COMMAND_READ
:
10409 case IDE_COMMAND_READ_MULTIPLE
:
10410 case IDE_COMMAND_READ_DMA
:
10411 case IDE_COMMAND_READ_DMA_Q
:
10412 case IDE_COMMAND_WRITE
:
10413 case IDE_COMMAND_WRITE_MULTIPLE
:
10414 case IDE_COMMAND_WRITE_DMA
:
10415 case IDE_COMMAND_WRITE_DMA_Q
:
10416 case IDE_COMMAND_FLUSH_CACHE
:
10417 case IDE_COMMAND_VERIFY
:
10419 //KdPrint2((PRINT_PREFIX "LBA "));
10420 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
10424 case IDE_COMMAND_READ_NATIVE_SIZE48
:
10425 case IDE_COMMAND_SET_NATIVE_SIZE48
:
10426 // we cannot set LBA flag for these commands to avoid BadBlock handling
10427 //flags |= ATA_CMD_FLAG_LBAIOsupp;
10428 flags
|= ATA_CMD_FLAG_48
;
10430 case IDE_COMMAND_READ_NATIVE_SIZE
:
10431 case IDE_COMMAND_SET_NATIVE_SIZE
:
10433 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
10436 flags
|= ATA_CMD_FLAG_48supp
;
10439 case IDE_COMMAND_READ
:
10440 command
= IDE_COMMAND_READ48
; break;
10441 case IDE_COMMAND_READ_MULTIPLE
:
10442 command
= IDE_COMMAND_READ_MUL48
; break;
10443 case IDE_COMMAND_READ_DMA
:
10444 command
= IDE_COMMAND_READ_DMA48
; break;
10445 case IDE_COMMAND_READ_DMA_Q
:
10446 command
= IDE_COMMAND_READ_DMA_Q48
; break;
10447 case IDE_COMMAND_WRITE
:
10448 command
= IDE_COMMAND_WRITE48
; break;
10449 case IDE_COMMAND_WRITE_MULTIPLE
:
10450 command
= IDE_COMMAND_WRITE_MUL48
; break;
10451 case IDE_COMMAND_WRITE_DMA
:
10452 command
= IDE_COMMAND_WRITE_DMA48
; break;
10453 case IDE_COMMAND_WRITE_DMA_Q
:
10454 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
10455 case IDE_COMMAND_FLUSH_CACHE
:
10456 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
10457 // case IDE_COMMAND_READ_NATIVE_SIZE:
10458 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
10459 case IDE_COMMAND_SET_NATIVE_SIZE
:
10460 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
10461 case IDE_COMMAND_VERIFY
:
10462 command
= IDE_COMMAND_VERIFY48
; break;
10464 //KdPrint2((PRINT_PREFIX "!28->48 "));
10465 flags
&= ~ATA_CMD_FLAG_48supp
;
10469 case IDE_COMMAND_READ
:
10470 case IDE_COMMAND_READ_MULTIPLE
:
10471 case IDE_COMMAND_READ_DMA48
:
10472 case IDE_COMMAND_READ_DMA_Q48
:
10473 case IDE_COMMAND_READ_STREAM_DMA48
:
10474 case IDE_COMMAND_READ_STREAM48
:
10475 case IDE_COMMAND_READ_DMA_Q
:
10476 case IDE_COMMAND_READ_DMA
:
10477 case IDE_COMMAND_READ_LOG_DMA48
:
10478 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10479 case IDE_COMMAND_IDENTIFY
:
10480 case IDE_COMMAND_ATAPI_IDENTIFY
:
10481 //KdPrint2((PRINT_PREFIX "RD "));
10482 flags
|= ATA_CMD_FLAG_In
;
10484 case IDE_COMMAND_WRITE
:
10485 case IDE_COMMAND_WRITE_MULTIPLE
:
10486 case IDE_COMMAND_WRITE_DMA48
:
10487 case IDE_COMMAND_WRITE_DMA_Q48
:
10488 case IDE_COMMAND_WRITE_DMA
:
10489 case IDE_COMMAND_WRITE_DMA_Q
:
10490 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10491 case IDE_COMMAND_WRITE_STREAM48
:
10492 case IDE_COMMAND_WRITE_FUA_DMA48
:
10493 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10494 //KdPrint2((PRINT_PREFIX "WR "));
10495 flags
|= ATA_CMD_FLAG_Out
;
10499 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
10500 AtaCommands48
[i
] = command
;
10501 AtaCommandFlags
[i
] = flags
;
10503 } // end UniataInitAtaCommands()
10508 Routine Description:
10510 Installable driver initialization entry point for system.
10518 Status from ScsiPortInitialize()
10525 IN PVOID DriverObject
,
10529 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
10530 ULONG adapterCount
;
10531 ULONG i
, c
, alt
, pref_alt
;
10532 ULONG statusToReturn
, newStatus
;
10533 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
10534 BOOLEAN ReEnter
= FALSE
;
10536 #ifndef USE_REACTOS_DDK
10540 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
10541 BOOLEAN PrimaryClaimed
= FALSE
;
10542 BOOLEAN SecondaryClaimed
= FALSE
;
10543 BOOLEAN IgnoreIsaCompatiblePci
= FALSE
;
10544 BOOLEAN IgnoreNativePci
= FALSE
;
10546 LARGE_INTEGER t0
, t1
;
10548 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
10549 //a = (WCHAR)strlen(ver_string);
10551 statusToReturn
= 0xffffffff;
10553 // Zero out structure.
10554 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10556 // Set size of hwInitializationData.
10557 hwInitializationData
.comm
.HwInitializationDataSize
=
10558 sizeof(hwInitializationData
.comm
) +
10559 // sizeof(hwInitializationData.nt4) +
10560 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10561 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10563 // Set entry points.
10564 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10565 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10566 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10567 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10569 // Specify size of extensions.
10570 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10571 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10572 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10574 // Indicate PIO device.
10575 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10577 // Request and parse arument string.
10578 KdPrint2((PRINT_PREFIX
"\n\nUniATA: parse ArgumentString\n"));
10579 // Zero out structure.
10580 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10581 hwInitializationData
.comm
.HwFindAdapter
= AtapiReadArgumentString
;
10582 ScsiPortInitialize(DriverObject
,
10584 &hwInitializationData
.comm
,
10588 Connect_DbgPrint();
10589 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
10590 if(g_opt_Verbose
) {
10591 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
10593 IgnoreIsaCompatiblePci
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci
) ? TRUE
: FALSE
;
10594 IgnoreNativePci
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", IgnoreNativePci
) ? TRUE
: FALSE
;
10596 KdPrint(("crashdump mode\n"));
10599 if(!SavedDriverObject
) {
10600 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
10601 #ifdef USE_REACTOS_DDK
10602 KdPrint(("UniATA Init: OS should be ReactOS\n"));
10606 CPU_num
= KeNumberProcessors
;
10608 // we are here for the 1st time
10609 // init CrossNT and get OS version
10610 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
10611 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
10612 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10615 CPU_num
= *KeNumberProcessors
;
10616 #endif // USE_REACTOS_DDK
10617 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, CPU_num
));
10619 KeQuerySystemTime(&t0
);
10621 KeQuerySystemTime(&t1
);
10622 } while(t0
.QuadPart
== t1
.QuadPart
);
10626 KeQuerySystemTime(&t1
);
10628 } while(t0
.QuadPart
== t1
.QuadPart
);
10629 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
10630 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
10632 KdPrint(("UniATA Init: ReEnter\n"));
10636 // (re)read bad block list
10637 InitBadBlocks(NULL
);
10640 // init ATA command translation table
10641 //UniataInitAtaCommands();
10643 // get registry path to settings
10644 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
10645 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
10646 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
10647 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
10648 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
10649 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
10652 if(WinVer_Id() >= WinVer_2k
) {
10653 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
10654 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10655 WinVer_WDM_Model
= TRUE
;
10657 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
10658 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10659 WinVer_WDM_Model
= TRUE
;
10663 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10664 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10666 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10669 // Set PnP-specific API
10670 if(WinVer_Id() > WinVer_NT
) {
10671 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10672 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10673 KdPrint(("set AtapiAdapterControl() ptr\n"));
10674 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10677 KdPrint2((PRINT_PREFIX
"\n\nUniATA init... (%d)\n", ReEnter
));
10680 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10681 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10682 g_opt_VirtualMachine
= 0;
10684 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10685 g_opt_VirtualMachine
= VM_VBOX
;
10687 // Pre-scan PCI bus, also check if we are under VM
10688 // But do not perform scan if PCI bus is claimed as unused
10689 if(!IgnoreIsaCompatiblePci
|| !IgnoreNativePci
) {
10690 KdPrint2((PRINT_PREFIX
"\nATAPI IDE enum supported PCI BusMaster Devices\n"));
10691 UniataEnumBusMasterController(DriverObject
, Argument2
);
10694 switch(g_opt_VirtualMachine
) {
10696 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10697 // adjust options for VirtualBox
10698 g_opt_WaitBusyCount
= 20000;
10699 g_opt_WaitBusyDelay
= 150;
10700 g_opt_WaitDrqDelay
= 100;
10701 g_opt_WaitBusyLongCount
= 20000;
10702 g_opt_MaxIsrWait
= 200;
10703 g_opt_AtapiSendDisableIntr
= FALSE
;
10704 g_opt_AtapiDmaRawRead
= FALSE
;
10707 KdPrint2((PRINT_PREFIX
"adjust options for Bochs\n"));
10708 g_opt_AtapiNoDma
= TRUE
;
10712 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10713 // old slow machine, adjust timings (us)
10714 g_opt_WaitBusyResetCount
= 20000;
10715 g_opt_WaitBusyCount
= 20000;
10716 g_opt_WaitBusyDelay
= 150;
10717 g_opt_WaitDrqDelay
= 100;
10718 g_opt_WaitBusyLongCount
= 20000;
10719 g_opt_MaxIsrWait
= 200;
10720 g_opt_DriveSelectNanoDelay
= 400;
10722 if(g_opt_VirtualMachine
> VM_NONE
) {
10723 g_opt_DriveSelectNanoDelay
= 0;
10726 g_opt_AtapiSendDisableIntr
= TRUE
;
10729 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10730 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10731 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10732 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10733 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10734 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
) ? TRUE
: FALSE
; // 1 vs 0
10735 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
) ? TRUE
: FALSE
; // 1 vs 0
10736 g_opt_AtapiNoDma
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiNoDma", g_opt_AtapiNoDma
) ? TRUE
: FALSE
; // 1 vs 0
10737 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10738 g_opt_DriveSelectNanoDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay
);
10741 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10742 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10743 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10744 for (i
=0; i
<BMListLen
; i
++) {
10746 if(!BMList
[i
].MasterDev
) {
10747 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10750 if(IgnoreIsaCompatiblePci
) {
10754 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10755 if(BMList
[i
].ChanInitOk
& 0x03) {
10756 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10758 newStatus
= STATUS_SUCCESS
;
10762 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10764 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10765 PrimaryClaimed
= TRUE
;
10766 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10767 SecondaryClaimed
= TRUE
;
10770 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&& !g_Dump
&&
10771 !(BMList
[i
].ChanInitOk
& 0x80)) {
10773 // We just want to claim our PCI device in compatible mode, since we shall not
10774 // tell system that we use it inside HwInitialize
10775 // Even more, we shall cheat system, that work with ISA
10776 // Note: this call may (but not 'must' or 'can') cause IO resource
10777 // reallocation and switch to native mode if HAL supports this
10778 newStatus
= (ULONG
)UniataClaimLegacyPCIIDE(i
);
10779 // Special check for NT3.51/NT4 (not ReactOS !!!)
10780 if(((NTSTATUS
)newStatus
== STATUS_CONFLICTING_ADDRESSES
) &&
10781 //(BMList[i].ChanInitOk & 0x40) &&
10783 (WinVer_Id() <= WinVer_NT
)) {
10784 // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of
10785 // BusMaster PCI controller
10786 // Since nobody claimed Primary/Secondary yet, try init and claim them
10787 // However it is not 100% safe way, especially under ReactOS, which doesn't resolve
10789 // We relay on ScsiPort internal checks
10790 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n"));
10791 newStatus
= STATUS_SUCCESS
;
10792 // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first)
10795 if(newStatus
!= STATUS_SUCCESS
) {
10796 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10801 if(g_opt_Verbose
) {
10802 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10805 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10807 for(c
=0; c
<2; c
++) {
10808 // check is channel is manually excluded
10809 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10813 if(PrimaryClaimed
) {
10814 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10819 if(SecondaryClaimed
) {
10820 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10825 if((WinVer_Id() < WinVer_2k
)) {
10826 // do not even try if already claimed
10828 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10831 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10834 if(!WinVer_WDM_Model
) {
10835 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10837 // in WDM model things are different....
10838 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10839 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10841 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10842 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10844 if(!WinVer_WDM_Model
) {
10845 BMList
[i
].channel
= (UCHAR
)c
;
10848 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10849 newStatus
= ScsiPortInitialize(DriverObject
,
10851 &hwInitializationData
.comm
,
10852 (PVOID
)(i
| ((alt
^ pref_alt
) ? 0x80000000 : 0)));
10853 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10854 if (newStatus
< statusToReturn
) {
10855 statusToReturn
= newStatus
;
10857 if (newStatus
== STATUS_SUCCESS
) {
10858 if(WinVer_Id() < WinVer_2k
) {
10859 // This should be done in HwInitialize under w2k+ to ensure that
10860 // channel is actually initialized
10861 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10863 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10864 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10868 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10869 c = 1; // this will break our for()
10870 BMList[i].ChanInitOk |= 0x01 << c;
10875 /* if(WinVer_Id() >= WinVer_2k) {
10876 // the following didn't work under higher OSes,
10877 // until we move setting of FLAGS to HwInit
10878 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10881 if(BMList
[i
].ChanInitOk
& 0x03) {
10882 // Under NT we receive status immediately, so
10883 // we can omit alternative init method if STATUS_SUCCESS returned.
10884 // Under w2k+ we relay on flags, set in HwInitialize.
10885 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10888 if(WinVer_Id() >= WinVer_2k
) {
10889 // try AltInit if HwInit was not called immediately under w2k+
10890 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10892 // if (WinVer_Id() == WinVer_NT) and some error occured
10893 // try alternative init method
10894 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10897 if(g_opt_Verbose
) {
10898 if(BMList
[i
].ChanInitOk
& 0x03) {
10899 _PrintNtConsole(" OK\n");
10901 _PrintNtConsole(" failed\n");
10907 /* KeBugCheckEx(0xc000000e,
10908 (i << 16) | BMList[0].ChanInitOk,
10910 newStatus, statusToReturn);*/
10912 // Look for PCI IDE controller
10913 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10914 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10915 for (; i
<BMListLen
; i
++) {
10917 if(IgnoreNativePci
) {
10920 /* if(BMList[i].MasterDev)
10922 if(g_opt_Verbose
) {
10923 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10924 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10925 BMList
[i
].busNumber
,
10926 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10927 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10930 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10931 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10932 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10934 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10935 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10936 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10937 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10939 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10941 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10942 hwInitializationData
.comm
.VendorId
,
10943 hwInitializationData
.comm
.DeviceId
));
10944 newStatus
= ScsiPortInitialize(DriverObject
,
10946 &hwInitializationData
.comm
,
10948 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10949 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10950 // Note: this is actually a BUG in scsiport.sys
10951 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10952 // However, this PCI Slot may have higher non-empty Functions
10953 // UniATA will perform all staff instead of ScsiPort under NT,
10954 // but for ReactOS it is better to patch ScsiPort.
10955 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10956 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10957 newStatus
= ScsiPortInitialize(DriverObject
,
10959 &hwInitializationData
.comm
,
10960 (PVOID
)(i
| 0x80000000));
10961 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10963 if (newStatus
< statusToReturn
)
10964 statusToReturn
= newStatus
;
10966 if(g_opt_Verbose
) {
10967 if(newStatus
== STATUS_SUCCESS
) {
10968 _PrintNtConsole(" OK\n");
10970 _PrintNtConsole(" failed\n");
10976 /* KeBugCheckEx(0xc000000e,
10979 newStatus, statusToReturn);*/
10983 hwInitializationData
.comm
.VendorId
= 0;
10984 hwInitializationData
.comm
.VendorIdLength
= 0;
10985 hwInitializationData
.comm
.DeviceId
= 0;
10986 hwInitializationData
.comm
.DeviceIdLength
= 0;
10989 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10991 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10994 // The adapter count is used by the find adapter routine to track how
10995 // which adapter addresses have been tested.
10997 // Indicate 2 access ranges and reset FindAdapter.
10998 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10999 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindIsaController
;
11001 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
11002 // Indicate ISA bustype.
11003 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
11006 // Call initialization for ISA bustype.
11007 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
11008 newStatus
= ScsiPortInitialize(DriverObject
,
11010 &hwInitializationData
.comm
,
11012 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
11013 if (newStatus
< statusToReturn
)
11014 statusToReturn
= newStatus
;
11016 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
11018 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
11019 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
11022 newStatus
= ScsiPortInitialize(DriverObject
,
11024 &hwInitializationData
.comm
,
11026 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
11027 if (newStatus
< statusToReturn
)
11028 statusToReturn
= newStatus
;
11030 InDriverEntry
= FALSE
;
11032 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
11034 return statusToReturn
;
11036 } // end DriverEntry()
11039 PSCSI_REQUEST_BLOCK
11041 BuildMechanismStatusSrb(
11042 IN PVOID HwDeviceExtension
,
11043 IN PSCSI_REQUEST_BLOCK Srb
11046 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11047 PSCSI_REQUEST_BLOCK srb
;
11049 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
11051 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
11053 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
11055 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
11056 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
11057 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
11058 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
11060 // Set flags to disable synchronous negociation.
11061 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
11063 // Set timeout to 4 seconds.
11064 srb
->TimeOutValue
= 4;
11066 srb
->CdbLength
= 6;
11067 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
11068 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
11069 srb
->SrbExtension
= AtaReq
;
11071 // Set CDB operation code.
11072 cdb
= (PCDB
)srb
->Cdb
;
11073 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
11074 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
11076 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
11079 } // end BuildMechanismStatusSrb()
11081 #endif //UNIATA_CORE
11083 PSCSI_REQUEST_BLOCK
11085 BuildRequestSenseSrb (
11086 IN PVOID HwDeviceExtension
,
11087 IN PSCSI_REQUEST_BLOCK Srb
11090 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11091 PSCSI_REQUEST_BLOCK srb
;
11093 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
11095 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
11097 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
11099 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
11100 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
11101 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
11102 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
11104 // Set flags to disable synchronous negociation.
11105 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
11107 // Set timeout to 2 seconds.
11108 srb
->TimeOutValue
= 4;
11110 srb
->CdbLength
= 6;
11111 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
11112 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
11113 srb
->SrbExtension
= AtaReq
;
11115 // Set CDB operation code.
11116 cdb
= (PCDB
)srb
->Cdb
;
11117 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
11118 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
11120 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
11123 } // end BuildRequestSenseSrb()
11125 #ifndef UNIATA_CORE
11129 AtapiRegCheckDevLunValue(
11130 IN PVOID HwDeviceExtension
,
11131 IN PCWCH NamePrefix
,
11139 ULONG val
= Default
;
11141 val
= AtapiRegCheckParameterValue(
11142 HwDeviceExtension
, NamePrefix
, Name
, val
);
11144 if(chan
!= CHAN_NOT_SPECIFIED
) {
11145 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
11146 val
= AtapiRegCheckParameterValue(
11147 HwDeviceExtension
, namex
, Name
, val
);
11148 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
11149 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
11150 val
= AtapiRegCheckParameterValue(
11151 HwDeviceExtension
, namex
, Name
, val
);
11155 } // end AtapiRegCheckDevLunValue()
11168 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
11187 swprintf(Buffer
+j
, L
"%2.2x", a
);
11195 } // end EncodeVendorStr()
11199 AtapiRegCheckDevValue(
11200 IN PVOID HwDeviceExtension
,
11207 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11208 // WCHAR name0[11];
11209 // WCHAR name1[11+4+5];
11210 // WCHAR name2[11+4+4+10];
11211 // WCHAR name3[11+4+4+5+20];
11212 // WCHAR name3[11+4+4+5+20+1];
11221 IN ULONG SlotNumber
;
11223 ULONG val
= Default
;
11225 KdPrint(( " Parameter %ws\n", Name
));
11227 if(deviceExtension
) {
11228 VendorID
= deviceExtension
->DevID
& 0xffff;
11229 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
11230 SlotNumber
= deviceExtension
->slotNumber
;
11234 SlotNumber
= 0xffffffff;
11237 val
= AtapiRegCheckDevLunValue(
11238 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
11240 if(deviceExtension
) {
11241 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
11243 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
11244 swprintf(namex
, L
"Parameters%s", namev
);
11245 val
= AtapiRegCheckDevLunValue(
11246 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11249 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
11250 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
11251 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
11253 swprintf(namex
, L
"Parameters%s", namev
);
11254 val
= AtapiRegCheckDevLunValue(
11255 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11257 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
11258 val
= AtapiRegCheckDevLunValue(
11259 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11261 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
11262 val
= AtapiRegCheckDevLunValue(
11263 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11265 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
11267 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
11268 swprintf(namex
, L
"Parameters%s", namev
);
11269 val
= AtapiRegCheckDevLunValue(
11270 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11272 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
11273 swprintf(namex
, L
"Parameters%s", namev
);
11274 val
= AtapiRegCheckDevLunValue(
11275 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11278 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
11280 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
11281 swprintf(namex
, L
"Parameters%s", namev
);
11282 val
= AtapiRegCheckDevLunValue(
11283 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11285 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
11286 swprintf(namex
, L
"Parameters%s", namev
);
11287 val
= AtapiRegCheckDevLunValue(
11288 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11293 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
11296 } // end AtapiRegCheckDevValue()
11299 The user must specify that Xxx is to run on the platform
11300 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
11301 Services\UniATA\Xxx:REG_DWORD:Zzz.
11303 The user can override the global setting to enable or disable Xxx on a
11304 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
11305 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
11307 If this registry value does not exist or contains the value zero then
11308 the timer to check for media change does not run.
11312 RegistryPath - pointer to the unicode string inside
11313 ...\CurrentControlSet\Services\UniATA
11314 DeviceNumber - The number of the HBA device object
11316 Returns: Registry Key value
11320 AtapiRegCheckParameterValue(
11321 IN PVOID HwDeviceExtension
,
11322 IN PCWSTR PathSuffix
,
11327 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
11329 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11331 LONG zero
= Default
;
11333 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
11336 LONG doRun
= Default
;
11338 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
11340 UNICODE_STRING paramPath
;
11346 // <SavedRegPath>\<PathSuffix> -> <Name>
11347 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
11348 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
11350 paramPath
.Length
= 0;
11351 paramPath
.MaximumLength
= RegistryPath
->Length
+
11352 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
11353 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
11354 if(!paramPath
.Buffer
) {
11355 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
11359 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
11360 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
11361 RtlAppendUnicodeToString(¶mPath
, L
"\\");
11362 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
11364 // Check for the Xxx value.
11365 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
11367 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
11368 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
11369 parameters
[0].EntryContext
= &doRun
;
11370 parameters
[0].DefaultType
= REG_DWORD
;
11371 parameters
[0].DefaultData
= &zero
;
11372 parameters
[0].DefaultLength
= sizeof(ULONG
);
11374 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
11375 paramPath
.Buffer
, parameters
, NULL
, NULL
);
11376 if(NT_SUCCESS(status
)) {
11377 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
11380 ExFreePool(paramPath
.Buffer
);
11382 if(!NT_SUCCESS(status
)) {
11389 #undef ITEMS_TO_QUERY
11391 } // end AtapiRegCheckParameterValue()
11394 SCSI_ADAPTER_CONTROL_STATUS
11396 AtapiAdapterControl(
11397 IN PVOID HwDeviceExtension
,
11398 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
11399 IN PVOID Parameters
11402 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11403 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
11404 ULONG numberChannels
= deviceExtension
->NumberChannels
;
11408 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
11410 switch(ControlType
) {
11411 case ScsiQuerySupportedControlTypes
: {
11412 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
11413 TRUE
, // ScsiQuerySupportedControlTypes
11414 TRUE
, // ScsiStopAdapter
11415 TRUE
, // ScsiRestartAdapter
11416 FALSE
, // ScsiSetBootConfig
11417 FALSE
// ScsiSetRunningConfig
11420 ULONG lim
= ScsiAdapterControlMax
;
11423 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
11425 if(pControlTypeList
->MaxControlType
< lim
) {
11426 lim
= pControlTypeList
->MaxControlType
;
11429 for(i
= 0; i
< lim
; i
++) {
11430 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
11436 case ScsiStopAdapter
: {
11438 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
11439 // Shut down all interrupts on the adapter. They'll get re-enabled
11440 // by the initialization routines.
11441 for (c
= 0; c
< numberChannels
; c
++) {
11442 AtapiResetController(deviceExtension
, c
);
11443 AtapiDisableInterrupts(deviceExtension
, c
);
11445 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
11446 // we must never get here for non-PCI
11447 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
11448 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
11452 case ScsiRestartAdapter
: {
11454 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
11455 // Enable all the interrupts on the adapter while port driver call
11456 // for power up an HBA that was shut down for power management
11458 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
11459 status
= UniataConnectIntr2(HwDeviceExtension
);
11460 if(NT_SUCCESS(status
)) {
11461 for (c
= 0; c
< numberChannels
; c
++) {
11462 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
11463 FindDevices(HwDeviceExtension
, 0, c
);
11464 AtapiEnableInterrupts(deviceExtension
, c
);
11465 AtapiHwInitialize__(deviceExtension
, c
);
11467 if(deviceExtension
->Isr2DevObj
) {
11468 // we must never get here for non-PCI
11469 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
11477 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
11478 return ScsiAdapterControlUnsuccessful
;
11482 return ScsiAdapterControlSuccess
;
11483 } // end AtapiAdapterControl()
11485 #endif //UNIATA_CORE
11495 #define DEBUG_MSG_BUFFER_SIZE 512
11506 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
11507 // UNICODE_STRING msgBuff;
11509 va_start(ap
, DebugMessage
);
11511 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
11513 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
11515 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
11516 HalDisplayString(dbg_print_tmp_buff
);
11519 if(g_LogToDisplay
> 1) {
11520 AtapiStallExecution(g_LogToDisplay
*1000);
11526 } // end PrintNtConsole()