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
;
109 BOOLEAN g_opt_Verbose
= 0;
111 BOOLEAN WinVer_WDM_Model
= FALSE
;
114 //UCHAR EnableDma = FALSE;
115 //UCHAR EnableReorder = FALSE;
121 AtapiResetController__(
122 IN PVOID HwDeviceExtension
,
124 IN UCHAR CompleteType
130 IN PHW_DEVICE_EXTENSION deviceExtension
,
136 UniataUserDeviceReset(
137 PHW_DEVICE_EXTENSION deviceExtension
,
138 PHW_LU_EXTENSION LunExt
,
142 #define RESET_COMPLETE_CURRENT 0x00
143 #define RESET_COMPLETE_ALL 0x01
144 #define RESET_COMPLETE_NONE 0x02
151 IN PVOID HwDeviceExtension
154 #ifdef UNIATA_USE_XXableInterrupts
155 #define RETTYPE_XXableInterrupts BOOLEAN
156 #define RETVAL_XXableInterrupts TRUE
158 #define RETTYPE_XXableInterrupts VOID
159 #define RETVAL_XXableInterrupts
162 RETTYPE_XXableInterrupts
165 IN PVOID HwDeviceExtension
168 RETTYPE_XXableInterrupts
170 AtapiEnableInterrupts__(
171 IN PVOID HwDeviceExtension
177 IN PVOID HwDeviceExtension
,
179 IN PHW_TIMER HwScsiTimer
,
180 IN ULONG MiniportTimerValue
183 SCSI_ADAPTER_CONTROL_STATUS
186 IN PVOID HwDeviceExtension
,
187 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
197 AtapiRegGetStringParameterValue(
198 IN PWSTR RegistryPath
,
204 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
206 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
211 ustr
.MaximumLength
= (USHORT
)MaxLen
;
212 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
214 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
215 parameters
[0].Name
= Name
;
216 parameters
[0].EntryContext
= &ustr
;
217 parameters
[0].DefaultType
= REG_SZ
;
218 parameters
[0].DefaultData
= Str
;
219 parameters
[0].DefaultLength
= MaxLen
;
221 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
222 RegistryPath
, parameters
, NULL
, NULL
);
224 if(!NT_SUCCESS(status
))
229 #undef ITEMS_TO_QUERY
230 } // end AtapiRegGetStringParameterValue()
248 if(!nano
|| !g_Perf
|| !g_PerfDt
)
250 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
255 KeQuerySystemTime(&t0
);
258 } // end UniataNanoSleep()
260 #define AtapiWritePortN_template(_type, _Type, sz) \
263 AtapiWritePort##sz( \
264 IN PHW_CHANNEL chan, \
265 IN ULONGIO_PTR _port, \
270 if(_port >= IDX_MAX_REG) { \
271 res = (PIORES)(_port); \
274 res = &chan->RegTranslation[_port]; \
276 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
280 KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \
281 ASSERT(FALSE); /* We should never get here */ \
284 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
286 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
287 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
292 AtapiWritePortN_template(ULONG
, Ulong
, 4);
293 AtapiWritePortN_template(USHORT
, Ushort
, 2);
294 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
296 #define AtapiWritePortExN_template(_type, _Type, sz) \
299 AtapiWritePortEx##sz( \
300 IN PHW_CHANNEL chan, \
301 IN ULONGIO_PTR _port, \
307 if(_port >= IDX_MAX_REG) { \
308 res = (PIORES)(_port); \
311 res = &chan->RegTranslation[_port]; \
313 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
317 KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
318 ASSERT(FALSE); /* We should never get here */ \
321 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
323 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
324 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
329 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
330 //AtapiWritePortExN_template(USHORT, Ushort, 2);
331 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
333 #define AtapiReadPortN_template(_type, _Type, sz) \
337 IN PHW_CHANNEL chan, \
338 IN ULONGIO_PTR _port \
342 if(_port >= IDX_MAX_REG) { \
343 res = (PIORES)(_port); \
346 res = &chan->RegTranslation[_port]; \
348 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
349 return (_type)(-1); \
352 KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \
353 ASSERT(FALSE); /* We should never get here */ \
356 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
357 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
359 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
360 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
364 AtapiReadPortN_template(ULONG
, Ulong
, 4);
365 AtapiReadPortN_template(USHORT
, Ushort
, 2);
366 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
368 #define AtapiReadPortExN_template(_type, _Type, sz) \
371 AtapiReadPortEx##sz( \
372 IN PHW_CHANNEL chan, \
373 IN ULONGIO_PTR _port, \
378 if(_port >= IDX_MAX_REG) { \
379 res = (PIORES)(_port); \
382 res = &chan->RegTranslation[_port]; \
384 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
385 return (_type)(-1); \
388 KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
389 ASSERT(FALSE); /* We should never get here */ \
392 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
394 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
395 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
399 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
400 //AtapiReadPortExN_template(USHORT, Ushort, 2);
401 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
403 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
406 AtapiReadBuffer##sz( \
407 IN PHW_CHANNEL chan, \
408 IN ULONGIO_PTR _port, \
418 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
420 Buffer = ((_type*)Buffer)+1; \
421 UniataNanoSleep(Timing); \
426 if(_port >= IDX_MAX_REG) { \
427 res = (PIORES)(_port); \
430 res = &chan->RegTranslation[_port]; \
432 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
436 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
437 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
441 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
443 Buffer = ((_type*)Buffer)+1; \
448 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
451 AtapiWriteBuffer##sz( \
452 IN PHW_CHANNEL chan, \
453 IN ULONGIO_PTR _port, \
463 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
464 Buffer = ((_type*)Buffer)+1; \
466 UniataNanoSleep(Timing); \
471 if(_port >= IDX_MAX_REG) { \
472 res = (PIORES)(_port); \
475 res = &chan->RegTranslation[_port]; \
477 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
481 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
482 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
486 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
488 Buffer = ((_type*)Buffer)+1; \
493 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
494 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
496 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
497 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
509 // Assume, proper drive is already seleted
510 WaitOnBusyLong(chan
);
511 for (i
= 0; i
< 0x10000; i
++) {
513 GetStatus(chan
, statusByte
);
514 if (statusByte
& IDE_STATUS_DRQ
) {
515 // Suck out any remaining bytes and throw away.
516 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
517 UniataNanoSleep(PIO0_TIMING
);
523 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
526 } // AtapiSuckPort2()
530 AtapiSuckPortBuffer2(
539 BOOLEAN retry
= FALSE
;
541 // Assume, proper drive is already seleted
542 WaitOnBusyLong(chan
);
543 for (i
= 0; i
< Count
; i
++) {
545 GetStatus(chan
, statusByte
);
546 if (statusByte
& IDE_STATUS_DRQ
) {
547 // Suck out any remaining bytes and throw away.
548 data
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
552 UniataNanoSleep(PIO0_TIMING
);
555 if(i
<Count
&& !retry
) {
556 KdPrint2((PRINT_PREFIX
" wait...\n"));
564 KdPrint2((PRINT_PREFIX
"AtapiSuckPortBuffer2: %#x words\n", i
));
566 AtapiSuckPort2(chan
);
570 } // AtapiSuckPortBuffer2()
576 IN ULONG DeviceNumber
583 if(chan->lun[DeviceNumber] &&
584 (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
585 KdPrint3((" Select %d\n", DeviceNumber));
588 if(chan
->last_devsel
== DeviceNumber
) {
589 //KdPrint3((" Selected %d\n", DeviceNumber));
592 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
); \
593 chan
->last_devsel
= DeviceNumber
? 1 : 0;
594 if(!g_opt_DriveSelectNanoDelay
) {
595 //KdPrint3((" Select %d\n", DeviceNumber));
598 //KdPrint3((" Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
599 UniataNanoSleep(g_opt_DriveSelectNanoDelay
);
601 } // end SelectDrive()
612 GetStatus(chan
, Status
);
613 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
614 if (Status
& IDE_STATUS_BUSY
) {
615 AtapiStallExecution(g_opt_WaitBusyDelay
);
616 GetStatus(chan
, Status
);
623 } // end WaitOnBusy()
634 Status
= WaitOnBusy(chan
);
635 if(!(Status
& IDE_STATUS_BUSY
))
637 for (i
=0; i
<g_opt_WaitBusyLongCount
; i
++) {
638 GetStatus(chan
, Status
);
639 if (Status
& IDE_STATUS_BUSY
) {
640 AtapiStallExecution(g_opt_WaitBusyLongDelay
);
647 } // end WaitOnBusyLong()
656 UCHAR Status
= IDE_STATUS_WRONG
;
657 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
658 GetBaseStatus(chan
, Status
);
659 if (Status
& IDE_STATUS_BUSY
) {
660 AtapiStallExecution(g_opt_WaitBusyDelay
);
667 } // end WaitOnBaseBusy()
678 Status
= WaitOnBaseBusy(chan
);
679 if(!(Status
& IDE_STATUS_BUSY
))
681 for (i
=0; i
<2000; i
++) {
682 GetBaseStatus(chan
, Status
);
683 if (Status
& IDE_STATUS_BUSY
) {
684 AtapiStallExecution(250);
691 } // end WaitOnBaseBusyLong()
696 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
702 if(Status
== IDE_STATUS_WRONG
) {
703 return IDE_STATUS_WRONG
;
705 if(Status
& IDE_STATUS_BUSY
) {
708 // if(deviceExtension->HwFlags & UNIATA_SATA) {
709 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
710 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
714 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
715 if ((Status
& IDE_STATUS_BUSY
) ||
716 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
720 return IDE_STATUS_IDLE
;
721 } // end UniataIsIdle()
732 for (i
=0; i
<20000; i
++) {
733 GetStatus(chan
, Status
);
734 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
735 if(Status2
== IDE_STATUS_WRONG
) {
739 if(Status2
& IDE_STATUS_BUSY
) {
740 AtapiStallExecution(10);
747 } // end WaitForIdleLong()
757 for (i
=0; i
<1000; i
++) {
758 GetStatus(chan
, Status
);
759 if (Status
& IDE_STATUS_BUSY
) {
760 AtapiStallExecution(g_opt_WaitDrqDelay
);
761 } else if (Status
& IDE_STATUS_DRQ
) {
764 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
768 } // end WaitForDrq()
778 for (i
=0; i
<2; i
++) {
779 GetStatus(chan
, Status
);
780 if (Status
& IDE_STATUS_BUSY
) {
781 AtapiStallExecution(g_opt_WaitDrqDelay
);
782 } else if (Status
& IDE_STATUS_DRQ
) {
785 AtapiStallExecution(g_opt_WaitDrqDelay
);
789 } // end WaitShortForDrq()
795 IN ULONG DeviceNumber
798 //ULONG c = chan->lChannel;
800 UCHAR dma_status
= 0;
801 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
802 UCHAR statusByte0
, statusByte2
;
804 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
805 UniataAhciSoftReset(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
);
809 GetBaseStatus(chan
, statusByte2
);
810 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
811 SelectDrive(chan
, DeviceNumber
);
812 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
814 KdPrint2((PRINT_PREFIX
" ESDI/MFM\n"));
815 AtapiStallExecution(10000);
816 for (i
= 0; i
< 1000; i
++) {
817 AtapiStallExecution(999);
820 // Seems to be unnecessary, verified by KtP
822 // original atapi.sys behavior for old ISA-only hardware
823 AtapiStallExecution(10000);
824 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
825 for (i = 0; i < 1000; i++) {
826 AtapiStallExecution(999);
829 AtapiStallExecution(500);
830 GetBaseStatus(chan
, statusByte2
);
831 statusByte0
= statusByte2
;
832 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
834 // Do not wait for BUSY assertion if it was initially set, jump to
835 // BUSY release wait loop
836 if(!(statusByte0
& IDE_STATUS_BUSY
)) {
837 // Wait for BUSY assertion, in some cases delay may occure
838 // 100ms should be enough
839 if(g_opt_VirtualMachine
== VM_BOCHS
) {
844 statusByte2
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
845 while (!(statusByte2
& IDE_STATUS_BUSY
) &&
848 if(!(statusByte0
& IDE_STATUS_ERROR
) && (statusByte2
& IDE_STATUS_ERROR
)) {
849 KdPrint2((PRINT_PREFIX
" Command aborted, statusByte2 %x:\n", statusByte2
));
852 AtapiStallExecution(10);
857 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
858 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
859 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
860 // implementation. (which is around 1 second)
861 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
864 AtapiStallExecution(30);
866 KdPrint2((PRINT_PREFIX
" set DFLAGS_REINIT_DMA\n"));
867 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
870 chan
->last_devsel
= -1; // make sure proper drive would be selected
871 SelectDrive(chan
, DeviceNumber
);
873 GetBaseStatus(chan
, statusByte2
);
874 AtapiStallExecution(500);
876 GetBaseStatus(chan
, statusByte2
);
877 if(chan
&& chan
->DeviceExtension
) {
878 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
879 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
881 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
883 if(dma_status
& BM_STATUS_INTR
) {
884 // bullshit, we have DMA interrupt, but had never initiate DMA operation
885 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
886 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
887 GetBaseStatus(chan
, statusByte2
);
889 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
890 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
891 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
892 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
897 } // end AtapiSoftReset()
902 IN
struct _HW_CHANNEL
* chan
,
903 IN BOOLEAN DisableInterrupts
,
907 KdPrint2((PRINT_PREFIX
"AtapiHardReset: %d, dis=%d\n", Delay
, DisableInterrupts
));
908 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_RESET_CONTROLLER
|
909 (DisableInterrupts
? IDE_DC_DISABLE_INTERRUPTS
: 0));
910 chan
->last_devsel
= -1;
911 AtapiStallExecution(Delay
);
912 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_REENABLE_CONTROLLER
);
913 } // end AtapiHardReset()
916 Send command to device.
917 Translate to 48-Lba form if required
922 IN PHW_DEVICE_EXTENSION deviceExtension
,
923 IN ULONG DeviceNumber
,
932 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
937 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
938 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
940 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
941 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
943 KdPrint3((" (ahci)\n"));
945 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
946 (PSCSI_REQUEST_BLOCK
)NULL
,
954 1000 /* timeout 1 sec */
960 SelectDrive(chan
, DeviceNumber
);
962 statusByte
= WaitOnBusy(chan
);
964 /* ready to issue command ? */
965 if (statusByte
& IDE_STATUS_BUSY
) {
966 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
969 // !!! We should not check ERROR condition here
970 // ERROR bit may be asserted durring previous operation
971 // and not cleared after SELECT
973 //>>>>>> NV: 2006/08/03
974 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
975 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
976 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
977 return IDE_STATUS_ERROR
;
978 //return SRB_STATUS_ERROR;
980 //<<<<<< NV: 2006/08/03
982 /* only use 48bit addressing if needed because of the overhead */
983 if (UniAta_need_lba48(command
, lba
, count
,
984 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
986 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
987 /* translate command into 48bit version */
988 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
989 command
= AtaCommands48
[command
];
991 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
995 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
998 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
999 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
1000 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
1001 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
1002 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
1003 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
1004 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
1005 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
1006 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
1007 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
1009 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
1010 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
1013 plba
= (PUCHAR
)&lba
; //ktp
1014 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1017 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
1018 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
1020 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
1021 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
1022 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
1023 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
1024 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1025 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
1026 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
1028 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
1029 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
1033 // write command code to device
1034 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
1036 switch (wait_flags
) {
1039 // caller requested wait for interrupt
1042 statusByte
= WaitForDrq(chan
);
1043 if (statusByte
& IDE_STATUS_DRQ
)
1045 AtapiStallExecution(500);
1046 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
1053 // caller requested wait for entering Wait state
1054 for (i
=0; i
<30 * 1000; i
++) {
1056 GetStatus(chan
, statusByte
);
1057 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1058 if(statusByte
== IDE_STATUS_WRONG
) {
1062 if(statusByte
& IDE_STATUS_ERROR
) {
1065 if(statusByte
& IDE_STATUS_BUSY
) {
1066 AtapiStallExecution(100);
1069 if((statusByte
& ~IDE_STATUS_INDEX
) == IDE_STATUS_IDLE
) {
1072 //if(deviceExtension->HwFlags & UNIATA_SATA) {
1073 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1076 AtapiStallExecution(100);
1079 //statusByte |= IDE_STATUS_BUSY;
1082 case ATA_WAIT_READY
:
1083 statusByte
= WaitOnBusyLong(chan
);
1085 case ATA_WAIT_BASE_READY
:
1086 statusByte
= WaitOnBaseBusyLong(chan
);
1089 GetStatus(chan
, statusByte
);
1090 if (statusByte
& IDE_STATUS_ERROR
) {
1091 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
1092 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
1095 KdPrint2((PRINT_PREFIX
" try to continue\n"));
1096 statusByte
&= ~IDE_STATUS_ERROR
;
1099 //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte));
1101 UniataExpectChannelInterrupt(chan
, TRUE
);
1103 InterlockedExchange(&(chan
->CheckIntr
),
1106 statusByte
= IDE_STATUS_SUCCESS
;
1110 //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
1113 } // end AtaCommand48()
1116 Send command to device.
1117 This is simply wrapper for AtaCommand48()
1122 IN PHW_DEVICE_EXTENSION deviceExtension
,
1123 IN ULONG DeviceNumber
,
1134 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
1135 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1137 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1138 count
, feature
, wait_flags
);
1140 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
1141 (PSCSI_REQUEST_BLOCK
)NULL
,
1145 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1148 0 /* ahci flags */ ,
1150 1000 /* timeout 1 sec */
1154 } // end AtaCommand()
1158 AtaPio2Mode(LONG pio
)
1161 default: return ATA_PIO
;
1162 case 0: return ATA_PIO0
;
1163 case 1: return ATA_PIO1
;
1164 case 2: return ATA_PIO2
;
1165 case 3: return ATA_PIO3
;
1166 case 4: return ATA_PIO4
;
1167 case 5: return ATA_PIO5
;
1169 } // end AtaPio2Mode()
1173 AtaPioMode(PIDENTIFY_DATA2 ident
)
1175 if (ident
->PioTimingsValid
) {
1176 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1178 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1180 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1183 if (ident
->PioCycleTimingMode
== 2)
1185 if (ident
->PioCycleTimingMode
== 1)
1187 if (ident
->PioCycleTimingMode
== 0)
1189 return IOMODE_NOT_SPECIFIED
;
1190 } // end AtaPioMode()
1194 AtaWmode(PIDENTIFY_DATA2 ident
)
1196 if (ident
->MultiWordDMASupport
& 0x04)
1198 if (ident
->MultiWordDMASupport
& 0x02)
1200 if (ident
->MultiWordDMASupport
& 0x01)
1202 return IOMODE_NOT_SPECIFIED
;
1207 AtaUmode(PIDENTIFY_DATA2 ident
)
1209 if (!ident
->UdmaModesValid
)
1210 return IOMODE_NOT_SPECIFIED
;
1211 if (ident
->UltraDMASupport
& 0x40)
1213 if (ident
->UltraDMASupport
& 0x20)
1215 if (ident
->UltraDMASupport
& 0x10)
1217 if (ident
->UltraDMASupport
& 0x08)
1219 if (ident
->UltraDMASupport
& 0x04)
1221 if (ident
->UltraDMASupport
& 0x02)
1223 if (ident
->UltraDMASupport
& 0x01)
1225 return IOMODE_NOT_SPECIFIED
;
1230 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1231 if(!ident
->SataCapabilities
||
1232 ident
->SataCapabilities
== 0xffff) {
1233 return IOMODE_NOT_SPECIFIED
;
1235 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1238 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1241 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1244 return IOMODE_NOT_SPECIFIED
;
1245 } // end AtaSAmode()
1252 IN PVOID HwDeviceExtension
1255 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1256 PHW_TIMER HwScsiTimer
;
1258 ULONG MiniportTimerValue
;
1259 BOOLEAN recall
= FALSE
;
1263 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1265 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1266 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1267 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1270 chan
= &(deviceExtension
->chan
[lChannel
]);
1274 HwScsiTimer
= chan
->HwScsiTimer
;
1275 chan
->HwScsiTimer
= NULL
;
1277 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1278 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1282 HwScsiTimer(HwDeviceExtension
);
1284 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1286 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1287 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1288 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1289 deviceExtension
->FirstDpcChan
=
1290 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1294 KeQuerySystemTime(&time
);
1295 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1297 chan
= &deviceExtension
->chan
[lChannel
];
1298 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1300 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1301 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1308 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1309 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1310 if(!MiniportTimerValue
)
1311 MiniportTimerValue
= 1;
1313 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1314 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1321 } // end AtapiTimerDpc()
1324 Wrapper for ScsiPort, that implements smart Dpc
1325 queueing. We need it to allow parallel functioning
1326 of IDE channels with shared interrupt. Standard Dpc mechanism
1327 cancels previous Dpc request (if any), but we need Dpc queue.
1332 IN PVOID HwDeviceExtension
,
1334 IN PHW_TIMER HwScsiTimer
,
1335 IN ULONG MiniportTimerValue
1338 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1340 LARGE_INTEGER time2
;
1342 PHW_CHANNEL prev_chan
;
1344 // BOOLEAN UseRequestTimerCall = TRUE;
1346 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1347 KeQuerySystemTime(&time
);
1349 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1350 time
.QuadPart
+= MiniportTimerValue
*10;
1351 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1353 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1355 i
= deviceExtension
->FirstDpcChan
;
1356 chan
= prev_chan
= NULL
;
1357 while(i
!= CHAN_NOT_SPECIFIED
) {
1359 chan
= &(deviceExtension
->chan
[i
]);
1360 if(chan
->DpcTime
> time
.QuadPart
) {
1363 i
= chan
->NextDpcChan
;
1365 chan
= &(deviceExtension
->chan
[lChannel
]);
1367 deviceExtension
->FirstDpcChan
= lChannel
;
1369 prev_chan
->NextDpcChan
= lChannel
;
1371 chan
->NextDpcChan
= i
;
1372 chan
->HwScsiTimer
= HwScsiTimer
;
1373 chan
->DpcTime
= time
.QuadPart
;
1375 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1376 if(time
.QuadPart
<= time2
.QuadPart
) {
1377 MiniportTimerValue
= 1;
1379 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1382 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1383 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1385 MiniportTimerValue
);
1387 } // end AtapiQueueTimerDpc()
1389 #endif //UNIATA_CORE
1399 UCHAR statusByteAlt
;
1401 GetStatus(chan
, statusByteAlt
);
1402 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1404 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1405 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1406 KdPrint2((PRINT_PREFIX
1407 " Reg_%#x (%#x) = %#x\n",
1409 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1412 if(!chan
->RegTranslation
[IDX_BM_IO
].Addr
) {
1415 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1416 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1417 KdPrint2((PRINT_PREFIX
1418 " BM_%#x (%#x) = %#x\n",
1420 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1424 } // end UniataDumpATARegs()
1430 IN PHW_CHANNEL chan
,
1431 IN ULONG DeviceNumber
,
1432 IN OUT PIDEREGS_EX regs
1435 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1437 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1439 // SATA/PATA, assume drive is selected
1441 UCHAR statusByteAlt
;
1443 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1444 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1445 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1446 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1450 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1451 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1452 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1453 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1454 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1455 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1457 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1461 } // end UniataSnapAtaRegs()
1465 Routine Description:
1467 Issue IDENTIFY command to a device.
1471 HwDeviceExtension - HBA miniport driver's adapter data storage
1472 DeviceNumber - Indicates which device.
1473 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1477 TRUE if all goes well.
1483 IN PVOID HwDeviceExtension
,
1484 IN ULONG DeviceNumber
,
1490 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1491 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1492 ULONG waitCount
= 50000;
1495 //UCHAR statusByte2;
1498 BOOLEAN atapiDev
= FALSE
;
1499 BOOLEAN use_ahci
= FALSE
;
1500 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1502 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1503 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1505 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1506 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1509 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1513 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1514 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1517 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1518 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1523 statusByte
= WaitOnBusyLong(chan
);
1525 if(!chan
->AhciInternalAtaReq
) {
1526 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1530 SelectDrive(chan
, DeviceNumber
);
1531 AtapiStallExecution(10);
1532 statusByte
= WaitOnBusyLong(chan
);
1533 // Check that the status register makes sense.
1534 GetBaseStatus(chan
, statusByte
);
1538 // original atapi.sys behavior for old ISA-only hardware
1539 AtapiStallExecution(100);
1544 if (Command
== IDE_COMMAND_IDENTIFY
) {
1545 // Mask status byte ERROR bits.
1546 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1547 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1548 // Check if register value is reasonable.
1550 if(statusByte
!= IDE_STATUS_IDLE
) {
1552 // No reset here !!!
1553 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1555 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1556 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1557 SelectDrive(chan
, DeviceNumber
);
1558 WaitOnBusyLong(chan
);
1560 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1561 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1563 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1564 signatureHigh
== ATAPI_MAGIC_MSB
) {
1566 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1570 // We really should wait up to 31 seconds
1571 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1572 // (30 seconds for device 1)
1574 // Wait for Busy to drop.
1575 AtapiStallExecution(100);
1576 GetStatus(chan
, statusByte
);
1577 if(statusByte
== IDE_STATUS_WRONG
) {
1578 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1582 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1583 GetBaseStatus(chan
, statusByte
);
1585 SelectDrive(chan
, DeviceNumber
);
1587 GetBaseStatus(chan
, statusByte
);
1589 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1591 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1592 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1594 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1595 signatureHigh
== ATAPI_MAGIC_MSB
) {
1596 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1601 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1602 if (statusByte
!= IDE_STATUS_IDLE
) {
1604 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1609 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1610 if(statusByte
== IDE_STATUS_WRONG
) {
1613 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1614 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1615 statusByte
= WaitForIdleLong(chan
);
1616 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1621 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1623 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1624 (PSCSI_REQUEST_BLOCK
)NULL
,
1625 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1630 0 /* ahci flags */ ,
1632 1000 /* timeout 1 sec */
1634 j
= 9; // AHCI is rather different, skip loop at all
1636 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1637 j
= 9; // don't send IDENTIFY, assume it is not supported
1638 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1639 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1640 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1642 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1643 j
= 4; // skip old-style checks
1647 for (; j
< 4*2; j
++) {
1648 // Send IDENTIFY command.
1650 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1652 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1656 KdPrint2((PRINT_PREFIX
"IssueIdentify: 0-status, not present\n"));
1659 if (statusByte
& IDE_STATUS_DRQ
) {
1660 // Read status to acknowledge any interrupts generated.
1661 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1662 GetBaseStatus(chan
, statusByte
);
1663 // One last check for Atapi.
1664 if (Command
== IDE_COMMAND_IDENTIFY
) {
1665 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1666 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1668 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1669 signatureHigh
== ATAPI_MAGIC_MSB
) {
1670 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1677 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1678 if (Command
== IDE_COMMAND_IDENTIFY
) {
1679 // Check the signature. If DRQ didn't come up it's likely Atapi.
1680 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1681 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1683 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1684 signatureHigh
== ATAPI_MAGIC_MSB
) {
1686 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1690 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1691 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1695 // Device didn't respond correctly. It will be given one more chance.
1696 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1697 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1698 GetBaseStatus(chan
, statusByte
);
1699 AtapiSoftReset(chan
,DeviceNumber
);
1701 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1702 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1704 GetBaseStatus(chan
, statusByte
);
1705 //GetStatus(chan, statusByte);
1706 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1709 // Check for error on really stupid master devices that assert random
1710 // patterns of bits in the status register at the slave address.
1711 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1712 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1717 // everything should already be done by controller
1719 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1720 j
= 9; // don't send IDENTIFY, assume it is not supported
1721 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1722 statusByte
= WaitForDrq(chan
);
1723 statusByte
= WaitOnBusyLong(chan
);
1724 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1725 GetBaseStatus(chan
, statusByte
);
1728 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1729 // Suck out 256 words. After waiting for one model that asserts busy
1730 // after receiving the Packet Identify command.
1731 statusByte
= WaitForDrq(chan
);
1732 statusByte
= WaitOnBusyLong(chan
);
1733 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1735 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1736 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1737 GetBaseStatus(chan
, statusByte
);
1740 GetBaseStatus(chan
, statusByte
);
1741 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1745 j
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
1746 KdPrint3((PRINT_PREFIX
"IssueIdentify: iReason %x\n", j
));
1749 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
1752 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
1753 KdPrint3((PRINT_PREFIX
"IssueIdentify: wCount %x\n", j
));
1758 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1760 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1761 // ATI/SII chipsets with memory-mapped IO hangs when
1762 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1763 // Unfortunately, I don't know yet how to workaround it except
1764 // specifying manual delay in the way you see below.
1765 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1767 // Work around for some IDE and one model Atapi that will present more than
1768 // 256 bytes for the Identify data.
1769 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1770 statusByte
= AtapiSuckPort2(chan
);
1772 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1773 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1776 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1777 statusByte
= WaitForDrq(chan
);
1778 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1779 GetBaseStatus(chan
, statusByte
);
1781 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1784 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1788 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1789 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1790 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1791 if(g_opt_VirtualMachine
== VM_AUTO
) {
1792 if((deviceExtension
->FullIdentifyData
.FirmwareRevision
[0] == 0 ||
1793 deviceExtension
->FullIdentifyData
.FirmwareRevision
[0] == ' ') &&
1794 (deviceExtension
->FullIdentifyData
.FirmwareRevision
[1] == 0 ||
1795 deviceExtension
->FullIdentifyData
.FirmwareRevision
[1] == ' ')) {
1796 // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
1797 // are declared BOCHS looks like regular PC
1798 if (!atapiDev
&& !AtapiStringCmp ((PCCHAR
)(deviceExtension
->FullIdentifyData
.SerialNumber
), "XBDH00", 6)) {
1799 KdPrint2((PRINT_PREFIX
"IssueIdentify: BOCHS HDD\n"));
1800 g_opt_VirtualMachine
= VM_BOCHS
;
1802 if (atapiDev
&& !AtapiStringCmp ((PCCHAR
)(deviceExtension
->FullIdentifyData
.SerialNumber
), "XBDC00", 6)) {
1803 KdPrint2((PRINT_PREFIX
"IssueIdentify: BOCHS CD\n"));
1804 g_opt_VirtualMachine
= VM_BOCHS
;
1809 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1810 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1811 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1813 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1814 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1815 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1816 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1818 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1819 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1820 deviceExtension
->FullIdentifyData
.SataSupport
,
1821 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1823 LunExt
->LimitedTransferMode
=
1824 LunExt
->OrigTransferMode
=
1825 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1826 LunExt
->TransferMode
=
1827 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1829 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1830 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1831 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1832 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1834 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d\n",
1835 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1838 KdPrint2((PRINT_PREFIX
"PowerMngt %d/%d, APM %d/%d\n",
1839 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.PowerMngt
,
1840 deviceExtension
->FullIdentifyData
.FeaturesSupport
.PowerMngt
,
1841 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.APM
,
1842 deviceExtension
->FullIdentifyData
.FeaturesSupport
.APM
1845 // Check out a few capabilities / limitations of the device.
1846 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1847 // Determine if this drive supports the MSN functions.
1848 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1850 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1851 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1854 // AHCI doesn't recommend using PIO and multiblock
1855 LunExt
->MaximumBlockXfer
= 0;
1857 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1858 // Determine max. block transfer for this device.
1859 LunExt
->MaximumBlockXfer
=
1860 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1862 LunExt
->NumOfSectors
= 0;
1863 if (Command
== IDE_COMMAND_IDENTIFY
) {
1864 ULONGLONG NumOfSectors
=0;
1865 ULONGLONG NativeNumOfSectors
=0;
1866 ULONGLONG cylinders
=0;
1867 ULONGLONG tmp_cylinders
=0;
1869 KdPrint2((PRINT_PREFIX
"PhysLogSectorSize %#x, %#x, offset %#x\n",
1870 deviceExtension
->FullIdentifyData
.PhysLogSectorSize
,
1871 deviceExtension
->FullIdentifyData
.LargeSectorSize
,
1872 deviceExtension
->FullIdentifyData
.LogicalSectorOffset
1875 KdPrint2((PRINT_PREFIX
"NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1876 deviceExtension
->FullIdentifyData
.NVCache_PM_Supported
,
1877 deviceExtension
->FullIdentifyData
.NVCache_PM_Enabled
,
1878 deviceExtension
->FullIdentifyData
.NVCache_Enabled
,
1879 deviceExtension
->FullIdentifyData
.NVCache_PM_Version
,
1880 deviceExtension
->FullIdentifyData
.NVCache_Version
1883 KdPrint2((PRINT_PREFIX
"R-rate %d\n",
1884 deviceExtension
->FullIdentifyData
.NominalMediaRotationRate
1886 KdPrint2((PRINT_PREFIX
"WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
1887 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.WriteCache
,
1888 deviceExtension
->FullIdentifyData
.FeaturesSupport
.WriteCache
,
1889 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.LookAhead
,
1890 deviceExtension
->FullIdentifyData
.FeaturesSupport
.LookAhead
,
1891 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.WriteBuffer
,
1892 deviceExtension
->FullIdentifyData
.FeaturesSupport
.WriteBuffer
,
1893 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.ReadBuffer
,
1894 deviceExtension
->FullIdentifyData
.FeaturesSupport
.ReadBuffer
,
1895 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Queued
,
1896 deviceExtension
->FullIdentifyData
.FeaturesSupport
.Queued
1899 KdPrint2((PRINT_PREFIX
"Protected %d/%d status %#x, rev %#x\n",
1900 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Protected
,
1901 deviceExtension
->FullIdentifyData
.FeaturesSupport
.Protected
,
1902 deviceExtension
->FullIdentifyData
.SecurityStatus
,
1903 deviceExtension
->FullIdentifyData
.MasterPasswdRevision
1906 // Read very-old-style drive geometry
1907 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1908 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1909 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1910 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1912 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1913 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1914 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1915 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1916 // Check for HDDs > 8Gb
1917 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1918 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1919 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1920 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1922 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1923 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1924 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1926 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1928 NumOfSectors
= cylinders
*
1929 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1930 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1932 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1936 // Check for LBA mode
1937 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1938 KdPrint2((PRINT_PREFIX
"SupportDMA flag %#x\n", deviceExtension
->FullIdentifyData
.SupportDma
));
1939 KdPrint2((PRINT_PREFIX
"SoftReset %#x\n", deviceExtension
->FullIdentifyData
.SoftReset
));
1940 KdPrint2((PRINT_PREFIX
"SupportIordy %#x, DisableIordy %#x\n",
1941 deviceExtension
->FullIdentifyData
.SupportIordy
,
1942 deviceExtension
->FullIdentifyData
.DisableIordy
1944 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1945 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1946 if ( deviceExtension
->FullIdentifyData
.SupportLba
1948 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1949 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1950 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1951 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1952 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1954 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1955 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1956 goto skip_lba_staff
;
1958 // Check for LBA48 support
1959 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1960 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1961 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1962 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1964 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1966 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1967 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1968 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1970 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1972 NativeNumOfSectors
= cylinders
*
1973 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1974 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1976 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1978 if(NativeNumOfSectors
> NumOfSectors
) {
1979 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1980 NumOfSectors
= NativeNumOfSectors
;
1984 // Check drive capacity report for LBA48-capable drives.
1985 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1986 ULONG hNativeNumOfSectors
;
1987 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1989 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1990 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1992 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1994 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1996 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1997 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1998 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
2000 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
2003 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
2004 NativeNumOfSectors
|=
2005 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
2006 hNativeNumOfSectors
=
2007 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
2008 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
2009 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
2011 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
2013 // Some drives report LBA48 capability while has capacity below 128Gb
2014 // Probably they support large block-counters.
2015 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
2016 // Here we check this
2017 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
2018 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
2020 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
2021 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
2023 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2025 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
2027 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
2028 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
2029 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
2030 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
2031 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
2032 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
2037 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
2038 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
2039 NativeNumOfSectors
= 0;
2043 if(NumOfSectors
<= ATA_MAX_LBA28
&&
2044 NativeNumOfSectors
> NumOfSectors
) {
2046 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
2047 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
2049 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
2050 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
2051 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2052 NumOfSectors
= NativeNumOfSectors
;
2058 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
2059 // check for native LBA size
2060 // some drives report ~32Gb in Identify Block
2061 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
2063 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
2064 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
2066 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2068 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
2070 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
2071 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
2072 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
2073 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
2075 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
2077 if(NativeNumOfSectors
> NumOfSectors
) {
2079 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
2080 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
2082 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
2083 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
2084 if(!(statusByte
& IDE_STATUS_ERROR
)) {
2085 NumOfSectors
= NativeNumOfSectors
;
2091 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
2093 // fill IdentifyData with bogus geometry
2094 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
2095 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
2096 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
2097 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
2098 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
2099 // ok, we can keep original values
2100 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2101 LunExt
->opt_GeomType
= GEOM_ORIG
;
2104 tmp_cylinders
= NumOfSectors
/ (255*63);
2105 if(tmp_cylinders
< 0xffff) {
2106 // we can use generic values for H/S for generic geometry approach
2107 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2108 LunExt
->opt_GeomType
= GEOM_STD
;
2111 // we should use UNIATA geometry approach
2112 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2113 LunExt
->opt_GeomType
= GEOM_UNIATA
;
2118 if(LunExt
->opt_GeomType
== GEOM_STD
) {
2119 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
2120 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
2122 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
2123 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
2125 cylinders
= NumOfSectors
/ (255*63);
2126 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
2128 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
2129 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
2131 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
2132 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
2133 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
2135 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
2137 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
2138 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
2139 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
2141 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
2143 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
2144 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
2145 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
2147 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
2149 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
2150 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
2151 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
2153 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
2154 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
2155 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
2158 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
2159 cylinders
= tmp_cylinders
;
2161 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
2162 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
2166 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
2167 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
2168 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
2170 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
2171 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
2172 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
2174 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
2175 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
2176 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
2180 LunExt
->NumOfSectors
= NumOfSectors
;
2182 if(deviceExtension
->FullIdentifyData
.MajorRevision
&&
2183 deviceExtension
->FullIdentifyData
.DoubleWordIo
) {
2184 LunExt
->DeviceFlags
|= DFLAGS_DWORDIO_ENABLED
;
2185 KdPrint2((PRINT_PREFIX
"IssueIdentify: DWORDIO supported\n"));
2189 if(deviceExtension
->FullIdentifyData
.MajorRevision
&&
2190 deviceExtension
->FullIdentifyData
.DoubleWordIo
) {
2191 LunExt
->DeviceFlags
|= DFLAGS_DWORDIO_ENABLED
;
2192 KdPrint2((PRINT_PREFIX
"IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
2194 if(deviceExtension
->FullIdentifyData
.AtapiDMA
.DMADirRequired
) {
2195 KdPrint2((PRINT_PREFIX
"DMADirRequired.\n"));
2197 if(deviceExtension
->FullIdentifyData
.AtapiByteCount0
) {
2198 KdPrint2((PRINT_PREFIX
"AtapiByteCount0=%x\n", deviceExtension
->FullIdentifyData
.AtapiByteCount0
));
2202 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
2203 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
2205 InitBadBlocks(LunExt
);
2207 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
2208 (Command
!= IDE_COMMAND_IDENTIFY
)) {
2210 // This device interrupts with the assertion of DRQ after receiving
2211 // Atapi Packet Command
2212 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
2213 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2216 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2219 if(Command
!= IDE_COMMAND_IDENTIFY
) {
2221 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
2223 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
2224 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
2226 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
2227 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
2228 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
2229 // set CD default costs
2230 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
2231 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
2232 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
2233 statusByte
= WaitForDrq(chan
);
2235 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
2236 LunExt
->IdentifyData
.DeviceType
));
2238 KdPrint2((PRINT_PREFIX
"IssueIdentify: AtapiCmdSize %#x\n", deviceExtension
->FullIdentifyData
.AtapiCmdSize
));
2240 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
2243 GetBaseStatus(chan
, statusByte
);
2244 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
2247 } // end IssueIdentify()
2252 Routine Description:
2253 Set drive parameters using the IDENTIFY data.
2256 HwDeviceExtension - HBA miniport driver's adapter data storage
2257 DeviceNumber - Indicates which device.
2260 TRUE if all goes well.
2266 IN PVOID HwDeviceExtension
,
2267 IN ULONG DeviceNumber
,
2271 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2272 PIDENTIFY_DATA2 identifyData
;
2273 PHW_LU_EXTENSION LunExt
;
2278 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2279 identifyData
= &(LunExt
->IdentifyData
);
2281 if(LunExt
->DeviceFlags
&
2282 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2285 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2286 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2288 // Send SET PARAMETER command.
2289 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2290 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2291 (identifyData
->NumberOfHeads
- 1), 0,
2292 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2294 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2295 if(statusByte
& IDE_STATUS_ERROR
) {
2296 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2297 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2298 errorByte
, statusByte
));
2302 if(statusByte
== IDE_STATUS_IDLE
) {
2308 } // end SetDriveParameters()
2313 PHW_LU_EXTENSION LunExt
2316 // keep only DFLAGS_HIDDEN flag
2317 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2318 LunExt
->AtapiReadyWaitDelay
= 0;
2319 } // end UniataForgetDevice()
2324 Routine Description:
2325 Reset IDE controller and/or Atapi device.
2329 HwDeviceExtension - HBA miniport driver's adapter data storage
2338 AtapiResetController(
2339 IN PVOID HwDeviceExtension
,
2343 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2344 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2345 } // end AtapiResetController()
2349 AtapiResetController__(
2350 IN PVOID HwDeviceExtension
,
2352 IN BOOLEAN CompleteType
2355 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2356 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2357 PHW_CHANNEL chan
= NULL
;
2361 PSCSI_REQUEST_BLOCK CurSrb
;
2362 ULONG ChannelCtrlFlags
;
2363 UCHAR dma_status
= 0;
2365 ULONG slotNumber
= deviceExtension
->slotNumber
;
2366 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2367 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2369 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2371 //ULONG RevID = deviceExtension->RevID;
2372 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2376 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2377 KdPrint2((PRINT_PREFIX
"simplexOnly %d, VM %x\n", deviceExtension
->simplexOnly
, g_opt_VirtualMachine
));
2379 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2380 // we shall reset both channels on SimplexOnly devices,
2381 // It's not worth doing so on normal controllers
2383 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2386 numberChannels
= deviceExtension
->NumberChannels
;
2389 for (; j
< numberChannels
; j
++) {
2391 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset lchannel %d[%d]\n", j
, deviceExtension
->Channel
));
2392 chan
= &(deviceExtension
->chan
[j
]);
2393 MaxLuns
= chan
->NumberLuns
;
2394 // Save control flags
2395 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2396 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType
, MaxLuns
, chan
, &chan
, ChannelCtrlFlags
));
2397 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2398 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2400 while((CurSrb
= UniataGetCurRequest(chan
))) {
2402 PHW_LU_EXTENSION LunExt
;
2403 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2405 i
= GET_CDEV(CurSrb
);
2406 KdPrint2((PRINT_PREFIX
" Lun %x\n", i
));
2407 LunExt
= chan
->lun
[i
];
2409 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2410 if(CurSrb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
2411 KdPrint2((PRINT_PREFIX
" was MechStatus\n"));
2413 if(!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)) {
2414 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
2415 KdPrint2((PRINT_PREFIX
" set DFLAGS_CHANGER_INITED\n"));
2418 // Check and see if we are processing an internal srb
2419 if (AtaReq
->OriginalSrb
) {
2420 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2421 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2422 CurSrb
->SrbExtension
= NULL
;
2423 AtaReq
->OriginalSrb
= NULL
;
2424 // NOTE: internal SRB doesn't get to SRB queue !!!
2425 CurSrb
= AtaReq
->Srb
;
2428 // Remove current request from queue
2429 UniataRemoveRequest(chan
, CurSrb
);
2431 // Check if request is in progress.
2432 ASSERT(AtaReq
->Srb
== CurSrb
);
2434 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2435 UCHAR CurPathId
= CurSrb
->PathId
;
2436 UCHAR TargetId
= CurSrb
->TargetId
;
2437 UCHAR Lun
= CurSrb
->Lun
;
2439 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2440 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2442 if (CurSrb
->SenseInfoBuffer
) {
2444 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2445 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer
, chan
, AtaReq
->Flags
));
2447 senseBuffer
->ErrorCode
= 0x70;
2448 senseBuffer
->Valid
= 1;
2449 senseBuffer
->AdditionalSenseLength
= 0xb;
2450 if(CompleteType
== RESET_COMPLETE_ALL
) {
2451 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2452 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2453 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2454 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2456 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2457 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2458 senseBuffer
->AdditionalSenseCode
= 0;
2459 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2463 if(!ATAPI_DEVICE(chan
, i
) && AtaReq
->bcount
&& AtaReq
->retry
< MAX_RETRIES
) {
2464 KdPrint2((PRINT_PREFIX
"Save IDE retry status %d\n", AtaReq
->retry
));
2465 LunExt
->errLastLba
= AtaReq
->lba
;
2466 LunExt
->errBCount
= AtaReq
->bcount
;
2467 LunExt
->errRetry
= AtaReq
->retry
+1;
2468 //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ));
2469 //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION));
2470 //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS));
2471 if(((AtaReq
->Flags
& REQ_FLAG_RW_MASK
) == REQ_FLAG_READ
) &&
2472 (ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) &&
2473 (g_opt_VirtualMachine
== VM_BOCHS
)) {
2474 KdPrint2((PRINT_PREFIX
"set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
2475 g_opt_BochsDmaReadWorkaround
= TRUE
;
2476 g_opt_AtapiNoDma
= TRUE
;
2478 KdPrint2((PRINT_PREFIX
"do nothing\n"));
2481 if(ATAPI_DEVICE(chan
, i
) && AtaReq
->bcount
&& !AtaReq
->retry
) {
2482 KdPrint2((PRINT_PREFIX
"Save ATAPI retry status %d\n", AtaReq
->retry
));
2483 LunExt
->errLastLba
= AtaReq
->lba
;
2484 LunExt
->errBCount
= AtaReq
->bcount
;
2485 LunExt
->errRetry
= AtaReq
->retry
+1;
2486 if(((AtaReq
->Flags
& REQ_FLAG_RW_MASK
) == REQ_FLAG_READ
) &&
2487 (ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) &&
2488 (g_opt_VirtualMachine
== VM_BOCHS
)) {
2489 KdPrint2((PRINT_PREFIX
"set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
2490 //g_opt_BochsDmaReadWorkaround = TRUE;
2491 g_opt_AtapiNoDma
= TRUE
;
2493 KdPrint2((PRINT_PREFIX
"do nothing\n"));
2496 LunExt
->errRetry
= 0;
2499 // Clear request tracking fields.
2500 AtaReq
->WordsLeft
= 0;
2501 AtaReq
->DataBuffer
= NULL
;
2502 AtaReq
->TransferLength
= 0;
2503 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2505 ScsiPortNotification(RequestComplete
,
2509 // Indicate ready for next request.
2510 ScsiPortNotification(NextLuRequest
,
2516 if(CompleteType
!= RESET_COMPLETE_ALL
)
2519 #endif //UNIATA_CORE
2520 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2522 // Clear expecting interrupt flag.
2523 UniataExpectChannelInterrupt(chan
, FALSE
);
2525 chan
->ChannelCtrlFlags
= ChannelCtrlFlags
& CTRFLAGS_PERMANENT
;
2526 InterlockedExchange(&(chan
->CheckIntr
),
2529 for (i
= 0; i
< MaxLuns
; i
++) {
2530 chan
->lun
[i
]->PowerState
= 0;
2533 if(ChipFlags
& UNIATA_AHCI
) {
2534 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2535 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2537 UniataDumpAhciPortRegs(chan
);
2539 AtapiDisableInterrupts(deviceExtension
, j
);
2540 UniataAhciReset(HwDeviceExtension
, j
);
2542 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2546 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2547 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2548 AtapiDisableInterrupts(deviceExtension
, j
);
2549 KdPrint2((PRINT_PREFIX
" done\n"));
2551 case ATA_INTEL_ID
: {
2555 if(!(ChipFlags
& UNIATA_SATA
)) {
2558 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2563 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2564 if(ChipFlags
& UNIATA_AHCI
) {
2567 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2568 GetPciConfig1(0x90, tmp8
);
2576 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2578 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2581 ChangePciConfig2(0x92, a
& ~mask
);
2582 AtapiStallExecution(10);
2583 ChangePciConfig2(0x92, a
| mask
);
2586 /* Wait up to 1 sec for "connect well". */
2587 if (ChipFlags
& (I6CH
| I6CH2
)) {
2593 GetPciConfig2(0x92, tmp16
);
2594 if (((tmp16
>> pshift
) & mask
) == mask
) {
2595 GetBaseStatus(chan
, statusByte
);
2596 if(statusByte
!= IDE_STATUS_WRONG
) {
2600 AtapiStallExecution(10000);
2604 KdPrint2((PRINT_PREFIX
" SIS\n"));
2605 if(!(ChipFlags
& UNIATA_SATA
))
2609 case ATA_NVIDIA_ID
: {
2610 KdPrint2((PRINT_PREFIX
" nVidia\n"));
2611 if(!(ChipFlags
& UNIATA_SATA
))
2615 case ATA_NVIDIA_ID
: {
2617 ULONG Channel
= deviceExtension
->Channel
+ j
;
2618 KdPrint2((PRINT_PREFIX
" nVidia\n"));
2619 if(!(ChipFlags
& UNIATA_SATA
)) {
2622 offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
2624 KdPrint2((PRINT_PREFIX
" disable Phy intr, offs %#x, c %u\n", offs
, Channel
));
2625 /* disable device and PHY state change interrupts */
2626 if(ChipFlags
& NVQ
) {
2627 KdPrint2((PRINT_PREFIX
" NVQ, 32bits reg\n"));
2628 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2629 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) & ((~(ULONG
)0x0000000d) << (!Channel
*16)) );
2631 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2632 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) & ((~(UCHAR
)0x0d) << (!Channel
*4)) );
2634 tmp16
= UniataSataPhyEnable(HwDeviceExtension
, j
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
);
2636 KdPrint2((PRINT_PREFIX
" enable Phy intr, offs %#x\n", offs
));
2637 /* enable device and PHY state change interrupts */
2638 if(ChipFlags
& NVQ
) {
2639 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2640 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) | (((ULONG
)0x0000000d) << (!Channel
*16)) );
2642 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2643 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) | (((UCHAR
)0x0d) << (!Channel
*4)) );
2646 KdPrint2((PRINT_PREFIX
" dev status %#x\n", tmp16
));
2647 if(tmp16
!= IDE_STATUS_WRONG
) {
2652 case ATA_SILICON_IMAGE_ID
: {
2654 ULONG Channel
= deviceExtension
->Channel
+ j
;
2655 if(!(ChipFlags
& UNIATA_SATA
))
2657 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2658 /* disable PHY state change interrupt */
2659 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2661 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2663 /* reset controller part for this channel */
2664 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2665 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2666 AtapiStallExecution(1000);
2667 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2668 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2672 case ATA_PROMISE_ID
: {
2675 if(ChipFlags
& UNIATA_SATA
) {
2676 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2677 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2681 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2682 IDE_DC_RESET_CONTROLLER );
2683 chan->last_devsel = -1;
2684 KdPrint2((PRINT_PREFIX " wait a little\n"));
2685 AtapiStallExecution(10000);
2686 // Disable interrupts
2687 KdPrint2((PRINT_PREFIX " disable intr\n"));
2688 AtapiDisableInterrupts(deviceExtension, j);
2689 AtapiStallExecution(100);
2690 KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2691 AtapiEnableInterrupts(deviceExtension, j);
2692 KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
2693 AtapiStallExecution(100000);
2695 AtapiHardReset(chan
, TRUE
, 100000);
2696 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2697 AtapiDisableInterrupts(deviceExtension
, j
);
2698 AtapiStallExecution(100);
2699 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2700 AtapiEnableInterrupts(deviceExtension
, j
);
2701 KdPrint2((PRINT_PREFIX
" done\n"));
2706 //if(!(ChipFlags & UNIATA_SATA)) {}
2707 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2708 // Reset DMA engine if active
2709 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2710 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2711 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2712 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2713 (dma_status
& BM_STATUS_INTR
)) {
2714 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2719 // all these shall be performed inside AtapiHwInitialize__() ?
2721 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2722 // Do special processing for ATAPI and IDE disk devices.
2723 for (i
= 0; i
< MaxLuns
; i
++) {
2725 // Check if device present.
2726 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2727 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2728 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2729 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2730 if(ChipFlags
& UNIATA_AHCI
) {
2731 // everything is done in UniataAhciReset()
2732 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2738 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2739 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2742 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2746 if(ChipFlags
& UNIATA_AHCI
) {
2747 // everything is done in UniataAhciReset()
2748 KdPrint2((PRINT_PREFIX
" found some device\n"));
2750 if(!IssueIdentify(HwDeviceExtension
,
2752 ATAPI_DEVICE(chan
, i
) ?
2753 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2755 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2756 UniataForgetDevice(chan
->lun
[i
]);
2760 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2761 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2762 UniataForgetDevice(chan
->lun
[i
]);
2767 SelectDrive(chan
, i
);
2768 AtapiStallExecution(10);
2769 statusByte
= WaitOnBusyLong(chan
);
2770 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2771 if(statusByte
== IDE_STATUS_WRONG
) {
2772 KdPrint2((PRINT_PREFIX
2773 "no drive, status %#x\n",
2775 UniataForgetDevice(chan
->lun
[i
]);
2777 // Check for ATAPI disk.
2778 if (ATAPI_DEVICE(chan
, i
)) {
2779 // Issue soft reset and issue identify.
2780 GetStatus(chan
, statusByte
);
2781 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2784 AtapiDisableInterrupts(deviceExtension
, j
);
2785 AtapiSoftReset(chan
, i
);
2786 AtapiEnableInterrupts(deviceExtension
, j
);
2788 GetStatus(chan
, statusByte
);
2790 if(statusByte
!= IDE_STATUS_SUCCESS
) {
2792 k
= UniataAnybodyHome(deviceExtension
, j
, i
);
2793 if(k
== ATA_AT_HOME_HDD
) {
2794 // device reset in progress, perform additional wait
2795 KdPrint2((PRINT_PREFIX
" long reset, wait up to 4.5 s\n"));
2797 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
2800 AtapiStallExecution(150);
2802 KdPrint2((PRINT_PREFIX
" exit after %u loops\n", k
));
2803 GetStatus(chan
, statusByte
);
2806 if(statusByte
== IDE_STATUS_SUCCESS
) {
2808 IssueIdentify(HwDeviceExtension
,
2810 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2813 KdPrint2((PRINT_PREFIX
2814 "AtapiResetController: Status after soft reset %#x\n",
2817 GetBaseStatus(chan
, statusByte
);
2820 // Issue identify and reinit after channel reset.
2822 if (statusByte
!= IDE_STATUS_IDLE
&&
2823 statusByte
!= IDE_STATUS_SUCCESS
&&
2824 statusByte
!= IDE_STATUS_DRDY
) {
2826 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2828 if(!IssueIdentify(HwDeviceExtension
,
2830 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2832 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2834 // Set disk geometry parameters.
2835 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2836 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2838 GetBaseStatus(chan
, statusByte
);
2840 // force DMA mode reinit
2841 KdPrint2((PRINT_PREFIX
" set DFLAGS_REINIT_DMA\n"));
2842 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2846 // Enable interrupts, note, we can have here recursive disable
2847 AtapiStallExecution(10);
2848 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2850 chan
->DisableIntr
));
2851 AtapiEnableInterrupts(deviceExtension
, j
);
2853 // Call the HwInitialize routine to setup multi-block.
2854 AtapiHwInitialize__(deviceExtension
, j
);
2856 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2860 } // end AtapiResetController__()
2865 Routine Description:
2866 This routine maps ATAPI and IDE errors to specific SRB statuses.
2869 HwDeviceExtension - HBA miniport driver's adapter data storage
2870 Srb - IO request packet
2879 IN PVOID HwDeviceExtension
,
2880 IN PSCSI_REQUEST_BLOCK Srb
2883 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2884 ULONG lChannel
= GET_CHANNEL(Srb
);
2885 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2887 UCHAR errorByte
= 0;
2888 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2890 ULONG DeviceNumber
= GET_CDEV(Srb
);
2891 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2893 // Read the error register.
2895 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2896 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2898 errorByte
= AtaReq
->ahci
.in_error
;
2902 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2904 KdPrint2((PRINT_PREFIX
2905 "MapError: Error register is %#x\n",
2908 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2910 switch (errorByte
>> 4) {
2911 case SCSI_SENSE_NO_SENSE
:
2913 KdPrint2((PRINT_PREFIX
2914 "ATAPI: No sense information\n"));
2915 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2916 srbStatus
= SRB_STATUS_ERROR
;
2919 case SCSI_SENSE_RECOVERED_ERROR
:
2921 KdPrint2((PRINT_PREFIX
2922 "ATAPI: Recovered error\n"));
2924 srbStatus
= SRB_STATUS_SUCCESS
;
2927 case SCSI_SENSE_NOT_READY
:
2929 KdPrint2((PRINT_PREFIX
2930 "ATAPI: Device not ready\n"));
2931 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2932 srbStatus
= SRB_STATUS_ERROR
;
2935 case SCSI_SENSE_MEDIUM_ERROR
:
2937 KdPrint2((PRINT_PREFIX
2938 "ATAPI: Media error\n"));
2939 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2940 srbStatus
= SRB_STATUS_ERROR
;
2943 case SCSI_SENSE_HARDWARE_ERROR
:
2945 KdPrint2((PRINT_PREFIX
2946 "ATAPI: Hardware error\n"));
2947 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2948 srbStatus
= SRB_STATUS_ERROR
;
2951 case SCSI_SENSE_ILLEGAL_REQUEST
:
2953 KdPrint2((PRINT_PREFIX
2954 "ATAPI: Illegal request\n"));
2955 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2956 srbStatus
= SRB_STATUS_ERROR
;
2959 case SCSI_SENSE_UNIT_ATTENTION
:
2961 KdPrint2((PRINT_PREFIX
2962 "ATAPI: Unit attention\n"));
2963 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2964 srbStatus
= SRB_STATUS_ERROR
;
2967 case SCSI_SENSE_DATA_PROTECT
:
2969 KdPrint2((PRINT_PREFIX
2970 "ATAPI: Data protect\n"));
2971 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2972 srbStatus
= SRB_STATUS_ERROR
;
2975 case SCSI_SENSE_BLANK_CHECK
:
2977 KdPrint2((PRINT_PREFIX
2978 "ATAPI: Blank check\n"));
2979 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2980 srbStatus
= SRB_STATUS_ERROR
;
2983 case SCSI_SENSE_ABORTED_COMMAND
:
2984 KdPrint2((PRINT_PREFIX
2985 "Atapi: Command Aborted\n"));
2986 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2987 srbStatus
= SRB_STATUS_ERROR
;
2992 KdPrint2((PRINT_PREFIX
2993 "ATAPI: Invalid sense information\n"));
2995 srbStatus
= SRB_STATUS_ERROR
;
3003 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
3004 chan
->ReturningMediaStatus
= errorByte
;
3006 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
3007 KdPrint2((PRINT_PREFIX
3008 "IDE: Media change\n"));
3009 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3010 srbStatus
= SRB_STATUS_ERROR
;
3012 if (Srb
->SenseInfoBuffer
) {
3014 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3016 senseBuffer
->ErrorCode
= 0x70;
3017 senseBuffer
->Valid
= 1;
3018 senseBuffer
->AdditionalSenseLength
= 0xb;
3019 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
3020 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
3021 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3023 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3026 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
3027 KdPrint2((PRINT_PREFIX
3028 "IDE: Command abort\n"));
3029 srbStatus
= SRB_STATUS_ABORTED
;
3030 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3032 if (Srb
->SenseInfoBuffer
) {
3034 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3036 senseBuffer
->ErrorCode
= 0x70;
3037 senseBuffer
->Valid
= 1;
3038 senseBuffer
->AdditionalSenseLength
= 0xb;
3039 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
3040 senseBuffer
->AdditionalSenseCode
= 0;
3041 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3043 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3046 LunExt
->ErrorCount
++;
3048 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
3050 KdPrint2((PRINT_PREFIX
3051 "IDE: End of media\n"));
3052 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3053 srbStatus
= SRB_STATUS_ERROR
;
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_UNIT_ATTENTION
;
3063 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
3064 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
3065 senseBuffer
->EndOfMedia
= 1;
3067 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3070 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
3071 LunExt
->ErrorCount
++;
3074 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
3076 KdPrint2((PRINT_PREFIX
3077 "IDE: Illegal length\n"));
3078 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
3080 if (Srb
->SenseInfoBuffer
) {
3082 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3084 senseBuffer
->ErrorCode
= 0x70;
3085 senseBuffer
->Valid
= 1;
3086 senseBuffer
->AdditionalSenseLength
= 0xb;
3087 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
3088 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
3089 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
3090 senseBuffer
->IncorrectLength
= 1;
3092 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3095 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
3097 KdPrint2((PRINT_PREFIX
3098 "IDE: Bad block\n"));
3099 srbStatus
= SRB_STATUS_ERROR
;
3100 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3101 if (Srb
->SenseInfoBuffer
) {
3103 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3105 senseBuffer
->ErrorCode
= 0x70;
3106 senseBuffer
->Valid
= 1;
3107 senseBuffer
->AdditionalSenseLength
= 0xb;
3108 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3109 senseBuffer
->AdditionalSenseCode
= 0;
3110 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3112 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3115 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
3117 KdPrint2((PRINT_PREFIX
3118 "IDE: Id not found\n"));
3119 srbStatus
= SRB_STATUS_ERROR
;
3120 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3122 if (Srb
->SenseInfoBuffer
) {
3124 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3126 senseBuffer
->ErrorCode
= 0x70;
3127 senseBuffer
->Valid
= 1;
3128 senseBuffer
->AdditionalSenseLength
= 0xb;
3129 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3130 senseBuffer
->AdditionalSenseCode
= 0;
3131 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3133 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3136 LunExt
->ErrorCount
++;
3138 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
3140 KdPrint2((PRINT_PREFIX
3141 "IDE: Media change\n"));
3142 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3143 srbStatus
= SRB_STATUS_ERROR
;
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_UNIT_ATTENTION
;
3153 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
3154 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3156 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3159 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
3161 KdPrint2((PRINT_PREFIX
3162 "IDE: Data error\n"));
3163 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3164 srbStatus
= SRB_STATUS_ERROR
;
3166 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
3167 LunExt
->ErrorCount
++;
3170 // Build sense buffer
3171 if (Srb
->SenseInfoBuffer
) {
3173 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3175 senseBuffer
->ErrorCode
= 0x70;
3176 senseBuffer
->Valid
= 1;
3177 senseBuffer
->AdditionalSenseLength
= 0xb;
3178 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3179 senseBuffer
->AdditionalSenseCode
= 0;
3180 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3182 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3186 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
3187 // deviceExtension->DWordIO = FALSE;
3189 KdPrint2((PRINT_PREFIX
3190 "MapError: ErrorCount >= MAX_ERRORS\n"));
3192 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
3193 LunExt
->MaximumBlockXfer
= 0;
3196 KdPrint2((PRINT_PREFIX
3197 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
3200 KdPrint2((PRINT_PREFIX
3201 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
3210 ScsiPortLogError( HwDeviceExtension
,
3218 // Reprogram to not use Multi-sector.
3221 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
3222 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3224 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
3226 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3227 // command was aborted.
3228 if (statusByte
& IDE_STATUS_ERROR
) {
3230 // Read the error register.
3231 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3233 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3237 // Adjust the devExt. value, if necessary.
3238 LunExt
->MaximumBlockXfer
= 0;
3246 // Set SCSI status to indicate a check condition.
3247 Srb
->ScsiStatus
= scsiStatus
;
3256 Routine Description:
3259 HwDeviceExtension - HBA miniport driver's adapter data storage
3263 TRUE - if initialization successful.
3264 FALSE - if initialization unsuccessful.
3270 IN PVOID HwDeviceExtension
3273 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3274 ULONG numberChannels
= deviceExtension
->NumberChannels
;
3277 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
3279 if(WinVer_WDM_Model
) {
3280 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
3282 if(deviceExtension
->MasterDev
) {
3283 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
3284 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
3285 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
3288 /* do extra chipset specific setups */
3289 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
3291 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3292 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3293 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3296 for (c
= 0; c
< numberChannels
; c
++) {
3297 AtapiHwInitialize__(deviceExtension
, c
);
3299 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
3301 } // end AtapiHwInitialize()
3305 AtapiHwInitialize__(
3306 IN PHW_DEVICE_EXTENSION deviceExtension
,
3311 UCHAR statusByte
, errorByte
;
3312 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3313 PHW_LU_EXTENSION LunExt
;
3315 ULONG PreferedMode
= 0xffffffff;
3317 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3318 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
3322 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
3323 FindDevices(deviceExtension
, 0, lChannel
);
3325 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
3327 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
3329 LunExt
= chan
->lun
[i
];
3331 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
3335 AtapiDisableInterrupts(deviceExtension
, lChannel
);
3336 AtapiStallExecution(1);
3338 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3340 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
3341 // Enable media status notification
3342 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
3344 // If supported, setup Multi-block transfers.
3345 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3346 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3347 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
3349 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3350 // command was aborted.
3351 if (statusByte
& IDE_STATUS_ERROR
) {
3353 // Read the error register.
3354 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3356 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3360 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3361 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3362 0, 0, ATA_WAIT_BASE_READY
);
3364 if (statusByte
& IDE_STATUS_ERROR
) {
3365 // Read the error register.
3366 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3368 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3372 // Adjust the devExt. value, if necessary.
3373 LunExt
->MaximumBlockXfer
= 0;
3376 KdPrint2((PRINT_PREFIX
3377 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3379 LunExt
->MaximumBlockXfer
));
3382 if(LunExt
->IdentifyData
.MajorRevision
) {
3384 if(LunExt
->opt_ReadCacheEnable
) {
3385 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3386 // If supported, setup read/write cacheing
3387 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3388 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3389 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3391 // Check for errors.
3392 if (statusByte
& IDE_STATUS_ERROR
) {
3393 KdPrint2((PRINT_PREFIX
3394 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3396 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3398 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3401 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3402 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3403 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3404 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3405 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3407 if(LunExt
->IdentifyData
.FeaturesSupport
.WriteCache
) {
3408 if(LunExt
->opt_WriteCacheEnable
) {
3409 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3410 // If supported & allowed, setup write cacheing
3411 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3412 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3413 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3414 // Check for errors.
3415 if (statusByte
& IDE_STATUS_ERROR
) {
3416 KdPrint2((PRINT_PREFIX
3417 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3419 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3421 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3424 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3425 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3426 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3427 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3428 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3432 if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/
3433 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3435 if(LunExt
->opt_AdvPowerMode
) {
3436 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3438 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3439 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3440 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3441 // Check for errors.
3442 if (statusByte
& IDE_STATUS_ERROR
) {
3443 KdPrint2((PRINT_PREFIX
3444 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3448 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3449 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3450 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3451 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3454 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3455 if(LunExt
->opt_AcousticMode
) {
3456 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3457 // setup acoustic mgmt
3458 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3459 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3460 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3461 // Check for errors.
3462 if (statusByte
& IDE_STATUS_ERROR
) {
3463 KdPrint2((PRINT_PREFIX
3464 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3468 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3469 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3470 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3471 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3474 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3475 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3476 // setup standby timer
3477 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3478 IDE_COMMAND_IDLE
, 0, 0, 0,
3479 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3480 // Check for errors.
3481 if (statusByte
& IDE_STATUS_ERROR
) {
3482 KdPrint2((PRINT_PREFIX
3483 "AtapiHwInitialize: standby timer on Device %d failed\n",
3489 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3492 //BOOLEAN isSanyo = FALSE;
3495 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3497 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3498 for (j
= 0; j
< 26; j
+= 2) {
3500 // Build a buffer based on the identify data.
3501 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3504 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3506 // Inquiry string for older model had a '-', newer is '_'
3507 if (vendorId
[12] == 'C') {
3509 // Torisan changer. Set the bit. This will be used in several places
3510 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3511 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3512 LunExt
->DiscsPresent
= 3;
3518 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3519 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3520 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3521 PreferedMode
= chan
->MaxTransferMode
;
3524 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3525 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3526 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3529 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3530 LunExt
->LimitedTransferMode
=
3531 LunExt
->TransferMode
=
3534 AtapiDmaInit__(deviceExtension
, LunExt
);
3536 LunExt
->LimitedTransferMode
=
3537 LunExt
->TransferMode
;
3538 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3540 // We need to get our device ready for action before
3541 // returning from this function
3543 // According to the atapi spec 2.5 or 2.6, an atapi device
3544 // clears its status BSY bit when it is ready for atapi commands.
3545 // However, some devices (Panasonic SQ-TC500N) are still
3546 // not ready even when the status BSY is clear. They don't react
3547 // to atapi commands.
3549 // Since there is really no other indication that tells us
3550 // the drive is really ready for action. We are going to check BSY
3551 // is clear and then just wait for an arbitrary amount of time!
3553 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3556 // have to get out of the loop sometime!
3557 // 10000 * 100us = 1000,000us = 1000ms = 1s
3559 GetStatus(chan
, statusByte
);
3560 if(statusByte
== IDE_STATUS_WRONG
) {
3563 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3565 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3566 // Wait for Busy to drop.
3567 AtapiStallExecution(100);
3568 GetStatus(chan
, statusByte
);
3572 // 5000 * 100us = 500,000us = 500ms = 0.5s
3573 if(statusByte
!= IDE_STATUS_WRONG
) {
3576 AtapiStallExecution(100);
3577 } while (waitCount
--);
3580 GetBaseStatus(chan
, statusByte
);
3581 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3582 AtapiStallExecution(10);
3587 } // end AtapiHwInitialize__()
3594 AtapiHwInitializeChanger(
3595 IN PVOID HwDeviceExtension
,
3596 IN PSCSI_REQUEST_BLOCK Srb
,
3597 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3599 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3600 ULONG lChannel
= GET_CHANNEL(Srb
);
3601 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3602 ULONG DeviceNumber
= GET_CDEV(Srb
);
3603 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3605 if (MechanismStatus
) {
3606 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3607 if (LunExt
->DiscsPresent
> 1) {
3608 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3612 } // end AtapiHwInitializeChanger()
3617 Routine Description:
3618 This routine will parse the string for a match on the keyword, then
3619 calculate the value for the keyword and return it to the caller.
3622 String - The ASCII string to parse.
3623 KeyWord - The keyword for the value desired.
3626 Zero if value not found
3627 Value converted from ASCII to binary.
3632 AtapiParseArgumentString(
3640 ULONG stringLength
= 0;
3641 ULONG keyWordLength
= 0;
3651 // Calculate the string length and lower case all characters.
3657 // Calculate the keyword length.
3663 if (keyWordLength
> stringLength
) {
3665 // Can't possibly have a match.
3669 // Now setup and start the compare.
3674 // The input string may start with white space. Skip it.
3675 while (*cptr
== ' ' || *cptr
== '\t') {
3679 if (*cptr
== '\0') {
3685 while ((*cptr
== *kptr
) ||
3686 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3687 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3691 if (*cptr
== '\0') {
3697 if (*kptr
== '\0') {
3699 // May have a match backup and check for blank or equals.
3700 while (*cptr
== ' ' || *cptr
== '\t') {
3704 // Found a match. Make sure there is an equals.
3707 // Not a match so move to the next semicolon.
3709 if (*cptr
++ == ';') {
3710 goto ContinueSearch
;
3715 // Skip the equals sign.
3718 // Skip white space.
3719 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3723 if (*cptr
== '\0') {
3724 // Early end of string, return not found
3729 // This isn't it either.
3731 goto ContinueSearch
;
3735 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3736 // Value is in Hex. Skip the "0x"
3738 for (index
= 0; *(cptr
+ index
); index
++) {
3740 if (*(cptr
+ index
) == ' ' ||
3741 *(cptr
+ index
) == '\t' ||
3742 *(cptr
+ index
) == ';') {
3746 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3747 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3749 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3750 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3751 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3752 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3754 // Syntax error, return not found.
3761 // Value is in Decimal.
3762 for (index
= 0; *(cptr
+ index
); index
++) {
3764 if (*(cptr
+ index
) == ' ' ||
3765 *(cptr
+ index
) == '\t' ||
3766 *(cptr
+ index
) == ';') {
3770 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3771 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3774 // Syntax error return not found.
3783 // Not a match check for ';' to continue search.
3785 if (*cptr
++ == ';') {
3786 goto ContinueSearch
;
3792 } // end AtapiParseArgumentString()_
3800 IN PVOID HwDeviceExtension
,
3805 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3806 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3809 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3812 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3813 // If the last command was DSC restrictive, see if it's set. If so, the device is
3814 // ready for a new request. Otherwise, reset the timer and come back to here later.
3816 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3817 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3818 // we shall have no problem with interrupt handler.
3819 if (!srb
|| chan
->ExpectingInterrupt
) {
3820 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3821 chan
->DpcState
= DPC_STATE_TIMER
;
3822 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3823 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3824 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3826 goto ReturnCallback
;
3830 if (!IS_RDP((srb
->Cdb
[0]))) {
3831 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3835 goto ReturnEnableIntr
;
3837 GetStatus(chan
, statusByte
);
3838 if (statusByte
& IDE_STATUS_DSC
) {
3840 UCHAR PathId
= srb
->PathId
;
3841 UCHAR TargetId
= srb
->TargetId
;
3842 UCHAR Lun
= srb
->Lun
;
3844 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3845 AtapiDmaDBSync(chan
, srb
);
3846 UniataRemoveRequest(chan
, srb
);
3847 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3848 // Clear current SRB.
3849 if(!deviceExtension
->simplexOnly
) {
3850 srb
= UniataGetCurRequest(chan
);
3856 // Ask for next request.
3857 ScsiPortNotification(NextLuRequest
,
3862 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3865 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3869 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3872 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3876 goto ReturnCallback
;
3881 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3882 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3883 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3884 #ifdef UNIATA_USE_XXableInterrupts
3885 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3886 // must be called on DISPATCH_LEVEL
3887 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3888 AtapiEnableInterrupts__
);
3890 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3891 InterlockedExchange(&(chan
->CheckIntr
),
3893 // Will raise IRQL to DIRQL
3894 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3895 AtapiEnableInterrupts__
,
3897 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3898 #endif // UNIATA_USE_XXableInterrupts
3900 //ASSERT(!deviceExtension->simplexOnly);
3905 // Check other channel
3906 // In simplex mode no interrupts must appear on other channels
3907 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3908 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3914 chan
= &(deviceExtension
->chan
[c
]);
3916 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3917 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3918 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3920 //ASSERT(!deviceExtension->simplexOnly);
3921 chan
->DpcState
= DPC_STATE_ISR
;
3922 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3923 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3927 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3930 } // end AtapiCallBack__()
3935 IN PVOID HwDeviceExtension
3938 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3939 } // end AtapiCallBack_X()
3941 #endif //UNIATA_CORE
3945 Routine Description:
3947 This is the interrupt service routine for ATAPI IDE miniport driver.
3951 HwDeviceExtension - HBA miniport driver's adapter data storage
3955 TRUE if expecting an interrupt.
3961 IN PVOID HwDeviceExtension
3964 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3966 BOOLEAN status
= FALSE
;
3970 //BOOLEAN checked[AHCI_MAX_PORT];
3974 KdPrint2((PRINT_PREFIX
"Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
3975 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3977 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3978 // AHCI may generate state change notification, never skip this check
3979 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3980 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3984 // assume all non-interrupted ports to be already checked
3986 // assume all not implemented ports to be already checked
3987 checked
|= ~deviceExtension
->AHCI_PI
;
3989 checked
= 0; // assume all ports are not checked
3992 if(!deviceExtension
->ExpectingInterrupt
) {
3993 // if we do not expect interrupt, exit now,
3994 // but keep in mind that it can be unexpected one
3995 // Note: this is just a hint, not exact counter
3996 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3997 //deviceExtension->ExpectingInterrupt++;
4000 // clear this flag now, it can be set again in sub-calls
4001 deviceExtension
->ExpectingInterrupt
=0;
4004 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4005 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
4009 for(pass
=0; pass
<2; pass
++) {
4010 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
4011 if(status
&& pass
) {
4012 // we catched some expected interrupts now.
4013 // do not touch unexpected until next ISR call
4016 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
4018 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
4020 if((checked
>>c
) & 0x01)
4023 // check non-empty and expecting interrupt channels first
4024 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
4027 checked
|= (ULONG
)1 << c
;
4029 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
4031 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
4032 // we get here on idle channels or when ISR is posted to DPC
4033 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
4036 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
4038 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
4039 // c_state = deviceExtension->chan[c].CheckIntr;
4040 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
4041 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
4044 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4045 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4046 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
4047 if(c_state
== CHECK_INTR_IDLE
) {
4048 // c_state = deviceExtension->chan[c].CheckIntr;
4049 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
4050 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
4053 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4054 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4055 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
4057 } while(c_state
== CHECK_INTR_CHECK
);
4058 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
4059 // check if already serviced
4060 if(c_state
== CHECK_INTR_ACTIVE
) {
4061 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
4065 if((c_state
== CHECK_INTR_DETECTED
) ||
4066 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
4068 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
4069 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
4070 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4075 // disable interrupts on other channel of legacy mode
4076 // ISA-bridged onboard controller
4077 if(deviceExtension
->simplexOnly
/*||
4078 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4079 AtapiDisableInterrupts(deviceExtension
, !c
);
4082 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
4083 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4084 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
4085 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
4088 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
4089 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4092 // re-enable interrupts on other channel
4093 if(deviceExtension
->simplexOnly
/*||
4094 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4095 AtapiEnableInterrupts(deviceExtension
, !c
);
4099 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
4100 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4105 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
4107 deviceExtension
->FirstChannelToCheck
++;
4108 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
4109 deviceExtension
->FirstChannelToCheck
= 0;
4112 } // end AtapiInterrupt()
4120 IN PKINTERRUPT Interrupt
,
4121 IN PVOID Isr2HwDeviceExtension
4124 // This ISR is intended to catch interrupts when we are already in other ISR instance
4125 // for the same device. This may happen when we have multiple channels,
4126 // especially on SMP machines
4128 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
4129 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
4131 BOOLEAN status
= FALSE
;
4137 // we should never get here for ISA/MCA
4138 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
4139 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
4143 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4144 // AHCI may generate state change notification, never skip this check
4145 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
4146 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
4150 // assume all non-interrupted ports to be already checked
4152 // assume all not implemented ports to be already checked
4153 checked
|= ~deviceExtension
->AHCI_PI
;
4156 checked
= 0; // assume all ports are not checked
4158 if(!deviceExtension
->ExpectingInterrupt
) {
4159 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
4160 deviceExtension
->ExpectingInterrupt
++;
4163 //deviceExtension->ExpectingInterrupt = 0;
4165 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4166 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
4168 if((checked
>>c
) & 0x01)
4171 checked
|= (ULONG
)1 << c
;
4173 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
4174 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
4178 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4179 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
4180 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
4182 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
4183 // hunt on unexpected intr (Some devices generate double interrupts,
4184 // some controllers (at least CMD649) interrupt twice with small delay.
4185 // If interrupts are disabled, they queue interrupt and re-issue it later,
4186 // when we do not expect it.
4191 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
4193 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
4194 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
4195 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
4196 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4201 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
4203 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4206 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
4207 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
4208 // there is an active ISR/DPC for one channel, but
4209 // we have an interrupt from another one
4210 // Lets inform current ISR/DPC about new interrupt
4211 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
4215 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
4218 } // end AtapiInterrupt2()
4220 RETTYPE_XXableInterrupts
4223 IN PVOID HwDeviceExtension
4226 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4229 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4230 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
4232 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
4234 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4235 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4236 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
4242 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
4245 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4246 AtapiDisableInterrupts(deviceExtension, lChannel);
4249 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
4250 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4251 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4254 return RETVAL_XXableInterrupts
;
4255 } // end AtapiInterruptDpc()
4258 RETTYPE_XXableInterrupts
4260 AtapiEnableInterrupts__(
4261 IN PVOID HwDeviceExtension
4264 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4265 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
4267 PHW_CHANNEL chan
= NULL
;
4269 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4270 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
4271 chan
= &(deviceExtension
->chan
[c
]);
4273 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
4274 // enable intrs on requested channel
4275 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
4276 AtapiEnableInterrupts(HwDeviceExtension
, c
);
4277 InterlockedExchange(&(chan
->CheckIntr
),
4280 // check if current or other channel(s) interrupted
4281 //AtapiInterrupt(HwDeviceExtension);
4283 if(deviceExtension
->simplexOnly
) {
4287 // check if other channel(s) interrupted
4288 // must do nothing in simplex mode
4289 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
4290 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4291 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
4294 //ASSERT(!deviceExtension->simplexOnly);
4295 chan
->DpcState
= DPC_STATE_ISR
;
4296 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4297 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
4301 // In simplex mode next command must be sent to device here
4302 if(deviceExtension
->simplexOnly
&& chan
) {
4303 PSCSI_REQUEST_BLOCK srb
;
4304 chan
= UniataGetNextChannel(chan
);
4306 srb
= UniataGetCurRequest(chan
);
4311 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
4315 return RETVAL_XXableInterrupts
;
4317 } // end AtapiEnableInterrupts__()
4319 #endif //UNIATA_CORE
4324 AtapiEnableInterrupts(
4325 IN PVOID HwDeviceExtension
,
4329 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4333 if(c
>= deviceExtension
->NumberChannels
) {
4334 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
4337 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
4338 !UniataAhciChanImplemented(deviceExtension
, c
)) {
4339 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
4343 chan
= &(deviceExtension
->chan
[c
]);
4344 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4345 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
4346 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4347 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
4348 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
4349 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
4350 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
4351 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
4353 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
4354 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
4357 //SelectDrive(chan, 0);
4358 //GetBaseStatus(chan, statusByte);
4359 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4360 0 | IDE_DC_A_4BIT
);
4361 //if(chan->NumberLuns) {
4362 // SelectDrive(chan, 1);
4363 // GetBaseStatus(chan, statusByte);
4364 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4366 // SelectDrive(chan, chan->cur_cdev);
4369 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4371 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4372 // keep interrupts disabled
4373 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4375 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4376 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4380 } // end AtapiEnableInterrupts()
4384 AtapiDisableInterrupts(
4385 IN PVOID HwDeviceExtension
,
4389 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4391 if(c
>= deviceExtension
->NumberChannels
) {
4392 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4395 chan
= &(deviceExtension
->chan
[c
]);
4396 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4397 // mark channel as busy
4398 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4399 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4400 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4402 //SelectDrive(chan, 0);
4403 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4404 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4405 //if(chan->NumberLuns) {
4406 // SelectDrive(chan, 1);
4407 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4408 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4409 // SelectDrive(chan, chan->cur_cdev);
4412 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4416 } // end AtapiDisableInterrupts()
4419 UniataExpectChannelInterrupt(
4420 IN
struct _HW_CHANNEL
* chan
,
4421 IN BOOLEAN Expecting
4424 chan
->ExpectingInterrupt
= Expecting
;
4426 chan
->DeviceExtension
->ExpectingInterrupt
++;
4428 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4429 chan
->DeviceExtension
->ExpectingInterrupt
--;
4432 } // end UniataExpectChannelInterrupt()
4435 Check hardware for interrupt state
4439 AtapiCheckInterrupt__(
4440 IN PVOID HwDeviceExtension
,
4441 IN UCHAR c
// logical channel
4444 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4445 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4446 PHW_LU_EXTENSION LunExt
;
4448 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4449 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4452 ULONG pr_status
= 0;
4453 UCHAR dma_status
= 0;
4456 UCHAR statusByte
= 0;
4457 ULONG slotNumber
= deviceExtension
->slotNumber
;
4458 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4459 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4462 BOOLEAN DmaTransfer
= FALSE
;
4463 BOOLEAN OurInterrupt
= FALSE
;
4464 BOOLEAN StatusValid
= FALSE
;
4466 UCHAR interruptReason
;
4467 BOOLEAN EarlyIntr
= FALSE
;
4468 BOOLEAN SingleBlockIntr
= FALSE
;
4470 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4473 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4474 LunExt
= chan
->lun
[chan
->cur_cdev
];
4476 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4477 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4479 if((ChipFlags
& UNIATA_AHCI
) &&
4480 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4482 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4483 return OurInterrupt
;
4486 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4487 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4488 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4489 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4490 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4491 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4492 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4493 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4494 OurInterrupt
= INTERRUPT_REASON_OUR
;
4496 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4497 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4498 OurInterrupt
= INTERRUPT_REASON_OUR
;
4500 if(statusByte
& IDE_STATUS_ERROR
) {
4501 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4502 OurInterrupt
= INTERRUPT_REASON_OUR
;
4504 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4505 OurInterrupt
= INTERRUPT_REASON_OUR
;
4508 return OurInterrupt
;
4511 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4513 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4514 deviceExtension
->Channel
+ c
, c
));
4516 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4517 deviceExtension
->Channel
+ c
, c
));
4518 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4519 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4522 // do controller-specific interrupt servicing staff
4523 if(deviceExtension
->UnknownDev
) {
4524 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4529 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4530 // Such behavior was observed with Intel ICH-xxx chips
4531 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4535 case ATA_PROMISE_ID
: {
4539 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4543 ((Channel
) ? 0x00004000 : 0x00000400))) {
4544 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4545 return INTERRUPT_REASON_IGNORE
;
4549 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4550 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4553 if(!(status
& 0x20)) {
4554 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4555 return INTERRUPT_REASON_IGNORE
;
4559 ULONG stat_reg
= (ChipFlags
& PRG2
) ? 0x60 : 0x6c;
4560 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40);
4561 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40, status
);
4563 if(status
& (1 << (Channel
+1))) {
4566 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4567 return INTERRUPT_REASON_IGNORE
;
4570 if(!(ChipFlags
& UNIATA_SATA
))
4573 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
);
4574 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
, (pr_status
& (0x11 << Channel
)));
4575 if(pr_status
& (0x11 << Channel
)) {
4576 // TODO: reset channel
4577 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4578 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4580 if(!(status
& (0x01 << Channel
))) {
4582 KdPrint2((PRINT_PREFIX
" Promise mio unexpected attach\n"));
4583 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4585 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4586 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4588 return INTERRUPT_REASON_IGNORE
;
4591 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4595 case ATA_NVIDIA_ID
: {
4596 if(!(ChipFlags
& UNIATA_SATA
))
4599 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4601 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4602 ULONG shift
= Channel
* ((ChipFlags
& NVQ
) ? 4 : 16);
4604 /* get and clear interrupt status */
4605 if(ChipFlags
& NVQ
) {
4606 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4607 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4609 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4610 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4612 KdPrint2((PRINT_PREFIX
" pr_status %x, shift %x\n", pr_status
, shift
));
4614 /* check for and handle connect events */
4615 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4616 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4618 /* check for and handle disconnect events */
4619 if((pr_status
& (0x08UL
<< shift
)) &&
4620 !((pr_status
& (0x04UL
<< shift
) &&
4621 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4622 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4624 /* do we have any device action ? */
4625 if(!(pr_status
& (0x01UL
<< shift
))) {
4626 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4627 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4628 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4630 return INTERRUPT_REASON_IGNORE
;
4636 KdPrint2((PRINT_PREFIX
"ATI\n"));
4637 if(ChipType
== SIIMIO
) {
4642 case ATA_SILICON_IMAGE_ID
:
4644 if(ChipType
== SIIMIO
) {
4646 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4647 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4648 if(reg32
== 0xffffffff) {
4649 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4650 return INTERRUPT_REASON_IGNORE
;
4652 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
))) {
4653 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4654 return INTERRUPT_REASON_IGNORE
;
4657 if(ChipFlags
& UNIATA_SATA
) {
4658 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4660 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4661 * controllers continue to assert IRQ as long as
4662 * SError bits are pending. Clear SError immediately.
4664 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4665 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4672 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4673 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4674 return OurInterrupt
;
4676 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4677 goto skip_dma_stat_check
;
4680 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4682 GetPciConfig1(0x71, reg8
);
4683 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4685 (Channel
? 0x08 : 0x04))) {
4686 return INTERRUPT_REASON_IGNORE
;
4689 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4690 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4692 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4699 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4700 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4701 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4702 return INTERRUPT_REASON_IGNORE
;
4704 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4705 AtapiStallExecution(1);
4706 AtapiWritePort1(chan
, IDX_BM_Command
,
4707 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4708 goto skip_dma_stat_check
;
4710 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4711 if(ChipFlags
& UNIATA_AHCI
) {
4714 if(ChipFlags
& UNIATA_SATA
) {
4715 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4716 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4718 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4719 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4720 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4727 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4728 if(ChipFlags
& UNIATA_AHCI
) {
4731 if(ChipFlags
& UNIATA_SATA
) {
4732 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4733 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4739 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4741 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4742 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4743 if(dma_status
& BM_STATUS_ERR
) {
4744 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4745 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4747 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4748 GetStatus(chan
, statusByte
);
4750 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4751 if(statusByte
& IDE_STATUS_ERROR
) {
4752 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4753 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4755 if ((statusByte
& IDE_STATUS_DSC
) &&
4756 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4757 (dma_status
== BM_STATUS_ACTIVE
)) {
4758 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4759 // some devices interrupts on each block transfer even in DMA mode
4760 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4761 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4762 ///* clear interrupt and get status */
4763 //GetBaseStatus(chan, statusByte);
4764 //return INTERRUPT_REASON_IGNORE;
4765 SingleBlockIntr
= TRUE
;
4768 return INTERRUPT_REASON_IGNORE
;
4773 if(dma_status
& BM_STATUS_INTR
) {
4774 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4775 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4776 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4778 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4781 skip_dma_stat_check
:
4782 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4783 AtapiStallExecution(1);
4786 /* if drive is busy it didn't interrupt */
4787 /* the exception is DCS + BSY state of ATAPI devices */
4789 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4790 GetStatus(chan
, statusByte
);
4792 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4793 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4795 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4797 if (statusByte
== IDE_STATUS_WRONG
) {
4798 // interrupt from empty controller ?
4800 if (statusByte
& IDE_STATUS_BUSY
) {
4801 if(!chan
->ExpectingInterrupt
) {
4802 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4803 return OurInterrupt
;
4806 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4807 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4809 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4810 return INTERRUPT_REASON_IGNORE
;
4812 if((statusByte
& ~(IDE_STATUS_DRQ
| IDE_STATUS_INDEX
)) !=
4813 (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4814 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4815 return INTERRUPT_REASON_IGNORE
;
4817 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4818 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4819 return INTERRUPT_REASON_IGNORE
;
4824 if(dma_status
& BM_STATUS_INTR
) {
4825 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4826 /* clear interrupt and get status */
4827 GetBaseStatus(chan
, statusByte
);
4828 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4829 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4831 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4832 return INTERRUPT_REASON_OUR
;
4835 if(g_WaitBusyInISR
) {
4836 GetStatus(chan
, statusByte
);
4837 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4838 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4839 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4840 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4841 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4843 if (statusByte
& IDE_STATUS_BUSY
) {
4844 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4845 return INTERRUPT_REASON_IGNORE
;
4851 /* clear interrupt and get status */
4852 GetBaseStatus(chan
, statusByte
);
4853 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4854 if (statusByte
== IDE_STATUS_WRONG
) {
4855 // interrupt from empty controller ?
4857 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4858 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4859 return OurInterrupt
;
4862 #ifndef UNIATA_PIO_ONLY
4864 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4865 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4867 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4868 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4872 if(SingleBlockIntr
) {
4873 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4875 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4878 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4884 if (!(chan
->ExpectingInterrupt
)) {
4886 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4888 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4889 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4891 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4892 return OurInterrupt
;
4894 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4895 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4896 return OurInterrupt
;
4898 //ASSERT(!chan->queue_depth || chan->cur_req);
4900 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4901 return INTERRUPT_REASON_OUR
;
4903 } // end AtapiCheckInterrupt__()
4909 IN PVOID HwDeviceExtension
,
4913 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4914 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4916 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4917 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4919 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4920 ULONG status
= SRB_STATUS_SUCCESS
;
4921 UCHAR dma_status
= 0;
4924 UCHAR statusByte
= 0,interruptReason
;
4926 BOOLEAN atapiDev
= FALSE
;
4933 BOOLEAN DmaTransfer
= FALSE
;
4935 ULONG TimerValue
= 1000;
4936 ULONG TotalTimerValue
= 0;
4937 #ifdef UNIATA_USE_XXableInterrupts
4938 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4940 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4941 #endif // UNIATA_USE_XXableInterrupts
4942 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4943 // BOOLEAN RestoreUseDpc = FALSE;
4944 BOOLEAN DataOverrun
= FALSE
;
4945 BOOLEAN NoStartIo
= TRUE
;
4946 BOOLEAN NoRetry
= FALSE
;
4948 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4950 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4951 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4957 UCHAR OldReqState
= REQ_STATE_NONE
;
4959 PHW_LU_EXTENSION LunExt
;
4964 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4966 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4969 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4970 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4971 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4973 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4977 PathId
= srb
->PathId
;
4978 TargetId
= srb
->TargetId
;
4984 goto enqueue_next_req
;
4987 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4988 DeviceNumber
= (UCHAR
)(TargetId
);
4989 LunExt
= chan
->lun
[DeviceNumber
];
4990 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4991 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4993 // check if we are in ISR DPC
4995 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4996 goto ServiceInterrupt
;
5000 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
5003 if (!(chan
->ExpectingInterrupt
)) {
5005 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
5009 // change request state
5011 OldReqState
= AtaReq
->ReqState
;
5012 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
5013 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
5016 // We don't want using DPC for fast operations, like
5017 // DMA completion, sending CDB, short ATAPI transfers, etc.
5019 // We MUST use DPC, because of interprocessor synchronization
5020 // on multiprocessor platforms
5023 goto ServiceInterrupt
;
5025 switch(OldReqState
) {
5026 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
5027 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
5028 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
5029 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
5030 case REQ_STATE_DPC_WAIT_BUSY0
:
5031 case REQ_STATE_DPC_WAIT_BUSY1
:
5032 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
5033 goto ServiceInterrupt
;
5034 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
5035 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
5039 if(!DmaTransfer
&& !atapiDev
) {
5040 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
5047 goto ServiceInterrupt
;
5049 #ifdef UNIATA_USE_XXableInterrupts
5051 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
5053 // shall never get here
5058 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
5060 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
5061 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
5063 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
5066 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
5067 goto ServiceInterrupt
;
5068 #endif // UNIATA_USE_XXableInterrupts
5073 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
5074 // We always get here when are called from timer callback, which is invoked on DRQL.
5075 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
5077 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
5078 // disable interrupts for this channel,
5079 // but avoid recursion and double-disable
5080 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
5081 UniataExpectChannelInterrupt(chan
, FALSE
);
5082 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5085 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
5087 #ifdef UNIATA_USE_XXableInterrupts
5088 // Will lower IRQL to DISPATCH_LEVEL
5089 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
5090 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
5091 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
5093 // Will raise IRQL to DIRQL
5094 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
5097 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5098 #endif // UNIATA_USE_XXableInterrupts
5103 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
5105 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
5106 // we must block interrupts from this channel
5107 // If device generate new interrupt before we get to DPC,
5108 // ISR will assume, that it is NOT our interrupt
5109 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5110 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
5112 // Will raise IRQL to DIRQL
5113 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
5117 #endif //UNIATA_CORE
5121 if(AtaReq
&& InDpc
) {
5122 switch(AtaReq
->ReqState
) {
5123 case REQ_STATE_DPC_WAIT_DRQ0
:
5125 case REQ_STATE_DPC_WAIT_BUSY
:
5127 case REQ_STATE_DPC_WAIT_DRQ
:
5129 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
5131 case REQ_STATE_DPC_WAIT_BUSY0
:
5132 case REQ_STATE_DPC_WAIT_BUSY1
:
5133 // continue normal execution
5139 #endif //UNIATA_CORE
5141 // make additional delay for old devices (if we are not in DPC)
5142 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
5146 !(deviceExtension->HwFlags & UNIATA_SATA)
5148 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
5149 AtapiStallExecution(10);
5153 /* clear interrupt and get status */
5154 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5155 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
5156 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
5158 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
5159 KdPrint3((PRINT_PREFIX
"Err intr (%#x), SE (%#x)\n",
5160 chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
),
5161 chan
->AhciLastSError
));
5162 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
5163 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
5164 // We have some other error except Overflow
5165 // Just signal ERROR, operation will be aborted in ERROR branch.
5166 statusByte
|= IDE_STATUS_ERROR
;
5167 AtaReq
->ahci
.in_serror
= chan
->AhciLastSError
;
5168 if(chan
->AhciLastSError
& (ATA_SE_HANDSHAKE_ERR
| ATA_SE_LINKSEQ_ERR
| ATA_SE_TRANSPORT_ERR
| ATA_SE_UNKNOWN_FIS
)) {
5169 KdPrint2((PRINT_PREFIX
"Unrecoverable\n"));
5173 // We have only Overflow. Abort operation and continue
5175 UniataDumpAhciPortRegs(chan
);
5177 if(!UniataAhciAbortOperation(chan
)) {
5178 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5181 UniataDumpAhciPortRegs(chan
);
5183 UniataAhciWaitCommandReady(chan
, 10);
5188 GetBaseStatus(chan
, statusByte
);
5191 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
5193 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
5197 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
5203 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5204 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
5206 if (statusByte
& IDE_STATUS_BUSY
) {
5207 if (deviceExtension
->DriverMustPoll
) {
5208 // Crashdump is polling and we got caught with busy asserted.
5209 // Just go away, and we will be polled again shortly.
5210 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
5211 goto ReturnEnableIntr
;
5214 // Ensure BUSY is non-asserted.
5215 // make a very small idle before falling to DPC
5216 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
5218 for (i
= 0; i
< k
; i
++) {
5220 GetBaseStatus(chan
, statusByte
);
5221 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5224 AtapiStallExecution(10);
5227 if (!InDpc
&& UseDpc
&& i
== 2) {
5229 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
5232 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5237 AtapiStallExecution(TimerValue
);
5238 goto ServiceInterrupt
;
5239 #endif //UNIATA_CORE
5241 if (InDpc
&& i
== k
) {
5242 // reset the controller.
5243 KdPrint2((PRINT_PREFIX
5244 " Resetting due to BUSY on entry - %#x.\n",
5246 goto IntrPrepareResetController
;
5251 if(!LunExt
->IdentifyData
.MajorRevision
&&
5254 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
5256 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
5257 //AtapiStallExecution(10);
5259 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5260 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
5262 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5263 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5266 if (statusByte
& IDE_STATUS_BUSY
) {
5267 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
5270 // This is just workaround
5271 // We should DISABLE interrupts before entering WAIT state
5272 UniataExpectChannelInterrupt(chan, TRUE);
5273 #endif //UNIATA_CORE
5275 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
5277 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
5278 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
5279 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
5280 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5283 #endif //UNIATA_CORE
5286 GetBaseStatus(chan
, statusByte
);
5287 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5288 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
5289 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
5290 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5291 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
5294 TotalTimerValue
+= TimerValue
;
5296 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
5298 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
5300 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5302 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
5304 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
5308 if(!LunExt
->AtapiReadyWaitDelay
) {
5309 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5313 #endif //UNIATA_CORE
5316 AtapiStallExecution(TimerValue
);
5319 if(!LunExt
->AtapiReadyWaitDelay
) {
5320 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5321 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
5323 if (statusByte
& IDE_STATUS_BUSY
) {
5324 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
5330 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5331 switch(OldReqState
) {
5332 case REQ_STATE_EARLY_INTR
:
5333 case REQ_STATE_DPC_WAIT_BUSY0
:
5335 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
5336 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
5337 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5344 // Check for error conditions.
5345 if ((statusByte
& IDE_STATUS_ERROR
) ||
5346 (dma_status
& BM_STATUS_ERR
)) {
5348 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5349 error
= AtaReq
->ahci
.in_error
;
5352 UniataDumpAhciPortRegs(chan
);
5354 if(!UniataAhciAbortOperation(chan
)) {
5355 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5357 // clear interrupts again
5358 UniataAhciWaitCommandReady(chan
, 10);
5360 UniataDumpAhciPortRegs(chan
);
5362 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
5364 AtaReq
->retry
+= MAX_RETRIES
;
5365 if(!error
&& (statusByte
& IDE_STATUS_ERROR
)) {
5366 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: force error status\n"));
5367 error
|= IDE_STATUS_ERROR
;
5371 UniataDumpAhciPortRegs(chan
);
5374 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5376 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
5378 if(error & IDE_STATUS_CORRECTED_ERROR) {
5379 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5380 statusByte &= ~IDE_STATUS_ERROR;
5385 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
5387 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
5390 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5391 KdPrint2((PRINT_PREFIX
" no wait ready after error\n"));
5394 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
5395 AtapiStallExecution(100);
5397 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
5398 AtapiStallExecution(10);
5402 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
5403 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
5405 for (k
= atapiDev
? 0 : 200; k
; k
--) {
5406 GetBaseStatus(chan
, statusByte
);
5407 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5408 AtapiStallExecution(50);
5415 /* if this is a UDMA CRC error, reinject request */
5418 if(AtaReq
->retry
< MAX_RETRIES
) {
5419 #ifdef IO_STATISTICS
5420 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5421 #endif //IO_STATISTICS
5423 (error & IDE_ERROR_ICRC)*/) {
5424 KdPrint2((PRINT_PREFIX
"Errors in DMA mode\n"));
5425 if(AtaReq
->retry
< MAX_RETRIES
) {
5427 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5428 //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5429 // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
5430 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5432 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5436 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5439 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5443 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5444 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5446 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
5447 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5450 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
5451 UniataSataClearErr(HwDeviceExtension
, lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 0);
5455 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5456 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5457 if(AtaReq
->retry
< MAX_RETRIES
) {
5459 // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
5460 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5461 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5462 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5463 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5467 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5470 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5474 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5475 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5476 // Fail this request.
5477 status
= SRB_STATUS_ERROR
;
5478 goto CompleteRequest
;
5480 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5483 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5484 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5485 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5487 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5488 #ifdef IO_STATISTICS
5489 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5490 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5492 LunExt
->RecoverCount
[AtaReq
->retry
],
5493 LunExt
->BlockIoCount
5495 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5496 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= LunExt
->BlockIoCount
/3 ||
5497 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5500 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5501 #endif //IO_STATISTICS
5502 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5503 LunExt
->LimitedTransferMode
=
5504 LunExt
->TransferMode
;
5507 #ifdef IO_STATISTICS
5508 if(AtaReq
->bcount
) {
5509 // we need stats for Read/Write operations
5510 LunExt
->BlockIoCount
++;
5513 #endif //IO_STATISTICS
5517 // check reason for this interrupt.
5520 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5523 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5524 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5526 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5528 wordsThisInterrupt
= DEV_BSIZE
/2;
5536 // simulate DRQ for DMA transfers
5537 statusByte
|= IDE_STATUS_DRQ
;
5539 if (statusByte
& IDE_STATUS_DRQ
) {
5542 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5544 if (LunExt
->MaximumBlockXfer
) {
5545 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5548 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5550 interruptReason
= ATAPI_IR_IO_toHost
;
5552 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5553 interruptReason
= ATAPI_IR_IO_toDev
;
5556 status
= SRB_STATUS_ERROR
;
5557 goto CompleteRequest
;
5560 } else if (statusByte
& IDE_STATUS_BUSY
) {
5562 //AtapiEnableInterrupts(deviceExtension, lChannel);
5563 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5568 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq
->WordsLeft
));
5569 if (AtaReq
->WordsLeft
) {
5571 // Funky behaviour seen with PCI IDE (not all, just one).
5573 // The ISR hits with DRQ low, but comes up later.
5574 for (k
= 0; k
< 5000; k
++) {
5575 GetBaseStatus(chan
, statusByte
);
5576 if (statusByte
& IDE_STATUS_DRQ
) {
5581 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5583 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5587 AtapiStallExecution(TimerValue
);
5588 goto ServiceInterrupt
;
5589 #endif //UNIATA_CORE
5591 AtapiStallExecution(100);
5594 // reset the controller.
5595 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5597 IntrPrepareResetController
:
5598 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5599 goto ReturnEnableIntr
;
5602 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5606 // Command complete - verify, write, or the SMART enable/disable.
5607 // Also get_media_status
5608 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5613 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5614 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5615 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5616 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5617 //status = SRB_STATUS_DATA_OVERRUN;
5620 status = SRB_STATUS_SUCCESS;
5622 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5623 AtaReq
->WordsLeft
= 0;
5625 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5627 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5628 // status = SRB_STATUS_DATA_OVERRUN;
5630 status
= SRB_STATUS_SUCCESS
;
5631 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5632 goto CompleteRequest
;
5634 if ((interruptReason
== ATAPI_IR_COD_Cmd
) && (statusByte
& IDE_STATUS_DRQ
)) {
5635 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5636 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, srb
);
5638 // Write the packet.
5639 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5640 // Send CDB to device.
5641 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5642 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5644 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5646 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5647 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5648 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5651 goto ReturnEnableIntr
;
5653 } else if ((interruptReason
== ATAPI_IR_IO_toDev
) && (statusByte
& IDE_STATUS_DRQ
)) {
5658 // Pick up bytes to transfer and convert to words.
5660 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5663 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5665 // Covert bytes to words.
5667 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5669 if (wordCount
!= AtaReq
->WordsLeft
) {
5670 KdPrint2((PRINT_PREFIX
5671 "AtapiInterrupt: %d words requested; %d words xferred\n",
5676 // Verify this makes sense.
5677 if (wordCount
> AtaReq
->WordsLeft
) {
5678 wordCount
= AtaReq
->WordsLeft
;
5679 KdPrint2((PRINT_PREFIX
5680 "AtapiInterrupt: Write underrun\n"));
5686 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5687 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5688 // Transfer only words requested.
5689 wordCount
= AtaReq
->WordsLeft
;
5691 // Transfer next block.
5692 wordCount
= wordsThisInterrupt
;
5697 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5698 //ASSERT(AtaReq->WordsLeft == wordCount);
5699 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5700 KdPrint2((PRINT_PREFIX
5701 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5702 if(AtaReq
->WordsLeft
> wordCount
) {
5703 AtaReq
->WordsLeft
-= wordCount
;
5704 AtaReq
->WordsTransfered
+= wordCount
;
5705 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5706 goto ReturnEnableIntr
;
5708 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5710 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5711 AtaReq
->WordsLeft
= 0;
5712 status
= SRB_STATUS_SUCCESS
;
5713 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5714 goto CompleteRequest
;
5717 // Ensure that this is a write command.
5718 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5720 KdPrint2((PRINT_PREFIX
5721 "AtapiInterrupt: Write interrupt\n"));
5723 statusByte
= WaitOnBusy(chan
);
5725 if (/*atapiDev || */ !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/
5726 || (wordCount
& 1)) {
5731 UniataGetPioTiming(LunExt
));
5735 (PULONG
)(AtaReq
->DataBuffer
),
5737 UniataGetPioTiming(LunExt
));
5741 KdPrint3((PRINT_PREFIX
5742 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5746 // Fail this request.
5747 status
= SRB_STATUS_ERROR
;
5748 if(!wordCount
&& atapiDev
&& (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
)) {
5749 // some devices feel bad after incorrect commands and may need reset
5750 KdPrint2((PRINT_PREFIX
5751 "AtapiInterrupt: Try ATAPI reset\n"));
5753 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5754 AtapiSoftReset(chan
, DeviceNumber
);
5755 AtapiEnableInterrupts(deviceExtension
, lChannel
);
5756 status
= SRB_STATUS_BUS_RESET
;
5757 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5759 // goto IntrPrepareResetController;
5761 goto CompleteRequest
;
5763 // Advance data buffer pointer and bytes left.
5764 AtaReq
->DataBuffer
+= wordCount
;
5765 AtaReq
->WordsLeft
-= wordCount
;
5766 AtaReq
->WordsTransfered
+= wordCount
;
5769 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5772 goto ReturnEnableIntr
;
5774 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5780 // Pick up bytes to transfer and convert to words.
5782 (ULONG
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5783 ((ULONG
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5785 // Convert bytes to words.
5786 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R byteCount %#x\n", wordCount
));
5789 When ATAPI 64k PIO read is requested we may have 0xfffe byte
5790 count reported for 0x10000 bytes in single interrupt.
5791 It is not allowed to read entire 64k block with DwordIo intead of
5794 if (wordCount
!= AtaReq
->WordsLeft
) {
5795 KdPrint2((PRINT_PREFIX
5796 "AtapiInterrupt: %d words requested; %d words xferred\n",
5801 // Verify this makes sense.
5802 if (wordCount
> AtaReq
->WordsLeft
) {
5803 wordCount
= AtaReq
->WordsLeft
;
5809 // Check if words left is at least 256.
5810 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5811 // Transfer only words requested.
5812 wordCount
= AtaReq
->WordsLeft
;
5814 // Transfer next block.
5815 wordCount
= wordsThisInterrupt
;
5820 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5821 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5822 KdPrint2((PRINT_PREFIX
5823 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5824 if(AtaReq
->WordsLeft
> wordCount
) {
5825 AtaReq
->WordsLeft
-= wordCount
;
5826 AtaReq
->WordsTransfered
+= wordCount
;
5827 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5828 goto ReturnEnableIntr
;
5830 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5832 //ASSERT(AtaReq->WordsLeft == wordCount);
5833 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5834 AtaReq
->WordsLeft
= 0;
5835 status
= SRB_STATUS_SUCCESS
;
5836 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5837 goto CompleteRequest
;
5839 // Ensure that this is a read command.
5840 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5843 "AtapiInterrupt: Read interrupt\n"));*/
5845 statusByte
= WaitOnBusy(chan
);
5847 if(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) {
5848 KdPrint2((PRINT_PREFIX
5849 "IdeIntr: pre-Read %#x Dwords\n", wordCount
/2));
5852 (PULONG
)(AtaReq
->DataBuffer
),
5854 UniataGetPioTiming(LunExt
));
5855 // Advance data buffer pointer and bytes left.
5856 AtaReq
->DataBuffer
+= wordCount
& ~1;
5857 AtaReq
->WordsLeft
-= wordCount
& ~1;
5858 AtaReq
->WordsTransfered
+= wordCount
& ~1;
5862 KdPrint2((PRINT_PREFIX
5863 "IdeIntr: Read %#x words\n", wordCount
));
5868 UniataGetPioTiming(LunExt
));
5871 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5872 //KdDump(AtaReq->DataBuffer, wordCount*2);
5873 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5874 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5877 GetBaseStatus(chan
, statusByte
);
5878 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5881 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5882 AtapiSuckPort2(chan
);
5883 GetBaseStatus(chan
, statusByte
);
5886 if(statusByte
& IDE_STATUS_BUSY
) {
5887 for (i
= 0; i
< 2; i
++) {
5888 AtapiStallExecution(10);
5889 GetBaseStatus(chan
, statusByte
);
5890 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5898 KdPrint3((PRINT_PREFIX
5899 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5903 // Fail this request.
5904 status
= SRB_STATUS_ERROR
;
5905 goto CompleteRequest
;
5907 //continue_atapi_pio_read:
5908 // Advance data buffer pointer and bytes left.
5909 AtaReq
->DataBuffer
+= wordCount
;
5910 AtaReq
->WordsLeft
-= wordCount
;
5911 AtaReq
->WordsTransfered
+= wordCount
;
5913 // Check for read command complete.
5914 if (AtaReq
->WordsLeft
== 0) {
5916 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5919 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
) {
5921 // Work around to make many atapi devices return correct sector size
5922 // of 2048. Also certain devices will have sector count == 0x00, check
5924 if (srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) {
5926 AtaReq
->DataBuffer
-= wordCount
;
5927 if (AtaReq
->DataBuffer
[0] == 0x00) {
5928 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5931 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5932 AtaReq
->DataBuffer
+= wordCount
;
5934 #ifndef UNIATA_INIT_CHANGERS
5936 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5938 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5940 AtapiHwInitializeChanger (HwDeviceExtension
,
5942 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5943 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
5944 KdPrint2((PRINT_PREFIX
" set DFLAGS_CHANGER_INITED\n"));
5946 #endif // UNIATA_INIT_CHANGERS
5948 GetStatus(chan
, statusByte
);
5949 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5950 // Assume command is completed if BUSY is cleared
5951 // and all data read
5952 // Optionally, we may receive COMPLETE interrupt later and
5953 // treat it as unexpected
5954 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5956 status
= SRB_STATUS_SUCCESS
;
5957 goto CompleteRequest
;
5963 // Completion for IDE drives.
5964 if (AtaReq->WordsLeft) {
5965 status = SRB_STATUS_DATA_OVERRUN;
5967 status = SRB_STATUS_SUCCESS;
5970 goto CompleteRequest;
5972 status
= SRB_STATUS_SUCCESS
;
5973 goto CompleteRequest
;
5978 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5979 GetStatus(chan
, statusByte
);
5980 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5981 // Assume command is completed if BUSY is cleared
5982 // even if NOT all data read
5983 // Optionally, we may receive COMPLETE interrupt later and
5984 // treat it as unexpected
5985 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5987 status
= SRB_STATUS_SUCCESS
;
5988 goto CompleteRequest
;
5991 if(!atapiDev
&& !DataOverrun
&& (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) &&
5992 ((statusByte
& ~IDE_STATUS_INDEX
) == (IDE_STATUS_IDLE
| IDE_STATUS_DRQ
))) {
5993 KdPrint2((PRINT_PREFIX
" HDD read data ready \n"));
5994 goto continue_read_drq
;
5999 goto ReturnEnableIntr
;
6001 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
6003 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
6004 // Command complete. We exactly know this because of IReason.
6007 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
6008 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
6009 AtaReq
->WordsLeft
= 0;
6011 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
6013 wordCount
= AtaReq
->WordsLeft
;
6014 // Advance data buffer pointer and bytes left.
6015 AtaReq
->DataBuffer
+= wordCount
;
6016 AtaReq
->WordsLeft
-= wordCount
;
6017 AtaReq
->WordsTransfered
+= wordCount
;
6019 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount
, AtaReq
->WordsTransfered
));
6022 //if (AtaReq->WordsLeft) {
6023 // status = SRB_STATUS_DATA_OVERRUN;
6025 status
= SRB_STATUS_SUCCESS
;
6028 #ifdef UNIATA_DUMP_ATAPI
6030 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6034 PCHAR ModeSelectData
;
6036 PSCSI_REQUEST_BLOCK Srb
= srb
;
6038 Cdb
= (PCDB
)(Srb
->Cdb
);
6039 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6040 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6041 CdbDataLen
= Srb
->DataTransferLength
;
6043 if(CdbDataLen
> 0x1000) {
6044 CdbDataLen
= 0x1000;
6048 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6049 KdPrint2(("P:T:D=%d:%d:%d\n",
6053 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
6056 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
6057 KdPrint(("ModeSense 6\n"));
6058 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6059 ModeSelectData
= CdbData
+4;
6060 KdDump(CdbData
, CdbDataLen
);
6062 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
6063 KdPrint(("ModeSense 10\n"));
6064 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6065 ModeSelectData
= CdbData
+8;
6066 KdDump(CdbData
, CdbDataLen
);
6068 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6069 KdPrint(("Read buffer from device:\n"));
6070 KdDump(CdbData
, CdbDataLen
);
6075 #endif //UNIATA_DUMP_ATAPI
6079 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
6080 // Check and see if we are processing our secret (mechanism status/request sense) srb
6082 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
6083 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
6084 status
= SRB_STATUS_DATA_OVERRUN
;
6087 if (AtaReq
->OriginalSrb
) {
6091 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
6092 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
6093 #ifdef UNIATA_INIT_CHANGERS
6094 // We can get here only when UNIATA_INIT_CHANGERS is defined
6095 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
6096 if (status
== SRB_STATUS_SUCCESS
) {
6098 AtapiHwInitializeChanger (HwDeviceExtension
,
6100 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
6102 // Get ready to issue the original srb
6103 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6104 AtaReq
->OriginalSrb
= NULL
;
6107 // failed! Get the sense key and maybe try again
6108 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
6110 AtaReq
->OriginalSrb
);
6113 // do not enable interrupts in DPC, do not waste time, do it now!
6114 if(UseDpc && chan->DisableIntr) {
6115 AtapiEnableInterrupts(HwDeviceExtension, c);
6117 RestoreUseDpc = TRUE;
6120 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
6122 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
6124 if (srbStatus
== SRB_STATUS_PENDING
) {
6125 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
6126 goto ReturnEnableIntr
;
6130 // restore state on error
6132 AtapiDisableInterrupts(HwDeviceExtension, c);
6136 KdPrint((PRINT_PREFIX
"AtapiInterrupt: ERROR: internal SCSIOP_MECHANISM_STATUS !!!!\n"));
6138 #endif // UNIATA_INIT_CHANGERS
6139 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
6141 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
6143 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
6144 if (status
== SRB_STATUS_DATA_OVERRUN
) {
6145 // Check to see if we at least get mininum number of bytes
6146 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
6147 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
6148 status
= SRB_STATUS_SUCCESS
;
6152 if (status
== SRB_STATUS_SUCCESS
) {
6154 #ifdef UNIATA_INIT_CHANGERS
6155 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
6157 chan
->MechStatusRetryCount
) {
6159 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
6160 // The sense key doesn't say the last request is illegal, so try again
6161 chan
->MechStatusRetryCount
--;
6162 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
6164 AtaReq
->OriginalSrb
);
6166 #endif // UNIATA_INIT_CHANGERS
6168 // Get ready to issue the original srb
6169 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6170 AtaReq
->OriginalSrb
= NULL
;
6172 #endif //UNIATA_CORE
6174 // do not enable interrupts in DPC, do not waste time, do it now!
6175 if(UseDpc && chan->DisableIntr) {
6176 AtapiEnableInterrupts(HwDeviceExtension, c);
6178 RestoreUseDpc = TRUE;
6181 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
6183 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
6185 if (srbStatus
== SRB_STATUS_PENDING
) {
6186 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
6187 goto ReturnEnableIntr
;
6191 // restore state on error
6193 AtapiDisableInterrupts(HwDeviceExtension, c);
6199 // If we get here, it means AtapiSendCommand() has failed
6200 // Can't recover. Pretend the original srb has failed and complete it.
6202 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
6204 if (AtaReq
->OriginalSrb
) {
6205 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6206 AtaReq
->OriginalSrb
= NULL
;
6209 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
6211 // fake an error and read no data
6212 status
= SRB_STATUS_ERROR
;
6213 srb
->ScsiStatus
= 0;
6214 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
6215 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
6218 } else if (status
== SRB_STATUS_ERROR
) {
6220 // Map error to specific SRB status and handle request sense.
6221 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
6222 status
= MapError(deviceExtension
,
6227 } else if(!DmaTransfer
) {
6229 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
6230 // Command complete.
6232 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
6233 // Wait for busy to drop.
6234 for (i
= 0; i
< 5*30; i
++) {
6235 GetBaseStatus(chan
, statusByte
);
6236 if (!(statusByte
& IDE_STATUS_BUSY
)) {
6241 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
6243 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
6247 AtapiStallExecution(TimerValue
);
6248 goto ServiceInterrupt
;
6249 #endif //UNIATA_CORE
6251 AtapiStallExecution(100);
6256 // reset the controller.
6257 KdPrint2((PRINT_PREFIX
6258 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
6260 goto IntrPrepareResetController
;
6262 // Check to see if DRQ is still up.
6263 if(statusByte
& IDE_STATUS_DRQ
) {
6264 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
6266 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6267 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
6269 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
6272 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
6275 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
6277 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
6279 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
6280 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
6281 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
6285 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
6286 //if ((statusByte & IDE_STATUS_DRQ)) {}
6287 if((statusByte
& IDE_STATUS_DRQ
) &&
6288 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
6291 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
6292 for (i
= 0; i
< 200; i
++) {
6293 GetBaseStatus(chan
, statusByte
);
6294 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6299 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
6300 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
6305 AtapiStallExecution(TimerValue
);
6306 goto ServiceInterrupt
;
6307 #endif //UNIATA_CORE
6309 AtapiStallExecution(100);
6313 // reset the controller.
6314 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
6316 goto IntrPrepareResetController
;
6320 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
6321 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
6322 //KdDump(srb->DataBuffer, srb->DataTransferLength);
6324 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
6325 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
6329 // Clear interrupt expecting flag.
6330 UniataExpectChannelInterrupt(chan
, FALSE
);
6331 // clear this flag now, it can be set again in sub-calls
6332 InterlockedExchange(&(chan
->CheckIntr
),
6335 // Sanity check that there is a current request.
6337 // Set status in SRB.
6338 srb
->SrbStatus
= (UCHAR
)status
;
6340 // Check for underflow.
6341 if(AtaReq
->WordsLeft
) {
6343 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
6344 // Subtract out residual words and update if filemark hit,
6345 // setmark hit , end of data, end of media...
6346 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
6347 if (status
== SRB_STATUS_DATA_OVERRUN
) {
6348 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6350 srb
->DataTransferLength
= 0;
6353 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6356 if(status
== SRB_STATUS_SUCCESS
) {
6357 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
6358 // // This should be set in UniataAhciEndTransaction() for AHCI
6359 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
6362 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
6363 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
6364 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6365 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6366 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
6369 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
6370 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6374 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
6377 // Indicate command complete.
6379 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
6382 if (status
== SRB_STATUS_SUCCESS
&&
6383 srb
->SenseInfoBuffer
&&
6384 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
6386 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
6388 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
6389 senseBuffer
->ErrorCode
= 0;
6390 senseBuffer
->Valid
= 1;
6391 senseBuffer
->AdditionalSenseLength
= 0xb;
6392 senseBuffer
->SenseKey
= 0;
6393 senseBuffer
->AdditionalSenseCode
= 0;
6394 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6396 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
6398 AtapiDmaDBSync(chan
, srb
);
6399 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
6400 UniataRemoveRequest(chan
, srb
);
6401 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
6402 ScsiPortNotification(RequestComplete
,
6408 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
6410 if (status
!= SRB_STATUS_SUCCESS
) {
6411 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6412 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
6415 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6417 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6418 // Build the SMART status block depending upon the completion status.
6419 cmdOutParameters
->cBufferSize
= wordCount
;
6420 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
6421 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
6423 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6425 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
6426 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
6429 UniataSnapAtaRegs(chan
, 0, regs
);
6431 regs
->bCommandReg
= SMART_CMD
;
6432 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
6434 cmdOutParameters
->cBufferSize
= 8;
6436 chan
->SmartCommand
= 0; // cleanup after execution
6438 // Indicate command complete.
6439 goto IntrCompleteReq
;
6444 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
6449 for (i
= 0; i
< 5; i
++) {
6450 GetBaseStatus(chan
, statusByte
);
6451 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6452 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
6456 if (statusByte
& IDE_STATUS_DSC
) {
6457 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
6461 AtapiStallExecution(50);
6464 // RDP can be cleared since previous check
6466 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6472 AtapiStallExecution(TimerValue
);
6473 goto ServiceInterrupt
;
6474 #endif //UNIATA_CORE
6477 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6480 srb
= UniataGetCurRequest(chan
);
6485 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6487 ScsiPortNotification(NextRequest
,
6491 ScsiPortNotification(NextLuRequest
,
6496 // in simplex mode next command must NOT be sent here
6497 if(!deviceExtension
->simplexOnly
) {
6498 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6501 // Try to get SRB fron any non-empty queue (later)
6502 if(deviceExtension
->simplexOnly
) {
6505 #endif //UNIATA_CORE
6507 goto ReturnEnableIntr
;
6511 // Unexpected int. Catch it
6512 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6516 if(g_opt_VirtualMachine
== VM_QEMU
) {
6517 if(interruptReason
== ATAPI_IR_IO_toDev
&& !(statusByte
& IDE_STATUS_DRQ
) && !DmaTransfer
) {
6518 statusByte
= WaitForDrq(chan
);
6519 if(statusByte
& IDE_STATUS_DRQ
) {
6525 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6526 AtaReq
->WordsLeft
== 0) {
6527 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6528 status
= SRB_STATUS_SUCCESS
;
6529 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6530 goto CompleteRequest
;
6536 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6537 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6538 deviceExtension
->ExpectingInterrupt
= TRUE
;
6540 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6541 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6542 #ifdef UNIATA_USE_XXableInterrupts
6543 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6544 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6545 // must be called on DISPATCH_LEVEL
6546 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6547 AtapiEnableInterrupts__
);
6549 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6550 InterlockedExchange(&(chan
->CheckIntr
),
6552 // Will raise IRQL to DIRQL
6554 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6555 AtapiEnableInterrupts__
,
6557 #endif // UNIATA_CORE
6558 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6559 #endif // UNIATA_USE_XXableInterrupts
6563 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6564 // in simplex mode next command must be sent here if
6566 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6569 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6570 chan
= UniataGetNextChannel(chan
);
6572 srb
= UniataGetCurRequest(chan
);
6576 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6578 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6581 #endif //UNIATA_CORE
6584 } // end AtapiInterrupt__()
6590 Routine Description:
6592 This routine handles SMART enable, disable, read attributes and threshold commands.
6596 HwDeviceExtension - HBA miniport driver's adapter data storage
6597 Srb - IO request packet
6606 IdeSendSmartCommand(
6607 IN PVOID HwDeviceExtension
,
6608 IN PSCSI_REQUEST_BLOCK Srb
,
6609 IN ULONG targetId
// assume it is always valid
6612 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6613 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6614 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6615 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6616 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6617 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6618 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6623 if (regs
->bCommandReg
!= SMART_CMD
) {
6624 KdPrint2((PRINT_PREFIX
6625 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6626 return SRB_STATUS_INVALID_REQUEST
;
6629 c
= targetId
/ deviceExtension
->NumberLuns
;
6630 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6631 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6633 chan
= &(deviceExtension
->chan
[c
]);
6635 chan
->SmartCommand
= regs
->bFeaturesReg
;
6637 // Determine which of the commands to carry out.
6638 switch(regs
->bFeaturesReg
) {
6639 case READ_ATTRIBUTES
:
6640 case READ_THRESHOLDS
:
6641 case READ_LOG_SECTOR
:
6642 case WRITE_LOG_SECTOR
:
6644 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6645 KdPrint2((PRINT_PREFIX
6646 "IdeSendSmartCommand: wrong buffer size\n"));
6647 return SRB_STATUS_DATA_OVERRUN
;
6650 statusByte
= WaitOnBusy(chan
);
6652 if (statusByte
& IDE_STATUS_BUSY
) {
6653 KdPrint2((PRINT_PREFIX
6654 "IdeSendSmartCommand: Returning BUSY status\n"));
6655 return SRB_STATUS_BUSY
;
6658 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6659 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6661 // Set data buffer pointer and words left.
6662 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6663 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6665 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6667 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6669 regs
->bSectorNumberReg
,
6670 regs
->bSectorCountReg
,
6674 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6675 // Wait for interrupt.
6676 return SRB_STATUS_PENDING
;
6678 return SRB_STATUS_ERROR
;
6682 case RETURN_SMART_STATUS
:
6683 case ENABLE_DISABLE_AUTOSAVE
:
6684 case EXECUTE_OFFLINE_DIAGS
:
6685 case SAVE_ATTRIBUTE_VALUES
:
6688 statusByte
= WaitOnBusy(chan
);
6690 if (statusByte
& IDE_STATUS_BUSY
) {
6691 KdPrint2((PRINT_PREFIX
6692 "IdeSendSmartCommand: Returning BUSY status\n"));
6693 return SRB_STATUS_BUSY
;
6696 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6697 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6699 // Set data buffer pointer and indicate no data transfer.
6700 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6701 AtaReq
->WordsLeft
= 0;
6703 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6705 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6707 regs
->bSectorNumberReg
,
6708 regs
->bSectorCountReg
,
6712 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6713 // Wait for interrupt.
6714 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6715 return SRB_STATUS_PENDING
;
6717 return SRB_STATUS_ERROR
;
6718 } // end switch(regs->bFeaturesReg)
6720 return SRB_STATUS_INVALID_REQUEST
;
6722 } // end IdeSendSmartCommand()
6724 #endif //UNIATA_CORE
6728 UniAtaCalculateLBARegs(
6729 PHW_LU_EXTENSION LunExt
,
6730 ULONGLONG startingSector
,
6734 UCHAR drvSelect
,sectorNumber
;
6738 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6740 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6741 if(LunExt
->DeviceExtension
) {
6742 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6745 return startingSector
;
6747 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6748 LunExt
->IdentifyData
.NumberOfHeads
;
6750 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6754 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6756 cylinder
= (USHORT
)(startingSector
/ tmp
);
6757 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6758 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6759 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6760 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6761 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6764 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6765 } // end UniAtaCalculateLBARegs()
6769 UniAtaCalculateLBARegsBack(
6770 PHW_LU_EXTENSION LunExt
,
6774 ULONG drvSelect
,sectorNumber
;
6778 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6781 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6782 LunExt
->IdentifyData
.NumberOfHeads
;
6784 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6785 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6786 sectorNumber
= (UCHAR
)(lba
& 0xff);
6788 lba
= sectorNumber
-1 +
6789 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6793 } // end UniAtaCalculateLBARegsBack()
6798 Routine Description:
6800 This routine handles IDE read and writes.
6804 HwDeviceExtension - HBA miniport driver's adapter data storage
6805 Srb - IO request packet
6815 IN PVOID HwDeviceExtension
,
6816 IN PSCSI_REQUEST_BLOCK Srb
,
6820 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6821 UCHAR lChannel
= GET_CHANNEL(Srb
);
6822 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6823 PHW_LU_EXTENSION LunExt
;
6824 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6825 //ULONG ldev = GET_LDEV(Srb);
6826 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6827 ULONGLONG startingSector
=0;
6828 ULONG max_bcount
= 0;
6829 ULONG wordCount
= 0;
6830 UCHAR statusByte
,statusByte2
;
6833 BOOLEAN use_dma
= FALSE
;
6836 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6837 LunExt
= chan
->lun
[DeviceNumber
];
6839 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6840 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6842 if(LunExt
->opt_ReadOnly
&&
6843 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6844 if(LunExt
->opt_ReadOnly
== 1) {
6845 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6846 return SRB_STATUS_ERROR
;
6848 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6849 return SRB_STATUS_SUCCESS
;
6853 // Set data buffer pointer and words left.
6854 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6856 if(AtaReq
->WordsTransfered
) {
6857 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6858 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6859 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6860 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6862 AtaReq
->TransferLength
/2,
6863 AtaReq
->WordsTransfered
,
6866 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6867 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6868 // Set up 1st block.
6869 switch(Srb
->Cdb
[0]) {
6872 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6873 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6876 case SCSIOP_WRITE12
:
6877 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6878 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6881 case SCSIOP_WRITE16
:
6882 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6883 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6886 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6888 AtaReq
->TransferLength
/2,
6891 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6894 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6896 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6897 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6899 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6905 if(LunExt
->errRetry
&&
6906 lba
== LunExt
->errLastLba
&&
6907 /* AtaReq->bcount && */ // errRetry can be set only for non-zero bcount
6908 AtaReq
->bcount
== LunExt
->errBCount
) {
6909 KdPrint3((PRINT_PREFIX
"IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n",
6910 LunExt
->errRetry
, LunExt
->errLastLba
, LunExt
->errBCount
));
6911 if(AtaReq
->retry
< MAX_RETRIES
) {
6912 AtaReq
->retry
= LunExt
->errRetry
;
6913 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
6915 LunExt
->errRetry
= 0;
6918 // assume best case here
6919 // we cannot reinit Dma until previous request is completed
6920 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6921 UniataAhciSetupCmdPtr(AtaReq
);
6922 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6923 (PUCHAR
)(AtaReq
->DataBuffer
),
6924 AtaReq
->bcount
* DEV_BSIZE
)) {
6925 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6926 return SRB_STATUS_ERROR
;
6929 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6931 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6932 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6933 (PUCHAR
)(AtaReq
->DataBuffer
),
6934 AtaReq
->bcount
* DEV_BSIZE
)) {
6939 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6940 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6941 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6943 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6944 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6945 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6947 (USHORT
)(AtaReq
->bcount
),
6949 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6953 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6954 return SRB_STATUS_ERROR
;
6957 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6958 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6961 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6963 } else { // exec_only
6964 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6967 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6971 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6973 return SRB_STATUS_PENDING
;
6976 // if this is queued request, reinit DMA and check
6977 // if DMA mode is still available
6978 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6979 if (/*EnableDma &&*/
6980 (LunExt
->TransferMode
>= ATA_DMA
)) {
6983 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6987 // Check if write request.
6988 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6990 // Prepare read command.
6992 cmd
= IDE_COMMAND_READ_DMA
;
6994 if(LunExt
->MaximumBlockXfer
) {
6995 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6997 cmd
= IDE_COMMAND_READ
;
7001 // Prepare write command.
7003 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
7004 cmd
= IDE_COMMAND_WRITE_DMA
;
7006 if (LunExt
->MaximumBlockXfer
) {
7007 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
7009 if (AtaReq
->WordsLeft
< wordCount
) {
7010 // Transfer only words requested.
7011 wordCount
= AtaReq
->WordsLeft
;
7013 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
7016 wordCount
= DEV_BSIZE
/2;
7017 cmd
= IDE_COMMAND_WRITE
;
7022 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
7023 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
7025 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7027 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7030 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7031 // AHCI doesn't distinguish DMA and PIO
7032 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7033 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7034 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
7035 InterlockedExchange(&(chan
->CheckIntr
),
7037 return SRB_STATUS_PENDING
;
7040 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
7043 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
7044 if(g_opt_BochsDmaReadWorkaround
&&
7045 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7046 KdPrint2((PRINT_PREFIX
"CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
7047 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7050 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
7052 (USHORT
)(AtaReq
->bcount
),
7053 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
7055 /* if(statusByte2 != IDE_STATUS_WRONG) {
7056 GetStatus(chan, statusByte2);
7058 if(statusByte2
& IDE_STATUS_ERROR
) {
7059 // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks).
7060 // Because some devices doesn't reset ERR from previous command immediately after getting new one.
7061 // On the other hand we cannot wait here because of possible timeout condition
7062 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7063 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
7064 return SRB_STATUS_ERROR
;
7067 if(!g_opt_BochsDmaReadWorkaround
||
7068 !(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7069 //GetStatus(chan, statusByte2);
7070 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7073 return SRB_STATUS_PENDING
;
7076 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
7078 (USHORT
)(AtaReq
->bcount
),
7079 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
7082 if (!(statusByte
& IDE_STATUS_DRQ
) ||
7083 statusByte
== IDE_STATUS_WRONG
) {
7085 if(statusByte
== IDE_STATUS_WRONG
) {
7086 KdPrint2((PRINT_PREFIX
7087 "IdeReadWrite: error sending command (%#x)\n",
7090 KdPrint2((PRINT_PREFIX
7091 "IdeReadWrite: DRQ never asserted (%#x)\n",
7095 AtaReq
->WordsLeft
= 0;
7097 // Clear interrupt expecting flag.
7098 UniataExpectChannelInterrupt(chan
, FALSE
);
7099 InterlockedExchange(&(chan
->CheckIntr
),
7102 // Clear current SRB.
7103 UniataRemoveRequest(chan
, Srb
);
7105 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
7108 UniataExpectChannelInterrupt(chan
, TRUE
);
7109 InterlockedExchange(&(chan
->CheckIntr
),
7112 // Write next DEV_BSIZE/2*N words.
7113 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) || (wordCount
& 1)) {
7114 KdPrint2((PRINT_PREFIX
7115 "IdeReadWrite: Write %#x words\n", wordCount
));
7120 UniataGetPioTiming(LunExt
));
7124 KdPrint2((PRINT_PREFIX
7125 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
7128 (PULONG
)(AtaReq
->DataBuffer
),
7130 UniataGetPioTiming(LunExt
));
7133 // Adjust buffer address and words left count.
7134 AtaReq
->WordsLeft
-= wordCount
;
7135 AtaReq
->DataBuffer
+= wordCount
;
7136 AtaReq
->WordsTransfered
+= wordCount
;
7138 // Wait for interrupt.
7139 return SRB_STATUS_PENDING
;
7141 } // end IdeReadWrite()
7147 Routine Description:
7148 This routine handles IDE Verify.
7151 HwDeviceExtension - HBA miniport driver's adapter data storage
7152 Srb - IO request packet
7161 IN PVOID HwDeviceExtension
,
7162 IN PSCSI_REQUEST_BLOCK Srb
7165 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7166 UCHAR lChannel
= GET_CHANNEL(Srb
);
7167 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
7168 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7169 PHW_LU_EXTENSION LunExt
;
7170 //ULONG ldev = GET_LDEV(Srb);
7171 ULONG DeviceNumber
= GET_CDEV(Srb
);
7173 ULONGLONG startingSector
=0;
7176 ULONGLONG endSector
;
7177 ULONG sectorCount
=0;
7180 LunExt
= chan
->lun
[DeviceNumber
];
7181 // Drive has these number sectors.
7182 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
7183 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
7184 LunExt
->IdentifyData
.NumberOfHeads
*
7185 LunExt
->IdentifyData
.NumberOfCylinders
;
7188 KdPrint2((PRINT_PREFIX
7189 "IdeVerify: Total sectors %#x\n",
7192 // Get starting sector number from CDB.
7193 switch(Srb
->Cdb
[0]) {
7195 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7196 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7198 case SCSIOP_VERIFY12
:
7199 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
7200 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7202 case SCSIOP_VERIFY16
:
7203 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7204 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7208 KdPrint2((PRINT_PREFIX
7209 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
7213 endSector
= startingSector
+ sectorCount
;
7215 KdPrint2((PRINT_PREFIX
7216 "IdeVerify: Ending sector %#I64x\n",
7219 if (endSector
> sectors
) {
7221 // Too big, round down.
7222 KdPrint2((PRINT_PREFIX
7223 "IdeVerify: Truncating request to %#x blocks\n",
7224 sectors
- startingSector
- 1));
7226 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
7230 // Set up sector count register. Round up to next block.
7231 if (sectorCount
> 0xFF) {
7232 sectorCount
= (USHORT
)0xFF;
7236 // Set data buffer pointer and words left.
7237 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7238 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7240 // Indicate expecting an interrupt.
7241 InterlockedExchange(&(chan
->CheckIntr
),
7244 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
7246 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
7247 IDE_COMMAND_VERIFY
, lba
,
7248 (USHORT
)sectorCount
,
7251 if(!(statusByte
& IDE_STATUS_ERROR
)) {
7252 // Wait for interrupt.
7253 return SRB_STATUS_PENDING
;
7255 return SRB_STATUS_ERROR
;
7257 } // end IdeVerify()
7259 #endif //UNIATA_CORE
7263 Routine Description:
7264 Send ATAPI packet command to device.
7267 HwDeviceExtension - HBA miniport driver's adapter data storage
7268 Srb - IO request packet
7276 IN PVOID HwDeviceExtension
,
7277 IN PSCSI_REQUEST_BLOCK Srb
,
7281 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7282 UCHAR lChannel
= GET_CHANNEL(Srb
);
7283 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
7284 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7285 PHW_LU_EXTENSION LunExt
;
7286 //ULONG ldev = GET_LDEV(Srb);
7287 ULONG DeviceNumber
= GET_CDEV(Srb
);
7289 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
7290 UCHAR interruptReason
;
7291 BOOLEAN use_dma
= FALSE
;
7292 BOOLEAN dma_reinited
= FALSE
;
7293 BOOLEAN retried
= FALSE
;
7297 LunExt
= chan
->lun
[DeviceNumber
];
7299 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
7300 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7301 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7304 #ifdef UNIATA_DUMP_ATAPI
7305 if(CmdAction
& CMD_ACTION_PREPARE
) {
7309 PCHAR ModeSelectData
;
7312 Cdb
= (PCDB
)(Srb
->Cdb
);
7313 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
7314 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
7315 CdbDataLen
= Srb
->DataTransferLength
;
7317 if(CdbDataLen
> 0x1000) {
7318 CdbDataLen
= 0x1000;
7322 KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7323 KdPrint2(("P:T:D=%d:%d:%d\n",
7327 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
7330 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
7331 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
7332 Cdb
->WRITE_CD
.LBA
[0],
7333 Cdb
->WRITE_CD
.LBA
[1],
7334 Cdb
->WRITE_CD
.LBA
[2],
7335 Cdb
->WRITE_CD
.LBA
[3]
7338 if(ScsiCommand
== SCSIOP_WRITE12
) {
7339 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
7340 Cdb
->CDB12READWRITE
.LBA
[0],
7341 Cdb
->CDB12READWRITE
.LBA
[1],
7342 Cdb
->CDB12READWRITE
.LBA
[2],
7343 Cdb
->CDB12READWRITE
.LBA
[3]
7346 if(ScsiCommand
== SCSIOP_WRITE16
) {
7347 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
7348 Cdb
->CDB16READWRITE
.LBA
[0],
7349 Cdb
->CDB16READWRITE
.LBA
[1],
7350 Cdb
->CDB16READWRITE
.LBA
[2],
7351 Cdb
->CDB16READWRITE
.LBA
[3],
7352 Cdb
->CDB16READWRITE
.LBA
[4],
7353 Cdb
->CDB16READWRITE
.LBA
[5],
7354 Cdb
->CDB16READWRITE
.LBA
[6],
7355 Cdb
->CDB16READWRITE
.LBA
[7]
7358 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
7359 KdPrint(("ModeSelect 6\n"));
7360 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7361 ModeSelectData
= CdbData
+4;
7362 KdDump(CdbData
, CdbDataLen
);
7364 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
7365 KdPrint(("ModeSelect 10\n"));
7366 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7367 ModeSelectData
= CdbData
+8;
7368 KdDump(CdbData
, CdbDataLen
);
7370 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7371 KdPrint(("Send buffer to device:\n"));
7372 KdDump(CdbData
, CdbDataLen
);
7377 #endif //UNIATA_DUMP_ATAPI
7380 if(CmdAction
== CMD_ACTION_PREPARE
) {
7381 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
7383 switch (Srb
->Cdb
[0]) {
7384 case SCSIOP_RECEIVE
:
7389 case SCSIOP_WRITE12
:
7391 case SCSIOP_WRITE16
:
7394 case SCSIOP_READ_CD
:
7395 case SCSIOP_READ_CD_MSF
:
7396 if(deviceExtension
->opt_AtapiDmaRawRead
) {
7402 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
7403 return SRB_STATUS_BUSY
;
7406 #ifdef UNIATA_INIT_CHANGERS
7407 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7408 !AtaReq
->OriginalSrb
) {
7409 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
7410 return SRB_STATUS_BUSY
;
7412 #endif // UNIATA_INIT_CHANGERS
7416 // standard atapi.sys claims:
7418 // We need to know how many platters our atapi cd-rom device might have.
7419 // Before anyone tries to send a srb to our target for the first time,
7420 // we must "secretly" send down a separate mechanism status srb in order to
7421 // initialize our device extension changer data. That's how we know how
7422 // many platters our target has.
7425 // some devices freeze (sometimes) forever on this command
7426 // Let CD-ROM driver send this command itself, if it find it necessary
7427 // We shall just parse output (if any)
7429 #ifdef UNIATA_INIT_CHANGERS
7430 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7431 !AtaReq
->OriginalSrb
) {
7435 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
7436 // Set this flag now. If the device hangs on the mech. status
7437 // command, we will not have the chance to set it.
7438 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
7440 chan
->MechStatusRetryCount
= 3;
7441 AtaReq
->OriginalSrb
= Srb
;
7442 AtaReq
->Srb
= BuildMechanismStatusSrb (
7446 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
7447 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7448 if (srbStatus
== SRB_STATUS_PENDING
) {
7449 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
7453 // failed! Get the sense key and maybe try again
7454 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
7455 AtaReq
->OriginalSrb
);
7457 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7459 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
7461 if (srbStatus
== SRB_STATUS_PENDING
) {
7462 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7466 // failed again ? should not get here
7467 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
7468 AtaReq
->OriginalSrb
= NULL
;
7472 #endif // UNIATA_INIT_CHANGERS
7473 #endif //UNIATA_CORE
7475 if((CmdAction
& CMD_ACTION_PREPARE
) &&
7476 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
7478 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
7480 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
7481 (Srb
->CdbLength
> 12)) {
7482 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
7483 return SRB_STATUS_INVALID_REQUEST
;
7486 // Set data buffer pointer and words left.
7487 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7488 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7489 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
7490 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7491 // reset this to force PRD init. May be already setup by recursive SRB
7492 AtaReq
->dma_entries
= 0;
7494 // check if reorderable
7495 switch(Srb
->Cdb
[0]) {
7497 case SCSIOP_WRITE16
:
7499 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7500 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7504 case SCSIOP_WRITE12
:
7506 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7512 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7514 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7516 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
7517 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7518 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7519 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7520 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7521 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7524 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7525 if(!AtaReq
->TransferLength
) {
7526 KdPrint((" assume 0-transfer\n"));
7528 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7529 KdPrint((" assume OUT\n"));
7530 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7532 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7533 KdPrint((" assume IN\n"));
7534 AtaReq
->Flags
|= REQ_FLAG_READ
;
7539 // check if DMA read/write
7540 if(g_opt_AtapiNoDma
) {
7541 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n"));
7544 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7545 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7549 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7550 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7554 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7555 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7557 if(AtaReq
->TransferLength
&& !(AtaReq
->TransferLength
& 0x0f)) {
7558 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: try DMA setup\n"));
7559 // try use DMA if TransferLength is 16-byte aligned
7560 switch(Srb
->Cdb
[0]) {
7562 case SCSIOP_WRITE12
:
7563 case SCSIOP_WRITE16
:
7565 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7568 case SCSIOP_RECEIVE
:
7573 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7575 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7576 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7579 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7580 (PUCHAR
)(AtaReq
->DataBuffer
),
7581 Srb
->DataTransferLength
7582 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7584 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7589 case SCSIOP_READ_CD
:
7590 case SCSIOP_READ_CD_MSF
:
7591 if(deviceExtension
->opt_AtapiDmaRawRead
)
7592 goto call_dma_setup
;
7596 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7597 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7602 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7603 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7615 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7616 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7619 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7620 (PUCHAR
)(AtaReq
->DataBuffer
),
7621 Srb
->DataTransferLength
)) {
7622 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7625 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7629 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq
->TransferLength
));
7633 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7635 UniataAhciSetupCmdPtr(AtaReq
);
7637 if(!Srb
->DataTransferLength
) {
7638 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7641 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7642 (PUCHAR
)(AtaReq
->DataBuffer
),
7643 Srb
->DataTransferLength
)) {
7644 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7645 return SRB_STATUS_ERROR
;
7648 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7650 FeatureReg
|= ATA_F_DMA
;
7651 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
) {
7652 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7653 KdPrint2((PRINT_PREFIX
"Set DMADir.\n"));
7654 FeatureReg
|= ATA_F_DMAREAD
;
7659 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7660 // this is done in UniataAhciSetupFIS_H2D()
7661 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7662 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7664 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7665 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7666 IDE_COMMAND_ATAPI_PACKET
/* command */,
7668 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7669 FeatureReg
/* feature */
7673 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7674 return SRB_STATUS_ERROR
;
7677 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7678 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7679 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7680 fis_size
, DeviceNumber
);
7682 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7686 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7687 // if this is queued request, reinit DMA and check
7688 // if DMA mode is still available
7689 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7690 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7691 if (/*EnableDma &&*/
7692 (LunExt
->TransferMode
>= ATA_DMA
)) {
7693 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7696 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7697 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7700 dma_reinited
= TRUE
;
7704 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7705 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7706 return SRB_STATUS_PENDING
;
7708 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7709 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7710 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7713 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7714 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7716 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7717 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7718 } if(AtaReq
->TransferLength
) {
7720 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7721 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7722 if (/*EnableDma &&*/
7723 (LunExt
->TransferMode
>= ATA_DMA
)) {
7726 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7731 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7733 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7734 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7735 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7736 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7739 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7740 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7741 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7744 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7746 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7747 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7749 // Make sure command is to ATAPI device.
7750 flags
= LunExt
->DeviceFlags
;
7751 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7752 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7754 // Indicate no device found at this address.
7755 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7756 return SRB_STATUS_SELECTION_TIMEOUT
;
7758 } else if(Srb
->Lun
> 0) {
7759 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7760 return SRB_STATUS_SELECTION_TIMEOUT
;
7763 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7764 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7765 return SRB_STATUS_SELECTION_TIMEOUT
;
7768 // Select device 0 or 1. Or more for PM
7769 SelectDrive(chan
, DeviceNumber
);
7771 // Verify that controller is ready for next command.
7772 GetStatus(chan
, statusByte
);
7773 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7775 if(statusByte
== IDE_STATUS_WRONG
) {
7776 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7779 if(statusByte
& IDE_STATUS_BUSY
) {
7780 if(statusByte
& IDE_STATUS_DSC
) {
7781 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7783 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7784 // We have to make reset here, since we are expecting device to be available
7785 //return SRB_STATUS_BUSY; // this cause queue freeze
7789 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7791 // Check if command list is free
7792 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7794 // controller is busy, however we expect it to be free
7795 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7799 if(statusByte
& IDE_STATUS_ERROR
) {
7800 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7802 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7803 // Read the error reg. to clear it and fail this request.
7804 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7805 return MapError(deviceExtension
, Srb
);
7807 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7810 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7811 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7812 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7813 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7815 AtapiStallExecution(200);
7816 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7817 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7818 return SRB_STATUS_PENDING
;
7821 if(IS_RDP(Srb
->Cdb
[0])) {
7823 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7827 if(statusByte
& IDE_STATUS_DRQ
) {
7829 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7831 // Try to drain the data that one preliminary device thinks that it has
7832 // to transfer. Hopefully this random assertion of DRQ will not be present
7833 // in production devices.
7834 statusByte
= AtapiSuckPort2(chan
);
7836 for (i = 0; i < 0x10000; i++) {
7837 GetStatus(chan, statusByte);
7838 if(statusByte & IDE_STATUS_DRQ) {
7839 AtapiReadPort2(chan, IDX_IO1_i_Data);
7845 if (statusByte
& IDE_STATUS_DRQ
) {
7846 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte
));
7848 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7850 AtapiSoftReset(chan
, DeviceNumber
);
7852 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7853 // Re-initialize Atapi device.
7854 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7856 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7857 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7859 // Inform the port driver that the bus has been reset.
7860 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7861 // Clean up device extension fields that AtapiStartIo won't.
7862 UniataExpectChannelInterrupt(chan
, FALSE
);
7864 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7867 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7869 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7870 return SRB_STATUS_BUS_RESET;
7873 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7877 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7878 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7879 return SRB_STATUS_SELECTION_TIMEOUT
;
7883 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7884 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7885 Srb
->Cdb
[1] &= ~0xE0;
7886 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7887 // Torisan changer. TUR's are overloaded to be platter switches.
7888 Srb
->Cdb
[7] = Srb
->Lun
;
7895 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7897 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7900 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7901 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7902 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7903 UniataExpectChannelInterrupt(chan
, TRUE
);
7904 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7905 return SRB_STATUS_PENDING
;
7908 statusByte
= WaitOnBusy(chan
);
7909 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7913 FeatureReg
|= ATA_F_DMA
;
7914 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
) {
7915 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7916 FeatureReg
|= ATA_F_DMAREAD
;
7921 // Write transfer byte count to registers.
7922 if (Srb
->DataTransferLength
>= 0x10000) {
7923 byteCountLow
= byteCountHigh
= 0xFF;
7925 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7926 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7929 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg
, byteCountHigh
, byteCountLow
));
7931 if (flags
& DFLAGS_INT_DRQ
) {
7932 // This device interrupts when ready to receive the packet.
7933 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7936 UniataExpectChannelInterrupt(chan
, TRUE
);
7937 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7938 InterlockedExchange(&(chan
->CheckIntr
),
7940 // inform driver that packet command must be sent in ISR
7941 flags
|= DFLAGS_INT_DRQ
;
7943 // This device quickly sets DRQ when ready to receive the packet.
7944 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7947 UniataExpectChannelInterrupt(chan
, TRUE
);
7948 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7949 InterlockedExchange(&(chan
->CheckIntr
),
7952 if(g_opt_AtapiSendDisableIntr
) {
7953 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7955 // remember status. Later we may check if error appeared after cmd packet
7956 statusByte0
= statusByte
;
7959 // must be already selected, experimental for ROS BUG-9119
7960 //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
7961 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_Feature
/*IDX_IO1_o_Feature*/, FeatureReg
);
7962 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0); // experimental for ROS BUG-9119
7963 //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0); // experimental for ROS BUG-9119
7964 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7965 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7966 // Write ATAPI packet command.
7967 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_Command
/*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET
);
7969 if (flags
& DFLAGS_INT_DRQ
) {
7970 // Wait for interrupt and send PACKET there
7971 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7972 return SRB_STATUS_PENDING
;
7978 statusByte = WaitForDrq(chan);
7980 // Need to read status register and clear interrupt (if any)
7981 GetBaseStatus(chan, statusByte);
7983 if (!(statusByte & IDE_STATUS_DRQ)) {
7984 if(g_opt_AtapiSendDisableIntr) {
7985 AtapiEnableInterrupts(deviceExtension, lChannel);
7987 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
7988 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7989 return SRB_STATUS_ERROR;
7992 GetStatus(chan
, statusByte
);
7993 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7995 //statusByte = WaitOnBaseBusy(chan);
7997 // Indicate expecting an interrupt and wait for it.
7998 UniataExpectChannelInterrupt(chan
, TRUE
);
8000 for(i
=0; i
<5000; i
++) {
8001 if(g_opt_AtapiSendDisableIntr
) {
8002 GetStatus(chan
, statusByte
);
8004 GetBaseStatus(chan
, statusByte
);
8006 interruptReason
= AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
8007 //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
8008 if(((interruptReason
& ATAPI_IR_COD
) == ATAPI_IR_COD_Cmd
) &&
8009 (((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRQ
)) == IDE_STATUS_DRQ
))) {
8012 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
8014 // KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason));
8017 if(((interruptReason
& ATAPI_IR_COD
) != ATAPI_IR_COD_Cmd
) ||
8018 (((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRQ
)) != IDE_STATUS_DRQ
)) ) {
8019 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: no CoD raised, abort cmd\n"));
8020 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x (%d)\n", interruptReason
, i
));
8021 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
8022 if(g_opt_AtapiSendDisableIntr
) {
8023 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8025 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ+CoD never asserted\n"));
8026 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8027 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Err on cmd: (%#x)\n", statusByte
));
8028 if(statusByte
>> 4) {
8029 GetBaseStatus(chan
, statusByte
);
8030 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8031 return MapError(deviceExtension
, Srb
);
8034 // AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8035 // return SRB_STATUS_ERROR;
8037 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason
, i
));
8040 GetBaseStatus(chan
, statusByte
);
8042 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
8043 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
8045 if(g_opt_AtapiSendDisableIntr
) {
8046 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8049 // Send CDB to device.
8052 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
8055 GetStatus(chan
, statusByte
);
8056 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
8058 // When we operate in DMA mode, we should not start transfer when there is an error on entry
8059 // Interrupt may never come in such case.
8060 if(statusByte
& IDE_STATUS_ERROR
) {
8062 GetBaseStatus(chan
, statusByte
);
8063 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
8065 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
8066 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
8068 // TODO: we should check interruptReason and decide what to do now
8070 // Read the error reg. to clear it and fail this request.
8071 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8072 return MapError(deviceExtension
, Srb
);
8074 if(statusByte
& IDE_STATUS_DRQ
) {
8075 // Some devices require this. If error condition is not checked in such a way,
8076 // device may not operate correctly and would be treated as failed
8077 // (and finally invisible for OS)
8078 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ on cmd: (%#x)\n", statusByte
));
8079 // Read the error reg. to clear it and fail this request.
8080 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8081 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Err on cmd: (%#x)\n", statusByte
));
8082 if(statusByte
>> 4) {
8083 GetBaseStatus(chan
, statusByte
);
8084 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8085 return MapError(deviceExtension
, Srb
);
8089 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
8090 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8093 InterlockedExchange(&(chan
->CheckIntr
),
8095 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
8097 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
8099 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
8100 return SRB_STATUS_PENDING
;
8102 } // end AtapiSendCommand()
8109 Routine Description:
8110 Program ATA registers for IDE disk transfer.
8113 HwDeviceExtension - ATAPI driver storage.
8114 Srb - System request block.
8117 SRB status (pending if all goes well).
8122 ULONG check_point
= 0;
8123 #define SetCheckPoint(cp) { check_point = (cp) ; }
8125 #define SetCheckPoint(cp)
8131 IN PVOID HwDeviceExtension
,
8132 IN PSCSI_REQUEST_BLOCK Srb
,
8137 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
8140 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8145 PHW_LU_EXTENSION LunExt
;
8149 UCHAR statusByte
,errorByte
;
8150 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
8153 PMODE_PARAMETER_HEADER modeData
;
8160 //ULONG __ebp__ = 0;
8162 SetCheckPoint(0x20);
8163 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
8168 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
8169 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
8170 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
8171 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
8172 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
8174 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
8175 Srb->SrbExtension));
8176 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
8179 SetCheckPoint(0x30);
8180 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8182 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
8184 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
8186 KdPrint2((PRINT_PREFIX
"** --- **\n"));
8188 lChannel
= GET_CHANNEL(Srb
);
8189 chan
= &(deviceExtension
->chan
[lChannel
]);
8190 //ldev = GET_LDEV(Srb);
8191 DeviceNumber
= GET_CDEV(Srb
);
8192 LunExt
= chan
->lun
[DeviceNumber
];
8194 SetCheckPoint(0x40);
8195 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
8196 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
8198 cdb
= (PCDB
)(Srb
->Cdb
);
8200 if(CmdAction
== CMD_ACTION_PREPARE
) {
8201 switch (Srb
->Cdb
[0]) {
8202 case SCSIOP_SERVICE_ACTION16
:
8203 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8206 goto default_no_prep
;
8209 case SCSIOP_INQUIRY
: // now it requires device access
8211 case SCSIOP_READ_CAPACITY
:
8215 case SCSIOP_WRITE12
:
8217 case SCSIOP_WRITE16
:
8218 case SCSIOP_REQUEST_SENSE
:
8220 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
8226 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
8227 return SRB_STATUS_BUSY
;
8231 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
8232 switch (Srb
->Cdb
[0]) {
8233 case SCSIOP_INQUIRY
:
8235 KdPrint2((PRINT_PREFIX
8236 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
8237 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8238 // Filter out wrong TIDs.
8239 if ((Srb
->Lun
!= 0) ||
8240 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
8241 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
8243 KdPrint2((PRINT_PREFIX
8244 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
8245 // Indicate no device found at this address.
8246 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8251 KdPrint2((PRINT_PREFIX
8252 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
8253 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8254 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
8256 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8258 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
8259 KdPrint2((PRINT_PREFIX
8260 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
8261 // Indicate no device found at this address.
8263 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8267 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
8268 KdPrint2((PRINT_PREFIX
8269 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
8270 // Indicate no device found at this address.
8271 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
8273 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8278 // Zero INQUIRY data structure.
8279 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8281 // Standard IDE interface only supports disks.
8282 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
8284 // Set the removable bit, if applicable.
8285 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
8286 KdPrint2((PRINT_PREFIX
8287 "RemovableMedia\n"));
8288 inquiryData
->RemovableMedia
= 1;
8290 // Set the Relative Addressing (LBA) bit, if applicable.
8291 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
8292 inquiryData
->RelativeAddressing
= 1;
8293 KdPrint2((PRINT_PREFIX
8294 "RelativeAddressing\n"));
8296 // Set the CommandQueue bit
8297 inquiryData
->CommandQueue
= 1;
8299 // Fill in vendor identification fields.
8300 for (i
= 0; i
< 24; i
+= 2) {
8301 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
8304 // Initialize unused portion of product id.
8305 for (i = 0; i < 4; i++) {
8306 inquiryData->ProductId[12+i] = ' ';
8309 // Move firmware revision from IDENTIFY data to
8310 // product revision in INQUIRY data.
8311 for (i
= 0; i
< 4; i
+= 2) {
8312 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
8315 status
= SRB_STATUS_SUCCESS
;
8320 case SCSIOP_REPORT_LUNS
: {
8323 PREPORT_LUNS_INFO_HDR LunInfo
;
8325 KdPrint2((PRINT_PREFIX
8326 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
8327 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8329 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
8336 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
8337 RtlZeroMemory(LunInfo
, 16);
8339 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
8340 Srb
->DataTransferLength
= 16;
8341 status
= SRB_STATUS_SUCCESS
;
8345 case SCSIOP_MODE_SENSE
:
8347 KdPrint2((PRINT_PREFIX
8348 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8349 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8351 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
8352 PMODE_POWER_CONDITION_PAGE modeData
;
8354 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
8355 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
8356 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
8357 status
= SRB_STATUS_DATA_OVERRUN
;
8359 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
8360 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
8362 modeData
->PageLength
= sizeof(MODE_POWER_CONDITION_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8364 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
8366 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
8367 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
8368 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
8369 status
= SRB_STATUS_SUCCESS
;
8372 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
8373 PMODE_CACHING_PAGE modeData
;
8375 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
8376 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
8377 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
8378 status
= SRB_STATUS_DATA_OVERRUN
;
8380 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
8381 modeData
->PageCode
= MODE_PAGE_CACHING
;
8382 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8383 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
8384 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
8385 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
8386 status
= SRB_STATUS_SUCCESS
;
8389 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8391 // This is used to determine if the media is write-protected.
8392 // Since IDE does not support mode sense then we will modify just the portion we need
8393 // so the higher level driver can determine if media is protected.
8395 //SelectDrive(chan, DeviceNumber);
8396 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8397 //statusByte = WaitOnBusy(chan);
8398 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8400 if (!(statusByte
& IDE_STATUS_ERROR
)) {
8402 // no error occured return success, media is not protected
8403 UniataExpectChannelInterrupt(chan
, FALSE
);
8404 InterlockedExchange(&(chan
->CheckIntr
),
8406 status
= SRB_STATUS_SUCCESS
;
8410 // error occured, handle it locally, clear interrupt
8411 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8413 GetBaseStatus(chan
, statusByte
);
8414 UniataExpectChannelInterrupt(chan
, FALSE
);
8415 InterlockedExchange(&(chan
->CheckIntr
),
8417 status
= SRB_STATUS_SUCCESS
;
8419 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
8421 //media is write-protected, set bit in mode sense buffer
8422 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
8424 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
8425 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
8428 status
= SRB_STATUS_SUCCESS
;
8430 status
= SRB_STATUS_INVALID_REQUEST
;
8434 case SCSIOP_TEST_UNIT_READY
:
8436 KdPrint2((PRINT_PREFIX
8437 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
8438 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8439 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8441 // Select device 0 or 1.
8442 //SelectDrive(chan, DeviceNumber);
8443 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8444 // Wait for busy. If media has not changed, return success
8445 //statusByte = WaitOnBusy(chan);
8446 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8448 if (!(statusByte
& IDE_STATUS_ERROR
)){
8449 UniataExpectChannelInterrupt(chan
, FALSE
);
8450 InterlockedExchange(&(chan
->CheckIntr
),
8452 status
= SRB_STATUS_SUCCESS
;
8454 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8455 if (errorByte
== IDE_ERROR_DATA_ERROR
){
8457 // Special case: If current media is write-protected,
8458 // the 0xDA command will always fail since the write-protect bit
8459 // is sticky,so we can ignore this error
8460 GetBaseStatus(chan
, statusByte
);
8461 UniataExpectChannelInterrupt(chan
, FALSE
);
8462 InterlockedExchange(&(chan
->CheckIntr
),
8464 status
= SRB_STATUS_SUCCESS
;
8468 // Request sense buffer to be build
8469 UniataExpectChannelInterrupt(chan
, TRUE
);
8470 InterlockedExchange(&(chan
->CheckIntr
),
8472 status
= SRB_STATUS_PENDING
;
8476 status
= SRB_STATUS_SUCCESS
;
8481 case SCSIOP_READ_CAPACITY
:
8483 KdPrint2((PRINT_PREFIX
8484 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8485 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8486 // Claim 512 byte blocks (big-endian).
8487 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8489 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
8490 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8492 // Calculate last sector.
8493 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
8494 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
8495 LunExt
->IdentifyData
.NumberOfHeads
*
8496 LunExt
->IdentifyData
.NumberOfCylinders
;
8500 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
8501 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
8502 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
8504 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
8506 KdPrint2((PRINT_PREFIX
8507 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
8509 LunExt
->IdentifyData
.SectorsPerTrack
,
8510 LunExt
->IdentifyData
.NumberOfHeads
,
8511 LunExt
->IdentifyData
.NumberOfCylinders
));
8514 status
= SRB_STATUS_SUCCESS
;
8517 case SCSIOP_SERVICE_ACTION16
:
8519 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8520 KdPrint2((PRINT_PREFIX
8521 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8522 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8523 // Claim 512 byte blocks (big-endian).
8524 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8526 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
8527 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8529 // Calculate last sector.
8530 if(!(lba
= LunExt
->NumOfSectors
)) {
8531 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
8532 LunExt
->IdentifyData
.NumberOfHeads
*
8533 LunExt
->IdentifyData
.NumberOfCylinders
;
8536 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
8538 KdPrint2((PRINT_PREFIX
8539 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8541 LunExt
->IdentifyData
.SectorsPerTrack
,
8542 LunExt
->IdentifyData
.NumberOfHeads
,
8543 LunExt
->IdentifyData
.NumberOfCylinders
));
8545 status
= SRB_STATUS_SUCCESS
;
8552 case SCSIOP_VERIFY12
:
8553 case SCSIOP_VERIFY16
:
8555 KdPrint2((PRINT_PREFIX
8556 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8557 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8558 status
= IdeVerify(HwDeviceExtension
,Srb
);
8565 case SCSIOP_WRITE12
:
8567 case SCSIOP_WRITE16
:
8569 KdPrint2((PRINT_PREFIX
8570 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8571 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
8572 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8573 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
8574 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
8575 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
8576 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
8577 status
= IdeReadWrite(HwDeviceExtension
,
8581 case SCSIOP_START_STOP_UNIT
:
8583 KdPrint2((PRINT_PREFIX
8584 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8585 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8586 //Determine what type of operation we should perform
8590 if(cdb
->START_STOP
.FL
||
8591 cdb
->START_STOP
.FormatLayerNumber
||
8592 cdb
->START_STOP
.Reserved2
||
8593 cdb
->START_STOP
.Reserved2_2
||
8594 cdb
->START_STOP
.Reserved3
||
8599 if (cdb
->START_STOP
.PowerConditions
) {
8600 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8601 switch(cdb
->START_STOP
.PowerConditions
) {
8602 case StartStop_Power_Idle
:
8603 command
= IDE_COMMAND_IDLE_IMMED
;
8605 case StartStop_Power_Standby
:
8606 command
= IDE_COMMAND_STANDBY_IMMED
;
8608 case StartStop_Power_Sleep
:
8609 // TODO: we should save power state in order to know
8610 // that RESET sould be issued to revert device into
8613 command
= IDE_COMMAND_SLEEP
;
8618 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8620 if (cdb
->START_STOP
.LoadEject
== 1) {
8621 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8623 // first select device 0 or 1.
8624 //SelectDrive(chan, DeviceNumber);
8625 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8626 command
= IDE_COMMAND_MEDIA_EJECT
;
8628 if (cdb
->START_STOP
.Start
== 0) {
8629 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8630 command
= IDE_COMMAND_STANDBY_IMMED
;
8632 // TODO: we may need to perform hard reset (after sleep) or
8633 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8634 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8636 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8637 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8638 status
= SRB_STATUS_SUCCESS
;
8641 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8642 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8643 command
= IDE_COMMAND_IDLE_IMMED
;
8645 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8646 status
= SRB_STATUS_SUCCESS
;
8651 statusByte
= WaitOnBaseBusy(chan
);
8652 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8653 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8654 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8655 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8659 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8660 if (Srb
->SenseInfoBuffer
) {
8662 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8664 senseBuffer
->ErrorCode
= 0x70;
8665 senseBuffer
->Valid
= 1;
8666 senseBuffer
->AdditionalSenseLength
= 0xb;
8667 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8668 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8669 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8671 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8672 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8674 status
= SRB_STATUS_ERROR
;
8678 case SCSIOP_MEDIUM_REMOVAL
:
8680 cdb
= (PCDB
)Srb
->Cdb
;
8682 if(LunExt
->IdentifyData
.Removable
) {
8683 statusByte
= WaitOnBaseBusy(chan
);
8685 //SelectDrive(chan, DeviceNumber);
8686 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8687 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8688 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8690 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8691 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8693 status
= SRB_STATUS_SUCCESS
;
8695 status
= SRB_STATUS_INVALID_REQUEST
;
8700 // Note: I don't implement this, because NTFS driver too often issues this command
8701 // It causes awful performance degrade. However, if somebody wants, I will implement
8702 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8703 case SCSIOP_FLUSH_BUFFER
:
8704 case SCSIOP_SYNCHRONIZE_CACHE
:
8706 SelectDrive(chan
, DeviceNumber
);
8707 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8708 status
= SRB_STATUS_SUCCESS
;
8709 // status = SRB_STATUS_PENDING;
8710 statusByte
= WaitOnBusy(chan
);
8714 case SCSIOP_REQUEST_SENSE
:
8715 // this function makes sense buffers to report the results
8716 // of the original GET_MEDIA_STATUS command
8718 KdPrint2((PRINT_PREFIX
8719 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8720 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8721 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8722 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8725 status
= SRB_STATUS_INVALID_REQUEST
;
8729 case SCSIOP_ATA_PASSTHROUGH
:
8732 BOOLEAN use_dma
= FALSE
;
8735 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8737 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8738 //lChannel = Srb->TargetId >> 1;
8740 DeviceNumber
= max(DeviceNumber
, 1);
8741 regs
->bDriveHeadReg
&= 0x0f;
8742 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8745 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8747 KdPrint2((PRINT_PREFIX
8748 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8749 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8751 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8752 to_lim
= Srb
->TimeOutValue
;
8754 if(Srb
->TimeOutValue
<= 2) {
8755 to_lim
= Srb
->TimeOutValue
*900;
8757 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8761 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8763 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8765 statusByte
= UniataAhciSendPIOCommandDirect(
8774 if(statusByte
== IDE_STATUS_WRONG
) {
8775 goto passthrough_err
;
8777 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8778 UniataAhciAbortOperation(chan
);
8779 goto passthrough_err
;
8781 goto passthrough_done
;
8785 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8786 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8788 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8789 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8790 (PUCHAR
)(Srb
->DataBuffer
),
8791 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8797 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8798 AtapiStallExecution(10);
8800 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
8803 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8804 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8805 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8806 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8807 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8808 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8810 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8811 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8812 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8813 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8814 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8815 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8816 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8817 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8818 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8819 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8821 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8824 GetBaseStatus(chan
, statusByte
);
8825 if(statusByte
& IDE_STATUS_ERROR
) {
8826 goto passthrough_err
;
8828 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8831 ScsiPortStallExecution(1); // wait for busy to be set
8833 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8834 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8835 GetBaseStatus(chan
, statusByte
);
8836 if(statusByte
& IDE_STATUS_ERROR
) {
8839 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8844 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8846 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8847 goto passthrough_err
;
8851 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8853 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8854 GetBaseStatus(chan
, statusByte
);
8856 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8857 AtapiSuckPort2(chan
);
8859 if (Srb
->SenseInfoBuffer
) {
8861 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8863 senseBuffer
->ErrorCode
= 0x70;
8864 senseBuffer
->Valid
= 1;
8865 senseBuffer
->AdditionalSenseLength
= 0xb;
8866 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8867 senseBuffer
->AdditionalSenseCode
= 0;
8868 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8870 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8871 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8873 status
= SRB_STATUS_ERROR
;
8877 if (statusByte
& IDE_STATUS_DRQ
) {
8878 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8880 (PUSHORT
) Srb
->DataBuffer
,
8881 Srb
->DataTransferLength
/ 2,
8883 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8885 (PUSHORT
) Srb
->DataBuffer
,
8886 Srb
->DataTransferLength
/ 2,
8891 status
= SRB_STATUS_SUCCESS
;
8894 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8896 } else { // read task register
8899 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8901 KdPrint2((PRINT_PREFIX
8902 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8903 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8905 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8906 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8909 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8912 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8913 status
= SRB_STATUS_DATA_OVERRUN
;
8916 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8917 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8918 UniataSnapAtaRegs(chan
, 0, regs
);
8920 status
= SRB_STATUS_SUCCESS
;
8927 KdPrint2((PRINT_PREFIX
8928 "IdeSendCommand: Unsupported command %#x\n",
8931 status
= SRB_STATUS_INVALID_REQUEST
;
8935 if(status
== SRB_STATUS_PENDING
) {
8936 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8937 if(CmdAction
& CMD_ACTION_EXEC
) {
8938 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8939 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8942 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8943 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8948 } // end IdeSendCommand()
8953 Routine Description:
8954 Enables disables media status notification
8957 HwDeviceExtension - ATAPI driver storage.
8964 IN PVOID HwDeviceExtension
,
8966 IN ULONG DeviceNumber
8969 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8971 UCHAR statusByte
,errorByte
;
8973 chan
= &(deviceExtension
->chan
[lChannel
]);
8974 SelectDrive(chan
, DeviceNumber
);
8976 if (EnableMSN
== TRUE
){
8978 // If supported enable Media Status Notification support
8979 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8982 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8983 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8984 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8986 if (statusByte
& IDE_STATUS_ERROR
) {
8987 // Read the error register.
8988 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8990 KdPrint2((PRINT_PREFIX
8991 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8995 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8996 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8997 chan
->ReturningMediaStatus
= 0;
9002 } else { // end if EnableMSN == TRUE
9004 // disable if previously enabled
9005 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
9007 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9008 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9009 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
9010 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
9017 } // end IdeMediaStatus()
9022 Routine Description:
9024 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
9025 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
9028 HwDeviceExtension - ATAPI driver storage.
9029 Srb - System request block.
9033 SRB status (ALWAYS SUCCESS).
9038 IdeBuildSenseBuffer(
9039 IN PVOID HwDeviceExtension
,
9040 IN PSCSI_REQUEST_BLOCK Srb
9043 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9045 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
9046 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
9050 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
9052 senseBuffer
->ErrorCode
= 0x70;
9053 senseBuffer
->Valid
= 1;
9054 senseBuffer
->AdditionalSenseLength
= 0xb;
9055 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
9056 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
9057 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9058 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
9060 senseBuffer
->ErrorCode
= 0x70;
9061 senseBuffer
->Valid
= 1;
9062 senseBuffer
->AdditionalSenseLength
= 0xb;
9063 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
9064 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
9065 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9066 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
9068 senseBuffer
->ErrorCode
= 0x70;
9069 senseBuffer
->Valid
= 1;
9070 senseBuffer
->AdditionalSenseLength
= 0xb;
9071 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
9072 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
9073 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9074 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
9076 senseBuffer
->ErrorCode
= 0x70;
9077 senseBuffer
->Valid
= 1;
9078 senseBuffer
->AdditionalSenseLength
= 0xb;
9079 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
9080 senseBuffer
->AdditionalSenseCode
= 0;
9081 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9083 return SRB_STATUS_SUCCESS
;
9085 return SRB_STATUS_ERROR
;
9087 }// End of IdeBuildSenseBuffer
9091 UniataUserDeviceReset(
9092 PHW_DEVICE_EXTENSION deviceExtension
,
9093 PHW_LU_EXTENSION LunExt
,
9098 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9099 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
9100 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
9101 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
9102 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
9104 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
9105 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
9106 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
9107 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
9110 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9111 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9113 } // end UniataUserDeviceReset()
9118 PHW_DEVICE_EXTENSION deviceExtension
,
9123 BOOLEAN PostReq
= FALSE
;
9125 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
9126 if(chan
->queue_depth
> 0) {
9129 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
9130 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
9131 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
9133 status
= SRB_STATUS_BUSY
;
9142 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
9146 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
9149 } // end UniataNeedQueueing()
9153 Routine Description:
9155 This routine is called from the SCSI port driver synchronized
9156 with the kernel to start an IO request.
9161 HwDeviceExtension - HBA miniport driver's adapter data storage
9162 Srb - IO request packet
9172 IN PVOID HwDeviceExtension
,
9173 IN PSCSI_REQUEST_BLOCK Srb
9176 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
9177 } // end AtapiStartIo()
9182 IN PVOID HwDeviceExtension
,
9183 IN PSCSI_REQUEST_BLOCK Srb
,
9187 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9190 PHW_LU_EXTENSION LunExt
;
9198 PSCSI_REQUEST_BLOCK tmpSrb
;
9199 BOOLEAN PostReq
= FALSE
;
9201 BOOLEAN commPort
= FALSE
;
9203 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
9204 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
9205 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
9206 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9208 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
9210 /* KeBugCheckEx(0xc000000e,
9211 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9213 TopLevel, 0x80000001);
9215 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
9216 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
9217 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
9218 UniAtaClearAtaReq(Srb
->SrbExtension
);
9221 do { // fetch all queued commands for the channel (if valid)
9223 lChannel
= GET_CHANNEL(Srb
);
9224 //ldev = GET_LDEV(Srb);
9227 DeviceNumber
= GET_CDEV(Srb
);
9230 //ASSERT(deviceExtension);
9233 KdPrint2((PRINT_PREFIX
9234 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9235 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
9236 KdPrint2((PRINT_PREFIX
" DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
9238 if(lChannel
== deviceExtension
->NumberChannels
&&
9239 !Srb
->Lun
&& !Srb
->TargetId
&&
9240 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
9241 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
9243 // This is our virtual device
9244 KdPrint2((PRINT_PREFIX
9245 "AtapiStartIo: Communication port\n"));
9246 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
9248 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
9249 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
9250 sizeof(PINQUIRYDATA
) ));
9252 status
= SRB_STATUS_DATA_OVERRUN
;
9256 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
9258 KdPrint2((PRINT_PREFIX
9260 // Zero INQUIRY data structure.
9261 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
9263 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
9265 // Fill in vendor identification fields.
9266 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
9268 status
= SRB_STATUS_SUCCESS
;
9272 /* Pass IOCTL request down */
9274 if(lChannel
>= deviceExtension
->NumberChannels
||
9275 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
9278 if(lChannel
>= deviceExtension
->NumberChannels
) {
9283 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9284 KdPrint3((PRINT_PREFIX
9285 "AtapiStartIo: SRB rejected\n"));
9286 // Indicate no device found at this address.
9287 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9288 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9292 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
9293 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
9298 chan
= &(deviceExtension
->chan
[lChannel
]);
9299 LunExt
= chan
->lun
[DeviceNumber
];
9303 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9309 if(!commPort
&& !LunExt
) {
9311 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
9314 deviceExtension
->NumberChannels
);
9315 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
9316 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
9317 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9318 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
9322 for(i=0; i<1000; i++) {
9323 AtapiStallExecution(3*1000);
9330 // Determine which function.
9331 switch (Srb
->Function
) {
9333 case SRB_FUNCTION_EXECUTE_SCSI
:
9335 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9336 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9337 // let passthrough go
9339 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9343 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9344 KdPrint2((PRINT_PREFIX
9345 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
9346 // Indicate no device found at this address.
9347 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9348 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9353 KdPrint2((PRINT_PREFIX
9354 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
9358 if(Srb->DataTransferLength) {
9360 a = ((PUCHAR)(Srb->DataBuffer))[0];
9363 } __except(EXCEPTION_EXECUTE_HANDLER) {
9364 KdPrint3((PRINT_PREFIX
9365 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
9366 // Indicate no device found at this address.
9367 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
9368 status = SRB_STATUS_ERROR;
9369 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
9374 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9378 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
9380 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
9381 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
9383 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9385 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
9386 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9388 /*KeBugCheckEx(0xc000000e,
9389 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9391 status, 0x80000001);*/
9392 if(status
== SRB_STATUS_BUSY
)
9393 status
= SRB_STATUS_PENDING
;
9394 // Insert requests AFTER they have been initialized on
9395 // CMD_ACTION_PREPARE stage
9396 // we should not check TopLevel here (it is always TRUE)
9397 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9398 UniataQueueRequest(chan
, Srb
);
9400 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9404 // Send command to device.
9405 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
9407 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
9408 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9409 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
9410 //ASSERT(!AtaReq->Flags);
9411 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9412 UniataQueueRequest(chan
, Srb
);
9413 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
9414 //ASSERT(!AtaReq->Flags);
9415 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9416 //ASSERT(!AtaReq->Flags);
9420 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9424 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9425 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
9426 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
9430 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9434 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9443 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
9444 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
9445 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
9446 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9448 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
9453 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
9460 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
9462 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9464 /* KeBugCheckEx(0xc000000e,
9465 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9467 status, 0x80000002);*/
9475 case SRB_FUNCTION_ABORT_COMMAND
:
9477 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
9479 // Verify that SRB to abort is still outstanding.
9480 if((tmpSrb
!= Srb
->NextSrb
) ||
9481 !chan
->queue_depth
) {
9483 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
9485 // Complete abort SRB.
9486 status
= SRB_STATUS_ABORT_FAILED
;
9490 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
9491 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
9492 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
9493 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
9494 // Log reset failure.
9495 KdPrint3((PRINT_PREFIX
9496 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
9497 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9499 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9500 status
= SRB_STATUS_ERROR
;
9503 status
= SRB_STATUS_SUCCESS
;
9506 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
9507 if (tmpSrb
->SenseInfoBuffer
&&
9508 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
9510 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
9512 senseBuffer
->ErrorCode
= 0;
9513 senseBuffer
->Valid
= 1;
9514 senseBuffer
->AdditionalSenseLength
= 0xb;
9515 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
9516 senseBuffer
->AdditionalSenseCode
= 0;
9517 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9519 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
9521 AtapiDmaDBSync(chan
, tmpSrb
);
9522 UniataRemoveRequest(chan
, tmpSrb
);
9523 // Indicate command complete.
9524 ScsiPortNotification(RequestComplete
,
9527 status
= SRB_STATUS_SUCCESS
;
9531 // Abort function indicates that a request timed out.
9532 // Call reset routine. Card will only be reset if
9533 // status indicates something is wrong.
9534 // Fall through to reset code.
9536 case SRB_FUNCTION_RESET_DEVICE
:
9537 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
9539 // Reset single device.
9540 // For now we support only Lun=0
9542 // Note: reset is immediate command, it cannot be queued since it is usually used to
9543 // revert not-responding device to operational state
9544 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
9545 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
9546 status
= SRB_STATUS_SUCCESS
;
9549 case SRB_FUNCTION_RESET_BUS
:
9551 // Reset Atapi and SCSI bus.
9553 // Note: reset is immediate command, it cannot be queued since it is usually used to
9554 // revert not- responding device to operational state
9555 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
9556 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
9557 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
9558 // Log reset failure.
9559 KdPrint3((PRINT_PREFIX
9560 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9561 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9563 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9564 status
= SRB_STATUS_ERROR
;
9567 status
= SRB_STATUS_SUCCESS
;
9572 case SRB_FUNCTION_SHUTDOWN
:
9574 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
9575 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9576 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
9579 // FLUSH ATAPI device - do nothing
9580 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
9582 // FLUSH IDE/ATA device
9583 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9584 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9585 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9586 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9587 // If supported & allowed, reset write cacheing
9588 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9590 // Disable write cache
9591 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9592 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9593 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9594 // Check for errors.
9595 if (status
& IDE_STATUS_ERROR
) {
9596 KdPrint2((PRINT_PREFIX
9597 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9600 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9602 // Re-enable write cache
9603 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9604 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9605 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9606 // Check for errors.
9607 if (status
& IDE_STATUS_ERROR
) {
9608 KdPrint2((PRINT_PREFIX
9609 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9611 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9613 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9617 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9619 status
= SRB_STATUS_SUCCESS
;
9623 case SRB_FUNCTION_FLUSH
:
9625 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9626 status
= SRB_STATUS_SUCCESS
;
9629 case SRB_FUNCTION_IO_CONTROL
: {
9633 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9635 len
= Srb
->DataTransferLength
;
9637 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9639 ULONG targetId
= (ULONG
)(-1);
9641 if(len
< sizeof(SRB_IO_CONTROL
)) {
9642 goto wrong_buffer_size
;
9645 // extract bogus bus address
9646 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9647 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9648 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9650 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9651 goto wrong_buffer_size
;
9654 targetId
= versionParameters
->bIDEDeviceMap
;
9655 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9657 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9658 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9659 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9660 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9661 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9662 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9663 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9664 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9665 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9666 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9667 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9668 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9670 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9672 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9673 goto wrong_buffer_size
;
9676 targetId
= cmdInParameters
->bDriveNumber
;
9677 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9681 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9682 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9683 status
= SRB_STATUS_INVALID_REQUEST
;
9687 // adjust (if necessary) bus address
9688 if(targetId
!= (ULONG
)(-1)) {
9690 // This is done because of how the IOCTL_SCSI_MINIPORT
9691 // determines 'targetid's'. Disk.sys places the real target id value
9692 // in the DeviceMap field. Once we do some parameter checking, the value passed
9693 // back to the application will be determined.
9695 if (deviceExtension
->NumberChannels
== 1) {
9696 // do this for legacy controllers and legacy callers
9697 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9698 DeviceNumber
= (targetId
& 0x01);
9702 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9703 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9704 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9705 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9706 lChannel
= (UCHAR
)targetId
/ 2;
9709 lChannel
= (UCHAR
)(targetId
/ 2);
9710 DeviceNumber
= targetId
& 0x01;
9713 // otherwise assume lChannel and DeviceNumber from Srb are ok
9715 if(lChannel
>= deviceExtension
->NumberChannels
||
9716 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9717 KdPrint2((PRINT_PREFIX
9718 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9720 // Indicate no device found at this address.
9723 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9724 chan
= &(deviceExtension
->chan
[lChannel
]);
9725 LunExt
= chan
->lun
[DeviceNumber
];
9729 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9731 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9736 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9737 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9739 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9740 UCHAR deviceNumberMap
;
9742 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9744 // Version and revision per SMART 1.03
9746 versionParameters
->bVersion
= 1;
9747 versionParameters
->bRevision
= 1;
9748 versionParameters
->bReserved
= 0;
9750 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9751 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9754 goto invalid_request
;
9757 // NOTE: This will only set the bit
9758 // corresponding to this drive's target id.
9759 // The bit mask is as follows:
9765 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9766 deviceNumberMap
= 1 << lChannel
;
9769 if (deviceExtension
->NumberChannels
== 1) {
9770 if (chan
->PrimaryAddress
) {
9771 deviceNumberMap
= 1 << DeviceNumber
;
9773 deviceNumberMap
= 4 << DeviceNumber
;
9776 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9779 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9781 status
= SRB_STATUS_SUCCESS
;
9785 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9787 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9788 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9790 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9791 // Extract the target.
9792 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9794 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9797 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9798 goto invalid_request
;
9804 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9805 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9806 goto invalid_request
;
9809 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9810 // Zero the output buffer
9811 RtlZeroMemory(cmdOutParameters
, len
);
9812 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9813 ((PUCHAR)cmdOutParameters)[i] = 0;
9816 // Build status block.
9817 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9818 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9819 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9821 // Extract the identify data from the device extension.
9822 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9823 cmdOutParameters
->cBufferSize
);
9825 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9826 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9827 // adjust checksum if it is possible
9831 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9832 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9834 cmdOutParameters
->bBuffer
[i
] = -csum
;
9835 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9837 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9839 status
= SRB_STATUS_SUCCESS
;
9843 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9844 cmdInParameters
.irDriveRegs
.bCommandReg
));
9845 status
= SRB_STATUS_INVALID_REQUEST
;
9851 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9852 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9853 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9854 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9855 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9856 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9857 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9858 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9861 // *all* IOCTLs here are SMART
9863 KdPrint2((PRINT_PREFIX
9864 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9867 goto invalid_request
;
9870 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9872 if(PostReq
|| TopLevel
) {
9873 UniataQueueRequest(chan
, Srb
);
9874 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9875 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9880 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9881 status
= SRB_STATUS_PENDING
;
9883 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9886 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9890 // we should not get here, checked above
9892 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9893 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9894 status = SRB_STATUS_INVALID_REQUEST;
9899 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9901 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9902 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9903 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9907 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9908 //chan = &(deviceExtension->chan[lChannel]);
9910 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9911 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9912 goto wrong_buffer_size
;
9915 if(AtaCtl
->addr
.Lun
||
9916 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9917 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9925 lChannel
= AtaCtl
->addr
.PathId
;
9926 chan
= &(deviceExtension
->chan
[lChannel
]);
9927 LunExt
= chan
->lun
[DeviceNumber
];
9930 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9932 /* check for valid LUN */
9933 switch (AtaCtl
->hdr
.ControlCode
) {
9934 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9935 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9936 // this would be BUS reset
9938 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9939 AtaCtl
->addr
.TargetId
!= 0xff ||
9940 AtaCtl
->addr
.Lun
!= 0
9942 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9943 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9944 lChannel
= AtaCtl
->addr
.PathId
;
9945 chan
= &(deviceExtension
->chan
[lChannel
]);
9946 LunExt
= chan
->lun
[DeviceNumber
];
9949 goto handle_bad_ldev
;
9952 lChannel
= AtaCtl
->addr
.PathId
;
9953 chan
= &(deviceExtension
->chan
[lChannel
]);
9956 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9957 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9958 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9959 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9960 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9963 KdPrint2((PRINT_PREFIX
9964 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9965 // Indicate no device found at this address.
9970 /* check if queueing is necessary */
9971 switch (AtaCtl
->hdr
.ControlCode
) {
9972 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9973 if(!LunExt
->nBadBlocks
) {
9976 goto uata_ctl_queue
;
9977 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9978 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9979 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9980 pos
+sizeof(AtaCtl
->SetMode
) ));
9981 goto wrong_buffer_size
;
9983 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9986 goto uata_ctl_queue
;
9987 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9988 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9990 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9991 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9993 if(PostReq
|| TopLevel
) {
9994 UniataQueueRequest(chan
, Srb
);
9995 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9996 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9999 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
10000 status
= SRB_STATUS_PENDING
;
10002 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
10005 } // end switch (AtaCtl->hdr.ControlCode)
10007 /* process request */
10008 switch (AtaCtl
->hdr
.ControlCode
) {
10009 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
10011 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
10013 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
10014 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10015 pos
+sizeof(AtaCtl
->FindDelDev
) ));
10016 goto wrong_buffer_size
;
10018 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
10019 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
10020 if(AtaCtl
->addr
.TargetId
!= 0xff) {
10021 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
10026 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
10027 AtapiStallExecution(1000 * 1000);
10030 FindDevices(HwDeviceExtension
,
10031 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
10032 ? UNIATA_FIND_DEV_UNHIDE
: 0,
10033 AtaCtl
->addr
.PathId
);
10034 status
= SRB_STATUS_SUCCESS
;
10038 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
10040 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
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 LunExt
->DeviceFlags
= 0;
10048 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
10049 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
10050 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
10051 UniataForgetDevice(LunExt
);
10054 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
10055 AtapiStallExecution(1000 * 1000);
10058 status
= SRB_STATUS_SUCCESS
;
10061 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
10063 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
10065 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
10066 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10067 pos
+sizeof(AtaCtl
->SetMode
) ));
10068 goto wrong_buffer_size
;
10070 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
10071 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
10073 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
10074 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
10075 if(LunExt
->LimitedTransferMode
>
10076 LunExt
->OrigTransferMode
) {
10077 // check for incorrect value
10078 LunExt
->LimitedTransferMode
=
10079 LunExt
->OrigTransferMode
;
10082 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
10084 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
10085 if(AtaCtl
->SetMode
.ApplyImmediately
) {
10086 AtapiDmaInit__(deviceExtension
, LunExt
);
10088 /* LunExt->TransferMode =
10089 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
10090 status
= SRB_STATUS_SUCCESS
;
10093 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
10095 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
10097 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
10098 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10099 pos
+sizeof(AtaCtl
->GetMode
) ));
10100 goto wrong_buffer_size
;
10102 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
10103 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
10104 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
10105 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
10107 status
= SRB_STATUS_SUCCESS
;
10110 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
10112 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
10114 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
10115 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10116 pos
+sizeof(AtaCtl
->Version
) ));
10117 goto wrong_buffer_size
;
10119 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
10120 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
10121 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
10122 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
10123 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
10125 status
= SRB_STATUS_SUCCESS
;
10128 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
10130 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
10132 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
10133 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
10134 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
10135 goto wrong_buffer_size
;
10137 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
10139 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
10140 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
10141 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
10142 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
10143 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
10144 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
10145 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
10146 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
10147 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
10148 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
10149 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
10150 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
10151 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
10152 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
10153 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
10154 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
10155 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
10156 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
10157 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
10158 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
10159 if(deviceExtension
->FullDevName
) {
10160 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
10162 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
10163 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
10164 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
10166 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
10169 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
10172 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
10173 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
10174 PHW_CHANNEL cur_chan
;
10175 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
10176 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
10177 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
10178 cur_chan
= &(deviceExtension
->chan
[i
]);
10179 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
10180 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
10181 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
10182 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
10183 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
10184 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
10185 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
10186 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
10187 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
10190 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
10191 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
10194 status
= SRB_STATUS_SUCCESS
;
10197 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
10199 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
10201 ForgetBadBlocks(LunExt
);
10203 status
= SRB_STATUS_SUCCESS
;
10206 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
10208 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
10213 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
10216 status
= SRB_STATUS_SUCCESS
;
10220 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
10221 AtaCtl
->hdr
.ControlCode
));
10222 status
= SRB_STATUS_INVALID_REQUEST
;
10227 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
10228 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
10229 "SCSIDISK", "-UNIATA-"));
10231 status
= SRB_STATUS_INVALID_REQUEST
;
10236 } // end SRB_FUNCTION_IO_CONTROL
10239 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
10240 // Indicate unsupported command.
10241 status
= SRB_STATUS_INVALID_REQUEST
;
10249 PathId
= Srb
->PathId
;
10250 TargetId
= Srb
->TargetId
;
10253 if (status
!= SRB_STATUS_PENDING
) {
10255 KdPrint2((PRINT_PREFIX
10256 "AtapiStartIo: Srb %#x complete with status %#x\n",
10260 // Set status in SRB.
10261 Srb
->SrbStatus
= (UCHAR
)status
;
10264 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
10265 AtapiDmaDBSync(chan
, Srb
);
10267 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
10268 UniataRemoveRequest(chan
, Srb
);
10269 // Indicate command complete.
10270 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
10271 ScsiPortNotification(RequestComplete
,
10275 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
10276 // Remove current Srb & get next one
10277 if((Srb
= UniataGetCurRequest(chan
))) {
10278 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10279 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
10280 // current request is under precessing, thus
10281 // we should do nothing here
10285 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
10287 //ASSERT(TopLevel);
10290 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
10292 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
10294 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
10295 // Indicate ready for next request.
10296 ScsiPortNotification(NextRequest
,
10300 ScsiPortNotification(NextLuRequest
,
10308 } // end AtapiStartIo__()
10313 UniataInitAtaCommands()
10319 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
10321 for(i
=0; i
<256; i
++) {
10326 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
10329 case IDE_COMMAND_READ_DMA48
:
10330 case IDE_COMMAND_READ_DMA_Q48
:
10331 case IDE_COMMAND_READ_STREAM_DMA48
:
10332 case IDE_COMMAND_READ_STREAM48
:
10333 case IDE_COMMAND_WRITE_DMA48
:
10334 case IDE_COMMAND_WRITE_DMA_Q48
:
10335 case IDE_COMMAND_READ_DMA_Q
:
10336 case IDE_COMMAND_READ_DMA
:
10337 case IDE_COMMAND_WRITE_DMA
:
10338 case IDE_COMMAND_WRITE_DMA_Q
:
10339 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10340 case IDE_COMMAND_WRITE_STREAM48
:
10341 case IDE_COMMAND_WRITE_FUA_DMA48
:
10342 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10343 case IDE_COMMAND_READ_LOG_DMA48
:
10344 case IDE_COMMAND_WRITE_LOG_DMA48
:
10345 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10346 case IDE_COMMAND_TRUSTED_SEND_DMA
:
10347 case IDE_COMMAND_DATA_SET_MGMT
:
10348 //KdPrint2((PRINT_PREFIX "DMA "));
10349 flags
|= ATA_CMD_FLAG_DMA
;
10353 case IDE_COMMAND_WRITE_FUA_DMA48
:
10354 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10355 case IDE_COMMAND_WRITE_MUL_FUA48
:
10357 flags
|= ATA_CMD_FLAG_FUA
;
10360 case IDE_COMMAND_READ48
:
10361 case IDE_COMMAND_READ_DMA48
:
10362 case IDE_COMMAND_READ_DMA_Q48
:
10363 case IDE_COMMAND_READ_MUL48
:
10364 case IDE_COMMAND_READ_STREAM_DMA48
:
10365 case IDE_COMMAND_READ_STREAM48
:
10366 case IDE_COMMAND_WRITE48
:
10367 case IDE_COMMAND_WRITE_DMA48
:
10368 case IDE_COMMAND_WRITE_DMA_Q48
:
10369 case IDE_COMMAND_WRITE_MUL48
:
10370 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10371 case IDE_COMMAND_WRITE_STREAM48
:
10372 case IDE_COMMAND_FLUSH_CACHE48
:
10373 case IDE_COMMAND_VERIFY48
:
10375 //KdPrint2((PRINT_PREFIX "48 "));
10376 flags
|= ATA_CMD_FLAG_48
;
10379 case IDE_COMMAND_READ
:
10380 case IDE_COMMAND_READ_MULTIPLE
:
10381 case IDE_COMMAND_READ_DMA
:
10382 case IDE_COMMAND_READ_DMA_Q
:
10383 case IDE_COMMAND_WRITE
:
10384 case IDE_COMMAND_WRITE_MULTIPLE
:
10385 case IDE_COMMAND_WRITE_DMA
:
10386 case IDE_COMMAND_WRITE_DMA_Q
:
10387 case IDE_COMMAND_FLUSH_CACHE
:
10388 case IDE_COMMAND_VERIFY
:
10390 //KdPrint2((PRINT_PREFIX "LBA "));
10391 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
10395 case IDE_COMMAND_READ_NATIVE_SIZE48
:
10396 case IDE_COMMAND_SET_NATIVE_SIZE48
:
10397 // we cannot set LBA flag for these commands to avoid BadBlock handling
10398 //flags |= ATA_CMD_FLAG_LBAIOsupp;
10399 flags
|= ATA_CMD_FLAG_48
;
10401 case IDE_COMMAND_READ_NATIVE_SIZE
:
10402 case IDE_COMMAND_SET_NATIVE_SIZE
:
10404 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
10407 flags
|= ATA_CMD_FLAG_48supp
;
10410 case IDE_COMMAND_READ
:
10411 command
= IDE_COMMAND_READ48
; break;
10412 case IDE_COMMAND_READ_MULTIPLE
:
10413 command
= IDE_COMMAND_READ_MUL48
; break;
10414 case IDE_COMMAND_READ_DMA
:
10415 command
= IDE_COMMAND_READ_DMA48
; break;
10416 case IDE_COMMAND_READ_DMA_Q
:
10417 command
= IDE_COMMAND_READ_DMA_Q48
; break;
10418 case IDE_COMMAND_WRITE
:
10419 command
= IDE_COMMAND_WRITE48
; break;
10420 case IDE_COMMAND_WRITE_MULTIPLE
:
10421 command
= IDE_COMMAND_WRITE_MUL48
; break;
10422 case IDE_COMMAND_WRITE_DMA
:
10423 command
= IDE_COMMAND_WRITE_DMA48
; break;
10424 case IDE_COMMAND_WRITE_DMA_Q
:
10425 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
10426 case IDE_COMMAND_FLUSH_CACHE
:
10427 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
10428 // case IDE_COMMAND_READ_NATIVE_SIZE:
10429 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
10430 case IDE_COMMAND_SET_NATIVE_SIZE
:
10431 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
10432 case IDE_COMMAND_VERIFY
:
10433 command
= IDE_COMMAND_VERIFY48
; break;
10435 //KdPrint2((PRINT_PREFIX "!28->48 "));
10436 flags
&= ~ATA_CMD_FLAG_48supp
;
10440 case IDE_COMMAND_READ
:
10441 case IDE_COMMAND_READ_MULTIPLE
:
10442 case IDE_COMMAND_READ_DMA48
:
10443 case IDE_COMMAND_READ_DMA_Q48
:
10444 case IDE_COMMAND_READ_STREAM_DMA48
:
10445 case IDE_COMMAND_READ_STREAM48
:
10446 case IDE_COMMAND_READ_DMA_Q
:
10447 case IDE_COMMAND_READ_DMA
:
10448 case IDE_COMMAND_READ_LOG_DMA48
:
10449 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10450 case IDE_COMMAND_IDENTIFY
:
10451 case IDE_COMMAND_ATAPI_IDENTIFY
:
10452 //KdPrint2((PRINT_PREFIX "RD "));
10453 flags
|= ATA_CMD_FLAG_In
;
10455 case IDE_COMMAND_WRITE
:
10456 case IDE_COMMAND_WRITE_MULTIPLE
:
10457 case IDE_COMMAND_WRITE_DMA48
:
10458 case IDE_COMMAND_WRITE_DMA_Q48
:
10459 case IDE_COMMAND_WRITE_DMA
:
10460 case IDE_COMMAND_WRITE_DMA_Q
:
10461 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10462 case IDE_COMMAND_WRITE_STREAM48
:
10463 case IDE_COMMAND_WRITE_FUA_DMA48
:
10464 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10465 //KdPrint2((PRINT_PREFIX "WR "));
10466 flags
|= ATA_CMD_FLAG_Out
;
10470 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
10471 AtaCommands48
[i
] = command
;
10472 AtaCommandFlags
[i
] = flags
;
10474 } // end UniataInitAtaCommands()
10479 Routine Description:
10481 Installable driver initialization entry point for system.
10489 Status from ScsiPortInitialize()
10496 IN PVOID DriverObject
,
10500 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
10501 ULONG adapterCount
;
10502 ULONG i
, c
, alt
, pref_alt
;
10503 ULONG statusToReturn
, newStatus
;
10504 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
10505 BOOLEAN ReEnter
= FALSE
;
10507 #ifndef USE_REACTOS_DDK
10511 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
10512 BOOLEAN PrimaryClaimed
= FALSE
;
10513 BOOLEAN SecondaryClaimed
= FALSE
;
10514 BOOLEAN IgnoreIsaCompatiblePci
= FALSE
;
10515 BOOLEAN IgnoreNativePci
= FALSE
;
10517 LARGE_INTEGER t0
, t1
;
10519 Connect_DbgPrint();
10520 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
10521 //a = (WCHAR)strlen(ver_string);
10523 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
10524 if(g_opt_Verbose
) {
10525 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
10527 IgnoreIsaCompatiblePci
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci
) ? TRUE
: FALSE
;
10528 IgnoreNativePci
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", IgnoreNativePci
) ? TRUE
: FALSE
;
10530 if(!SavedDriverObject
) {
10531 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
10532 #ifdef USE_REACTOS_DDK
10533 KdPrint(("UniATA Init: OS should be ReactOS\n"));
10537 CPU_num
= KeNumberProcessors
;
10539 // we are here for the 1st time
10540 // init CrossNT and get OS version
10541 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
10542 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
10543 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10546 CPU_num
= *KeNumberProcessors
;
10547 #endif // USE_REACTOS_DDK
10548 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, CPU_num
));
10550 KeQuerySystemTime(&t0
);
10552 KeQuerySystemTime(&t1
);
10553 } while(t0
.QuadPart
== t1
.QuadPart
);
10557 KeQuerySystemTime(&t1
);
10559 } while(t0
.QuadPart
== t1
.QuadPart
);
10560 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
10561 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
10563 KdPrint(("UniATA Init: ReEnter\n"));
10567 // (re)read bad block list
10568 InitBadBlocks(NULL
);
10571 // init ATA command translation table
10572 //UniataInitAtaCommands();
10574 // get registry path to settings
10575 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
10576 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
10577 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
10578 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
10579 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
10580 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
10583 if(WinVer_Id() >= WinVer_2k
) {
10584 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
10585 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10586 WinVer_WDM_Model
= TRUE
;
10588 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
10589 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10590 WinVer_WDM_Model
= TRUE
;
10594 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10595 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10597 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10600 statusToReturn
= 0xffffffff;
10602 // Zero out structure.
10603 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10605 // Set size of hwInitializationData.
10606 hwInitializationData
.comm
.HwInitializationDataSize
=
10607 sizeof(hwInitializationData
.comm
) +
10608 // sizeof(hwInitializationData.nt4) +
10609 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10610 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10612 // Set entry points.
10613 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10614 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10615 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10616 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10618 // Specify size of extensions.
10619 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10620 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10621 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10623 // Indicate PIO device.
10624 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10625 // Set PnP-specific API
10626 if(WinVer_Id() > WinVer_NT
) {
10627 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10628 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10629 KdPrint(("set AtapiAdapterControl() ptr\n"));
10630 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10633 KdPrint2((PRINT_PREFIX
"\n\nUniATA init... (%d)\n", ReEnter
));
10636 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10637 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10638 g_opt_VirtualMachine
= 0;
10640 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10641 g_opt_VirtualMachine
= VM_VBOX
;
10643 // Pre-scan PCI bus, also check if we are under VM
10644 // But do not perform scan if PCI bus is claimed as unused
10645 if(!IgnoreIsaCompatiblePci
|| !IgnoreNativePci
) {
10646 KdPrint2((PRINT_PREFIX
"\nATAPI IDE enum supported PCI BusMaster Devices\n"));
10647 UniataEnumBusMasterController(DriverObject
, Argument2
);
10650 switch(g_opt_VirtualMachine
) {
10652 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10653 // adjust options for VirtualBox
10654 g_opt_WaitBusyCount
= 20000;
10655 g_opt_WaitBusyDelay
= 150;
10656 g_opt_WaitDrqDelay
= 100;
10657 g_opt_WaitBusyLongCount
= 20000;
10658 g_opt_MaxIsrWait
= 200;
10659 g_opt_AtapiSendDisableIntr
= FALSE
;
10660 g_opt_AtapiDmaRawRead
= FALSE
;
10663 KdPrint2((PRINT_PREFIX
"adjust options for Bochs\n"));
10664 g_opt_AtapiNoDma
= TRUE
;
10668 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10669 // old slow machine, adjust timings (us)
10670 g_opt_WaitBusyResetCount
= 20000;
10671 g_opt_WaitBusyCount
= 20000;
10672 g_opt_WaitBusyDelay
= 150;
10673 g_opt_WaitDrqDelay
= 100;
10674 g_opt_WaitBusyLongCount
= 20000;
10675 g_opt_MaxIsrWait
= 200;
10676 g_opt_DriveSelectNanoDelay
= 400;
10678 if(g_opt_VirtualMachine
> VM_NONE
) {
10679 g_opt_DriveSelectNanoDelay
= 0;
10682 g_opt_AtapiSendDisableIntr
= TRUE
;
10685 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10686 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10687 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10688 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10689 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10690 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
) ? TRUE
: FALSE
; // 1 vs 0
10691 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
) ? TRUE
: FALSE
; // 1 vs 0
10692 g_opt_AtapiNoDma
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiNoDma", g_opt_AtapiNoDma
) ? TRUE
: FALSE
; // 1 vs 0
10693 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10694 g_opt_DriveSelectNanoDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay
);
10697 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10698 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10699 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10700 for (i
=0; i
<BMListLen
; i
++) {
10702 if(!BMList
[i
].MasterDev
) {
10703 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10706 if(IgnoreIsaCompatiblePci
) {
10710 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10711 if(BMList
[i
].ChanInitOk
& 0x03) {
10712 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10714 newStatus
= STATUS_SUCCESS
;
10718 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10720 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10721 PrimaryClaimed
= TRUE
;
10722 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10723 SecondaryClaimed
= TRUE
;
10726 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10727 !(BMList
[i
].ChanInitOk
& 0x80)) {
10729 // We just want to claim our PCI device in compatible mode, since we shall not
10730 // tell system that we use it inside HwInitialize
10731 // Even more, we shall cheat system, that work with ISA
10732 // Note: this call may (but not 'must' or 'can') cause IO resource
10733 // reallocation and switch to native mode if HAL supports this
10734 newStatus
= (ULONG
)UniataClaimLegacyPCIIDE(i
);
10735 // Special check for NT3.51/NT4 (not ReactOS !!!)
10736 if(((NTSTATUS
)newStatus
== STATUS_CONFLICTING_ADDRESSES
) &&
10737 //(BMList[i].ChanInitOk & 0x40) &&
10739 (WinVer_Id() <= WinVer_NT
)) {
10740 // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of
10741 // BusMaster PCI controller
10742 // Since nobody claimed Primary/Secondary yet, try init and claim them
10743 // However it is not 100% safe way, especially under ReactOS, which doesn't resolve
10745 // We relay on ScsiPort internal checks
10746 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n"));
10747 newStatus
= STATUS_SUCCESS
;
10748 // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first)
10751 if(newStatus
!= STATUS_SUCCESS
) {
10752 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10757 if(g_opt_Verbose
) {
10758 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10761 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10763 for(c
=0; c
<2; c
++) {
10764 // check is channel is manually excluded
10765 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10769 if(PrimaryClaimed
) {
10770 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10775 if(SecondaryClaimed
) {
10776 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10781 if((WinVer_Id() < WinVer_2k
)) {
10782 // do not even try if already claimed
10784 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10787 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10790 if(!WinVer_WDM_Model
) {
10791 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10793 // in WDM model things are different....
10794 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10795 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10797 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10798 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10800 if(!WinVer_WDM_Model
) {
10801 BMList
[i
].channel
= (UCHAR
)c
;
10804 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10805 newStatus
= ScsiPortInitialize(DriverObject
,
10807 &hwInitializationData
.comm
,
10808 (PVOID
)(i
| ((alt
^ pref_alt
) ? 0x80000000 : 0)));
10809 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10810 if (newStatus
< statusToReturn
) {
10811 statusToReturn
= newStatus
;
10813 if (newStatus
== STATUS_SUCCESS
) {
10814 if(WinVer_Id() < WinVer_2k
) {
10815 // This should be done in HwInitialize under w2k+ to ensure that
10816 // channel is actually initialized
10817 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10819 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10820 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10824 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10825 c = 1; // this will break our for()
10826 BMList[i].ChanInitOk |= 0x01 << c;
10831 /* if(WinVer_Id() >= WinVer_2k) {
10832 // the following didn't work under higher OSes,
10833 // until we move setting of FLAGS to HwInit
10834 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10837 if(BMList
[i
].ChanInitOk
& 0x03) {
10838 // Under NT we receive status immediately, so
10839 // we can omit alternative init method if STATUS_SUCCESS returned.
10840 // Under w2k+ we relay on flags, set in HwInitialize.
10841 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10844 if(WinVer_Id() >= WinVer_2k
) {
10845 // try AltInit if HwInit was not called immediately under w2k+
10846 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10848 // if (WinVer_Id() == WinVer_NT) and some error occured
10849 // try alternative init method
10850 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10853 if(g_opt_Verbose
) {
10854 if(BMList
[i
].ChanInitOk
& 0x03) {
10855 _PrintNtConsole(" OK\n");
10857 _PrintNtConsole(" failed\n");
10863 /* KeBugCheckEx(0xc000000e,
10864 (i << 16) | BMList[0].ChanInitOk,
10866 newStatus, statusToReturn);*/
10868 // Look for PCI IDE controller
10869 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10870 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10871 for (; i
<BMListLen
; i
++) {
10873 if(IgnoreNativePci
) {
10876 /* if(BMList[i].MasterDev)
10878 if(g_opt_Verbose
) {
10879 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10880 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10881 BMList
[i
].busNumber
,
10882 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10883 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10886 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10887 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10888 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10890 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10891 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10892 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10893 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10895 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10897 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10898 hwInitializationData
.comm
.VendorId
,
10899 hwInitializationData
.comm
.DeviceId
));
10900 newStatus
= ScsiPortInitialize(DriverObject
,
10902 &hwInitializationData
.comm
,
10904 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10905 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10906 // Note: this is actually a BUG in scsiport.sys
10907 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10908 // However, this PCI Slot may have higher non-empty Functions
10909 // UniATA will perform all staff instead of ScsiPort under NT,
10910 // but for ReactOS it is better to patch ScsiPort.
10911 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10912 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10913 newStatus
= ScsiPortInitialize(DriverObject
,
10915 &hwInitializationData
.comm
,
10916 (PVOID
)(i
| 0x80000000));
10917 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10919 if (newStatus
< statusToReturn
)
10920 statusToReturn
= newStatus
;
10922 if(g_opt_Verbose
) {
10923 if(newStatus
== STATUS_SUCCESS
) {
10924 _PrintNtConsole(" OK\n");
10926 _PrintNtConsole(" failed\n");
10932 /* KeBugCheckEx(0xc000000e,
10935 newStatus, statusToReturn);*/
10939 hwInitializationData
.comm
.VendorId
= 0;
10940 hwInitializationData
.comm
.VendorIdLength
= 0;
10941 hwInitializationData
.comm
.DeviceId
= 0;
10942 hwInitializationData
.comm
.DeviceIdLength
= 0;
10945 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10947 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10950 // The adapter count is used by the find adapter routine to track how
10951 // which adapter addresses have been tested.
10953 // Indicate 2 access ranges and reset FindAdapter.
10954 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10955 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindIsaController
;
10957 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10958 // Indicate ISA bustype.
10959 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10962 // Call initialization for ISA bustype.
10963 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10964 newStatus
= ScsiPortInitialize(DriverObject
,
10966 &hwInitializationData
.comm
,
10968 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10969 if (newStatus
< statusToReturn
)
10970 statusToReturn
= newStatus
;
10972 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10974 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10975 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10978 newStatus
= ScsiPortInitialize(DriverObject
,
10980 &hwInitializationData
.comm
,
10982 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10983 if (newStatus
< statusToReturn
)
10984 statusToReturn
= newStatus
;
10986 InDriverEntry
= FALSE
;
10988 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10990 return statusToReturn
;
10992 } // end DriverEntry()
10995 PSCSI_REQUEST_BLOCK
10997 BuildMechanismStatusSrb(
10998 IN PVOID HwDeviceExtension
,
10999 IN PSCSI_REQUEST_BLOCK Srb
11002 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11003 PSCSI_REQUEST_BLOCK srb
;
11005 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
11007 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
11009 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
11011 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
11012 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
11013 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
11014 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
11016 // Set flags to disable synchronous negociation.
11017 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
11019 // Set timeout to 4 seconds.
11020 srb
->TimeOutValue
= 4;
11022 srb
->CdbLength
= 6;
11023 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
11024 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
11025 srb
->SrbExtension
= AtaReq
;
11027 // Set CDB operation code.
11028 cdb
= (PCDB
)srb
->Cdb
;
11029 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
11030 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
11032 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
11035 } // end BuildMechanismStatusSrb()
11037 #endif //UNIATA_CORE
11039 PSCSI_REQUEST_BLOCK
11041 BuildRequestSenseSrb (
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 2 seconds.
11064 srb
->TimeOutValue
= 4;
11066 srb
->CdbLength
= 6;
11067 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
11068 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
11069 srb
->SrbExtension
= AtaReq
;
11071 // Set CDB operation code.
11072 cdb
= (PCDB
)srb
->Cdb
;
11073 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
11074 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
11076 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
11079 } // end BuildRequestSenseSrb()
11081 #ifndef UNIATA_CORE
11085 AtapiRegCheckDevLunValue(
11086 IN PVOID HwDeviceExtension
,
11087 IN PCWCH NamePrefix
,
11095 ULONG val
= Default
;
11097 val
= AtapiRegCheckParameterValue(
11098 HwDeviceExtension
, NamePrefix
, Name
, val
);
11100 if(chan
!= CHAN_NOT_SPECIFIED
) {
11101 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
11102 val
= AtapiRegCheckParameterValue(
11103 HwDeviceExtension
, namex
, Name
, val
);
11104 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
11105 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
11106 val
= AtapiRegCheckParameterValue(
11107 HwDeviceExtension
, namex
, Name
, val
);
11111 } // end AtapiRegCheckDevLunValue()
11124 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
11143 swprintf(Buffer
+j
, L
"%2.2x", a
);
11151 } // end EncodeVendorStr()
11155 AtapiRegCheckDevValue(
11156 IN PVOID HwDeviceExtension
,
11163 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11164 // WCHAR name0[11];
11165 // WCHAR name1[11+4+5];
11166 // WCHAR name2[11+4+4+10];
11167 // WCHAR name3[11+4+4+5+20];
11168 // WCHAR name3[11+4+4+5+20+1];
11177 IN ULONG SlotNumber
;
11179 ULONG val
= Default
;
11181 KdPrint(( " Parameter %ws\n", Name
));
11183 if(deviceExtension
) {
11184 VendorID
= deviceExtension
->DevID
& 0xffff;
11185 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
11186 SlotNumber
= deviceExtension
->slotNumber
;
11190 SlotNumber
= 0xffffffff;
11193 val
= AtapiRegCheckDevLunValue(
11194 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
11196 if(deviceExtension
) {
11197 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
11199 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
11200 swprintf(namex
, L
"Parameters%s", namev
);
11201 val
= AtapiRegCheckDevLunValue(
11202 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11205 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
11206 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
11207 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
11209 swprintf(namex
, L
"Parameters%s", namev
);
11210 val
= AtapiRegCheckDevLunValue(
11211 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11213 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
11214 val
= AtapiRegCheckDevLunValue(
11215 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11217 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
11218 val
= AtapiRegCheckDevLunValue(
11219 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11221 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
11223 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
11224 swprintf(namex
, L
"Parameters%s", namev
);
11225 val
= AtapiRegCheckDevLunValue(
11226 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11228 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
11229 swprintf(namex
, L
"Parameters%s", namev
);
11230 val
= AtapiRegCheckDevLunValue(
11231 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11234 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
11236 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
11237 swprintf(namex
, L
"Parameters%s", namev
);
11238 val
= AtapiRegCheckDevLunValue(
11239 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11241 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
11242 swprintf(namex
, L
"Parameters%s", namev
);
11243 val
= AtapiRegCheckDevLunValue(
11244 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
11249 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
11252 } // end AtapiRegCheckDevValue()
11255 The user must specify that Xxx is to run on the platform
11256 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
11257 Services\UniATA\Xxx:REG_DWORD:Zzz.
11259 The user can override the global setting to enable or disable Xxx on a
11260 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
11261 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
11263 If this registry value does not exist or contains the value zero then
11264 the timer to check for media change does not run.
11268 RegistryPath - pointer to the unicode string inside
11269 ...\CurrentControlSet\Services\UniATA
11270 DeviceNumber - The number of the HBA device object
11272 Returns: Registry Key value
11276 AtapiRegCheckParameterValue(
11277 IN PVOID HwDeviceExtension
,
11278 IN PCWSTR PathSuffix
,
11283 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
11285 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11287 LONG zero
= Default
;
11289 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
11292 LONG doRun
= Default
;
11294 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
11296 UNICODE_STRING paramPath
;
11298 // <SavedRegPath>\<PathSuffix> -> <Name>
11299 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
11300 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
11302 paramPath
.Length
= 0;
11303 paramPath
.MaximumLength
= RegistryPath
->Length
+
11304 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
11305 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
11306 if(!paramPath
.Buffer
) {
11307 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
11311 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
11312 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
11313 RtlAppendUnicodeToString(¶mPath
, L
"\\");
11314 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
11316 // Check for the Xxx value.
11317 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
11319 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
11320 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
11321 parameters
[0].EntryContext
= &doRun
;
11322 parameters
[0].DefaultType
= REG_DWORD
;
11323 parameters
[0].DefaultData
= &zero
;
11324 parameters
[0].DefaultLength
= sizeof(ULONG
);
11326 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
11327 paramPath
.Buffer
, parameters
, NULL
, NULL
);
11328 if(NT_SUCCESS(status
)) {
11329 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
11332 ExFreePool(paramPath
.Buffer
);
11334 if(!NT_SUCCESS(status
)) {
11340 #undef ITEMS_TO_QUERY
11342 } // end AtapiRegCheckParameterValue()
11345 SCSI_ADAPTER_CONTROL_STATUS
11347 AtapiAdapterControl(
11348 IN PVOID HwDeviceExtension
,
11349 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
11350 IN PVOID Parameters
11353 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11354 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
11355 ULONG numberChannels
= deviceExtension
->NumberChannels
;
11359 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
11361 switch(ControlType
) {
11362 case ScsiQuerySupportedControlTypes
: {
11363 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
11364 TRUE
, // ScsiQuerySupportedControlTypes
11365 TRUE
, // ScsiStopAdapter
11366 TRUE
, // ScsiRestartAdapter
11367 FALSE
, // ScsiSetBootConfig
11368 FALSE
// ScsiSetRunningConfig
11371 ULONG lim
= ScsiAdapterControlMax
;
11374 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
11376 if(pControlTypeList
->MaxControlType
< lim
) {
11377 lim
= pControlTypeList
->MaxControlType
;
11380 for(i
= 0; i
< lim
; i
++) {
11381 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
11387 case ScsiStopAdapter
: {
11389 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
11390 // Shut down all interrupts on the adapter. They'll get re-enabled
11391 // by the initialization routines.
11392 for (c
= 0; c
< numberChannels
; c
++) {
11393 AtapiResetController(deviceExtension
, c
);
11394 AtapiDisableInterrupts(deviceExtension
, c
);
11396 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
11397 // we must never get here for non-PCI
11398 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
11399 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
11403 case ScsiRestartAdapter
: {
11405 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
11406 // Enable all the interrupts on the adapter while port driver call
11407 // for power up an HBA that was shut down for power management
11409 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
11410 status
= UniataConnectIntr2(HwDeviceExtension
);
11411 if(NT_SUCCESS(status
)) {
11412 for (c
= 0; c
< numberChannels
; c
++) {
11413 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
11414 FindDevices(HwDeviceExtension
, 0, c
);
11415 AtapiEnableInterrupts(deviceExtension
, c
);
11416 AtapiHwInitialize__(deviceExtension
, c
);
11418 if(deviceExtension
->Isr2DevObj
) {
11419 // we must never get here for non-PCI
11420 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
11428 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
11429 return ScsiAdapterControlUnsuccessful
;
11433 return ScsiAdapterControlSuccess
;
11434 } // end AtapiAdapterControl()
11436 #endif //UNIATA_CORE
11446 #define DEBUG_MSG_BUFFER_SIZE 512
11457 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
11458 // UNICODE_STRING msgBuff;
11460 va_start(ap
, DebugMessage
);
11462 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
11464 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
11466 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
11467 HalDisplayString(dbg_print_tmp_buff
);
11470 if(g_LogToDisplay
> 1) {
11471 AtapiStallExecution(g_LogToDisplay
*1000);
11477 } // end PrintNtConsole()