3 Copyright (c) 2002-2015 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are 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)
62 static const CHAR ver_string
[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR
"\n";
64 static const CHAR uniata_comm_name
[] = UNIATA_COMM_PORT_VENDOR_STR
" \n";
66 UNICODE_STRING SavedRegPath
;
67 WCHAR SavedRegPathBuffer
[256];
71 UCHAR AtaCommands48
[256];
72 UCHAR AtaCommandFlags
[256];
75 ULONG ForceSimplex
= 0;
81 ULONG g_LogToDisplay
= 0;
84 ULONG g_WaitBusyInISR
= 1;
86 ULONG g_opt_WaitBusyCount
= 200; // 20000
87 ULONG g_opt_WaitBusyDelay
= 10; // 150
88 ULONG g_opt_WaitDrqDelay
= 10; // 100
89 ULONG g_opt_WaitBusyLongCount
= 2000; // 2000
90 ULONG g_opt_WaitBusyLongDelay
= 250; // 250
91 ULONG g_opt_MaxIsrWait
= 40; //
92 BOOLEAN g_opt_AtapiSendDisableIntr
= 0; // 0
93 BOOLEAN g_opt_AtapiDmaRawRead
= 1; // 0
94 BOOLEAN hasPCI
= FALSE
;
96 ULONG g_opt_VirtualMachine
= 0; // Auto
98 BOOLEAN InDriverEntry
= TRUE
;
100 BOOLEAN g_opt_Verbose
= 0;
102 BOOLEAN WinVer_WDM_Model
= FALSE
;
104 //UCHAR EnableDma = FALSE;
105 //UCHAR EnableReorder = FALSE;
111 AtapiResetController__(
112 IN PVOID HwDeviceExtension
,
114 IN UCHAR CompleteType
120 IN PHW_DEVICE_EXTENSION deviceExtension
,
126 UniataUserDeviceReset(
127 PHW_DEVICE_EXTENSION deviceExtension
,
128 PHW_LU_EXTENSION LunExt
,
132 #define RESET_COMPLETE_CURRENT 0x00
133 #define RESET_COMPLETE_ALL 0x01
134 #define RESET_COMPLETE_NONE 0x02
141 IN PVOID HwDeviceExtension
144 #ifdef UNIATA_USE_XXableInterrupts
145 #define RETTYPE_XXableInterrupts BOOLEAN
146 #define RETVAL_XXableInterrupts TRUE
148 #define RETTYPE_XXableInterrupts VOID
149 #define RETVAL_XXableInterrupts
152 RETTYPE_XXableInterrupts
155 IN PVOID HwDeviceExtension
158 RETTYPE_XXableInterrupts
160 AtapiEnableInterrupts__(
161 IN PVOID HwDeviceExtension
167 IN PVOID HwDeviceExtension
,
169 IN PHW_TIMER HwScsiTimer
,
170 IN ULONG MiniportTimerValue
173 SCSI_ADAPTER_CONTROL_STATUS
176 IN PVOID HwDeviceExtension
,
177 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
187 AtapiRegGetStringParameterValue(
188 IN PWSTR RegistryPath
,
194 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
196 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
201 ustr
.MaximumLength
= (USHORT
)MaxLen
;
202 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
204 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
205 parameters
[0].Name
= Name
;
206 parameters
[0].EntryContext
= &ustr
;
207 parameters
[0].DefaultType
= REG_SZ
;
208 parameters
[0].DefaultData
= Str
;
209 parameters
[0].DefaultLength
= MaxLen
;
211 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
212 RegistryPath
, parameters
, NULL
, NULL
);
214 if(!NT_SUCCESS(status
))
219 #undef ITEMS_TO_QUERY
220 } // end AtapiRegGetStringParameterValue()
238 if(!nano
|| !g_Perf
|| !g_PerfDt
)
240 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
245 KeQuerySystemTime(&t0
);
248 } // end UniataNanoSleep()
250 #define AtapiWritePortN_template(_type, _Type, sz) \
253 AtapiWritePort##sz( \
254 IN PHW_CHANNEL chan, \
255 IN ULONGIO_PTR _port, \
260 if(_port >= IDX_MAX_REG) { \
261 res = (PIORES)(_port); \
264 res = &chan->RegTranslation[_port]; \
266 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
270 KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \
271 ASSERT(FALSE); /* We should never get here */ \
274 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
276 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
277 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
282 AtapiWritePortN_template(ULONG
, Ulong
, 4);
283 AtapiWritePortN_template(USHORT
, Ushort
, 2);
284 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
286 #define AtapiWritePortExN_template(_type, _Type, sz) \
289 AtapiWritePortEx##sz( \
290 IN PHW_CHANNEL chan, \
291 IN ULONGIO_PTR _port, \
297 if(_port >= IDX_MAX_REG) { \
298 res = (PIORES)(_port); \
301 res = &chan->RegTranslation[_port]; \
303 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
307 KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
308 ASSERT(FALSE); /* We should never get here */ \
311 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
313 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
314 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
319 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
320 //AtapiWritePortExN_template(USHORT, Ushort, 2);
321 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
323 #define AtapiReadPortN_template(_type, _Type, sz) \
327 IN PHW_CHANNEL chan, \
328 IN ULONGIO_PTR _port \
332 if(_port >= IDX_MAX_REG) { \
333 res = (PIORES)(_port); \
336 res = &chan->RegTranslation[_port]; \
338 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
339 return (_type)(-1); \
342 KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \
343 ASSERT(FALSE); /* We should never get here */ \
346 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
347 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
349 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
350 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
354 AtapiReadPortN_template(ULONG
, Ulong
, 4);
355 AtapiReadPortN_template(USHORT
, Ushort
, 2);
356 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
358 #define AtapiReadPortExN_template(_type, _Type, sz) \
361 AtapiReadPortEx##sz( \
362 IN PHW_CHANNEL chan, \
363 IN ULONGIO_PTR _port, \
368 if(_port >= IDX_MAX_REG) { \
369 res = (PIORES)(_port); \
372 res = &chan->RegTranslation[_port]; \
374 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
375 return (_type)(-1); \
378 KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
379 ASSERT(FALSE); /* We should never get here */ \
382 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
384 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
385 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
389 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
390 //AtapiReadPortExN_template(USHORT, Ushort, 2);
391 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
393 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
396 AtapiReadBuffer##sz( \
397 IN PHW_CHANNEL chan, \
398 IN ULONGIO_PTR _port, \
408 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
410 Buffer = ((_type*)Buffer)+1; \
411 UniataNanoSleep(Timing); \
416 if(_port >= IDX_MAX_REG) { \
417 res = (PIORES)(_port); \
420 res = &chan->RegTranslation[_port]; \
422 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
426 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
427 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
431 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
433 Buffer = ((_type*)Buffer)+1; \
438 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
441 AtapiWriteBuffer##sz( \
442 IN PHW_CHANNEL chan, \
443 IN ULONGIO_PTR _port, \
453 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
454 Buffer = ((_type*)Buffer)+1; \
456 UniataNanoSleep(Timing); \
461 if(_port >= IDX_MAX_REG) { \
462 res = (PIORES)(_port); \
465 res = &chan->RegTranslation[_port]; \
467 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
471 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
472 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
476 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
478 Buffer = ((_type*)Buffer)+1; \
483 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
484 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
486 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
487 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
499 // Assume, proper drive is already seleted
500 WaitOnBusyLong(chan
);
501 for (i
= 0; i
< 0x10000; i
++) {
503 GetStatus(chan
, statusByte
);
504 if (statusByte
& IDE_STATUS_DRQ
) {
505 // Suck out any remaining bytes and throw away.
506 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
507 UniataNanoSleep(PIO0_TIMING
);
513 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
516 } // AtapiSuckPort2()
520 AtapiSuckPortBuffer2(
529 BOOLEAN retry
= FALSE
;
531 // Assume, proper drive is already seleted
532 WaitOnBusyLong(chan
);
533 for (i
= 0; i
< Count
; i
++) {
535 GetStatus(chan
, statusByte
);
536 if (statusByte
& IDE_STATUS_DRQ
) {
537 // Suck out any remaining bytes and throw away.
538 data
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
542 UniataNanoSleep(PIO0_TIMING
);
545 if(i
<Count
&& !retry
) {
546 KdPrint2((PRINT_PREFIX
" wait...\n"));
554 KdPrint2((PRINT_PREFIX
"AtapiSuckPortBuffer2: %#x words\n", i
));
556 AtapiSuckPort2(chan
);
560 } // AtapiSuckPortBuffer2()
571 GetStatus(chan
, Status
);
572 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
573 if (Status
& IDE_STATUS_BUSY
) {
574 AtapiStallExecution(g_opt_WaitBusyDelay
);
575 GetStatus(chan
, Status
);
582 } // end WaitOnBusy()
593 Status
= WaitOnBusy(chan
);
594 if(!(Status
& IDE_STATUS_BUSY
))
596 for (i
=0; i
<g_opt_WaitBusyLongCount
; i
++) {
597 GetStatus(chan
, Status
);
598 if (Status
& IDE_STATUS_BUSY
) {
599 AtapiStallExecution(g_opt_WaitBusyLongDelay
);
606 } // end WaitOnBusyLong()
615 UCHAR Status
= IDE_STATUS_WRONG
;
616 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
617 GetBaseStatus(chan
, Status
);
618 if (Status
& IDE_STATUS_BUSY
) {
619 AtapiStallExecution(g_opt_WaitBusyDelay
);
626 } // end WaitOnBaseBusy()
637 Status
= WaitOnBaseBusy(chan
);
638 if(!(Status
& IDE_STATUS_BUSY
))
640 for (i
=0; i
<2000; i
++) {
641 GetBaseStatus(chan
, Status
);
642 if (Status
& IDE_STATUS_BUSY
) {
643 AtapiStallExecution(250);
650 } // end WaitOnBaseBusyLong()
655 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
661 if(Status
== IDE_STATUS_WRONG
) {
662 return IDE_STATUS_WRONG
;
664 if(Status
& IDE_STATUS_BUSY
) {
667 // if(deviceExtension->HwFlags & UNIATA_SATA) {
668 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
669 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
673 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
674 if ((Status
& IDE_STATUS_BUSY
) ||
675 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
679 return IDE_STATUS_IDLE
;
680 } // end UniataIsIdle()
691 for (i
=0; i
<20000; i
++) {
692 GetStatus(chan
, Status
);
693 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
694 if(Status2
== IDE_STATUS_WRONG
) {
698 if(Status2
& IDE_STATUS_BUSY
) {
699 AtapiStallExecution(10);
706 } // end WaitForIdleLong()
716 for (i
=0; i
<1000; i
++) {
717 GetStatus(chan
, Status
);
718 if (Status
& IDE_STATUS_BUSY
) {
719 AtapiStallExecution(g_opt_WaitDrqDelay
);
720 } else if (Status
& IDE_STATUS_DRQ
) {
723 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
727 } // end WaitForDrq()
737 for (i
=0; i
<2; i
++) {
738 GetStatus(chan
, Status
);
739 if (Status
& IDE_STATUS_BUSY
) {
740 AtapiStallExecution(g_opt_WaitDrqDelay
);
741 } else if (Status
& IDE_STATUS_DRQ
) {
744 AtapiStallExecution(g_opt_WaitDrqDelay
);
748 } // end WaitShortForDrq()
757 //ULONG c = chan->lChannel;
759 UCHAR dma_status
= 0;
760 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
763 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
764 UniataAhciSoftReset(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
);
768 GetBaseStatus(chan
, statusByte2
);
769 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
770 SelectDrive(chan
, DeviceNumber
);
771 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
773 AtapiStallExecution(10000);
774 for (i
= 0; i
< 1000; i
++) {
775 AtapiStallExecution(999);
778 AtapiStallExecution(500);
779 GetBaseStatus(chan
, statusByte2
);
780 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
782 // Do not wait for BUSY assertion if it was initially set, jump to
783 // BUSY release wait loop
784 if(!(statusByte2
& IDE_STATUS_BUSY
)) {
785 // Wait for BUSY assertion, in some cases delay may occure
786 // 100ms should be enough
788 while (!(AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
791 AtapiStallExecution(10);
796 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
797 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
798 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
799 // implementation. (which is around 1 second)
800 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
803 AtapiStallExecution(30);
805 KdPrint2((PRINT_PREFIX
" set DFLAGS_REINIT_DMA\n"));
806 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
809 SelectDrive(chan
, DeviceNumber
);
811 GetBaseStatus(chan
, statusByte2
);
812 AtapiStallExecution(500);
814 GetBaseStatus(chan
, statusByte2
);
815 if(chan
&& chan
->DeviceExtension
) {
816 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
817 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
819 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
821 if(dma_status
& BM_STATUS_INTR
) {
822 // bullshit, we have DMA interrupt, but had never initiate DMA operation
823 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
824 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
825 GetBaseStatus(chan
, statusByte2
);
827 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
828 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
829 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
830 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
835 } // end AtapiSoftReset()
838 Send command to device.
839 Translate to 48-Lba form if required
844 IN PHW_DEVICE_EXTENSION deviceExtension
,
845 IN ULONG DeviceNumber
,
854 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
859 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
860 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
862 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
863 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
865 KdPrint3((" (ahci)\n"));
867 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
868 (PSCSI_REQUEST_BLOCK
)NULL
,
876 1000 /* timeout 1 sec */
882 SelectDrive(chan
, DeviceNumber
);
884 statusByte
= WaitOnBusy(chan
);
886 /* ready to issue command ? */
887 if (statusByte
& IDE_STATUS_BUSY
) {
888 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
891 // !!! We should not check ERROR condition here
892 // ERROR bit may be asserted durring previous operation
893 // and not cleared after SELECT
895 //>>>>>> NV: 2006/08/03
896 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
897 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
898 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
899 return IDE_STATUS_ERROR
;
900 //return SRB_STATUS_ERROR;
902 //<<<<<< NV: 2006/08/03
904 /* only use 48bit addressing if needed because of the overhead */
905 if (UniAta_need_lba48(command
, lba
, count
,
906 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
908 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
909 /* translate command into 48bit version */
910 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
911 command
= AtaCommands48
[command
];
913 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
917 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
920 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
921 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
922 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
923 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
924 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
925 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
926 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
927 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
928 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
929 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
931 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
932 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
935 plba
= (PUCHAR
)&lba
; //ktp
936 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
939 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
940 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
942 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
943 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
944 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
945 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
946 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
947 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
948 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
950 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
951 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
955 // write command code to device
956 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
958 switch (wait_flags
) {
961 // caller requested wait for interrupt
964 statusByte
= WaitForDrq(chan
);
965 if (statusByte
& IDE_STATUS_DRQ
)
967 AtapiStallExecution(500);
968 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
975 // caller requested wait for entering Wait state
976 for (i
=0; i
<30 * 1000; i
++) {
978 GetStatus(chan
, statusByte
);
979 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
980 if(statusByte
== IDE_STATUS_WRONG
) {
984 if(statusByte
& IDE_STATUS_ERROR
) {
987 if(statusByte
& IDE_STATUS_BUSY
) {
988 AtapiStallExecution(100);
991 if(statusByte
== IDE_STATUS_IDLE
) {
994 //if(deviceExtension->HwFlags & UNIATA_SATA) {
995 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
998 AtapiStallExecution(100);
1001 //statusByte |= IDE_STATUS_BUSY;
1004 case ATA_WAIT_READY
:
1005 statusByte
= WaitOnBusyLong(chan
);
1007 case ATA_WAIT_BASE_READY
:
1008 statusByte
= WaitOnBaseBusyLong(chan
);
1011 GetStatus(chan
, statusByte
);
1012 if (statusByte
& IDE_STATUS_ERROR
) {
1013 // Note: some diveces doesn't clear ERR immediately
1014 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
1015 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
1018 KdPrint2((PRINT_PREFIX
" try to continue\n"));
1019 statusByte
&= ~IDE_STATUS_ERROR
;
1022 //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte));
1024 UniataExpectChannelInterrupt(chan
, TRUE
);
1026 InterlockedExchange(&(chan
->CheckIntr
),
1029 statusByte
= IDE_STATUS_SUCCESS
;
1033 //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
1036 } // end AtaCommand48()
1039 Send command to device.
1040 This is simply wrapper for AtaCommand48()
1045 IN PHW_DEVICE_EXTENSION deviceExtension
,
1046 IN ULONG DeviceNumber
,
1057 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
1058 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1060 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1061 count
, feature
, wait_flags
);
1063 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
1064 (PSCSI_REQUEST_BLOCK
)NULL
,
1068 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1071 0 /* ahci flags */ ,
1073 1000 /* timeout 1 sec */
1077 } // end AtaCommand()
1081 AtaPio2Mode(LONG pio
)
1084 default: return ATA_PIO
;
1085 case 0: return ATA_PIO0
;
1086 case 1: return ATA_PIO1
;
1087 case 2: return ATA_PIO2
;
1088 case 3: return ATA_PIO3
;
1089 case 4: return ATA_PIO4
;
1090 case 5: return ATA_PIO5
;
1092 } // end AtaPio2Mode()
1096 AtaPioMode(PIDENTIFY_DATA2 ident
)
1098 if (ident
->PioTimingsValid
) {
1099 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1101 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1103 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1106 if (ident
->PioCycleTimingMode
== 2)
1108 if (ident
->PioCycleTimingMode
== 1)
1110 if (ident
->PioCycleTimingMode
== 0)
1112 return IOMODE_NOT_SPECIFIED
;
1113 } // end AtaPioMode()
1117 AtaWmode(PIDENTIFY_DATA2 ident
)
1119 if (ident
->MultiWordDMASupport
& 0x04)
1121 if (ident
->MultiWordDMASupport
& 0x02)
1123 if (ident
->MultiWordDMASupport
& 0x01)
1125 return IOMODE_NOT_SPECIFIED
;
1130 AtaUmode(PIDENTIFY_DATA2 ident
)
1132 if (!ident
->UdmaModesValid
)
1133 return IOMODE_NOT_SPECIFIED
;
1134 if (ident
->UltraDMASupport
& 0x40)
1136 if (ident
->UltraDMASupport
& 0x20)
1138 if (ident
->UltraDMASupport
& 0x10)
1140 if (ident
->UltraDMASupport
& 0x08)
1142 if (ident
->UltraDMASupport
& 0x04)
1144 if (ident
->UltraDMASupport
& 0x02)
1146 if (ident
->UltraDMASupport
& 0x01)
1148 return IOMODE_NOT_SPECIFIED
;
1153 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1154 if(!ident
->SataCapabilities
||
1155 ident
->SataCapabilities
== 0xffff) {
1156 return IOMODE_NOT_SPECIFIED
;
1158 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1161 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1164 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1167 return IOMODE_NOT_SPECIFIED
;
1168 } // end AtaSAmode()
1175 IN PVOID HwDeviceExtension
1178 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1179 PHW_TIMER HwScsiTimer
;
1181 ULONG MiniportTimerValue
;
1182 BOOLEAN recall
= FALSE
;
1186 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1188 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1189 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1190 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1193 chan
= &(deviceExtension
->chan
[lChannel
]);
1197 HwScsiTimer
= chan
->HwScsiTimer
;
1198 chan
->HwScsiTimer
= NULL
;
1200 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1201 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1205 HwScsiTimer(HwDeviceExtension
);
1207 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1209 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1210 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1211 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1212 deviceExtension
->FirstDpcChan
=
1213 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1217 KeQuerySystemTime(&time
);
1218 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1220 chan
= &deviceExtension
->chan
[lChannel
];
1221 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1223 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1224 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1231 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1232 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1233 if(!MiniportTimerValue
)
1234 MiniportTimerValue
= 1;
1236 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1237 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1244 } // end AtapiTimerDpc()
1247 Wrapper for ScsiPort, that implements smart Dpc
1248 queueing. We need it to allow parallel functioning
1249 of IDE channles with shared interrupt. Standard Dpc mechanism
1250 cancels previous Dpc request (if any), but we need Dpc queue.
1255 IN PVOID HwDeviceExtension
,
1257 IN PHW_TIMER HwScsiTimer
,
1258 IN ULONG MiniportTimerValue
1261 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1263 LARGE_INTEGER time2
;
1265 PHW_CHANNEL prev_chan
;
1267 // BOOLEAN UseRequestTimerCall = TRUE;
1269 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1270 KeQuerySystemTime(&time
);
1272 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1273 time
.QuadPart
+= MiniportTimerValue
*10;
1274 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1276 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1278 i
= deviceExtension
->FirstDpcChan
;
1279 chan
= prev_chan
= NULL
;
1280 while(i
!= CHAN_NOT_SPECIFIED
) {
1282 chan
= &(deviceExtension
->chan
[i
]);
1283 if(chan
->DpcTime
> time
.QuadPart
) {
1286 i
= chan
->NextDpcChan
;
1288 chan
= &(deviceExtension
->chan
[lChannel
]);
1290 deviceExtension
->FirstDpcChan
= lChannel
;
1292 prev_chan
->NextDpcChan
= lChannel
;
1294 chan
->NextDpcChan
= i
;
1295 chan
->HwScsiTimer
= HwScsiTimer
;
1296 chan
->DpcTime
= time
.QuadPart
;
1298 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1299 if(time
.QuadPart
<= time2
.QuadPart
) {
1300 MiniportTimerValue
= 1;
1302 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1305 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1306 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1308 MiniportTimerValue
);
1310 } // end AtapiQueueTimerDpc()
1312 #endif //UNIATA_CORE
1322 UCHAR statusByteAlt
;
1324 GetStatus(chan
, statusByteAlt
);
1325 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1327 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1328 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1329 KdPrint2((PRINT_PREFIX
1330 " Reg_%#x (%#x) = %#x\n",
1332 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1335 if(!chan
->RegTranslation
[IDX_BM_IO
].Addr
) {
1338 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1339 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1340 KdPrint2((PRINT_PREFIX
1341 " BM_%#x (%#x) = %#x\n",
1343 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1347 } // end UniataDumpATARegs()
1353 IN PHW_CHANNEL chan
,
1354 IN ULONG DeviceNumber
,
1355 IN OUT PIDEREGS_EX regs
1358 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1360 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1362 // SATA/PATA, assume drive is selected
1364 UCHAR statusByteAlt
;
1366 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1367 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1368 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1369 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1373 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1374 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1375 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1376 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1377 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1378 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1380 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1384 } // end UniataSnapAtaRegs()
1388 Routine Description:
1390 Issue IDENTIFY command to a device.
1394 HwDeviceExtension - HBA miniport driver's adapter data storage
1395 DeviceNumber - Indicates which device.
1396 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1400 TRUE if all goes well.
1406 IN PVOID HwDeviceExtension
,
1407 IN ULONG DeviceNumber
,
1413 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1414 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1415 ULONG waitCount
= 50000;
1418 //UCHAR statusByte2;
1421 BOOLEAN atapiDev
= FALSE
;
1422 BOOLEAN use_ahci
= FALSE
;
1423 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1425 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1426 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1428 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1429 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1432 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1436 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1437 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1440 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1441 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1446 statusByte
= WaitOnBusyLong(chan
);
1448 if(!chan
->AhciInternalAtaReq
) {
1449 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1453 SelectDrive(chan
, DeviceNumber
);
1454 AtapiStallExecution(10);
1455 statusByte
= WaitOnBusyLong(chan
);
1456 // Check that the status register makes sense.
1457 GetBaseStatus(chan
, statusByte
);
1460 if (Command
== IDE_COMMAND_IDENTIFY
) {
1461 // Mask status byte ERROR bits.
1462 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1463 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1464 // Check if register value is reasonable.
1466 if(statusByte
!= IDE_STATUS_IDLE
) {
1468 // No reset here !!!
1469 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1471 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1472 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1473 SelectDrive(chan
, DeviceNumber
);
1474 WaitOnBusyLong(chan
);
1476 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1477 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1479 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1480 signatureHigh
== ATAPI_MAGIC_MSB
) {
1482 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1486 // We really should wait up to 31 seconds
1487 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1488 // (30 seconds for device 1)
1490 // Wait for Busy to drop.
1491 AtapiStallExecution(100);
1492 GetStatus(chan
, statusByte
);
1493 if(statusByte
== IDE_STATUS_WRONG
) {
1494 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1498 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1499 GetBaseStatus(chan
, statusByte
);
1501 SelectDrive(chan
, DeviceNumber
);
1503 GetBaseStatus(chan
, statusByte
);
1505 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1507 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1508 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1510 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1511 signatureHigh
== ATAPI_MAGIC_MSB
) {
1512 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1517 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1518 if (statusByte
!= IDE_STATUS_IDLE
) {
1520 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1525 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1526 if(statusByte
== IDE_STATUS_WRONG
) {
1529 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1530 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1531 statusByte
= WaitForIdleLong(chan
);
1532 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1537 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1539 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1540 (PSCSI_REQUEST_BLOCK
)NULL
,
1541 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1546 0 /* ahci flags */ ,
1548 1000 /* timeout 1 sec */
1550 j
= 9; // AHCI is rather different, skip loop at all
1552 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1553 j
= 9; // don't send IDENTIFY, assume it is not supported
1554 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1555 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1556 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1558 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1559 j
= 4; // skip old-style checks
1563 for (; j
< 4*2; j
++) {
1564 // Send IDENTIFY command.
1566 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1568 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1572 KdPrint2((PRINT_PREFIX
"IssueIdentify: 0-status, not present\n"));
1575 if (statusByte
& IDE_STATUS_DRQ
) {
1576 // Read status to acknowledge any interrupts generated.
1577 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1578 GetBaseStatus(chan
, statusByte
);
1579 // One last check for Atapi.
1580 if (Command
== IDE_COMMAND_IDENTIFY
) {
1581 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1582 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1584 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1585 signatureHigh
== ATAPI_MAGIC_MSB
) {
1586 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1593 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1594 if (Command
== IDE_COMMAND_IDENTIFY
) {
1595 // Check the signature. If DRQ didn't come up it's likely Atapi.
1596 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1597 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1599 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1600 signatureHigh
== ATAPI_MAGIC_MSB
) {
1602 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1606 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1607 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1611 // Device didn't respond correctly. It will be given one more chance.
1612 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1613 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1614 GetBaseStatus(chan
, statusByte
);
1615 AtapiSoftReset(chan
,DeviceNumber
);
1617 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1618 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1620 GetBaseStatus(chan
, statusByte
);
1621 //GetStatus(chan, statusByte);
1622 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1625 // Check for error on really stupid master devices that assert random
1626 // patterns of bits in the status register at the slave address.
1627 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1628 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1633 // everything should already be done by controller
1635 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1636 j
= 9; // don't send IDENTIFY, assume it is not supported
1637 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1638 statusByte
= WaitForDrq(chan
);
1639 statusByte
= WaitOnBusyLong(chan
);
1640 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1641 GetBaseStatus(chan
, statusByte
);
1644 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1645 // Suck out 256 words. After waiting for one model that asserts busy
1646 // after receiving the Packet Identify command.
1647 statusByte
= WaitForDrq(chan
);
1648 statusByte
= WaitOnBusyLong(chan
);
1649 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1651 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1652 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1653 GetBaseStatus(chan
, statusByte
);
1656 GetBaseStatus(chan
, statusByte
);
1657 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1659 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1661 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1664 j
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
1665 KdPrint3((PRINT_PREFIX
"IssueIdentify: iReason %x\n", j
));
1668 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
1671 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
1672 KdPrint3((PRINT_PREFIX
"IssueIdentify: wCount %x\n", j
));
1676 // ATI/SII chipsets with memory-mapped IO hangs when
1677 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1678 // Unfortunately, I don't know yet how to workaround it except
1679 // specifying manual delay in the way you see below.
1680 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1682 // Work around for some IDE and one model Atapi that will present more than
1683 // 256 bytes for the Identify data.
1684 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1685 statusByte
= AtapiSuckPort2(chan
);
1687 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1688 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1691 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1692 statusByte
= WaitForDrq(chan
);
1693 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1694 GetBaseStatus(chan
, statusByte
);
1696 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1699 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1703 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1704 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1705 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1706 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1707 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1708 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1710 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1711 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1712 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1713 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1715 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1716 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1717 deviceExtension
->FullIdentifyData
.SataSupport
,
1718 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1720 LunExt
->LimitedTransferMode
=
1721 LunExt
->OrigTransferMode
=
1722 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1723 LunExt
->TransferMode
=
1724 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1726 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1727 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1728 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1729 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1731 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d\n",
1732 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1735 KdPrint2((PRINT_PREFIX
"PowerMngt %d/%d, APM %d/%d\n",
1736 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.PowerMngt
,
1737 deviceExtension
->FullIdentifyData
.FeaturesSupport
.PowerMngt
,
1738 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.APM
,
1739 deviceExtension
->FullIdentifyData
.FeaturesSupport
.APM
1742 // Check out a few capabilities / limitations of the device.
1743 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1744 // Determine if this drive supports the MSN functions.
1745 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1747 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1748 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1751 // AHCI doesn't recommend using PIO and multiblock
1752 LunExt
->MaximumBlockXfer
= 0;
1754 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1755 // Determine max. block transfer for this device.
1756 LunExt
->MaximumBlockXfer
=
1757 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1759 LunExt
->NumOfSectors
= 0;
1760 if (Command
== IDE_COMMAND_IDENTIFY
) {
1761 ULONGLONG NumOfSectors
=0;
1762 ULONGLONG NativeNumOfSectors
=0;
1763 ULONGLONG cylinders
=0;
1764 ULONGLONG tmp_cylinders
=0;
1766 KdPrint2((PRINT_PREFIX
"PhysLogSectorSize %#x, %#x, offset %#x\n",
1767 deviceExtension
->FullIdentifyData
.PhysLogSectorSize
,
1768 deviceExtension
->FullIdentifyData
.LargeSectorSize
,
1769 deviceExtension
->FullIdentifyData
.LogicalSectorOffset
1772 KdPrint2((PRINT_PREFIX
"NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1773 deviceExtension
->FullIdentifyData
.NVCache_PM_Supported
,
1774 deviceExtension
->FullIdentifyData
.NVCache_PM_Enabled
,
1775 deviceExtension
->FullIdentifyData
.NVCache_Enabled
,
1776 deviceExtension
->FullIdentifyData
.NVCache_PM_Version
,
1777 deviceExtension
->FullIdentifyData
.NVCache_Version
1780 KdPrint2((PRINT_PREFIX
"R-rate %d\n",
1781 deviceExtension
->FullIdentifyData
.NominalMediaRotationRate
1783 KdPrint2((PRINT_PREFIX
"WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
1784 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.WriteCache
,
1785 deviceExtension
->FullIdentifyData
.FeaturesSupport
.WriteCache
,
1786 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.LookAhead
,
1787 deviceExtension
->FullIdentifyData
.FeaturesSupport
.LookAhead
,
1788 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.WriteBuffer
,
1789 deviceExtension
->FullIdentifyData
.FeaturesSupport
.WriteBuffer
,
1790 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.ReadBuffer
,
1791 deviceExtension
->FullIdentifyData
.FeaturesSupport
.ReadBuffer
,
1792 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Queued
,
1793 deviceExtension
->FullIdentifyData
.FeaturesSupport
.Queued
1796 KdPrint2((PRINT_PREFIX
"Protected %d/%d status %#x, rev %#x\n",
1797 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Protected
,
1798 deviceExtension
->FullIdentifyData
.FeaturesSupport
.Protected
,
1799 deviceExtension
->FullIdentifyData
.SecurityStatus
,
1800 deviceExtension
->FullIdentifyData
.MasterPasswdRevision
1803 // Read very-old-style drive geometry
1804 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1805 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1806 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1807 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1809 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1810 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1811 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1812 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1813 // Check for HDDs > 8Gb
1814 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1815 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1816 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1817 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1819 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1820 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1821 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1823 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1825 NumOfSectors
= cylinders
*
1826 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1827 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1829 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1833 // Check for LBA mode
1834 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1835 KdPrint2((PRINT_PREFIX
"SupportDMA flag %#x\n", deviceExtension
->FullIdentifyData
.SupportDma
));
1836 KdPrint2((PRINT_PREFIX
"SoftReset %#x\n", deviceExtension
->FullIdentifyData
.SoftReset
));
1837 KdPrint2((PRINT_PREFIX
"SupportIordy %#x, DisableIordy %#x\n",
1838 deviceExtension
->FullIdentifyData
.SupportIordy
,
1839 deviceExtension
->FullIdentifyData
.DisableIordy
1841 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1842 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1843 if ( deviceExtension
->FullIdentifyData
.SupportLba
1845 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1846 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1847 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1848 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1849 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1851 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1852 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1853 goto skip_lba_staff
;
1855 // Check for LBA48 support
1856 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1857 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1858 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1859 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1861 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1863 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1864 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1865 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1867 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1869 NativeNumOfSectors
= cylinders
*
1870 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1871 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1873 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1875 if(NativeNumOfSectors
> NumOfSectors
) {
1876 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1877 NumOfSectors
= NativeNumOfSectors
;
1881 // Check drive capacity report for LBA48-capable drives.
1882 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1883 ULONG hNativeNumOfSectors
;
1884 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1886 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1887 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1889 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1891 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1893 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1894 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1895 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1897 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1900 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1901 NativeNumOfSectors
|=
1902 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1903 hNativeNumOfSectors
=
1904 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1905 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1906 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1908 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1910 // Some drives report LBA48 capability while has capacity below 128Gb
1911 // Probably they support large block-counters.
1912 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1913 // Here we check this
1914 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1915 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1917 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1918 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1920 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1922 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1924 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1925 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1926 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1927 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1928 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1929 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1934 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1935 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1936 NativeNumOfSectors
= 0;
1940 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1941 NativeNumOfSectors
> NumOfSectors
) {
1943 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1944 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1946 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1947 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1948 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1949 NumOfSectors
= NativeNumOfSectors
;
1955 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1956 // check for native LBA size
1957 // some drives report ~32Gb in Identify Block
1958 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1960 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1961 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1963 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1965 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1967 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1968 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1969 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1970 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1972 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1974 if(NativeNumOfSectors
> NumOfSectors
) {
1976 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1977 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1979 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1980 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1981 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1982 NumOfSectors
= NativeNumOfSectors
;
1988 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1990 // fill IdentifyData with bogus geometry
1991 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1992 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1993 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1994 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1995 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1996 // ok, we can keep original values
1997 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1998 LunExt
->opt_GeomType
= GEOM_ORIG
;
2001 tmp_cylinders
= NumOfSectors
/ (255*63);
2002 if(tmp_cylinders
< 0xffff) {
2003 // we can use generic values for H/S for generic geometry approach
2004 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2005 LunExt
->opt_GeomType
= GEOM_STD
;
2008 // we should use UNIATA geometry approach
2009 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
2010 LunExt
->opt_GeomType
= GEOM_UNIATA
;
2015 if(LunExt
->opt_GeomType
== GEOM_STD
) {
2016 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
2017 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
2019 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
2020 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
2022 cylinders
= NumOfSectors
/ (255*63);
2023 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
2025 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
2026 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
2028 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
2029 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
2030 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
2032 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
2034 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
2035 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
2036 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
2038 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
2040 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
2041 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
2042 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
2044 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
2046 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
2047 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
2048 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
2050 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
2051 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
2052 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
2055 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
2056 cylinders
= tmp_cylinders
;
2058 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
2059 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
2063 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
2064 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
2065 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
2067 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
2068 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
2069 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
2071 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
2072 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
2073 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
2077 LunExt
->NumOfSectors
= NumOfSectors
;
2079 if(deviceExtension
->FullIdentifyData
.MajorRevision
&&
2080 deviceExtension
->FullIdentifyData
.DoubleWordIo
) {
2081 //LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
2082 KdPrint2((PRINT_PREFIX
"IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
2086 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
2087 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
2089 InitBadBlocks(LunExt
);
2091 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
2092 (Command
!= IDE_COMMAND_IDENTIFY
)) {
2094 // This device interrupts with the assertion of DRQ after receiving
2095 // Atapi Packet Command
2096 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
2097 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2100 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2103 if(Command
!= IDE_COMMAND_IDENTIFY
) {
2105 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
2107 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
2108 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
2110 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
2111 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
2112 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
2113 // set CD default costs
2114 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
2115 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
2116 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
2117 statusByte
= WaitForDrq(chan
);
2120 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
2121 LunExt
->IdentifyData
.DeviceType
));
2123 KdPrint2((PRINT_PREFIX
"IssueIdentify: AtapiCmdSize %#x\n", deviceExtension
->FullIdentifyData
.AtapiCmdSize
));
2125 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
2128 GetBaseStatus(chan
, statusByte
);
2129 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
2132 } // end IssueIdentify()
2137 Routine Description:
2138 Set drive parameters using the IDENTIFY data.
2141 HwDeviceExtension - HBA miniport driver's adapter data storage
2142 DeviceNumber - Indicates which device.
2145 TRUE if all goes well.
2151 IN PVOID HwDeviceExtension
,
2152 IN ULONG DeviceNumber
,
2156 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2157 PIDENTIFY_DATA2 identifyData
;
2158 PHW_LU_EXTENSION LunExt
;
2163 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2164 identifyData
= &(LunExt
->IdentifyData
);
2166 if(LunExt
->DeviceFlags
&
2167 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2170 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2171 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2173 // Send SET PARAMETER command.
2174 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2175 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2176 (identifyData
->NumberOfHeads
- 1), 0,
2177 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2179 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2180 if(statusByte
& IDE_STATUS_ERROR
) {
2181 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2182 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2183 errorByte
, statusByte
));
2187 if(statusByte
== IDE_STATUS_IDLE
) {
2193 } // end SetDriveParameters()
2198 PHW_LU_EXTENSION LunExt
2201 // keep only DFLAGS_HIDDEN flag
2202 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2203 LunExt
->AtapiReadyWaitDelay
= 0;
2204 } // end UniataForgetDevice()
2209 Routine Description:
2210 Reset IDE controller and/or Atapi device.
2214 HwDeviceExtension - HBA miniport driver's adapter data storage
2223 AtapiResetController(
2224 IN PVOID HwDeviceExtension
,
2228 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2229 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2230 } // end AtapiResetController()
2234 AtapiResetController__(
2235 IN PVOID HwDeviceExtension
,
2237 IN BOOLEAN CompleteType
2240 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2241 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2242 PHW_CHANNEL chan
= NULL
;
2246 PSCSI_REQUEST_BLOCK CurSrb
;
2247 ULONG ChannelCtrlFlags
;
2248 UCHAR dma_status
= 0;
2250 ULONG slotNumber
= deviceExtension
->slotNumber
;
2251 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2252 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2254 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2256 //ULONG RevID = deviceExtension->RevID;
2257 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2261 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2262 KdPrint2((PRINT_PREFIX
"simplexOnly %d\n", deviceExtension
->simplexOnly
));
2264 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2265 // we shall reset both channels on SimplexOnly devices,
2266 // It's not worth doing so on normal controllers
2268 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2271 numberChannels
= deviceExtension
->NumberChannels
;
2274 for (; j
< numberChannels
; j
++) {
2276 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset lchannel %d[%d]\n", j
, deviceExtension
->Channel
));
2277 chan
= &(deviceExtension
->chan
[j
]);
2278 MaxLuns
= chan
->NumberLuns
;
2279 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType
, MaxLuns
, chan
, &chan
));
2280 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2281 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2283 while((CurSrb
= UniataGetCurRequest(chan
))) {
2285 PHW_LU_EXTENSION LunExt
;
2286 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2288 i
= GET_CDEV(CurSrb
);
2289 KdPrint2((PRINT_PREFIX
" Lun %x\n", i
));
2290 LunExt
= chan
->lun
[i
];
2292 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2293 if(CurSrb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
2294 KdPrint2((PRINT_PREFIX
" was MechStatus\n"));
2296 if(!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)) {
2297 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
2298 KdPrint2((PRINT_PREFIX
" set DFLAGS_CHANGER_INITED\n"));
2301 // Check and see if we are processing an internal srb
2302 if (AtaReq
->OriginalSrb
) {
2303 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2304 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2305 CurSrb
->SrbExtension
= NULL
;
2306 AtaReq
->OriginalSrb
= NULL
;
2307 // NOTE: internal SRB doesn't get to SRB queue !!!
2308 CurSrb
= AtaReq
->Srb
;
2311 // Remove current request from queue
2312 UniataRemoveRequest(chan
, CurSrb
);
2314 // Check if request is in progress.
2315 ASSERT(AtaReq
->Srb
== CurSrb
);
2317 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2318 UCHAR PathId
= CurSrb
->PathId
;
2319 UCHAR TargetId
= CurSrb
->TargetId
;
2320 UCHAR Lun
= CurSrb
->Lun
;
2322 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2323 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2325 if (CurSrb
->SenseInfoBuffer
) {
2327 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2328 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x\n", senseBuffer
, chan
));
2330 senseBuffer
->ErrorCode
= 0x70;
2331 senseBuffer
->Valid
= 1;
2332 senseBuffer
->AdditionalSenseLength
= 0xb;
2333 if(CompleteType
== RESET_COMPLETE_ALL
) {
2334 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2335 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2336 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2337 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2339 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2340 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2341 senseBuffer
->AdditionalSenseCode
= 0;
2342 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2346 if(!ATAPI_DEVICE(chan
, i
) && AtaReq
->bcount
&& AtaReq
->retry
< MAX_RETRIES
) {
2347 KdPrint2((PRINT_PREFIX
"Save retry status %d\n", AtaReq
->retry
));
2348 LunExt
->errLastLba
= AtaReq
->lba
;
2349 LunExt
->errBCount
= AtaReq
->bcount
;
2350 LunExt
->errRetry
= AtaReq
->retry
+1;
2352 LunExt
->errRetry
= 0;
2355 // Clear request tracking fields.
2356 AtaReq
->WordsLeft
= 0;
2357 AtaReq
->DataBuffer
= NULL
;
2358 AtaReq
->TransferLength
= 0;
2359 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2361 ScsiPortNotification(RequestComplete
,
2365 // Indicate ready for next request.
2366 ScsiPortNotification(NextLuRequest
,
2372 if(CompleteType
!= RESET_COMPLETE_ALL
)
2375 #endif //UNIATA_CORE
2376 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2378 // Save control flags
2379 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2380 // Clear expecting interrupt flag.
2381 UniataExpectChannelInterrupt(chan
, FALSE
);
2383 chan
->ChannelCtrlFlags
= 0;
2384 InterlockedExchange(&(chan
->CheckIntr
),
2387 for (i
= 0; i
< MaxLuns
; i
++) {
2388 chan
->lun
[i
]->PowerState
= 0;
2391 if(ChipFlags
& UNIATA_AHCI
) {
2392 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2393 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2395 UniataDumpAhciPortRegs(chan
);
2397 AtapiDisableInterrupts(deviceExtension
, j
);
2398 UniataAhciReset(HwDeviceExtension
, j
);
2400 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2404 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2405 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2406 AtapiDisableInterrupts(deviceExtension
, j
);
2407 KdPrint2((PRINT_PREFIX
" done\n"));
2409 case ATA_INTEL_ID
: {
2413 if(!(ChipFlags
& UNIATA_SATA
)) {
2416 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2421 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2422 if(ChipFlags
& UNIATA_AHCI
) {
2425 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2426 GetPciConfig1(0x90, tmp8
);
2434 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2436 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2439 ChangePciConfig2(0x92, a
& ~mask
);
2440 AtapiStallExecution(10);
2441 ChangePciConfig2(0x92, a
| mask
);
2444 /* Wait up to 1 sec for "connect well". */
2445 if (ChipFlags
& (I6CH
| I6CH2
)) {
2451 GetPciConfig2(0x92, tmp16
);
2452 if (((tmp16
>> pshift
) & mask
) == mask
) {
2453 GetBaseStatus(chan
, statusByte
);
2454 if(statusByte
!= IDE_STATUS_WRONG
) {
2458 AtapiStallExecution(10000);
2462 case ATA_NVIDIA_ID
: {
2464 ULONG Channel
= deviceExtension
->Channel
+ j
;
2465 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2466 if(!(ChipFlags
& UNIATA_SATA
)) {
2469 offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
2471 KdPrint2((PRINT_PREFIX
" disable Phy intr, offs %#x, c %u\n", offs
, Channel
));
2472 /* disable device and PHY state change interrupts */
2473 if(ChipFlags
& NVQ
) {
2474 KdPrint2((PRINT_PREFIX
" NVQ, 32bits reg\n"));
2475 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2476 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) & ((~(ULONG
)0x0000000d) << (!Channel
*16)) );
2478 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2479 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) & ((~(UCHAR
)0x0d) << (!Channel
*4)) );
2481 tmp16
= UniataSataPhyEnable(HwDeviceExtension
, j
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
);
2483 KdPrint2((PRINT_PREFIX
" enable Phy intr, offs %#x\n", offs
));
2484 /* enable device and PHY state change interrupts */
2485 if(ChipFlags
& NVQ
) {
2486 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2487 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) | (((ULONG
)0x0000000d) << (!Channel
*16)) );
2489 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2490 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) | (((UCHAR
)0x0d) << (!Channel
*4)) );
2493 KdPrint2((PRINT_PREFIX
" dev status %#x\n", tmp16
));
2494 if(tmp16
!= IDE_STATUS_WRONG
) {
2498 case ATA_SILICON_IMAGE_ID
: {
2500 ULONG Channel
= deviceExtension
->Channel
+ j
;
2501 if(!(ChipFlags
& UNIATA_SATA
))
2503 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2504 /* disable PHY state change interrupt */
2505 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2507 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2509 /* reset controller part for this channel */
2510 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2511 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2512 AtapiStallExecution(1000);
2513 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2514 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2518 case ATA_PROMISE_ID
: {
2521 if(ChipFlags
& UNIATA_SATA
) {
2522 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2523 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2526 KdPrint2((PRINT_PREFIX
" send reset\n"));
2527 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2528 IDE_DC_RESET_CONTROLLER
);
2529 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2530 AtapiStallExecution(10000);
2531 // Disable interrupts
2532 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2533 AtapiDisableInterrupts(deviceExtension
, j
);
2534 AtapiStallExecution(100);
2535 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2536 AtapiEnableInterrupts(deviceExtension
, j
);
2537 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2538 AtapiStallExecution(100000);
2539 KdPrint2((PRINT_PREFIX
" done\n"));
2544 //if(!(ChipFlags & UNIATA_SATA)) {}
2545 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2546 // Reset DMA engine if active
2547 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2548 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2549 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2550 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2551 (dma_status
& BM_STATUS_INTR
)) {
2552 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2557 // all these shall be performed inside AtapiHwInitialize__() ?
2559 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2560 // Do special processing for ATAPI and IDE disk devices.
2561 for (i
= 0; i
< MaxLuns
; i
++) {
2563 // Check if device present.
2564 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2565 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2566 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2567 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2568 if(ChipFlags
& UNIATA_AHCI
) {
2569 // everything is done in UniataAhciReset()
2570 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2576 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2577 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2580 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2584 if(ChipFlags
& UNIATA_AHCI
) {
2585 // everything is done in UniataAhciReset()
2586 KdPrint2((PRINT_PREFIX
" found some device\n"));
2588 if(!IssueIdentify(HwDeviceExtension
,
2590 ATAPI_DEVICE(chan
, i
) ?
2591 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2593 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2594 UniataForgetDevice(chan
->lun
[i
]);
2598 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2599 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2600 UniataForgetDevice(chan
->lun
[i
]);
2605 SelectDrive(chan
, i
);
2606 AtapiStallExecution(10);
2607 statusByte
= WaitOnBusyLong(chan
);
2608 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2609 if(statusByte
== IDE_STATUS_WRONG
) {
2610 KdPrint2((PRINT_PREFIX
2611 "no drive, status %#x\n",
2613 UniataForgetDevice(chan
->lun
[i
]);
2615 // Check for ATAPI disk.
2616 if (ATAPI_DEVICE(chan
, i
)) {
2617 // Issue soft reset and issue identify.
2618 GetStatus(chan
, statusByte
);
2619 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2622 AtapiDisableInterrupts(deviceExtension
, j
);
2623 AtapiSoftReset(chan
, i
);
2624 AtapiEnableInterrupts(deviceExtension
, j
);
2626 GetStatus(chan
, statusByte
);
2628 if(statusByte
!= IDE_STATUS_SUCCESS
) {
2630 k
= UniataAnybodyHome(deviceExtension
, j
, i
);
2631 if(k
== ATA_AT_HOME_HDD
) {
2632 // device reset in progress, perform additional wait
2633 KdPrint2((PRINT_PREFIX
" long reset, wait up to 4.5 s\n"));
2635 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
2638 AtapiStallExecution(150);
2640 KdPrint2((PRINT_PREFIX
" exit after %u loops\n", k
));
2641 GetStatus(chan
, statusByte
);
2644 if(statusByte
== IDE_STATUS_SUCCESS
) {
2646 IssueIdentify(HwDeviceExtension
,
2648 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2651 KdPrint2((PRINT_PREFIX
2652 "AtapiResetController: Status after soft reset %#x\n",
2655 GetBaseStatus(chan
, statusByte
);
2658 // Issue identify and reinit after channel reset.
2660 if (statusByte
!= IDE_STATUS_IDLE
&&
2661 statusByte
!= IDE_STATUS_SUCCESS
&&
2662 statusByte
!= IDE_STATUS_DRDY
) {
2664 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2666 if(!IssueIdentify(HwDeviceExtension
,
2668 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2670 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2672 // Set disk geometry parameters.
2673 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2674 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2676 GetBaseStatus(chan
, statusByte
);
2678 // force DMA mode reinit
2679 KdPrint2((PRINT_PREFIX
" set DFLAGS_REINIT_DMA\n"));
2680 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2684 // Enable interrupts, note, we can have here recursive disable
2685 AtapiStallExecution(10);
2686 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2688 chan
->DisableIntr
));
2689 AtapiEnableInterrupts(deviceExtension
, j
);
2691 // Call the HwInitialize routine to setup multi-block.
2692 AtapiHwInitialize__(deviceExtension
, j
);
2694 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2698 } // end AtapiResetController__()
2703 Routine Description:
2704 This routine maps ATAPI and IDE errors to specific SRB statuses.
2707 HwDeviceExtension - HBA miniport driver's adapter data storage
2708 Srb - IO request packet
2717 IN PVOID HwDeviceExtension
,
2718 IN PSCSI_REQUEST_BLOCK Srb
2721 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2722 ULONG lChannel
= GET_CHANNEL(Srb
);
2723 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2725 UCHAR errorByte
= 0;
2726 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2728 ULONG DeviceNumber
= GET_CDEV(Srb
);
2729 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2731 // Read the error register.
2733 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2734 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2736 errorByte
= AtaReq
->ahci
.in_error
;
2740 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2742 KdPrint2((PRINT_PREFIX
2743 "MapError: Error register is %#x\n",
2746 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2748 switch (errorByte
>> 4) {
2749 case SCSI_SENSE_NO_SENSE
:
2751 KdPrint2((PRINT_PREFIX
2752 "ATAPI: No sense information\n"));
2753 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2754 srbStatus
= SRB_STATUS_ERROR
;
2757 case SCSI_SENSE_RECOVERED_ERROR
:
2759 KdPrint2((PRINT_PREFIX
2760 "ATAPI: Recovered error\n"));
2762 srbStatus
= SRB_STATUS_SUCCESS
;
2765 case SCSI_SENSE_NOT_READY
:
2767 KdPrint2((PRINT_PREFIX
2768 "ATAPI: Device not ready\n"));
2769 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2770 srbStatus
= SRB_STATUS_ERROR
;
2773 case SCSI_SENSE_MEDIUM_ERROR
:
2775 KdPrint2((PRINT_PREFIX
2776 "ATAPI: Media error\n"));
2777 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2778 srbStatus
= SRB_STATUS_ERROR
;
2781 case SCSI_SENSE_HARDWARE_ERROR
:
2783 KdPrint2((PRINT_PREFIX
2784 "ATAPI: Hardware error\n"));
2785 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2786 srbStatus
= SRB_STATUS_ERROR
;
2789 case SCSI_SENSE_ILLEGAL_REQUEST
:
2791 KdPrint2((PRINT_PREFIX
2792 "ATAPI: Illegal request\n"));
2793 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2794 srbStatus
= SRB_STATUS_ERROR
;
2797 case SCSI_SENSE_UNIT_ATTENTION
:
2799 KdPrint2((PRINT_PREFIX
2800 "ATAPI: Unit attention\n"));
2801 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2802 srbStatus
= SRB_STATUS_ERROR
;
2805 case SCSI_SENSE_DATA_PROTECT
:
2807 KdPrint2((PRINT_PREFIX
2808 "ATAPI: Data protect\n"));
2809 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2810 srbStatus
= SRB_STATUS_ERROR
;
2813 case SCSI_SENSE_BLANK_CHECK
:
2815 KdPrint2((PRINT_PREFIX
2816 "ATAPI: Blank check\n"));
2817 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2818 srbStatus
= SRB_STATUS_ERROR
;
2821 case SCSI_SENSE_ABORTED_COMMAND
:
2822 KdPrint2((PRINT_PREFIX
2823 "Atapi: Command Aborted\n"));
2824 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2825 srbStatus
= SRB_STATUS_ERROR
;
2830 KdPrint2((PRINT_PREFIX
2831 "ATAPI: Invalid sense information\n"));
2833 srbStatus
= SRB_STATUS_ERROR
;
2841 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2842 chan
->ReturningMediaStatus
= errorByte
;
2844 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2845 KdPrint2((PRINT_PREFIX
2846 "IDE: Media change\n"));
2847 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2848 srbStatus
= SRB_STATUS_ERROR
;
2850 if (Srb
->SenseInfoBuffer
) {
2852 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2854 senseBuffer
->ErrorCode
= 0x70;
2855 senseBuffer
->Valid
= 1;
2856 senseBuffer
->AdditionalSenseLength
= 0xb;
2857 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2858 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2859 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2861 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2864 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2865 KdPrint2((PRINT_PREFIX
2866 "IDE: Command abort\n"));
2867 srbStatus
= SRB_STATUS_ABORTED
;
2868 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2870 if (Srb
->SenseInfoBuffer
) {
2872 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2874 senseBuffer
->ErrorCode
= 0x70;
2875 senseBuffer
->Valid
= 1;
2876 senseBuffer
->AdditionalSenseLength
= 0xb;
2877 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2878 senseBuffer
->AdditionalSenseCode
= 0;
2879 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2881 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2884 LunExt
->ErrorCount
++;
2886 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2888 KdPrint2((PRINT_PREFIX
2889 "IDE: End of media\n"));
2890 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2891 srbStatus
= SRB_STATUS_ERROR
;
2893 if (Srb
->SenseInfoBuffer
) {
2895 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2897 senseBuffer
->ErrorCode
= 0x70;
2898 senseBuffer
->Valid
= 1;
2899 senseBuffer
->AdditionalSenseLength
= 0xb;
2900 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2901 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2902 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2903 senseBuffer
->EndOfMedia
= 1;
2905 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2908 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2909 LunExt
->ErrorCount
++;
2912 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2914 KdPrint2((PRINT_PREFIX
2915 "IDE: Illegal length\n"));
2916 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2918 if (Srb
->SenseInfoBuffer
) {
2920 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2922 senseBuffer
->ErrorCode
= 0x70;
2923 senseBuffer
->Valid
= 1;
2924 senseBuffer
->AdditionalSenseLength
= 0xb;
2925 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2926 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2927 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2928 senseBuffer
->IncorrectLength
= 1;
2930 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2933 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2935 KdPrint2((PRINT_PREFIX
2936 "IDE: Bad block\n"));
2937 srbStatus
= SRB_STATUS_ERROR
;
2938 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2939 if (Srb
->SenseInfoBuffer
) {
2941 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2943 senseBuffer
->ErrorCode
= 0x70;
2944 senseBuffer
->Valid
= 1;
2945 senseBuffer
->AdditionalSenseLength
= 0xb;
2946 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2947 senseBuffer
->AdditionalSenseCode
= 0;
2948 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2950 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2953 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2955 KdPrint2((PRINT_PREFIX
2956 "IDE: Id not found\n"));
2957 srbStatus
= SRB_STATUS_ERROR
;
2958 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2960 if (Srb
->SenseInfoBuffer
) {
2962 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2964 senseBuffer
->ErrorCode
= 0x70;
2965 senseBuffer
->Valid
= 1;
2966 senseBuffer
->AdditionalSenseLength
= 0xb;
2967 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2968 senseBuffer
->AdditionalSenseCode
= 0;
2969 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2971 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2974 LunExt
->ErrorCount
++;
2976 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2978 KdPrint2((PRINT_PREFIX
2979 "IDE: Media change\n"));
2980 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2981 srbStatus
= SRB_STATUS_ERROR
;
2983 if (Srb
->SenseInfoBuffer
) {
2985 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2987 senseBuffer
->ErrorCode
= 0x70;
2988 senseBuffer
->Valid
= 1;
2989 senseBuffer
->AdditionalSenseLength
= 0xb;
2990 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2991 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2992 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2994 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2997 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2999 KdPrint2((PRINT_PREFIX
3000 "IDE: Data error\n"));
3001 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
3002 srbStatus
= SRB_STATUS_ERROR
;
3004 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
3005 LunExt
->ErrorCount
++;
3008 // Build sense buffer
3009 if (Srb
->SenseInfoBuffer
) {
3011 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
3013 senseBuffer
->ErrorCode
= 0x70;
3014 senseBuffer
->Valid
= 1;
3015 senseBuffer
->AdditionalSenseLength
= 0xb;
3016 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
3017 senseBuffer
->AdditionalSenseCode
= 0;
3018 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
3020 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3024 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
3025 // deviceExtension->DWordIO = FALSE;
3027 KdPrint2((PRINT_PREFIX
3028 "MapError: ErrorCount >= MAX_ERRORS\n"));
3030 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
3031 LunExt
->MaximumBlockXfer
= 0;
3034 KdPrint2((PRINT_PREFIX
3035 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
3038 KdPrint2((PRINT_PREFIX
3039 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
3048 ScsiPortLogError( HwDeviceExtension
,
3056 // Reprogram to not use Multi-sector.
3059 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
3060 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3062 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
3064 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3065 // command was aborted.
3066 if (statusByte
& IDE_STATUS_ERROR
) {
3068 // Read the error register.
3069 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3071 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3075 // Adjust the devExt. value, if necessary.
3076 LunExt
->MaximumBlockXfer
= 0;
3084 // Set SCSI status to indicate a check condition.
3085 Srb
->ScsiStatus
= scsiStatus
;
3094 Routine Description:
3097 HwDeviceExtension - HBA miniport driver's adapter data storage
3101 TRUE - if initialization successful.
3102 FALSE - if initialization unsuccessful.
3108 IN PVOID HwDeviceExtension
3111 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3112 ULONG numberChannels
= deviceExtension
->NumberChannels
;
3115 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
3117 if(WinVer_WDM_Model
) {
3118 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
3120 if(deviceExtension
->MasterDev
) {
3121 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
3122 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
3123 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
3126 /* do extra chipset specific setups */
3127 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
3129 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3130 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3131 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3134 for (c
= 0; c
< numberChannels
; c
++) {
3135 AtapiHwInitialize__(deviceExtension
, c
);
3137 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
3139 } // end AtapiHwInitialize()
3143 AtapiHwInitialize__(
3144 IN PHW_DEVICE_EXTENSION deviceExtension
,
3149 UCHAR statusByte
, errorByte
;
3150 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3151 PHW_LU_EXTENSION LunExt
;
3153 ULONG PreferedMode
= 0xffffffff;
3155 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3156 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
3160 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
3161 FindDevices(deviceExtension
, 0, lChannel
);
3163 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
3165 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
3167 LunExt
= chan
->lun
[i
];
3169 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
3173 AtapiDisableInterrupts(deviceExtension
, lChannel
);
3174 AtapiStallExecution(1);
3176 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3178 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
3179 // Enable media status notification
3180 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
3182 // If supported, setup Multi-block transfers.
3183 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3184 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3185 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
3187 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3188 // command was aborted.
3189 if (statusByte
& IDE_STATUS_ERROR
) {
3191 // Read the error register.
3192 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3194 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3198 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3199 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3200 0, 0, ATA_WAIT_BASE_READY
);
3202 if (statusByte
& IDE_STATUS_ERROR
) {
3203 // Read the error register.
3204 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3206 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3210 // Adjust the devExt. value, if necessary.
3211 LunExt
->MaximumBlockXfer
= 0;
3214 KdPrint2((PRINT_PREFIX
3215 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3217 LunExt
->MaximumBlockXfer
));
3220 if(LunExt
->IdentifyData
.MajorRevision
) {
3222 if(LunExt
->opt_ReadCacheEnable
) {
3223 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3224 // If supported, setup read/write cacheing
3225 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3226 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3227 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3229 // Check for errors.
3230 if (statusByte
& IDE_STATUS_ERROR
) {
3231 KdPrint2((PRINT_PREFIX
3232 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3234 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3236 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3239 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3240 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3241 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3242 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3243 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3245 if(LunExt
->IdentifyData
.FeaturesSupport
.WriteCache
) {
3246 if(LunExt
->opt_WriteCacheEnable
) {
3247 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3248 // If supported & allowed, setup write cacheing
3249 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3250 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3251 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3252 // Check for errors.
3253 if (statusByte
& IDE_STATUS_ERROR
) {
3254 KdPrint2((PRINT_PREFIX
3255 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3257 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3259 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3262 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3263 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3264 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3265 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3266 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3270 if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/
3271 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3273 if(LunExt
->opt_AdvPowerMode
) {
3274 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3276 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3277 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3278 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3279 // Check for errors.
3280 if (statusByte
& IDE_STATUS_ERROR
) {
3281 KdPrint2((PRINT_PREFIX
3282 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3286 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3287 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3288 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3289 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3292 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3293 if(LunExt
->opt_AcousticMode
) {
3294 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3295 // setup acoustic mgmt
3296 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3297 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3298 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3299 // Check for errors.
3300 if (statusByte
& IDE_STATUS_ERROR
) {
3301 KdPrint2((PRINT_PREFIX
3302 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3306 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3307 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3308 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3309 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3312 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3313 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3314 // setup standby timer
3315 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3316 IDE_COMMAND_IDLE
, 0, 0, 0,
3317 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3318 // Check for errors.
3319 if (statusByte
& IDE_STATUS_ERROR
) {
3320 KdPrint2((PRINT_PREFIX
3321 "AtapiHwInitialize: standby timer on Device %d failed\n",
3327 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3330 //BOOLEAN isSanyo = FALSE;
3333 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3335 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3336 for (j
= 0; j
< 26; j
+= 2) {
3338 // Build a buffer based on the identify data.
3339 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3342 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3344 // Inquiry string for older model had a '-', newer is '_'
3345 if (vendorId
[12] == 'C') {
3347 // Torisan changer. Set the bit. This will be used in several places
3348 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3349 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3350 LunExt
->DiscsPresent
= 3;
3356 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3357 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3358 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3359 PreferedMode
= chan
->MaxTransferMode
;
3362 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3363 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3364 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3367 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3368 LunExt
->LimitedTransferMode
=
3369 LunExt
->TransferMode
=
3372 AtapiDmaInit__(deviceExtension
, LunExt
);
3374 LunExt
->LimitedTransferMode
=
3375 LunExt
->TransferMode
;
3376 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3378 // We need to get our device ready for action before
3379 // returning from this function
3381 // According to the atapi spec 2.5 or 2.6, an atapi device
3382 // clears its status BSY bit when it is ready for atapi commands.
3383 // However, some devices (Panasonic SQ-TC500N) are still
3384 // not ready even when the status BSY is clear. They don't react
3385 // to atapi commands.
3387 // Since there is really no other indication that tells us
3388 // the drive is really ready for action. We are going to check BSY
3389 // is clear and then just wait for an arbitrary amount of time!
3391 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3394 // have to get out of the loop sometime!
3395 // 10000 * 100us = 1000,000us = 1000ms = 1s
3397 GetStatus(chan
, statusByte
);
3398 if(statusByte
== IDE_STATUS_WRONG
) {
3401 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3403 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3404 // Wait for Busy to drop.
3405 AtapiStallExecution(100);
3406 GetStatus(chan
, statusByte
);
3410 // 5000 * 100us = 500,000us = 500ms = 0.5s
3411 if(statusByte
!= IDE_STATUS_WRONG
) {
3414 AtapiStallExecution(100);
3415 } while (waitCount
--);
3418 GetBaseStatus(chan
, statusByte
);
3419 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3420 AtapiStallExecution(10);
3425 } // end AtapiHwInitialize__()
3432 AtapiHwInitializeChanger(
3433 IN PVOID HwDeviceExtension
,
3434 IN PSCSI_REQUEST_BLOCK Srb
,
3435 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3437 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3438 ULONG lChannel
= GET_CHANNEL(Srb
);
3439 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3440 ULONG DeviceNumber
= GET_CDEV(Srb
);
3441 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3443 if (MechanismStatus
) {
3444 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3445 if (LunExt
->DiscsPresent
> 1) {
3446 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3450 } // end AtapiHwInitializeChanger()
3455 Routine Description:
3456 This routine will parse the string for a match on the keyword, then
3457 calculate the value for the keyword and return it to the caller.
3460 String - The ASCII string to parse.
3461 KeyWord - The keyword for the value desired.
3464 Zero if value not found
3465 Value converted from ASCII to binary.
3470 AtapiParseArgumentString(
3478 ULONG stringLength
= 0;
3479 ULONG keyWordLength
= 0;
3489 // Calculate the string length and lower case all characters.
3495 // Calculate the keyword length.
3501 if (keyWordLength
> stringLength
) {
3503 // Can't possibly have a match.
3507 // Now setup and start the compare.
3512 // The input string may start with white space. Skip it.
3513 while (*cptr
== ' ' || *cptr
== '\t') {
3517 if (*cptr
== '\0') {
3523 while ((*cptr
== *kptr
) ||
3524 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3525 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3529 if (*cptr
== '\0') {
3535 if (*kptr
== '\0') {
3537 // May have a match backup and check for blank or equals.
3538 while (*cptr
== ' ' || *cptr
== '\t') {
3542 // Found a match. Make sure there is an equals.
3545 // Not a match so move to the next semicolon.
3547 if (*cptr
++ == ';') {
3548 goto ContinueSearch
;
3553 // Skip the equals sign.
3556 // Skip white space.
3557 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3561 if (*cptr
== '\0') {
3562 // Early end of string, return not found
3567 // This isn't it either.
3569 goto ContinueSearch
;
3573 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3574 // Value is in Hex. Skip the "0x"
3576 for (index
= 0; *(cptr
+ index
); index
++) {
3578 if (*(cptr
+ index
) == ' ' ||
3579 *(cptr
+ index
) == '\t' ||
3580 *(cptr
+ index
) == ';') {
3584 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3585 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3587 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3588 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3589 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3590 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3592 // Syntax error, return not found.
3599 // Value is in Decimal.
3600 for (index
= 0; *(cptr
+ index
); index
++) {
3602 if (*(cptr
+ index
) == ' ' ||
3603 *(cptr
+ index
) == '\t' ||
3604 *(cptr
+ index
) == ';') {
3608 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3609 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3612 // Syntax error return not found.
3621 // Not a match check for ';' to continue search.
3623 if (*cptr
++ == ';') {
3624 goto ContinueSearch
;
3630 } // end AtapiParseArgumentString()_
3638 IN PVOID HwDeviceExtension
,
3643 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3644 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3647 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3650 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3651 // If the last command was DSC restrictive, see if it's set. If so, the device is
3652 // ready for a new request. Otherwise, reset the timer and come back to here later.
3654 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3655 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3656 // we shall have no problem with interrupt handler.
3657 if (!srb
|| chan
->ExpectingInterrupt
) {
3658 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3659 chan
->DpcState
= DPC_STATE_TIMER
;
3660 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3661 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3662 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3664 goto ReturnCallback
;
3668 if (!IS_RDP((srb
->Cdb
[0]))) {
3669 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3673 goto ReturnEnableIntr
;
3675 GetStatus(chan
, statusByte
);
3676 if (statusByte
& IDE_STATUS_DSC
) {
3678 UCHAR PathId
= srb
->PathId
;
3679 UCHAR TargetId
= srb
->TargetId
;
3680 UCHAR Lun
= srb
->Lun
;
3682 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3683 AtapiDmaDBSync(chan
, srb
);
3684 UniataRemoveRequest(chan
, srb
);
3685 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3686 // Clear current SRB.
3687 if(!deviceExtension
->simplexOnly
) {
3688 srb
= UniataGetCurRequest(chan
);
3694 // Ask for next request.
3695 ScsiPortNotification(NextLuRequest
,
3700 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3703 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3707 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3710 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3714 goto ReturnCallback
;
3719 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3720 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3721 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3722 #ifdef UNIATA_USE_XXableInterrupts
3723 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3724 // must be called on DISPATCH_LEVEL
3725 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3726 AtapiEnableInterrupts__
);
3728 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3729 InterlockedExchange(&(chan
->CheckIntr
),
3731 // Will raise IRQL to DIRQL
3732 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3733 AtapiEnableInterrupts__
,
3735 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3736 #endif // UNIATA_USE_XXableInterrupts
3738 //ASSERT(!deviceExtension->simplexOnly);
3743 // Check other channel
3744 // In simplex mode no interrupts must appear on other channels
3745 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3746 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3752 chan
= &(deviceExtension
->chan
[c
]);
3754 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3755 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3756 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3758 //ASSERT(!deviceExtension->simplexOnly);
3759 chan
->DpcState
= DPC_STATE_ISR
;
3760 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3761 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3765 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3768 } // end AtapiCallBack__()
3773 IN PVOID HwDeviceExtension
3776 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3777 } // end AtapiCallBack_X()
3779 #endif //UNIATA_CORE
3783 Routine Description:
3785 This is the interrupt service routine for ATAPI IDE miniport driver.
3789 HwDeviceExtension - HBA miniport driver's adapter data storage
3793 TRUE if expecting an interrupt.
3799 IN PVOID HwDeviceExtension
3802 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3804 BOOLEAN status
= FALSE
;
3808 //BOOLEAN checked[AHCI_MAX_PORT];
3812 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3813 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3815 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3816 // AHCI may generate state change notification, never skip this check
3817 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3818 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3822 // assume all non-interrupted ports to be already checked
3824 // assume all not implemented ports to be already checked
3825 checked
|= ~deviceExtension
->AHCI_PI
;
3827 checked
= 0; // assume all ports are not checked
3830 if(!deviceExtension
->ExpectingInterrupt
) {
3831 // if we do not expect interrupt, exit now,
3832 // but keep in mind that it can be unexpected one
3833 // Note: this is just a hint, not exact counter
3834 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3835 //deviceExtension->ExpectingInterrupt++;
3838 // clear this flag now, it can be set again in sub-calls
3839 deviceExtension
->ExpectingInterrupt
=0;
3842 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3843 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3847 for(pass
=0; pass
<2; pass
++) {
3848 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3849 if(status
&& pass
) {
3850 // we catched some expected interrupts now.
3851 // do not touch unexpected until next ISR call
3854 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3856 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3858 if((checked
>>c
) & 0x01)
3861 // check non-empty and expecting interrupt channels first
3862 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3865 checked
|= (ULONG
)1 << c
;
3867 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3869 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3870 // we get here on idle channels or when ISR is posted to DPC
3871 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3874 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3876 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3877 // c_state = deviceExtension->chan[c].CheckIntr;
3878 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3879 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3882 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3883 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3884 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3885 if(c_state
== CHECK_INTR_IDLE
) {
3886 // c_state = deviceExtension->chan[c].CheckIntr;
3887 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3888 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3891 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3892 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3893 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3895 } while(c_state
== CHECK_INTR_CHECK
);
3896 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3897 // check if already serviced
3898 if(c_state
== CHECK_INTR_ACTIVE
) {
3899 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3903 if((c_state
== CHECK_INTR_DETECTED
) ||
3904 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3906 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3907 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3908 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3913 // disable interrupts on other channel of legacy mode
3914 // ISA-bridged onboard controller
3915 if(deviceExtension
->simplexOnly
/*||
3916 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3917 AtapiDisableInterrupts(deviceExtension
, !c
);
3920 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3921 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3922 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3923 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3926 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3927 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3930 // re-enable interrupts on other channel
3931 if(deviceExtension
->simplexOnly
/*||
3932 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3933 AtapiEnableInterrupts(deviceExtension
, !c
);
3937 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3938 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3943 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3945 deviceExtension
->FirstChannelToCheck
++;
3946 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3947 deviceExtension
->FirstChannelToCheck
= 0;
3950 } // end AtapiInterrupt()
3958 IN PKINTERRUPT Interrupt
,
3959 IN PVOID Isr2HwDeviceExtension
3962 // This ISR is intended to catch interrupts when we are already in other ISR instance
3963 // for the same device. This may happen when we have multiple channels,
3964 // especially on SMP machines
3966 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3967 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3969 BOOLEAN status
= FALSE
;
3975 // we should never get here for ISA/MCA
3976 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3977 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3981 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3982 // AHCI may generate state change notification, never skip this check
3983 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3984 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3988 // assume all non-interrupted ports to be already checked
3990 // assume all not implemented ports to be already checked
3991 checked
|= ~deviceExtension
->AHCI_PI
;
3994 checked
= 0; // assume all ports are not checked
3996 if(!deviceExtension
->ExpectingInterrupt
) {
3997 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3998 deviceExtension
->ExpectingInterrupt
++;
4001 //deviceExtension->ExpectingInterrupt = 0;
4003 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4004 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
4006 if((checked
>>c
) & 0x01)
4009 checked
|= (ULONG
)1 << c
;
4011 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
4012 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
4016 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4017 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
4018 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
4020 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
4021 // hunt on unexpected intr (Some devices generate double interrupts,
4022 // some controllers (at least CMD649) interrupt twice with small delay.
4023 // If interrupts are disabled, they queue interrupt and re-issue it later,
4024 // when we do not expect it.
4029 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
4031 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
4032 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
4033 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
4034 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4039 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
4041 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4044 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
4045 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
4046 // there is an active ISR/DPC for one channel, but
4047 // we have an interrupt from another one
4048 // Lets inform current ISR/DPC about new interrupt
4049 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
4053 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
4056 } // end AtapiInterrupt2()
4058 RETTYPE_XXableInterrupts
4061 IN PVOID HwDeviceExtension
4064 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4067 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4068 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
4070 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
4072 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4073 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4074 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
4080 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
4083 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4084 AtapiDisableInterrupts(deviceExtension, lChannel);
4087 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
4088 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4089 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4092 return RETVAL_XXableInterrupts
;
4093 } // end AtapiInterruptDpc()
4096 RETTYPE_XXableInterrupts
4098 AtapiEnableInterrupts__(
4099 IN PVOID HwDeviceExtension
4102 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4103 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
4105 PHW_CHANNEL chan
= NULL
;
4107 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4108 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
4109 chan
= &(deviceExtension
->chan
[c
]);
4111 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
4112 // enable intrs on requested channel
4113 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
4114 AtapiEnableInterrupts(HwDeviceExtension
, c
);
4115 InterlockedExchange(&(chan
->CheckIntr
),
4118 // check if current or other channel(s) interrupted
4119 //AtapiInterrupt(HwDeviceExtension);
4121 if(deviceExtension
->simplexOnly
) {
4125 // check if other channel(s) interrupted
4126 // must do nothing in simplex mode
4127 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
4128 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4129 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
4132 //ASSERT(!deviceExtension->simplexOnly);
4133 chan
->DpcState
= DPC_STATE_ISR
;
4134 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4135 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
4139 // In simplex mode next command must be sent to device here
4140 if(deviceExtension
->simplexOnly
&& chan
) {
4141 PSCSI_REQUEST_BLOCK srb
;
4142 chan
= UniataGetNextChannel(chan
);
4144 srb
= UniataGetCurRequest(chan
);
4149 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
4153 return RETVAL_XXableInterrupts
;
4155 } // end AtapiEnableInterrupts__()
4157 #endif //UNIATA_CORE
4162 AtapiEnableInterrupts(
4163 IN PVOID HwDeviceExtension
,
4167 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4171 if(c
>= deviceExtension
->NumberChannels
) {
4172 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
4175 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
4176 !UniataAhciChanImplemented(deviceExtension
, c
)) {
4177 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
4181 chan
= &(deviceExtension
->chan
[c
]);
4182 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4183 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
4184 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4185 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
4186 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
4187 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
4188 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
4189 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
4191 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
4192 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
4195 //SelectDrive(chan, 0);
4196 //GetBaseStatus(chan, statusByte);
4197 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4198 0 | IDE_DC_A_4BIT
);
4199 //if(chan->NumberLuns) {
4200 // SelectDrive(chan, 1);
4201 // GetBaseStatus(chan, statusByte);
4202 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4204 // SelectDrive(chan, chan->cur_cdev);
4207 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4209 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4210 // keep interrupts disabled
4211 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4213 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4214 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4218 } // end AtapiEnableInterrupts()
4222 AtapiDisableInterrupts(
4223 IN PVOID HwDeviceExtension
,
4227 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4229 if(c
>= deviceExtension
->NumberChannels
) {
4230 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4233 chan
= &(deviceExtension
->chan
[c
]);
4234 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4235 // mark channel as busy
4236 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4237 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4238 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4240 //SelectDrive(chan, 0);
4241 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4242 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4243 //if(chan->NumberLuns) {
4244 // SelectDrive(chan, 1);
4245 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4246 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4247 // SelectDrive(chan, chan->cur_cdev);
4250 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4254 } // end AtapiDisableInterrupts()
4257 UniataExpectChannelInterrupt(
4258 IN
struct _HW_CHANNEL
* chan
,
4259 IN BOOLEAN Expecting
4262 chan
->ExpectingInterrupt
= Expecting
;
4264 chan
->DeviceExtension
->ExpectingInterrupt
++;
4266 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4267 chan
->DeviceExtension
->ExpectingInterrupt
--;
4270 } // end UniataExpectChannelInterrupt()
4273 Check hardware for interrupt state
4277 AtapiCheckInterrupt__(
4278 IN PVOID HwDeviceExtension
,
4279 IN UCHAR c
// logical channel
4282 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4283 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4284 PHW_LU_EXTENSION LunExt
;
4286 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4287 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4290 ULONG pr_status
= 0;
4291 UCHAR dma_status
= 0;
4294 UCHAR statusByte
= 0;
4295 ULONG slotNumber
= deviceExtension
->slotNumber
;
4296 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4297 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4300 BOOLEAN DmaTransfer
= FALSE
;
4301 BOOLEAN OurInterrupt
= FALSE
;
4302 BOOLEAN StatusValid
= FALSE
;
4304 UCHAR interruptReason
;
4305 BOOLEAN EarlyIntr
= FALSE
;
4306 BOOLEAN SingleBlockIntr
= FALSE
;
4308 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4311 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4312 LunExt
= chan
->lun
[chan
->cur_cdev
];
4314 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4315 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4317 if((ChipFlags
& UNIATA_AHCI
) &&
4318 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4320 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4321 return OurInterrupt
;
4324 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4325 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4326 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4327 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4328 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4329 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4330 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4331 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4332 OurInterrupt
= INTERRUPT_REASON_OUR
;
4334 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4335 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4336 OurInterrupt
= INTERRUPT_REASON_OUR
;
4338 if(statusByte
& IDE_STATUS_ERROR
) {
4339 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4340 OurInterrupt
= INTERRUPT_REASON_OUR
;
4342 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4343 OurInterrupt
= INTERRUPT_REASON_OUR
;
4346 return OurInterrupt
;
4349 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4351 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4352 deviceExtension
->Channel
+ c
, c
));
4354 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4355 deviceExtension
->Channel
+ c
, c
));
4356 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4357 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4360 // do controller-specific interrupt servicing staff
4361 if(deviceExtension
->UnknownDev
) {
4362 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4367 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4368 // Such behavior was observed with Intel ICH-xxx chips
4369 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4373 case ATA_PROMISE_ID
: {
4377 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4381 ((Channel
) ? 0x00004000 : 0x00000400))) {
4382 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4383 return INTERRUPT_REASON_IGNORE
;
4387 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4388 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4391 if(!(status
& 0x20)) {
4392 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4393 return INTERRUPT_REASON_IGNORE
;
4397 ULONG stat_reg
= (ChipFlags
& PRG2
) ? 0x60 : 0x6c;
4398 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40);
4399 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40, status
);
4401 if(status
& (1 << (Channel
+1))) {
4404 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4405 return INTERRUPT_REASON_IGNORE
;
4408 if(!(ChipFlags
& UNIATA_SATA
))
4411 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
);
4412 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
, (pr_status
& (0x11 << Channel
)));
4413 if(pr_status
& (0x11 << Channel
)) {
4414 // TODO: reset channel
4415 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4416 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4418 if(!(status
& (0x01 << Channel
))) {
4420 KdPrint2((PRINT_PREFIX
" Promise mio unexpected attach\n"));
4421 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4423 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4424 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4426 return INTERRUPT_REASON_IGNORE
;
4429 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4433 case ATA_NVIDIA_ID
: {
4434 if(!(ChipFlags
& UNIATA_SATA
))
4437 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4439 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4440 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
4442 /* get and clear interrupt status */
4443 if(ChipFlags
& NVQ
) {
4444 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4445 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4447 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4448 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4450 KdPrint2((PRINT_PREFIX
" pr_status %x, shift %x\n", pr_status
, shift
));
4452 /* check for and handle connect events */
4453 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4454 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4456 /* check for and handle disconnect events */
4457 if((pr_status
& (0x08UL
<< shift
)) &&
4458 !((pr_status
& (0x04UL
<< shift
) &&
4459 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4460 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4462 /* do we have any device action ? */
4463 if(!(pr_status
& (0x01UL
<< shift
))) {
4464 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4465 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4466 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4468 return INTERRUPT_REASON_IGNORE
;
4474 KdPrint2((PRINT_PREFIX
"ATI\n"));
4475 if(ChipType
== SIIMIO
) {
4480 case ATA_SILICON_IMAGE_ID
:
4482 if(ChipType
== SIIMIO
) {
4484 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4485 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4486 if(reg32
== 0xffffffff) {
4487 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4488 return INTERRUPT_REASON_IGNORE
;
4490 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
))) {
4491 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4492 return INTERRUPT_REASON_IGNORE
;
4495 if(ChipFlags
& UNIATA_SATA
) {
4496 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4498 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4499 * controllers continue to assert IRQ as long as
4500 * SError bits are pending. Clear SError immediately.
4502 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4503 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4510 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4511 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4512 return OurInterrupt
;
4514 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4515 goto skip_dma_stat_check
;
4518 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4520 GetPciConfig1(0x71, reg8
);
4521 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4523 (Channel
? 0x08 : 0x04))) {
4524 return INTERRUPT_REASON_IGNORE
;
4527 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4528 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4530 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4537 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4538 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4539 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4540 return INTERRUPT_REASON_IGNORE
;
4542 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4543 AtapiStallExecution(1);
4544 AtapiWritePort1(chan
, IDX_BM_Command
,
4545 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4546 goto skip_dma_stat_check
;
4548 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4549 if(ChipFlags
& UNIATA_AHCI
) {
4552 if(ChipFlags
& UNIATA_SATA
) {
4553 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4554 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4556 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4557 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4558 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4565 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4566 if(ChipFlags
& UNIATA_AHCI
) {
4569 if(ChipFlags
& UNIATA_SATA
) {
4570 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4571 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4577 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4579 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4580 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4581 if(dma_status
& BM_STATUS_ERR
) {
4582 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4583 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4585 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4586 GetStatus(chan
, statusByte
);
4588 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4589 if(statusByte
& IDE_STATUS_ERROR
) {
4590 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4591 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4593 if ((statusByte
& IDE_STATUS_DSC
) &&
4594 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4595 (dma_status
== BM_STATUS_ACTIVE
)) {
4596 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4597 // some devices interrupts on each block transfer even in DMA mode
4598 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4599 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4600 ///* clear interrupt and get status */
4601 //GetBaseStatus(chan, statusByte);
4602 //return INTERRUPT_REASON_IGNORE;
4603 SingleBlockIntr
= TRUE
;
4606 return INTERRUPT_REASON_IGNORE
;
4611 if(dma_status
& BM_STATUS_INTR
) {
4612 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4613 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4614 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4616 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4619 skip_dma_stat_check
:
4620 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4621 AtapiStallExecution(1);
4624 /* if drive is busy it didn't interrupt */
4625 /* the exception is DCS + BSY state of ATAPI devices */
4627 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4628 GetStatus(chan
, statusByte
);
4630 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4631 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4633 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4635 if (statusByte
== IDE_STATUS_WRONG
) {
4636 // interrupt from empty controller ?
4638 if (statusByte
& IDE_STATUS_BUSY
) {
4639 if(!chan
->ExpectingInterrupt
) {
4640 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4641 return OurInterrupt
;
4644 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4645 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4647 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4648 return INTERRUPT_REASON_IGNORE
;
4650 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4651 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4652 return INTERRUPT_REASON_IGNORE
;
4654 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4655 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4656 return INTERRUPT_REASON_IGNORE
;
4661 if(dma_status
& BM_STATUS_INTR
) {
4662 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4663 /* clear interrupt and get status */
4664 GetBaseStatus(chan
, statusByte
);
4665 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4666 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4668 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4669 return INTERRUPT_REASON_OUR
;
4672 if(g_WaitBusyInISR
) {
4673 GetStatus(chan
, statusByte
);
4674 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4675 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4676 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4677 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4678 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4680 if (statusByte
& IDE_STATUS_BUSY
) {
4681 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4682 return INTERRUPT_REASON_IGNORE
;
4688 /* clear interrupt and get status */
4689 GetBaseStatus(chan
, statusByte
);
4690 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4691 if (statusByte
== IDE_STATUS_WRONG
) {
4692 // interrupt from empty controller ?
4694 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4695 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4696 return OurInterrupt
;
4699 #ifndef UNIATA_PIO_ONLY
4701 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4702 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4704 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4705 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4709 if(SingleBlockIntr
) {
4710 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4712 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4715 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4721 if (!(chan
->ExpectingInterrupt
)) {
4723 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4725 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4726 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4728 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4729 return OurInterrupt
;
4731 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4732 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4733 return OurInterrupt
;
4735 //ASSERT(!chan->queue_depth || chan->cur_req);
4737 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4738 return INTERRUPT_REASON_OUR
;
4740 } // end AtapiCheckInterrupt__()
4746 IN PVOID HwDeviceExtension
,
4750 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4751 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4753 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4754 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4756 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4757 ULONG status
= SRB_STATUS_SUCCESS
;
4758 UCHAR dma_status
= 0;
4761 UCHAR statusByte
= 0,interruptReason
;
4763 BOOLEAN atapiDev
= FALSE
;
4770 BOOLEAN DmaTransfer
= FALSE
;
4772 ULONG TimerValue
= 1000;
4773 ULONG TotalTimerValue
= 0;
4774 #ifdef UNIATA_USE_XXableInterrupts
4775 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4777 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4778 #endif // UNIATA_USE_XXableInterrupts
4779 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4780 // BOOLEAN RestoreUseDpc = FALSE;
4781 BOOLEAN DataOverrun
= FALSE
;
4782 BOOLEAN NoStartIo
= TRUE
;
4783 BOOLEAN NoRetry
= FALSE
;
4785 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4787 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4788 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4794 UCHAR OldReqState
= REQ_STATE_NONE
;
4796 PHW_LU_EXTENSION LunExt
;
4801 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4803 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4806 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4807 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4808 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4810 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4814 PathId
= srb
->PathId
;
4815 TargetId
= srb
->TargetId
;
4821 goto enqueue_next_req
;
4824 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4825 DeviceNumber
= (UCHAR
)(TargetId
);
4826 LunExt
= chan
->lun
[DeviceNumber
];
4827 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4828 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4830 // check if we are in ISR DPC
4832 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4833 goto ServiceInterrupt
;
4837 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4840 if (!(chan
->ExpectingInterrupt
)) {
4842 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4846 // change request state
4848 OldReqState
= AtaReq
->ReqState
;
4849 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4850 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4853 // We don't want using DPC for fast operations, like
4854 // DMA completion, sending CDB, short ATAPI transfers, etc.
4856 // We MUST use DPC, because of interprocessor synchronization
4857 // on multiprocessor platforms
4860 goto ServiceInterrupt
;
4862 switch(OldReqState
) {
4863 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4864 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4865 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4866 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4867 case REQ_STATE_DPC_WAIT_BUSY0
:
4868 case REQ_STATE_DPC_WAIT_BUSY1
:
4869 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4870 goto ServiceInterrupt
;
4871 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4872 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4876 if(!DmaTransfer
&& !atapiDev
) {
4877 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4884 goto ServiceInterrupt
;
4886 #ifdef UNIATA_USE_XXableInterrupts
4888 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4890 // shall never get here
4895 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4897 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4898 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4900 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4903 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4904 goto ServiceInterrupt
;
4905 #endif // UNIATA_USE_XXableInterrupts
4910 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4911 // We always get here when are called from timer callback, which is invoked on DRQL.
4912 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4914 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4915 // disable interrupts for this channel,
4916 // but avoid recursion and double-disable
4917 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4918 UniataExpectChannelInterrupt(chan
, FALSE
);
4919 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4922 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4924 #ifdef UNIATA_USE_XXableInterrupts
4925 // Will lower IRQL to DISPATCH_LEVEL
4926 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4927 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4928 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4930 // Will raise IRQL to DIRQL
4931 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4934 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4935 #endif // UNIATA_USE_XXableInterrupts
4940 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4942 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4943 // we must block interrupts from this channel
4944 // If device generate new interrupt before we get to DPC,
4945 // ISR will assume, that it is NOT our interrupt
4946 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4947 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4949 // Will raise IRQL to DIRQL
4950 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4954 #endif //UNIATA_CORE
4958 if(AtaReq
&& InDpc
) {
4959 switch(AtaReq
->ReqState
) {
4960 case REQ_STATE_DPC_WAIT_DRQ0
:
4962 case REQ_STATE_DPC_WAIT_BUSY
:
4964 case REQ_STATE_DPC_WAIT_DRQ
:
4966 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4968 case REQ_STATE_DPC_WAIT_BUSY0
:
4969 case REQ_STATE_DPC_WAIT_BUSY1
:
4970 // continue normal execution
4976 #endif //UNIATA_CORE
4978 // make additional delay for old devices (if we are not in DPC)
4979 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4983 !(deviceExtension->HwFlags & UNIATA_SATA)
4985 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4986 AtapiStallExecution(10);
4990 /* clear interrupt and get status */
4991 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4992 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4993 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4995 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4996 KdPrint3((PRINT_PREFIX
"Err intr (%#x), SE (%#x)\n",
4997 chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
),
4998 chan
->AhciLastSError
));
4999 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
5000 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
5001 // We have some other error except Overflow
5002 // Just signal ERROR, operation will be aborted in ERROR branch.
5003 statusByte
|= IDE_STATUS_ERROR
;
5004 AtaReq
->ahci
.in_serror
= chan
->AhciLastSError
;
5005 if(chan
->AhciLastSError
& (ATA_SE_HANDSHAKE_ERR
| ATA_SE_LINKSEQ_ERR
| ATA_SE_TRANSPORT_ERR
| ATA_SE_UNKNOWN_FIS
)) {
5006 KdPrint2((PRINT_PREFIX
"Unrecoverable\n"));
5010 // We have only Overflow. Abort operation and continue
5012 UniataDumpAhciPortRegs(chan
);
5014 if(!UniataAhciAbortOperation(chan
)) {
5015 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5018 UniataDumpAhciPortRegs(chan
);
5020 UniataAhciWaitCommandReady(chan
, 10);
5025 GetBaseStatus(chan
, statusByte
);
5028 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
5030 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
5034 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
5040 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5041 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
5043 if (statusByte
& IDE_STATUS_BUSY
) {
5044 if (deviceExtension
->DriverMustPoll
) {
5045 // Crashdump is polling and we got caught with busy asserted.
5046 // Just go away, and we will be polled again shortly.
5047 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
5048 goto ReturnEnableIntr
;
5051 // Ensure BUSY is non-asserted.
5052 // make a very small idle before falling to DPC
5053 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
5055 for (i
= 0; i
< k
; i
++) {
5057 GetBaseStatus(chan
, statusByte
);
5058 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5061 AtapiStallExecution(10);
5064 if (!InDpc
&& UseDpc
&& i
== 2) {
5066 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
5069 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5074 AtapiStallExecution(TimerValue
);
5075 goto ServiceInterrupt
;
5076 #endif //UNIATA_CORE
5078 if (InDpc
&& i
== k
) {
5079 // reset the controller.
5080 KdPrint2((PRINT_PREFIX
5081 " Resetting due to BUSY on entry - %#x.\n",
5083 goto IntrPrepareResetController
;
5088 if(!LunExt
->IdentifyData
.MajorRevision
&&
5091 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
5093 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
5094 //AtapiStallExecution(10);
5096 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5097 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
5099 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5100 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5103 if (statusByte
& IDE_STATUS_BUSY
) {
5104 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
5107 // This is just workaround
5108 // We should DISABLE interrupts before entering WAIT state
5109 UniataExpectChannelInterrupt(chan, TRUE);
5110 #endif //UNIATA_CORE
5112 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
5114 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
5115 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
5116 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
5117 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5120 #endif //UNIATA_CORE
5123 GetBaseStatus(chan
, statusByte
);
5124 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5125 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
5126 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
5127 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5128 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
5131 TotalTimerValue
+= TimerValue
;
5133 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
5135 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
5137 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5139 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
5141 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
5145 if(!LunExt
->AtapiReadyWaitDelay
) {
5146 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5150 #endif //UNIATA_CORE
5153 AtapiStallExecution(TimerValue
);
5156 if(!LunExt
->AtapiReadyWaitDelay
) {
5157 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5158 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
5160 if (statusByte
& IDE_STATUS_BUSY
) {
5161 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
5167 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5168 switch(OldReqState
) {
5169 case REQ_STATE_EARLY_INTR
:
5170 case REQ_STATE_DPC_WAIT_BUSY0
:
5172 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
5173 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
5174 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5181 // Check for error conditions.
5182 if ((statusByte
& IDE_STATUS_ERROR
) ||
5183 (dma_status
& BM_STATUS_ERR
)) {
5185 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5186 error
= AtaReq
->ahci
.in_error
;
5189 UniataDumpAhciPortRegs(chan
);
5191 if(!UniataAhciAbortOperation(chan
)) {
5192 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5194 // clear interrupts again
5195 UniataAhciWaitCommandReady(chan
, 10);
5197 UniataDumpAhciPortRegs(chan
);
5199 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
5201 AtaReq
->retry
+= MAX_RETRIES
;
5202 if(!error
&& (statusByte
& IDE_STATUS_ERROR
)) {
5203 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: force error status\n"));
5204 error
|= IDE_STATUS_ERROR
;
5208 UniataDumpAhciPortRegs(chan
);
5211 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5213 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
5215 if(error & IDE_STATUS_CORRECTED_ERROR) {
5216 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5217 statusByte &= ~IDE_STATUS_ERROR;
5222 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
5224 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
5227 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5228 KdPrint2((PRINT_PREFIX
" no wait ready after error\n"));
5231 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
5232 AtapiStallExecution(100);
5234 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
5235 AtapiStallExecution(10);
5239 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
5240 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
5242 for (k
= atapiDev
? 0 : 200; k
; k
--) {
5243 GetBaseStatus(chan
, statusByte
);
5244 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5245 AtapiStallExecution(50);
5252 /* if this is a UDMA CRC error, reinject request */
5255 if(AtaReq
->retry
< MAX_RETRIES
) {
5256 #ifdef IO_STATISTICS
5257 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5258 #endif //IO_STATISTICS
5260 (error & IDE_ERROR_ICRC)*/) {
5261 KdPrint2((PRINT_PREFIX
"Errors in DMA mode\n"));
5262 if(AtaReq
->retry
< MAX_RETRIES
) {
5264 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5265 //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5266 // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
5267 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5269 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5273 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5276 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5280 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5281 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5283 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
5284 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5287 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
5288 UniataSataClearErr(HwDeviceExtension
, lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 0);
5292 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5293 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5294 if(AtaReq
->retry
< MAX_RETRIES
) {
5296 // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
5297 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5298 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5299 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5300 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5304 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5307 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5311 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5312 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5313 // Fail this request.
5314 status
= SRB_STATUS_ERROR
;
5315 goto CompleteRequest
;
5317 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5320 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5321 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5322 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5324 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5325 #ifdef IO_STATISTICS
5326 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5327 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5329 LunExt
->RecoverCount
[AtaReq
->retry
],
5330 LunExt
->BlockIoCount
5332 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5333 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= LunExt
->BlockIoCount
/3 ||
5334 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5337 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5338 #endif //IO_STATISTICS
5339 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5340 LunExt
->LimitedTransferMode
=
5341 LunExt
->TransferMode
;
5344 #ifdef IO_STATISTICS
5345 if(AtaReq
->bcount
) {
5346 // we need stats for Read/Write operations
5347 LunExt
->BlockIoCount
++;
5350 #endif //IO_STATISTICS
5354 // check reason for this interrupt.
5357 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5360 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5361 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5363 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5365 wordsThisInterrupt
= DEV_BSIZE
/2;
5373 // simulate DRQ for DMA transfers
5374 statusByte
|= IDE_STATUS_DRQ
;
5376 if (statusByte
& IDE_STATUS_DRQ
) {
5379 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5381 if (LunExt
->MaximumBlockXfer
) {
5382 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5385 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5387 interruptReason
= ATAPI_IR_IO_toHost
;
5389 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5390 interruptReason
= ATAPI_IR_IO_toDev
;
5393 status
= SRB_STATUS_ERROR
;
5394 goto CompleteRequest
;
5397 } else if (statusByte
& IDE_STATUS_BUSY
) {
5399 //AtapiEnableInterrupts(deviceExtension, lChannel);
5400 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5405 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq
->WordsLeft
));
5406 if (AtaReq
->WordsLeft
) {
5408 // Funky behaviour seen with PCI IDE (not all, just one).
5410 // The ISR hits with DRQ low, but comes up later.
5411 for (k
= 0; k
< 5000; k
++) {
5412 GetBaseStatus(chan
, statusByte
);
5413 if (statusByte
& IDE_STATUS_DRQ
) {
5418 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5420 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5424 AtapiStallExecution(TimerValue
);
5425 goto ServiceInterrupt
;
5426 #endif //UNIATA_CORE
5428 AtapiStallExecution(100);
5431 // reset the controller.
5432 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5434 IntrPrepareResetController
:
5435 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5436 goto ReturnEnableIntr
;
5439 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5443 // Command complete - verify, write, or the SMART enable/disable.
5444 // Also get_media_status
5445 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5450 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5451 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5452 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5453 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5454 //status = SRB_STATUS_DATA_OVERRUN;
5457 status = SRB_STATUS_SUCCESS;
5459 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5460 AtaReq
->WordsLeft
= 0;
5462 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5464 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5465 // status = SRB_STATUS_DATA_OVERRUN;
5467 status
= SRB_STATUS_SUCCESS
;
5468 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5469 goto CompleteRequest
;
5471 if (interruptReason
== ATAPI_IR_COD_Cmd
&& (statusByte
& IDE_STATUS_DRQ
)) {
5472 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5473 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, srb
);
5475 // Write the packet.
5476 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5477 // Send CDB to device.
5478 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5479 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5481 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5483 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5484 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5485 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5488 goto ReturnEnableIntr
;
5490 } else if (interruptReason
== ATAPI_IR_IO_toDev
&& (statusByte
& IDE_STATUS_DRQ
)) {
5495 // Pick up bytes to transfer and convert to words.
5497 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5500 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5502 // Covert bytes to words.
5504 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5506 if (wordCount
!= AtaReq
->WordsLeft
) {
5507 KdPrint2((PRINT_PREFIX
5508 "AtapiInterrupt: %d words requested; %d words xferred\n",
5513 // Verify this makes sense.
5514 if (wordCount
> AtaReq
->WordsLeft
) {
5515 wordCount
= AtaReq
->WordsLeft
;
5516 KdPrint2((PRINT_PREFIX
5517 "AtapiInterrupt: Write underrun\n"));
5523 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5524 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5525 // Transfer only words requested.
5526 wordCount
= AtaReq
->WordsLeft
;
5528 // Transfer next block.
5529 wordCount
= wordsThisInterrupt
;
5534 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5535 //ASSERT(AtaReq->WordsLeft == wordCount);
5536 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5537 KdPrint2((PRINT_PREFIX
5538 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5539 if(AtaReq
->WordsLeft
> wordCount
) {
5540 AtaReq
->WordsLeft
-= wordCount
;
5541 AtaReq
->WordsTransfered
+= wordCount
;
5542 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5543 goto ReturnEnableIntr
;
5545 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5547 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5548 AtaReq
->WordsLeft
= 0;
5549 status
= SRB_STATUS_SUCCESS
;
5550 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5551 goto CompleteRequest
;
5554 // Ensure that this is a write command.
5555 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5557 KdPrint2((PRINT_PREFIX
5558 "AtapiInterrupt: Write interrupt\n"));
5560 statusByte
= WaitOnBusy(chan
);
5562 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/
5563 || (wordCount
& 1)) {
5568 UniataGetPioTiming(LunExt
));
5572 (PULONG
)(AtaReq
->DataBuffer
),
5574 UniataGetPioTiming(LunExt
));
5578 KdPrint3((PRINT_PREFIX
5579 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5583 if(!wordCount
&& atapiDev
&&
5584 !(statusByte
& (IDE_STATUS_ERROR
| IDE_STATUS_BUSY
)) &&
5585 (statusByte
& IDE_STATUS_DRQ
)) {
5586 // this can be late Packet interrupt after packet sending
5587 KdPrint2((PRINT_PREFIX
" unreliable wordCount ?\n"));
5589 wordCount
= AtapiSuckPortBuffer2(chan
,
5592 KdPrint2((PRINT_PREFIX
" transferred %#x\n", wordCount
));
5593 GetBaseStatus(chan
, statusByte
);
5594 KdPrint2((PRINT_PREFIX
" status %#x, statusByte\n"));
5596 interruptReason
= ATAPI_IR_IO_toHost
;
5598 UniataDumpATARegs(chan
);
5601 if(wordCount
&& AtaReq
->WordsLeft
) {
5602 goto continue_atapi_pio_read
;
5605 // Fail this request.
5606 status
= SRB_STATUS_ERROR
;
5607 if(!wordCount
&& atapiDev
&& (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
)) {
5608 // some devices feel bad after incorrect commands and may need reset
5609 KdPrint2((PRINT_PREFIX
5610 "AtapiInterrupt: Try ATAPI reset\n"));
5612 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5613 AtapiSoftReset(chan
, DeviceNumber
);
5614 AtapiEnableInterrupts(deviceExtension
, lChannel
);
5615 status
= SRB_STATUS_BUS_RESET
;
5616 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5618 // goto IntrPrepareResetController;
5620 goto CompleteRequest
;
5622 // Advance data buffer pointer and bytes left.
5623 AtaReq
->DataBuffer
+= wordCount
;
5624 AtaReq
->WordsLeft
-= wordCount
;
5625 AtaReq
->WordsTransfered
+= wordCount
;
5628 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5631 goto ReturnEnableIntr
;
5633 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5638 // Pick up bytes to transfer and convert to words.
5640 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5641 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5643 // Convert bytes to words.
5645 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5647 if (wordCount
!= AtaReq
->WordsLeft
) {
5648 KdPrint2((PRINT_PREFIX
5649 "AtapiInterrupt: %d words requested; %d words xferred\n",
5654 // Verify this makes sense.
5655 if (wordCount
> AtaReq
->WordsLeft
) {
5656 wordCount
= AtaReq
->WordsLeft
;
5662 // Check if words left is at least 256.
5663 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5664 // Transfer only words requested.
5665 wordCount
= AtaReq
->WordsLeft
;
5667 // Transfer next block.
5668 wordCount
= wordsThisInterrupt
;
5673 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5674 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5675 KdPrint2((PRINT_PREFIX
5676 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5677 if(AtaReq
->WordsLeft
> wordCount
) {
5678 AtaReq
->WordsLeft
-= wordCount
;
5679 AtaReq
->WordsTransfered
+= wordCount
;
5680 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5681 goto ReturnEnableIntr
;
5683 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5685 //ASSERT(AtaReq->WordsLeft == wordCount);
5686 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5687 AtaReq
->WordsLeft
= 0;
5688 status
= SRB_STATUS_SUCCESS
;
5689 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5690 goto CompleteRequest
;
5693 // Ensure that this is a read command.
5694 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5697 "AtapiInterrupt: Read interrupt\n"));*/
5699 statusByte
= WaitOnBusy(chan
);
5701 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/
5702 || (wordCount
& 1)) {
5703 KdPrint2((PRINT_PREFIX
5704 "IdeIntr: Read %#x words\n", wordCount
));
5709 UniataGetPioTiming(LunExt
));
5710 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5711 //KdDump(AtaReq->DataBuffer, wordCount*2);
5712 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5713 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5716 GetBaseStatus(chan
, statusByte
);
5717 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5720 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5721 AtapiSuckPort2(chan
);
5722 GetBaseStatus(chan
, statusByte
);
5725 if(statusByte
& IDE_STATUS_BUSY
) {
5726 for (i
= 0; i
< 2; i
++) {
5727 AtapiStallExecution(10);
5728 GetBaseStatus(chan
, statusByte
);
5729 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5735 KdPrint2((PRINT_PREFIX
5736 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5739 (PULONG
)(AtaReq
->DataBuffer
),
5741 UniataGetPioTiming(LunExt
));
5745 KdPrint3((PRINT_PREFIX
5746 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5750 // Fail this request.
5751 status
= SRB_STATUS_ERROR
;
5752 goto CompleteRequest
;
5754 continue_atapi_pio_read
:
5755 // Advance data buffer pointer and bytes left.
5756 AtaReq
->DataBuffer
+= wordCount
;
5757 AtaReq
->WordsLeft
-= wordCount
;
5758 AtaReq
->WordsTransfered
+= wordCount
;
5760 // Check for read command complete.
5761 if (AtaReq
->WordsLeft
== 0) {
5763 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5766 // Work around to make many atapi devices return correct sector size
5767 // of 2048. Also certain devices will have sector count == 0x00, check
5769 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5770 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5772 AtaReq
->DataBuffer
-= wordCount
;
5773 if (AtaReq
->DataBuffer
[0] == 0x00) {
5775 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5779 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5780 AtaReq
->DataBuffer
+= wordCount
;
5783 GetStatus(chan
, statusByte
);
5784 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5785 // Assume command is completed if BUSY is cleared
5786 // and all data read
5787 // Optionally, we may receive COMPLETE interrupt later and
5788 // treat it as unexpected
5789 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5791 status
= SRB_STATUS_SUCCESS
;
5792 goto CompleteRequest
;
5798 // Completion for IDE drives.
5799 if (AtaReq->WordsLeft) {
5800 status = SRB_STATUS_DATA_OVERRUN;
5802 status = SRB_STATUS_SUCCESS;
5805 goto CompleteRequest;
5807 status
= SRB_STATUS_SUCCESS
;
5808 goto CompleteRequest
;
5813 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5814 GetStatus(chan
, statusByte
);
5815 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5816 // Assume command is completed if BUSY is cleared
5817 // even if NOT all data read
5818 // Optionally, we may receive COMPLETE interrupt later and
5819 // treat it as unexpected
5820 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5822 status
= SRB_STATUS_SUCCESS
;
5823 goto CompleteRequest
;
5826 if(!atapiDev
&& !DataOverrun
&& (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) &&
5827 (statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_DRQ
))) {
5828 KdPrint2((PRINT_PREFIX
" HDD read data ready \n"));
5829 goto continue_read_drq
;
5834 goto ReturnEnableIntr
;
5836 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
5838 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5839 // Command complete. We exactly know this because of IReason.
5842 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5843 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
5844 AtaReq
->WordsLeft
= 0;
5846 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
5848 wordCount
= AtaReq
->WordsLeft
;
5849 // Advance data buffer pointer and bytes left.
5850 AtaReq
->DataBuffer
+= wordCount
;
5851 AtaReq
->WordsLeft
-= wordCount
;
5852 AtaReq
->WordsTransfered
+= wordCount
;
5854 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount
, AtaReq
->WordsTransfered
));
5857 //if (AtaReq->WordsLeft) {
5858 // status = SRB_STATUS_DATA_OVERRUN;
5860 status
= SRB_STATUS_SUCCESS
;
5863 #ifdef UNIATA_DUMP_ATAPI
5865 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5869 PCHAR ModeSelectData
;
5871 PSCSI_REQUEST_BLOCK Srb
= srb
;
5873 Cdb
= (PCDB
)(Srb
->Cdb
);
5874 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5875 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5876 CdbDataLen
= Srb
->DataTransferLength
;
5878 if(CdbDataLen
> 0x1000) {
5879 CdbDataLen
= 0x1000;
5883 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5884 KdPrint2(("P:T:D=%d:%d:%d\n",
5888 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5891 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5892 KdPrint(("ModeSense 6\n"));
5893 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5894 ModeSelectData
= CdbData
+4;
5895 KdDump(CdbData
, CdbDataLen
);
5897 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5898 KdPrint(("ModeSense 10\n"));
5899 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5900 ModeSelectData
= CdbData
+8;
5901 KdDump(CdbData
, CdbDataLen
);
5903 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5904 KdPrint(("Read buffer from device:\n"));
5905 KdDump(CdbData
, CdbDataLen
);
5910 #endif //UNIATA_DUMP_ATAPI
5914 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5915 // Check and see if we are processing our secret (mechanism status/request sense) srb
5917 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5918 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5919 status
= SRB_STATUS_DATA_OVERRUN
;
5922 if (AtaReq
->OriginalSrb
) {
5926 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5927 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5929 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5930 if (status
== SRB_STATUS_SUCCESS
) {
5932 AtapiHwInitializeChanger (HwDeviceExtension
,
5934 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5936 // Get ready to issue the original srb
5937 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5938 AtaReq
->OriginalSrb
= NULL
;
5941 // failed! Get the sense key and maybe try again
5942 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5944 AtaReq
->OriginalSrb
);
5947 // do not enable interrupts in DPC, do not waste time, do it now!
5948 if(UseDpc && chan->DisableIntr) {
5949 AtapiEnableInterrupts(HwDeviceExtension, c);
5951 RestoreUseDpc = TRUE;
5954 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5956 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5958 if (srbStatus
== SRB_STATUS_PENDING
) {
5959 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5960 goto ReturnEnableIntr
;
5964 // restore state on error
5966 AtapiDisableInterrupts(HwDeviceExtension, c);
5970 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5972 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5974 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5975 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5976 // Check to see if we at least get mininum number of bytes
5977 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5978 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5979 status
= SRB_STATUS_SUCCESS
;
5983 if (status
== SRB_STATUS_SUCCESS
) {
5985 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5986 chan
->MechStatusRetryCount
) {
5988 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5989 // The sense key doesn't say the last request is illegal, so try again
5990 chan
->MechStatusRetryCount
--;
5991 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5993 AtaReq
->OriginalSrb
);
5996 // last request was illegal. No point trying again.
5997 // Do-nothing call ?
5998 AtapiHwInitializeChanger (HwDeviceExtension
,
6000 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6002 // Get ready to issue the original srb
6003 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6004 AtaReq
->OriginalSrb
= NULL
;
6006 #endif //UNIATA_CORE
6008 // do not enable interrupts in DPC, do not waste time, do it now!
6009 if(UseDpc && chan->DisableIntr) {
6010 AtapiEnableInterrupts(HwDeviceExtension, c);
6012 RestoreUseDpc = TRUE;
6015 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
6017 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
6019 if (srbStatus
== SRB_STATUS_PENDING
) {
6020 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
6021 goto ReturnEnableIntr
;
6025 // restore state on error
6027 AtapiDisableInterrupts(HwDeviceExtension, c);
6033 // If we get here, it means AtapiSendCommand() has failed
6034 // Can't recover. Pretend the original srb has failed and complete it.
6036 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
6038 if (AtaReq
->OriginalSrb
) {
6039 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
6040 // Do-nothing call ?
6041 AtapiHwInitializeChanger (HwDeviceExtension
,
6043 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6044 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6045 AtaReq
->OriginalSrb
= NULL
;
6048 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
6050 // fake an error and read no data
6051 status
= SRB_STATUS_ERROR
;
6052 srb
->ScsiStatus
= 0;
6053 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
6054 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
6057 } else if (status
== SRB_STATUS_ERROR
) {
6059 // Map error to specific SRB status and handle request sense.
6060 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
6061 status
= MapError(deviceExtension
,
6066 } else if(!DmaTransfer
) {
6068 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
6069 // Command complete.
6071 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
6072 // Wait for busy to drop.
6073 for (i
= 0; i
< 5*30; i
++) {
6074 GetBaseStatus(chan
, statusByte
);
6075 if (!(statusByte
& IDE_STATUS_BUSY
)) {
6080 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
6082 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
6086 AtapiStallExecution(TimerValue
);
6087 goto ServiceInterrupt
;
6088 #endif //UNIATA_CORE
6090 AtapiStallExecution(100);
6095 // reset the controller.
6096 KdPrint2((PRINT_PREFIX
6097 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
6099 goto IntrPrepareResetController
;
6101 // Check to see if DRQ is still up.
6102 if(statusByte
& IDE_STATUS_DRQ
) {
6103 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
6105 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6106 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
6108 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
6111 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
6114 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
6116 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
6118 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
6119 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
6120 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
6124 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
6125 //if ((statusByte & IDE_STATUS_DRQ)) {}
6126 if((statusByte
& IDE_STATUS_DRQ
) &&
6127 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
6130 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
6131 for (i
= 0; i
< 200; i
++) {
6132 GetBaseStatus(chan
, statusByte
);
6133 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6138 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
6139 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
6144 AtapiStallExecution(TimerValue
);
6145 goto ServiceInterrupt
;
6146 #endif //UNIATA_CORE
6148 AtapiStallExecution(100);
6152 // reset the controller.
6153 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
6155 goto IntrPrepareResetController
;
6159 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
6160 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
6161 //KdDump(srb->DataBuffer, srb->DataTransferLength);
6163 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
6164 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
6168 // Clear interrupt expecting flag.
6169 UniataExpectChannelInterrupt(chan
, FALSE
);
6170 // clear this flag now, it can be set again in sub-calls
6171 InterlockedExchange(&(chan
->CheckIntr
),
6174 // Sanity check that there is a current request.
6176 // Set status in SRB.
6177 srb
->SrbStatus
= (UCHAR
)status
;
6179 // Check for underflow.
6180 if(AtaReq
->WordsLeft
) {
6182 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
6183 // Subtract out residual words and update if filemark hit,
6184 // setmark hit , end of data, end of media...
6185 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
6186 if (status
== SRB_STATUS_DATA_OVERRUN
) {
6187 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6189 srb
->DataTransferLength
= 0;
6192 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6195 if(status
== SRB_STATUS_SUCCESS
) {
6196 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
6197 // // This should be set in UniataAhciEndTransaction() for AHCI
6198 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
6201 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
6202 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
6203 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6204 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6205 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
6208 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
6209 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6213 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
6216 // Indicate command complete.
6218 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
6221 if (status
== SRB_STATUS_SUCCESS
&&
6222 srb
->SenseInfoBuffer
&&
6223 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
6225 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
6227 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
6228 senseBuffer
->ErrorCode
= 0;
6229 senseBuffer
->Valid
= 1;
6230 senseBuffer
->AdditionalSenseLength
= 0xb;
6231 senseBuffer
->SenseKey
= 0;
6232 senseBuffer
->AdditionalSenseCode
= 0;
6233 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6235 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
6237 AtapiDmaDBSync(chan
, srb
);
6238 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
6239 UniataRemoveRequest(chan
, srb
);
6240 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
6241 ScsiPortNotification(RequestComplete
,
6247 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
6249 if (status
!= SRB_STATUS_SUCCESS
) {
6250 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6251 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
6254 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6256 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6257 // Build the SMART status block depending upon the completion status.
6258 cmdOutParameters
->cBufferSize
= wordCount
;
6259 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
6260 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
6262 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6264 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
6265 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
6268 UniataSnapAtaRegs(chan
, 0, regs
);
6270 regs
->bCommandReg
= SMART_CMD
;
6271 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
6273 cmdOutParameters
->cBufferSize
= 8;
6275 chan
->SmartCommand
= 0; // cleanup after execution
6277 // Indicate command complete.
6278 goto IntrCompleteReq
;
6283 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
6288 for (i
= 0; i
< 5; i
++) {
6289 GetBaseStatus(chan
, statusByte
);
6290 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6291 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
6295 if (statusByte
& IDE_STATUS_DSC
) {
6296 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
6300 AtapiStallExecution(50);
6303 // RDP can be cleared since previous check
6305 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6311 AtapiStallExecution(TimerValue
);
6312 goto ServiceInterrupt
;
6313 #endif //UNIATA_CORE
6316 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6319 srb
= UniataGetCurRequest(chan
);
6324 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6326 ScsiPortNotification(NextRequest
,
6330 ScsiPortNotification(NextLuRequest
,
6335 // in simplex mode next command must NOT be sent here
6336 if(!deviceExtension
->simplexOnly
) {
6337 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6340 // Try to get SRB fron any non-empty queue (later)
6341 if(deviceExtension
->simplexOnly
) {
6344 #endif //UNIATA_CORE
6346 goto ReturnEnableIntr
;
6350 // Unexpected int. Catch it
6351 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6355 if(g_opt_VirtualMachine
== VM_QEMU
) {
6356 if(interruptReason
== ATAPI_IR_IO_toDev
&& !(statusByte
& IDE_STATUS_DRQ
) && !DmaTransfer
) {
6357 statusByte
= WaitForDrq(chan
);
6358 if(statusByte
& IDE_STATUS_DRQ
) {
6364 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6365 AtaReq
->WordsLeft
== 0) {
6366 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6367 status
= SRB_STATUS_SUCCESS
;
6368 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6369 goto CompleteRequest
;
6375 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6376 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6377 deviceExtension
->ExpectingInterrupt
= TRUE
;
6379 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6380 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6381 #ifdef UNIATA_USE_XXableInterrupts
6382 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6383 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6384 // must be called on DISPATCH_LEVEL
6385 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6386 AtapiEnableInterrupts__
);
6388 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6389 InterlockedExchange(&(chan
->CheckIntr
),
6391 // Will raise IRQL to DIRQL
6393 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6394 AtapiEnableInterrupts__
,
6396 #endif // UNIATA_CORE
6397 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6398 #endif // UNIATA_USE_XXableInterrupts
6402 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6403 // in simplex mode next command must be sent here if
6405 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6408 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6409 chan
= UniataGetNextChannel(chan
);
6411 srb
= UniataGetCurRequest(chan
);
6415 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6417 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6420 #endif //UNIATA_CORE
6423 } // end AtapiInterrupt__()
6429 Routine Description:
6431 This routine handles SMART enable, disable, read attributes and threshold commands.
6435 HwDeviceExtension - HBA miniport driver's adapter data storage
6436 Srb - IO request packet
6445 IdeSendSmartCommand(
6446 IN PVOID HwDeviceExtension
,
6447 IN PSCSI_REQUEST_BLOCK Srb
,
6448 IN ULONG targetId
// assume it is always valid
6451 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6452 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6453 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6454 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6455 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6456 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6457 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6462 if (regs
->bCommandReg
!= SMART_CMD
) {
6463 KdPrint2((PRINT_PREFIX
6464 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6465 return SRB_STATUS_INVALID_REQUEST
;
6468 c
= targetId
/ deviceExtension
->NumberLuns
;
6469 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6470 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6472 chan
= &(deviceExtension
->chan
[c
]);
6474 chan
->SmartCommand
= regs
->bFeaturesReg
;
6476 // Determine which of the commands to carry out.
6477 switch(regs
->bFeaturesReg
) {
6478 case READ_ATTRIBUTES
:
6479 case READ_THRESHOLDS
:
6480 case READ_LOG_SECTOR
:
6481 case WRITE_LOG_SECTOR
:
6483 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6484 KdPrint2((PRINT_PREFIX
6485 "IdeSendSmartCommand: wrong buffer size\n"));
6486 return SRB_STATUS_DATA_OVERRUN
;
6489 statusByte
= WaitOnBusy(chan
);
6491 if (statusByte
& IDE_STATUS_BUSY
) {
6492 KdPrint2((PRINT_PREFIX
6493 "IdeSendSmartCommand: Returning BUSY status\n"));
6494 return SRB_STATUS_BUSY
;
6497 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6498 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6500 // Set data buffer pointer and words left.
6501 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6502 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6504 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6506 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6508 regs
->bSectorNumberReg
,
6509 regs
->bSectorCountReg
,
6513 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6514 // Wait for interrupt.
6515 return SRB_STATUS_PENDING
;
6517 return SRB_STATUS_ERROR
;
6521 case RETURN_SMART_STATUS
:
6522 case ENABLE_DISABLE_AUTOSAVE
:
6523 case EXECUTE_OFFLINE_DIAGS
:
6524 case SAVE_ATTRIBUTE_VALUES
:
6527 statusByte
= WaitOnBusy(chan
);
6529 if (statusByte
& IDE_STATUS_BUSY
) {
6530 KdPrint2((PRINT_PREFIX
6531 "IdeSendSmartCommand: Returning BUSY status\n"));
6532 return SRB_STATUS_BUSY
;
6535 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6536 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6538 // Set data buffer pointer and indicate no data transfer.
6539 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6540 AtaReq
->WordsLeft
= 0;
6542 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6544 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6546 regs
->bSectorNumberReg
,
6547 regs
->bSectorCountReg
,
6551 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6552 // Wait for interrupt.
6553 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6554 return SRB_STATUS_PENDING
;
6556 return SRB_STATUS_ERROR
;
6557 } // end switch(regs->bFeaturesReg)
6559 return SRB_STATUS_INVALID_REQUEST
;
6561 } // end IdeSendSmartCommand()
6563 #endif //UNIATA_CORE
6567 UniAtaCalculateLBARegs(
6568 PHW_LU_EXTENSION LunExt
,
6569 ULONGLONG startingSector
,
6573 UCHAR drvSelect
,sectorNumber
;
6577 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6578 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6579 if(LunExt
->DeviceExtension
) {
6580 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6583 return startingSector
;
6585 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6586 LunExt
->IdentifyData
.NumberOfHeads
;
6588 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6592 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6594 cylinder
= (USHORT
)(startingSector
/ tmp
);
6595 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6596 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6597 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6598 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6599 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6603 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6604 } // end UniAtaCalculateLBARegs()
6608 UniAtaCalculateLBARegsBack(
6609 PHW_LU_EXTENSION LunExt
,
6613 ULONG drvSelect
,sectorNumber
;
6617 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6620 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6621 LunExt
->IdentifyData
.NumberOfHeads
;
6623 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6624 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6625 sectorNumber
= (UCHAR
)(lba
& 0xff);
6627 lba
= sectorNumber
-1 +
6628 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6632 } // end UniAtaCalculateLBARegsBack()
6637 Routine Description:
6639 This routine handles IDE read and writes.
6643 HwDeviceExtension - HBA miniport driver's adapter data storage
6644 Srb - IO request packet
6654 IN PVOID HwDeviceExtension
,
6655 IN PSCSI_REQUEST_BLOCK Srb
,
6659 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6660 UCHAR lChannel
= GET_CHANNEL(Srb
);
6661 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6662 PHW_LU_EXTENSION LunExt
;
6663 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6664 //ULONG ldev = GET_LDEV(Srb);
6665 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6666 ULONGLONG startingSector
=0;
6668 ULONG wordCount
= 0;
6669 UCHAR statusByte
,statusByte2
;
6672 BOOLEAN use_dma
= FALSE
;
6675 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6676 LunExt
= chan
->lun
[DeviceNumber
];
6678 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6679 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6681 if(LunExt
->opt_ReadOnly
&&
6682 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6683 if(LunExt
->opt_ReadOnly
== 1) {
6684 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6685 return SRB_STATUS_ERROR
;
6687 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6688 return SRB_STATUS_SUCCESS
;
6692 // Set data buffer pointer and words left.
6693 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6695 if(AtaReq
->WordsTransfered
) {
6696 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6697 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6698 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6699 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6701 AtaReq
->TransferLength
/2,
6702 AtaReq
->WordsTransfered
,
6705 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6706 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6707 // Set up 1st block.
6708 switch(Srb
->Cdb
[0]) {
6711 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6712 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6715 case SCSIOP_WRITE12
:
6716 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6717 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6720 case SCSIOP_WRITE16
:
6721 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6722 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6725 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6727 AtaReq
->TransferLength
/2,
6730 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6733 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6735 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6736 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6738 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6744 if(LunExt
->errRetry
&&
6745 lba
== LunExt
->errLastLba
&&
6746 AtaReq
->bcount
== LunExt
->errBCount
) {
6747 KdPrint3((PRINT_PREFIX
"IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n",
6748 LunExt
->errRetry
, LunExt
->errLastLba
, LunExt
->errBCount
));
6749 if(AtaReq
->retry
< MAX_RETRIES
) {
6750 AtaReq
->retry
= LunExt
->errRetry
;
6751 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
6755 // assume best case here
6756 // we cannot reinit Dma until previous request is completed
6757 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6758 UniataAhciSetupCmdPtr(AtaReq
);
6759 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6760 (PUCHAR
)(AtaReq
->DataBuffer
),
6761 AtaReq
->bcount
* DEV_BSIZE
)) {
6762 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6763 return SRB_STATUS_ERROR
;
6766 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6768 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6769 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6770 (PUCHAR
)(AtaReq
->DataBuffer
),
6771 AtaReq
->bcount
* DEV_BSIZE
)) {
6776 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6777 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6778 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6780 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6781 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6782 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6784 (USHORT
)(AtaReq
->bcount
),
6786 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6790 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6791 return SRB_STATUS_ERROR
;
6794 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6795 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6798 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6800 } else { // exec_only
6801 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6804 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6808 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6810 return SRB_STATUS_PENDING
;
6813 // if this is queued request, reinit DMA and check
6814 // if DMA mode is still available
6815 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6816 if (/*EnableDma &&*/
6817 (LunExt
->TransferMode
>= ATA_DMA
)) {
6820 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6824 // Check if write request.
6825 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6827 // Prepare read command.
6829 cmd
= IDE_COMMAND_READ_DMA
;
6831 if(LunExt
->MaximumBlockXfer
) {
6832 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6834 cmd
= IDE_COMMAND_READ
;
6838 // Prepare write command.
6840 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6841 cmd
= IDE_COMMAND_WRITE_DMA
;
6843 if (LunExt
->MaximumBlockXfer
) {
6844 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6846 if (AtaReq
->WordsLeft
< wordCount
) {
6847 // Transfer only words requested.
6848 wordCount
= AtaReq
->WordsLeft
;
6850 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6853 wordCount
= DEV_BSIZE
/2;
6854 cmd
= IDE_COMMAND_WRITE
;
6859 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6860 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6862 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6864 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6867 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6868 // AHCI doesn't distinguish DMA and PIO
6869 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6870 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6871 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6872 InterlockedExchange(&(chan
->CheckIntr
),
6874 return SRB_STATUS_PENDING
;
6877 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6880 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
6882 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6884 (USHORT
)(AtaReq
->bcount
),
6885 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6887 /* if(statusByte2 != IDE_STATUS_WRONG) {
6888 GetStatus(chan, statusByte2);
6890 if(statusByte2
& IDE_STATUS_ERROR
) {
6891 // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks).
6892 // Because some devices doesn't reset ERR from previous command immediately after getting new one.
6893 // On the other hand we cannot wait here because of possible timeout condition
6894 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6895 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6896 return SRB_STATUS_ERROR
;
6899 //GetStatus(chan, statusByte2);
6900 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6902 return SRB_STATUS_PENDING
;
6905 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6907 (USHORT
)(AtaReq
->bcount
),
6908 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6911 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6912 statusByte
== IDE_STATUS_WRONG
) {
6914 if(statusByte
== IDE_STATUS_WRONG
) {
6915 KdPrint2((PRINT_PREFIX
6916 "IdeReadWrite: error sending command (%#x)\n",
6919 KdPrint2((PRINT_PREFIX
6920 "IdeReadWrite: DRQ never asserted (%#x)\n",
6924 AtaReq
->WordsLeft
= 0;
6926 // Clear interrupt expecting flag.
6927 UniataExpectChannelInterrupt(chan
, FALSE
);
6928 InterlockedExchange(&(chan
->CheckIntr
),
6931 // Clear current SRB.
6932 UniataRemoveRequest(chan
, Srb
);
6934 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6937 UniataExpectChannelInterrupt(chan
, TRUE
);
6938 InterlockedExchange(&(chan
->CheckIntr
),
6941 // Write next DEV_BSIZE/2*N words.
6942 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) || (wordCount
& 1)) {
6943 KdPrint2((PRINT_PREFIX
6944 "IdeReadWrite: Write %#x words\n", wordCount
));
6949 UniataGetPioTiming(LunExt
));
6953 KdPrint2((PRINT_PREFIX
6954 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6957 (PULONG
)(AtaReq
->DataBuffer
),
6959 UniataGetPioTiming(LunExt
));
6962 // Adjust buffer address and words left count.
6963 AtaReq
->WordsLeft
-= wordCount
;
6964 AtaReq
->DataBuffer
+= wordCount
;
6965 AtaReq
->WordsTransfered
+= wordCount
;
6967 // Wait for interrupt.
6968 return SRB_STATUS_PENDING
;
6970 } // end IdeReadWrite()
6976 Routine Description:
6977 This routine handles IDE Verify.
6980 HwDeviceExtension - HBA miniport driver's adapter data storage
6981 Srb - IO request packet
6990 IN PVOID HwDeviceExtension
,
6991 IN PSCSI_REQUEST_BLOCK Srb
6994 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6995 UCHAR lChannel
= GET_CHANNEL(Srb
);
6996 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6997 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6998 PHW_LU_EXTENSION LunExt
;
6999 //ULONG ldev = GET_LDEV(Srb);
7000 ULONG DeviceNumber
= GET_CDEV(Srb
);
7002 ULONGLONG startingSector
=0;
7005 ULONGLONG endSector
;
7006 ULONG sectorCount
=0;
7009 LunExt
= chan
->lun
[DeviceNumber
];
7010 // Drive has these number sectors.
7011 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
7012 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
7013 LunExt
->IdentifyData
.NumberOfHeads
*
7014 LunExt
->IdentifyData
.NumberOfCylinders
;
7017 KdPrint2((PRINT_PREFIX
7018 "IdeVerify: Total sectors %#x\n",
7021 // Get starting sector number from CDB.
7022 switch(Srb
->Cdb
[0]) {
7024 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7025 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7027 case SCSIOP_VERIFY12
:
7028 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
7029 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7031 case SCSIOP_VERIFY16
:
7032 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7033 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7037 KdPrint2((PRINT_PREFIX
7038 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
7042 endSector
= startingSector
+ sectorCount
;
7044 KdPrint2((PRINT_PREFIX
7045 "IdeVerify: Ending sector %#I64x\n",
7048 if (endSector
> sectors
) {
7050 // Too big, round down.
7051 KdPrint2((PRINT_PREFIX
7052 "IdeVerify: Truncating request to %#x blocks\n",
7053 sectors
- startingSector
- 1));
7055 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
7059 // Set up sector count register. Round up to next block.
7060 if (sectorCount
> 0xFF) {
7061 sectorCount
= (USHORT
)0xFF;
7065 // Set data buffer pointer and words left.
7066 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7067 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7069 // Indicate expecting an interrupt.
7070 InterlockedExchange(&(chan
->CheckIntr
),
7073 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
7075 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
7076 IDE_COMMAND_VERIFY
, lba
,
7077 (USHORT
)sectorCount
,
7080 if(!(statusByte
& IDE_STATUS_ERROR
)) {
7081 // Wait for interrupt.
7082 return SRB_STATUS_PENDING
;
7084 return SRB_STATUS_ERROR
;
7086 } // end IdeVerify()
7088 #endif //UNIATA_CORE
7092 Routine Description:
7093 Send ATAPI packet command to device.
7096 HwDeviceExtension - HBA miniport driver's adapter data storage
7097 Srb - IO request packet
7105 IN PVOID HwDeviceExtension
,
7106 IN PSCSI_REQUEST_BLOCK Srb
,
7110 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7111 UCHAR lChannel
= GET_CHANNEL(Srb
);
7112 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
7113 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7114 PHW_LU_EXTENSION LunExt
;
7115 //ULONG ldev = GET_LDEV(Srb);
7116 ULONG DeviceNumber
= GET_CDEV(Srb
);
7118 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
7119 BOOLEAN use_dma
= FALSE
;
7120 BOOLEAN dma_reinited
= FALSE
;
7121 BOOLEAN retried
= FALSE
;
7125 LunExt
= chan
->lun
[DeviceNumber
];
7127 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
7128 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7129 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7132 #ifdef UNIATA_DUMP_ATAPI
7133 if(CmdAction
& CMD_ACTION_PREPARE
) {
7137 PCHAR ModeSelectData
;
7140 Cdb
= (PCDB
)(Srb
->Cdb
);
7141 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
7142 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
7143 CdbDataLen
= Srb
->DataTransferLength
;
7145 if(CdbDataLen
> 0x1000) {
7146 CdbDataLen
= 0x1000;
7150 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7151 KdPrint2(("P:T:D=%d:%d:%d\n",
7155 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
7158 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
7159 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
7160 Cdb
->WRITE_CD
.LBA
[0],
7161 Cdb
->WRITE_CD
.LBA
[1],
7162 Cdb
->WRITE_CD
.LBA
[2],
7163 Cdb
->WRITE_CD
.LBA
[3]
7166 if(ScsiCommand
== SCSIOP_WRITE12
) {
7167 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
7168 Cdb
->CDB12READWRITE
.LBA
[0],
7169 Cdb
->CDB12READWRITE
.LBA
[1],
7170 Cdb
->CDB12READWRITE
.LBA
[2],
7171 Cdb
->CDB12READWRITE
.LBA
[3]
7174 if(ScsiCommand
== SCSIOP_WRITE16
) {
7175 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
7176 Cdb
->CDB16READWRITE
.LBA
[0],
7177 Cdb
->CDB16READWRITE
.LBA
[1],
7178 Cdb
->CDB16READWRITE
.LBA
[2],
7179 Cdb
->CDB16READWRITE
.LBA
[3],
7180 Cdb
->CDB16READWRITE
.LBA
[4],
7181 Cdb
->CDB16READWRITE
.LBA
[5],
7182 Cdb
->CDB16READWRITE
.LBA
[6],
7183 Cdb
->CDB16READWRITE
.LBA
[7]
7186 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
7187 KdPrint(("ModeSelect 6\n"));
7188 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7189 ModeSelectData
= CdbData
+4;
7190 KdDump(CdbData
, CdbDataLen
);
7192 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
7193 KdPrint(("ModeSelect 10\n"));
7194 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7195 ModeSelectData
= CdbData
+8;
7196 KdDump(CdbData
, CdbDataLen
);
7198 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7199 KdPrint(("Send buffer to device:\n"));
7200 KdDump(CdbData
, CdbDataLen
);
7205 #endif //UNIATA_DUMP_ATAPI
7208 if(CmdAction
== CMD_ACTION_PREPARE
) {
7209 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
7211 switch (Srb
->Cdb
[0]) {
7212 case SCSIOP_RECEIVE
:
7217 case SCSIOP_WRITE12
:
7219 case SCSIOP_WRITE16
:
7222 case SCSIOP_READ_CD
:
7223 case SCSIOP_READ_CD_MSF
:
7224 if(deviceExtension
->opt_AtapiDmaRawRead
) {
7230 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
7231 return SRB_STATUS_BUSY
;
7234 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7235 !AtaReq
->OriginalSrb
) {
7236 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
7237 return SRB_STATUS_BUSY
;
7242 // We need to know how many platters our atapi cd-rom device might have.
7243 // Before anyone tries to send a srb to our target for the first time,
7244 // we must "secretly" send down a separate mechanism status srb in order to
7245 // initialize our device extension changer data. That's how we know how
7246 // many platters our target has.
7248 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7249 !AtaReq
->OriginalSrb
) {
7253 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
7254 // Set this flag now. If the device hangs on the mech. status
7255 // command, we will not have the chance to set it.
7256 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
7258 chan
->MechStatusRetryCount
= 3;
7259 AtaReq
->OriginalSrb
= Srb
;
7260 AtaReq
->Srb
= BuildMechanismStatusSrb (
7264 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
7265 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7266 if (srbStatus
== SRB_STATUS_PENDING
) {
7267 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
7271 // failed! Get the sense key and maybe try again
7272 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
7273 AtaReq
->OriginalSrb
);
7275 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7277 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
7279 if (srbStatus
== SRB_STATUS_PENDING
) {
7280 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7284 // failed again ? should not get here
7286 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
7287 AtaReq
->OriginalSrb
= NULL
;
7289 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
7290 // Do-nothing call ?
7291 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
7292 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
7296 #endif //UNIATA_CORE
7298 if((CmdAction
& CMD_ACTION_PREPARE
) &&
7299 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
7301 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
7303 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
7304 (Srb
->CdbLength
> 12)) {
7305 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
7306 return SRB_STATUS_INVALID_REQUEST
;
7309 // Set data buffer pointer and words left.
7310 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7311 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7312 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
7313 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7314 // reset this to force PRD init. May be already setup by recursive SRB
7315 AtaReq
->dma_entries
= 0;
7317 // check if reorderable
7318 switch(Srb
->Cdb
[0]) {
7320 case SCSIOP_WRITE16
:
7322 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7323 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7327 case SCSIOP_WRITE12
:
7329 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7335 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7337 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7339 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
7340 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7341 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7342 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7343 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7344 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7347 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7348 if(!AtaReq
->TransferLength
) {
7349 KdPrint((" assume 0-transfer\n"));
7351 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7352 KdPrint((" assume OUT\n"));
7353 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7355 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7356 KdPrint((" assume IN\n"));
7357 AtaReq
->Flags
|= REQ_FLAG_READ
;
7362 // check if DMA read/write
7363 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7364 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7368 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7369 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7373 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7374 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7376 if(AtaReq
->TransferLength
) {
7378 switch(Srb
->Cdb
[0]) {
7380 case SCSIOP_WRITE12
:
7381 case SCSIOP_WRITE16
:
7383 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7386 case SCSIOP_RECEIVE
:
7391 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7393 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7394 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7397 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7398 (PUCHAR
)(AtaReq
->DataBuffer
),
7399 Srb
->DataTransferLength
7400 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7402 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7407 case SCSIOP_READ_CD
:
7408 case SCSIOP_READ_CD_MSF
:
7409 if(deviceExtension
->opt_AtapiDmaRawRead
)
7410 goto call_dma_setup
;
7414 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7415 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7420 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7421 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7433 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7434 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7437 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7438 (PUCHAR
)(AtaReq
->DataBuffer
),
7439 Srb
->DataTransferLength
)) {
7440 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7443 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7447 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7451 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7453 UniataAhciSetupCmdPtr(AtaReq
);
7455 if(!Srb
->DataTransferLength
) {
7456 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7459 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7460 (PUCHAR
)(AtaReq
->DataBuffer
),
7461 Srb
->DataTransferLength
)) {
7462 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7463 return SRB_STATUS_ERROR
;
7466 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7468 FeatureReg
|= ATA_F_DMA
;
7469 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7470 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7471 FeatureReg
|= ATA_F_DMAREAD
;
7475 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7476 // this is done in UniataAhciSetupFIS_H2D()
7477 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7478 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7480 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7481 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7482 IDE_COMMAND_ATAPI_PACKET
/* command */,
7484 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7485 FeatureReg
/* feature */
7489 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7490 return SRB_STATUS_ERROR
;
7493 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7494 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7495 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7496 fis_size
, DeviceNumber
);
7498 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7502 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7503 // if this is queued request, reinit DMA and check
7504 // if DMA mode is still available
7505 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7506 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7507 if (/*EnableDma &&*/
7508 (LunExt
->TransferMode
>= ATA_DMA
)) {
7509 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7512 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7513 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7516 dma_reinited
= TRUE
;
7520 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7521 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7522 return SRB_STATUS_PENDING
;
7524 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7525 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7526 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7529 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7530 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7532 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7533 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7534 } if(AtaReq
->TransferLength
) {
7536 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7537 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7538 if (/*EnableDma &&*/
7539 (LunExt
->TransferMode
>= ATA_DMA
)) {
7542 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7547 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7549 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7550 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7551 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7552 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7555 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7556 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7557 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7560 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7562 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7563 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7565 // Make sure command is to ATAPI device.
7566 flags
= LunExt
->DeviceFlags
;
7567 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7568 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7570 // Indicate no device found at this address.
7571 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7572 return SRB_STATUS_SELECTION_TIMEOUT
;
7574 } else if(Srb
->Lun
> 0) {
7575 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7576 return SRB_STATUS_SELECTION_TIMEOUT
;
7579 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7580 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7581 return SRB_STATUS_SELECTION_TIMEOUT
;
7584 // Select device 0 or 1. Or more for PM
7585 SelectDrive(chan
, DeviceNumber
);
7587 // Verify that controller is ready for next command.
7588 GetStatus(chan
, statusByte
);
7589 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7591 if(statusByte
== IDE_STATUS_WRONG
) {
7592 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7595 if(statusByte
& IDE_STATUS_BUSY
) {
7596 if(statusByte
& IDE_STATUS_DSC
) {
7597 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7599 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7600 // We have to make reset here, since we are expecting device to be available
7601 //return SRB_STATUS_BUSY; // this cause queue freeze
7605 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7607 // Check if command list is free
7608 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7610 // controller is busy, however we expect it to be free
7611 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7615 if(statusByte
& IDE_STATUS_ERROR
) {
7616 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7618 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7619 // Read the error reg. to clear it and fail this request.
7620 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7621 return MapError(deviceExtension
, Srb
);
7623 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7626 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7627 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7628 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7629 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7631 AtapiStallExecution(200);
7632 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7633 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7634 return SRB_STATUS_PENDING
;
7637 if(IS_RDP(Srb
->Cdb
[0])) {
7639 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7643 if(statusByte
& IDE_STATUS_DRQ
) {
7645 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7647 // Try to drain the data that one preliminary device thinks that it has
7648 // to transfer. Hopefully this random assertion of DRQ will not be present
7649 // in production devices.
7650 statusByte
= AtapiSuckPort2(chan
);
7652 for (i = 0; i < 0x10000; i++) {
7653 GetStatus(chan, statusByte);
7654 if(statusByte & IDE_STATUS_DRQ) {
7655 AtapiReadPort2(chan, IDX_IO1_i_Data);
7661 if (statusByte
& IDE_STATUS_DRQ
) {
7663 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7665 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7667 AtapiSoftReset(chan
, DeviceNumber
);
7669 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7670 // Re-initialize Atapi device.
7671 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7673 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7674 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7676 // Inform the port driver that the bus has been reset.
7677 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7678 // Clean up device extension fields that AtapiStartIo won't.
7679 UniataExpectChannelInterrupt(chan
, FALSE
);
7681 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7684 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7686 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7687 return SRB_STATUS_BUS_RESET;
7690 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7694 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7695 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7696 return SRB_STATUS_SELECTION_TIMEOUT
;
7700 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7701 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7702 Srb
->Cdb
[1] &= ~0xE0;
7703 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7704 // Torisan changer. TUR's are overloaded to be platter switches.
7705 Srb
->Cdb
[7] = Srb
->Lun
;
7712 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7714 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7717 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7718 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7719 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7720 UniataExpectChannelInterrupt(chan
, TRUE
);
7721 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7722 return SRB_STATUS_PENDING
;
7725 statusByte
= WaitOnBusy(chan
);
7726 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7730 FeatureReg
|= ATA_F_DMA
;
7731 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7732 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7733 FeatureReg
|= ATA_F_DMAREAD
;
7737 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7739 // Write transfer byte count to registers.
7740 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7741 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7743 if (Srb
->DataTransferLength
>= 0x10000) {
7744 byteCountLow
= byteCountHigh
= 0xFF;
7747 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7748 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7750 if (flags
& DFLAGS_INT_DRQ
) {
7752 // This device interrupts when ready to receive the packet.
7754 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7757 UniataExpectChannelInterrupt(chan
, TRUE
);
7758 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7759 InterlockedExchange(&(chan
->CheckIntr
),
7762 // Write ATAPI packet command.
7763 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7765 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7766 return SRB_STATUS_PENDING
;
7770 // This device quickly sets DRQ when ready to receive the packet.
7772 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7775 UniataExpectChannelInterrupt(chan
, TRUE
);
7776 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7777 InterlockedExchange(&(chan
->CheckIntr
),
7780 if(g_opt_AtapiSendDisableIntr
) {
7781 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7783 // remember status. Later we may check if error appeared after cmd packet
7784 statusByte0
= statusByte
;
7786 // Write ATAPI packet command.
7787 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7791 statusByte
= WaitForDrq(chan
);
7793 // Need to read status register and clear interrupt (if any)
7794 GetBaseStatus(chan
, statusByte
);
7796 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7798 if(g_opt_AtapiSendDisableIntr
) {
7799 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7801 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7802 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7803 return SRB_STATUS_ERROR
;
7806 GetStatus(chan
, statusByte
);
7807 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7809 // Send CDB to device.
7810 statusByte
= WaitOnBaseBusy(chan
);
7812 // Indicate expecting an interrupt and wait for it.
7813 UniataExpectChannelInterrupt(chan
, TRUE
);
7814 InterlockedExchange(&(chan
->CheckIntr
),
7816 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7819 GetBaseStatus(chan
, statusByte
);
7822 statusByte
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7823 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", statusByte
));
7826 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7827 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
7829 if(g_opt_AtapiSendDisableIntr
) {
7830 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7835 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7838 GetStatus(chan
, statusByte
);
7839 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7841 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7842 // Interrupt may never come in such case.
7843 if(statusByte
& IDE_STATUS_ERROR
) {
7844 UCHAR interruptReason
;
7846 GetBaseStatus(chan
, statusByte
);
7847 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7849 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7850 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
7852 // TODO: we should check interruptReason and decide what to do now
7854 // Read the error reg. to clear it and fail this request.
7855 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7856 return MapError(deviceExtension
, Srb
);
7858 /* if(statusByte & IDE_STATUS_DSC) {
7859 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7860 // Read the error reg. to clear it and fail this request.
7861 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7862 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7863 if(statusByte >> 4) {
7864 GetBaseStatus(chan, statusByte);
7865 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7866 return MapError(deviceExtension, Srb);
7870 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7871 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7874 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7876 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7877 return SRB_STATUS_PENDING
;
7879 } // end AtapiSendCommand()
7886 Routine Description:
7887 Program ATA registers for IDE disk transfer.
7890 HwDeviceExtension - ATAPI driver storage.
7891 Srb - System request block.
7894 SRB status (pending if all goes well).
7899 ULONG check_point
= 0;
7900 #define SetCheckPoint(cp) { check_point = (cp) ; }
7902 #define SetCheckPoint(cp)
7908 IN PVOID HwDeviceExtension
,
7909 IN PSCSI_REQUEST_BLOCK Srb
,
7914 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7917 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7922 PHW_LU_EXTENSION LunExt
;
7926 UCHAR statusByte
,errorByte
;
7927 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7930 PMODE_PARAMETER_HEADER modeData
;
7937 //ULONG __ebp__ = 0;
7939 SetCheckPoint(0x20);
7940 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7945 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7946 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7947 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7948 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7949 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7951 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7952 Srb->SrbExtension));
7953 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7956 SetCheckPoint(0x30);
7957 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7959 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7961 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7963 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7965 lChannel
= GET_CHANNEL(Srb
);
7966 chan
= &(deviceExtension
->chan
[lChannel
]);
7967 //ldev = GET_LDEV(Srb);
7968 DeviceNumber
= GET_CDEV(Srb
);
7969 LunExt
= chan
->lun
[DeviceNumber
];
7971 SetCheckPoint(0x40);
7972 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7973 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7975 cdb
= (PCDB
)(Srb
->Cdb
);
7977 if(CmdAction
== CMD_ACTION_PREPARE
) {
7978 switch (Srb
->Cdb
[0]) {
7979 case SCSIOP_SERVICE_ACTION16
:
7980 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7983 goto default_no_prep
;
7986 case SCSIOP_INQUIRY
: // now it requires device access
7988 case SCSIOP_READ_CAPACITY
:
7992 case SCSIOP_WRITE12
:
7994 case SCSIOP_WRITE16
:
7995 case SCSIOP_REQUEST_SENSE
:
7997 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
8003 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
8004 return SRB_STATUS_BUSY
;
8008 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
8009 switch (Srb
->Cdb
[0]) {
8010 case SCSIOP_INQUIRY
:
8012 KdPrint2((PRINT_PREFIX
8013 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
8014 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8015 // Filter out wrong TIDs.
8016 if ((Srb
->Lun
!= 0) ||
8017 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
8018 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
8020 KdPrint2((PRINT_PREFIX
8021 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
8022 // Indicate no device found at this address.
8023 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8028 KdPrint2((PRINT_PREFIX
8029 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
8030 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8031 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
8033 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8035 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
8036 KdPrint2((PRINT_PREFIX
8037 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
8038 // Indicate no device found at this address.
8040 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8044 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
8045 KdPrint2((PRINT_PREFIX
8046 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
8047 // Indicate no device found at this address.
8048 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
8050 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8055 // Zero INQUIRY data structure.
8056 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8058 // Standard IDE interface only supports disks.
8059 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
8061 // Set the removable bit, if applicable.
8062 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
8063 KdPrint2((PRINT_PREFIX
8064 "RemovableMedia\n"));
8065 inquiryData
->RemovableMedia
= 1;
8067 // Set the Relative Addressing (LBA) bit, if applicable.
8068 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
8069 inquiryData
->RelativeAddressing
= 1;
8070 KdPrint2((PRINT_PREFIX
8071 "RelativeAddressing\n"));
8073 // Set the CommandQueue bit
8074 inquiryData
->CommandQueue
= 1;
8076 // Fill in vendor identification fields.
8077 for (i
= 0; i
< 24; i
+= 2) {
8078 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
8081 // Initialize unused portion of product id.
8082 for (i = 0; i < 4; i++) {
8083 inquiryData->ProductId[12+i] = ' ';
8086 // Move firmware revision from IDENTIFY data to
8087 // product revision in INQUIRY data.
8088 for (i
= 0; i
< 4; i
+= 2) {
8089 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
8092 status
= SRB_STATUS_SUCCESS
;
8097 case SCSIOP_REPORT_LUNS
: {
8100 PREPORT_LUNS_INFO_HDR LunInfo
;
8102 KdPrint2((PRINT_PREFIX
8103 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
8104 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8106 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
8113 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
8114 RtlZeroMemory(LunInfo
, 16);
8116 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
8117 Srb
->DataTransferLength
= 16;
8118 status
= SRB_STATUS_SUCCESS
;
8122 case SCSIOP_MODE_SENSE
:
8124 KdPrint2((PRINT_PREFIX
8125 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8126 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8128 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
8129 PMODE_POWER_CONDITION_PAGE modeData
;
8131 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
8132 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
8133 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
8134 status
= SRB_STATUS_DATA_OVERRUN
;
8136 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
8137 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
8139 modeData
->PageLength
= sizeof(MODE_POWER_CONDITION_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8141 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
8143 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
8144 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
8145 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
8146 status
= SRB_STATUS_SUCCESS
;
8149 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
8150 PMODE_CACHING_PAGE modeData
;
8152 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
8153 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
8154 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
8155 status
= SRB_STATUS_DATA_OVERRUN
;
8157 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
8158 modeData
->PageCode
= MODE_PAGE_CACHING
;
8159 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8160 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
8161 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
8162 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
8163 status
= SRB_STATUS_SUCCESS
;
8166 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8168 // This is used to determine if the media is write-protected.
8169 // Since IDE does not support mode sense then we will modify just the portion we need
8170 // so the higher level driver can determine if media is protected.
8172 //SelectDrive(chan, DeviceNumber);
8173 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8174 //statusByte = WaitOnBusy(chan);
8175 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8177 if (!(statusByte
& IDE_STATUS_ERROR
)) {
8179 // no error occured return success, media is not protected
8180 UniataExpectChannelInterrupt(chan
, FALSE
);
8181 InterlockedExchange(&(chan
->CheckIntr
),
8183 status
= SRB_STATUS_SUCCESS
;
8187 // error occured, handle it locally, clear interrupt
8188 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8190 GetBaseStatus(chan
, statusByte
);
8191 UniataExpectChannelInterrupt(chan
, FALSE
);
8192 InterlockedExchange(&(chan
->CheckIntr
),
8194 status
= SRB_STATUS_SUCCESS
;
8196 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
8198 //media is write-protected, set bit in mode sense buffer
8199 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
8201 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
8202 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
8205 status
= SRB_STATUS_SUCCESS
;
8207 status
= SRB_STATUS_INVALID_REQUEST
;
8211 case SCSIOP_TEST_UNIT_READY
:
8213 KdPrint2((PRINT_PREFIX
8214 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
8215 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8216 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8218 // Select device 0 or 1.
8219 //SelectDrive(chan, DeviceNumber);
8220 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8221 // Wait for busy. If media has not changed, return success
8222 //statusByte = WaitOnBusy(chan);
8223 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8225 if (!(statusByte
& IDE_STATUS_ERROR
)){
8226 UniataExpectChannelInterrupt(chan
, FALSE
);
8227 InterlockedExchange(&(chan
->CheckIntr
),
8229 status
= SRB_STATUS_SUCCESS
;
8231 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8232 if (errorByte
== IDE_ERROR_DATA_ERROR
){
8234 // Special case: If current media is write-protected,
8235 // the 0xDA command will always fail since the write-protect bit
8236 // is sticky,so we can ignore this error
8237 GetBaseStatus(chan
, statusByte
);
8238 UniataExpectChannelInterrupt(chan
, FALSE
);
8239 InterlockedExchange(&(chan
->CheckIntr
),
8241 status
= SRB_STATUS_SUCCESS
;
8245 // Request sense buffer to be build
8246 UniataExpectChannelInterrupt(chan
, TRUE
);
8247 InterlockedExchange(&(chan
->CheckIntr
),
8249 status
= SRB_STATUS_PENDING
;
8253 status
= SRB_STATUS_SUCCESS
;
8258 case SCSIOP_READ_CAPACITY
:
8260 KdPrint2((PRINT_PREFIX
8261 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8262 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8263 // Claim 512 byte blocks (big-endian).
8264 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8266 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
8267 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8269 // Calculate last sector.
8270 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
8271 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
8272 LunExt
->IdentifyData
.NumberOfHeads
*
8273 LunExt
->IdentifyData
.NumberOfCylinders
;
8277 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
8278 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
8279 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
8281 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
8283 KdPrint2((PRINT_PREFIX
8284 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
8286 LunExt
->IdentifyData
.SectorsPerTrack
,
8287 LunExt
->IdentifyData
.NumberOfHeads
,
8288 LunExt
->IdentifyData
.NumberOfCylinders
));
8291 status
= SRB_STATUS_SUCCESS
;
8294 case SCSIOP_SERVICE_ACTION16
:
8296 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8297 KdPrint2((PRINT_PREFIX
8298 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8299 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8300 // Claim 512 byte blocks (big-endian).
8301 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8303 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
8304 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8306 // Calculate last sector.
8307 if(!(lba
= LunExt
->NumOfSectors
)) {
8308 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
8309 LunExt
->IdentifyData
.NumberOfHeads
*
8310 LunExt
->IdentifyData
.NumberOfCylinders
;
8313 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
8315 KdPrint2((PRINT_PREFIX
8316 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8318 LunExt
->IdentifyData
.SectorsPerTrack
,
8319 LunExt
->IdentifyData
.NumberOfHeads
,
8320 LunExt
->IdentifyData
.NumberOfCylinders
));
8322 status
= SRB_STATUS_SUCCESS
;
8329 case SCSIOP_VERIFY12
:
8330 case SCSIOP_VERIFY16
:
8332 KdPrint2((PRINT_PREFIX
8333 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8334 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8335 status
= IdeVerify(HwDeviceExtension
,Srb
);
8342 case SCSIOP_WRITE12
:
8344 case SCSIOP_WRITE16
:
8346 KdPrint2((PRINT_PREFIX
8347 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8348 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
8349 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8350 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
8351 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
8352 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
8353 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
8354 status
= IdeReadWrite(HwDeviceExtension
,
8358 case SCSIOP_START_STOP_UNIT
:
8360 KdPrint2((PRINT_PREFIX
8361 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8362 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8363 //Determine what type of operation we should perform
8367 if(cdb
->START_STOP
.FL
||
8368 cdb
->START_STOP
.FormatLayerNumber
||
8369 cdb
->START_STOP
.Reserved2
||
8370 cdb
->START_STOP
.Reserved2_2
||
8371 cdb
->START_STOP
.Reserved3
||
8376 if (cdb
->START_STOP
.PowerConditions
) {
8377 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8378 switch(cdb
->START_STOP
.PowerConditions
) {
8379 case StartStop_Power_Idle
:
8380 command
= IDE_COMMAND_IDLE_IMMED
;
8382 case StartStop_Power_Standby
:
8383 command
= IDE_COMMAND_STANDBY_IMMED
;
8385 case StartStop_Power_Sleep
:
8386 // TODO: we should save power state in order to know
8387 // that RESET sould be issued to revert device into
8390 command
= IDE_COMMAND_SLEEP
;
8395 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8397 if (cdb
->START_STOP
.LoadEject
== 1) {
8398 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8400 // first select device 0 or 1.
8401 //SelectDrive(chan, DeviceNumber);
8402 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8403 command
= IDE_COMMAND_MEDIA_EJECT
;
8405 if (cdb
->START_STOP
.Start
== 0) {
8406 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8407 command
= IDE_COMMAND_STANDBY_IMMED
;
8409 // TODO: we may need to perform hard reset (after sleep) or
8410 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8411 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8413 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8414 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8415 status
= SRB_STATUS_SUCCESS
;
8418 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8419 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8420 command
= IDE_COMMAND_IDLE_IMMED
;
8422 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8423 status
= SRB_STATUS_SUCCESS
;
8428 statusByte
= WaitOnBaseBusy(chan
);
8429 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8430 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8431 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8432 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8436 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8437 if (Srb
->SenseInfoBuffer
) {
8439 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8441 senseBuffer
->ErrorCode
= 0x70;
8442 senseBuffer
->Valid
= 1;
8443 senseBuffer
->AdditionalSenseLength
= 0xb;
8444 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8445 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8446 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8448 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8449 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8451 status
= SRB_STATUS_ERROR
;
8455 case SCSIOP_MEDIUM_REMOVAL
:
8457 cdb
= (PCDB
)Srb
->Cdb
;
8459 if(LunExt
->IdentifyData
.Removable
) {
8460 statusByte
= WaitOnBaseBusy(chan
);
8462 //SelectDrive(chan, DeviceNumber);
8463 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8464 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8465 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8467 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8468 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8470 status
= SRB_STATUS_SUCCESS
;
8472 status
= SRB_STATUS_INVALID_REQUEST
;
8477 // Note: I don't implement this, because NTFS driver too often issues this command
8478 // It causes awful performance degrade. However, if somebody wants, I will implement
8479 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8480 case SCSIOP_FLUSH_BUFFER
:
8481 case SCSIOP_SYNCHRONIZE_CACHE
:
8483 SelectDrive(chan
, DeviceNumber
);
8484 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8485 status
= SRB_STATUS_SUCCESS
;
8486 // status = SRB_STATUS_PENDING;
8487 statusByte
= WaitOnBusy(chan
);
8491 case SCSIOP_REQUEST_SENSE
:
8492 // this function makes sense buffers to report the results
8493 // of the original GET_MEDIA_STATUS command
8495 KdPrint2((PRINT_PREFIX
8496 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8497 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8498 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8499 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8502 status
= SRB_STATUS_INVALID_REQUEST
;
8506 case SCSIOP_ATA_PASSTHROUGH
:
8509 BOOLEAN use_dma
= FALSE
;
8512 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8514 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8515 //lChannel = Srb->TargetId >> 1;
8517 DeviceNumber
= max(DeviceNumber
, 1);
8518 regs
->bDriveHeadReg
&= 0x0f;
8519 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8522 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8524 KdPrint2((PRINT_PREFIX
8525 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8526 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8528 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8529 to_lim
= Srb
->TimeOutValue
;
8531 if(Srb
->TimeOutValue
<= 2) {
8532 to_lim
= Srb
->TimeOutValue
*900;
8534 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8538 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8540 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8542 statusByte
= UniataAhciSendPIOCommandDirect(
8551 if(statusByte
== IDE_STATUS_WRONG
) {
8552 goto passthrough_err
;
8554 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8555 UniataAhciAbortOperation(chan
);
8556 goto passthrough_err
;
8558 goto passthrough_done
;
8562 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8563 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8565 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8566 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8567 (PUCHAR
)(Srb
->DataBuffer
),
8568 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8574 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8575 AtapiStallExecution(10);
8577 AtapiDmaDBPreSync(HwDeviceExtension
, chan
, Srb
);
8580 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8581 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8582 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8583 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8584 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8585 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8587 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8588 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8589 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8590 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8591 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8592 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8593 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8594 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8595 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8596 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8598 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8601 GetBaseStatus(chan
, statusByte
);
8602 if(statusByte
& IDE_STATUS_ERROR
) {
8603 goto passthrough_err
;
8605 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8608 ScsiPortStallExecution(1); // wait for busy to be set
8610 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8611 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8612 GetBaseStatus(chan
, statusByte
);
8613 if(statusByte
& IDE_STATUS_ERROR
) {
8616 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8621 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8623 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8624 goto passthrough_err
;
8628 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8630 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8631 GetBaseStatus(chan
, statusByte
);
8633 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8634 AtapiSuckPort2(chan
);
8636 if (Srb
->SenseInfoBuffer
) {
8638 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8640 senseBuffer
->ErrorCode
= 0x70;
8641 senseBuffer
->Valid
= 1;
8642 senseBuffer
->AdditionalSenseLength
= 0xb;
8643 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8644 senseBuffer
->AdditionalSenseCode
= 0;
8645 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8647 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8648 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8650 status
= SRB_STATUS_ERROR
;
8654 if (statusByte
& IDE_STATUS_DRQ
) {
8655 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8657 (PUSHORT
) Srb
->DataBuffer
,
8658 Srb
->DataTransferLength
/ 2,
8660 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8662 (PUSHORT
) Srb
->DataBuffer
,
8663 Srb
->DataTransferLength
/ 2,
8668 status
= SRB_STATUS_SUCCESS
;
8671 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8673 } else { // read task register
8676 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8678 KdPrint2((PRINT_PREFIX
8679 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8680 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8682 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8683 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8686 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8689 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8690 status
= SRB_STATUS_DATA_OVERRUN
;
8693 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8694 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8695 UniataSnapAtaRegs(chan
, 0, regs
);
8697 status
= SRB_STATUS_SUCCESS
;
8704 KdPrint2((PRINT_PREFIX
8705 "IdeSendCommand: Unsupported command %#x\n",
8708 status
= SRB_STATUS_INVALID_REQUEST
;
8712 if(status
== SRB_STATUS_PENDING
) {
8713 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8714 if(CmdAction
& CMD_ACTION_EXEC
) {
8715 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8716 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8719 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8720 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8725 } // end IdeSendCommand()
8730 Routine Description:
8731 Enables disables media status notification
8734 HwDeviceExtension - ATAPI driver storage.
8741 IN PVOID HwDeviceExtension
,
8743 IN ULONG DeviceNumber
8746 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8748 UCHAR statusByte
,errorByte
;
8750 chan
= &(deviceExtension
->chan
[lChannel
]);
8751 SelectDrive(chan
, DeviceNumber
);
8753 if (EnableMSN
== TRUE
){
8755 // If supported enable Media Status Notification support
8756 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8759 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8760 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8761 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8763 if (statusByte
& IDE_STATUS_ERROR
) {
8764 // Read the error register.
8765 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8767 KdPrint2((PRINT_PREFIX
8768 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8772 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8773 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8774 chan
->ReturningMediaStatus
= 0;
8779 } else { // end if EnableMSN == TRUE
8781 // disable if previously enabled
8782 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8784 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8785 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8786 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8787 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8794 } // end IdeMediaStatus()
8799 Routine Description:
8801 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8802 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8805 HwDeviceExtension - ATAPI driver storage.
8806 Srb - System request block.
8810 SRB status (ALWAYS SUCCESS).
8815 IdeBuildSenseBuffer(
8816 IN PVOID HwDeviceExtension
,
8817 IN PSCSI_REQUEST_BLOCK Srb
8820 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8822 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8823 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8827 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8829 senseBuffer
->ErrorCode
= 0x70;
8830 senseBuffer
->Valid
= 1;
8831 senseBuffer
->AdditionalSenseLength
= 0xb;
8832 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8833 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8834 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8835 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8837 senseBuffer
->ErrorCode
= 0x70;
8838 senseBuffer
->Valid
= 1;
8839 senseBuffer
->AdditionalSenseLength
= 0xb;
8840 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8841 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8842 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8843 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8845 senseBuffer
->ErrorCode
= 0x70;
8846 senseBuffer
->Valid
= 1;
8847 senseBuffer
->AdditionalSenseLength
= 0xb;
8848 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8849 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8850 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8851 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8853 senseBuffer
->ErrorCode
= 0x70;
8854 senseBuffer
->Valid
= 1;
8855 senseBuffer
->AdditionalSenseLength
= 0xb;
8856 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8857 senseBuffer
->AdditionalSenseCode
= 0;
8858 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8860 return SRB_STATUS_SUCCESS
;
8862 return SRB_STATUS_ERROR
;
8864 }// End of IdeBuildSenseBuffer
8868 UniataUserDeviceReset(
8869 PHW_DEVICE_EXTENSION deviceExtension
,
8870 PHW_LU_EXTENSION LunExt
,
8875 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8876 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8877 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8878 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8879 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8881 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8882 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8883 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8884 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8887 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8888 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8890 } // end UniataUserDeviceReset()
8895 PHW_DEVICE_EXTENSION deviceExtension
,
8900 BOOLEAN PostReq
= FALSE
;
8902 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8903 if(chan
->queue_depth
> 0) {
8906 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8907 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8908 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8910 status
= SRB_STATUS_BUSY
;
8919 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8923 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8926 } // end UniataNeedQueueing()
8930 Routine Description:
8932 This routine is called from the SCSI port driver synchronized
8933 with the kernel to start an IO request.
8938 HwDeviceExtension - HBA miniport driver's adapter data storage
8939 Srb - IO request packet
8949 IN PVOID HwDeviceExtension
,
8950 IN PSCSI_REQUEST_BLOCK Srb
8953 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8954 } // end AtapiStartIo()
8959 IN PVOID HwDeviceExtension
,
8960 IN PSCSI_REQUEST_BLOCK Srb
,
8964 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8967 PHW_LU_EXTENSION LunExt
;
8975 PSCSI_REQUEST_BLOCK tmpSrb
;
8976 BOOLEAN PostReq
= FALSE
;
8978 BOOLEAN commPort
= FALSE
;
8980 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8981 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8982 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8983 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8985 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8987 /* KeBugCheckEx(0xc000000e,
8988 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8990 TopLevel, 0x80000001);
8992 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8993 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8994 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8995 UniAtaClearAtaReq(Srb
->SrbExtension
);
8998 do { // fetch all queued commands for the channel (if valid)
9000 lChannel
= GET_CHANNEL(Srb
);
9001 //ldev = GET_LDEV(Srb);
9004 DeviceNumber
= GET_CDEV(Srb
);
9007 //ASSERT(deviceExtension);
9010 KdPrint2((PRINT_PREFIX
9011 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9012 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
9013 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
9015 if(lChannel
== deviceExtension
->NumberChannels
&&
9016 !Srb
->Lun
&& !Srb
->TargetId
&&
9017 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
9018 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
9020 // This is our virtual device
9021 KdPrint2((PRINT_PREFIX
9022 "AtapiStartIo: Communication port\n"));
9023 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
9025 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
9026 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
9027 sizeof(PINQUIRYDATA
) ));
9029 status
= SRB_STATUS_DATA_OVERRUN
;
9033 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
9035 KdPrint2((PRINT_PREFIX
9037 // Zero INQUIRY data structure.
9038 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
9040 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
9042 // Fill in vendor identification fields.
9043 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
9045 status
= SRB_STATUS_SUCCESS
;
9049 /* Pass IOCTL request down */
9051 if(lChannel
>= deviceExtension
->NumberChannels
||
9052 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
9055 if(lChannel
>= deviceExtension
->NumberChannels
) {
9060 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9061 KdPrint3((PRINT_PREFIX
9062 "AtapiStartIo: SRB rejected\n"));
9063 // Indicate no device found at this address.
9064 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9065 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9069 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
9070 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
9075 chan
= &(deviceExtension
->chan
[lChannel
]);
9076 LunExt
= chan
->lun
[DeviceNumber
];
9080 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9086 if(!commPort
&& !LunExt
) {
9088 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
9091 deviceExtension
->NumberChannels
);
9092 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
9093 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
9094 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9095 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
9099 for(i=0; i<1000; i++) {
9100 AtapiStallExecution(3*1000);
9107 // Determine which function.
9108 switch (Srb
->Function
) {
9110 case SRB_FUNCTION_EXECUTE_SCSI
:
9112 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9113 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9114 // let passthrough go
9116 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9120 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9121 KdPrint2((PRINT_PREFIX
9122 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
9123 // Indicate no device found at this address.
9124 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9125 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9130 KdPrint2((PRINT_PREFIX
9131 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
9135 if(Srb->DataTransferLength) {
9137 a = ((PUCHAR)(Srb->DataBuffer))[0];
9140 } __except(EXCEPTION_EXECUTE_HANDLER) {
9141 KdPrint3((PRINT_PREFIX
9142 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
9143 // Indicate no device found at this address.
9144 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
9145 status = SRB_STATUS_ERROR;
9146 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
9151 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9155 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
9157 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
9158 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
9160 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9162 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
9163 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9165 /*KeBugCheckEx(0xc000000e,
9166 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9168 status, 0x80000001);*/
9169 if(status
== SRB_STATUS_BUSY
)
9170 status
= SRB_STATUS_PENDING
;
9171 // Insert requests AFTER they have been initialized on
9172 // CMD_ACTION_PREPARE stage
9173 // we should not check TopLevel here (it is always TRUE)
9174 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9175 UniataQueueRequest(chan
, Srb
);
9177 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9181 // Send command to device.
9182 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
9184 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
9185 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9186 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
9187 //ASSERT(!AtaReq->Flags);
9188 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9189 UniataQueueRequest(chan
, Srb
);
9190 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
9191 //ASSERT(!AtaReq->Flags);
9192 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9193 //ASSERT(!AtaReq->Flags);
9197 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9201 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9202 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
9203 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
9207 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9211 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9220 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
9221 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
9222 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
9223 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9225 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
9230 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
9237 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
9239 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9241 /* KeBugCheckEx(0xc000000e,
9242 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9244 status, 0x80000002);*/
9252 case SRB_FUNCTION_ABORT_COMMAND
:
9254 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
9256 // Verify that SRB to abort is still outstanding.
9257 if((tmpSrb
!= Srb
->NextSrb
) ||
9258 !chan
->queue_depth
) {
9260 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
9262 // Complete abort SRB.
9263 status
= SRB_STATUS_ABORT_FAILED
;
9267 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
9268 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
9269 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
9270 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
9271 // Log reset failure.
9272 KdPrint3((PRINT_PREFIX
9273 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
9274 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9276 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9277 status
= SRB_STATUS_ERROR
;
9280 status
= SRB_STATUS_SUCCESS
;
9283 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
9284 if (tmpSrb
->SenseInfoBuffer
&&
9285 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
9287 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
9289 senseBuffer
->ErrorCode
= 0;
9290 senseBuffer
->Valid
= 1;
9291 senseBuffer
->AdditionalSenseLength
= 0xb;
9292 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
9293 senseBuffer
->AdditionalSenseCode
= 0;
9294 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9296 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
9298 AtapiDmaDBSync(chan
, tmpSrb
);
9299 UniataRemoveRequest(chan
, tmpSrb
);
9300 // Indicate command complete.
9301 ScsiPortNotification(RequestComplete
,
9304 status
= SRB_STATUS_SUCCESS
;
9308 // Abort function indicates that a request timed out.
9309 // Call reset routine. Card will only be reset if
9310 // status indicates something is wrong.
9311 // Fall through to reset code.
9313 case SRB_FUNCTION_RESET_DEVICE
:
9314 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
9316 // Reset single device.
9317 // For now we support only Lun=0
9319 // Note: reset is immediate command, it cannot be queued since it is usually used to
9320 // revert not-responding device to operational state
9321 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
9322 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
9323 status
= SRB_STATUS_SUCCESS
;
9326 case SRB_FUNCTION_RESET_BUS
:
9328 // Reset Atapi and SCSI bus.
9330 // Note: reset is immediate command, it cannot be queued since it is usually used to
9331 // revert not- responding device to operational state
9332 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
9333 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
9334 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
9335 // Log reset failure.
9336 KdPrint3((PRINT_PREFIX
9337 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9338 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9340 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9341 status
= SRB_STATUS_ERROR
;
9344 status
= SRB_STATUS_SUCCESS
;
9349 case SRB_FUNCTION_SHUTDOWN
:
9351 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
9352 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9353 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
9356 // FLUSH ATAPI device - do nothing
9357 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
9359 // FLUSH IDE/ATA device
9360 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9361 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9362 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9363 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9364 // If supported & allowed, reset write cacheing
9365 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9367 // Disable write cache
9368 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9369 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9370 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9371 // Check for errors.
9372 if (status
& IDE_STATUS_ERROR
) {
9373 KdPrint2((PRINT_PREFIX
9374 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9377 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9379 // Re-enable write cache
9380 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9381 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9382 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9383 // Check for errors.
9384 if (status
& IDE_STATUS_ERROR
) {
9385 KdPrint2((PRINT_PREFIX
9386 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9388 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9390 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9394 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9396 status
= SRB_STATUS_SUCCESS
;
9400 case SRB_FUNCTION_FLUSH
:
9402 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9403 status
= SRB_STATUS_SUCCESS
;
9406 case SRB_FUNCTION_IO_CONTROL
: {
9410 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9412 len
= Srb
->DataTransferLength
;
9414 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9416 ULONG targetId
= (ULONG
)(-1);
9418 if(len
< sizeof(SRB_IO_CONTROL
)) {
9419 goto wrong_buffer_size
;
9422 // extract bogus bus address
9423 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9424 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9425 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9427 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9428 goto wrong_buffer_size
;
9431 targetId
= versionParameters
->bIDEDeviceMap
;
9432 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9434 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9435 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9436 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9437 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9438 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9439 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9440 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9441 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9442 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9443 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9444 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9445 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9447 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9449 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9450 goto wrong_buffer_size
;
9453 targetId
= cmdInParameters
->bDriveNumber
;
9454 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9458 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9459 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9460 status
= SRB_STATUS_INVALID_REQUEST
;
9464 // adjust (if necessary) bus address
9465 if(targetId
!= (ULONG
)(-1)) {
9467 // This is done because of how the IOCTL_SCSI_MINIPORT
9468 // determines 'targetid's'. Disk.sys places the real target id value
9469 // in the DeviceMap field. Once we do some parameter checking, the value passed
9470 // back to the application will be determined.
9472 if (deviceExtension
->NumberChannels
== 1) {
9473 // do this for legacy controllers and legacy callers
9474 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9475 DeviceNumber
= (targetId
& 0x01);
9479 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9480 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9481 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9482 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9483 lChannel
= (UCHAR
)targetId
/ 2;
9486 lChannel
= (UCHAR
)(targetId
/ 2);
9487 DeviceNumber
= targetId
& 0x01;
9490 // otherwise assume lChannel and DeviceNumber from Srb are ok
9492 if(lChannel
>= deviceExtension
->NumberChannels
||
9493 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9494 KdPrint2((PRINT_PREFIX
9495 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9497 // Indicate no device found at this address.
9500 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9501 chan
= &(deviceExtension
->chan
[lChannel
]);
9502 LunExt
= chan
->lun
[DeviceNumber
];
9506 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9508 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9513 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9514 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9516 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9517 UCHAR deviceNumberMap
;
9519 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9521 // Version and revision per SMART 1.03
9523 versionParameters
->bVersion
= 1;
9524 versionParameters
->bRevision
= 1;
9525 versionParameters
->bReserved
= 0;
9527 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9528 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9531 goto invalid_request
;
9534 // NOTE: This will only set the bit
9535 // corresponding to this drive's target id.
9536 // The bit mask is as follows:
9542 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9543 deviceNumberMap
= 1 << lChannel
;
9546 if (deviceExtension
->NumberChannels
== 1) {
9547 if (chan
->PrimaryAddress
) {
9548 deviceNumberMap
= 1 << DeviceNumber
;
9550 deviceNumberMap
= 4 << DeviceNumber
;
9553 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9556 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9558 status
= SRB_STATUS_SUCCESS
;
9562 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9564 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9565 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9567 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9568 // Extract the target.
9569 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9571 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9574 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9575 goto invalid_request
;
9581 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9582 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9583 goto invalid_request
;
9586 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9587 // Zero the output buffer
9588 RtlZeroMemory(cmdOutParameters
, len
);
9589 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9590 ((PUCHAR)cmdOutParameters)[i] = 0;
9593 // Build status block.
9594 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9595 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9596 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9598 // Extract the identify data from the device extension.
9599 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9600 cmdOutParameters
->cBufferSize
);
9602 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9603 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9604 // adjust checksum if it is possible
9608 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9609 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9611 cmdOutParameters
->bBuffer
[i
] = -csum
;
9612 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9614 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9616 status
= SRB_STATUS_SUCCESS
;
9620 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9621 cmdInParameters
.irDriveRegs
.bCommandReg
));
9622 status
= SRB_STATUS_INVALID_REQUEST
;
9628 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9629 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9630 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9631 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9632 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9633 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9634 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9635 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9638 // *all* IOCTLs here are SMART
9640 KdPrint2((PRINT_PREFIX
9641 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9644 goto invalid_request
;
9647 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9649 if(PostReq
|| TopLevel
) {
9650 UniataQueueRequest(chan
, Srb
);
9651 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9652 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9657 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9658 status
= SRB_STATUS_PENDING
;
9660 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9663 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9667 // we should not get here, checked above
9669 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9670 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9671 status = SRB_STATUS_INVALID_REQUEST;
9676 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9678 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9679 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9680 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9684 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9685 //chan = &(deviceExtension->chan[lChannel]);
9687 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9688 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9689 goto wrong_buffer_size
;
9692 if(AtaCtl
->addr
.Lun
||
9693 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9694 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9702 lChannel
= AtaCtl
->addr
.PathId
;
9703 chan
= &(deviceExtension
->chan
[lChannel
]);
9704 LunExt
= chan
->lun
[DeviceNumber
];
9707 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9709 /* check for valid LUN */
9710 switch (AtaCtl
->hdr
.ControlCode
) {
9711 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9712 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9713 // this would be BUS reset
9715 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9716 AtaCtl
->addr
.TargetId
!= 0xff ||
9717 AtaCtl
->addr
.Lun
!= 0
9719 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9720 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9721 lChannel
= AtaCtl
->addr
.PathId
;
9722 chan
= &(deviceExtension
->chan
[lChannel
]);
9723 LunExt
= chan
->lun
[DeviceNumber
];
9726 goto handle_bad_ldev
;
9729 lChannel
= AtaCtl
->addr
.PathId
;
9730 chan
= &(deviceExtension
->chan
[lChannel
]);
9733 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9734 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9735 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9736 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9737 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9740 KdPrint2((PRINT_PREFIX
9741 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9742 // Indicate no device found at this address.
9747 /* check if queueing is necessary */
9748 switch (AtaCtl
->hdr
.ControlCode
) {
9749 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9750 if(!LunExt
->nBadBlocks
) {
9753 goto uata_ctl_queue
;
9754 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9755 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9756 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9757 pos
+sizeof(AtaCtl
->SetMode
) ));
9758 goto wrong_buffer_size
;
9760 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9763 goto uata_ctl_queue
;
9764 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9765 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9767 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9768 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9770 if(PostReq
|| TopLevel
) {
9771 UniataQueueRequest(chan
, Srb
);
9772 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9773 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9776 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9777 status
= SRB_STATUS_PENDING
;
9779 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9782 } // end switch (AtaCtl->hdr.ControlCode)
9784 /* process request */
9785 switch (AtaCtl
->hdr
.ControlCode
) {
9786 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9788 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9790 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9791 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9792 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9793 goto wrong_buffer_size
;
9795 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9796 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9797 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9798 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9803 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9804 AtapiStallExecution(1000 * 1000);
9807 FindDevices(HwDeviceExtension
,
9808 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9809 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9810 AtaCtl
->addr
.PathId
);
9811 status
= SRB_STATUS_SUCCESS
;
9815 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9817 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9819 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9820 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9821 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9822 goto wrong_buffer_size
;
9824 LunExt
->DeviceFlags
= 0;
9825 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9826 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9827 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9828 UniataForgetDevice(LunExt
);
9831 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9832 AtapiStallExecution(1000 * 1000);
9835 status
= SRB_STATUS_SUCCESS
;
9838 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9840 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9842 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9843 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9844 pos
+sizeof(AtaCtl
->SetMode
) ));
9845 goto wrong_buffer_size
;
9847 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9848 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9850 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9851 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9852 if(LunExt
->LimitedTransferMode
>
9853 LunExt
->OrigTransferMode
) {
9854 // check for incorrect value
9855 LunExt
->LimitedTransferMode
=
9856 LunExt
->OrigTransferMode
;
9859 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9861 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9862 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9863 AtapiDmaInit__(deviceExtension
, LunExt
);
9865 /* LunExt->TransferMode =
9866 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9867 status
= SRB_STATUS_SUCCESS
;
9870 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9872 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9874 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9875 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9876 pos
+sizeof(AtaCtl
->GetMode
) ));
9877 goto wrong_buffer_size
;
9879 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9880 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9881 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9882 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9884 status
= SRB_STATUS_SUCCESS
;
9887 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9889 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9891 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9892 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9893 pos
+sizeof(AtaCtl
->Version
) ));
9894 goto wrong_buffer_size
;
9896 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9897 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9898 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9899 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9900 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9902 status
= SRB_STATUS_SUCCESS
;
9905 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9907 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9909 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9910 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9911 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9912 goto wrong_buffer_size
;
9914 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9916 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9917 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9918 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9919 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9920 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9921 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9922 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9923 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9924 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9925 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9926 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9927 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9928 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9929 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9930 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9931 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9932 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9933 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9934 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9935 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9936 if(deviceExtension
->FullDevName
) {
9937 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9939 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9940 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9941 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9943 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9946 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9949 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9950 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9951 PHW_CHANNEL cur_chan
;
9952 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9953 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9954 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9955 cur_chan
= &(deviceExtension
->chan
[i
]);
9956 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9957 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9958 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9959 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9960 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9961 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9962 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9963 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9964 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9967 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9968 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9971 status
= SRB_STATUS_SUCCESS
;
9974 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9976 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9978 ForgetBadBlocks(LunExt
);
9980 status
= SRB_STATUS_SUCCESS
;
9983 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9985 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9990 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9993 status
= SRB_STATUS_SUCCESS
;
9997 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9998 AtaCtl
->hdr
.ControlCode
));
9999 status
= SRB_STATUS_INVALID_REQUEST
;
10004 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
10005 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
10006 "SCSIDISK", "-UNIATA-"));
10008 status
= SRB_STATUS_INVALID_REQUEST
;
10013 } // end SRB_FUNCTION_IO_CONTROL
10016 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
10017 // Indicate unsupported command.
10018 status
= SRB_STATUS_INVALID_REQUEST
;
10026 PathId
= Srb
->PathId
;
10027 TargetId
= Srb
->TargetId
;
10030 if (status
!= SRB_STATUS_PENDING
) {
10032 KdPrint2((PRINT_PREFIX
10033 "AtapiStartIo: Srb %#x complete with status %#x\n",
10037 // Set status in SRB.
10038 Srb
->SrbStatus
= (UCHAR
)status
;
10041 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
10042 AtapiDmaDBSync(chan
, Srb
);
10044 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
10045 UniataRemoveRequest(chan
, Srb
);
10046 // Indicate command complete.
10047 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
10048 ScsiPortNotification(RequestComplete
,
10052 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
10053 // Remove current Srb & get next one
10054 if((Srb
= UniataGetCurRequest(chan
))) {
10055 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10056 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
10057 // current request is under precessing, thus
10058 // we should do nothing here
10062 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
10064 //ASSERT(TopLevel);
10067 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
10069 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
10071 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
10072 // Indicate ready for next request.
10073 ScsiPortNotification(NextRequest
,
10077 ScsiPortNotification(NextLuRequest
,
10085 } // end AtapiStartIo__()
10090 UniataInitAtaCommands()
10096 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
10098 for(i
=0; i
<256; i
++) {
10103 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
10106 case IDE_COMMAND_READ_DMA48
:
10107 case IDE_COMMAND_READ_DMA_Q48
:
10108 case IDE_COMMAND_READ_STREAM_DMA48
:
10109 case IDE_COMMAND_READ_STREAM48
:
10110 case IDE_COMMAND_WRITE_DMA48
:
10111 case IDE_COMMAND_WRITE_DMA_Q48
:
10112 case IDE_COMMAND_READ_DMA_Q
:
10113 case IDE_COMMAND_READ_DMA
:
10114 case IDE_COMMAND_WRITE_DMA
:
10115 case IDE_COMMAND_WRITE_DMA_Q
:
10116 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10117 case IDE_COMMAND_WRITE_STREAM48
:
10118 case IDE_COMMAND_WRITE_FUA_DMA48
:
10119 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10120 case IDE_COMMAND_READ_LOG_DMA48
:
10121 case IDE_COMMAND_WRITE_LOG_DMA48
:
10122 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10123 case IDE_COMMAND_TRUSTED_SEND_DMA
:
10124 case IDE_COMMAND_DATA_SET_MGMT
:
10125 //KdPrint2((PRINT_PREFIX "DMA "));
10126 flags
|= ATA_CMD_FLAG_DMA
;
10130 case IDE_COMMAND_WRITE_FUA_DMA48
:
10131 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10132 case IDE_COMMAND_WRITE_MUL_FUA48
:
10134 flags
|= ATA_CMD_FLAG_FUA
;
10137 case IDE_COMMAND_READ48
:
10138 case IDE_COMMAND_READ_DMA48
:
10139 case IDE_COMMAND_READ_DMA_Q48
:
10140 case IDE_COMMAND_READ_MUL48
:
10141 case IDE_COMMAND_READ_STREAM_DMA48
:
10142 case IDE_COMMAND_READ_STREAM48
:
10143 case IDE_COMMAND_WRITE48
:
10144 case IDE_COMMAND_WRITE_DMA48
:
10145 case IDE_COMMAND_WRITE_DMA_Q48
:
10146 case IDE_COMMAND_WRITE_MUL48
:
10147 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10148 case IDE_COMMAND_WRITE_STREAM48
:
10149 case IDE_COMMAND_FLUSH_CACHE48
:
10150 case IDE_COMMAND_VERIFY48
:
10152 //KdPrint2((PRINT_PREFIX "48 "));
10153 flags
|= ATA_CMD_FLAG_48
;
10156 case IDE_COMMAND_READ
:
10157 case IDE_COMMAND_READ_MULTIPLE
:
10158 case IDE_COMMAND_READ_DMA
:
10159 case IDE_COMMAND_READ_DMA_Q
:
10160 case IDE_COMMAND_WRITE
:
10161 case IDE_COMMAND_WRITE_MULTIPLE
:
10162 case IDE_COMMAND_WRITE_DMA
:
10163 case IDE_COMMAND_WRITE_DMA_Q
:
10164 case IDE_COMMAND_FLUSH_CACHE
:
10165 case IDE_COMMAND_VERIFY
:
10167 //KdPrint2((PRINT_PREFIX "LBA "));
10168 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
10172 case IDE_COMMAND_READ_NATIVE_SIZE48
:
10173 case IDE_COMMAND_SET_NATIVE_SIZE48
:
10174 // we cannot set LBA flag for these commands to avoid BadBlock handling
10175 //flags |= ATA_CMD_FLAG_LBAIOsupp;
10176 flags
|= ATA_CMD_FLAG_48
;
10178 case IDE_COMMAND_READ_NATIVE_SIZE
:
10179 case IDE_COMMAND_SET_NATIVE_SIZE
:
10181 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
10184 flags
|= ATA_CMD_FLAG_48supp
;
10187 case IDE_COMMAND_READ
:
10188 command
= IDE_COMMAND_READ48
; break;
10189 case IDE_COMMAND_READ_MULTIPLE
:
10190 command
= IDE_COMMAND_READ_MUL48
; break;
10191 case IDE_COMMAND_READ_DMA
:
10192 command
= IDE_COMMAND_READ_DMA48
; break;
10193 case IDE_COMMAND_READ_DMA_Q
:
10194 command
= IDE_COMMAND_READ_DMA_Q48
; break;
10195 case IDE_COMMAND_WRITE
:
10196 command
= IDE_COMMAND_WRITE48
; break;
10197 case IDE_COMMAND_WRITE_MULTIPLE
:
10198 command
= IDE_COMMAND_WRITE_MUL48
; break;
10199 case IDE_COMMAND_WRITE_DMA
:
10200 command
= IDE_COMMAND_WRITE_DMA48
; break;
10201 case IDE_COMMAND_WRITE_DMA_Q
:
10202 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
10203 case IDE_COMMAND_FLUSH_CACHE
:
10204 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
10205 // case IDE_COMMAND_READ_NATIVE_SIZE:
10206 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
10207 case IDE_COMMAND_SET_NATIVE_SIZE
:
10208 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
10209 case IDE_COMMAND_VERIFY
:
10210 command
= IDE_COMMAND_VERIFY48
; break;
10212 //KdPrint2((PRINT_PREFIX "!28->48 "));
10213 flags
&= ~ATA_CMD_FLAG_48supp
;
10217 case IDE_COMMAND_READ
:
10218 case IDE_COMMAND_READ_MULTIPLE
:
10219 case IDE_COMMAND_READ_DMA48
:
10220 case IDE_COMMAND_READ_DMA_Q48
:
10221 case IDE_COMMAND_READ_STREAM_DMA48
:
10222 case IDE_COMMAND_READ_STREAM48
:
10223 case IDE_COMMAND_READ_DMA_Q
:
10224 case IDE_COMMAND_READ_DMA
:
10225 case IDE_COMMAND_READ_LOG_DMA48
:
10226 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10227 case IDE_COMMAND_IDENTIFY
:
10228 case IDE_COMMAND_ATAPI_IDENTIFY
:
10229 //KdPrint2((PRINT_PREFIX "RD "));
10230 flags
|= ATA_CMD_FLAG_In
;
10232 case IDE_COMMAND_WRITE
:
10233 case IDE_COMMAND_WRITE_MULTIPLE
:
10234 case IDE_COMMAND_WRITE_DMA48
:
10235 case IDE_COMMAND_WRITE_DMA_Q48
:
10236 case IDE_COMMAND_WRITE_DMA
:
10237 case IDE_COMMAND_WRITE_DMA_Q
:
10238 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10239 case IDE_COMMAND_WRITE_STREAM48
:
10240 case IDE_COMMAND_WRITE_FUA_DMA48
:
10241 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10242 //KdPrint2((PRINT_PREFIX "WR "));
10243 flags
|= ATA_CMD_FLAG_Out
;
10247 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
10248 AtaCommands48
[i
] = command
;
10249 AtaCommandFlags
[i
] = flags
;
10251 } // end UniataInitAtaCommands()
10255 Routine Description:
10257 Installable driver initialization entry point for system.
10265 Status from ScsiPortInitialize()
10272 IN PVOID DriverObject
,
10276 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
10277 ULONG adapterCount
;
10279 ULONG statusToReturn
, newStatus
;
10280 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
10281 BOOLEAN ReEnter
= FALSE
;
10283 #ifndef USE_REACTOS_DDK
10287 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
10288 BOOLEAN PrimaryClaimed
= FALSE
;
10289 BOOLEAN SecondaryClaimed
= FALSE
;
10291 LARGE_INTEGER t0
, t1
;
10293 Connect_DbgPrint();
10294 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
10295 //a = (WCHAR)strlen(ver_string);
10297 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
10298 if(g_opt_Verbose
) {
10299 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
10302 if(!SavedDriverObject
) {
10303 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
10304 #ifdef USE_REACTOS_DDK
10305 KdPrint(("UniATA Init: OS should be ReactOS\n"));
10310 // we are here for the 1st time
10311 // init CrossNT and get OS version
10312 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
10313 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
10314 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10317 #endif // USE_REACTOS_DDK
10318 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, *KeNumberProcessors
));
10320 KeQuerySystemTime(&t0
);
10322 KeQuerySystemTime(&t1
);
10323 } while(t0
.QuadPart
== t1
.QuadPart
);
10327 KeQuerySystemTime(&t1
);
10329 } while(t0
.QuadPart
== t1
.QuadPart
);
10330 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
10331 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
10333 KdPrint(("UniATA Init: ReEnter\n"));
10337 // (re)read bad block list
10338 InitBadBlocks(NULL
);
10341 // init ATA command translation table
10342 UniataInitAtaCommands();
10343 // get registry path to settings
10344 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
10345 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
10346 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
10347 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
10348 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
10349 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
10352 if(WinVer_Id() >= WinVer_2k
) {
10353 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
10354 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10355 WinVer_WDM_Model
= TRUE
;
10357 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
10358 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10359 WinVer_WDM_Model
= TRUE
;
10363 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10364 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10366 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10369 statusToReturn
= 0xffffffff;
10371 // Zero out structure.
10372 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10374 // Set size of hwInitializationData.
10375 hwInitializationData
.comm
.HwInitializationDataSize
=
10376 sizeof(hwInitializationData
.comm
) +
10377 // sizeof(hwInitializationData.nt4) +
10378 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10379 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10381 // Set entry points.
10382 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10383 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10384 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10385 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10387 // Specify size of extensions.
10388 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10389 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10390 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10392 // Indicate PIO device.
10393 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10394 // Set PnP-specific API
10395 if(WinVer_Id() > WinVer_NT
) {
10396 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10397 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10398 KdPrint(("set AtapiAdapterControl() ptr\n"));
10399 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10402 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
10406 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10407 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10408 g_opt_VirtualMachine
= 0;
10410 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10411 g_opt_VirtualMachine
= VM_VBOX
;
10413 // Pre-scan PCI bus, also check if we are under VM
10414 UniataEnumBusMasterController(DriverObject
, Argument2
);
10416 switch(g_opt_VirtualMachine
) {
10418 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10419 // adjust options for VirtualBox
10420 g_opt_WaitBusyCount
= 20000;
10421 g_opt_WaitBusyDelay
= 150;
10422 g_opt_WaitDrqDelay
= 100;
10423 g_opt_WaitBusyLongCount
= 20000;
10424 g_opt_MaxIsrWait
= 200;
10425 g_opt_AtapiSendDisableIntr
= FALSE
;
10426 g_opt_AtapiDmaRawRead
= FALSE
;
10431 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10432 // old slow machine, adjust timings
10433 g_opt_WaitBusyCount
= 20000;
10434 g_opt_WaitBusyDelay
= 150;
10435 g_opt_WaitDrqDelay
= 100;
10436 g_opt_WaitBusyLongCount
= 20000;
10437 g_opt_MaxIsrWait
= 200;
10440 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10441 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10442 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10443 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10444 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10445 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
) ? TRUE
: FALSE
; // 1 vs 0
10446 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
) ? TRUE
: FALSE
; // 1 vs 0
10447 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10450 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10451 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10452 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10453 for (i
=0; i
<BMListLen
; i
++) {
10455 if(!BMList
[i
].MasterDev
) {
10456 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10459 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10463 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10464 if(BMList
[i
].ChanInitOk
& 0x03) {
10465 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10467 newStatus
= STATUS_SUCCESS
;
10471 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10473 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10474 PrimaryClaimed
= TRUE
;
10475 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10476 SecondaryClaimed
= TRUE
;
10478 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10479 !(BMList
[i
].ChanInitOk
& 0x80)) {
10480 newStatus
= UniataClaimLegacyPCIIDE(i
);
10481 if(newStatus
!= STATUS_SUCCESS
) {
10482 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10487 if(g_opt_Verbose
) {
10488 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10492 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10494 for(c
=0; c
<2; c
++) {
10496 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10500 if(PrimaryClaimed
) {
10501 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10506 if(SecondaryClaimed
) {
10507 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10512 if((WinVer_Id() < WinVer_2k
)) {
10513 // do not even try if already claimed
10515 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10518 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10521 if(!WinVer_WDM_Model
) {
10522 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10524 // in WDM model things are different....
10525 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10526 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10528 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10529 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10531 if(!WinVer_WDM_Model
) {
10532 BMList
[i
].channel
= (UCHAR
)c
;
10535 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10536 newStatus
= ScsiPortInitialize(DriverObject
,
10538 &hwInitializationData
.comm
,
10539 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10540 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10541 if (newStatus
< statusToReturn
) {
10542 statusToReturn
= newStatus
;
10544 if (newStatus
== STATUS_SUCCESS
) {
10545 if(WinVer_Id() < WinVer_2k
) {
10546 // This should be done in HwInitialize under w2k+ to ensure that
10547 // channel is actually initialized
10548 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10550 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10551 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10555 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10556 c = 1; // this will break our for()
10557 BMList[i].ChanInitOk |= 0x01 << c;
10562 /* if(WinVer_Id() >= WinVer_2k) {
10563 // the following didn't work under higher OSes,
10564 // until we move setting of FLAGS to HwInit
10565 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10568 if(BMList
[i
].ChanInitOk
& 0x03) {
10569 // Under NT we receive status immediately, so
10570 // we can omit alternative init method if STATUS_SUCCESS returned.
10571 // Under w2k+ we relay on flags, set in HwInitialize.
10572 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10575 if(WinVer_Id() >= WinVer_2k
) {
10576 // try AltInit if HwInit was not called immediately under w2k+
10577 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10579 // if (WinVer_Id() == WinVer_NT) and some error occured
10580 // try alternative init method
10581 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10584 if(g_opt_Verbose
) {
10585 if(BMList
[i
].ChanInitOk
& 0x03) {
10586 _PrintNtConsole(" OK\n");
10588 _PrintNtConsole(" failed\n");
10594 /* KeBugCheckEx(0xc000000e,
10595 (i << 16) | BMList[0].ChanInitOk,
10597 newStatus, statusToReturn);*/
10599 // Look for PCI IDE controller
10600 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10601 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10602 for (; i
<BMListLen
; i
++) {
10604 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10607 /* if(BMList[i].MasterDev)
10609 if(g_opt_Verbose
) {
10610 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10611 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10612 BMList
[i
].busNumber
,
10613 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10614 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10617 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10618 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10619 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10621 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10622 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10623 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10624 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10626 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10628 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10629 hwInitializationData
.comm
.VendorId
,
10630 hwInitializationData
.comm
.DeviceId
));
10631 newStatus
= ScsiPortInitialize(DriverObject
,
10633 &hwInitializationData
.comm
,
10635 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10636 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10637 // Note: this is actually a BUG in scsiport.sys
10638 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10639 // However, this PCI Slot may have higher non-empty Functions
10640 // UniATA will perform all staff instead of ScsiPort under NT,
10641 // but for ReactOS it is better to patch ScsiPort.
10642 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10643 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10644 newStatus
= ScsiPortInitialize(DriverObject
,
10646 &hwInitializationData
.comm
,
10647 (PVOID
)(i
| 0x80000000));
10648 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10650 if (newStatus
< statusToReturn
)
10651 statusToReturn
= newStatus
;
10653 if(g_opt_Verbose
) {
10654 if(newStatus
== STATUS_SUCCESS
) {
10655 _PrintNtConsole(" OK\n");
10657 _PrintNtConsole(" failed\n");
10663 /* KeBugCheckEx(0xc000000e,
10666 newStatus, statusToReturn);*/
10670 hwInitializationData
.comm
.VendorId
= 0;
10671 hwInitializationData
.comm
.VendorIdLength
= 0;
10672 hwInitializationData
.comm
.DeviceId
= 0;
10673 hwInitializationData
.comm
.DeviceIdLength
= 0;
10676 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10678 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10681 // The adapter count is used by the find adapter routine to track how
10682 // which adapter addresses have been tested.
10684 // Indicate 2 access ranges and reset FindAdapter.
10685 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10686 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10688 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10689 // Indicate ISA bustype.
10690 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10693 // Call initialization for ISA bustype.
10694 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10695 newStatus
= ScsiPortInitialize(DriverObject
,
10697 &hwInitializationData
.comm
,
10699 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10700 if (newStatus
< statusToReturn
)
10701 statusToReturn
= newStatus
;
10703 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10705 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10706 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10709 newStatus
= ScsiPortInitialize(DriverObject
,
10711 &hwInitializationData
.comm
,
10713 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10714 if (newStatus
< statusToReturn
)
10715 statusToReturn
= newStatus
;
10717 InDriverEntry
= FALSE
;
10719 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10721 return statusToReturn
;
10723 } // end DriverEntry()
10726 PSCSI_REQUEST_BLOCK
10728 BuildMechanismStatusSrb(
10729 IN PVOID HwDeviceExtension
,
10730 IN PSCSI_REQUEST_BLOCK Srb
10733 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10734 PSCSI_REQUEST_BLOCK srb
;
10736 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10738 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10740 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10742 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10743 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10744 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10745 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10747 // Set flags to disable synchronous negociation.
10748 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10750 // Set timeout to 4 seconds.
10751 srb
->TimeOutValue
= 4;
10753 srb
->CdbLength
= 6;
10754 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10755 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10756 srb
->SrbExtension
= AtaReq
;
10758 // Set CDB operation code.
10759 cdb
= (PCDB
)srb
->Cdb
;
10760 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10761 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10763 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10766 } // end BuildMechanismStatusSrb()
10768 #endif //UNIATA_CORE
10770 PSCSI_REQUEST_BLOCK
10772 BuildRequestSenseSrb (
10773 IN PVOID HwDeviceExtension
,
10774 IN PSCSI_REQUEST_BLOCK Srb
10777 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10778 PSCSI_REQUEST_BLOCK srb
;
10780 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10782 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10784 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10786 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10787 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10788 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10789 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10791 // Set flags to disable synchronous negociation.
10792 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10794 // Set timeout to 2 seconds.
10795 srb
->TimeOutValue
= 4;
10797 srb
->CdbLength
= 6;
10798 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10799 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10800 srb
->SrbExtension
= AtaReq
;
10802 // Set CDB operation code.
10803 cdb
= (PCDB
)srb
->Cdb
;
10804 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10805 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10807 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10810 } // end BuildRequestSenseSrb()
10812 #ifndef UNIATA_CORE
10816 AtapiRegCheckDevLunValue(
10817 IN PVOID HwDeviceExtension
,
10818 IN PCWCH NamePrefix
,
10826 ULONG val
= Default
;
10828 val
= AtapiRegCheckParameterValue(
10829 HwDeviceExtension
, NamePrefix
, Name
, val
);
10831 if(chan
!= CHAN_NOT_SPECIFIED
) {
10832 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10833 val
= AtapiRegCheckParameterValue(
10834 HwDeviceExtension
, namex
, Name
, val
);
10835 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10836 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10837 val
= AtapiRegCheckParameterValue(
10838 HwDeviceExtension
, namex
, Name
, val
);
10842 } // end AtapiRegCheckDevLunValue()
10855 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10874 swprintf(Buffer
+j
, L
"%2.2x", a
);
10882 } // end EncodeVendorStr()
10886 AtapiRegCheckDevValue(
10887 IN PVOID HwDeviceExtension
,
10894 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10895 // WCHAR name0[11];
10896 // WCHAR name1[11+4+5];
10897 // WCHAR name2[11+4+4+10];
10898 // WCHAR name3[11+4+4+5+20];
10899 // WCHAR name3[11+4+4+5+20+1];
10908 IN ULONG SlotNumber
;
10910 ULONG val
= Default
;
10912 KdPrint(( " Parameter %ws\n", Name
));
10914 if(deviceExtension
) {
10915 VendorID
= deviceExtension
->DevID
& 0xffff;
10916 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10917 SlotNumber
= deviceExtension
->slotNumber
;
10921 SlotNumber
= 0xffffffff;
10924 val
= AtapiRegCheckDevLunValue(
10925 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10927 if(deviceExtension
) {
10928 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10930 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10931 swprintf(namex
, L
"Parameters%s", namev
);
10932 val
= AtapiRegCheckDevLunValue(
10933 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10936 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10937 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10938 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10940 swprintf(namex
, L
"Parameters%s", namev
);
10941 val
= AtapiRegCheckDevLunValue(
10942 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10944 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10945 val
= AtapiRegCheckDevLunValue(
10946 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10948 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10949 val
= AtapiRegCheckDevLunValue(
10950 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10952 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10954 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10955 swprintf(namex
, L
"Parameters%s", namev
);
10956 val
= AtapiRegCheckDevLunValue(
10957 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10959 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10960 swprintf(namex
, L
"Parameters%s", namev
);
10961 val
= AtapiRegCheckDevLunValue(
10962 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10965 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10967 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10968 swprintf(namex
, L
"Parameters%s", namev
);
10969 val
= AtapiRegCheckDevLunValue(
10970 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10972 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10973 swprintf(namex
, L
"Parameters%s", namev
);
10974 val
= AtapiRegCheckDevLunValue(
10975 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10980 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10983 } // end AtapiRegCheckDevValue()
10986 The user must specify that Xxx is to run on the platform
10987 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10988 Services\UniATA\Xxx:REG_DWORD:Zzz.
10990 The user can override the global setting to enable or disable Xxx on a
10991 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10992 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10994 If this registry value does not exist or contains the value zero then
10995 the timer to check for media change does not run.
10999 RegistryPath - pointer to the unicode string inside
11000 ...\CurrentControlSet\Services\UniATA
11001 DeviceNumber - The number of the HBA device object
11003 Returns: Registry Key value
11007 AtapiRegCheckParameterValue(
11008 IN PVOID HwDeviceExtension
,
11009 IN PCWSTR PathSuffix
,
11014 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
11016 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11018 LONG zero
= Default
;
11020 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
11023 LONG doRun
= Default
;
11025 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
11027 UNICODE_STRING paramPath
;
11029 // <SavedRegPath>\<PathSuffix> -> <Name>
11030 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
11031 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
11033 paramPath
.Length
= 0;
11034 paramPath
.MaximumLength
= RegistryPath
->Length
+
11035 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
11036 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
11037 if(!paramPath
.Buffer
) {
11038 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
11042 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
11043 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
11044 RtlAppendUnicodeToString(¶mPath
, L
"\\");
11045 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
11047 // Check for the Xxx value.
11048 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
11050 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
11051 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
11052 parameters
[0].EntryContext
= &doRun
;
11053 parameters
[0].DefaultType
= REG_DWORD
;
11054 parameters
[0].DefaultData
= &zero
;
11055 parameters
[0].DefaultLength
= sizeof(ULONG
);
11057 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
11058 paramPath
.Buffer
, parameters
, NULL
, NULL
);
11059 if(NT_SUCCESS(status
)) {
11060 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
11063 ExFreePool(paramPath
.Buffer
);
11065 if(!NT_SUCCESS(status
)) {
11071 #undef ITEMS_TO_QUERY
11073 } // end AtapiRegCheckParameterValue()
11076 SCSI_ADAPTER_CONTROL_STATUS
11078 AtapiAdapterControl(
11079 IN PVOID HwDeviceExtension
,
11080 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
11081 IN PVOID Parameters
11084 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11085 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
11086 ULONG numberChannels
= deviceExtension
->NumberChannels
;
11090 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
11092 switch(ControlType
) {
11093 case ScsiQuerySupportedControlTypes
: {
11094 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
11095 TRUE
, // ScsiQuerySupportedControlTypes
11096 TRUE
, // ScsiStopAdapter
11097 TRUE
, // ScsiRestartAdapter
11098 FALSE
, // ScsiSetBootConfig
11099 FALSE
// ScsiSetRunningConfig
11102 ULONG lim
= ScsiAdapterControlMax
;
11105 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
11107 if(pControlTypeList
->MaxControlType
< lim
) {
11108 lim
= pControlTypeList
->MaxControlType
;
11111 for(i
= 0; i
< lim
; i
++) {
11112 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
11118 case ScsiStopAdapter
: {
11120 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
11121 // Shut down all interrupts on the adapter. They'll get re-enabled
11122 // by the initialization routines.
11123 for (c
= 0; c
< numberChannels
; c
++) {
11124 AtapiResetController(deviceExtension
, c
);
11125 AtapiDisableInterrupts(deviceExtension
, c
);
11127 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
11128 // we must never get here for non-PCI
11129 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
11130 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
11134 case ScsiRestartAdapter
: {
11136 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
11137 // Enable all the interrupts on the adapter while port driver call
11138 // for power up an HBA that was shut down for power management
11140 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
11141 status
= UniataConnectIntr2(HwDeviceExtension
);
11142 if(NT_SUCCESS(status
)) {
11143 for (c
= 0; c
< numberChannels
; c
++) {
11144 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
11145 FindDevices(HwDeviceExtension
, 0, c
);
11146 AtapiEnableInterrupts(deviceExtension
, c
);
11147 AtapiHwInitialize__(deviceExtension
, c
);
11149 if(deviceExtension
->Isr2DevObj
) {
11150 // we must never get here for non-PCI
11151 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
11159 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
11160 return ScsiAdapterControlUnsuccessful
;
11164 return ScsiAdapterControlSuccess
;
11165 } // end AtapiAdapterControl()
11167 #endif //UNIATA_CORE
11177 #define DEBUG_MSG_BUFFER_SIZE 512
11188 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
11189 // UNICODE_STRING msgBuff;
11191 va_start(ap
, DebugMessage
);
11193 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
11195 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
11197 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
11198 HalDisplayString(dbg_print_tmp_buff
);
11201 if(g_LogToDisplay
> 1) {
11202 AtapiStallExecution(g_LogToDisplay
*1000);
11208 } // end PrintNtConsole()