3 Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2) 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 BOOLEAN g_opt_AtapiSendDisableIntr
= 1; // 0
90 BOOLEAN g_opt_AtapiDmaRawRead
= 1; // 0
92 ULONG g_opt_VirtualMachine
= 0; // Auto
94 BOOLEAN InDriverEntry
= TRUE
;
96 BOOLEAN g_opt_Verbose
= 0;
98 BOOLEAN WinVer_WDM_Model
= FALSE
;
100 //UCHAR EnableDma = FALSE;
101 //UCHAR EnableReorder = FALSE;
107 AtapiResetController__(
108 IN PVOID HwDeviceExtension
,
110 IN UCHAR CompleteType
116 IN PHW_DEVICE_EXTENSION deviceExtension
,
120 #define RESET_COMPLETE_CURRENT 0x00
121 #define RESET_COMPLETE_ALL 0x01
122 #define RESET_COMPLETE_NONE 0x02
129 IN PVOID HwDeviceExtension
132 #ifdef UNIATA_USE_XXableInterrupts
133 #define RETTYPE_XXableInterrupts BOOLEAN
134 #define RETVAL_XXableInterrupts TRUE
136 #define RETTYPE_XXableInterrupts VOID
137 #define RETVAL_XXableInterrupts
140 RETTYPE_XXableInterrupts
143 IN PVOID HwDeviceExtension
146 RETTYPE_XXableInterrupts
148 AtapiEnableInterrupts__(
149 IN PVOID HwDeviceExtension
155 IN PVOID HwDeviceExtension
,
157 IN PHW_TIMER HwScsiTimer
,
158 IN ULONG MiniportTimerValue
161 SCSI_ADAPTER_CONTROL_STATUS
164 IN PVOID HwDeviceExtension
,
165 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
175 AtapiRegGetStringParameterValue(
176 IN PWSTR RegistryPath
,
182 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
184 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
189 ustr
.MaximumLength
= (USHORT
)MaxLen
;
190 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
192 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
193 parameters
[0].Name
= Name
;
194 parameters
[0].EntryContext
= &ustr
;
195 parameters
[0].DefaultType
= REG_SZ
;
196 parameters
[0].DefaultData
= Str
;
197 parameters
[0].DefaultLength
= MaxLen
;
199 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
200 RegistryPath
, parameters
, NULL
, NULL
);
202 if(!NT_SUCCESS(status
))
207 #undef ITEMS_TO_QUERY
208 } // end AtapiRegGetStringParameterValue()
226 if(!nano
|| !g_Perf
|| !g_PerfDt
)
228 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
233 KeQuerySystemTime(&t0
);
236 } // end UniataNanoSleep()
238 #define AtapiWritePortN_template(_type, _Type, sz) \
241 AtapiWritePort##sz( \
242 IN PHW_CHANNEL chan, \
243 IN ULONGIO_PTR _port, \
248 if(_port >= IDX_MAX_REG) { \
249 res = (PIORES)(_port); \
252 res = &chan->RegTranslation[_port]; \
254 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
260 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
262 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
263 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
268 AtapiWritePortN_template(ULONG
, Ulong
, 4);
269 AtapiWritePortN_template(USHORT
, Ushort
, 2);
270 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
272 #define AtapiWritePortExN_template(_type, _Type, sz) \
275 AtapiWritePortEx##sz( \
276 IN PHW_CHANNEL chan, \
277 IN ULONGIO_PTR _port, \
283 if(_port >= IDX_MAX_REG) { \
284 res = (PIORES)(_port); \
287 res = &chan->RegTranslation[_port]; \
289 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
295 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
297 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
298 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
303 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
304 //AtapiWritePortExN_template(USHORT, Ushort, 2);
305 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
307 #define AtapiReadPortN_template(_type, _Type, sz) \
311 IN PHW_CHANNEL chan, \
312 IN ULONGIO_PTR _port \
316 if(_port >= IDX_MAX_REG) { \
317 res = (PIORES)(_port); \
320 res = &chan->RegTranslation[_port]; \
322 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
323 return (_type)(-1); \
329 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
330 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
332 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
333 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
337 AtapiReadPortN_template(ULONG
, Ulong
, 4);
338 AtapiReadPortN_template(USHORT
, Ushort
, 2);
339 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
341 #define AtapiReadPortExN_template(_type, _Type, sz) \
344 AtapiReadPortEx##sz( \
345 IN PHW_CHANNEL chan, \
346 IN ULONGIO_PTR _port, \
351 if(_port >= IDX_MAX_REG) { \
352 res = (PIORES)(_port); \
355 res = &chan->RegTranslation[_port]; \
357 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
358 return (_type)(-1); \
364 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
366 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
367 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
371 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
372 //AtapiReadPortExN_template(USHORT, Ushort, 2);
373 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
375 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
378 AtapiReadBuffer##sz( \
379 IN PHW_CHANNEL chan, \
380 IN ULONGIO_PTR _port, \
390 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
392 Buffer = ((_type*)Buffer)+1; \
393 UniataNanoSleep(Timing); \
398 if(_port >= IDX_MAX_REG) { \
399 res = (PIORES)(_port); \
402 res = &chan->RegTranslation[_port]; \
404 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
408 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
409 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
413 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
415 Buffer = ((_type*)Buffer)+1; \
420 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
423 AtapiWriteBuffer##sz( \
424 IN PHW_CHANNEL chan, \
425 IN ULONGIO_PTR _port, \
435 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
436 Buffer = ((_type*)Buffer)+1; \
438 UniataNanoSleep(Timing); \
443 if(_port >= IDX_MAX_REG) { \
444 res = (PIORES)(_port); \
447 res = &chan->RegTranslation[_port]; \
449 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
453 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
454 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
458 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
460 Buffer = ((_type*)Buffer)+1; \
465 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
466 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
468 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
469 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
481 WaitOnBusyLong(chan
);
482 for (i
= 0; i
< 0x10000; i
++) {
484 GetStatus(chan
, statusByte
);
485 if (statusByte
& IDE_STATUS_DRQ
) {
486 // Suck out any remaining bytes and throw away.
487 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
493 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
496 } // AtapiSuckPort2()
506 for (i
=0; i
<200; i
++) {
507 GetStatus(chan
, Status
);
508 if (Status
& IDE_STATUS_BUSY
) {
509 AtapiStallExecution(10);
516 } // end WaitOnBusy()
527 Status
= WaitOnBusy(chan
);
528 if(!(Status
& IDE_STATUS_BUSY
))
530 for (i
=0; i
<2000; i
++) {
531 GetStatus(chan
, Status
);
532 if (Status
& IDE_STATUS_BUSY
) {
533 AtapiStallExecution(250);
540 } // end WaitOnBusyLong()
550 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
551 GetBaseStatus(chan
, Status
);
552 if (Status
& IDE_STATUS_BUSY
) {
553 AtapiStallExecution(g_opt_WaitBusyDelay
);
560 } // end WaitOnBaseBusy()
571 Status
= WaitOnBaseBusy(chan
);
572 if(!(Status
& IDE_STATUS_BUSY
))
574 for (i
=0; i
<2000; i
++) {
575 GetBaseStatus(chan
, Status
);
576 if (Status
& IDE_STATUS_BUSY
) {
577 AtapiStallExecution(250);
584 } // end WaitOnBaseBusyLong()
589 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
598 if(Status
& IDE_STATUS_BUSY
) {
601 // if(deviceExtension->HwFlags & UNIATA_SATA) {
602 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
603 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
607 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
608 if ((Status
& IDE_STATUS_BUSY
) ||
609 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
613 return IDE_STATUS_IDLE
;
614 } // end UniataIsIdle()
625 for (i
=0; i
<20000; i
++) {
626 GetStatus(chan
, Status
);
627 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
628 if(Status2
== 0xff) {
632 if(Status2
& IDE_STATUS_BUSY
) {
633 AtapiStallExecution(10);
640 } // end WaitForIdleLong()
650 for (i
=0; i
<1000; i
++) {
651 GetStatus(chan
, Status
);
652 if (Status
& IDE_STATUS_BUSY
) {
653 AtapiStallExecution(g_opt_WaitDrqDelay
);
654 } else if (Status
& IDE_STATUS_DRQ
) {
657 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
661 } // end WaitForDrq()
671 for (i
=0; i
<2; i
++) {
672 GetStatus(chan
, Status
);
673 if (Status
& IDE_STATUS_BUSY
) {
674 AtapiStallExecution(g_opt_WaitDrqDelay
);
675 } else if (Status
& IDE_STATUS_DRQ
) {
678 AtapiStallExecution(g_opt_WaitDrqDelay
);
682 } // end WaitShortForDrq()
691 //ULONG c = chan->lChannel;
693 UCHAR dma_status
= 0;
694 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
697 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
698 UniataAhciSoftReset(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
);
702 GetBaseStatus(chan
, statusByte2
);
703 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
704 SelectDrive(chan
, DeviceNumber
);
705 AtapiStallExecution(500);
706 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
708 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
709 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
710 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
711 // implementation. (which is around 1 second)
712 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
715 AtapiStallExecution(30);
718 SelectDrive(chan
, DeviceNumber
);
720 GetBaseStatus(chan
, statusByte2
);
721 AtapiStallExecution(500);
723 GetBaseStatus(chan
, statusByte2
);
724 if(chan
&& chan
->DeviceExtension
) {
725 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
726 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
728 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
730 if(dma_status
& BM_STATUS_INTR
) {
731 // bullshit, we have DMA interrupt, but had never initiate DMA operation
732 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
733 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
734 GetBaseStatus(chan
, statusByte2
);
736 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
737 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
738 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
739 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
744 } // end AtapiSoftReset()
747 Send command to device.
748 Translate to 48-Lba form if required
753 IN PHW_DEVICE_EXTENSION deviceExtension
,
754 IN ULONG DeviceNumber
,
763 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
768 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
769 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
771 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
772 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
774 KdPrint3((" (ahci)\n"));
776 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
778 if(!UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
779 &(AHCI_CMD
->cfis
[0]),
788 if(UniataAhciSendCommand(deviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == 0xff) {
789 KdPrint2((" timeout\n"));
792 return IDE_STATUS_IDLE
;
795 SelectDrive(chan
, DeviceNumber
);
797 statusByte
= WaitOnBusy(chan
);
799 /* ready to issue command ? */
800 if (statusByte
& IDE_STATUS_BUSY
) {
801 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
804 // !!! We should not check ERROR condition here
805 // ERROR bit may be asserted durring previous operation
806 // and not cleared after SELECT
808 //>>>>>> NV: 2006/08/03
809 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
810 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
811 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
812 return IDE_STATUS_ERROR
;
813 //return SRB_STATUS_ERROR;
815 //<<<<<< NV: 2006/08/03
817 /* only use 48bit addressing if needed because of the overhead */
818 if (UniAta_need_lba48(command
, lba
, count
,
819 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
821 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
822 /* translate command into 48bit version */
823 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
824 command
= AtaCommands48
[command
];
826 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
830 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
833 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
834 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
835 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
836 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
837 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
838 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
839 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
840 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
841 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
842 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
844 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
845 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
848 plba
= (PUCHAR
)&lba
; //ktp
849 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
852 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
853 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
855 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
856 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
857 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
858 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
859 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
860 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
861 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
863 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
864 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
868 // write command code to device
869 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
874 // caller requested wait for interrupt
877 statusByte
= WaitForDrq(chan
);
878 if (statusByte
& IDE_STATUS_DRQ
)
880 AtapiStallExecution(500);
881 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
888 // caller requested wait for entering Wait state
889 for (i
=0; i
<30 * 1000; i
++) {
891 GetStatus(chan
, statusByte
);
892 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
893 if(statusByte
== 0xff) {
897 if(statusByte
& IDE_STATUS_ERROR
) {
900 if(statusByte
& IDE_STATUS_BUSY
) {
901 AtapiStallExecution(100);
904 if(statusByte
== IDE_STATUS_IDLE
) {
907 //if(deviceExtension->HwFlags & UNIATA_SATA) {
908 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
911 AtapiStallExecution(100);
914 //statusByte |= IDE_STATUS_BUSY;
918 statusByte
= WaitOnBusyLong(chan
);
920 case ATA_WAIT_BASE_READY
:
921 statusByte
= WaitOnBaseBusyLong(chan
);
924 GetStatus(chan
, statusByte
);
925 if (statusByte
& IDE_STATUS_ERROR
) {
926 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
927 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
930 KdPrint2((PRINT_PREFIX
" try to continue\n"));
931 statusByte
&= ~IDE_STATUS_ERROR
;
933 chan
->ExpectingInterrupt
= TRUE
;
935 InterlockedExchange(&(chan
->CheckIntr
),
941 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
944 } // end AtaCommand48()
947 Send command to device.
948 This is simply wrapper for AtaCommand48()
953 IN PHW_DEVICE_EXTENSION deviceExtension
,
954 IN ULONG DeviceNumber
,
965 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
966 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
968 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
969 count
, feature
, flags
);
971 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
972 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
974 KdPrint3(("AtaCommand(ahci)\n"));
976 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
978 if(!UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
979 &(AHCI_CMD
->cfis
[0]),
981 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
988 if(UniataAhciSendCommand(deviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == 0xff) {
989 KdPrint2((" timeout\n"));
992 return IDE_STATUS_IDLE
;
994 } // end AtaCommand()
998 AtaPio2Mode(LONG pio
)
1001 default: return ATA_PIO
;
1002 case 0: return ATA_PIO0
;
1003 case 1: return ATA_PIO1
;
1004 case 2: return ATA_PIO2
;
1005 case 3: return ATA_PIO3
;
1006 case 4: return ATA_PIO4
;
1007 case 5: return ATA_PIO5
;
1009 } // end AtaPio2Mode()
1013 AtaPioMode(PIDENTIFY_DATA2 ident
)
1015 if (ident
->PioTimingsValid
) {
1016 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1018 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1020 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1023 if (ident
->PioCycleTimingMode
== 2)
1025 if (ident
->PioCycleTimingMode
== 1)
1027 if (ident
->PioCycleTimingMode
== 0)
1030 } // end AtaPioMode()
1034 AtaWmode(PIDENTIFY_DATA2 ident
)
1036 if (ident
->MultiWordDMASupport
& 0x04)
1038 if (ident
->MultiWordDMASupport
& 0x02)
1040 if (ident
->MultiWordDMASupport
& 0x01)
1047 AtaUmode(PIDENTIFY_DATA2 ident
)
1049 if (!ident
->UdmaModesValid
)
1051 if (ident
->UltraDMASupport
& 0x40)
1053 if (ident
->UltraDMASupport
& 0x20)
1055 if (ident
->UltraDMASupport
& 0x10)
1057 if (ident
->UltraDMASupport
& 0x08)
1059 if (ident
->UltraDMASupport
& 0x04)
1061 if (ident
->UltraDMASupport
& 0x02)
1063 if (ident
->UltraDMASupport
& 0x01)
1074 IN PVOID HwDeviceExtension
1077 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1078 PHW_TIMER HwScsiTimer
;
1080 ULONG MiniportTimerValue
;
1081 BOOLEAN recall
= FALSE
;
1085 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1087 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1088 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1089 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1092 chan
= &deviceExtension
->chan
[lChannel
];
1096 HwScsiTimer
= chan
->HwScsiTimer
;
1097 chan
->HwScsiTimer
= NULL
;
1099 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1100 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1104 HwScsiTimer(HwDeviceExtension
);
1106 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1108 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1109 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1110 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1111 deviceExtension
->FirstDpcChan
=
1112 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1116 KeQuerySystemTime(&time
);
1117 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1119 chan
= &deviceExtension
->chan
[lChannel
];
1120 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1122 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1123 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1130 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1131 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1132 if(!MiniportTimerValue
)
1133 MiniportTimerValue
= 1;
1135 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1136 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1143 } // end AtapiTimerDpc()
1146 Wrapper for ScsiPort, that implements smart Dpc
1147 queueing. We need it to allow parallel functioning
1148 of IDE channles with shared interrupt. Standard Dpc mechanism
1149 cancels previous Dpc request (if any), but we need Dpc queue.
1154 IN PVOID HwDeviceExtension
,
1156 IN PHW_TIMER HwScsiTimer
,
1157 IN ULONG MiniportTimerValue
1160 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1162 LARGE_INTEGER time2
;
1164 PHW_CHANNEL prev_chan
;
1166 // BOOLEAN UseRequestTimerCall = TRUE;
1168 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1169 KeQuerySystemTime(&time
);
1171 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1172 time
.QuadPart
+= MiniportTimerValue
*10;
1173 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1175 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1177 i
= deviceExtension
->FirstDpcChan
;
1178 chan
= prev_chan
= NULL
;
1179 while(i
!= CHAN_NOT_SPECIFIED
) {
1181 chan
= &deviceExtension
->chan
[i
];
1182 if(chan
->DpcTime
> time
.QuadPart
) {
1185 i
= chan
->NextDpcChan
;
1187 chan
= &deviceExtension
->chan
[lChannel
];
1189 deviceExtension
->FirstDpcChan
= lChannel
;
1191 prev_chan
->NextDpcChan
= lChannel
;
1193 chan
->NextDpcChan
= i
;
1194 chan
->HwScsiTimer
= HwScsiTimer
;
1195 chan
->DpcTime
= time
.QuadPart
;
1197 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1198 if(time
.QuadPart
<= time2
.QuadPart
) {
1199 MiniportTimerValue
= 1;
1201 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1204 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1205 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1207 MiniportTimerValue
);
1209 } // end AtapiQueueTimerDpc()
1211 #endif //UNIATA_CORE
1220 UCHAR statusByteAlt
;
1222 GetStatus(chan
, statusByteAlt
);
1223 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1225 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1226 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1227 KdPrint2((PRINT_PREFIX
1228 " Reg_%#x (%#x) = %#x\n",
1230 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1233 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1234 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1235 KdPrint2((PRINT_PREFIX
1236 " BM_%#x (%#x) = %#x\n",
1238 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1242 } // end UniataDumpATARegs()
1246 Routine Description:
1248 Issue IDENTIFY command to a device.
1252 HwDeviceExtension - HBA miniport driver's adapter data storage
1253 DeviceNumber - Indicates which device.
1254 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1258 TRUE if all goes well.
1264 IN PVOID HwDeviceExtension
,
1265 IN ULONG DeviceNumber
,
1271 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1272 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1273 ULONG waitCount
= 50000;
1279 BOOLEAN atapiDev
= FALSE
;
1280 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1282 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1283 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1286 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1290 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1291 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1294 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1295 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1299 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
1300 statusByte
= WaitOnBusyLong(chan
);
1302 SelectDrive(chan
, DeviceNumber
);
1303 AtapiStallExecution(10);
1304 statusByte
= WaitOnBusyLong(chan
);
1305 // Check that the status register makes sense.
1306 GetBaseStatus(chan
, statusByte2
);
1308 UniataDumpATARegs(chan
);
1311 if (Command
== IDE_COMMAND_IDENTIFY
) {
1312 // Mask status byte ERROR bits.
1313 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1314 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1315 // Check if register value is reasonable.
1317 if(statusByte
!= IDE_STATUS_IDLE
) {
1319 // No reset here !!!
1320 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1322 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1323 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1324 SelectDrive(chan
, DeviceNumber
);
1325 WaitOnBusyLong(chan
);
1327 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1328 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1330 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1331 signatureHigh
== ATAPI_MAGIC_MSB
) {
1333 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1337 // We really should wait up to 31 seconds
1338 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1339 // (30 seconds for device 1)
1341 // Wait for Busy to drop.
1342 AtapiStallExecution(100);
1343 GetStatus(chan
, statusByte
);
1345 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1346 GetBaseStatus(chan
, statusByte2
);
1348 SelectDrive(chan
, DeviceNumber
);
1350 GetBaseStatus(chan
, statusByte2
);
1352 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1354 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1355 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1357 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1358 signatureHigh
== ATAPI_MAGIC_MSB
) {
1359 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1364 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1365 if (statusByte
!= IDE_STATUS_IDLE
) {
1367 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1372 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1373 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1374 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1375 statusByte
= WaitForIdleLong(chan
);
1376 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1381 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1382 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1383 j
= 4; // skip old-style checks
1387 for (; j
< 4*2; j
++) {
1388 // Send IDENTIFY command.
1389 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1392 if (statusByte
& IDE_STATUS_DRQ
) {
1393 // Read status to acknowledge any interrupts generated.
1394 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1395 GetBaseStatus(chan
, statusByte
);
1396 // One last check for Atapi.
1397 if (Command
== IDE_COMMAND_IDENTIFY
) {
1398 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1399 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1401 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1402 signatureHigh
== ATAPI_MAGIC_MSB
) {
1403 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1410 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1411 if (Command
== IDE_COMMAND_IDENTIFY
) {
1412 // Check the signature. If DRQ didn't come up it's likely Atapi.
1413 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1414 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1416 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1417 signatureHigh
== ATAPI_MAGIC_MSB
) {
1419 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1423 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1424 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1428 // Device didn't respond correctly. It will be given one more chances.
1429 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1430 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1431 GetBaseStatus(chan
, statusByte
);
1432 AtapiSoftReset(chan
,DeviceNumber
);
1434 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1435 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1437 GetBaseStatus(chan
, statusByte
);
1438 //GetStatus(chan, statusByte);
1439 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1442 // Check for error on really stupid master devices that assert random
1443 // patterns of bits in the status register at the slave address.
1444 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1445 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1449 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1450 // Suck out 256 words. After waiting for one model that asserts busy
1451 // after receiving the Packet Identify command.
1452 statusByte
= WaitForDrq(chan
);
1453 statusByte
= WaitOnBusyLong(chan
);
1454 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1456 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1457 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1458 GetBaseStatus(chan
, statusByte
);
1461 GetBaseStatus(chan
, statusByte
);
1462 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1464 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1466 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1470 // ATI/SII chipsets with memory-mapped IO hangs when
1471 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1472 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1473 KdPrint2((PRINT_PREFIX
1474 " IO_%#x (%#x), %s:\n",
1476 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1477 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1478 for(i
=0; i
<256; i
++) {
1480 KdPrint2((PRINT_PREFIX
1483 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1485 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1486 KdPrint2((PRINT_PREFIX
1488 AtapiStallExecution(1);
1489 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1492 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1494 // Work around for some IDE and one model Atapi that will present more than
1495 // 256 bytes for the Identify data.
1496 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1497 statusByte
= AtapiSuckPort2(chan
);
1499 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1500 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1503 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1504 statusByte
= WaitForDrq(chan
);
1505 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1506 GetBaseStatus(chan
, statusByte
);
1508 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1511 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1515 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1516 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1517 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1518 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1519 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1520 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1522 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1523 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1524 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1525 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1527 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1529 // Check out a few capabilities / limitations of the device.
1530 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1531 // Determine if this drive supports the MSN functions.
1532 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1534 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1535 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1537 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1538 // Determine max. block transfer for this device.
1539 LunExt
->MaximumBlockXfer
=
1540 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1542 LunExt
->NumOfSectors
= 0;
1543 if (Command
== IDE_COMMAND_IDENTIFY
) {
1544 ULONGLONG NumOfSectors
=0;
1545 ULONGLONG NativeNumOfSectors
=0;
1546 ULONGLONG cylinders
=0;
1547 ULONGLONG tmp_cylinders
=0;
1548 // Read very-old-style drive geometry
1549 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1550 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1551 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1552 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1554 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1555 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1556 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1557 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1558 // Check for HDDs > 8Gb
1559 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1560 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1561 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1562 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1564 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1565 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1566 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1568 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1570 NumOfSectors
= cylinders
*
1571 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1572 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1574 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1578 // Check for LBA mode
1579 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1580 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1581 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1582 if ( deviceExtension
->FullIdentifyData
.SupportLba
1584 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1585 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1586 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1587 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1588 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1590 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1591 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1592 goto skip_lba_staff
;
1594 // Check for LBA48 support
1595 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1596 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1597 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1598 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1600 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1602 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1603 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1604 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1606 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1608 NativeNumOfSectors
= cylinders
*
1609 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1610 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1612 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1614 if(NativeNumOfSectors
> NumOfSectors
) {
1615 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1616 NumOfSectors
= NativeNumOfSectors
;
1620 // Check drive capacity report for LBA48-capable drives.
1621 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1622 ULONG hNativeNumOfSectors
;
1623 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1625 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1626 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1628 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1629 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1630 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1631 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1633 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1636 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1637 NativeNumOfSectors
|=
1638 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1639 hNativeNumOfSectors
=
1640 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1641 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1642 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1644 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1646 // Some drives report LBA48 capability while has capacity below 128Gb
1647 // Probably they support large block-counters.
1648 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1649 // Here we check this
1650 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1651 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1653 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1654 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1656 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1657 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1658 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1659 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1660 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1661 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1662 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1666 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1667 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1668 NativeNumOfSectors
= 0;
1672 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1673 NativeNumOfSectors
> NumOfSectors
) {
1675 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1676 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1678 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1679 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1680 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1681 NumOfSectors
= NativeNumOfSectors
;
1687 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1688 // check for native LBA size
1689 // some drives report ~32Gb in Identify Block
1690 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1692 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1693 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1695 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1696 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1697 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1698 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1699 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1701 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1703 if(NativeNumOfSectors
> NumOfSectors
) {
1705 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1706 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1708 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1709 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1710 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1711 NumOfSectors
= NativeNumOfSectors
;
1717 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1719 // fill IdentifyData with bogus geometry
1720 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1721 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1722 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1723 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1724 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1725 // ok, we can keep original values
1726 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1727 LunExt
->opt_GeomType
= GEOM_ORIG
;
1730 tmp_cylinders
= NumOfSectors
/ (255*63);
1731 if(tmp_cylinders
< 0xffff) {
1732 // we can use generic values for H/S for generic geometry approach
1733 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1734 LunExt
->opt_GeomType
= GEOM_STD
;
1737 // we should use UNIATA geometry approach
1738 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1739 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1743 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1745 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1746 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1747 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1749 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1750 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1752 cylinders
= NumOfSectors
/ (255*63);
1753 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1755 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1756 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1758 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1759 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1760 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1762 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1764 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1765 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1766 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1768 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1770 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1771 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1772 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1774 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1776 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1777 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1778 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1780 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1781 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1782 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1785 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1786 cylinders
= tmp_cylinders
;
1788 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1789 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1793 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1794 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1795 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1797 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1798 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1799 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1801 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1802 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1803 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1807 LunExt
->NumOfSectors
= NumOfSectors
;
1808 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1809 deviceExtension->FullIdentifyData.DoubleWordIo) {
1810 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1814 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1815 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1817 InitBadBlocks(LunExt
);
1819 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1820 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1822 // This device interrupts with the assertion of DRQ after receiving
1823 // Atapi Packet Command
1824 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1825 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1828 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1831 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1833 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1835 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1836 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1838 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1839 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1840 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1841 // set CD default costs
1842 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1843 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1844 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1845 statusByte
= WaitForDrq(chan
);
1847 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1848 LunExt
->IdentifyData
.DeviceType
));
1851 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1854 GetBaseStatus(chan
, statusByte
);
1855 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1858 } // end IssueIdentify()
1863 Routine Description:
1864 Set drive parameters using the IDENTIFY data.
1867 HwDeviceExtension - HBA miniport driver's adapter data storage
1868 DeviceNumber - Indicates which device.
1871 TRUE if all goes well.
1877 IN PVOID HwDeviceExtension
,
1878 IN ULONG DeviceNumber
,
1882 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1883 PIDENTIFY_DATA2 identifyData
;
1884 PHW_LU_EXTENSION LunExt
;
1889 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
1890 identifyData
= &(LunExt
->IdentifyData
);
1892 if(LunExt
->DeviceFlags
&
1893 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1896 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1897 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1899 // Send SET PARAMETER command.
1900 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1901 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1902 (identifyData
->NumberOfHeads
- 1), 0,
1903 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1905 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1906 if(statusByte
& IDE_STATUS_ERROR
) {
1907 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1908 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1909 errorByte
, statusByte
));
1913 if(statusByte
== IDE_STATUS_IDLE
) {
1919 } // end SetDriveParameters()
1924 PHW_LU_EXTENSION LunExt
1927 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
1928 } // end UniataForgetDevice()
1933 Routine Description:
1934 Reset IDE controller and/or Atapi device.
1937 HwDeviceExtension - HBA miniport driver's adapter data storage
1946 AtapiResetController(
1947 IN PVOID HwDeviceExtension
,
1951 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1952 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1953 } // end AtapiResetController()
1958 AtapiResetController__(
1959 IN PVOID HwDeviceExtension
,
1961 IN BOOLEAN CompleteType
1964 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1965 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1966 PHW_CHANNEL chan
= NULL
;
1970 PSCSI_REQUEST_BLOCK CurSrb
;
1971 ULONG ChannelCtrlFlags
;
1972 UCHAR dma_status
= 0;
1974 ULONG slotNumber
= deviceExtension
->slotNumber
;
1975 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1976 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1978 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1980 //ULONG RevID = deviceExtension->RevID;
1981 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1985 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1987 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
1988 // we shall reset both channels on SimplexOnly devices,
1989 // It's not worth doing so on normal controllers
1991 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
1994 numberChannels
= deviceExtension
->NumberChannels
;
1997 for (; j
< numberChannels
; j
++) {
1999 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
2000 chan
= &deviceExtension
->chan
[j
];
2001 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
2002 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2003 MaxLuns
= chan
->NumberLuns
;
2004 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2006 while((CurSrb
= UniataGetCurRequest(chan
))) {
2008 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2010 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
2011 // Check and see if we are processing an internal srb
2012 if (AtaReq
->OriginalSrb
) {
2013 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2014 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2015 AtaReq
->OriginalSrb
= NULL
;
2016 // NOTE: internal SRB doesn't get to SRB queue !!!
2017 CurSrb
= AtaReq
->Srb
;
2020 // Remove current request from queue
2021 UniataRemoveRequest(chan
, CurSrb
);
2023 // Check if request is in progress.
2024 ASSERT(AtaReq
->Srb
== CurSrb
);
2026 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2027 UCHAR PathId
= CurSrb
->PathId
;
2028 UCHAR TargetId
= CurSrb
->TargetId
;
2029 UCHAR Lun
= CurSrb
->Lun
;
2031 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2032 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2034 if (CurSrb
->SenseInfoBuffer
) {
2036 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2038 senseBuffer
->ErrorCode
= 0x70;
2039 senseBuffer
->Valid
= 1;
2040 senseBuffer
->AdditionalSenseLength
= 0xb;
2041 if(CompleteType
== RESET_COMPLETE_ALL
) {
2042 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2043 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2044 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2045 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2047 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2048 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2049 senseBuffer
->AdditionalSenseCode
= 0;
2050 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2054 // Clear request tracking fields.
2055 AtaReq
->WordsLeft
= 0;
2056 AtaReq
->DataBuffer
= NULL
;
2057 AtaReq
->TransferLength
= 0;
2059 ScsiPortNotification(RequestComplete
,
2063 // Indicate ready for next request.
2064 ScsiPortNotification(NextLuRequest
,
2070 if(CompleteType
!= RESET_COMPLETE_ALL
)
2073 #endif //UNIATA_CORE
2074 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2076 // Save control flags
2077 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2078 // Clear expecting interrupt flag.
2079 chan
->ExpectingInterrupt
= FALSE
;
2081 chan
->ChannelCtrlFlags
= 0;
2082 InterlockedExchange(&(chan
->CheckIntr
),
2086 if(ChipFlags
& UNIATA_AHCI
) {
2087 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2088 UniataAhciReset(HwDeviceExtension
, j
);
2090 KdPrint2((PRINT_PREFIX
" ATA path\n"));
2091 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2092 AtapiDisableInterrupts(deviceExtension
, j
);
2093 KdPrint2((PRINT_PREFIX
" done\n"));
2095 case ATA_INTEL_ID
: {
2098 if(!(ChipFlags
& UNIATA_SATA
))
2100 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2105 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2106 if(ChipFlags
& UNIATA_AHCI
) {
2109 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2110 GetPciConfig1(0x90, tmp8
);
2118 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2120 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2123 ChangePciConfig2(0x92, a
& ~mask
);
2124 AtapiStallExecution(10);
2125 ChangePciConfig2(0x92, a
| mask
);
2128 /* Wait up to 1 sec for "connect well". */
2129 if (ChipFlags
& (I6CH
| I6CH2
))
2135 AtapiStallExecution(10000);
2136 GetPciConfig2(0x92, tmp16
);
2137 if ((tmp16
& mask
) == mask
) {
2138 AtapiStallExecution(10000);
2144 case ATA_NVIDIA_ID
: {
2145 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2146 if(!(ChipFlags
& UNIATA_SATA
))
2149 case ATA_SILICON_IMAGE_ID
: {
2151 ULONG Channel
= deviceExtension
->Channel
+ j
;
2152 if(!(ChipFlags
& UNIATA_SATA
))
2154 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2155 /* disable PHY state change interrupt */
2156 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2158 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2160 /* reset controller part for this channel */
2161 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2162 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2163 AtapiStallExecution(1000);
2164 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2165 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2169 case ATA_PROMISE_ID
: {
2172 if(ChipFlags
& UNIATA_SATA
) {
2173 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2174 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2177 KdPrint2((PRINT_PREFIX
" send reset\n"));
2178 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2179 IDE_DC_RESET_CONTROLLER
);
2180 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2181 AtapiStallExecution(10000);
2182 // Disable interrupts
2183 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2184 AtapiDisableInterrupts(deviceExtension
, j
);
2185 AtapiStallExecution(100);
2186 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2187 AtapiEnableInterrupts(deviceExtension
, j
);
2188 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2189 AtapiStallExecution(100000);
2190 KdPrint2((PRINT_PREFIX
" done\n"));
2195 //if(!(ChipFlags & UNIATA_SATA)) {}
2196 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2197 // Reset DMA engine if active
2198 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2199 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2200 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2201 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2202 (dma_status
& BM_STATUS_INTR
)) {
2203 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2208 // all these shall be performed inside AtapiHwInitialize__() ?
2210 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2211 // Do special processing for ATAPI and IDE disk devices.
2212 for (i
= 0; i
< MaxLuns
; i
++) {
2214 // Check if device present.
2215 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2216 if(ChipFlags
& UNIATA_AHCI
) {
2217 // everything is done in UniataAhciReset()
2218 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2224 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2225 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2228 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2232 if(ChipFlags
& UNIATA_AHCI
) {
2233 // everything is done in UniataAhciReset()
2234 KdPrint2((PRINT_PREFIX
" found some device\n"));
2236 if(!IssueIdentify(HwDeviceExtension
,
2238 (chan
->lun
[i
]->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ?
2239 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2241 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2242 UniataForgetDevice(chan
->lun
[i
]);
2246 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2247 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2248 UniataForgetDevice(chan
->lun
[i
]);
2253 SelectDrive(chan
, i
);
2254 AtapiStallExecution(10);
2255 statusByte
= WaitOnBusyLong(chan
);
2256 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2257 if(statusByte
== 0xff) {
2258 KdPrint2((PRINT_PREFIX
2259 "no drive, status %#x\n",
2261 UniataForgetDevice(chan
->lun
[i
]);
2263 // Check for ATAPI disk.
2264 if (chan
->lun
[i
]->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2265 // Issue soft reset and issue identify.
2266 GetStatus(chan
, statusByte
);
2267 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2270 AtapiDisableInterrupts(deviceExtension
, j
);
2271 AtapiSoftReset(chan
, i
);
2272 AtapiEnableInterrupts(deviceExtension
, j
);
2274 GetStatus(chan
, statusByte
);
2276 if(statusByte
== IDE_STATUS_SUCCESS
) {
2278 IssueIdentify(HwDeviceExtension
,
2280 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2283 KdPrint2((PRINT_PREFIX
2284 "AtapiResetController: Status after soft reset %#x\n",
2287 GetBaseStatus(chan
, statusByte
);
2290 // Issue identify and reinit after channel reset.
2292 if (statusByte
!= IDE_STATUS_IDLE
&&
2293 statusByte
!= IDE_STATUS_SUCCESS
&&
2294 statusByte
!= IDE_STATUS_DRDY
) {
2296 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2298 if(!IssueIdentify(HwDeviceExtension
,
2300 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2302 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2304 // Set disk geometry parameters.
2305 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2306 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2308 GetBaseStatus(chan
, statusByte
);
2310 // force DMA mode reinit
2311 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2315 // Enable interrupts, note, the we can have here recursive disable
2316 AtapiStallExecution(10);
2317 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2319 chan
->DisableIntr
));
2320 AtapiEnableInterrupts(deviceExtension
, j
);
2322 // Call the HwInitialize routine to setup multi-block.
2323 AtapiHwInitialize__(deviceExtension
, j
);
2325 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2329 } // end AtapiResetController__()
2334 Routine Description:
2335 This routine maps ATAPI and IDE errors to specific SRB statuses.
2338 HwDeviceExtension - HBA miniport driver's adapter data storage
2339 Srb - IO request packet
2348 IN PVOID HwDeviceExtension
,
2349 IN PSCSI_REQUEST_BLOCK Srb
2352 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2353 ULONG lChannel
= GET_CHANNEL(Srb
);
2354 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2357 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2359 ULONG DeviceNumber
= GET_CDEV(Srb
);
2360 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2362 // Read the error register.
2364 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2365 KdPrint2((PRINT_PREFIX
2366 "MapError: Error register is %#x\n",
2369 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2371 switch (errorByte
>> 4) {
2372 case SCSI_SENSE_NO_SENSE
:
2374 KdPrint2((PRINT_PREFIX
2375 "ATAPI: No sense information\n"));
2376 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2377 srbStatus
= SRB_STATUS_ERROR
;
2380 case SCSI_SENSE_RECOVERED_ERROR
:
2382 KdPrint2((PRINT_PREFIX
2383 "ATAPI: Recovered error\n"));
2385 srbStatus
= SRB_STATUS_SUCCESS
;
2388 case SCSI_SENSE_NOT_READY
:
2390 KdPrint2((PRINT_PREFIX
2391 "ATAPI: Device not ready\n"));
2392 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2393 srbStatus
= SRB_STATUS_ERROR
;
2396 case SCSI_SENSE_MEDIUM_ERROR
:
2398 KdPrint2((PRINT_PREFIX
2399 "ATAPI: Media error\n"));
2400 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2401 srbStatus
= SRB_STATUS_ERROR
;
2404 case SCSI_SENSE_HARDWARE_ERROR
:
2406 KdPrint2((PRINT_PREFIX
2407 "ATAPI: Hardware error\n"));
2408 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2409 srbStatus
= SRB_STATUS_ERROR
;
2412 case SCSI_SENSE_ILLEGAL_REQUEST
:
2414 KdPrint2((PRINT_PREFIX
2415 "ATAPI: Illegal request\n"));
2416 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2417 srbStatus
= SRB_STATUS_ERROR
;
2420 case SCSI_SENSE_UNIT_ATTENTION
:
2422 KdPrint2((PRINT_PREFIX
2423 "ATAPI: Unit attention\n"));
2424 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2425 srbStatus
= SRB_STATUS_ERROR
;
2428 case SCSI_SENSE_DATA_PROTECT
:
2430 KdPrint2((PRINT_PREFIX
2431 "ATAPI: Data protect\n"));
2432 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2433 srbStatus
= SRB_STATUS_ERROR
;
2436 case SCSI_SENSE_BLANK_CHECK
:
2438 KdPrint2((PRINT_PREFIX
2439 "ATAPI: Blank check\n"));
2440 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2441 srbStatus
= SRB_STATUS_ERROR
;
2444 case SCSI_SENSE_ABORTED_COMMAND
:
2445 KdPrint2((PRINT_PREFIX
2446 "Atapi: Command Aborted\n"));
2447 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2448 srbStatus
= SRB_STATUS_ERROR
;
2453 KdPrint2((PRINT_PREFIX
2454 "ATAPI: Invalid sense information\n"));
2456 srbStatus
= SRB_STATUS_ERROR
;
2464 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2465 chan
->ReturningMediaStatus
= errorByte
;
2467 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2468 KdPrint2((PRINT_PREFIX
2469 "IDE: Media change\n"));
2470 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2471 srbStatus
= SRB_STATUS_ERROR
;
2473 if (Srb
->SenseInfoBuffer
) {
2475 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2477 senseBuffer
->ErrorCode
= 0x70;
2478 senseBuffer
->Valid
= 1;
2479 senseBuffer
->AdditionalSenseLength
= 0xb;
2480 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2481 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2482 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2484 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2487 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2488 KdPrint2((PRINT_PREFIX
2489 "IDE: Command abort\n"));
2490 srbStatus
= SRB_STATUS_ABORTED
;
2491 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2493 if (Srb
->SenseInfoBuffer
) {
2495 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2497 senseBuffer
->ErrorCode
= 0x70;
2498 senseBuffer
->Valid
= 1;
2499 senseBuffer
->AdditionalSenseLength
= 0xb;
2500 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2501 senseBuffer
->AdditionalSenseCode
= 0;
2502 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2504 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2507 LunExt
->ErrorCount
++;
2509 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2511 KdPrint2((PRINT_PREFIX
2512 "IDE: End of media\n"));
2513 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2514 srbStatus
= SRB_STATUS_ERROR
;
2516 if (Srb
->SenseInfoBuffer
) {
2518 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2520 senseBuffer
->ErrorCode
= 0x70;
2521 senseBuffer
->Valid
= 1;
2522 senseBuffer
->AdditionalSenseLength
= 0xb;
2523 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2524 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2525 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2526 senseBuffer
->EndOfMedia
= 1;
2528 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2531 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2532 LunExt
->ErrorCount
++;
2535 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2537 KdPrint2((PRINT_PREFIX
2538 "IDE: Illegal length\n"));
2539 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2541 if (Srb
->SenseInfoBuffer
) {
2543 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2545 senseBuffer
->ErrorCode
= 0x70;
2546 senseBuffer
->Valid
= 1;
2547 senseBuffer
->AdditionalSenseLength
= 0xb;
2548 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2549 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2550 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2551 senseBuffer
->IncorrectLength
= 1;
2553 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2556 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2558 KdPrint2((PRINT_PREFIX
2559 "IDE: Bad block\n"));
2560 srbStatus
= SRB_STATUS_ERROR
;
2561 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2562 if (Srb
->SenseInfoBuffer
) {
2564 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2566 senseBuffer
->ErrorCode
= 0x70;
2567 senseBuffer
->Valid
= 1;
2568 senseBuffer
->AdditionalSenseLength
= 0xb;
2569 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2570 senseBuffer
->AdditionalSenseCode
= 0;
2571 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2573 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2576 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2578 KdPrint2((PRINT_PREFIX
2579 "IDE: Id not found\n"));
2580 srbStatus
= SRB_STATUS_ERROR
;
2581 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2583 if (Srb
->SenseInfoBuffer
) {
2585 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2587 senseBuffer
->ErrorCode
= 0x70;
2588 senseBuffer
->Valid
= 1;
2589 senseBuffer
->AdditionalSenseLength
= 0xb;
2590 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2591 senseBuffer
->AdditionalSenseCode
= 0;
2592 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2594 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2597 LunExt
->ErrorCount
++;
2599 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2601 KdPrint2((PRINT_PREFIX
2602 "IDE: Media change\n"));
2603 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2604 srbStatus
= SRB_STATUS_ERROR
;
2606 if (Srb
->SenseInfoBuffer
) {
2608 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2610 senseBuffer
->ErrorCode
= 0x70;
2611 senseBuffer
->Valid
= 1;
2612 senseBuffer
->AdditionalSenseLength
= 0xb;
2613 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2614 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2615 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2617 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2620 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2622 KdPrint2((PRINT_PREFIX
2623 "IDE: Data error\n"));
2624 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2625 srbStatus
= SRB_STATUS_ERROR
;
2627 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2628 LunExt
->ErrorCount
++;
2631 // Build sense buffer
2632 if (Srb
->SenseInfoBuffer
) {
2634 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2636 senseBuffer
->ErrorCode
= 0x70;
2637 senseBuffer
->Valid
= 1;
2638 senseBuffer
->AdditionalSenseLength
= 0xb;
2639 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2640 senseBuffer
->AdditionalSenseCode
= 0;
2641 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2643 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2647 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
2648 // deviceExtension->DWordIO = FALSE;
2650 KdPrint2((PRINT_PREFIX
2651 "MapError: ErrorCount >= MAX_ERRORS\n"));
2653 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2654 LunExt
->MaximumBlockXfer
= 0;
2657 KdPrint2((PRINT_PREFIX
2658 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2661 KdPrint2((PRINT_PREFIX
2662 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2671 ScsiPortLogError( HwDeviceExtension
,
2679 // Reprogram to not use Multi-sector.
2682 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2683 !(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2685 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2687 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2688 // command was aborted.
2689 if (statusByte
& IDE_STATUS_ERROR
) {
2691 // Read the error register.
2692 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2694 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2698 // Adjust the devExt. value, if necessary.
2699 LunExt
->MaximumBlockXfer
= 0;
2707 // Set SCSI status to indicate a check condition.
2708 Srb
->ScsiStatus
= scsiStatus
;
2717 Routine Description:
2720 HwDeviceExtension - HBA miniport driver's adapter data storage
2723 TRUE - if initialization successful.
2724 FALSE - if initialization unsuccessful.
2730 IN PVOID HwDeviceExtension
2733 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2734 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2737 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2739 if(WinVer_WDM_Model
) {
2740 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2743 /* do extra chipset specific setups */
2744 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2746 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2747 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2748 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2751 for (c
= 0; c
< numberChannels
; c
++) {
2752 AtapiHwInitialize__(deviceExtension
, c
);
2754 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2756 } // end AtapiHwInitialize()
2760 AtapiHwInitialize__(
2761 IN PHW_DEVICE_EXTENSION deviceExtension
,
2766 UCHAR statusByte
, errorByte
;
2767 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2768 PHW_LU_EXTENSION LunExt
;
2770 ULONG PreferedMode
= 0xffffffff;
2772 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2773 FindDevices(deviceExtension
, 0, lChannel
);
2775 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
2777 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2779 LunExt
= chan
->lun
[i
];
2781 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2785 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2786 AtapiStallExecution(1);
2788 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2790 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2791 // Enable media status notification
2792 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
2794 // If supported, setup Multi-block transfers.
2795 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2796 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2797 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2799 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2800 // command was aborted.
2801 if (statusByte
& IDE_STATUS_ERROR
) {
2803 // Read the error register.
2804 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2806 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2810 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2811 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2812 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2814 if (statusByte
& IDE_STATUS_ERROR
) {
2815 // Read the error register.
2816 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2818 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2822 // Adjust the devExt. value, if necessary.
2823 LunExt
->MaximumBlockXfer
= 0;
2826 KdPrint2((PRINT_PREFIX
2827 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2829 LunExt
->MaximumBlockXfer
));
2832 if(LunExt
->IdentifyData
.MajorRevision
) {
2834 if(LunExt
->opt_ReadCacheEnable
) {
2835 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2836 // If supported, setup read/write cacheing
2837 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2838 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2839 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2841 // Check for errors.
2842 if (statusByte
& IDE_STATUS_ERROR
) {
2843 KdPrint2((PRINT_PREFIX
2844 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2846 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2848 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2851 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2852 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2853 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2854 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2855 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2857 if(LunExt
->opt_WriteCacheEnable
) {
2858 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2859 // If supported & allowed, setup write cacheing
2860 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2861 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2862 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2863 // Check for errors.
2864 if (statusByte
& IDE_STATUS_ERROR
) {
2865 KdPrint2((PRINT_PREFIX
2866 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2868 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2870 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2873 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2874 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2875 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2876 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2877 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2881 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2884 BOOLEAN isSanyo
= FALSE
;
2887 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2889 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2890 for (j
= 0; j
< 26; j
+= 2) {
2892 // Build a buffer based on the identify data.
2893 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2896 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2898 // Inquiry string for older model had a '-', newer is '_'
2899 if (vendorId
[12] == 'C') {
2901 // Torisan changer. Set the bit. This will be used in several places
2902 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2903 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2904 LunExt
->DiscsPresent
= 3;
2910 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2911 if(PreferedMode
== 0xffffffff) {
2912 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2913 PreferedMode
= chan
->MaxTransferMode
;
2916 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2917 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2918 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2921 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2922 LunExt
->OrigTransferMode
=
2923 LunExt
->LimitedTransferMode
=
2924 LunExt
->TransferMode
=
2927 AtapiDmaInit__(deviceExtension
, LunExt
);
2929 LunExt
->OrigTransferMode
=
2930 LunExt
->LimitedTransferMode
=
2931 LunExt
->TransferMode
;
2932 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2934 // We need to get our device ready for action before
2935 // returning from this function
2937 // According to the atapi spec 2.5 or 2.6, an atapi device
2938 // clears its status BSY bit when it is ready for atapi commands.
2939 // However, some devices (Panasonic SQ-TC500N) are still
2940 // not ready even when the status BSY is clear. They don't react
2941 // to atapi commands.
2943 // Since there is really no other indication that tells us
2944 // the drive is really ready for action. We are going to check BSY
2945 // is clear and then just wait for an arbitrary amount of time!
2947 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2950 // have to get out of the loop sometime!
2951 // 10000 * 100us = 1000,000us = 1000ms = 1s
2953 GetStatus(chan
, statusByte
);
2954 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2956 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2957 // Wait for Busy to drop.
2958 AtapiStallExecution(100);
2959 GetStatus(chan
, statusByte
);
2963 // 5000 * 100us = 500,000us = 500ms = 0.5s
2966 AtapiStallExecution(100);
2967 } while (waitCount
--);
2969 GetBaseStatus(chan
, statusByte
);
2970 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2971 AtapiStallExecution(10);
2976 } // end AtapiHwInitialize()
2983 AtapiHwInitializeChanger(
2984 IN PVOID HwDeviceExtension
,
2985 IN PSCSI_REQUEST_BLOCK Srb
,
2986 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2988 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2989 ULONG lChannel
= GET_CHANNEL(Srb
);
2990 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2991 ULONG DeviceNumber
= GET_CDEV(Srb
);
2992 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2994 if (MechanismStatus
) {
2995 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2996 if (LunExt
->DiscsPresent
> 1) {
2997 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3001 } // end AtapiHwInitializeChanger()
3006 Routine Description:
3007 This routine will parse the string for a match on the keyword, then
3008 calculate the value for the keyword and return it to the caller.
3011 String - The ASCII string to parse.
3012 KeyWord - The keyword for the value desired.
3015 Zero if value not found
3016 Value converted from ASCII to binary.
3021 AtapiParseArgumentString(
3029 ULONG stringLength
= 0;
3030 ULONG keyWordLength
= 0;
3040 // Calculate the string length and lower case all characters.
3046 // Calculate the keyword length.
3052 if (keyWordLength
> stringLength
) {
3054 // Can't possibly have a match.
3058 // Now setup and start the compare.
3063 // The input string may start with white space. Skip it.
3064 while (*cptr
== ' ' || *cptr
== '\t') {
3068 if (*cptr
== '\0') {
3074 while ((*cptr
== *kptr
) ||
3075 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3076 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3080 if (*cptr
== '\0') {
3086 if (*kptr
== '\0') {
3088 // May have a match backup and check for blank or equals.
3089 while (*cptr
== ' ' || *cptr
== '\t') {
3093 // Found a match. Make sure there is an equals.
3096 // Not a match so move to the next semicolon.
3098 if (*cptr
++ == ';') {
3099 goto ContinueSearch
;
3104 // Skip the equals sign.
3107 // Skip white space.
3108 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3112 if (*cptr
== '\0') {
3113 // Early end of string, return not found
3118 // This isn't it either.
3120 goto ContinueSearch
;
3124 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3125 // Value is in Hex. Skip the "0x"
3127 for (index
= 0; *(cptr
+ index
); index
++) {
3129 if (*(cptr
+ index
) == ' ' ||
3130 *(cptr
+ index
) == '\t' ||
3131 *(cptr
+ index
) == ';') {
3135 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3136 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3138 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3139 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3140 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3141 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3143 // Syntax error, return not found.
3150 // Value is in Decimal.
3151 for (index
= 0; *(cptr
+ index
); index
++) {
3153 if (*(cptr
+ index
) == ' ' ||
3154 *(cptr
+ index
) == '\t' ||
3155 *(cptr
+ index
) == ';') {
3159 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3160 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3163 // Syntax error return not found.
3172 // Not a match check for ';' to continue search.
3174 if (*cptr
++ == ';') {
3175 goto ContinueSearch
;
3181 } // end AtapiParseArgumentString()_
3189 IN PVOID HwDeviceExtension
,
3194 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3195 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3198 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3201 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3202 // If the last command was DSC restrictive, see if it's set. If so, the device is
3203 // ready for a new request. Otherwise, reset the timer and come back to here later.
3205 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3206 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3207 // we shall have no problem with interrupt handler.
3208 if (!srb
|| chan
->ExpectingInterrupt
) {
3209 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3210 chan
->DpcState
= DPC_STATE_TIMER
;
3211 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3212 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3213 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3215 goto ReturnCallback
;
3219 if (!IS_RDP((srb
->Cdb
[0]))) {
3220 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3224 goto ReturnEnableIntr
;
3226 GetStatus(chan
, statusByte
);
3227 if (statusByte
& IDE_STATUS_DSC
) {
3229 UCHAR PathId
= srb
->PathId
;
3230 UCHAR TargetId
= srb
->TargetId
;
3231 UCHAR Lun
= srb
->Lun
;
3233 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3234 AtapiDmaDBSync(chan
, srb
);
3235 UniataRemoveRequest(chan
, srb
);
3236 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3237 // Clear current SRB.
3238 if(!deviceExtension
->simplexOnly
) {
3239 srb
= UniataGetCurRequest(chan
);
3245 // Ask for next request.
3246 ScsiPortNotification(NextLuRequest
,
3251 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3254 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3258 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3261 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3265 goto ReturnCallback
;
3270 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3271 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3272 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3273 #ifdef UNIATA_USE_XXableInterrupts
3274 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3275 // must be called on DISPATCH_LEVEL
3276 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3277 AtapiEnableInterrupts__
);
3279 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3280 InterlockedExchange(&(chan
->CheckIntr
),
3282 // Will raise IRQL to DIRQL
3283 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3284 AtapiEnableInterrupts__
,
3286 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3287 #endif // UNIATA_USE_XXableInterrupts
3289 //ASSERT(!deviceExtension->simplexOnly);
3294 // Check other channel
3295 // In simplex mode no interrupts must appear on other channels
3296 for(_c
=0; _c
<deviceExtension
->NumberChannels
-1; _c
++) {
3297 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3299 chan
= &(deviceExtension
->chan
[c
]);
3301 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3302 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3303 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3305 //ASSERT(!deviceExtension->simplexOnly);
3306 chan
->DpcState
= DPC_STATE_ISR
;
3307 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3308 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3312 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3315 } // end AtapiCallBack__()
3320 IN PVOID HwDeviceExtension
3323 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3326 #endif //UNIATA_CORE
3330 Routine Description:
3332 This is the interrupt service routine for ATAPI IDE miniport driver.
3336 HwDeviceExtension - HBA miniport driver's adapter data storage
3340 TRUE if expecting an interrupt.
3346 IN PVOID HwDeviceExtension
3349 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3351 BOOLEAN status
= FALSE
;
3355 BOOLEAN checked
[AHCI_MAX_PORT
];
3358 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
3360 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3361 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3362 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3368 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3369 checked
[_c
] = FALSE
;
3373 for(pass
=0; pass
<2; pass
++) {
3374 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3376 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3381 // check non-empty and expecting interrupt channels first
3382 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3387 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3389 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3390 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3393 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3395 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3396 // c_state = deviceExtension->chan[c].CheckIntr;
3397 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3398 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3401 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3402 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3403 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3404 if(c_state
== CHECK_INTR_IDLE
) {
3405 // c_state = deviceExtension->chan[c].CheckIntr;
3406 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3407 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3410 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3411 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3412 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3414 } while(c_state
== CHECK_INTR_CHECK
);
3415 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3416 // check if already serviced
3417 if(c_state
== CHECK_INTR_ACTIVE
) {
3418 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3422 if((c_state
== CHECK_INTR_DETECTED
) ||
3423 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3425 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3426 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3427 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3430 // disable interrupts on other channel of legacy mode
3431 // ISA-bridged onboard controller
3432 if(deviceExtension
->simplexOnly
/*||
3433 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3434 AtapiDisableInterrupts(deviceExtension
, !c
);
3437 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3438 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3439 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3440 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3443 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3444 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3447 // re-enable interrupts on other channel
3448 if(deviceExtension
->simplexOnly
/*||
3449 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3450 AtapiEnableInterrupts(deviceExtension
, !c
);
3454 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3455 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3460 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3462 deviceExtension
->FirstChannelToCheck
++;
3463 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3464 deviceExtension
->FirstChannelToCheck
= 0;
3467 } // end AtapiInterrupt()
3475 IN PKINTERRUPT Interrupt
,
3476 IN PVOID Isr2HwDeviceExtension
3480 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3481 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3483 BOOLEAN status
= FALSE
;
3488 // we should never get here for ISA/MCA
3489 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3490 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3494 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3495 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3496 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3502 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3503 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3505 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3506 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3510 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3511 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
3512 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
3514 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3515 // hunt on unexpected intr (Some devices generate double interrupts,
3516 // some controllers (at least CMD649) interrupt twice with small delay.
3517 // If interrupts are disabled, they queue interrupt and re-issue it later,
3518 // when we do not expect it.
3523 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3525 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3526 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3527 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3528 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3533 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3535 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3538 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3539 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3540 // there is an active ISR/DPC for one channel, but
3541 // we have an interrupt from another one
3542 // Lets inform current ISR/DPC about new interrupt
3543 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3547 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3550 } // end AtapiInterrupt2()
3552 RETTYPE_XXableInterrupts
3555 IN PVOID HwDeviceExtension
3558 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3561 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3562 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3564 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3566 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3567 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3568 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
3574 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3577 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3578 AtapiDisableInterrupts(deviceExtension, lChannel);
3581 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3582 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3583 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3586 return RETVAL_XXableInterrupts
;
3587 } // end AtapiInterruptDpc()
3590 RETTYPE_XXableInterrupts
3592 AtapiEnableInterrupts__(
3593 IN PVOID HwDeviceExtension
3596 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3597 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3599 PHW_CHANNEL chan
= NULL
;
3601 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3602 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3603 chan
= &(deviceExtension
->chan
[c
]);
3605 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3606 // enable intrs on requested channel
3607 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3608 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3609 InterlockedExchange(&(chan
->CheckIntr
),
3612 // check if current or other channel(s) interrupted
3613 //AtapiInterrupt(HwDeviceExtension);
3615 if(deviceExtension
->simplexOnly
) {
3619 // check if other channel(s) interrupted
3620 // must do nothing in simplex mode
3621 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3622 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3623 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3626 //ASSERT(!deviceExtension->simplexOnly);
3627 chan
->DpcState
= DPC_STATE_ISR
;
3628 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3629 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3633 // In simplex mode next command must be sent to device here
3634 if(deviceExtension
->simplexOnly
&& chan
) {
3635 PSCSI_REQUEST_BLOCK srb
;
3636 chan
= UniataGetNextChannel(chan
);
3638 srb
= UniataGetCurRequest(chan
);
3643 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3647 return RETVAL_XXableInterrupts
;
3649 } // end AtapiEnableInterrupts__()
3651 #endif //UNIATA_CORE
3656 AtapiEnableInterrupts(
3657 IN PVOID HwDeviceExtension
,
3661 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3663 if(c
>= deviceExtension
->NumberChannels
) {
3664 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
3667 chan
= &(deviceExtension
->chan
[c
]);
3668 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
3669 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
3670 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3671 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
3673 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3676 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3678 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3679 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3682 } // end AtapiEnableInterrupts()
3686 AtapiDisableInterrupts(
3687 IN PVOID HwDeviceExtension
,
3691 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3693 if(c
>= deviceExtension
->NumberChannels
) {
3694 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
3697 chan
= &(deviceExtension
->chan
[c
]);
3698 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
3699 // mark channel as busy
3700 if(InterlockedIncrement(&chan
->DisableIntr
)) {
3701 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3702 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
3703 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
3704 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
3705 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
3706 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
3707 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
3710 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3711 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3713 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
3717 } // end AtapiDisableInterrupts()
3721 Check hardware for interrupt state
3725 AtapiCheckInterrupt__(
3726 IN PVOID HwDeviceExtension
,
3727 IN UCHAR c
// logical channel
3730 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3731 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3732 PHW_LU_EXTENSION LunExt
;
3734 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
3735 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
3738 ULONG pr_status
= 0;
3739 UCHAR dma_status
= 0;
3743 ULONG slotNumber
= deviceExtension
->slotNumber
;
3744 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
3745 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
3748 BOOLEAN DmaTransfer
= FALSE
;
3749 BOOLEAN OurInterrupt
= FALSE
;
3751 UCHAR interruptReason
;
3752 BOOLEAN EarlyIntr
= FALSE
;
3754 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
3757 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3759 if((ChipFlags
& UNIATA_AHCI
) &&
3760 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3761 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, -1);
3762 return OurInterrupt
;
3765 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
3767 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
3768 deviceExtension
->Channel
+ c
, c
));
3770 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
3771 deviceExtension
->Channel
+ c
, c
));
3772 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3773 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
3776 // do controller-specific interrupt servicing staff
3777 if(deviceExtension
->UnknownDev
) {
3778 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
3783 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
3784 // Such behavior was observed with Intel ICH-xxx chips
3785 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
3789 case ATA_PROMISE_ID
: {
3793 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
3797 ((Channel
) ? 0x00004000 : 0x00000400))) {
3798 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
3799 return INTERRUPT_REASON_IGNORE
;
3803 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
3804 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
3807 if(!(status
& 0x20)) {
3808 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
3809 return INTERRUPT_REASON_IGNORE
;
3813 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
3814 if(ChipFlags
& PRSATA
) {
3815 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
3816 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
3818 if(pr_status
& (0x11 << Channel
)) {
3819 // TODO: reset channel
3820 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
3821 return INTERRUPT_REASON_IGNORE
;
3823 if(!(status
& (0x01 << Channel
))) {
3824 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
3825 return INTERRUPT_REASON_IGNORE
;
3827 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
3831 case ATA_NVIDIA_ID
: {
3832 if(!(ChipFlags
& UNIATA_SATA
))
3835 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
3837 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
3838 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
3840 /* get and clear interrupt status */
3841 if(ChipFlags
& NVQ
) {
3842 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3843 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
3845 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3846 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
3848 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
3850 /* check for and handle connect events */
3851 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
3852 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
3854 /* check for and handle disconnect events */
3855 if((pr_status
& (0x08UL
<< shift
)) &&
3856 !((pr_status
& (0x04UL
<< shift
) &&
3857 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
3858 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
3860 /* do we have any device action ? */
3861 if(!(pr_status
& (0x01UL
<< shift
))) {
3862 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
3863 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
3864 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3866 return INTERRUPT_REASON_IGNORE
;
3872 KdPrint2((PRINT_PREFIX
"ATI\n"));
3873 if(ChipType
== SIIMIO
) {
3878 case ATA_SILICON_IMAGE_ID
:
3880 if(ChipType
== SIIMIO
) {
3882 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
3883 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
3884 if(reg32
== 0xffffffff) {
3885 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
3886 return INTERRUPT_REASON_IGNORE
;
3888 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
))) {
3889 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
3890 return INTERRUPT_REASON_IGNORE
;
3893 if(ChipFlags
& UNIATA_SATA
) {
3894 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
3896 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
3897 * controllers continue to assert IRQ as long as
3898 * SError bits are pending. Clear SError immediately.
3900 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
3901 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3908 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3909 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
3910 return OurInterrupt
;
3912 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
3913 goto skip_dma_stat_check
;
3916 if(!(deviceExtension
->HwFlags
& SIIINTR
))
3918 GetPciConfig1(0x71, reg8
);
3919 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
3921 (Channel
? 0x08 : 0x04))) {
3922 return INTERRUPT_REASON_IGNORE
;
3925 KdPrint2((PRINT_PREFIX
" cmd our\n"));
3926 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3928 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
3935 //dma_status = GetDmaStatus(deviceExtension, lChannel);
3936 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3937 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
3938 return INTERRUPT_REASON_IGNORE
;
3940 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
3941 AtapiStallExecution(1);
3942 AtapiWritePort1(chan
, IDX_BM_Command
,
3943 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
3944 goto skip_dma_stat_check
;
3946 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3947 if(ChipFlags
& UNIATA_AHCI
) {
3950 if(ChipFlags
& UNIATA_SATA
) {
3951 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
3952 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3954 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
3955 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
3956 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3963 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3964 if(ChipFlags
& UNIATA_AHCI
) {
3967 if(ChipFlags
& UNIATA_SATA
) {
3968 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
3969 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3975 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
3977 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3978 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
3979 if(dma_status
& BM_STATUS_ERR
) {
3980 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
3981 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3983 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3984 GetStatus(chan
, statusByte
);
3985 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3986 if(statusByte
& IDE_STATUS_ERROR
) {
3987 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
3988 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
3990 return INTERRUPT_REASON_IGNORE
;
3995 if(dma_status
& BM_STATUS_INTR
) {
3996 // bullshit, we have DMA interrupt, but had never initiate DMA operation
3997 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
3998 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4000 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4003 skip_dma_stat_check
:
4004 if(!(ChipFlags
& UNIATA_SATA
)) {
4005 AtapiStallExecution(1);
4008 LunExt
= chan
->lun
[chan
->cur_cdev
];
4009 /* if drive is busy it didn't interrupt */
4010 /* the exception is DCS + BSY state of ATAPI devices */
4011 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4012 GetStatus(chan
, statusByte
);
4013 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4014 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4016 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4018 if (statusByte
== 0xff) {
4019 // interrupt from empty controller ?
4021 if (statusByte
& IDE_STATUS_BUSY
) {
4022 if(!chan
->ExpectingInterrupt
) {
4023 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4024 return OurInterrupt
;
4027 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4028 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4030 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4031 return INTERRUPT_REASON_IGNORE
;
4033 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4034 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4035 return INTERRUPT_REASON_IGNORE
;
4037 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4038 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4039 return INTERRUPT_REASON_IGNORE
;
4044 if(dma_status
& BM_STATUS_INTR
) {
4045 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4046 /* clear interrupt and get status */
4047 GetBaseStatus(chan
, statusByte
);
4048 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4049 return INTERRUPT_REASON_OUR
;
4052 if(g_WaitBusyInISR
) {
4053 GetStatus(chan
, statusByte
);
4054 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4055 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4056 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4057 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4058 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4060 if (statusByte
& IDE_STATUS_BUSY
) {
4061 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4062 return INTERRUPT_REASON_IGNORE
;
4068 /* clear interrupt and get status */
4069 GetBaseStatus(chan
, statusByte
);
4070 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4071 if (statusByte
== 0xff) {
4072 // interrupt from empty controller ?
4074 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4075 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4076 return OurInterrupt
;
4079 #ifndef UNIATA_PIO_ONLY
4081 if(!EarlyIntr
|| g_WaitBusyInISR
) {
4082 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4084 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4085 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4089 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4091 AtaReq
->ReqState
= REQ_STATE_EARLY_INTR
;
4097 if (!(chan
->ExpectingInterrupt
)) {
4099 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4101 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4102 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4104 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4105 return OurInterrupt
;
4107 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4108 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4109 return OurInterrupt
;
4111 //ASSERT(!chan->queue_depth || chan->cur_req);
4113 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4114 return INTERRUPT_REASON_OUR
;
4116 } // end AtapiCheckInterrupt__()
4122 IN PVOID HwDeviceExtension
,
4126 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4127 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4129 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4130 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4132 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4133 ULONG status
= SRB_STATUS_SUCCESS
;
4134 UCHAR dma_status
= 0;
4137 UCHAR statusByte
= 0,interruptReason
;
4139 BOOLEAN atapiDev
= FALSE
;
4144 BOOLEAN DmaTransfer
= FALSE
;
4146 ULONG TimerValue
= 1000;
4147 #ifdef UNIATA_USE_XXableInterrupts
4148 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4150 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4151 #endif // UNIATA_USE_XXableInterrupts
4152 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4153 // BOOLEAN RestoreUseDpc = FALSE;
4154 BOOLEAN DataOverrun
= FALSE
;
4155 BOOLEAN NoStartIo
= TRUE
;
4157 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4159 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4160 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4166 UCHAR OldReqState
= REQ_STATE_NONE
;
4168 PHW_LU_EXTENSION LunExt
;
4171 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4173 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4175 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4176 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ) {
4178 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4182 PathId
= srb
->PathId
;
4183 TargetId
= srb
->TargetId
;
4189 goto enqueue_next_req
;
4192 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4193 DeviceNumber
= (UCHAR
)(TargetId
);
4194 LunExt
= chan
->lun
[DeviceNumber
];
4195 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4196 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4198 // check if we are in ISR DPC
4200 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4201 goto ServiceInterrupt
;
4205 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4208 if (!(chan
->ExpectingInterrupt
)) {
4210 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4214 // change request state
4216 OldReqState
= AtaReq
->ReqState
;
4217 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4218 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4221 // We don't want using DPC for fast operations, like
4222 // DMA completion, sending CDB, short ATAPI transfers, etc.
4224 // We MUST use DPC, because of interprocessor synchronization
4225 // on multiprocessor platforms
4228 goto ServiceInterrupt
;
4230 switch(OldReqState
) {
4231 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4232 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4233 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4234 case REQ_STATE_DPC_WAIT_BUSY0
:
4235 case REQ_STATE_DPC_WAIT_BUSY1
:
4236 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4237 goto ServiceInterrupt
;
4238 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4239 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4243 if(!DmaTransfer
&& !atapiDev
) {
4244 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4251 goto ServiceInterrupt
;
4253 #ifdef UNIATA_USE_XXableInterrupts
4255 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4257 // shall never get here
4262 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4264 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4265 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4267 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4270 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4271 goto ServiceInterrupt
;
4272 #endif // UNIATA_USE_XXableInterrupts
4277 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4278 // We always get here when are called from timer callback, which is invoked on DRQL.
4279 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4281 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4282 // disable interrupts for this channel,
4283 // but avoid recursion and double-disable
4284 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4285 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4288 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4290 #ifdef UNIATA_USE_XXableInterrupts
4291 // Will lower IRQL to DISPATCH_LEVEL
4292 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4293 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4294 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4296 // Will raise IRQL to DIRQL
4297 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4300 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4301 #endif // UNIATA_USE_XXableInterrupts
4306 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4308 // Will raise IRQL to DIRQL
4309 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4313 #endif //UNIATA_CORE
4317 if(AtaReq
&& InDpc
) {
4318 switch(AtaReq
->ReqState
) {
4319 case REQ_STATE_DPC_WAIT_DRQ0
:
4321 case REQ_STATE_DPC_WAIT_BUSY
:
4323 case REQ_STATE_DPC_WAIT_DRQ
:
4325 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4327 case REQ_STATE_DPC_WAIT_BUSY0
:
4328 case REQ_STATE_DPC_WAIT_BUSY1
:
4329 // continue normal execution
4335 #endif //UNIATA_CORE
4337 // make additional delay for old devices (if we are not in DPC)
4338 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4342 !(deviceExtension->HwFlags & UNIATA_SATA)
4344 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4345 AtapiStallExecution(10);
4348 /* clear interrupt and get status */
4350 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4351 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4352 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& 0xff);
4354 GetBaseStatus(chan
, statusByte
);
4357 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4359 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4363 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4367 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4368 KdPrint3((PRINT_PREFIX
" AHCI branch\n"));
4372 if (statusByte
& IDE_STATUS_BUSY
) {
4373 if (deviceExtension
->DriverMustPoll
) {
4374 // Crashdump is polling and we got caught with busy asserted.
4375 // Just go away, and we will be polled again shortly.
4376 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4377 goto ReturnEnableIntr
;
4380 // Ensure BUSY is non-asserted.
4381 // make a very small idle before falling to DPC
4382 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4384 for (i
= 0; i
< k
; i
++) {
4386 GetBaseStatus(chan
, statusByte
);
4387 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4390 AtapiStallExecution(10);
4393 if (!InDpc
&& UseDpc
&& i
== 2) {
4395 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4398 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4403 AtapiStallExecution(TimerValue
);
4404 goto ServiceInterrupt
;
4405 #endif //UNIATA_CORE
4407 if (InDpc
&& i
== k
) {
4408 // reset the controller.
4409 KdPrint2((PRINT_PREFIX
4410 " Resetting due to BUSY on entry - %#x.\n",
4412 goto IntrPrepareResetController
;
4417 if(!LunExt
->IdentifyData
.MajorRevision
&&
4420 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4422 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices (2)\n"));
4423 AtapiStallExecution(10);
4425 if (statusByte
& IDE_STATUS_BUSY
) {
4426 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4427 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting\n"));
4429 GetStatus(chan
, statusByte
);
4430 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4431 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4432 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
4433 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4434 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4438 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4440 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4442 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4444 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4446 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4451 AtapiStallExecution(TimerValue
);
4452 #endif //UNIATA_CORE
4455 AtapiStallExecution(10);
4457 if (statusByte
& IDE_STATUS_BUSY
) {
4458 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4464 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4465 switch(OldReqState
) {
4466 case REQ_STATE_EARLY_INTR
:
4467 case REQ_STATE_DPC_WAIT_BUSY0
:
4469 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4470 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4471 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4478 // Check for error conditions.
4479 if ((statusByte
& IDE_STATUS_ERROR
) ||
4480 (dma_status
& BM_STATUS_ERR
)) {
4482 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4483 error
= (UCHAR
)((AtaReq
->ahci
.in_status
>> 8) && 0xff);
4485 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4487 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4489 if(error & IDE_STATUS_CORRECTED_ERROR) {
4490 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4491 statusByte &= ~IDE_STATUS_ERROR;
4496 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4498 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4503 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4504 AtapiStallExecution(100);
4506 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4507 AtapiStallExecution(10);
4511 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4512 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4514 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4515 GetStatus(chan
, statusByte
);
4516 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4517 AtapiStallExecution(50);
4524 /* if this is a UDMA CRC error, reinject request */
4527 if(AtaReq
->retry
< MAX_RETRIES
) {
4528 #ifdef IO_STATISTICS
4529 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
4530 #endif //IO_STATISTICS
4532 (error & IDE_ERROR_ICRC)*/) {
4533 if(AtaReq
->retry
< MAX_RETRIES
) {
4535 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4536 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4537 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4538 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4542 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4545 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
4549 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4550 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
4552 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
4553 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
4554 if(AtaReq
->retry
< MAX_RETRIES
) {
4556 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4557 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4558 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4559 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4563 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4566 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
4570 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
4571 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
4572 // Fail this request.
4573 status
= SRB_STATUS_ERROR
;
4574 goto CompleteRequest
;
4576 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
4579 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
4580 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
4581 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
4583 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
4584 #ifdef IO_STATISTICS
4585 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
4586 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
4588 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
],
4589 chan
->lun
[DeviceNumber
]->BlockIoCount
4591 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
]++;
4592 if(chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
4593 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
4596 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
4597 #endif //IO_STATISTICS
4598 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", deviceExtension
->lun
[DeviceNumber
].TransferMode
));
4599 deviceExtension
->lun
[DeviceNumber
].LimitedTransferMode
=
4600 deviceExtension
->lun
[DeviceNumber
].TransferMode
;
4603 #ifdef IO_STATISTICS
4604 if(AtaReq
->bcount
) {
4605 // we need stats for Read/Write operations
4606 chan
->lun
[DeviceNumber
]->BlockIoCount
++;
4608 chan
->lun
[DeviceNumber
]->IoCount
++;
4609 #endif //IO_STATISTICS
4613 // check reason for this interrupt.
4616 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
4619 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4620 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4622 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4624 wordsThisInterrupt
= DEV_BSIZE
/2;
4632 // simulate DRQ for DMA transfers
4633 statusByte
|= IDE_STATUS_DRQ
;
4635 if (statusByte
& IDE_STATUS_DRQ
) {
4638 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4640 if (LunExt
->MaximumBlockXfer
) {
4641 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
4644 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4646 interruptReason
= 0x2;
4648 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4649 interruptReason
= 0x0;
4652 status
= SRB_STATUS_ERROR
;
4653 goto CompleteRequest
;
4656 } else if (statusByte
& IDE_STATUS_BUSY
) {
4658 //AtapiEnableInterrupts(deviceExtension, lChannel);
4659 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
4664 if (AtaReq
->WordsLeft
) {
4666 // Funky behaviour seen with PCI IDE (not all, just one).
4668 // The ISR hits with DRQ low, but comes up later.
4669 for (k
= 0; k
< 5000; k
++) {
4670 GetStatus(chan
, statusByte
);
4671 if (statusByte
& IDE_STATUS_DRQ
) {
4676 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
4678 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
4682 AtapiStallExecution(TimerValue
);
4683 goto ServiceInterrupt
;
4684 #endif //UNIATA_CORE
4686 AtapiStallExecution(100);
4689 // reset the controller.
4690 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
4692 IntrPrepareResetController
:
4693 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
4694 goto ReturnEnableIntr
;
4697 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
4701 // Command complete - verify, write, or the SMART enable/disable.
4702 // Also get_media_status
4703 interruptReason
= 0x3;
4708 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
4709 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4710 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
4711 goto ReturnEnableIntr
;
4713 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
4714 // Write the packet.
4715 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
4716 // Send CDB to device.
4717 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
, 6, 0);
4718 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4720 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
4721 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
4722 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
4725 goto ReturnEnableIntr
;
4727 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
4732 // Pick up bytes to transfer and convert to words.
4734 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4737 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
4739 // Covert bytes to words.
4741 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
4743 if (wordCount
!= AtaReq
->WordsLeft
) {
4744 KdPrint2((PRINT_PREFIX
4745 "AtapiInterrupt: %d words requested; %d words xferred\n",
4750 // Verify this makes sense.
4751 if (wordCount
> AtaReq
->WordsLeft
) {
4752 wordCount
= AtaReq
->WordsLeft
;
4753 KdPrint2((PRINT_PREFIX
4754 "AtapiInterrupt: Write underrun\n"));
4760 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
4761 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4762 // Transfer only words requested.
4763 wordCount
= AtaReq
->WordsLeft
;
4765 // Transfer next block.
4766 wordCount
= wordsThisInterrupt
;
4770 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4771 //ASSERT(AtaReq->WordsLeft == wordCount);
4772 AtaReq
->WordsLeft
= 0;
4773 status
= SRB_STATUS_SUCCESS
;
4774 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4775 goto CompleteRequest
;
4777 // Ensure that this is a write command.
4778 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4780 KdPrint2((PRINT_PREFIX
4781 "AtapiInterrupt: Write interrupt\n"));
4783 statusByte
= WaitOnBusy(chan
);
4785 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4790 UniataGetPioTiming(LunExt
));
4794 (PULONG
)(AtaReq
->DataBuffer
),
4796 UniataGetPioTiming(LunExt
));
4800 KdPrint3((PRINT_PREFIX
4801 "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
4805 // Fail this request.
4806 status
= SRB_STATUS_ERROR
;
4807 goto CompleteRequest
;
4810 // Advance data buffer pointer and bytes left.
4811 AtaReq
->DataBuffer
+= wordCount
;
4812 AtaReq
->WordsLeft
-= wordCount
;
4815 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4818 goto ReturnEnableIntr
;
4820 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
4825 // Pick up bytes to transfer and convert to words.
4827 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
4828 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
4830 // Covert bytes to words.
4832 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
4834 if (wordCount
!= AtaReq
->WordsLeft
) {
4835 KdPrint2((PRINT_PREFIX
4836 "AtapiInterrupt: %d words requested; %d words xferred\n",
4841 // Verify this makes sense.
4842 if (wordCount
> AtaReq
->WordsLeft
) {
4843 wordCount
= AtaReq
->WordsLeft
;
4849 // Check if words left is at least 256.
4850 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4851 // Transfer only words requested.
4852 wordCount
= AtaReq
->WordsLeft
;
4854 // Transfer next block.
4855 wordCount
= wordsThisInterrupt
;
4859 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4860 //ASSERT(AtaReq->WordsLeft == wordCount);
4861 AtaReq
->WordsLeft
= 0;
4862 status
= SRB_STATUS_SUCCESS
;
4863 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4864 goto CompleteRequest
;
4866 // Ensure that this is a read command.
4867 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4870 "AtapiInterrupt: Read interrupt\n"));*/
4872 statusByte
= WaitOnBusy(chan
);
4874 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4875 KdPrint2((PRINT_PREFIX
4876 "IdeIntr: Read %#x words\n", wordCount
));
4881 UniataGetPioTiming(LunExt
));
4882 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
4883 //KdDump(AtaReq->DataBuffer, wordCount*2);
4884 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
4885 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
4888 GetStatus(chan
, statusByte
);
4889 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4892 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
4893 AtapiSuckPort2(chan
);
4897 KdPrint2((PRINT_PREFIX
4898 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
4901 (PULONG
)(AtaReq
->DataBuffer
),
4903 UniataGetPioTiming(LunExt
));
4907 KdPrint3((PRINT_PREFIX
4908 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
4912 // Fail this request.
4913 status
= SRB_STATUS_ERROR
;
4914 goto CompleteRequest
;
4917 // Advance data buffer pointer and bytes left.
4918 AtaReq
->DataBuffer
+= wordCount
;
4919 AtaReq
->WordsLeft
-= wordCount
;
4921 // Check for read command complete.
4922 if (AtaReq
->WordsLeft
== 0) {
4924 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
4927 // Work around to make many atapi devices return correct sector size
4928 // of 2048. Also certain devices will have sector count == 0x00, check
4930 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
4931 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
4933 AtaReq
->DataBuffer
-= wordCount
;
4934 if (AtaReq
->DataBuffer
[0] == 0x00) {
4936 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
4940 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
4941 AtaReq
->DataBuffer
+= wordCount
;
4946 // Completion for IDE drives.
4947 if (AtaReq->WordsLeft) {
4948 status = SRB_STATUS_DATA_OVERRUN;
4950 status = SRB_STATUS_SUCCESS;
4953 goto CompleteRequest;
4955 status
= SRB_STATUS_SUCCESS
;
4956 goto CompleteRequest
;
4961 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4965 goto ReturnEnableIntr
;
4967 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
4969 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
4970 // Command complete.
4972 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
4973 AtaReq
->WordsLeft
= 0;
4975 if (AtaReq
->WordsLeft
) {
4976 status
= SRB_STATUS_DATA_OVERRUN
;
4978 status
= SRB_STATUS_SUCCESS
;
4981 #ifdef UNIATA_DUMP_ATAPI
4983 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4987 PCHAR ModeSelectData
;
4989 PSCSI_REQUEST_BLOCK Srb
= srb
;
4991 Cdb
= (PCDB
)(Srb
->Cdb
);
4992 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
4993 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
4994 CdbDataLen
= Srb
->DataTransferLength
;
4996 if(CdbDataLen
> 0x1000) {
4997 CdbDataLen
= 0x1000;
5001 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5002 KdPrint2(("P:T:D=%d:%d:%d\n",
5006 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5009 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5010 KdPrint(("ModeSense 6\n"));
5011 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5012 ModeSelectData
= CdbData
+4;
5013 KdDump(CdbData
, CdbDataLen
);
5015 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5016 KdPrint(("ModeSense 10\n"));
5017 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5018 ModeSelectData
= CdbData
+8;
5019 KdDump(CdbData
, CdbDataLen
);
5021 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5022 KdPrint(("Read buffer from device:\n"));
5023 KdDump(CdbData
, CdbDataLen
);
5028 #endif //UNIATA_DUMP_ATAPI
5032 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest\n"));
5033 // Check and see if we are processing our secret (mechanism status/request sense) srb
5034 if (AtaReq
->OriginalSrb
) {
5038 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5039 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5041 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5042 if (status
== SRB_STATUS_SUCCESS
) {
5044 AtapiHwInitializeChanger (HwDeviceExtension
,
5046 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5048 // Get ready to issue the original srb
5049 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5050 AtaReq
->OriginalSrb
= NULL
;
5053 // failed! Get the sense key and maybe try again
5054 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5056 AtaReq
->OriginalSrb
);
5059 // do not enable interrupts in DPC, do not waste time, do it now!
5060 if(UseDpc && chan->DisableIntr) {
5061 AtapiEnableInterrupts(HwDeviceExtension, c);
5063 RestoreUseDpc = TRUE;
5066 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5068 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5070 if (srbStatus
== SRB_STATUS_PENDING
) {
5071 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5072 goto ReturnEnableIntr
;
5076 // restore state on error
5078 AtapiDisableInterrupts(HwDeviceExtension, c);
5082 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5084 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5086 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5087 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5088 // Check to see if we at least get mininum number of bytes
5089 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5090 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5091 status
= SRB_STATUS_SUCCESS
;
5095 if (status
== SRB_STATUS_SUCCESS
) {
5097 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5098 chan
->MechStatusRetryCount
) {
5100 // The sense key doesn't say the last request is illegal, so try again
5101 chan
->MechStatusRetryCount
--;
5102 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5104 AtaReq
->OriginalSrb
);
5107 // last request was illegal. No point trying again
5108 AtapiHwInitializeChanger (HwDeviceExtension
,
5110 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5112 // Get ready to issue the original srb
5113 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5114 AtaReq
->OriginalSrb
= NULL
;
5116 #endif //UNIATA_CORE
5118 // do not enable interrupts in DPC, do not waste time, do it now!
5119 if(UseDpc && chan->DisableIntr) {
5120 AtapiEnableInterrupts(HwDeviceExtension, c);
5122 RestoreUseDpc = TRUE;
5125 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5127 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5129 if (srbStatus
== SRB_STATUS_PENDING
) {
5130 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5131 goto ReturnEnableIntr
;
5135 // restore state on error
5137 AtapiDisableInterrupts(HwDeviceExtension, c);
5143 // If we get here, it means AtapiSendCommand() has failed
5144 // Can't recover. Pretend the original srb has failed and complete it.
5146 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5148 if (AtaReq
->OriginalSrb
) {
5149 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5150 AtapiHwInitializeChanger (HwDeviceExtension
,
5152 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5153 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5154 AtaReq
->OriginalSrb
= NULL
;
5157 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5159 // fake an error and read no data
5160 status
= SRB_STATUS_ERROR
;
5161 srb
->ScsiStatus
= 0;
5162 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5163 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5166 } else if (status
== SRB_STATUS_ERROR
) {
5168 // Map error to specific SRB status and handle request sense.
5169 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5170 status
= MapError(deviceExtension
,
5175 } else if(!DmaTransfer
) {
5177 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5178 // Command complete.
5180 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
5181 // Wait for busy to drop.
5182 for (i
= 0; i
< 5*30; i
++) {
5183 GetStatus(chan
, statusByte
);
5184 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5189 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
5191 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
5195 AtapiStallExecution(TimerValue
);
5196 goto ServiceInterrupt
;
5197 #endif //UNIATA_CORE
5199 AtapiStallExecution(100);
5204 // reset the controller.
5205 KdPrint2((PRINT_PREFIX
5206 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5208 goto IntrPrepareResetController
;
5210 // Check to see if DRQ is still up.
5211 if(statusByte
& IDE_STATUS_DRQ
) {
5212 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5214 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5215 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5217 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5220 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5223 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5225 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5227 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5228 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5229 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5233 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5234 //if ((statusByte & IDE_STATUS_DRQ)) {}
5235 if((statusByte
& IDE_STATUS_DRQ
) &&
5236 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5239 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5240 for (i
= 0; i
< 200; i
++) {
5241 GetStatus(chan
, statusByte
);
5242 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5247 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5248 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5253 AtapiStallExecution(TimerValue
);
5254 goto ServiceInterrupt
;
5255 #endif //UNIATA_CORE
5257 AtapiStallExecution(100);
5261 // reset the controller.
5262 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5264 goto IntrPrepareResetController
;
5268 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5269 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5270 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5272 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5273 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5277 // Clear interrupt expecting flag.
5278 chan
->ExpectingInterrupt
= FALSE
;
5279 InterlockedExchange(&(chan
->CheckIntr
),
5282 // Sanity check that there is a current request.
5284 // Set status in SRB.
5285 srb
->SrbStatus
= (UCHAR
)status
;
5287 // Check for underflow.
5288 if(AtaReq
->WordsLeft
) {
5290 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5291 // Subtract out residual words and update if filemark hit,
5292 // setmark hit , end of data, end of media...
5293 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5294 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5295 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5297 srb
->DataTransferLength
= 0;
5300 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5303 if(status
== SRB_STATUS_SUCCESS
) {
5304 AtaReq
->WordsTransfered
+= AtaReq
->bcount
* DEV_BSIZE
/2;
5306 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5307 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5308 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5309 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5310 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5313 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5314 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5318 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5321 // Indicate command complete.
5323 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5326 if (status
== SRB_STATUS_SUCCESS
&&
5327 srb
->SenseInfoBuffer
&&
5328 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5330 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5332 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5333 senseBuffer
->ErrorCode
= 0;
5334 senseBuffer
->Valid
= 1;
5335 senseBuffer
->AdditionalSenseLength
= 0xb;
5336 senseBuffer
->SenseKey
= 0;
5337 senseBuffer
->AdditionalSenseCode
= 0;
5338 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5340 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5342 AtapiDmaDBSync(chan
, srb
);
5343 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5344 UniataRemoveRequest(chan
, srb
);
5345 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5346 ScsiPortNotification(RequestComplete
,
5352 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5353 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5355 if (status
!= SRB_STATUS_SUCCESS
) {
5356 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5357 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5360 // Build the SMART status block depending upon the completion status.
5361 cmdOutParameters
->cBufferSize
= wordCount
;
5362 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5363 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5365 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5367 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5368 cmdOutParameters
->bBuffer
[0] = RETURN_SMART_STATUS
;
5369 cmdOutParameters
->bBuffer
[1] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
5370 cmdOutParameters
->bBuffer
[2] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Unused1
);
5371 cmdOutParameters
->bBuffer
[3] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5372 cmdOutParameters
->bBuffer
[4] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
);
5373 cmdOutParameters
->bBuffer
[5] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_DriveSelect
);
5374 cmdOutParameters
->bBuffer
[6] = SMART_CMD
;
5375 cmdOutParameters
->cBufferSize
= 8;
5378 // Indicate command complete.
5379 goto IntrCompleteReq
;
5384 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5389 for (i
= 0; i
< 5; i
++) {
5390 GetStatus(chan
, statusByte
);
5391 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5392 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5396 if (statusByte
& IDE_STATUS_DSC
) {
5397 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5401 AtapiStallExecution(50);
5404 // RDP can be cleared since previous check
5406 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5412 AtapiStallExecution(TimerValue
);
5413 goto ServiceInterrupt
;
5414 #endif //UNIATA_CORE
5417 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5420 srb
= UniataGetCurRequest(chan
);
5425 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5427 ScsiPortNotification(NextRequest
,
5431 ScsiPortNotification(NextLuRequest
,
5436 // in simplex mode next command must NOT be sent here
5437 if(!deviceExtension
->simplexOnly
) {
5438 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5441 // Try to get SRB fron any non-empty queue (later)
5442 if(deviceExtension
->simplexOnly
) {
5445 #endif //UNIATA_CORE
5447 goto ReturnEnableIntr
;
5451 // Unexpected int. Catch it
5452 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
5460 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
5462 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
5463 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
5464 #ifdef UNIATA_USE_XXableInterrupts
5465 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
5466 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
5467 // must be called on DISPATCH_LEVEL
5468 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
5469 AtapiEnableInterrupts__
);
5471 AtapiEnableInterrupts(HwDeviceExtension
, c
);
5472 InterlockedExchange(&(chan
->CheckIntr
),
5474 // Will raise IRQL to DIRQL
5476 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
5477 AtapiEnableInterrupts__
,
5479 #endif // UNIATA_CORE
5480 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5481 #endif // UNIATA_USE_XXableInterrupts
5485 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
5486 // in simplex mode next command must be sent here if
5488 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
5491 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
5492 chan
= UniataGetNextChannel(chan
);
5494 srb
= UniataGetCurRequest(chan
);
5498 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
5500 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5503 #endif //UNIATA_CORE
5506 } // end AtapiInterrupt__()
5512 Routine Description:
5514 This routine handles SMART enable, disable, read attributes and threshold commands.
5518 HwDeviceExtension - HBA miniport driver's adapter data storage
5519 Srb - IO request packet
5528 IdeSendSmartCommand(
5529 IN PVOID HwDeviceExtension
,
5530 IN PSCSI_REQUEST_BLOCK Srb
5533 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5534 ULONG c
= GET_CHANNEL(Srb
);
5535 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
5536 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5537 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5538 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5539 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
5541 UCHAR statusByte
,targetId
;
5544 if (regs
->bCommandReg
!= SMART_CMD
) {
5545 KdPrint2((PRINT_PREFIX
5546 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
5547 return SRB_STATUS_INVALID_REQUEST
;
5550 targetId
= cmdInParameters
.bDriveNumber
;
5552 //TODO optimize this check
5553 if ((!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) ||
5554 (deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
5556 return SRB_STATUS_SELECTION_TIMEOUT
;
5559 chan
->SmartCommand
= regs
->bFeaturesReg
;
5561 // Determine which of the commands to carry out.
5562 switch(regs
->bFeaturesReg
) {
5563 case READ_ATTRIBUTES
:
5564 case READ_THRESHOLDS
:
5566 statusByte
= WaitOnBusy(chan
);
5568 if (statusByte
& IDE_STATUS_BUSY
) {
5569 KdPrint2((PRINT_PREFIX
5570 "IdeSendSmartCommand: Returning BUSY status\n"));
5571 return SRB_STATUS_BUSY
;
5574 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5575 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
5577 // Set data buffer pointer and words left.
5578 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5579 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
5581 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5583 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5585 regs
->bSectorNumberReg
,
5586 regs
->bSectorCountReg
,
5590 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5591 // Wait for interrupt.
5592 return SRB_STATUS_PENDING
;
5594 return SRB_STATUS_ERROR
;
5598 case RETURN_SMART_STATUS
:
5599 case ENABLE_DISABLE_AUTOSAVE
:
5600 case EXECUTE_OFFLINE_DIAGS
:
5601 case SAVE_ATTRIBUTE_VALUES
:
5603 statusByte
= WaitOnBusy(chan
);
5605 if (statusByte
& IDE_STATUS_BUSY
) {
5606 KdPrint2((PRINT_PREFIX
5607 "IdeSendSmartCommand: Returning BUSY status\n"));
5608 return SRB_STATUS_BUSY
;
5611 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5612 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
5614 // Set data buffer pointer and indicate no data transfer.
5615 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5616 AtaReq
->WordsLeft
= 0;
5618 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5620 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5622 regs
->bSectorNumberReg
,
5623 regs
->bSectorCountReg
,
5627 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5628 // Wait for interrupt.
5629 return SRB_STATUS_PENDING
;
5631 return SRB_STATUS_ERROR
;
5632 } // end switch(regs->bFeaturesReg)
5634 return SRB_STATUS_INVALID_REQUEST
;
5636 } // end IdeSendSmartCommand()
5638 #endif //UNIATA_CORE
5642 UniAtaCalculateLBARegs(
5643 PHW_LU_EXTENSION LunExt
,
5644 ULONG startingSector
,
5648 UCHAR drvSelect
,sectorNumber
;
5652 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5653 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
5654 if(LunExt
->DeviceExtension
) {
5655 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
5658 return startingSector
;
5660 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5661 LunExt
->IdentifyData
.NumberOfHeads
;
5663 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5667 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
5669 cylinder
= (USHORT
)(startingSector
/ tmp
);
5670 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5671 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5672 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
5673 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
5674 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
5678 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5679 } // end UniAtaCalculateLBARegs()
5683 UniAtaCalculateLBARegsBack(
5684 PHW_LU_EXTENSION LunExt
,
5688 ULONG drvSelect
,sectorNumber
;
5692 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5695 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5696 LunExt
->IdentifyData
.NumberOfHeads
;
5698 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5699 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5700 sectorNumber
= (UCHAR
)(lba
& 0xff);
5702 lba
= sectorNumber
-1 +
5703 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5707 } // end UniAtaCalculateLBARegsBack()
5712 Routine Description:
5714 This routine handles IDE read and writes.
5718 HwDeviceExtension - HBA miniport driver's adapter data storage
5719 Srb - IO request packet
5729 IN PVOID HwDeviceExtension
,
5730 IN PSCSI_REQUEST_BLOCK Srb
,
5734 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5735 UCHAR lChannel
= GET_CHANNEL(Srb
);
5736 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5737 PHW_LU_EXTENSION LunExt
;
5738 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5739 //ULONG ldev = GET_LDEV(Srb);
5740 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
5741 ULONG startingSector
;
5743 ULONG wordCount
= 0;
5744 UCHAR statusByte
,statusByte2
;
5747 BOOLEAN use_dma
= FALSE
;
5750 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5751 LunExt
= chan
->lun
[DeviceNumber
];
5753 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5754 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5756 if(LunExt
->opt_ReadOnly
&&
5757 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
5758 if(LunExt
->opt_ReadOnly
== 1) {
5759 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
5760 return SRB_STATUS_ERROR
;
5762 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
5763 return SRB_STATUS_SUCCESS
;
5767 // Set data buffer pointer and words left.
5768 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5770 if(AtaReq
->WordsTransfered
) {
5771 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
5772 startingSector
= (ULONG
)(UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
5773 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
5774 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
5776 AtaReq
->TransferLength
/2,
5777 AtaReq
->WordsTransfered
,
5780 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
5781 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5782 // Set up 1st block.
5783 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5784 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5785 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
5787 AtaReq
->TransferLength
/2,
5790 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5793 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
5795 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
5796 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5798 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5805 // assume best case here
5806 // we cannot reinit Dma until previous request is completed
5807 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5809 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5810 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5811 (PUCHAR
)(AtaReq
->DataBuffer
),
5812 AtaReq
->bcount
* DEV_BSIZE
)) {
5817 if(use_dma
&& (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5818 UniataAhciSetupCmdPtr(AtaReq
);
5819 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
5820 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
5822 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
5823 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
5824 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: /*IDE_COMMAND_WRITE_DMA*/ IDE_COMMAND_READ_DMA
,
5826 (USHORT
)(AtaReq
->bcount
),
5832 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
5833 return SRB_STATUS_ERROR
;
5836 AtaReq
->ahci
.io_cmd_flags
= (USHORT
)(((AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
) |
5837 /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
5838 (fis_size
/ sizeof(ULONG
)) |
5839 (DeviceNumber
<< 12));
5840 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
5843 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5845 } else { // exec_only
5846 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5849 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5853 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5855 return SRB_STATUS_PENDING
;
5858 // if this is queued request, reinit DMA and check
5859 // if DMA mode is still available
5860 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
5861 if (/*EnableDma &&*/
5862 (LunExt
->TransferMode
>= ATA_DMA
)) {
5865 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5869 // Check if write request.
5870 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5872 // Prepare read command.
5874 cmd
= IDE_COMMAND_READ_DMA
;
5876 if(LunExt
->MaximumBlockXfer
) {
5877 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5879 cmd
= IDE_COMMAND_READ
;
5883 // Prepare write command.
5885 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
5886 cmd
= IDE_COMMAND_WRITE_DMA
;
5888 if (LunExt
->MaximumBlockXfer
) {
5889 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5891 if (AtaReq
->WordsLeft
< wordCount
) {
5892 // Transfer only words requested.
5893 wordCount
= AtaReq
->WordsLeft
;
5895 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5898 wordCount
= DEV_BSIZE
/2;
5899 cmd
= IDE_COMMAND_WRITE
;
5904 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5905 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5907 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5909 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5912 if(use_dma
&& (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5913 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
5914 UniataAhciBeginTransaction(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5915 return SRB_STATUS_PENDING
;
5918 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5920 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5922 (USHORT
)(AtaReq
->bcount
),
5923 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5925 if(statusByte2
!= 0xff) {
5926 GetStatus(chan
, statusByte2
);
5928 if(statusByte2
& IDE_STATUS_ERROR
) {
5929 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5930 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5931 return SRB_STATUS_ERROR
;
5934 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5936 return SRB_STATUS_PENDING
;
5939 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5941 (USHORT
)(AtaReq
->bcount
),
5942 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5945 if (!(statusByte
& IDE_STATUS_DRQ
) ||
5946 statusByte
== 0xff) {
5948 if(statusByte
== 0xff) {
5949 KdPrint2((PRINT_PREFIX
5950 "IdeReadWrite: error sending command (%#x)\n",
5953 KdPrint2((PRINT_PREFIX
5954 "IdeReadWrite: DRQ never asserted (%#x)\n",
5958 AtaReq
->WordsLeft
= 0;
5960 // Clear interrupt expecting flag.
5961 chan
->ExpectingInterrupt
= FALSE
;
5962 InterlockedExchange(&(chan
->CheckIntr
),
5965 // Clear current SRB.
5966 UniataRemoveRequest(chan
, Srb
);
5968 return (statusByte
== 0xff) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
5971 chan
->ExpectingInterrupt
= TRUE
;
5972 InterlockedExchange(&(chan
->CheckIntr
),
5975 // Write next DEV_BSIZE/2*N words.
5976 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5977 KdPrint2((PRINT_PREFIX
5978 "IdeReadWrite: Write %#x words\n", wordCount
));
5983 UniataGetPioTiming(LunExt
));
5987 KdPrint2((PRINT_PREFIX
5988 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5991 (PULONG
)(AtaReq
->DataBuffer
),
5993 UniataGetPioTiming(LunExt
));
5996 // Adjust buffer address and words left count.
5997 AtaReq
->WordsLeft
-= wordCount
;
5998 AtaReq
->DataBuffer
+= wordCount
;
6000 // Wait for interrupt.
6001 return SRB_STATUS_PENDING
;
6003 } // end IdeReadWrite()
6009 Routine Description:
6010 This routine handles IDE Verify.
6013 HwDeviceExtension - HBA miniport driver's adapter data storage
6014 Srb - IO request packet
6023 IN PVOID HwDeviceExtension
,
6024 IN PSCSI_REQUEST_BLOCK Srb
6027 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6028 UCHAR lChannel
= GET_CHANNEL(Srb
);
6029 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6030 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6031 PHW_LU_EXTENSION LunExt
;
6032 //ULONG ldev = GET_LDEV(Srb);
6033 ULONG DeviceNumber
= GET_CDEV(Srb
);
6035 ULONG startingSector
;
6042 LunExt
= chan
->lun
[DeviceNumber
];
6043 // Drive has these number sectors.
6044 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6045 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6046 LunExt
->IdentifyData
.NumberOfHeads
*
6047 LunExt
->IdentifyData
.NumberOfCylinders
;
6050 KdPrint2((PRINT_PREFIX
6051 "IdeVerify: Total sectors %#x\n",
6054 // Get starting sector number from CDB.
6055 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6056 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6058 KdPrint2((PRINT_PREFIX
6059 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
6063 endSector
= startingSector
+ sectorCount
;
6065 KdPrint2((PRINT_PREFIX
6066 "IdeVerify: Ending sector %#x\n",
6069 if (endSector
> sectors
) {
6071 // Too big, round down.
6072 KdPrint2((PRINT_PREFIX
6073 "IdeVerify: Truncating request to %#x blocks\n",
6074 sectors
- startingSector
- 1));
6076 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
6080 // Set up sector count register. Round up to next block.
6081 if (sectorCount
> 0xFF) {
6082 sectorCount
= (USHORT
)0xFF;
6086 // Set data buffer pointer and words left.
6087 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6088 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6090 // Indicate expecting an interrupt.
6091 InterlockedExchange(&(chan
->CheckIntr
),
6094 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6096 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6097 IDE_COMMAND_VERIFY
, lba
,
6101 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6102 // Wait for interrupt.
6103 return SRB_STATUS_PENDING
;
6105 return SRB_STATUS_ERROR
;
6107 } // end IdeVerify()
6109 #endif //UNIATA_CORE
6113 Routine Description:
6114 Send ATAPI packet command to device.
6117 HwDeviceExtension - HBA miniport driver's adapter data storage
6118 Srb - IO request packet
6126 IN PVOID HwDeviceExtension
,
6127 IN PSCSI_REQUEST_BLOCK Srb
,
6131 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6132 UCHAR lChannel
= GET_CHANNEL(Srb
);
6133 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6134 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6135 PHW_LU_EXTENSION LunExt
;
6136 //ULONG ldev = GET_LDEV(Srb);
6137 ULONG DeviceNumber
= GET_CDEV(Srb
);
6140 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
6141 BOOLEAN use_dma
= FALSE
;
6142 BOOLEAN dma_reinited
= FALSE
;
6143 BOOLEAN retried
= FALSE
;
6146 LunExt
= chan
->lun
[DeviceNumber
];
6148 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
6149 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6150 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6152 #ifdef UNIATA_DUMP_ATAPI
6153 if(CmdAction
& CMD_ACTION_PREPARE
) {
6157 PCHAR ModeSelectData
;
6160 Cdb
= (PCDB
)(Srb
->Cdb
);
6161 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6162 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6163 CdbDataLen
= Srb
->DataTransferLength
;
6165 if(CdbDataLen
> 0x1000) {
6166 CdbDataLen
= 0x1000;
6170 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6171 KdPrint2(("P:T:D=%d:%d:%d\n",
6175 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
6178 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
6179 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6180 Cdb
->WRITE_CD
.LBA
[0],
6181 Cdb
->WRITE_CD
.LBA
[1],
6182 Cdb
->WRITE_CD
.LBA
[2],
6183 Cdb
->WRITE_CD
.LBA
[3]
6186 if(ScsiCommand
== SCSIOP_WRITE12
) {
6187 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6188 Cdb
->CDB12READWRITE
.LBA
[0],
6189 Cdb
->CDB12READWRITE
.LBA
[1],
6190 Cdb
->CDB12READWRITE
.LBA
[2],
6191 Cdb
->CDB12READWRITE
.LBA
[3]
6194 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
6195 KdPrint(("ModeSelect 6\n"));
6196 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6197 ModeSelectData
= CdbData
+4;
6198 KdDump(CdbData
, CdbDataLen
);
6200 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
6201 KdPrint(("ModeSelect 10\n"));
6202 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6203 ModeSelectData
= CdbData
+8;
6204 KdDump(CdbData
, CdbDataLen
);
6206 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6207 KdPrint(("Send buffer to device:\n"));
6208 KdDump(CdbData
, CdbDataLen
);
6213 #endif //UNIATA_DUMP_ATAPI
6216 if(CmdAction
== CMD_ACTION_PREPARE
) {
6217 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
6218 switch (Srb
->Cdb
[0]) {
6222 case SCSIOP_WRITE12
:
6226 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
6227 return SRB_STATUS_BUSY
;
6230 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6231 !AtaReq
->OriginalSrb
) {
6232 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6233 return SRB_STATUS_BUSY
;
6237 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6238 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6240 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
6241 // Set data buffer pointer and words left.
6242 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6243 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6244 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6245 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6247 // check if reorderable
6248 switch(Srb
->Cdb
[0]) {
6250 case SCSIOP_WRITE12
:
6252 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6258 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6260 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6262 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6263 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6264 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
6265 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6269 // check if DMA read/write
6270 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6271 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6273 if(AtaReq
->TransferLength
) {
6275 switch(Srb
->Cdb
[0]) {
6277 case SCSIOP_WRITE12
:
6278 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
6284 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
6286 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6287 (PUCHAR
)(AtaReq
->DataBuffer
),
6288 Srb
->DataTransferLength
6289 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
6291 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6296 case SCSIOP_READ_CD
:
6297 if(deviceExtension
->opt_AtapiDmaRawRead
)
6298 goto call_dma_setup
;
6302 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
6303 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6308 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
6309 KdPrint2((PRINT_PREFIX
"dma RO\n"));
6320 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6321 (PUCHAR
)(AtaReq
->DataBuffer
),
6322 Srb
->DataTransferLength
)) {
6323 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
6326 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6330 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
6334 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6335 UniataAhciSetupCmdPtr(AtaReq
);
6336 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
6337 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6338 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, 16);
6340 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6341 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6342 IDE_COMMAND_ATAPI_PACKET
/* command */,
6344 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
6345 use_dma
? ATA_F_DMA
: 0/* feature */,
6346 ATA_IMMEDIATE
/* flags */
6350 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
6351 return SRB_STATUS_ERROR
;
6354 AtaReq
->ahci
.io_cmd_flags
= (USHORT
)(((AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
) |
6355 /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
6356 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
) |
6357 (fis_size
/ sizeof(ULONG
)) |
6358 (DeviceNumber
<< 12));
6359 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6363 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6364 // if this is queued request, reinit DMA and check
6365 // if DMA mode is still available
6366 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
6367 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6368 if (/*EnableDma &&*/
6369 (LunExt
->TransferMode
>= ATA_DMA
)) {
6370 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
6373 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6374 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
6377 dma_reinited
= TRUE
;
6381 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6382 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
6383 return SRB_STATUS_PENDING
;
6385 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6386 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6387 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6390 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6391 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
6393 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6394 //AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
6395 } if(AtaReq
->TransferLength
) {
6397 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
6398 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6399 if (/*EnableDma &&*/
6400 (LunExt
->TransferMode
>= ATA_DMA
)) {
6403 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6408 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
6410 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6411 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
6412 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
6413 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6416 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6417 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6418 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6421 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
6424 // We need to know how many platters our atapi cd-rom device might have.
6425 // Before anyone tries to send a srb to our target for the first time,
6426 // we must "secretly" send down a separate mechanism status srb in order to
6427 // initialize our device extension changer data. That's how we know how
6428 // many platters our target has.
6430 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6431 !AtaReq
->OriginalSrb
) {
6435 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6436 // Set this flag now. If the device hangs on the mech. status
6437 // command, we will not have the chance to set it.
6438 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6440 chan
->MechStatusRetryCount
= 3;
6441 AtaReq
->OriginalSrb
= Srb
;
6442 AtaReq
->Srb
= BuildMechanismStatusSrb (
6446 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6447 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6448 if (srbStatus
== SRB_STATUS_PENDING
) {
6449 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6452 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6453 AtaReq
->OriginalSrb
= NULL
;
6454 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6455 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6456 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6460 #endif //UNIATA_CORE
6462 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
6463 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
6465 // Make sure command is to ATAPI device.
6466 flags
= LunExt
->DeviceFlags
;
6467 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6468 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
6470 // Indicate no device found at this address.
6471 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6472 return SRB_STATUS_SELECTION_TIMEOUT
;
6474 } else if(Srb
->Lun
> 0) {
6475 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6476 return SRB_STATUS_SELECTION_TIMEOUT
;
6479 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
6480 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6481 return SRB_STATUS_SELECTION_TIMEOUT
;
6484 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6485 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
6487 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6489 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6491 UniataAhciBeginTransaction(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6492 return SRB_STATUS_PENDING
;
6495 // Select device 0 or 1.
6496 SelectDrive(chan
, DeviceNumber
);
6498 // Verify that controller is ready for next command.
6499 GetStatus(chan
, statusByte
);
6500 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
6502 if(statusByte
== 0xff) {
6503 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
6506 if(statusByte
& IDE_STATUS_BUSY
) {
6507 if(statusByte
& IDE_STATUS_DSC
) {
6508 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
6510 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
6511 // We have to make reset here, since we are expecting device to be available
6512 //return SRB_STATUS_BUSY; // this cause queue freeze
6516 if(statusByte
& IDE_STATUS_ERROR
) {
6517 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
6519 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
6520 // Read the error reg. to clear it and fail this request.
6521 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6522 return MapError(deviceExtension
, Srb
);
6524 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
6527 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
6528 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
6529 if((!(statusByte
& IDE_STATUS_DSC
)) &&
6530 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6532 AtapiStallExecution(200);
6533 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6534 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6535 return SRB_STATUS_PENDING
;
6538 if(IS_RDP(Srb
->Cdb
[0])) {
6540 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6544 if(statusByte
& IDE_STATUS_DRQ
) {
6546 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6548 // Try to drain the data that one preliminary device thinks that it has
6549 // to transfer. Hopefully this random assertion of DRQ will not be present
6550 // in production devices.
6551 for (i
= 0; i
< 0x10000; i
++) {
6552 GetStatus(chan
, statusByte
);
6553 if(statusByte
& IDE_STATUS_DRQ
) {
6554 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6562 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6564 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6566 AtapiSoftReset(chan
, DeviceNumber
);
6568 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6569 // Re-initialize Atapi device.
6570 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
6572 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
6573 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
6575 // Inform the port driver that the bus has been reset.
6576 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6577 // Clean up device extension fields that AtapiStartIo won't.
6578 chan
->ExpectingInterrupt
= FALSE
;
6580 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6583 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6585 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
6586 return SRB_STATUS_BUS_RESET;
6589 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
6593 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
6594 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6595 return SRB_STATUS_SELECTION_TIMEOUT
;
6599 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6600 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6601 Srb
->Cdb
[1] &= ~0xE0;
6602 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6603 // Torisan changer. TUR's are overloaded to be platter switches.
6604 Srb
->Cdb
[7] = Srb
->Lun
;
6611 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6613 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6616 statusByte
= WaitOnBusy(chan
);
6617 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6620 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6621 use_dma
? ATA_F_DMA
: 0);
6623 // Write transfer byte count to registers.
6624 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6625 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6627 if (Srb
->DataTransferLength
>= 0x10000) {
6628 byteCountLow
= byteCountHigh
= 0xFF;
6631 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6632 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6634 if (flags
& DFLAGS_INT_DRQ
) {
6636 // This device interrupts when ready to receive the packet.
6638 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6641 chan
->ExpectingInterrupt
= TRUE
;
6642 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6643 InterlockedExchange(&(chan
->CheckIntr
),
6646 // Write ATAPI packet command.
6647 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6649 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
6650 return SRB_STATUS_PENDING
;
6654 // This device quickly sets DRQ when ready to receive the packet.
6656 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6659 chan
->ExpectingInterrupt
= TRUE
;
6660 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6661 InterlockedExchange(&(chan
->CheckIntr
),
6664 if(g_opt_AtapiSendDisableIntr
) {
6665 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6668 // Write ATAPI packet command.
6669 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6673 statusByte
= WaitForDrq(chan
);
6675 // Need to read status register and clear interrupt (if any)
6676 GetBaseStatus(chan
, statusByte
);
6678 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6680 if(g_opt_AtapiSendDisableIntr
) {
6681 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6683 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6684 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6685 return SRB_STATUS_ERROR
;
6688 GetStatus(chan
, statusByte
);
6689 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6691 // Send CDB to device.
6692 statusByte
= WaitOnBaseBusy(chan
);
6694 // Indicate expecting an interrupt and wait for it.
6695 chan
->ExpectingInterrupt
= TRUE
;
6696 InterlockedExchange(&(chan
->CheckIntr
),
6698 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6700 GetBaseStatus(chan
, statusByte
);
6702 if(g_opt_AtapiSendDisableIntr
) {
6703 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6711 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6712 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6715 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6717 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6718 return SRB_STATUS_PENDING
;
6720 } // end AtapiSendCommand()
6727 Routine Description:
6728 Program ATA registers for IDE disk transfer.
6731 HwDeviceExtension - ATAPI driver storage.
6732 Srb - System request block.
6735 SRB status (pending if all goes well).
6740 ULONG check_point
= 0;
6741 #define SetCheckPoint(cp) { check_point = (cp) ; }
6743 #define SetCheckPoint(cp)
6749 IN PVOID HwDeviceExtension
,
6750 IN PSCSI_REQUEST_BLOCK Srb
,
6755 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6758 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6766 UCHAR statusByte
,errorByte
;
6769 PMODE_PARAMETER_HEADER modeData
;
6774 //ULONG __ebp__ = 0;
6776 SetCheckPoint(0x20);
6777 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6782 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6783 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6784 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6785 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6786 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6788 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6789 Srb->SrbExtension));
6790 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6793 SetCheckPoint(0x30);
6794 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6796 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6798 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6800 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6802 lChannel
= GET_CHANNEL(Srb
);
6803 chan
= &(deviceExtension
->chan
[lChannel
]);
6804 //ldev = GET_LDEV(Srb);
6805 DeviceNumber
= GET_CDEV(Srb
);
6807 SetCheckPoint(0x40);
6808 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6809 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6811 if(CmdAction
== CMD_ACTION_PREPARE
) {
6812 switch (Srb
->Cdb
[0]) {
6814 case SCSIOP_INQUIRY
: // now it requires device access
6816 case SCSIOP_READ_CAPACITY
:
6819 case SCSIOP_REQUEST_SENSE
:
6821 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6826 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6827 return SRB_STATUS_BUSY
;
6831 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6832 switch (Srb
->Cdb
[0]) {
6833 case SCSIOP_INQUIRY
:
6835 KdPrint2((PRINT_PREFIX
6836 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6837 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6838 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6839 // which support up to two devices.
6840 if ((Srb
->Lun
!= 0) ||
6841 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6842 (Srb
->TargetId
> deviceExtension
->NumberLuns
)) {
6844 KdPrint2((PRINT_PREFIX
6845 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6846 // Indicate no device found at this address.
6847 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6852 KdPrint2((PRINT_PREFIX
6853 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6854 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6855 PIDENTIFY_DATA2 identifyData
= &(chan
->lun
[DeviceNumber
]->IdentifyData
);
6857 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6859 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
6860 KdPrint2((PRINT_PREFIX
6861 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6862 // Indicate no device found at this address.
6864 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6868 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
6869 KdPrint2((PRINT_PREFIX
6870 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6871 // Indicate no device found at this address.
6872 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
6874 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6879 // Zero INQUIRY data structure.
6880 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6882 // Standard IDE interface only supports disks.
6883 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6885 // Set the removable bit, if applicable.
6886 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6887 KdPrint2((PRINT_PREFIX
6888 "RemovableMedia\n"));
6889 inquiryData
->RemovableMedia
= 1;
6891 // Set the Relative Addressing (LBA) bit, if applicable.
6892 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6893 inquiryData
->RelativeAddressing
= 1;
6894 KdPrint2((PRINT_PREFIX
6895 "RelativeAddressing\n"));
6897 // Set the CommandQueue bit
6898 inquiryData
->CommandQueue
= 1;
6900 // Fill in vendor identification fields.
6901 for (i
= 0; i
< 24; i
+= 2) {
6902 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6905 // Initialize unused portion of product id.
6906 for (i = 0; i < 4; i++) {
6907 inquiryData->ProductId[12+i] = ' ';
6910 // Move firmware revision from IDENTIFY data to
6911 // product revision in INQUIRY data.
6912 for (i
= 0; i
< 4; i
+= 2) {
6913 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6916 status
= SRB_STATUS_SUCCESS
;
6921 case SCSIOP_MODE_SENSE
:
6923 KdPrint2((PRINT_PREFIX
6924 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6925 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6926 // This is used to determine if the media is write-protected.
6927 // Since IDE does not support mode sense then we will modify just the portion we need
6928 // so the higher level driver can determine if media is protected.
6929 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6931 SelectDrive(chan
, DeviceNumber
);
6932 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6933 statusByte
= WaitOnBusy(chan
);
6935 if (!(statusByte
& IDE_STATUS_ERROR
)){
6937 // no error occured return success, media is not protected
6938 chan
->ExpectingInterrupt
= FALSE
;
6939 InterlockedExchange(&(chan
->CheckIntr
),
6941 status
= SRB_STATUS_SUCCESS
;
6945 // error occured, handle it locally, clear interrupt
6946 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6948 GetBaseStatus(chan
, statusByte
);
6949 chan
->ExpectingInterrupt
= FALSE
;
6950 InterlockedExchange(&(chan
->CheckIntr
),
6952 status
= SRB_STATUS_SUCCESS
;
6954 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6956 //media is write-protected, set bit in mode sense buffer
6957 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6959 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6960 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6963 status
= SRB_STATUS_SUCCESS
;
6965 status
= SRB_STATUS_INVALID_REQUEST
;
6969 case SCSIOP_TEST_UNIT_READY
:
6971 KdPrint2((PRINT_PREFIX
6972 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6973 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6974 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6976 // Select device 0 or 1.
6977 SelectDrive(chan
, DeviceNumber
);
6978 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6980 // Wait for busy. If media has not changed, return success
6981 statusByte
= WaitOnBusy(chan
);
6983 if (!(statusByte
& IDE_STATUS_ERROR
)){
6984 chan
->ExpectingInterrupt
= FALSE
;
6985 InterlockedExchange(&(chan
->CheckIntr
),
6987 status
= SRB_STATUS_SUCCESS
;
6989 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6990 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6992 // Special case: If current media is write-protected,
6993 // the 0xDA command will always fail since the write-protect bit
6994 // is sticky,so we can ignore this error
6995 GetBaseStatus(chan
, statusByte
);
6996 chan
->ExpectingInterrupt
= FALSE
;
6997 InterlockedExchange(&(chan
->CheckIntr
),
6999 status
= SRB_STATUS_SUCCESS
;
7003 // Request sense buffer to be build
7004 chan
->ExpectingInterrupt
= TRUE
;
7005 InterlockedExchange(&(chan
->CheckIntr
),
7007 status
= SRB_STATUS_PENDING
;
7011 status
= SRB_STATUS_SUCCESS
;
7016 case SCSIOP_READ_CAPACITY
:
7018 KdPrint2((PRINT_PREFIX
7019 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7020 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7021 // Claim 512 byte blocks (big-endian).
7022 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7024 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7026 // Calculate last sector.
7027 if(!(i
= (ULONG
)chan
->lun
[DeviceNumber
]->NumOfSectors
)) {
7028 i
= chan
->lun
[DeviceNumber
]->IdentifyData
.SectorsPerTrack
*
7029 chan
->lun
[DeviceNumber
]->IdentifyData
.NumberOfHeads
*
7030 chan
->lun
[DeviceNumber
]->IdentifyData
.NumberOfCylinders
;
7034 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7035 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7036 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7038 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7040 KdPrint2((PRINT_PREFIX
7041 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7043 chan
->lun
[DeviceNumber
]->IdentifyData
.SectorsPerTrack
,
7044 chan
->lun
[DeviceNumber
]->IdentifyData
.NumberOfHeads
,
7045 chan
->lun
[DeviceNumber
]->IdentifyData
.NumberOfCylinders
));
7048 status
= SRB_STATUS_SUCCESS
;
7053 KdPrint2((PRINT_PREFIX
7054 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7055 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7056 status
= IdeVerify(HwDeviceExtension
,Srb
);
7063 KdPrint2((PRINT_PREFIX
7064 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7065 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
7066 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7067 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7068 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7069 status
= IdeReadWrite(HwDeviceExtension
,
7073 case SCSIOP_START_STOP_UNIT
:
7075 KdPrint2((PRINT_PREFIX
7076 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
7077 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7078 //Determine what type of operation we should perform
7079 cdb
= (PCDB
)Srb
->Cdb
;
7081 if (cdb
->START_STOP
.LoadEject
== 1){
7083 statusByte
= WaitOnBaseBusy(chan
);
7085 // first select device 0 or 1.
7086 SelectDrive(chan
, DeviceNumber
);
7087 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
7089 status
= SRB_STATUS_SUCCESS
;
7092 case SCSIOP_MEDIUM_REMOVAL
:
7094 cdb
= (PCDB
)Srb
->Cdb
;
7096 statusByte
= WaitOnBaseBusy(chan
);
7098 SelectDrive(chan
, DeviceNumber
);
7099 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
7100 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
7102 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
7104 status
= SRB_STATUS_SUCCESS
;
7107 // Note: I don't implement this, because NTFS driver too often issues this command
7108 // It causes awful performance degrade. However, if somebody wants, I will implement
7109 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
7112 case SCSIOP_FLUSH_BUFFER
:
7113 case SCSIOP_SYNCHRONIZE_CACHE
:
7115 SelectDrive(chan
, DeviceNumber
);
7116 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
7117 status
= SRB_STATUS_SUCCESS
;
7118 // status = SRB_STATUS_PENDING;
7119 statusByte
= WaitOnBusy(chan
);
7123 case SCSIOP_REQUEST_SENSE
:
7124 // this function makes sense buffers to report the results
7125 // of the original GET_MEDIA_STATUS command
7127 KdPrint2((PRINT_PREFIX
7128 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7129 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7130 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7131 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
7134 status
= SRB_STATUS_INVALID_REQUEST
;
7138 case SCSIOP_ATA_PASSTHROUGH
:
7141 BOOLEAN use_dma
= FALSE
;
7144 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
7146 lChannel
= Srb
->TargetId
>> 1;
7148 regs
->bDriveHeadReg
&= 0x0f;
7149 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
7151 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
7153 KdPrint2((PRINT_PREFIX
7154 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
7155 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7158 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7160 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
7161 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
7163 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
7164 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
7165 (PUCHAR
)(Srb
->DataBuffer
),
7166 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
7172 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
7173 AtapiStallExecution(10);
7175 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
7176 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
7177 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
7178 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
7179 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
7180 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
7182 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
7183 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
7184 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
7185 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
7186 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
7187 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
7188 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
7189 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
7190 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
7191 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
7193 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
7196 GetBaseStatus(chan
, statusByte
);
7197 if(statusByte
& IDE_STATUS_ERROR
) {
7198 goto passthrough_err
;
7200 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
7203 ScsiPortStallExecution(1); // wait for busy to be set
7205 if(regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) {
7206 to_lim
= Srb
->TimeOutValue
;
7208 if(Srb
->TimeOutValue
<= 2) {
7209 to_lim
= Srb
->TimeOutValue
*900;
7211 to_lim
= (Srb
->TimeOutValue
*999) - 500;
7214 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
7215 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
7216 GetBaseStatus(chan
, statusByte
);
7217 if(statusByte
& IDE_STATUS_ERROR
) {
7220 if(!(statusByte
& IDE_STATUS_BUSY
)) {
7225 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
7227 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
7228 goto passthrough_err
;
7232 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
7234 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
7235 GetBaseStatus(chan
, statusByte
);
7237 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
7238 AtapiSuckPort2(chan
);
7240 if (Srb
->SenseInfoBuffer
) {
7242 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
7244 senseBuffer
->ErrorCode
= 0x70;
7245 senseBuffer
->Valid
= 1;
7246 senseBuffer
->AdditionalSenseLength
= 0xb;
7247 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7248 senseBuffer
->AdditionalSenseCode
= 0;
7249 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7251 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
7252 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
7254 status
= SRB_STATUS_ERROR
;
7258 if (statusByte
& IDE_STATUS_DRQ
) {
7259 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7261 (PUSHORT
) Srb
->DataBuffer
,
7262 Srb
->DataTransferLength
/ 2,
7264 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7266 (PUSHORT
) Srb
->DataBuffer
,
7267 Srb
->DataTransferLength
/ 2,
7272 status
= SRB_STATUS_SUCCESS
;
7275 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7277 } else { // read task register
7279 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
7281 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
7283 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
7284 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7285 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
7286 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
7287 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
7288 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
7290 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7291 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7292 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
7293 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
7294 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
7295 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
7296 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
7297 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
7298 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
7299 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
7301 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
7302 status
= SRB_STATUS_SUCCESS
;
7309 KdPrint2((PRINT_PREFIX
7310 "IdeSendCommand: Unsupported command %#x\n",
7313 status
= SRB_STATUS_INVALID_REQUEST
;
7317 if(status
== SRB_STATUS_PENDING
) {
7318 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
7319 if(CmdAction
& CMD_ACTION_EXEC
) {
7320 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
7321 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
7324 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
7325 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7330 } // end IdeSendCommand()
7335 Routine Description:
7336 Enables disables media status notification
7339 HwDeviceExtension - ATAPI driver storage.
7346 IN PVOID HwDeviceExtension
,
7348 IN ULONG DeviceNumber
7351 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7353 UCHAR statusByte
,errorByte
;
7355 chan
= &(deviceExtension
->chan
[lChannel
]);
7357 if (EnableMSN
== TRUE
){
7359 // If supported enable Media Status Notification support
7360 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
7363 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
7364 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7365 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7367 if (statusByte
& IDE_STATUS_ERROR
) {
7368 // Read the error register.
7369 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7371 KdPrint2((PRINT_PREFIX
7372 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
7376 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
7377 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
7378 chan
->ReturningMediaStatus
= 0;
7383 } else { // end if EnableMSN == TRUE
7385 // disable if previously enabled
7386 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
7388 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
7389 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7390 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7391 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
7398 } // end IdeMediaStatus()
7403 Routine Description:
7405 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
7406 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
7409 HwDeviceExtension - ATAPI driver storage.
7410 Srb - System request block.
7414 SRB status (ALWAYS SUCCESS).
7419 IdeBuildSenseBuffer(
7420 IN PVOID HwDeviceExtension
,
7421 IN PSCSI_REQUEST_BLOCK Srb
7424 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7426 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
7427 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
7431 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
7433 senseBuffer
->ErrorCode
= 0x70;
7434 senseBuffer
->Valid
= 1;
7435 senseBuffer
->AdditionalSenseLength
= 0xb;
7436 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7437 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7438 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7439 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
7441 senseBuffer
->ErrorCode
= 0x70;
7442 senseBuffer
->Valid
= 1;
7443 senseBuffer
->AdditionalSenseLength
= 0xb;
7444 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7445 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7446 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7447 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
7449 senseBuffer
->ErrorCode
= 0x70;
7450 senseBuffer
->Valid
= 1;
7451 senseBuffer
->AdditionalSenseLength
= 0xb;
7452 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
7453 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
7454 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7455 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
7457 senseBuffer
->ErrorCode
= 0x70;
7458 senseBuffer
->Valid
= 1;
7459 senseBuffer
->AdditionalSenseLength
= 0xb;
7460 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
7461 senseBuffer
->AdditionalSenseCode
= 0;
7462 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7464 return SRB_STATUS_SUCCESS
;
7466 return SRB_STATUS_ERROR
;
7468 }// End of IdeBuildSenseBuffer
7472 UniataUserDeviceReset(
7473 PHW_DEVICE_EXTENSION deviceExtension
,
7474 PHW_LU_EXTENSION LunExt
,
7479 AtapiDisableInterrupts(deviceExtension
, PathId
);
7480 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
7481 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
7482 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), LunExt
->Lun
);
7484 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
7485 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
7486 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
7487 deviceExtension
->chan
[PathId
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7490 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7491 AtapiEnableInterrupts(deviceExtension
, PathId
);
7493 } // end UniataUserDeviceReset()
7498 PHW_DEVICE_EXTENSION deviceExtension
,
7503 BOOLEAN PostReq
= FALSE
;
7505 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
7506 if(chan
->queue_depth
> 0) {
7509 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
7510 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
7511 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
7513 status
= SRB_STATUS_BUSY
;
7522 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
7526 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
7529 } // end UniataNeedQueueing()
7533 Routine Description:
7535 This routine is called from the SCSI port driver synchronized
7536 with the kernel to start an IO request.
7540 HwDeviceExtension - HBA miniport driver's adapter data storage
7541 Srb - IO request packet
7551 IN PVOID HwDeviceExtension
,
7552 IN PSCSI_REQUEST_BLOCK Srb
7555 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
7556 } // end AtapiStartIo()
7561 IN PVOID HwDeviceExtension
,
7562 IN PSCSI_REQUEST_BLOCK Srb
,
7566 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7569 PHW_LU_EXTENSION LunExt
;
7577 PSCSI_REQUEST_BLOCK tmpSrb
;
7578 BOOLEAN PostReq
= FALSE
;
7580 BOOLEAN commPort
= FALSE
;
7582 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
7583 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7584 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7585 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7587 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7589 /* KeBugCheckEx(0xc000000e,
7590 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7592 TopLevel, 0x80000001);
7594 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7595 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7596 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7601 lChannel
= GET_CHANNEL(Srb
);
7602 //ldev = GET_LDEV(Srb);
7605 DeviceNumber
= GET_CDEV(Srb
);
7607 //ASSERT(deviceExtension);
7610 KdPrint2((PRINT_PREFIX
7611 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7612 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7613 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7615 if(lChannel
== deviceExtension
->NumberChannels
&&
7616 !Srb
->Lun
&& !Srb
->TargetId
&&
7617 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
7618 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
7620 KdPrint2((PRINT_PREFIX
7621 "AtapiStartIo: Communication port\n"));
7622 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
7624 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7626 KdPrint2((PRINT_PREFIX
7628 // Zero INQUIRY data structure.
7629 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7631 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
7633 // Fill in vendor identification fields.
7634 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
7636 status
= SRB_STATUS_SUCCESS
;
7640 /* Pass IOCTL request down */
7642 if(lChannel
>= deviceExtension
->NumberChannels
||
7643 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
7646 if(lChannel
>= deviceExtension
->NumberChannels
) {
7651 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
7652 KdPrint3((PRINT_PREFIX
7653 "AtapiStartIo: SRB rejected\n"));
7654 // Indicate no device found at this address.
7655 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7656 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7662 chan
= &(deviceExtension
->chan
[lChannel
]);
7663 LunExt
= chan
->lun
[DeviceNumber
];
7667 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7673 if(!commPort
&& !LunExt
) {
7675 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7678 deviceExtension
->NumberChannels
);
7679 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
7680 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7681 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7682 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7686 for(i=0; i<1000; i++) {
7687 AtapiStallExecution(3*1000);
7694 // Determine which function.
7695 switch (Srb
->Function
) {
7697 case SRB_FUNCTION_EXECUTE_SCSI
:
7699 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7700 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7701 // let passthrough go
7703 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7707 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
7708 KdPrint2((PRINT_PREFIX
7709 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7710 // Indicate no device found at this address.
7711 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7712 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7719 if(Srb->DataTransferLength) {
7721 a = ((PUCHAR)(Srb->DataBuffer))[0];
7724 } __except(EXCEPTION_EXECUTE_HANDLER) {
7725 KdPrint3((PRINT_PREFIX
7726 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7727 // Indicate no device found at this address.
7728 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7729 status = SRB_STATUS_ERROR;
7730 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7735 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7739 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
7741 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7742 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
7744 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7746 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7747 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7749 /*KeBugCheckEx(0xc000000e,
7750 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7752 status, 0x80000001);*/
7753 if(status
== SRB_STATUS_BUSY
)
7754 status
= SRB_STATUS_PENDING
;
7755 // Insert requests AFTER they have been initialized on
7756 // CMD_ACTION_PREPARE stage
7757 // we should not check TopLevel here (it is always TRUE)
7758 //ASSERT(chan->lun[GET_CDEV(Srb)]);
7759 UniataQueueRequest(chan
, Srb
);
7761 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7764 // Send command to device.
7765 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7767 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7768 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7769 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7770 //ASSERT(!AtaReq->Flags);
7771 //ASSERT(chan->lun[GET_CDEV(Srb)]);
7772 UniataQueueRequest(chan
, Srb
);
7773 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7774 //ASSERT(!AtaReq->Flags);
7775 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7776 //ASSERT(!AtaReq->Flags);
7780 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7784 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7785 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
7786 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
7790 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7794 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7803 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7804 KdPrint3((PRINT_PREFIX
"Try ATAPI send\n"));
7805 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7807 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7812 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7819 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7821 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7823 /* KeBugCheckEx(0xc000000e,
7824 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7826 status, 0x80000002);*/
7834 case SRB_FUNCTION_ABORT_COMMAND
:
7836 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7838 // Verify that SRB to abort is still outstanding.
7839 if((tmpSrb
!= Srb
->NextSrb
) ||
7840 !chan
->queue_depth
) {
7842 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7844 // Complete abort SRB.
7845 status
= SRB_STATUS_ABORT_FAILED
;
7849 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7850 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7851 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7852 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7853 // Log reset failure.
7854 KdPrint3((PRINT_PREFIX
7855 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7856 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7858 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7859 status
= SRB_STATUS_ERROR
;
7862 status
= SRB_STATUS_SUCCESS
;
7865 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7866 if (tmpSrb
->SenseInfoBuffer
&&
7867 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7869 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7871 senseBuffer
->ErrorCode
= 0;
7872 senseBuffer
->Valid
= 1;
7873 senseBuffer
->AdditionalSenseLength
= 0xb;
7874 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7875 senseBuffer
->AdditionalSenseCode
= 0;
7876 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7878 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7880 AtapiDmaDBSync(chan
, tmpSrb
);
7881 UniataRemoveRequest(chan
, tmpSrb
);
7882 // Indicate command complete.
7883 ScsiPortNotification(RequestComplete
,
7886 status
= SRB_STATUS_SUCCESS
;
7890 // Abort function indicates that a request timed out.
7891 // Call reset routine. Card will only be reset if
7892 // status indicates something is wrong.
7893 // Fall through to reset code.
7895 case SRB_FUNCTION_RESET_DEVICE
:
7896 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7898 // Reset single device.
7899 // For now we support only Lun=0
7901 // Note: reset is immediate command, it cannot be queued since it is usually used to
7902 // revert not- responding device to operational state
7903 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7904 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
7905 status
= SRB_STATUS_SUCCESS
;
7908 case SRB_FUNCTION_RESET_BUS
:
7910 // Reset Atapi and SCSI bus.
7912 // Note: reset is immediate command, it cannot be queued since it is usually used to
7913 // revert not- responding device to operational state
7914 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7915 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7916 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7917 // Log reset failure.
7918 KdPrint3((PRINT_PREFIX
7919 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7920 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7922 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7923 status
= SRB_STATUS_ERROR
;
7926 status
= SRB_STATUS_SUCCESS
;
7931 case SRB_FUNCTION_SHUTDOWN
:
7933 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7934 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7935 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7938 // FLUSH ATAPI device - do nothing
7939 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7941 // FLUSH IDE/ATA device
7942 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7943 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7944 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
7945 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7946 // If supported & allowed, reset write cacheing
7947 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7949 // Disable write cache
7950 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
7951 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7952 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7953 // Check for errors.
7954 if (status
& IDE_STATUS_ERROR
) {
7955 KdPrint2((PRINT_PREFIX
7956 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7959 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7961 // Re-enable write cache
7962 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
7963 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7964 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7965 // Check for errors.
7966 if (status
& IDE_STATUS_ERROR
) {
7967 KdPrint2((PRINT_PREFIX
7968 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7970 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7972 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7976 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7978 status
= SRB_STATUS_SUCCESS
;
7982 case SRB_FUNCTION_FLUSH
:
7984 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7985 status
= SRB_STATUS_SUCCESS
;
7988 /* case SRB_FUNCTION_SHUTDOWN:
7989 case SRB_FUNCTION_FLUSH:
7991 // Flush device's cache.
7992 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7994 if (chan->CurrentSrb) {
7996 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7997 Srb->SrbStatus = SRB_STATUS_BUSY;
7998 ScsiPortNotification(RequestComplete,
8004 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
8005 status = SRB_STATUS_SUCCESS;
8007 status = AtaCommand(deviceExtension, GET_CDEV(Srb), GET_CHANNEL(Srb),
8008 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
8009 if (status & IDE_STATUS_DRQ) {
8010 status = SRB_STATUS_SUCCESS;
8012 status = SRB_STATUS_SELECTION_TIMEOUT;
8017 case SRB_FUNCTION_IO_CONTROL
: {
8021 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
8023 len
= Srb
->DataTransferLength
;
8025 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
8027 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
8028 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
8030 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
8033 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
8035 // Version and revision per SMART 1.03
8037 versionParameters
->bVersion
= 1;
8038 versionParameters
->bRevision
= 1;
8039 versionParameters
->bReserved
= 0;
8041 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
8042 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
8044 // This is done because of how the IOCTL_SCSI_MINIPORT
8045 // determines 'targetid's'. Disk.sys places the real target id value
8046 // in the DeviceMap field. Once we do some parameter checking, the value passed
8047 // back to the application will be determined.
8049 deviceNumber
= versionParameters
->bIDEDeviceMap
;
8052 KdPrint2((PRINT_PREFIX
8053 "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
8054 // Indicate no device found at this address.
8055 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8056 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8060 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
8063 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8067 // NOTE: This will only set the bit
8068 // corresponding to this drive's target id.
8069 // The bit mask is as follows:
8075 if (deviceExtension
->NumberChannels
== 1) {
8076 if (chan
->PrimaryAddress
) {
8077 deviceNumber
= 1 << DeviceNumber
;
8079 deviceNumber
= 4 << DeviceNumber
;
8082 deviceNumber
= (1 << DeviceNumber
) << lChannel
;
8085 versionParameters
->bIDEDeviceMap
= deviceNumber
;
8087 status
= SRB_STATUS_SUCCESS
;
8091 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
8093 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
8094 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
8097 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
8098 // Extract the target.
8099 targetId
= cmdInParameters
.bDriveNumber
;
8100 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
8101 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
8102 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8103 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
8104 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8108 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
8110 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
8111 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
8112 status
= SRB_STATUS_INVALID_REQUEST
;
8118 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8119 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
8120 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
8121 status
= SRB_STATUS_INVALID_REQUEST
;
8125 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
8126 // Zero the output buffer
8127 RtlZeroMemory(cmdOutParameters
, len
);
8128 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
8129 ((PUCHAR)cmdOutParameters)[i] = 0;
8132 // Build status block.
8133 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
8134 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
8135 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
8137 // Extract the identify data from the device extension.
8138 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
8139 cmdOutParameters
->cBufferSize
);
8141 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
8143 status
= SRB_STATUS_SUCCESS
;
8147 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
8148 cmdInParameters
.irDriveRegs
.bCommandReg
));
8149 status
= SRB_STATUS_INVALID_REQUEST
;
8155 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
8156 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
8157 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
8158 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
8159 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
8160 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
8161 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
8162 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
8165 KdPrint2((PRINT_PREFIX
8166 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
8167 // Indicate no device found at this address.
8168 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8169 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8173 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8175 if(PostReq
|| TopLevel
) {
8176 UniataQueueRequest(chan
, Srb
);
8177 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8178 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8183 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
8184 status
= SRB_STATUS_PENDING
;
8186 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8189 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
8194 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
8195 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
8196 status
= SRB_STATUS_INVALID_REQUEST
;
8201 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
8203 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
8204 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
8205 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
8208 //chan = &(deviceExtension->chan[lChannel]);
8210 if(AtaCtl
->addr
.Lun
||
8211 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
8212 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
8220 lChannel
= AtaCtl
->addr
.PathId
;
8221 chan
= &(deviceExtension
->chan
[lChannel
]);
8222 LunExt
= chan
->lun
[DeviceNumber
];
8225 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
8227 /* check for valid LUN */
8228 switch (AtaCtl
->hdr
.ControlCode
) {
8229 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
8230 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
8231 // this would be BUS reset
8233 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
8234 AtaCtl
->addr
.TargetId
!= 0xff ||
8235 AtaCtl
->addr
.Lun
!= 0
8237 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
8238 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
8239 lChannel
= AtaCtl
->addr
.PathId
;
8240 chan
= &(deviceExtension
->chan
[lChannel
]);
8241 LunExt
= chan
->lun
[DeviceNumber
];
8244 goto handle_bad_ldev
;
8247 lChannel
= AtaCtl
->addr
.PathId
;
8248 chan
= &(deviceExtension
->chan
[lChannel
]);
8251 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
8252 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
8253 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
8254 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
8255 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
8258 KdPrint2((PRINT_PREFIX
8259 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
8260 // Indicate no device found at this address.
8265 /* check if queueing is necessary */
8266 switch (AtaCtl
->hdr
.ControlCode
) {
8267 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
8268 if(!LunExt
->nBadBlocks
) {
8271 goto uata_ctl_queue
;
8272 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
8273 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
8276 goto uata_ctl_queue
;
8277 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
8278 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
8280 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
8281 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8283 if(PostReq
|| TopLevel
) {
8284 UniataQueueRequest(chan
, Srb
);
8285 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8286 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8289 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
8290 status
= SRB_STATUS_PENDING
;
8292 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8295 } // end switch (AtaCtl->hdr.ControlCode)
8297 /* process request */
8298 switch (AtaCtl
->hdr
.ControlCode
) {
8299 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
8301 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
8303 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
8304 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
8305 if(AtaCtl
->addr
.TargetId
!= 0xff) {
8306 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
8311 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
8312 AtapiStallExecution(1000 * 1000);
8315 FindDevices(HwDeviceExtension
,
8316 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
8317 ? UNIATA_FIND_DEV_UNHIDE
: 0,
8318 AtaCtl
->addr
.PathId
);
8319 status
= SRB_STATUS_SUCCESS
;
8323 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
8325 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
8327 LunExt
->DeviceFlags
= 0;
8328 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
8329 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
8330 LunExt
->DeviceFlags
|= DFLAGS_HIDDEN
;
8333 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
8334 AtapiStallExecution(1000 * 1000);
8337 status
= SRB_STATUS_SUCCESS
;
8340 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
8342 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
8344 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
8345 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
8347 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
8348 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
8349 if(LunExt
->LimitedTransferMode
>
8350 LunExt
->OrigTransferMode
) {
8351 // check for incorrect value
8352 LunExt
->LimitedTransferMode
=
8353 LunExt
->OrigTransferMode
;
8356 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
8358 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8359 if(AtaCtl
->SetMode
.ApplyImmediately
) {
8360 AtapiDmaInit__(deviceExtension
, LunExt
);
8362 /* LunExt->TransferMode =
8363 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
8364 status
= SRB_STATUS_SUCCESS
;
8367 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
8369 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
8371 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
8372 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
8373 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
8375 status
= SRB_STATUS_SUCCESS
;
8378 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
8380 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
8382 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
8383 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
8384 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
8385 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
8386 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
8388 status
= SRB_STATUS_SUCCESS
;
8391 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
8393 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
8395 AtaCtl
->AdapterInfo
.HeaderLength
= FIELD_OFFSET(ADAPTERINFO
, Chan
);
8397 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
8398 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
8399 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
8400 status
= SRB_STATUS_DATA_OVERRUN
;
8404 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
8405 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
8406 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
8407 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
8408 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
8409 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
8410 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
8411 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
8412 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
8413 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
8414 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
8415 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
8416 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
8417 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
8418 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
8419 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
8420 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
8421 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
8422 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
8423 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
8424 if(deviceExtension
->FullDevName
) {
8425 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
8427 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
8428 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
8430 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
8432 status
= SRB_STATUS_SUCCESS
;
8435 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
8437 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
8439 ForgetBadBlocks(LunExt
);
8441 status
= SRB_STATUS_SUCCESS
;
8444 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
8446 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
8451 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
8454 status
= SRB_STATUS_SUCCESS
;
8458 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
8459 AtaCtl
->hdr
.ControlCode
));
8460 status
= SRB_STATUS_INVALID_REQUEST
;
8465 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
8466 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
8467 "SCSIDISK", "-UNIATA-"));
8469 status
= SRB_STATUS_INVALID_REQUEST
;
8474 } // end SRB_FUNCTION_IO_CONTROL
8477 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
8478 // Indicate unsupported command.
8479 status
= SRB_STATUS_INVALID_REQUEST
;
8487 PathId
= Srb
->PathId
;
8488 TargetId
= Srb
->TargetId
;
8491 if (status
!= SRB_STATUS_PENDING
) {
8493 KdPrint2((PRINT_PREFIX
8494 "AtapiStartIo: Srb %#x complete with status %#x\n",
8498 // Set status in SRB.
8499 Srb
->SrbStatus
= (UCHAR
)status
;
8501 AtapiDmaDBSync(chan
, Srb
);
8502 UniataRemoveRequest(chan
, Srb
);
8503 // Indicate command complete.
8504 ScsiPortNotification(RequestComplete
,
8508 // Remove current Srb & get next one
8509 if((Srb
= UniataGetCurRequest(chan
))) {
8510 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8511 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
8512 // current request is under precessing, thus
8513 // we should do nothing here
8521 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
8523 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
8525 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
8526 // Indicate ready for next request.
8527 ScsiPortNotification(NextRequest
,
8531 ScsiPortNotification(NextLuRequest
,
8539 } // end AtapiStartIo__()
8544 UniataInitAtaCommands()
8550 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
8552 for(i
=0; i
<256; i
++) {
8557 KdPrint2((PRINT_PREFIX
"cmd %2.2x: ", command
));
8560 case IDE_COMMAND_READ_DMA48
:
8561 case IDE_COMMAND_READ_DMA_Q48
:
8562 case IDE_COMMAND_READ_STREAM_DMA48
:
8563 case IDE_COMMAND_READ_STREAM48
:
8564 case IDE_COMMAND_WRITE_DMA48
:
8565 case IDE_COMMAND_WRITE_DMA_Q48
:
8566 case IDE_COMMAND_READ_DMA_Q
:
8567 case IDE_COMMAND_READ_DMA
:
8568 case IDE_COMMAND_WRITE_DMA
:
8569 case IDE_COMMAND_WRITE_DMA_Q
:
8570 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8571 case IDE_COMMAND_WRITE_STREAM48
:
8572 case IDE_COMMAND_WRITE_FUA_DMA48
:
8573 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8574 case IDE_COMMAND_READ_LOG_DMA48
:
8575 case IDE_COMMAND_WRITE_LOG_DMA48
:
8576 case IDE_COMMAND_TRUSTED_RCV_DMA
:
8577 case IDE_COMMAND_TRUSTED_SEND_DMA
:
8578 KdPrint2((PRINT_PREFIX
"DMA "));
8579 flags
|= ATA_CMD_FLAG_DMA
;
8583 case IDE_COMMAND_READ48
:
8584 case IDE_COMMAND_READ_DMA48
:
8585 case IDE_COMMAND_READ_DMA_Q48
:
8586 case IDE_COMMAND_READ_MUL48
:
8587 case IDE_COMMAND_READ_STREAM_DMA48
:
8588 case IDE_COMMAND_READ_STREAM48
:
8589 case IDE_COMMAND_WRITE48
:
8590 case IDE_COMMAND_WRITE_DMA48
:
8591 case IDE_COMMAND_WRITE_DMA_Q48
:
8592 case IDE_COMMAND_WRITE_MUL48
:
8593 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8594 case IDE_COMMAND_WRITE_STREAM48
:
8595 case IDE_COMMAND_WRITE_FUA_DMA48
:
8596 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8597 case IDE_COMMAND_WRITE_MUL_FUA48
:
8598 case IDE_COMMAND_FLUSH_CACHE48
:
8599 case IDE_COMMAND_VERIFY48
:
8601 KdPrint2((PRINT_PREFIX
"48 "));
8602 flags
|= ATA_CMD_FLAG_48
;
8605 case IDE_COMMAND_READ
:
8606 case IDE_COMMAND_READ_MULTIPLE
:
8607 case IDE_COMMAND_READ_DMA
:
8608 case IDE_COMMAND_READ_DMA_Q
:
8609 case IDE_COMMAND_WRITE
:
8610 case IDE_COMMAND_WRITE_MULTIPLE
:
8611 case IDE_COMMAND_WRITE_DMA
:
8612 case IDE_COMMAND_WRITE_DMA_Q
:
8613 case IDE_COMMAND_FLUSH_CACHE
:
8614 case IDE_COMMAND_VERIFY
:
8616 KdPrint2((PRINT_PREFIX
"LBA "));
8617 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
8620 flags
|= ATA_CMD_FLAG_48supp
;
8623 case IDE_COMMAND_READ
:
8624 command
= IDE_COMMAND_READ48
; break;
8625 case IDE_COMMAND_READ_MULTIPLE
:
8626 command
= IDE_COMMAND_READ_MUL48
; break;
8627 case IDE_COMMAND_READ_DMA
:
8628 command
= IDE_COMMAND_READ_DMA48
; break;
8629 case IDE_COMMAND_READ_DMA_Q
:
8630 command
= IDE_COMMAND_READ_DMA_Q48
; break;
8631 case IDE_COMMAND_WRITE
:
8632 command
= IDE_COMMAND_WRITE48
; break;
8633 case IDE_COMMAND_WRITE_MULTIPLE
:
8634 command
= IDE_COMMAND_WRITE_MUL48
; break;
8635 case IDE_COMMAND_WRITE_DMA
:
8636 command
= IDE_COMMAND_WRITE_DMA48
; break;
8637 case IDE_COMMAND_WRITE_DMA_Q
:
8638 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
8639 case IDE_COMMAND_FLUSH_CACHE
:
8640 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
8641 // case IDE_COMMAND_READ_NATIVE_SIZE:
8642 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
8643 case IDE_COMMAND_SET_NATIVE_SIZE
:
8644 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
8645 case IDE_COMMAND_VERIFY
:
8646 command
= IDE_COMMAND_VERIFY48
; break;
8648 KdPrint2((PRINT_PREFIX
"!28->48 "));
8649 flags
&= ~ATA_CMD_FLAG_48supp
;
8652 KdPrint2((PRINT_PREFIX
"\t -> %2.2x (%2.2x)\n", command
, flags
));
8653 AtaCommands48
[i
] = command
;
8654 AtaCommandFlags
[i
] = flags
;
8656 } // end UniataInitAtaCommands()
8660 Routine Description:
8662 Installable driver initialization entry point for system.
8670 Status from ScsiPortInitialize()
8677 IN PVOID DriverObject
,
8681 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
8684 ULONG statusToReturn
, newStatus
;
8685 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
8686 BOOLEAN ReEnter
= FALSE
;
8688 #ifndef USE_REACTOS_DDK
8692 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
8693 BOOLEAN PrimaryClaimed
= FALSE
;
8694 BOOLEAN SecondaryClaimed
= FALSE
;
8696 LARGE_INTEGER t0
, t1
;
8699 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
8700 a
= (WCHAR
)strlen(ver_string
);
8702 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
8704 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
8707 if(!SavedDriverObject
) {
8708 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8709 #ifdef USE_REACTOS_DDK
8710 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8715 // we are here for the 1st time
8716 // init CrossNT and get OS version
8717 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
8718 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
8719 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
8722 #endif // USE_REACTOS_DDK
8723 KdPrint(("UniATA Init: OS ver %x.%x (%d)\n", MajorVersion
, MinorVersion
, BuildNumber
));
8725 KeQuerySystemTime(&t0
);
8727 KeQuerySystemTime(&t1
);
8728 } while(t0
.QuadPart
== t1
.QuadPart
);
8732 KeQuerySystemTime(&t1
);
8734 } while(t0
.QuadPart
== t1
.QuadPart
);
8735 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8736 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8738 KdPrint(("UniATA Init: ReEnter\n"));
8742 // (re)read bad block list
8743 InitBadBlocks(NULL
);
8746 // init ATA command translation table
8747 UniataInitAtaCommands();
8748 // get registry path to settings
8749 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8750 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8751 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8752 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8753 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8754 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8757 if(WinVer_Id() >= WinVer_2k
) {
8758 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
8759 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
8760 WinVer_WDM_Model
= TRUE
;
8762 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
8763 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
8764 WinVer_WDM_Model
= TRUE
;
8768 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8769 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8771 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8774 statusToReturn
= 0xffffffff;
8776 // Zero out structure.
8777 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8779 // Set size of hwInitializationData.
8780 hwInitializationData
.comm
.HwInitializationDataSize
=
8781 sizeof(hwInitializationData
.comm
) +
8782 // sizeof(hwInitializationData.nt4) +
8783 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8784 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
8786 // Set entry points.
8787 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8788 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8789 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8790 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8792 // Specify size of extensions.
8793 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8794 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8795 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8797 // Indicate PIO device.
8798 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8799 // Set PnP-specific API
8800 if(WinVer_Id() > WinVer_NT
) {
8801 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
8802 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8803 KdPrint(("set AtapiAdapterControl() ptr\n"));
8804 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8807 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8811 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
8812 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
8813 g_opt_VirtualMachine
= 0;
8815 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
8816 g_opt_VirtualMachine
= VM_VBOX
;
8818 // Pre-scan PCI bus, also check if we are under VM
8819 UniataEnumBusMasterController(DriverObject
, Argument2
);
8821 switch(g_opt_VirtualMachine
) {
8823 // adjust options for VirtualBox
8824 g_opt_WaitBusyCount
= 20000;
8825 g_opt_WaitBusyDelay
= 150;
8826 g_opt_WaitDrqDelay
= 100;
8827 g_opt_AtapiSendDisableIntr
= 0;
8828 g_opt_AtapiDmaRawRead
= FALSE
;
8832 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
8833 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
8834 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
8835 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
8836 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
8840 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8841 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8842 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8843 for (i
=0; i
<BMListLen
; i
++) {
8845 if(!BMList
[i
].MasterDev
) {
8846 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8849 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8853 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8854 if(BMList
[i
].ChanInitOk
& 0x03) {
8855 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8857 newStatus
= STATUS_SUCCESS
;
8861 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8863 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8864 PrimaryClaimed
= TRUE
;
8865 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8866 SecondaryClaimed
= TRUE
;
8869 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8873 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
8875 for(c
=0; c
<2; c
++) {
8877 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8881 if(PrimaryClaimed
) {
8882 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8887 if(SecondaryClaimed
) {
8888 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8893 if((WinVer_Id() < WinVer_2k
)) {
8894 // do not even try if already claimed
8896 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8899 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8902 if(!WinVer_WDM_Model
) {
8903 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8905 // in WDM model things are different....
8906 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
8907 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
8909 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8910 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8912 if(!WinVer_WDM_Model
) {
8913 BMList
[i
].channel
= (UCHAR
)c
;
8916 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8917 newStatus
= ScsiPortInitialize(DriverObject
,
8919 &hwInitializationData
.comm
,
8920 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8921 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
8922 if (newStatus
< statusToReturn
) {
8923 statusToReturn
= newStatus
;
8925 if (newStatus
== STATUS_SUCCESS
) {
8926 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8928 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8929 c = 1; // this will break our for()
8930 BMList[i].ChanInitOk |= 0x01 << c;
8935 if(WinVer_Id() >= WinVer_2k
) {
8936 // the following doesn't work under higher OSes
8937 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8940 if(BMList
[i
].ChanInitOk
& 0x03) {
8941 // under NT we receive status immediately, so
8942 // we can omit alternative init method id STATUS_SUCCESS returned
8943 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8946 // if (WinVer_Id() == WinVer_NT) and some error occured
8947 // try alternative init method
8950 if(WinVer_WDM_Model
) {
8951 hwInitializationData
.comm
.HwFindAdapter
= UniataFindFakeBusMasterController
;
8952 hwInitializationData
.comm
.NumberOfAccessRanges
= 5;
8953 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8955 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8956 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8957 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8958 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8960 //BMList[i].channel = 0/*(UCHAR)c*/;
8962 KdPrint2((PRINT_PREFIX
"Try init fake: %4.4s %4.4s \n",
8963 hwInitializationData
.comm
.VendorId
,
8964 hwInitializationData
.comm
.DeviceId
));
8965 newStatus
= ScsiPortInitialize(DriverObject
,
8967 &hwInitializationData
.comm
,
8969 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
8973 if(BMList
[i
].ChanInitOk
& 0x03) {
8974 _PrintNtConsole(" OK\n");
8976 _PrintNtConsole(" failed\n");
8982 /* KeBugCheckEx(0xc000000e,
8983 (i << 16) | BMList[0].ChanInitOk,
8985 newStatus, statusToReturn);*/
8987 // Look for PCI IDE controller
8988 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8989 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8990 for (; i
<BMListLen
; i
++) {
8992 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8995 /* if(BMList[i].MasterDev)
8998 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8999 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
9000 BMList
[i
].busNumber
,
9001 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
9002 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
9005 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
9006 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
9007 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
9009 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
9010 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
9011 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
9012 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
9014 BMList
[i
].channel
= 0/*(UCHAR)c*/;
9016 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
9017 hwInitializationData
.comm
.VendorId
,
9018 hwInitializationData
.comm
.DeviceId
));
9019 newStatus
= ScsiPortInitialize(DriverObject
,
9021 &hwInitializationData
.comm
,
9023 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
9024 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
9025 // Note: this is actually a BUG in scsiport.sys
9026 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
9027 // However, this PCI Slot may have higher non-empty Functions
9028 // UniATA will perform all staff instead of ScsiPort under NT,
9029 // but for ReactOS it is better to patch ScsiPort.
9030 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
9031 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
9032 newStatus
= ScsiPortInitialize(DriverObject
,
9034 &hwInitializationData
.comm
,
9035 (PVOID
)(i
| 0x80000000));
9036 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
9038 if (newStatus
< statusToReturn
)
9039 statusToReturn
= newStatus
;
9042 if(newStatus
== STATUS_SUCCESS
) {
9043 _PrintNtConsole(" OK\n");
9045 _PrintNtConsole(" failed\n");
9051 /* KeBugCheckEx(0xc000000e,
9054 newStatus, statusToReturn);*/
9058 hwInitializationData
.comm
.VendorId
= 0;
9059 hwInitializationData
.comm
.VendorIdLength
= 0;
9060 hwInitializationData
.comm
.DeviceId
= 0;
9061 hwInitializationData
.comm
.DeviceIdLength
= 0;
9063 // The adapter count is used by the find adapter routine to track how
9064 // which adapter addresses have been tested.
9066 // Indicate 2 access ranges and reset FindAdapter.
9067 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
9068 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
9070 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
9071 // Indicate ISA bustype.
9072 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
9075 // Call initialization for ISA bustype.
9076 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
9077 newStatus
= ScsiPortInitialize(DriverObject
,
9079 &hwInitializationData
.comm
,
9081 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
9082 if (newStatus
< statusToReturn
)
9083 statusToReturn
= newStatus
;
9085 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
9087 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
9088 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
9091 newStatus
= ScsiPortInitialize(DriverObject
,
9093 &hwInitializationData
.comm
,
9095 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
9096 if (newStatus
< statusToReturn
)
9097 statusToReturn
= newStatus
;
9099 InDriverEntry
= FALSE
;
9101 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
9103 return statusToReturn
;
9105 } // end DriverEntry()
9110 BuildMechanismStatusSrb(
9111 IN PVOID HwDeviceExtension
,
9112 IN PSCSI_REQUEST_BLOCK Srb
9115 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9116 PSCSI_REQUEST_BLOCK srb
;
9118 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9120 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
9122 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
9124 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
9125 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
9126 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
9127 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
9129 // Set flags to disable synchronous negociation.
9130 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
9132 // Set timeout to 4 seconds.
9133 srb
->TimeOutValue
= 4;
9136 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
9137 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
9138 srb
->SrbExtension
= AtaReq
;
9140 // Set CDB operation code.
9141 cdb
= (PCDB
)srb
->Cdb
;
9142 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
9143 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
9146 } // end BuildMechanismStatusSrb()
9148 #endif //UNIATA_CORE
9152 BuildRequestSenseSrb (
9153 IN PVOID HwDeviceExtension
,
9154 IN PSCSI_REQUEST_BLOCK Srb
9157 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9158 PSCSI_REQUEST_BLOCK srb
;
9160 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9162 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
9164 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
9166 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
9167 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
9168 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
9169 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
9171 // Set flags to disable synchronous negociation.
9172 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
9174 // Set timeout to 2 seconds.
9175 srb
->TimeOutValue
= 4;
9178 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
9179 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
9180 srb
->SrbExtension
= AtaReq
;
9182 // Set CDB operation code.
9183 cdb
= (PCDB
)srb
->Cdb
;
9184 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
9185 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
9188 } // end BuildRequestSenseSrb()
9194 AtapiRegCheckDevLunValue(
9195 IN PVOID HwDeviceExtension
,
9196 IN PCWCH NamePrefix
,
9204 ULONG val
= Default
;
9206 val
= AtapiRegCheckParameterValue(
9207 HwDeviceExtension
, NamePrefix
, Name
, val
);
9209 if(chan
!= CHAN_NOT_SPECIFIED
) {
9210 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
9211 val
= AtapiRegCheckParameterValue(
9212 HwDeviceExtension
, namex
, Name
, val
);
9213 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
9214 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
9215 val
= AtapiRegCheckParameterValue(
9216 HwDeviceExtension
, namex
, Name
, val
);
9220 } // end AtapiRegCheckDevLunValue()
9233 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
9252 swprintf(Buffer
+j
, L
"%2.2x", a
);
9260 } // end EncodeVendorStr()
9264 AtapiRegCheckDevValue(
9265 IN PVOID HwDeviceExtension
,
9272 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9274 // WCHAR name1[11+4+5];
9275 // WCHAR name2[11+4+4+10];
9276 // WCHAR name3[11+4+4+5+20];
9277 // WCHAR name3[11+4+4+5+20+1];
9286 IN ULONG SlotNumber
;
9288 ULONG val
= Default
;
9290 KdPrint(( " Parameter %ws\n", Name
));
9292 if(deviceExtension
) {
9293 VendorID
= deviceExtension
->DevID
& 0xffff;
9294 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
9295 SlotNumber
= deviceExtension
->slotNumber
;
9299 SlotNumber
= 0xffffffff;
9302 val
= AtapiRegCheckDevLunValue(
9303 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
9305 if(deviceExtension
) {
9306 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9308 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
9309 swprintf(namex
, L
"Parameters%s", namev
);
9310 val
= AtapiRegCheckDevLunValue(
9311 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9314 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
9315 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
9316 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
9318 swprintf(namex
, L
"Parameters%s", namev
);
9319 val
= AtapiRegCheckDevLunValue(
9320 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9322 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
9323 val
= AtapiRegCheckDevLunValue(
9324 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9326 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
9327 val
= AtapiRegCheckDevLunValue(
9328 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9330 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
9332 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
9333 swprintf(namex
, L
"Parameters%s", namev
);
9334 val
= AtapiRegCheckDevLunValue(
9335 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9337 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
9338 swprintf(namex
, L
"Parameters%s", namev
);
9339 val
= AtapiRegCheckDevLunValue(
9340 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9343 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
9345 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
9346 swprintf(namex
, L
"Parameters%s", namev
);
9347 val
= AtapiRegCheckDevLunValue(
9348 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9350 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
9351 swprintf(namex
, L
"Parameters%s", namev
);
9352 val
= AtapiRegCheckDevLunValue(
9353 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
9358 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
9361 } // end AtapiRegCheckDevValue()
9364 The user must specify that Xxx is to run on the platform
9365 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
9366 Services\UniATA\Xxx:REG_DWORD:Zzz.
9368 The user can override the global setting to enable or disable Xxx on a
9369 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
9370 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
9372 If this registry value does not exist or contains the value zero then
9373 the timer to check for media change does not run.
9377 RegistryPath - pointer to the unicode string inside
9378 ...\CurrentControlSet\Services\UniATA
9379 DeviceNumber - The number of the HBA device object
9381 Returns: Registry Key value
9385 AtapiRegCheckParameterValue(
9386 IN PVOID HwDeviceExtension
,
9387 IN PCWSTR PathSuffix
,
9392 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
9394 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
9396 LONG zero
= Default
;
9398 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
9401 LONG doRun
= Default
;
9403 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
9405 UNICODE_STRING paramPath
;
9407 // <SavedRegPath>\<PathSuffix> -> <Name>
9408 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
9409 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
9411 paramPath
.Length
= 0;
9412 paramPath
.MaximumLength
= RegistryPath
->Length
+
9413 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
9414 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
9415 if(!paramPath
.Buffer
) {
9416 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
9420 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
9421 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
9422 RtlAppendUnicodeToString(¶mPath
, L
"\\");
9423 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
9425 // Check for the Xxx value.
9426 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
9428 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
9429 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
9430 parameters
[0].EntryContext
= &doRun
;
9431 parameters
[0].DefaultType
= REG_DWORD
;
9432 parameters
[0].DefaultData
= &zero
;
9433 parameters
[0].DefaultLength
= sizeof(ULONG
);
9435 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
9436 paramPath
.Buffer
, parameters
, NULL
, NULL
);
9437 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
9439 ExFreePool(paramPath
.Buffer
);
9441 if(!NT_SUCCESS(status
)) {
9447 #undef ITEMS_TO_QUERY
9449 } // end AtapiRegCheckParameterValue()
9452 SCSI_ADAPTER_CONTROL_STATUS
9454 AtapiAdapterControl(
9455 IN PVOID HwDeviceExtension
,
9456 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
9460 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9461 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
9462 ULONG numberChannels
= deviceExtension
->NumberChannels
;
9466 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
9468 switch(ControlType
) {
9469 case ScsiQuerySupportedControlTypes
: {
9470 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
9471 TRUE
, // ScsiQuerySupportedControlTypes
9472 TRUE
, // ScsiStopAdapter
9473 TRUE
, // ScsiRestartAdapter
9474 FALSE
, // ScsiSetBootConfig
9475 FALSE
// ScsiSetRunningConfig
9478 ULONG lim
= ScsiAdapterControlMax
;
9481 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
9483 if(pControlTypeList
->MaxControlType
< lim
) {
9484 lim
= pControlTypeList
->MaxControlType
;
9487 for(i
= 0; i
< lim
; i
++) {
9488 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
9494 case ScsiStopAdapter
: {
9496 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
9497 // Shut down all interrupts on the adapter. They'll get re-enabled
9498 // by the initialization routines.
9499 for (c
= 0; c
< numberChannels
; c
++) {
9500 AtapiResetController(deviceExtension
, c
);
9501 AtapiDisableInterrupts(deviceExtension
, c
);
9503 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9504 // we must never get here for non-PCI
9505 status
= UniataDisconnectIntr2(HwDeviceExtension
);
9506 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
9510 case ScsiRestartAdapter
: {
9512 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
9513 // Enable all the interrupts on the adapter while port driver call
9514 // for power up an HBA that was shut down for power management
9516 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
9517 status
= UniataConnectIntr2(HwDeviceExtension
);
9518 for (c
= 0; c
< numberChannels
; c
++) {
9519 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
9520 FindDevices(HwDeviceExtension
, 0, c
);
9521 AtapiEnableInterrupts(deviceExtension
, c
);
9522 AtapiHwInitialize__(deviceExtension
, c
);
9524 if(deviceExtension
->Isr2DevObj
) {
9525 // we must never get here for non-PCI
9526 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9533 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
9534 return ScsiAdapterControlUnsuccessful
;
9538 return ScsiAdapterControlSuccess
;
9539 } // end AtapiAdapterControl()
9541 #endif //UNIATA_CORE
9560 UCHAR dbg_print_tmp_buff
[512];
9561 // UNICODE_STRING msgBuff;
9563 va_start(ap
, DebugMessage
);
9565 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
9567 dbg_print_tmp_buff
[511] = 0;
9569 KdPrint(((PCHAR
)&(dbg_print_tmp_buff
[0])));
9570 HalDisplayString(dbg_print_tmp_buff
);
9574 } // end PrintNtConsole()