3 Copyright (c) 2002-2008 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 BOOLEAN InDriverEntry
= TRUE
;
88 BOOLEAN g_opt_Verbose
= 0;
90 BOOLEAN WinVer_WDM_Model
= FALSE
;
91 //UCHAR EnableDma = FALSE;
92 //UCHAR EnableReorder = FALSE;
98 AtapiResetController__(
99 IN PVOID HwDeviceExtension
,
101 IN UCHAR CompleteType
107 IN PHW_DEVICE_EXTENSION deviceExtension
,
111 #define RESET_COMPLETE_CURRENT 0x00
112 #define RESET_COMPLETE_ALL 0x01
113 #define RESET_COMPLETE_NONE 0x02
120 IN PVOID HwDeviceExtension
123 #ifdef UNIATA_USE_XXableInterrupts
124 #define RETTYPE_XXableInterrupts BOOLEAN
125 #define RETVAL_XXableInterrupts TRUE
127 #define RETTYPE_XXableInterrupts VOID
128 #define RETVAL_XXableInterrupts
131 RETTYPE_XXableInterrupts
134 IN PVOID HwDeviceExtension
137 RETTYPE_XXableInterrupts
139 AtapiEnableInterrupts__(
140 IN PVOID HwDeviceExtension
146 IN PVOID HwDeviceExtension
,
148 IN PHW_TIMER HwScsiTimer
,
149 IN ULONG MiniportTimerValue
152 SCSI_ADAPTER_CONTROL_STATUS
155 IN PVOID HwDeviceExtension
,
156 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
164 AtapiCheckInterrupt__(
165 IN PVOID HwDeviceExtension
,
174 AtapiRegGetStringParameterValue(
175 IN PWSTR RegistryPath
,
181 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
183 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
188 ustr
.MaximumLength
= (USHORT
)MaxLen
;
189 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
191 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
192 parameters
[0].Name
= Name
;
193 parameters
[0].EntryContext
= &ustr
;
194 parameters
[0].DefaultType
= REG_SZ
;
195 parameters
[0].DefaultData
= Str
;
196 parameters
[0].DefaultLength
= MaxLen
;
198 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
199 RegistryPath
, parameters
, NULL
, NULL
);
201 if(!NT_SUCCESS(status
))
206 #undef ITEMS_TO_QUERY
207 } // end AtapiRegGetStringParameterValue()
225 if(!nano
|| !g_Perf
|| !g_PerfDt
)
227 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
232 KeQuerySystemTime(&t0
);
235 } // end UniataNanoSleep()
238 #define AtapiWritePortN_template(_type, _Type, sz) \
241 AtapiWritePort##sz( \
242 IN PHW_CHANNEL chan, \
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)); \
258 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
260 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
261 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
266 AtapiWritePortN_template(ULONG
, Ulong
, 4);
267 AtapiWritePortN_template(USHORT
, Ushort
, 2);
268 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
270 #define AtapiWritePortExN_template(_type, _Type, sz) \
273 AtapiWritePortEx##sz( \
274 IN PHW_CHANNEL chan, \
281 if(_port >= IDX_MAX_REG) { \
282 res = (PIORES)(_port); \
285 res = &chan->RegTranslation[_port]; \
287 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
291 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
293 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
294 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
299 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
300 //AtapiWritePortExN_template(USHORT, Ushort, 2);
301 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
303 #define AtapiReadPortN_template(_type, _Type, sz) \
307 IN PHW_CHANNEL chan, \
312 if(_port >= IDX_MAX_REG) { \
313 res = (PIORES)(_port); \
316 res = &chan->RegTranslation[_port]; \
318 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
319 return (_type)(-1); \
322 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
323 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
325 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
326 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
330 AtapiReadPortN_template(ULONG
, Ulong
, 4);
331 AtapiReadPortN_template(USHORT
, Ushort
, 2);
332 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
334 #define AtapiReadPortExN_template(_type, _Type, sz) \
337 AtapiReadPortEx##sz( \
338 IN PHW_CHANNEL chan, \
344 if(_port >= IDX_MAX_REG) { \
345 res = (PIORES)(_port); \
348 res = &chan->RegTranslation[_port]; \
350 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
351 return (_type)(-1); \
354 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
356 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
357 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
361 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
362 //AtapiReadPortExN_template(USHORT, Ushort, 2);
363 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
365 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
368 AtapiReadBuffer##sz( \
369 IN PHW_CHANNEL chan, \
380 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
382 Buffer = ((_type*)Buffer)+1; \
383 UniataNanoSleep(Timing); \
388 if(_port >= IDX_MAX_REG) { \
389 res = (PIORES)(_port); \
392 res = &chan->RegTranslation[_port]; \
394 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
398 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
399 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
403 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
405 Buffer = ((_type*)Buffer)+1; \
410 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
413 AtapiWriteBuffer##sz( \
414 IN PHW_CHANNEL chan, \
425 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
426 Buffer = ((_type*)Buffer)+1; \
428 UniataNanoSleep(Timing); \
433 if(_port >= IDX_MAX_REG) { \
434 res = (PIORES)(_port); \
437 res = &chan->RegTranslation[_port]; \
439 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
443 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
444 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
448 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
450 Buffer = ((_type*)Buffer)+1; \
455 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
456 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
458 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
459 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
471 WaitOnBusyLong(chan
);
472 for (i
= 0; i
< 0x10000; i
++) {
474 GetStatus(chan
, statusByte
);
475 if (statusByte
& IDE_STATUS_DRQ
) {
476 // Suck out any remaining bytes and throw away.
477 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
483 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
486 } // AtapiSuckPort2()
496 for (i
=0; i
<20000; i
++) {
497 GetStatus(chan
, Status
);
498 if (Status
& IDE_STATUS_BUSY
) {
499 AtapiStallExecution(150);
506 } // end WaitOnBusy()
517 Status
= WaitOnBusy(chan
);
518 if(!(Status
& IDE_STATUS_BUSY
))
520 for (i
=0; i
<2000; i
++) {
521 GetStatus(chan
, Status
);
522 if (Status
& IDE_STATUS_BUSY
) {
523 AtapiStallExecution(250);
530 } // end WaitOnBusyLong()
540 for (i
=0; i
<20000; i
++) {
541 GetBaseStatus(chan
, Status
);
542 if (Status
& IDE_STATUS_BUSY
) {
543 AtapiStallExecution(150);
550 } // end WaitOnBaseBusy()
561 Status
= WaitOnBaseBusy(chan
);
562 if(!(Status
& IDE_STATUS_BUSY
))
564 for (i
=0; i
<2000; i
++) {
565 GetBaseStatus(chan
, Status
);
566 if (Status
& IDE_STATUS_BUSY
) {
567 AtapiStallExecution(250);
574 } // end WaitOnBaseBusyLong()
579 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
588 if(Status
& IDE_STATUS_BUSY
) {
591 // if(deviceExtension->HwFlags & UNIATA_SATA) {
592 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
593 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
597 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
598 if ((Status
& IDE_STATUS_BUSY
) ||
599 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
603 return IDE_STATUS_IDLE
;
604 } // end UniataIsIdle()
615 for (i
=0; i
<20000; i
++) {
616 GetStatus(chan
, Status
);
617 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
618 if(Status2
== 0xff) {
622 if(Status2
& IDE_STATUS_BUSY
) {
623 AtapiStallExecution(10);
630 } // end WaitForIdleLong()
640 for (i
=0; i
<1000; i
++) {
641 GetStatus(chan
, Status
);
642 if (Status
& IDE_STATUS_BUSY
) {
643 AtapiStallExecution(100);
644 } else if (Status
& IDE_STATUS_DRQ
) {
647 AtapiStallExecution(200);
651 } // end WaitForDrq()
661 for (i
=0; i
<2; i
++) {
662 GetStatus(chan
, Status
);
663 if (Status
& IDE_STATUS_BUSY
) {
664 AtapiStallExecution(100);
665 } else if (Status
& IDE_STATUS_DRQ
) {
668 AtapiStallExecution(100);
672 } // end WaitShortForDrq()
681 //ULONG c = chan->lChannel;
683 UCHAR dma_status
= 0;
684 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
687 GetBaseStatus(chan
, statusByte2
);
688 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
689 SelectDrive(chan
, DeviceNumber
);
690 AtapiStallExecution(10000);
691 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
692 for (i
= 0; i
< 1000; i
++) {
693 AtapiStallExecution(999);
695 SelectDrive(chan
, DeviceNumber
);
697 GetBaseStatus(chan
, statusByte2
);
698 AtapiStallExecution(500);
700 GetBaseStatus(chan
, statusByte2
);
701 if(chan
&& chan
->DeviceExtension
) {
702 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
703 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
705 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
707 if(dma_status
& BM_STATUS_INTR
) {
708 // bullshit, we have DMA interrupt, but had never initiate DMA operation
709 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
710 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
711 GetBaseStatus(chan
, statusByte2
);
713 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
714 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
718 } // end AtapiSoftReset()
721 Send command to device.
722 Translate to 48-Lba form if required
727 IN PHW_DEVICE_EXTENSION deviceExtension
,
728 IN ULONG DeviceNumber
,
737 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
739 ULONG ldev
= lChannel
*2 + DeviceNumber
;
743 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
744 deviceExtension
->DevIndex
, deviceExtension
->Channel
, ldev
, command
, lba
, count
, feature
));
746 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
747 SelectDrive(chan
, DeviceNumber
);
749 statusByte
= WaitOnBusy(chan
);
751 /* ready to issue command ? */
752 if (statusByte
& IDE_STATUS_BUSY
) {
753 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
757 // !!! We should not check ERROR condition here
758 // ERROR bit may be asserted durring previous operation
759 // and not cleared after SELECT
761 //>>>>>> NV: 2006/08/03
762 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
763 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
764 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
765 return IDE_STATUS_ERROR
;
766 //return SRB_STATUS_ERROR;
768 //<<<<<< NV: 2006/08/03
770 /* only use 48bit addressing if needed because of the overhead */
771 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
772 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
774 KdPrint2((PRINT_PREFIX
" ldev %#x USE_LBA_48\n", ldev
));
775 /* translate command into 48bit version */
776 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
777 command
= AtaCommands48
[command
];
779 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
783 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
786 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
787 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
788 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
789 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
790 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
791 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
792 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
793 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
794 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
795 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
797 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
798 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
801 plba
= (PUCHAR
)&lba
; //ktp
802 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
805 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
806 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
808 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
809 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
810 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
811 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
812 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
813 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
814 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
816 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
817 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
821 // write command code to device
822 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
827 // caller requested wait for interrupt
830 statusByte
= WaitForDrq(chan
);
831 if (statusByte
& IDE_STATUS_DRQ
)
833 AtapiStallExecution(500);
834 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
841 // caller requested wait for entering Wait state
842 for (i
=0; i
<30 * 1000; i
++) {
844 GetStatus(chan
, statusByte
);
845 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
846 if(statusByte
== 0xff) {
850 if(statusByte
& IDE_STATUS_ERROR
) {
853 if(statusByte
& IDE_STATUS_BUSY
) {
854 AtapiStallExecution(100);
857 if(statusByte
== IDE_STATUS_IDLE
) {
860 //if(deviceExtension->HwFlags & UNIATA_SATA) {
861 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
864 AtapiStallExecution(100);
867 //statusByte |= IDE_STATUS_BUSY;
871 statusByte
= WaitOnBusyLong(chan
);
873 case ATA_WAIT_BASE_READY
:
874 statusByte
= WaitOnBaseBusyLong(chan
);
877 GetStatus(chan
, statusByte
);
878 if (statusByte
& IDE_STATUS_ERROR
) {
879 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
880 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
883 KdPrint2((PRINT_PREFIX
" try to continue\n"));
884 statusByte
&= ~IDE_STATUS_ERROR
;
886 chan
->ExpectingInterrupt
= TRUE
;
888 InterlockedExchange(&(chan
->CheckIntr
),
894 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
897 } // end AtaCommand48()
900 Send command to device.
901 This is simply wrapper for AtaCommand48()
906 IN PHW_DEVICE_EXTENSION deviceExtension
,
907 IN ULONG DeviceNumber
,
918 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
920 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
921 count
, feature
, flags
);
922 } // end AtaCommand()
926 AtaPio2Mode(LONG pio
)
929 default: return ATA_PIO
;
930 case 0: return ATA_PIO0
;
931 case 1: return ATA_PIO1
;
932 case 2: return ATA_PIO2
;
933 case 3: return ATA_PIO3
;
934 case 4: return ATA_PIO4
;
935 case 5: return ATA_PIO5
;
937 } // end AtaPio2Mode()
941 AtaPioMode(PIDENTIFY_DATA2 ident
)
943 if (ident
->PioTimingsValid
) {
944 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
946 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
948 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
951 if (ident
->PioCycleTimingMode
== 2)
953 if (ident
->PioCycleTimingMode
== 1)
955 if (ident
->PioCycleTimingMode
== 0)
958 } // end AtaPioMode()
962 AtaWmode(PIDENTIFY_DATA2 ident
)
964 if (ident
->MultiWordDMASupport
& 0x04)
966 if (ident
->MultiWordDMASupport
& 0x02)
968 if (ident
->MultiWordDMASupport
& 0x01)
975 AtaUmode(PIDENTIFY_DATA2 ident
)
977 if (!ident
->UdmaModesValid
)
979 if (ident
->UltraDMASupport
& 0x40)
981 if (ident
->UltraDMASupport
& 0x20)
983 if (ident
->UltraDMASupport
& 0x10)
985 if (ident
->UltraDMASupport
& 0x08)
987 if (ident
->UltraDMASupport
& 0x04)
989 if (ident
->UltraDMASupport
& 0x02)
991 if (ident
->UltraDMASupport
& 0x01)
1002 IN PVOID HwDeviceExtension
1005 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1006 PHW_TIMER HwScsiTimer
;
1008 ULONG MiniportTimerValue
;
1009 BOOLEAN recall
= FALSE
;
1013 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1015 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1016 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1017 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1020 chan
= &deviceExtension
->chan
[lChannel
];
1024 HwScsiTimer
= chan
->HwScsiTimer
;
1025 chan
->HwScsiTimer
= NULL
;
1027 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1028 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1032 HwScsiTimer(HwDeviceExtension
);
1034 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1036 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1037 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1038 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1039 deviceExtension
->FirstDpcChan
=
1040 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1044 KeQuerySystemTime(&time
);
1045 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1047 chan
= &deviceExtension
->chan
[lChannel
];
1048 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1050 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1051 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1058 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1059 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1060 if(!MiniportTimerValue
)
1061 MiniportTimerValue
= 1;
1063 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1064 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1071 } // end AtapiTimerDpc()
1074 Wrapper for ScsiPort, that implements smart Dpc
1075 queueing. We need it to allow parallel functioning
1076 of IDE channles with shared interrupt. Standard Dpc mechanism
1077 cancels previous Dpc request (if any), but we need Dpc queue.
1082 IN PVOID HwDeviceExtension
,
1084 IN PHW_TIMER HwScsiTimer
,
1085 IN ULONG MiniportTimerValue
1088 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1090 LARGE_INTEGER time2
;
1092 PHW_CHANNEL prev_chan
;
1094 // BOOLEAN UseRequestTimerCall = TRUE;
1096 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1097 KeQuerySystemTime(&time
);
1099 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1100 time
.QuadPart
+= MiniportTimerValue
*10;
1101 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1103 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1105 i
= deviceExtension
->FirstDpcChan
;
1106 chan
= prev_chan
= NULL
;
1107 while(i
!= CHAN_NOT_SPECIFIED
) {
1109 chan
= &deviceExtension
->chan
[i
];
1110 if(chan
->DpcTime
> time
.QuadPart
) {
1113 i
= chan
->NextDpcChan
;
1115 chan
= &deviceExtension
->chan
[lChannel
];
1117 deviceExtension
->FirstDpcChan
= lChannel
;
1119 prev_chan
->NextDpcChan
= lChannel
;
1121 chan
->NextDpcChan
= i
;
1122 chan
->HwScsiTimer
= HwScsiTimer
;
1123 chan
->DpcTime
= time
.QuadPart
;
1125 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1126 if(time
.QuadPart
<= time2
.QuadPart
) {
1127 MiniportTimerValue
= 1;
1129 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1132 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1133 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1135 MiniportTimerValue
);
1137 } // end AtapiQueueTimerDpc()
1139 #endif //UNIATA_CORE
1148 UCHAR statusByteAlt
;
1150 GetStatus(chan
, statusByteAlt
);
1151 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1153 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1154 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1155 KdPrint2((PRINT_PREFIX
1156 " Reg_%#x (%#x) = %#x\n",
1158 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1161 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1162 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1163 KdPrint2((PRINT_PREFIX
1164 " BM_%#x (%#x) = %#x\n",
1166 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1170 } // end UniataDumpATARegs()
1174 Routine Description:
1176 Issue IDENTIFY command to a device.
1180 HwDeviceExtension - HBA miniport driver's adapter data storage
1181 DeviceNumber - Indicates which device.
1182 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1186 TRUE if all goes well.
1192 IN PVOID HwDeviceExtension
,
1193 IN ULONG DeviceNumber
,
1199 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1200 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1201 ULONG waitCount
= 50000;
1207 BOOLEAN atapiDev
= FALSE
;
1208 ULONG ldev
= (lChannel
* 2) + DeviceNumber
;
1209 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
1211 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1212 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1215 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1216 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1220 SelectDrive(chan
, DeviceNumber
);
1221 AtapiStallExecution(10);
1222 statusByte
= WaitOnBusyLong(chan
);
1223 // Check that the status register makes sense.
1224 GetBaseStatus(chan
, statusByte2
);
1226 UniataDumpATARegs(chan
);
1228 if (Command
== IDE_COMMAND_IDENTIFY
) {
1229 // Mask status byte ERROR bits.
1230 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1231 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1232 // Check if register value is reasonable.
1234 if(statusByte
!= IDE_STATUS_IDLE
) {
1236 // No reset here !!!
1237 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1239 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1240 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1241 SelectDrive(chan
, DeviceNumber
);
1242 WaitOnBusyLong(chan
);
1244 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1245 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1247 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1248 signatureHigh
== ATAPI_MAGIC_MSB
) {
1250 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (ldev %d)\n", ldev
));
1254 // We really should wait up to 31 seconds
1255 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1256 // (30 seconds for device 1)
1258 // Wait for Busy to drop.
1259 AtapiStallExecution(100);
1260 GetStatus(chan
, statusByte
);
1262 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1263 GetBaseStatus(chan
, statusByte2
);
1265 SelectDrive(chan
, DeviceNumber
);
1267 GetBaseStatus(chan
, statusByte2
);
1269 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1271 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1272 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1274 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1275 signatureHigh
== ATAPI_MAGIC_MSB
) {
1276 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev
));
1281 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1282 if (statusByte
!= IDE_STATUS_IDLE
) {
1284 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (ldev %d)\n", ldev
));
1289 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1290 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1291 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1292 statusByte
= WaitForIdleLong(chan
);
1293 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1298 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1299 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1304 for (; j
< 4*2; j
++) {
1305 // Send IDENTIFY command.
1306 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1309 if (statusByte
& IDE_STATUS_DRQ
) {
1310 // Read status to acknowledge any interrupts generated.
1311 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1312 GetBaseStatus(chan
, statusByte
);
1313 // One last check for Atapi.
1314 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1315 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1317 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1318 signatureHigh
== ATAPI_MAGIC_MSB
) {
1319 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev
));
1325 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1326 if (Command
== IDE_COMMAND_IDENTIFY
) {
1327 // Check the signature. If DRQ didn't come up it's likely Atapi.
1328 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1329 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1331 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1332 signatureHigh
== ATAPI_MAGIC_MSB
) {
1334 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev
));
1338 // Device didn't respond correctly. It will be given one more chances.
1339 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1340 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1341 GetBaseStatus(chan
, statusByte
);
1342 AtapiSoftReset(chan
,DeviceNumber
);
1344 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1345 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1347 GetBaseStatus(chan
, statusByte
);
1348 //GetStatus(chan, statusByte);
1349 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1352 // Check for error on really stupid master devices that assert random
1353 // patterns of bits in the status register at the slave address.
1354 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1355 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1359 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1360 // Suck out 256 words. After waiting for one model that asserts busy
1361 // after receiving the Packet Identify command.
1362 statusByte
= WaitForDrq(chan
);
1363 statusByte
= WaitOnBusyLong(chan
);
1364 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1366 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1367 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1368 GetBaseStatus(chan
, statusByte
);
1371 GetBaseStatus(chan
, statusByte
);
1372 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1374 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1376 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1380 // ATI/SII chipsets with memory-mapped IO hangs when
1381 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1382 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1383 KdPrint2((PRINT_PREFIX
1384 " IO_%#x (%#x), %s:\n",
1386 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1387 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1388 for(i
=0; i
<256; i
++) {
1390 KdPrint2((PRINT_PREFIX
1393 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1395 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1396 KdPrint2((PRINT_PREFIX
1398 AtapiStallExecution(1);
1399 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1402 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1404 // Work around for some IDE and one model Atapi that will present more than
1405 // 256 bytes for the Identify data.
1406 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1407 statusByte
= AtapiSuckPort2(chan
);
1409 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1410 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1413 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1414 statusByte
= WaitForDrq(chan
);
1415 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1416 GetBaseStatus(chan
, statusByte
);
1418 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1421 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1425 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1426 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1427 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1428 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1429 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1430 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1432 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1433 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1434 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1435 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1437 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1439 // Check out a few capabilities / limitations of the device.
1440 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1441 // Determine if this drive supports the MSN functions.
1442 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1444 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1445 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1447 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1448 // Determine max. block transfer for this device.
1449 LunExt
->MaximumBlockXfer
=
1450 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1452 LunExt
->NumOfSectors
= 0;
1453 if (Command
== IDE_COMMAND_IDENTIFY
) {
1454 ULONGLONG NumOfSectors
=0;
1455 ULONGLONG NativeNumOfSectors
=0;
1456 ULONGLONG cylinders
=0;
1457 ULONGLONG tmp_cylinders
=0;
1458 // Read very-old-style drive geometry
1459 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1460 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1461 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1462 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1464 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1465 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1466 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1467 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1468 // Check for HDDs > 8Gb
1469 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1470 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1471 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1472 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1474 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1475 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1476 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1478 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1480 NumOfSectors
= cylinders
*
1481 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1482 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1484 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1488 // Check for LBA mode
1489 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1490 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1491 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1492 if ( deviceExtension
->FullIdentifyData
.SupportLba
1494 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1495 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1496 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1497 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1498 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1500 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1501 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1502 goto skip_lba_staff
;
1504 // Check for LBA48 support
1505 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1506 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1507 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1508 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1510 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1512 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1513 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1514 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1516 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1518 NativeNumOfSectors
= cylinders
*
1519 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1520 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1522 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1524 if(NativeNumOfSectors
> NumOfSectors
) {
1525 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1526 NumOfSectors
= NativeNumOfSectors
;
1530 // Check drive capacity report for LBA48-capable drives.
1531 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1532 ULONG hNativeNumOfSectors
;
1533 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1535 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1536 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1538 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1539 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1540 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1541 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1543 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1546 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1547 NativeNumOfSectors
|=
1548 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1549 hNativeNumOfSectors
=
1550 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1551 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1552 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1554 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1556 // Some drives report LBA48 capability while has capacity below 128Gb
1557 // Probably they support large block-counters.
1558 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1559 // Here we check this
1560 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1561 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1563 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1564 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1566 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1567 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1568 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1569 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1570 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1571 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1572 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1576 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1577 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1578 NativeNumOfSectors
= 0;
1582 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1583 NativeNumOfSectors
> NumOfSectors
) {
1585 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1586 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1588 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1589 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1590 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1591 NumOfSectors
= NativeNumOfSectors
;
1597 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1598 // check for native LBA size
1599 // some drives report ~32Gb in Identify Block
1600 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1602 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1603 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1605 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1606 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1607 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1608 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1609 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1611 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1613 if(NativeNumOfSectors
> NumOfSectors
) {
1615 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1616 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1618 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1619 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1620 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1621 NumOfSectors
= NativeNumOfSectors
;
1627 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1629 // fill IdentifyData with bogus geometry
1630 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1631 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1632 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1633 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1634 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1635 // ok, we can keep original values
1636 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1637 LunExt
->opt_GeomType
= GEOM_ORIG
;
1640 tmp_cylinders
= NumOfSectors
/ (255*63);
1641 if(tmp_cylinders
< 0xffff) {
1642 // we can use generic values for H/S for generic geometry approach
1643 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1644 LunExt
->opt_GeomType
= GEOM_STD
;
1647 // we should use UNIATA geometry approach
1648 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1649 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1653 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1655 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1656 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1657 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1659 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1660 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1662 cylinders
= NumOfSectors
/ (255*63);
1663 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1665 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1666 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1668 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1669 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1670 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1672 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1674 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1675 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1676 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1678 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1680 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1681 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1682 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1684 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1686 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1687 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1688 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1690 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1691 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1692 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1695 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1696 cylinders
= tmp_cylinders
;
1698 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1699 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1703 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1704 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1705 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1707 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1708 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1709 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1711 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1712 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1713 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1717 LunExt
->NumOfSectors
= NumOfSectors
;
1718 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1719 deviceExtension->FullIdentifyData.DoubleWordIo) {
1720 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1724 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1725 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1727 InitBadBlocks(LunExt
);
1729 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1730 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1732 // This device interrupts with the assertion of DRQ after receiving
1733 // Atapi Packet Command
1734 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1735 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1738 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1741 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1743 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1745 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1746 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1748 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1749 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1750 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1751 // set CD default costs
1752 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1753 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1754 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1755 statusByte
= WaitForDrq(chan
);
1757 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1758 LunExt
->IdentifyData
.DeviceType
));
1761 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1764 GetBaseStatus(chan
, statusByte
);
1765 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1768 } // end IssueIdentify()
1773 Routine Description:
1774 Set drive parameters using the IDENTIFY data.
1777 HwDeviceExtension - HBA miniport driver's adapter data storage
1778 DeviceNumber - Indicates which device.
1781 TRUE if all goes well.
1787 IN PVOID HwDeviceExtension
,
1788 IN ULONG DeviceNumber
,
1792 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1793 PIDENTIFY_DATA2 identifyData
= &deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].IdentifyData
;
1798 if(deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].DeviceFlags
&
1799 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1802 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1803 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1805 // Send SET PARAMETER command.
1806 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1807 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1808 (identifyData
->NumberOfHeads
- 1), 0,
1809 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1811 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1812 if(statusByte
& IDE_STATUS_ERROR
) {
1813 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1814 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1815 errorByte
, statusByte
));
1819 if(statusByte
== IDE_STATUS_IDLE
) {
1825 } // end SetDriveParameters()
1830 PHW_LU_EXTENSION LunExt
1833 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
1834 } // end UniataForgetDevice()
1839 Routine Description:
1840 Reset IDE controller and/or Atapi device.
1843 HwDeviceExtension - HBA miniport driver's adapter data storage
1852 AtapiResetController(
1853 IN PVOID HwDeviceExtension
,
1857 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1858 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1859 } // end AtapiResetController()
1864 AtapiResetController__(
1865 IN PVOID HwDeviceExtension
,
1867 IN BOOLEAN CompleteType
1870 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1871 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1872 PHW_CHANNEL chan
= NULL
;
1876 PSCSI_REQUEST_BLOCK CurSrb
;
1877 ULONG ChannelCtrlFlags
;
1878 UCHAR dma_status
= 0;
1880 ULONG slotNumber
= deviceExtension
->slotNumber
;
1881 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1882 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1884 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1886 //ULONG RevID = deviceExtension->RevID;
1887 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1891 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1893 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
1894 // we shall reset both channels on SimplexOnly devices,
1895 // It's not worth doing so on normal controllers
1897 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
1900 numberChannels
= deviceExtension
->NumberChannels
;
1903 for (; j
< numberChannels
; j
++) {
1905 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
1906 chan
= &deviceExtension
->chan
[j
];
1907 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
1908 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
1909 if(CompleteType
!= RESET_COMPLETE_NONE
) {
1911 while((CurSrb
= UniataGetCurRequest(chan
))) {
1913 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
1915 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
1916 // Check and see if we are processing an internal srb
1917 if (AtaReq
->OriginalSrb
) {
1918 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
1919 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
1920 AtaReq
->OriginalSrb
= NULL
;
1921 // NOTE: internal SRB doesn't get to SRB queue !!!
1922 CurSrb
= AtaReq
->Srb
;
1925 // Remove current request from queue
1926 UniataRemoveRequest(chan
, CurSrb
);
1928 // Check if request is in progress.
1929 ASSERT(AtaReq
->Srb
== CurSrb
);
1931 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1932 UCHAR PathId
= CurSrb
->PathId
;
1933 UCHAR TargetId
= CurSrb
->TargetId
;
1934 UCHAR Lun
= CurSrb
->Lun
;
1936 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
1937 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
1939 if (CurSrb
->SenseInfoBuffer
) {
1941 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
1943 senseBuffer
->ErrorCode
= 0x70;
1944 senseBuffer
->Valid
= 1;
1945 senseBuffer
->AdditionalSenseLength
= 0xb;
1946 if(CompleteType
== RESET_COMPLETE_ALL
) {
1947 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1948 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
1949 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
1950 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
1952 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1953 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
1954 senseBuffer
->AdditionalSenseCode
= 0;
1955 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
1959 // Clear request tracking fields.
1960 AtaReq
->WordsLeft
= 0;
1961 AtaReq
->DataBuffer
= NULL
;
1962 AtaReq
->TransferLength
= 0;
1964 ScsiPortNotification(RequestComplete
,
1968 // Indicate ready for next request.
1969 ScsiPortNotification(NextLuRequest
,
1975 if(CompleteType
!= RESET_COMPLETE_ALL
)
1978 #endif //UNIATA_CORE
1979 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1981 // Save control flags
1982 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
1983 // Clear expecting interrupt flag.
1984 chan
->ExpectingInterrupt
= FALSE
;
1986 chan
->ChannelCtrlFlags
= 0;
1987 InterlockedExchange(&(chan
->CheckIntr
),
1991 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
1992 AtapiDisableInterrupts(deviceExtension
, j
);
1993 KdPrint2((PRINT_PREFIX
" done\n"));
1995 case ATA_INTEL_ID
: {
1998 if(!(ChipFlags
& UNIATA_SATA
))
2000 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2004 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2005 if(ChipFlags
& UNIATA_AHCI
) {
2008 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2009 GetPciConfig1(0x90, tmp8
);
2016 ChangePciConfig2(0x92, a
& ~mask
);
2017 AtapiStallExecution(10);
2018 ChangePciConfig2(0x92, a
| mask
);
2021 AtapiStallExecution(10000);
2022 GetPciConfig2(0x92, tmp16
);
2023 if ((tmp16
& (mask
<< 4)) == (mask
<< 4)) {
2024 AtapiStallExecution(10000);
2030 case ATA_NVIDIA_ID
: {
2031 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2032 if(!(ChipFlags
& UNIATA_SATA
))
2035 case ATA_SILICON_IMAGE_ID
: {
2037 ULONG Channel
= deviceExtension
->Channel
+ j
;
2038 if(!(ChipFlags
& UNIATA_SATA
))
2040 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2041 /* disable PHY state change interrupt */
2042 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2044 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2046 /* reset controller part for this channel */
2047 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2048 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2049 AtapiStallExecution(1000);
2050 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2051 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2055 case ATA_PROMISE_ID
: {
2058 if(ChipFlags
& UNIATA_SATA
) {
2059 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2060 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2063 KdPrint2((PRINT_PREFIX
" send reset\n"));
2064 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2065 IDE_DC_RESET_CONTROLLER
);
2066 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2067 AtapiStallExecution(10000);
2068 // Disable interrupts
2069 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2070 AtapiDisableInterrupts(deviceExtension
, j
);
2071 AtapiStallExecution(100);
2072 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2073 AtapiEnableInterrupts(deviceExtension
, j
);
2074 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2075 AtapiStallExecution(100000);
2076 KdPrint2((PRINT_PREFIX
" done\n"));
2081 //if(!(ChipFlags & UNIATA_SATA)) {
2082 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2083 // Reset DMA engine if active
2084 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2085 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2086 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2087 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2088 (dma_status
& BM_STATUS_INTR
)) {
2089 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2093 // all these shall be performed inside AtapiHwInitialize__() ?
2095 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2096 // Do special processing for ATAPI and IDE disk devices.
2097 for (i
= 0; i
< max_ldev
; i
++) {
2099 // Check if device present.
2100 if (!(deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2104 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2105 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2108 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2112 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2113 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2114 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2119 SelectDrive(chan
, i
);
2120 AtapiStallExecution(10);
2121 statusByte
= WaitOnBusyLong(chan
);
2122 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2123 if(statusByte
== 0xff) {
2124 KdPrint2((PRINT_PREFIX
2125 "no drive, status %#x\n",
2127 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2129 // Check for ATAPI disk.
2130 if (deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2131 // Issue soft reset and issue identify.
2132 GetStatus(chan
, statusByte
);
2133 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2136 AtapiDisableInterrupts(deviceExtension
, j
);
2137 AtapiSoftReset(chan
, i
);
2138 AtapiEnableInterrupts(deviceExtension
, j
);
2140 GetStatus(chan
, statusByte
);
2142 if(statusByte
== IDE_STATUS_SUCCESS
) {
2144 IssueIdentify(HwDeviceExtension
,
2146 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2149 KdPrint2((PRINT_PREFIX
2150 "AtapiResetController: Status after soft reset %#x\n",
2153 GetBaseStatus(chan
, statusByte
);
2156 // Issue identify and reinit after channel reset.
2158 if (statusByte
!= IDE_STATUS_IDLE
&&
2159 statusByte
!= IDE_STATUS_SUCCESS
&&
2160 statusByte
!= IDE_STATUS_DRDY
) {
2162 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2164 if(!IssueIdentify(HwDeviceExtension
,
2166 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2168 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2170 // Set disk geometry parameters.
2171 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2172 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2174 GetBaseStatus(chan
, statusByte
);
2176 // force DMA mode reinit
2177 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
|= DFLAGS_REINIT_DMA
;
2181 // Enable interrupts, note, the we can have here recursive disable
2182 AtapiStallExecution(10);
2183 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2185 chan
->DisableIntr
));
2186 AtapiEnableInterrupts(deviceExtension
, j
);
2188 // Call the HwInitialize routine to setup multi-block.
2189 AtapiHwInitialize__(deviceExtension
, j
);
2191 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2195 } // end AtapiResetController__()
2200 Routine Description:
2201 This routine maps ATAPI and IDE errors to specific SRB statuses.
2204 HwDeviceExtension - HBA miniport driver's adapter data storage
2205 Srb - IO request packet
2214 IN PVOID HwDeviceExtension
,
2215 IN PSCSI_REQUEST_BLOCK Srb
2218 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2219 ULONG lChannel
= GET_CHANNEL(Srb
);
2220 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2223 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2225 ULONG ldev
= GET_LDEV(Srb
);
2227 // Read the error register.
2229 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2230 KdPrint2((PRINT_PREFIX
2231 "MapError: Error register is %#x\n",
2234 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2236 switch (errorByte
>> 4) {
2237 case SCSI_SENSE_NO_SENSE
:
2239 KdPrint2((PRINT_PREFIX
2240 "ATAPI: No sense information\n"));
2241 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2242 srbStatus
= SRB_STATUS_ERROR
;
2245 case SCSI_SENSE_RECOVERED_ERROR
:
2247 KdPrint2((PRINT_PREFIX
2248 "ATAPI: Recovered error\n"));
2250 srbStatus
= SRB_STATUS_SUCCESS
;
2253 case SCSI_SENSE_NOT_READY
:
2255 KdPrint2((PRINT_PREFIX
2256 "ATAPI: Device not ready\n"));
2257 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2258 srbStatus
= SRB_STATUS_ERROR
;
2261 case SCSI_SENSE_MEDIUM_ERROR
:
2263 KdPrint2((PRINT_PREFIX
2264 "ATAPI: Media error\n"));
2265 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2266 srbStatus
= SRB_STATUS_ERROR
;
2269 case SCSI_SENSE_HARDWARE_ERROR
:
2271 KdPrint2((PRINT_PREFIX
2272 "ATAPI: Hardware error\n"));
2273 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2274 srbStatus
= SRB_STATUS_ERROR
;
2277 case SCSI_SENSE_ILLEGAL_REQUEST
:
2279 KdPrint2((PRINT_PREFIX
2280 "ATAPI: Illegal request\n"));
2281 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2282 srbStatus
= SRB_STATUS_ERROR
;
2285 case SCSI_SENSE_UNIT_ATTENTION
:
2287 KdPrint2((PRINT_PREFIX
2288 "ATAPI: Unit attention\n"));
2289 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2290 srbStatus
= SRB_STATUS_ERROR
;
2293 case SCSI_SENSE_DATA_PROTECT
:
2295 KdPrint2((PRINT_PREFIX
2296 "ATAPI: Data protect\n"));
2297 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2298 srbStatus
= SRB_STATUS_ERROR
;
2301 case SCSI_SENSE_BLANK_CHECK
:
2303 KdPrint2((PRINT_PREFIX
2304 "ATAPI: Blank check\n"));
2305 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2306 srbStatus
= SRB_STATUS_ERROR
;
2309 case SCSI_SENSE_ABORTED_COMMAND
:
2310 KdPrint2((PRINT_PREFIX
2311 "Atapi: Command Aborted\n"));
2312 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2313 srbStatus
= SRB_STATUS_ERROR
;
2318 KdPrint2((PRINT_PREFIX
2319 "ATAPI: Invalid sense information\n"));
2321 srbStatus
= SRB_STATUS_ERROR
;
2329 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2330 chan
->ReturningMediaStatus
= errorByte
;
2332 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2333 KdPrint2((PRINT_PREFIX
2334 "IDE: Media change\n"));
2335 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2336 srbStatus
= SRB_STATUS_ERROR
;
2338 if (Srb
->SenseInfoBuffer
) {
2340 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2342 senseBuffer
->ErrorCode
= 0x70;
2343 senseBuffer
->Valid
= 1;
2344 senseBuffer
->AdditionalSenseLength
= 0xb;
2345 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2346 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2347 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2349 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2352 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2353 KdPrint2((PRINT_PREFIX
2354 "IDE: Command abort\n"));
2355 srbStatus
= SRB_STATUS_ABORTED
;
2356 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2358 if (Srb
->SenseInfoBuffer
) {
2360 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2362 senseBuffer
->ErrorCode
= 0x70;
2363 senseBuffer
->Valid
= 1;
2364 senseBuffer
->AdditionalSenseLength
= 0xb;
2365 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2366 senseBuffer
->AdditionalSenseCode
= 0;
2367 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2369 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2372 deviceExtension
->lun
[ldev
].ErrorCount
++;
2374 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2376 KdPrint2((PRINT_PREFIX
2377 "IDE: End of media\n"));
2378 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2379 srbStatus
= SRB_STATUS_ERROR
;
2381 if (Srb
->SenseInfoBuffer
) {
2383 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2385 senseBuffer
->ErrorCode
= 0x70;
2386 senseBuffer
->Valid
= 1;
2387 senseBuffer
->AdditionalSenseLength
= 0xb;
2388 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2389 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2390 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2391 senseBuffer
->EndOfMedia
= 1;
2393 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2396 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2397 deviceExtension
->lun
[ldev
].ErrorCount
++;
2400 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2402 KdPrint2((PRINT_PREFIX
2403 "IDE: Illegal length\n"));
2404 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2406 if (Srb
->SenseInfoBuffer
) {
2408 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2410 senseBuffer
->ErrorCode
= 0x70;
2411 senseBuffer
->Valid
= 1;
2412 senseBuffer
->AdditionalSenseLength
= 0xb;
2413 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2414 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2415 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2416 senseBuffer
->IncorrectLength
= 1;
2418 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2421 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2423 KdPrint2((PRINT_PREFIX
2424 "IDE: Bad block\n"));
2425 srbStatus
= SRB_STATUS_ERROR
;
2426 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2427 if (Srb
->SenseInfoBuffer
) {
2429 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2431 senseBuffer
->ErrorCode
= 0x70;
2432 senseBuffer
->Valid
= 1;
2433 senseBuffer
->AdditionalSenseLength
= 0xb;
2434 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2435 senseBuffer
->AdditionalSenseCode
= 0;
2436 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2438 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2441 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2443 KdPrint2((PRINT_PREFIX
2444 "IDE: Id not found\n"));
2445 srbStatus
= SRB_STATUS_ERROR
;
2446 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2448 if (Srb
->SenseInfoBuffer
) {
2450 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2452 senseBuffer
->ErrorCode
= 0x70;
2453 senseBuffer
->Valid
= 1;
2454 senseBuffer
->AdditionalSenseLength
= 0xb;
2455 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2456 senseBuffer
->AdditionalSenseCode
= 0;
2457 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2459 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2462 deviceExtension
->lun
[ldev
].ErrorCount
++;
2464 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2466 KdPrint2((PRINT_PREFIX
2467 "IDE: Media change\n"));
2468 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2469 srbStatus
= SRB_STATUS_ERROR
;
2471 if (Srb
->SenseInfoBuffer
) {
2473 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2475 senseBuffer
->ErrorCode
= 0x70;
2476 senseBuffer
->Valid
= 1;
2477 senseBuffer
->AdditionalSenseLength
= 0xb;
2478 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2479 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2480 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2482 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2485 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2487 KdPrint2((PRINT_PREFIX
2488 "IDE: Data error\n"));
2489 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2490 srbStatus
= SRB_STATUS_ERROR
;
2492 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2493 deviceExtension
->lun
[ldev
].ErrorCount
++;
2496 // Build sense buffer
2497 if (Srb
->SenseInfoBuffer
) {
2499 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2501 senseBuffer
->ErrorCode
= 0x70;
2502 senseBuffer
->Valid
= 1;
2503 senseBuffer
->AdditionalSenseLength
= 0xb;
2504 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2505 senseBuffer
->AdditionalSenseCode
= 0;
2506 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2508 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2512 if (deviceExtension
->lun
[ldev
].ErrorCount
>= MAX_ERRORS
) {
2513 // deviceExtension->DWordIO = FALSE;
2515 KdPrint2((PRINT_PREFIX
2516 "MapError: ErrorCount >= MAX_ERRORS\n"));
2518 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2519 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2522 KdPrint2((PRINT_PREFIX
2523 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2526 KdPrint2((PRINT_PREFIX
2527 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2536 ScsiPortLogError( HwDeviceExtension
,
2544 // Reprogram to not use Multi-sector.
2547 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2548 !(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2550 statusByte
= AtaCommand(deviceExtension
, ldev
& 0x1, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2552 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2553 // command was aborted.
2554 if (statusByte
& IDE_STATUS_ERROR
) {
2556 // Read the error register.
2557 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2559 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2563 // Adjust the devExt. value, if necessary.
2564 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2572 // Set SCSI status to indicate a check condition.
2573 Srb
->ScsiStatus
= scsiStatus
;
2582 Routine Description:
2585 HwDeviceExtension - HBA miniport driver's adapter data storage
2588 TRUE - if initialization successful.
2589 FALSE - if initialization unsuccessful.
2595 IN PVOID HwDeviceExtension
2598 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2599 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2602 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2604 if(WinVer_WDM_Model
) {
2605 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2608 /* do extra chipset specific setups */
2609 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2611 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2612 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2613 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2616 for (c
= 0; c
< numberChannels
; c
++) {
2617 AtapiHwInitialize__(deviceExtension
, c
);
2619 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2621 } // end AtapiHwInitialize()
2625 AtapiHwInitialize__(
2626 IN PHW_DEVICE_EXTENSION deviceExtension
,
2631 UCHAR statusByte
, errorByte
;
2632 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2633 PHW_LU_EXTENSION LunExt
;
2635 ULONG PreferedMode
= 0xffffffff;
2637 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2638 FindDevices(deviceExtension
, 0, lChannel
);
2640 for (i
= lChannel
*2; i
< (lChannel
+1)*2; i
++) {
2642 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2644 LunExt
= &(deviceExtension
->lun
[i
]);
2646 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2650 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2651 AtapiStallExecution(1);
2653 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2655 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2656 // Enable media status notification
2657 IdeMediaStatus(TRUE
,deviceExtension
,(UCHAR
)i
);
2659 // If supported, setup Multi-block transfers.
2660 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2661 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2662 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2664 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2665 // command was aborted.
2666 if (statusByte
& IDE_STATUS_ERROR
) {
2668 // Read the error register.
2669 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2671 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2675 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2676 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2677 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2679 if (statusByte
& IDE_STATUS_ERROR
) {
2680 // Read the error register.
2681 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2683 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2687 // Adjust the devExt. value, if necessary.
2688 LunExt
->MaximumBlockXfer
= 0;
2691 KdPrint2((PRINT_PREFIX
2692 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2694 LunExt
->MaximumBlockXfer
));
2697 if(LunExt
->IdentifyData
.MajorRevision
) {
2699 if(LunExt
->opt_ReadCacheEnable
) {
2700 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2701 // If supported, setup read/write cacheing
2702 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2703 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2704 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2706 // Check for errors.
2707 if (statusByte
& IDE_STATUS_ERROR
) {
2708 KdPrint2((PRINT_PREFIX
2709 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2711 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2713 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2716 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2717 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2718 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2719 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2720 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2722 if(LunExt
->opt_WriteCacheEnable
) {
2723 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2724 // If supported & allowed, setup write cacheing
2725 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2726 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2727 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2728 // Check for errors.
2729 if (statusByte
& IDE_STATUS_ERROR
) {
2730 KdPrint2((PRINT_PREFIX
2731 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2733 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2735 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2738 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2739 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2740 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2741 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2742 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2746 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2749 BOOLEAN isSanyo
= FALSE
;
2752 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2754 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2755 for (j
= 0; j
< 26; j
+= 2) {
2757 // Build a buffer based on the identify data.
2758 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2761 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2763 // Inquiry string for older model had a '-', newer is '_'
2764 if (vendorId
[12] == 'C') {
2766 // Torisan changer. Set the bit. This will be used in several places
2767 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2768 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2769 LunExt
->DiscsPresent
= 3;
2775 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2776 if(PreferedMode
== 0xffffffff) {
2777 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2778 PreferedMode
= chan
->MaxTransferMode
;
2781 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2782 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2783 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2786 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2787 LunExt
->OrigTransferMode
=
2788 LunExt
->LimitedTransferMode
=
2789 LunExt
->TransferMode
=
2792 AtapiDmaInit__(deviceExtension
, i
);
2794 LunExt
->OrigTransferMode
=
2795 LunExt
->LimitedTransferMode
=
2796 LunExt
->TransferMode
;
2797 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2799 // We need to get our device ready for action before
2800 // returning from this function
2802 // According to the atapi spec 2.5 or 2.6, an atapi device
2803 // clears its status BSY bit when it is ready for atapi commands.
2804 // However, some devices (Panasonic SQ-TC500N) are still
2805 // not ready even when the status BSY is clear. They don't react
2806 // to atapi commands.
2808 // Since there is really no other indication that tells us
2809 // the drive is really ready for action. We are going to check BSY
2810 // is clear and then just wait for an arbitrary amount of time!
2812 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2815 // have to get out of the loop sometime!
2816 // 10000 * 100us = 1000,000us = 1000ms = 1s
2818 GetStatus(chan
, statusByte
);
2819 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2821 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2822 // Wait for Busy to drop.
2823 AtapiStallExecution(100);
2824 GetStatus(chan
, statusByte
);
2828 // 5000 * 100us = 500,000us = 500ms = 0.5s
2831 AtapiStallExecution(100);
2832 } while (waitCount
--);
2834 GetBaseStatus(chan
, statusByte
);
2835 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2836 AtapiStallExecution(10);
2841 } // end AtapiHwInitialize()
2848 AtapiHwInitializeChanger(
2849 IN PVOID HwDeviceExtension
,
2850 IN PSCSI_REQUEST_BLOCK Srb
,
2851 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2853 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2854 ULONG ldev
= GET_LDEV(Srb
);
2856 if (MechanismStatus
) {
2857 deviceExtension
->lun
[ldev
].DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2858 if (deviceExtension
->lun
[ldev
].DiscsPresent
> 1) {
2859 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
2863 } // end AtapiHwInitializeChanger()
2868 Routine Description:
2869 This routine will parse the string for a match on the keyword, then
2870 calculate the value for the keyword and return it to the caller.
2873 String - The ASCII string to parse.
2874 KeyWord - The keyword for the value desired.
2877 Zero if value not found
2878 Value converted from ASCII to binary.
2883 AtapiParseArgumentString(
2891 ULONG stringLength
= 0;
2892 ULONG keyWordLength
= 0;
2902 // Calculate the string length.
2908 // Calculate the keyword length.
2914 if (keyWordLength
> stringLength
) {
2916 // Can't possibly have a match.
2920 // Now setup and start the compare.
2925 // The input string may start with white space. Skip it.
2926 while (*cptr
== ' ' || *cptr
== '\t') {
2930 if (*cptr
== '\0') {
2936 while ((*cptr
== *kptr
) ||
2937 (*cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
2938 (*cptr
>= 'a' && *cptr
- ('a' - 'A') == *kptr
)) {
2942 if (*cptr
== '\0') {
2948 if (*kptr
== '\0') {
2950 // May have a match backup and check for blank or equals.
2951 while (*cptr
== ' ' || *cptr
== '\t') {
2955 // Found a match. Make sure there is an equals.
2958 // Not a match so move to the next semicolon.
2960 if (*cptr
++ == ';') {
2961 goto ContinueSearch
;
2966 // Skip the equals sign.
2969 // Skip white space.
2970 while ((*cptr
== ' ') || (*cptr
== '\t')) {
2974 if (*cptr
== '\0') {
2975 // Early end of string, return not found
2980 // This isn't it either.
2982 goto ContinueSearch
;
2986 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
2987 // Value is in Hex. Skip the "0x"
2989 for (index
= 0; *(cptr
+ index
); index
++) {
2991 if (*(cptr
+ index
) == ' ' ||
2992 *(cptr
+ index
) == '\t' ||
2993 *(cptr
+ index
) == ';') {
2997 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
2998 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3000 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3001 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3002 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3003 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3005 // Syntax error, return not found.
3012 // Value is in Decimal.
3013 for (index
= 0; *(cptr
+ index
); index
++) {
3015 if (*(cptr
+ index
) == ' ' ||
3016 *(cptr
+ index
) == '\t' ||
3017 *(cptr
+ index
) == ';') {
3021 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3022 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3025 // Syntax error return not found.
3034 // Not a match check for ';' to continue search.
3036 if (*cptr
++ == ';') {
3037 goto ContinueSearch
;
3043 } // end AtapiParseArgumentString()_
3051 IN PVOID HwDeviceExtension
,
3056 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3057 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3060 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3063 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3064 // If the last command was DSC restrictive, see if it's set. If so, the device is
3065 // ready for a new request. Otherwise, reset the timer and come back to here later.
3067 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3068 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3069 // we shall have no problem with interrupt handler.
3070 if (!srb
|| chan
->ExpectingInterrupt
) {
3071 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3072 chan
->DpcState
= DPC_STATE_TIMER
;
3073 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3074 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3075 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3077 goto ReturnCallback
;
3081 if (!IS_RDP((srb
->Cdb
[0]))) {
3082 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3086 goto ReturnEnableIntr
;
3088 GetStatus(chan
, statusByte
);
3089 if (statusByte
& IDE_STATUS_DSC
) {
3091 UCHAR PathId
= srb
->PathId
;
3092 UCHAR TargetId
= srb
->TargetId
;
3093 UCHAR Lun
= srb
->Lun
;
3095 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3096 AtapiDmaDBSync(chan
, srb
);
3097 UniataRemoveRequest(chan
, srb
);
3098 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3099 // Clear current SRB.
3100 if(!deviceExtension
->simplexOnly
) {
3101 srb
= UniataGetCurRequest(chan
);
3107 // Ask for next request.
3108 ScsiPortNotification(NextLuRequest
,
3113 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3116 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3120 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3123 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3127 goto ReturnCallback
;
3132 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3133 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3134 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3135 #ifdef UNIATA_USE_XXableInterrupts
3136 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3137 // must be called on DISPATCH_LEVEL
3138 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3139 AtapiEnableInterrupts__
);
3141 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3142 InterlockedExchange(&(chan
->CheckIntr
),
3144 // Will raise IRQL to DIRQL
3145 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3146 AtapiEnableInterrupts__
,
3148 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3149 #endif // UNIATA_USE_XXableInterrupts
3151 //ASSERT(!deviceExtension->simplexOnly);
3156 // Check other channel
3157 // In simplex mode no interrupts must appear on other channels
3158 for(_c
=0; _c
<deviceExtension
->NumberChannels
-1; _c
++) {
3159 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3161 chan
= &(deviceExtension
->chan
[c
]);
3163 if((ULONG
)InterlockedCompareExchange(&chan
->CheckIntr
,
3165 CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
) {
3166 //ASSERT(!deviceExtension->simplexOnly);
3167 chan
->DpcState
= DPC_STATE_ISR
;
3168 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3169 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3173 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3176 } // end AtapiCallBack__()
3181 IN PVOID HwDeviceExtension
3184 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3187 #endif //UNIATA_CORE
3191 Routine Description:
3193 This is the interrupt service routine for ATAPI IDE miniport driver.
3197 HwDeviceExtension - HBA miniport driver's adapter data storage
3201 TRUE if expecting an interrupt.
3207 IN PVOID HwDeviceExtension
3210 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3212 BOOLEAN status
= FALSE
;
3216 BOOLEAN checked
[AHCI_MAX_PORT
];
3218 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
3220 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3221 checked
[_c
] = FALSE
;
3224 // atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
3225 for(pass
=0; pass
<2; pass
++) {
3226 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3228 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3229 //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags)
3230 // & DFLAGS_DEVICE_PRESENT;
3235 // check non-empty and expecting interrupt channels first
3236 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3241 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3243 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3244 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3247 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3249 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3250 // c_state = deviceExtension->chan[c].CheckIntr;
3251 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3252 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3254 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3256 CHECK_INTR_DETECTED
);
3257 if(c_state
== CHECK_INTR_IDLE
) {
3258 // c_state = deviceExtension->chan[c].CheckIntr;
3259 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3260 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3262 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3266 } while(c_state
== CHECK_INTR_CHECK
);
3267 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3268 // check if already serviced
3269 if(c_state
== CHECK_INTR_ACTIVE
) {
3270 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3274 if((c_state
== CHECK_INTR_DETECTED
) ||
3275 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3278 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3279 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3282 // disable interrupts on other channel of legacy mode
3283 // ISA-bridged onboard controller
3284 if(deviceExtension
->simplexOnly
/*||
3285 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3286 AtapiDisableInterrupts(deviceExtension
, !c
);
3289 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3290 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3291 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3292 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3295 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3296 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3299 // re-enable interrupts on other channel
3300 if(deviceExtension
->simplexOnly
/*||
3301 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3302 AtapiEnableInterrupts(deviceExtension
, !c
);
3306 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3307 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3312 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3314 deviceExtension
->FirstChannelToCheck
++;
3315 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3316 deviceExtension
->FirstChannelToCheck
= 0;
3319 } // end AtapiInterrupt()
3327 IN PKINTERRUPT Interrupt
,
3328 IN PVOID Isr2HwDeviceExtension
3332 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3333 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3335 BOOLEAN status
= FALSE
;
3339 // we should never get here for ISA/MCA
3340 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3341 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3345 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3346 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3348 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3349 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3353 if((ULONG
)CrNtInterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3355 CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
) {
3356 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3357 // hunt on unexpected intr (Some devices generate double interrupts,
3358 // some controllers (at least CMD649) interrupt twice with small delay.
3359 // If interrupts are disabled, they queue interrupt and re-issue it later,
3360 // when we do not expect it.
3365 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3367 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3369 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3370 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3375 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3377 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3380 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3381 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3382 // there is an active ISR/DPC for one channel, but
3383 // we have an interrupt from another one
3384 // Lets inform current ISR/DPC about new interrupt
3385 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3389 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3392 } // end AtapiInterrupt2()
3394 RETTYPE_XXableInterrupts
3397 IN PVOID HwDeviceExtension
3400 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3403 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3404 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3406 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3408 if((ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3410 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3415 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3418 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3419 AtapiDisableInterrupts(deviceExtension, lChannel);
3422 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3423 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3424 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3427 return RETVAL_XXableInterrupts
;
3428 } // end AtapiInterruptDpc()
3431 RETTYPE_XXableInterrupts
3433 AtapiEnableInterrupts__(
3434 IN PVOID HwDeviceExtension
3437 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3438 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3440 PHW_CHANNEL chan
= NULL
;
3442 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3443 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3444 chan
= &(deviceExtension
->chan
[c
]);
3446 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3447 // enable intrs on requested channel
3448 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3449 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3450 InterlockedExchange(&(chan
->CheckIntr
),
3453 // check if current or other channel(s) interrupted
3454 //AtapiInterrupt(HwDeviceExtension);
3456 if(deviceExtension
->simplexOnly
) {
3460 // check if other channel(s) interrupted
3461 // must do nothing in simplex mode
3462 if((ULONG
)CrNtInterlockedCompareExchange(&(chan
->CheckIntr
),
3464 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3467 //ASSERT(!deviceExtension->simplexOnly);
3468 chan
->DpcState
= DPC_STATE_ISR
;
3469 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3470 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3474 // In simplex mode next command must be sent to device here
3475 if(deviceExtension
->simplexOnly
&& chan
) {
3476 PSCSI_REQUEST_BLOCK srb
;
3477 chan
= UniataGetNextChannel(chan
);
3479 srb
= UniataGetCurRequest(chan
);
3484 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3488 return RETVAL_XXableInterrupts
;
3490 } // end AtapiEnableInterrupts__()
3492 #endif //UNIATA_CORE
3497 AtapiEnableInterrupts(
3498 IN PVOID HwDeviceExtension
,
3502 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3503 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3504 if(c
>= deviceExtension
->NumberChannels
) {
3507 if(!InterlockedDecrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3508 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3510 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3512 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3513 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3516 } // end AtapiEnableInterrupts()
3520 AtapiDisableInterrupts(
3521 IN PVOID HwDeviceExtension
,
3525 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3526 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3527 // mark channel as busy
3528 if(c
>= deviceExtension
->NumberChannels
) {
3531 if(InterlockedIncrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3532 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3533 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3534 deviceExtension
->chan
[c
].ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
3538 } // end AtapiDisableInterrupts()
3542 Check hardware for interrupt state
3546 AtapiCheckInterrupt__(
3547 IN PVOID HwDeviceExtension
,
3548 IN UCHAR c
// logical channel
3551 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3552 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3553 PHW_LU_EXTENSION LunExt
;
3555 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
3556 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
3559 ULONG pr_status
= 0;
3560 UCHAR dma_status
= 0;
3564 ULONG slotNumber
= deviceExtension
->slotNumber
;
3565 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
3566 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
3569 BOOLEAN DmaTransfer
= FALSE
;
3570 BOOLEAN OurInterrupt
= FALSE
;
3572 UCHAR interruptReason
;
3573 BOOLEAN EarlyIntr
= FALSE
;
3575 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
3578 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3580 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
3582 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
3583 deviceExtension
->Channel
+ c
, c
));
3585 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
3586 deviceExtension
->Channel
+ c
, c
));
3587 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3588 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
3591 // do controller-specific interrupt servicing staff
3592 if(deviceExtension
->UnknownDev
) {
3593 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
3597 if((ChipFlags
& UNIATA_AHCI
) &&
3598 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3599 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
);
3600 return OurInterrupt
;
3604 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
3605 // Such behavior was observed with Intel ICH-xxx chips
3606 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
3610 case ATA_PROMISE_ID
: {
3614 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
3618 ((Channel
) ? 0x00004000 : 0x00000400))) {
3619 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
3624 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
3625 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
3628 if(!(status
& 0x20)) {
3629 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
3634 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
3635 if(ChipFlags
& PRSATA
) {
3636 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
3637 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
3639 if(pr_status
& (0x11 << Channel
)) {
3640 // TODO: reset channel
3641 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
3644 if(!(status
& (0x01 << Channel
))) {
3645 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
3648 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
3652 case ATA_NVIDIA_ID
: {
3653 if(!(ChipFlags
& UNIATA_SATA
))
3656 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
3658 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
3659 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
3661 /* get and clear interrupt status */
3662 if(ChipFlags
& NVQ
) {
3663 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3664 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
3666 pr_status
= AtapiReadPortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3667 AtapiWritePortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
3669 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
3671 /* check for and handle connect events */
3672 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
3673 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
3675 /* check for and handle disconnect events */
3676 if((pr_status
& (0x08UL
<< shift
)) &&
3677 !((pr_status
& (0x04UL
<< shift
) &&
3678 AtapiReadPort4(chan
, IDX_SATA_SStatus
))) ) {
3679 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
3681 /* do we have any device action ? */
3682 if(!(pr_status
& (0x01UL
<< shift
))) {
3683 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
3684 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3693 KdPrint2((PRINT_PREFIX
"ATI\n"));
3694 if(ChipType
== SIIMIO
) {
3699 case ATA_SILICON_IMAGE_ID
:
3701 if(ChipType
== SIIMIO
) {
3703 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
3704 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
3705 if(reg32
== 0xffffffff) {
3706 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
3709 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
))) {
3710 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
3714 if(ChipFlags
& UNIATA_SATA
) {
3715 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
3717 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
3718 * controllers continue to assert IRQ as long as
3719 * SError bits are pending. Clear SError immediately.
3721 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3729 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3730 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
3731 return OurInterrupt
;
3733 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
3734 goto skip_dma_stat_check
;
3737 if(!(deviceExtension
->HwFlags
& SIIINTR
))
3739 GetPciConfig1(0x71, reg8
);
3740 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
3742 (Channel
? 0x08 : 0x04))) {
3746 KdPrint2((PRINT_PREFIX
" cmd our\n"));
3749 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
3756 //dma_status = GetDmaStatus(deviceExtension, lChannel);
3757 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3758 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
3761 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
3762 AtapiStallExecution(1);
3763 AtapiWritePort1(chan
, IDX_BM_Command
,
3764 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
3765 goto skip_dma_stat_check
;
3767 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3768 if(ChipFlags
& UNIATA_AHCI
) {
3771 if(ChipFlags
& UNIATA_SATA
) {
3772 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3779 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
3781 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3782 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
3783 if(dma_status
& BM_STATUS_ERR
) {
3784 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
3787 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3788 GetStatus(chan
, statusByte
);
3789 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3790 if(statusByte
& IDE_STATUS_ERROR
) {
3791 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
3799 if(dma_status
& BM_STATUS_INTR
) {
3800 // bullshit, we have DMA interrupt, but had never initiate DMA operation
3801 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
3802 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
3807 skip_dma_stat_check
:
3808 if(!(ChipFlags
& UNIATA_SATA
)) {
3809 AtapiStallExecution(1);
3812 LunExt
= &(deviceExtension
->lun
[c
*2 + chan
->cur_cdev
]);
3813 /* if drive is busy it didn't interrupt */
3814 /* the exception is DCS + BSY state of ATAPI devices */
3815 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3816 GetStatus(chan
, statusByte
);
3817 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3818 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
3820 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
3822 if (statusByte
== 0xff) {
3823 // interrupt from empty controller ?
3825 if (statusByte
& IDE_STATUS_BUSY
) {
3826 if(!chan
->ExpectingInterrupt
) {
3827 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
3828 return OurInterrupt
;
3831 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3832 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3834 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
3837 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
3838 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
3841 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
3842 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
3848 if(dma_status
& BM_STATUS_INTR
) {
3849 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
3850 /* clear interrupt and get status */
3851 GetBaseStatus(chan
, statusByte
);
3852 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
3856 if(g_WaitBusyInISR
) {
3857 GetStatus(chan
, statusByte
);
3858 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
3859 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3860 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
3861 if (!(statusByte
& IDE_STATUS_BUSY
)) {
3862 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
3864 if (statusByte
& IDE_STATUS_BUSY
) {
3865 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
3872 /* clear interrupt and get status */
3873 GetBaseStatus(chan
, statusByte
);
3874 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
3875 if (statusByte
== 0xff) {
3876 // interrupt from empty controller ?
3878 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
3879 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
3880 return OurInterrupt
;
3883 #ifndef UNIATA_PIO_ONLY
3885 if(!EarlyIntr
|| g_WaitBusyInISR
) {
3886 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
3888 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3889 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3893 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
3895 AtaReq
->ReqState
= REQ_STATE_EARLY_INTR
;
3901 if (!(chan
->ExpectingInterrupt
)) {
3903 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
3905 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3906 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3908 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
3909 return OurInterrupt
;
3911 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
3912 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
3913 return OurInterrupt
;
3915 //ASSERT(!chan->queue_depth || chan->cur_req);
3917 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
3920 } // end AtapiCheckInterrupt__()
3926 IN PVOID HwDeviceExtension
,
3930 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3931 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3933 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3934 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3936 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
3937 ULONG status
= SRB_STATUS_SUCCESS
;
3938 UCHAR dma_status
= 0;
3941 UCHAR statusByte
= 0,interruptReason
;
3943 BOOLEAN atapiDev
= FALSE
;
3948 BOOLEAN DmaTransfer
= FALSE
;
3950 ULONG TimerValue
= 1000;
3951 #ifdef UNIATA_USE_XXableInterrupts
3952 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
3954 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
3955 #endif // UNIATA_USE_XXableInterrupts
3956 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
3957 // BOOLEAN RestoreUseDpc = FALSE;
3958 BOOLEAN DataOverrun
= FALSE
;
3959 BOOLEAN NoStartIo
= TRUE
;
3961 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
3963 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
3964 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
3970 UCHAR OldReqState
= REQ_STATE_NONE
;
3972 PHW_LU_EXTENSION LunExt
;
3975 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3977 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
3979 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
3980 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ) {
3982 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
3986 PathId
= srb
->PathId
;
3987 TargetId
= srb
->TargetId
;
3993 goto enqueue_next_req
;
3996 ldev
= GET_LDEV2(PathId
, TargetId
, Lun
);
3997 DeviceNumber
= (UCHAR
)(ldev
& 1);
3998 LunExt
= &(deviceExtension
->lun
[ldev
]);
3999 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4000 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4002 // check if we are in ISR DPC
4004 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4005 goto ServiceInterrupt
;
4009 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4012 if (!(chan
->ExpectingInterrupt
)) {
4014 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4018 // change request state
4020 OldReqState
= AtaReq
->ReqState
;
4021 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4022 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4025 // We don't want using DPC for fast operations, like
4026 // DMA completion, sending CDB, short ATAPI transfers, etc.
4028 // We MUST use DPC, because of interprocessor synchronization
4029 // on multiprocessor platforms
4032 goto ServiceInterrupt
;
4034 switch(OldReqState
) {
4035 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4036 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4037 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4038 case REQ_STATE_DPC_WAIT_BUSY0
:
4039 case REQ_STATE_DPC_WAIT_BUSY1
:
4040 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4041 goto ServiceInterrupt
;
4042 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4043 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4047 if(!DmaTransfer
&& !atapiDev
) {
4048 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4055 goto ServiceInterrupt
;
4057 #ifdef UNIATA_USE_XXableInterrupts
4059 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4061 // shall never get here
4066 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4068 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4069 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4071 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4074 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4075 goto ServiceInterrupt
;
4076 #endif // UNIATA_USE_XXableInterrupts
4081 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4082 // We always get here when are called from timer callback, which is invoked on DRQL.
4083 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4085 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4086 // disable interrupts for this channel,
4087 // but avoid recursion and double-disable
4088 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4089 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4092 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4094 #ifdef UNIATA_USE_XXableInterrupts
4095 // Will lower IRQL to DISPATCH_LEVEL
4096 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4097 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4098 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4100 // Will raise IRQL to DIRQL
4101 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4104 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4105 #endif // UNIATA_USE_XXableInterrupts
4110 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4112 // Will raise IRQL to DIRQL
4113 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4117 #endif //UNIATA_CORE
4121 if(AtaReq
&& InDpc
) {
4122 switch(AtaReq
->ReqState
) {
4123 case REQ_STATE_DPC_WAIT_DRQ0
:
4125 case REQ_STATE_DPC_WAIT_BUSY
:
4127 case REQ_STATE_DPC_WAIT_DRQ
:
4129 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4131 case REQ_STATE_DPC_WAIT_BUSY0
:
4132 case REQ_STATE_DPC_WAIT_BUSY1
:
4133 // continue normal execution
4139 #endif //UNIATA_CORE
4141 // make additional delay for old devices (if we are not in DPC)
4142 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4146 !(deviceExtension->HwFlags & UNIATA_SATA)
4148 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4149 AtapiStallExecution(10);
4152 /* clear interrupt and get status */
4153 GetBaseStatus(chan
, statusByte
);
4155 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4157 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4161 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4167 if (statusByte
& IDE_STATUS_BUSY
) {
4168 if (deviceExtension
->DriverMustPoll
) {
4169 // Crashdump is polling and we got caught with busy asserted.
4170 // Just go away, and we will be polled again shortly.
4171 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4172 goto ReturnEnableIntr
;
4175 // Ensure BUSY is non-asserted.
4176 // make a very small idle before falling to DPC
4177 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4179 for (i
= 0; i
< k
; i
++) {
4181 GetBaseStatus(chan
, statusByte
);
4182 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4185 AtapiStallExecution(10);
4188 if (!InDpc
&& UseDpc
&& i
== 2) {
4190 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4193 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4198 AtapiStallExecution(TimerValue
);
4199 goto ServiceInterrupt
;
4200 #endif //UNIATA_CORE
4202 if (InDpc
&& i
== k
) {
4203 // reset the controller.
4204 KdPrint2((PRINT_PREFIX
4205 " Resetting due to BUSY on entry - %#x.\n",
4207 goto IntrPrepareResetController
;
4212 if(!LunExt
->IdentifyData
.MajorRevision
&&
4215 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4217 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices (2)\n"));
4218 AtapiStallExecution(10);
4220 if (statusByte
& IDE_STATUS_BUSY
) {
4221 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {
4222 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting\n"));
4224 GetStatus(chan
, statusByte
);
4225 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4226 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4227 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
4228 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4229 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4233 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4235 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4237 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4239 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4241 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4246 AtapiStallExecution(TimerValue
);
4247 #endif //UNIATA_CORE
4250 AtapiStallExecution(10);
4252 if (statusByte
& IDE_STATUS_BUSY
) {
4253 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4259 if(AtaReq
&& DmaTransfer
) {
4260 switch(OldReqState
) {
4261 case REQ_STATE_EARLY_INTR
:
4262 case REQ_STATE_DPC_WAIT_BUSY0
:
4264 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4265 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4266 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4273 // Check for error conditions.
4274 if ((statusByte
& IDE_STATUS_ERROR
) ||
4275 (dma_status
& BM_STATUS_ERR
)) {
4277 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4278 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4280 if(error & IDE_STATUS_CORRECTED_ERROR) {
4281 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4282 statusByte &= ~IDE_STATUS_ERROR;
4287 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4289 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4294 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4295 AtapiStallExecution(100);
4297 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4298 AtapiStallExecution(10);
4302 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4303 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4305 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4306 GetStatus(chan
, statusByte
);
4307 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4308 AtapiStallExecution(100);
4315 /* if this is a UDMA CRC error, reinject request */
4318 if(AtaReq
->retry
< MAX_RETRIES
) {
4319 #ifdef IO_STATISTICS
4320 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
4321 #endif //IO_STATISTICS
4323 (error & IDE_ERROR_ICRC)*/) {
4324 if(AtaReq
->retry
< MAX_RETRIES
) {
4326 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4327 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4328 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4329 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4333 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4336 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
4340 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4341 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
4343 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
4344 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
4345 if(AtaReq
->retry
< MAX_RETRIES
) {
4347 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4348 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4349 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4350 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4354 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4357 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
4361 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
4362 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
4363 // Fail this request.
4364 status
= SRB_STATUS_ERROR
;
4365 goto CompleteRequest
;
4367 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
4370 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
4371 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
4372 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
4374 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
4375 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
4376 #ifdef IO_STATISTICS
4377 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
]++;
4378 if(chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->IoCount
/3 ||
4379 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
4382 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
4383 #endif //IO_STATISTICS
4384 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", deviceExtension
->lun
[DeviceNumber
].TransferMode
));
4385 deviceExtension
->lun
[DeviceNumber
].LimitedTransferMode
=
4386 deviceExtension
->lun
[DeviceNumber
].TransferMode
;
4389 #ifdef IO_STATISTICS
4390 chan
->lun
[DeviceNumber
]->IoCount
++;
4391 #endif //IO_STATISTICS
4395 // check reason for this interrupt.
4398 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
4401 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4402 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4404 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4406 wordsThisInterrupt
= DEV_BSIZE
/2;
4414 // simulate DRQ for DMA transfers
4415 statusByte
|= IDE_STATUS_DRQ
;
4417 if (statusByte
& IDE_STATUS_DRQ
) {
4420 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4422 if (LunExt
->MaximumBlockXfer
) {
4423 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
4426 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4428 interruptReason
= 0x2;
4430 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4431 interruptReason
= 0x0;
4434 status
= SRB_STATUS_ERROR
;
4435 goto CompleteRequest
;
4438 } else if (statusByte
& IDE_STATUS_BUSY
) {
4440 //AtapiEnableInterrupts(deviceExtension, lChannel);
4441 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
4446 if (AtaReq
->WordsLeft
) {
4448 // Funky behaviour seen with PCI IDE (not all, just one).
4450 // The ISR hits with DRQ low, but comes up later.
4451 for (k
= 0; k
< 5000; k
++) {
4452 GetStatus(chan
, statusByte
);
4453 if (statusByte
& IDE_STATUS_DRQ
) {
4458 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
4460 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
4464 AtapiStallExecution(TimerValue
);
4465 goto ServiceInterrupt
;
4466 #endif //UNIATA_CORE
4468 AtapiStallExecution(100);
4471 // reset the controller.
4472 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
4474 IntrPrepareResetController
:
4475 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
4476 goto ReturnEnableIntr
;
4479 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
4483 // Command complete - verify, write, or the SMART enable/disable.
4484 // Also get_media_status
4485 interruptReason
= 0x3;
4490 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
4491 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
4492 // Write the packet.
4493 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
4494 // Send CDB to device.
4495 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
, 6, 0);
4496 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4498 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
4499 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
4500 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, srb
);
4503 goto ReturnEnableIntr
;
4505 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
4510 // Pick up bytes to transfer and convert to words.
4512 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4515 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
4517 // Covert bytes to words.
4519 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
4521 if (wordCount
!= AtaReq
->WordsLeft
) {
4522 KdPrint2((PRINT_PREFIX
4523 "AtapiInterrupt: %d words requested; %d words xferred\n",
4528 // Verify this makes sense.
4529 if (wordCount
> AtaReq
->WordsLeft
) {
4530 wordCount
= AtaReq
->WordsLeft
;
4531 KdPrint2((PRINT_PREFIX
4532 "AtapiInterrupt: Write underrun\n"));
4538 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
4539 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4541 // Transfer only words requested.
4542 wordCount
= AtaReq
->WordsLeft
;
4546 // Transfer next block.
4547 wordCount
= wordsThisInterrupt
;
4551 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4552 //ASSERT(AtaReq->WordsLeft == wordCount);
4553 AtaReq
->WordsLeft
= 0;
4554 status
= SRB_STATUS_SUCCESS
;
4555 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4556 goto CompleteRequest
;
4558 // Ensure that this is a write command.
4559 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4561 KdPrint2((PRINT_PREFIX
4562 "AtapiInterrupt: Write interrupt\n"));
4564 statusByte
= WaitOnBusy(chan
);
4566 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4571 UniataGetPioTiming(LunExt
));
4575 (PULONG
)(AtaReq
->DataBuffer
),
4577 UniataGetPioTiming(LunExt
));
4581 KdPrint3((PRINT_PREFIX
4582 "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
4586 // Fail this request.
4587 status
= SRB_STATUS_ERROR
;
4588 goto CompleteRequest
;
4591 // Advance data buffer pointer and bytes left.
4592 AtaReq
->DataBuffer
+= wordCount
;
4593 AtaReq
->WordsLeft
-= wordCount
;
4596 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4599 goto ReturnEnableIntr
;
4601 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
4606 // Pick up bytes to transfer and convert to words.
4608 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
4609 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
4611 // Covert bytes to words.
4613 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
4615 if (wordCount
!= AtaReq
->WordsLeft
) {
4616 KdPrint2((PRINT_PREFIX
4617 "AtapiInterrupt: %d words requested; %d words xferred\n",
4622 // Verify this makes sense.
4623 if (wordCount
> AtaReq
->WordsLeft
) {
4624 wordCount
= AtaReq
->WordsLeft
;
4630 // Check if words left is at least 256.
4631 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4633 // Transfer only words requested.
4634 wordCount
= AtaReq
->WordsLeft
;
4638 // Transfer next block.
4639 wordCount
= wordsThisInterrupt
;
4643 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4644 //ASSERT(AtaReq->WordsLeft == wordCount);
4645 AtaReq
->WordsLeft
= 0;
4646 status
= SRB_STATUS_SUCCESS
;
4647 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4648 goto CompleteRequest
;
4650 // Ensure that this is a read command.
4651 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4654 "AtapiInterrupt: Read interrupt\n"));*/
4656 statusByte
= WaitOnBusy(chan
);
4658 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4659 KdPrint2((PRINT_PREFIX
4660 "IdeIntr: Read %#x words\n", wordCount
));
4665 UniataGetPioTiming(LunExt
));
4666 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
4667 //KdDump(AtaReq->DataBuffer, wordCount*2);
4668 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
4669 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
4672 GetStatus(chan
, statusByte
);
4673 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4676 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
4677 AtapiSuckPort2(chan
);
4681 KdPrint2((PRINT_PREFIX
4682 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
4685 (PULONG
)(AtaReq
->DataBuffer
),
4687 UniataGetPioTiming(LunExt
));
4691 KdPrint3((PRINT_PREFIX
4692 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
4696 // Fail this request.
4697 status
= SRB_STATUS_ERROR
;
4698 goto CompleteRequest
;
4701 // Advance data buffer pointer and bytes left.
4702 AtaReq
->DataBuffer
+= wordCount
;
4703 AtaReq
->WordsLeft
-= wordCount
;
4705 // Check for read command complete.
4706 if (AtaReq
->WordsLeft
== 0) {
4708 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
4711 // Work around to make many atapi devices return correct sector size
4712 // of 2048. Also certain devices will have sector count == 0x00, check
4714 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
4715 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
4717 AtaReq
->DataBuffer
-= wordCount
;
4718 if (AtaReq
->DataBuffer
[0] == 0x00) {
4720 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
4724 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
4725 AtaReq
->DataBuffer
+= wordCount
;
4730 // Completion for IDE drives.
4731 if (AtaReq->WordsLeft) {
4732 status = SRB_STATUS_DATA_OVERRUN;
4734 status = SRB_STATUS_SUCCESS;
4737 goto CompleteRequest;
4739 status
= SRB_STATUS_SUCCESS
;
4740 goto CompleteRequest
;
4745 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4749 goto ReturnEnableIntr
;
4751 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
4753 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
4754 // Command complete.
4756 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
4757 AtaReq
->WordsLeft
= 0;
4759 if (AtaReq
->WordsLeft
) {
4760 status
= SRB_STATUS_DATA_OVERRUN
;
4762 status
= SRB_STATUS_SUCCESS
;
4765 #ifdef UNIATA_DUMP_ATAPI
4767 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4771 PCHAR ModeSelectData
;
4773 PSCSI_REQUEST_BLOCK Srb
= srb
;
4775 Cdb
= (PCDB
)(Srb
->Cdb
);
4776 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
4777 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
4778 CdbDataLen
= Srb
->DataTransferLength
;
4780 if(CdbDataLen
> 0x1000) {
4781 CdbDataLen
= 0x1000;
4785 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
4786 KdPrint2(("P:T:D=%d:%d:%d\n",
4790 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
4793 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
4794 KdPrint(("ModeSense 6\n"));
4795 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4796 ModeSelectData
= CdbData
+4;
4797 KdDump(CdbData
, CdbDataLen
);
4799 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
4800 KdPrint(("ModeSense 10\n"));
4801 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4802 ModeSelectData
= CdbData
+8;
4803 KdDump(CdbData
, CdbDataLen
);
4805 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4806 KdPrint(("Read buffer from device:\n"));
4807 KdDump(CdbData
, CdbDataLen
);
4812 #endif //UNIATA_DUMP_ATAPI
4816 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest\n"));
4817 // Check and see if we are processing our secret (mechanism status/request sense) srb
4818 if (AtaReq
->OriginalSrb
) {
4822 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
4823 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
4825 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
4826 if (status
== SRB_STATUS_SUCCESS
) {
4828 AtapiHwInitializeChanger (HwDeviceExtension
,
4830 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
4832 // Get ready to issue the original srb
4833 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4834 AtaReq
->OriginalSrb
= NULL
;
4837 // failed! Get the sense key and maybe try again
4838 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
4840 AtaReq
->OriginalSrb
);
4843 // do not enable interrupts in DPC, do not waste time, do it now!
4844 if(UseDpc && chan->DisableIntr) {
4845 AtapiEnableInterrupts(HwDeviceExtension, c);
4847 RestoreUseDpc = TRUE;
4850 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4852 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
4854 if (srbStatus
== SRB_STATUS_PENDING
) {
4855 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
4856 goto ReturnEnableIntr
;
4860 // restore state on error
4862 AtapiDisableInterrupts(HwDeviceExtension, c);
4866 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
4868 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
4870 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
4871 if (status
== SRB_STATUS_DATA_OVERRUN
) {
4872 // Check to see if we at least get mininum number of bytes
4873 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
4874 (offsetof (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
4875 status
= SRB_STATUS_SUCCESS
;
4879 if (status
== SRB_STATUS_SUCCESS
) {
4881 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
4882 chan
->MechStatusRetryCount
) {
4884 // The sense key doesn't say the last request is illegal, so try again
4885 chan
->MechStatusRetryCount
--;
4886 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
4888 AtaReq
->OriginalSrb
);
4891 // last request was illegal. No point trying again
4892 AtapiHwInitializeChanger (HwDeviceExtension
,
4894 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4896 // Get ready to issue the original srb
4897 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4898 AtaReq
->OriginalSrb
= NULL
;
4900 #endif //UNIATA_CORE
4902 // do not enable interrupts in DPC, do not waste time, do it now!
4903 if(UseDpc && chan->DisableIntr) {
4904 AtapiEnableInterrupts(HwDeviceExtension, c);
4906 RestoreUseDpc = TRUE;
4909 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4911 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
4913 if (srbStatus
== SRB_STATUS_PENDING
) {
4914 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
4915 goto ReturnEnableIntr
;
4919 // restore state on error
4921 AtapiDisableInterrupts(HwDeviceExtension, c);
4927 // If we get here, it means AtapiSendCommand() has failed
4928 // Can't recover. Pretend the original srb has failed and complete it.
4930 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
4932 if (AtaReq
->OriginalSrb
) {
4933 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
4934 AtapiHwInitializeChanger (HwDeviceExtension
,
4936 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4937 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4938 AtaReq
->OriginalSrb
= NULL
;
4941 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
4943 // fake an error and read no data
4944 status
= SRB_STATUS_ERROR
;
4945 srb
->ScsiStatus
= 0;
4946 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
4947 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
4950 } else if (status
== SRB_STATUS_ERROR
) {
4952 // Map error to specific SRB status and handle request sense.
4953 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
4954 status
= MapError(deviceExtension
,
4959 } else if(!DmaTransfer
) {
4961 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
4962 // Command complete.
4964 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
4965 // Wait for busy to drop.
4966 for (i
= 0; i
< 5*30; i
++) {
4967 GetStatus(chan
, statusByte
);
4968 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4973 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
4975 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
4979 AtapiStallExecution(TimerValue
);
4980 goto ServiceInterrupt
;
4981 #endif //UNIATA_CORE
4983 AtapiStallExecution(100);
4988 // reset the controller.
4989 KdPrint2((PRINT_PREFIX
4990 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
4992 goto IntrPrepareResetController
;
4994 // Check to see if DRQ is still up.
4995 if(statusByte
& IDE_STATUS_DRQ
) {
4996 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
4998 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4999 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5001 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5004 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5007 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5009 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5011 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5012 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5013 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5017 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5018 //if ((statusByte & IDE_STATUS_DRQ)) {}
5019 if((statusByte
& IDE_STATUS_DRQ
) &&
5020 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5023 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5024 for (i
= 0; i
< 200; i
++) {
5025 GetStatus(chan
, statusByte
);
5026 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5031 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5032 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5037 AtapiStallExecution(TimerValue
);
5038 goto ServiceInterrupt
;
5039 #endif //UNIATA_CORE
5041 AtapiStallExecution(100);
5045 // reset the controller.
5046 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5048 goto IntrPrepareResetController
;
5052 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5053 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5054 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5056 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5057 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5061 // Clear interrupt expecting flag.
5062 chan
->ExpectingInterrupt
= FALSE
;
5063 InterlockedExchange(&(chan
->CheckIntr
),
5066 // Sanity check that there is a current request.
5068 // Set status in SRB.
5069 srb
->SrbStatus
= (UCHAR
)status
;
5071 // Check for underflow.
5072 if(AtaReq
->WordsLeft
) {
5074 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5075 // Subtract out residual words and update if filemark hit,
5076 // setmark hit , end of data, end of media...
5077 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5078 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5079 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5081 srb
->DataTransferLength
= 0;
5084 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5087 if(status
== SRB_STATUS_SUCCESS
) {
5088 AtaReq
->WordsTransfered
+= AtaReq
->bcount
* DEV_BSIZE
/2;
5090 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5091 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5092 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5093 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5094 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5097 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5098 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5102 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5105 // Indicate command complete.
5107 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5110 if (status
== SRB_STATUS_SUCCESS
&&
5111 srb
->SenseInfoBuffer
&&
5112 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5114 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5116 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5117 senseBuffer
->ErrorCode
= 0;
5118 senseBuffer
->Valid
= 1;
5119 senseBuffer
->AdditionalSenseLength
= 0xb;
5120 senseBuffer
->SenseKey
= 0;
5121 senseBuffer
->AdditionalSenseCode
= 0;
5122 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5124 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5126 AtapiDmaDBSync(chan
, srb
);
5127 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5128 UniataRemoveRequest(chan
, srb
);
5129 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5130 ScsiPortNotification(RequestComplete
,
5136 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5137 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5139 if (status
!= SRB_STATUS_SUCCESS
) {
5140 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5141 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5144 // Build the SMART status block depending upon the completion status.
5145 cmdOutParameters
->cBufferSize
= wordCount
;
5146 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5147 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5149 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5151 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5152 cmdOutParameters
->bBuffer
[0] = RETURN_SMART_STATUS
;
5153 cmdOutParameters
->bBuffer
[1] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
5154 cmdOutParameters
->bBuffer
[2] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Unused1
);
5155 cmdOutParameters
->bBuffer
[3] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5156 cmdOutParameters
->bBuffer
[4] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
);
5157 cmdOutParameters
->bBuffer
[5] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_DriveSelect
);
5158 cmdOutParameters
->bBuffer
[6] = SMART_CMD
;
5159 cmdOutParameters
->cBufferSize
= 8;
5162 // Indicate command complete.
5163 goto IntrCompleteReq
;
5168 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5173 for (i
= 0; i
< 5; i
++) {
5174 GetStatus(chan
, statusByte
);
5175 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5176 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5180 if (statusByte
& IDE_STATUS_DSC
) {
5181 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5185 AtapiStallExecution(50);
5188 // RDP can be cleared since previous check
5190 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5196 AtapiStallExecution(TimerValue
);
5197 goto ServiceInterrupt
;
5198 #endif //UNIATA_CORE
5201 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5204 srb
= UniataGetCurRequest(chan
);
5209 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5211 ScsiPortNotification(NextRequest
,
5215 ScsiPortNotification(NextLuRequest
,
5220 // in simplex mode next command must NOT be sent here
5221 if(!deviceExtension
->simplexOnly
) {
5222 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5225 // Try to get SRB fron any non-empty queue (later)
5226 if(deviceExtension
->simplexOnly
) {
5229 #endif //UNIATA_CORE
5231 goto ReturnEnableIntr
;
5235 // Unexpected int. Catch it
5236 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
5244 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
5246 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
5247 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
5248 #ifdef UNIATA_USE_XXableInterrupts
5249 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
5250 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
5251 // must be called on DISPATCH_LEVEL
5252 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
5253 AtapiEnableInterrupts__
);
5255 AtapiEnableInterrupts(HwDeviceExtension
, c
);
5256 InterlockedExchange(&(chan
->CheckIntr
),
5258 // Will raise IRQL to DIRQL
5260 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
5261 AtapiEnableInterrupts__
,
5263 #endif // UNIATA_CORE
5264 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5265 #endif // UNIATA_USE_XXableInterrupts
5269 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
5270 // in simplex mode next command must be sent here if
5272 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
5275 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
5276 chan
= UniataGetNextChannel(chan
);
5278 srb
= UniataGetCurRequest(chan
);
5282 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
5284 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5287 #endif //UNIATA_CORE
5290 } // end AtapiInterrupt__()
5296 Routine Description:
5298 This routine handles SMART enable, disable, read attributes and threshold commands.
5302 HwDeviceExtension - HBA miniport driver's adapter data storage
5303 Srb - IO request packet
5312 IdeSendSmartCommand(
5313 IN PVOID HwDeviceExtension
,
5314 IN PSCSI_REQUEST_BLOCK Srb
5317 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5318 ULONG c
= GET_CHANNEL(Srb
);
5319 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
5320 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5321 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5322 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5323 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
5325 UCHAR statusByte
,targetId
;
5328 if (regs
->bCommandReg
!= SMART_CMD
) {
5329 KdPrint2((PRINT_PREFIX
5330 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
5331 return SRB_STATUS_INVALID_REQUEST
;
5334 targetId
= cmdInParameters
.bDriveNumber
;
5336 //TODO optimize this check
5337 if ((!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) ||
5338 (deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
5340 return SRB_STATUS_SELECTION_TIMEOUT
;
5343 chan
->SmartCommand
= regs
->bFeaturesReg
;
5345 // Determine which of the commands to carry out.
5346 switch(regs
->bFeaturesReg
) {
5347 case READ_ATTRIBUTES
:
5348 case READ_THRESHOLDS
:
5350 statusByte
= WaitOnBusy(chan
);
5352 if (statusByte
& IDE_STATUS_BUSY
) {
5353 KdPrint2((PRINT_PREFIX
5354 "IdeSendSmartCommand: Returning BUSY status\n"));
5355 return SRB_STATUS_BUSY
;
5358 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5359 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
5361 // Set data buffer pointer and words left.
5362 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5363 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
5365 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5367 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5369 regs
->bSectorNumberReg
,
5370 regs
->bSectorCountReg
,
5374 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5375 // Wait for interrupt.
5376 return SRB_STATUS_PENDING
;
5378 return SRB_STATUS_ERROR
;
5382 case RETURN_SMART_STATUS
:
5383 case ENABLE_DISABLE_AUTOSAVE
:
5384 case EXECUTE_OFFLINE_DIAGS
:
5385 case SAVE_ATTRIBUTE_VALUES
:
5387 statusByte
= WaitOnBusy(chan
);
5389 if (statusByte
& IDE_STATUS_BUSY
) {
5390 KdPrint2((PRINT_PREFIX
5391 "IdeSendSmartCommand: Returning BUSY status\n"));
5392 return SRB_STATUS_BUSY
;
5395 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5396 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
5398 // Set data buffer pointer and indicate no data transfer.
5399 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5400 AtaReq
->WordsLeft
= 0;
5402 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5404 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5406 regs
->bSectorNumberReg
,
5407 regs
->bSectorCountReg
,
5411 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5412 // Wait for interrupt.
5413 return SRB_STATUS_PENDING
;
5415 return SRB_STATUS_ERROR
;
5416 } // end switch(regs->bFeaturesReg)
5418 return SRB_STATUS_INVALID_REQUEST
;
5420 } // end IdeSendSmartCommand()
5422 #endif //UNIATA_CORE
5426 UniAtaCalculateLBARegs(
5427 PHW_LU_EXTENSION LunExt
,
5428 ULONG startingSector
,
5432 UCHAR drvSelect
,sectorNumber
;
5438 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5439 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
5440 if(LunExt
->DeviceExtension
) {
5441 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
5444 return startingSector
;
5446 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5447 LunExt
->IdentifyData
.NumberOfHeads
;
5449 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5453 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
5455 cylinder
= (USHORT
)(startingSector
/ tmp
);
5456 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5457 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5458 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
5459 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
5460 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
5463 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5464 } // end UniAtaCalculateLBARegs()
5468 UniAtaCalculateLBARegsBack(
5469 PHW_LU_EXTENSION LunExt
,
5473 ULONG drvSelect
,sectorNumber
;
5477 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5480 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5481 LunExt
->IdentifyData
.NumberOfHeads
;
5483 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5484 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5485 sectorNumber
= (UCHAR
)(lba
& 0xff);
5487 lba
= sectorNumber
-1 +
5488 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5492 } // end UniAtaCalculateLBARegsBack()
5497 Routine Description:
5499 This routine handles IDE read and writes.
5503 HwDeviceExtension - HBA miniport driver's adapter data storage
5504 Srb - IO request packet
5514 IN PVOID HwDeviceExtension
,
5515 IN PSCSI_REQUEST_BLOCK Srb
,
5519 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5520 UCHAR lChannel
= GET_CHANNEL(Srb
);
5521 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5522 PHW_LU_EXTENSION LunExt
;
5523 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5524 ULONG ldev
= GET_LDEV(Srb
);
5525 UCHAR DeviceNumber
= (UCHAR
)(ldev
& 1);
5526 ULONG startingSector
;
5528 ULONG wordCount
= 0;
5529 UCHAR statusByte
,statusByte2
;
5532 BOOLEAN use_dma
= FALSE
;
5534 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5535 LunExt
= &deviceExtension
->lun
[ldev
];
5537 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5538 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5540 if(LunExt
->opt_ReadOnly
&&
5541 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
5542 if(LunExt
->opt_ReadOnly
== 1) {
5543 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
5544 return SRB_STATUS_ERROR
;
5546 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
5547 return SRB_STATUS_SUCCESS
;
5551 // Set data buffer pointer and words left.
5552 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5554 if(AtaReq
->WordsTransfered
) {
5555 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
5556 startingSector
= (ULONG
)(UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
5557 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
5558 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
5560 AtaReq
->TransferLength
/2,
5561 AtaReq
->WordsTransfered
,
5564 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
5565 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5566 // Set up 1st block.
5567 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5568 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5569 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
5571 AtaReq
->TransferLength
/2,
5574 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5577 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
5579 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
5580 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5582 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5589 // assume best case here
5590 // we cannot reinit Dma until previous request is completed
5591 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5593 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5594 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5595 (PUCHAR
)(AtaReq
->DataBuffer
),
5596 AtaReq
->bcount
* DEV_BSIZE
)) {
5600 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5601 } else { // exec_only
5602 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5605 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5609 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5610 return SRB_STATUS_PENDING
;
5613 // if this is queued request, reinit DMA and check
5614 // if DMA mode is still available
5615 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5616 if (/*EnableDma &&*/
5617 (LunExt
->TransferMode
>= ATA_DMA
)) {
5620 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5624 // Check if write request.
5625 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5627 // Prepare read command.
5629 cmd
= IDE_COMMAND_READ_DMA
;
5631 if(LunExt
->MaximumBlockXfer
) {
5632 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5634 cmd
= IDE_COMMAND_READ
;
5638 // Prepare write command.
5640 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
5641 cmd
= IDE_COMMAND_WRITE_DMA
;
5643 if (LunExt
->MaximumBlockXfer
) {
5644 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5646 if (AtaReq
->WordsLeft
< wordCount
) {
5647 // Transfer only words requested.
5648 wordCount
= AtaReq
->WordsLeft
;
5650 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5653 wordCount
= DEV_BSIZE
/2;
5654 cmd
= IDE_COMMAND_WRITE
;
5659 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5661 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5665 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5666 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5668 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5670 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5672 (USHORT
)(AtaReq
->bcount
),
5673 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5675 if(statusByte2
!= 0xff) {
5676 GetStatus(chan
, statusByte2
);
5678 if(statusByte2
& IDE_STATUS_ERROR
) {
5679 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5680 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5681 return SRB_STATUS_ERROR
;
5684 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5686 return SRB_STATUS_PENDING
;
5689 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5691 (USHORT
)(AtaReq
->bcount
),
5692 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5695 if (!(statusByte
& IDE_STATUS_DRQ
) ||
5696 statusByte
== 0xff) {
5698 if(statusByte
== 0xff) {
5699 KdPrint2((PRINT_PREFIX
5700 "IdeReadWrite: error sending command (%#x)\n",
5703 KdPrint2((PRINT_PREFIX
5704 "IdeReadWrite: DRQ never asserted (%#x)\n",
5708 AtaReq
->WordsLeft
= 0;
5710 // Clear interrupt expecting flag.
5711 chan
->ExpectingInterrupt
= FALSE
;
5712 InterlockedExchange(&(chan
->CheckIntr
),
5715 // Clear current SRB.
5716 UniataRemoveRequest(chan
, Srb
);
5718 return (statusByte
== 0xff) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
5721 chan
->ExpectingInterrupt
= TRUE
;
5722 InterlockedExchange(&(chan
->CheckIntr
),
5725 // Write next DEV_BSIZE/2*N words.
5726 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5727 KdPrint2((PRINT_PREFIX
5728 "IdeReadWrite: Write %#x words\n", wordCount
));
5733 UniataGetPioTiming(LunExt
));
5737 KdPrint2((PRINT_PREFIX
5738 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5741 (PULONG
)(AtaReq
->DataBuffer
),
5743 UniataGetPioTiming(LunExt
));
5746 // Adjust buffer address and words left count.
5747 AtaReq
->WordsLeft
-= wordCount
;
5748 AtaReq
->DataBuffer
+= wordCount
;
5750 // Wait for interrupt.
5751 return SRB_STATUS_PENDING
;
5753 } // end IdeReadWrite()
5759 Routine Description:
5760 This routine handles IDE Verify.
5763 HwDeviceExtension - HBA miniport driver's adapter data storage
5764 Srb - IO request packet
5773 IN PVOID HwDeviceExtension
,
5774 IN PSCSI_REQUEST_BLOCK Srb
5777 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5778 UCHAR lChannel
= GET_CHANNEL(Srb
);
5779 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5780 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5781 PHW_LU_EXTENSION LunExt
;
5782 ULONG ldev
= GET_LDEV(Srb
);
5784 ULONG startingSector
;
5791 LunExt
= &deviceExtension
->lun
[ldev
];
5792 // Drive has these number sectors.
5793 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
5794 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
5795 LunExt
->IdentifyData
.NumberOfHeads
*
5796 LunExt
->IdentifyData
.NumberOfCylinders
;
5799 KdPrint2((PRINT_PREFIX
5800 "IdeVerify: Total sectors %#x\n",
5803 // Get starting sector number from CDB.
5804 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5805 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5807 KdPrint2((PRINT_PREFIX
5808 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
5812 endSector
= startingSector
+ sectorCount
;
5814 KdPrint2((PRINT_PREFIX
5815 "IdeVerify: Ending sector %#x\n",
5818 if (endSector
> sectors
) {
5820 // Too big, round down.
5821 KdPrint2((PRINT_PREFIX
5822 "IdeVerify: Truncating request to %#x blocks\n",
5823 sectors
- startingSector
- 1));
5825 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
5829 // Set up sector count register. Round up to next block.
5830 if (sectorCount
> 0xFF) {
5831 sectorCount
= (USHORT
)0xFF;
5835 // Set data buffer pointer and words left.
5836 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5837 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5839 // Indicate expecting an interrupt.
5840 InterlockedExchange(&(chan
->CheckIntr
),
5843 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5845 statusByte
= AtaCommand48(deviceExtension
, ldev
& 0x01, GET_CHANNEL(Srb
),
5846 IDE_COMMAND_VERIFY
, lba
,
5850 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5851 // Wait for interrupt.
5852 return SRB_STATUS_PENDING
;
5854 return SRB_STATUS_ERROR
;
5856 } // end IdeVerify()
5858 #endif //UNIATA_CORE
5862 Routine Description:
5863 Send ATAPI packet command to device.
5866 HwDeviceExtension - HBA miniport driver's adapter data storage
5867 Srb - IO request packet
5875 IN PVOID HwDeviceExtension
,
5876 IN PSCSI_REQUEST_BLOCK Srb
,
5880 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5881 UCHAR lChannel
= GET_CHANNEL(Srb
);
5882 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5883 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5884 ULONG ldev
= GET_LDEV(Srb
);
5887 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
5888 BOOLEAN use_dma
= FALSE
;
5889 BOOLEAN dma_reinited
= FALSE
;
5890 BOOLEAN retried
= FALSE
;
5892 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
5893 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
5894 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
5896 #ifdef UNIATA_DUMP_ATAPI
5897 if(CmdAction
& CMD_ACTION_PREPARE
) {
5901 PCHAR ModeSelectData
;
5904 Cdb
= (PCDB
)(Srb
->Cdb
);
5905 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5906 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5907 CdbDataLen
= Srb
->DataTransferLength
;
5909 if(CdbDataLen
> 0x1000) {
5910 CdbDataLen
= 0x1000;
5914 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5915 KdPrint2(("P:T:D=%d:%d:%d\n",
5919 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
5922 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
5923 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
5924 Cdb
->WRITE_CD
.LBA
[0],
5925 Cdb
->WRITE_CD
.LBA
[1],
5926 Cdb
->WRITE_CD
.LBA
[2],
5927 Cdb
->WRITE_CD
.LBA
[3]
5930 if(ScsiCommand
== SCSIOP_WRITE12
) {
5931 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
5932 Cdb
->CDB12READWRITE
.LBA
[0],
5933 Cdb
->CDB12READWRITE
.LBA
[1],
5934 Cdb
->CDB12READWRITE
.LBA
[2],
5935 Cdb
->CDB12READWRITE
.LBA
[3]
5938 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
5939 KdPrint(("ModeSelect 6\n"));
5940 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5941 ModeSelectData
= CdbData
+4;
5942 KdDump(CdbData
, CdbDataLen
);
5944 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
5945 KdPrint(("ModeSelect 10\n"));
5946 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5947 ModeSelectData
= CdbData
+8;
5948 KdDump(CdbData
, CdbDataLen
);
5950 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5951 KdPrint(("Send buffer to device:\n"));
5952 KdDump(CdbData
, CdbDataLen
);
5957 #endif //UNIATA_DUMP_ATAPI
5960 if(CmdAction
== CMD_ACTION_PREPARE
) {
5961 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
5962 switch (Srb
->Cdb
[0]) {
5966 case SCSIOP_WRITE12
:
5970 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
5971 return SRB_STATUS_BUSY
;
5974 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5975 !AtaReq
->OriginalSrb
) {
5976 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
5977 return SRB_STATUS_BUSY
;
5981 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5982 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5984 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
5985 // Set data buffer pointer and words left.
5986 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5987 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5988 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5989 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5991 // check if reorderable
5992 switch(Srb
->Cdb
[0]) {
5994 case SCSIOP_WRITE12
:
5996 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6002 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6004 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6006 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6007 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6008 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
6009 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6013 // check if DMA read/write
6014 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6015 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6017 if(AtaReq
->TransferLength
) {
6019 switch(Srb
->Cdb
[0]) {
6021 case SCSIOP_WRITE12
:
6022 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
6028 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
6030 if(AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6031 (PUCHAR
)(AtaReq
->DataBuffer
),
6032 Srb
->DataTransferLength
6033 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
6035 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6040 case SCSIOP_READ_CD
:
6041 if(deviceExtension
->opt_AtapiDmaRawRead
)
6042 goto call_dma_setup
;
6046 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
6047 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6052 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
6053 KdPrint2((PRINT_PREFIX
"dma RO\n"));
6064 if(!AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6065 (PUCHAR
)(AtaReq
->DataBuffer
),
6066 Srb
->DataTransferLength
)) {
6067 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
6070 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6074 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
6078 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6079 // if this is queued request, reinit DMA and check
6080 // if DMA mode is still available
6081 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
6082 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6083 if (/*EnableDma &&*/
6084 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6085 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
6088 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6089 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
6092 dma_reinited
= TRUE
;
6096 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6097 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
6098 return SRB_STATUS_PENDING
;
6100 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6101 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6102 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6105 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6106 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
6108 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6109 //AtapiDmaReinit(deviceExtension, ldev, AtaReq);
6110 } if(AtaReq
->TransferLength
) {
6112 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
6113 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6114 if (/*EnableDma &&*/
6115 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6118 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6123 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
6125 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6126 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
6127 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
6128 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6131 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6132 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6133 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6136 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
6139 // We need to know how many platters our atapi cd-rom device might have.
6140 // Before anyone tries to send a srb to our target for the first time,
6141 // we must "secretly" send down a separate mechanism status srb in order to
6142 // initialize our device extension changer data. That's how we know how
6143 // many platters our target has.
6145 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6146 !AtaReq
->OriginalSrb
) {
6150 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6151 // Set this flag now. If the device hangs on the mech. status
6152 // command, we will not have the chance to set it.
6153 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6155 chan
->MechStatusRetryCount
= 3;
6156 AtaReq
->OriginalSrb
= Srb
;
6157 AtaReq
->Srb
= BuildMechanismStatusSrb (
6161 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6162 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6163 if (srbStatus
== SRB_STATUS_PENDING
) {
6164 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6167 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6168 AtaReq
->OriginalSrb
= NULL
;
6169 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6170 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6171 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6175 #endif //UNIATA_CORE
6177 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
6178 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
6180 // Make sure command is to ATAPI device.
6181 flags
= deviceExtension
->lun
[ldev
].DeviceFlags
;
6182 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6183 if((Srb
->Lun
) > (deviceExtension
->lun
[ldev
].DiscsPresent
- 1)) {
6185 // Indicate no device found at this address.
6186 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6187 return SRB_STATUS_SELECTION_TIMEOUT
;
6189 } else if(Srb
->Lun
> 0) {
6190 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6191 return SRB_STATUS_SELECTION_TIMEOUT
;
6194 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
6195 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6196 return SRB_STATUS_SELECTION_TIMEOUT
;
6199 // Select device 0 or 1.
6200 SelectDrive(chan
, ldev
& 0x1);
6202 // Verify that controller is ready for next command.
6203 GetStatus(chan
, statusByte
);
6204 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
6206 if(statusByte
== 0xff) {
6207 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
6210 if(statusByte
& IDE_STATUS_BUSY
) {
6211 if(statusByte
& IDE_STATUS_DSC
) {
6212 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
6214 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
6215 // We have to make reset here, since we are expecting device to be available
6216 //return SRB_STATUS_BUSY; // this cause queue freeze
6220 if(statusByte
& IDE_STATUS_ERROR
) {
6221 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
6223 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
6224 // Read the error reg. to clear it and fail this request.
6225 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6226 return MapError(deviceExtension
, Srb
);
6228 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
6231 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
6232 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
6233 if((!(statusByte
& IDE_STATUS_DSC
)) &&
6234 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6236 AtapiStallExecution(200);
6237 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6238 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6239 return SRB_STATUS_PENDING
;
6242 if(IS_RDP(Srb
->Cdb
[0])) {
6244 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6248 if(statusByte
& IDE_STATUS_DRQ
) {
6250 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6252 // Try to drain the data that one preliminary device thinks that it has
6253 // to transfer. Hopefully this random assertion of DRQ will not be present
6254 // in production devices.
6255 for (i
= 0; i
< 0x10000; i
++) {
6256 GetStatus(chan
, statusByte
);
6257 if(statusByte
& IDE_STATUS_DRQ
) {
6258 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6266 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6268 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6270 AtapiSoftReset(chan
, ldev
& 1);
6272 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6273 // Re-initialize Atapi device.
6274 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), ldev
& 1, TRUE
);
6276 IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb),
6277 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
6279 // Inform the port driver that the bus has been reset.
6280 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6281 // Clean up device extension fields that AtapiStartIo won't.
6282 chan
->ExpectingInterrupt
= FALSE
;
6284 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6287 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6289 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
6290 return SRB_STATUS_BUS_RESET;
6293 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
6297 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
6298 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6299 return SRB_STATUS_SELECTION_TIMEOUT
;
6303 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6304 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6305 Srb
->Cdb
[1] &= ~0xE0;
6306 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6307 // Torisan changer. TUR's are overloaded to be platter switches.
6308 Srb
->Cdb
[7] = Srb
->Lun
;
6315 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6317 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6320 statusByte
= WaitOnBusy(chan
);
6321 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6324 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6325 use_dma
? ATA_F_DMA
: 0);
6327 // Write transfer byte count to registers.
6328 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6329 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6331 if (Srb
->DataTransferLength
>= 0x10000) {
6332 byteCountLow
= byteCountHigh
= 0xFF;
6335 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6336 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6338 if (flags
& DFLAGS_INT_DRQ
) {
6340 // This device interrupts when ready to receive the packet.
6342 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6345 chan
->ExpectingInterrupt
= TRUE
;
6346 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6347 InterlockedExchange(&(chan
->CheckIntr
),
6350 // Write ATAPI packet command.
6351 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6353 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
6354 return SRB_STATUS_PENDING
;
6358 // This device quickly sets DRQ when ready to receive the packet.
6360 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6363 chan
->ExpectingInterrupt
= TRUE
;
6364 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6365 InterlockedExchange(&(chan
->CheckIntr
),
6368 //AtapiDisableInterrupts(deviceExtension, lChannel);
6370 // Write ATAPI packet command.
6371 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6375 statusByte
= WaitForDrq(chan
);
6377 // Need to read status register and clear interrupt (if any)
6378 GetBaseStatus(chan
, statusByte
);
6380 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6382 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6383 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6384 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6385 return SRB_STATUS_ERROR
;
6389 GetStatus(chan
, statusByte
);
6390 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6392 // Send CDB to device.
6393 statusByte
= WaitOnBaseBusy(chan
);
6395 // Indicate expecting an interrupt and wait for it.
6396 chan
->ExpectingInterrupt
= TRUE
;
6397 InterlockedExchange(&(chan
->CheckIntr
),
6399 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6401 GetBaseStatus(chan
, statusByte
);
6403 //AtapiEnableInterrupts(deviceExtension, lChannel);
6410 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6411 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
);
6414 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6416 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6417 return SRB_STATUS_PENDING
;
6419 } // end AtapiSendCommand()
6426 Routine Description:
6427 Program ATA registers for IDE disk transfer.
6430 HwDeviceExtension - ATAPI driver storage.
6431 Srb - System request block.
6434 SRB status (pending if all goes well).
6439 ULONG check_point
= 0;
6440 #define SetCheckPoint(cp) { check_point = (cp) ; }
6442 #define SetCheckPoint(cp)
6448 IN PVOID HwDeviceExtension
,
6449 IN PSCSI_REQUEST_BLOCK Srb
,
6454 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6457 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6465 UCHAR statusByte
,errorByte
;
6468 PMODE_PARAMETER_HEADER modeData
;
6472 //ULONG __ebp__ = 0;
6474 SetCheckPoint(0x20);
6475 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6480 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6481 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6482 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6483 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6484 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6486 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6487 Srb->SrbExtension));
6488 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6491 SetCheckPoint(0x30);
6492 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6494 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6496 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6498 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6500 lChannel
= GET_CHANNEL(Srb
);
6501 chan
= &(deviceExtension
->chan
[lChannel
]);
6502 ldev
= GET_LDEV(Srb
);
6504 SetCheckPoint(0x40);
6505 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6506 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6508 if(CmdAction
== CMD_ACTION_PREPARE
) {
6509 switch (Srb
->Cdb
[0]) {
6511 case SCSIOP_INQUIRY
: // now it requires device access
6513 case SCSIOP_READ_CAPACITY
:
6516 case SCSIOP_REQUEST_SENSE
:
6518 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6523 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6524 return SRB_STATUS_BUSY
;
6528 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6529 switch (Srb
->Cdb
[0]) {
6530 case SCSIOP_INQUIRY
:
6532 KdPrint2((PRINT_PREFIX
6533 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6534 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6535 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6536 // which support up to two devices.
6537 if ((Srb
->Lun
!= 0) ||
6538 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6539 (Srb
->TargetId
> 2) /*||
6540 (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) {
6542 KdPrint2((PRINT_PREFIX
6543 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6544 // Indicate no device found at this address.
6545 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6550 KdPrint2((PRINT_PREFIX
6551 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6552 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6553 PIDENTIFY_DATA2 identifyData
= &(deviceExtension
->lun
[ldev
].IdentifyData
);
6555 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6557 if(!CheckDevice(HwDeviceExtension
, lChannel
, ldev
& 1, FALSE
)) {
6558 KdPrint2((PRINT_PREFIX
6559 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6560 // Indicate no device found at this address.
6562 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6566 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, ldev
& 1)) {
6567 KdPrint2((PRINT_PREFIX
6568 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6569 // Indicate no device found at this address.
6570 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
6572 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6577 // Zero INQUIRY data structure.
6578 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6580 // Standard IDE interface only supports disks.
6581 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6583 // Set the removable bit, if applicable.
6584 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6585 KdPrint2((PRINT_PREFIX
6586 "RemovableMedia\n"));
6587 inquiryData
->RemovableMedia
= 1;
6589 // Set the Relative Addressing (LBA) bit, if applicable.
6590 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6591 inquiryData
->RelativeAddressing
= 1;
6592 KdPrint2((PRINT_PREFIX
6593 "RelativeAddressing\n"));
6595 // Set the CommandQueue bit
6596 inquiryData
->CommandQueue
= 1;
6598 // Fill in vendor identification fields.
6599 for (i
= 0; i
< 24; i
+= 2) {
6600 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6603 // Initialize unused portion of product id.
6604 for (i = 0; i < 4; i++) {
6605 inquiryData->ProductId[12+i] = ' ';
6608 // Move firmware revision from IDENTIFY data to
6609 // product revision in INQUIRY data.
6610 for (i
= 0; i
< 4; i
+= 2) {
6611 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6614 status
= SRB_STATUS_SUCCESS
;
6619 case SCSIOP_MODE_SENSE
:
6621 KdPrint2((PRINT_PREFIX
6622 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6623 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6624 // This is used to determine if the media is write-protected.
6625 // Since IDE does not support mode sense then we will modify just the portion we need
6626 // so the higher level driver can determine if media is protected.
6627 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6629 SelectDrive(chan
, ldev
& 0x1);
6630 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6631 statusByte
= WaitOnBusy(chan
);
6633 if (!(statusByte
& IDE_STATUS_ERROR
)){
6635 // no error occured return success, media is not protected
6636 chan
->ExpectingInterrupt
= FALSE
;
6637 InterlockedExchange(&(chan
->CheckIntr
),
6639 status
= SRB_STATUS_SUCCESS
;
6643 // error occured, handle it locally, clear interrupt
6644 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6646 GetBaseStatus(chan
, statusByte
);
6647 chan
->ExpectingInterrupt
= FALSE
;
6648 InterlockedExchange(&(chan
->CheckIntr
),
6650 status
= SRB_STATUS_SUCCESS
;
6652 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6654 //media is write-protected, set bit in mode sense buffer
6655 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6657 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6658 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6661 status
= SRB_STATUS_SUCCESS
;
6663 status
= SRB_STATUS_INVALID_REQUEST
;
6667 case SCSIOP_TEST_UNIT_READY
:
6669 KdPrint2((PRINT_PREFIX
6670 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6671 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6672 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6674 // Select device 0 or 1.
6675 SelectDrive(chan
, ldev
& 0x1);
6676 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6678 // Wait for busy. If media has not changed, return success
6679 statusByte
= WaitOnBusy(chan
);
6681 if (!(statusByte
& IDE_STATUS_ERROR
)){
6682 chan
->ExpectingInterrupt
= FALSE
;
6683 InterlockedExchange(&(chan
->CheckIntr
),
6685 status
= SRB_STATUS_SUCCESS
;
6687 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6688 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6690 // Special case: If current media is write-protected,
6691 // the 0xDA command will always fail since the write-protect bit
6692 // is sticky,so we can ignore this error
6693 GetBaseStatus(chan
, statusByte
);
6694 chan
->ExpectingInterrupt
= FALSE
;
6695 InterlockedExchange(&(chan
->CheckIntr
),
6697 status
= SRB_STATUS_SUCCESS
;
6701 // Request sense buffer to be build
6702 chan
->ExpectingInterrupt
= TRUE
;
6703 InterlockedExchange(&(chan
->CheckIntr
),
6705 status
= SRB_STATUS_PENDING
;
6709 status
= SRB_STATUS_SUCCESS
;
6714 case SCSIOP_READ_CAPACITY
:
6716 KdPrint2((PRINT_PREFIX
6717 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
6718 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6719 // Claim 512 byte blocks (big-endian).
6720 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
6722 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
6724 // Calculate last sector.
6725 if(!(i
= (ULONG
)deviceExtension
->lun
[ldev
].NumOfSectors
)) {
6726 i
= deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
*
6727 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
*
6728 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
;
6732 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
6733 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
6734 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
6736 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
6738 KdPrint2((PRINT_PREFIX
6739 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
6741 deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
,
6742 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
,
6743 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
));
6746 status
= SRB_STATUS_SUCCESS
;
6751 KdPrint2((PRINT_PREFIX
6752 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
6753 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6754 status
= IdeVerify(HwDeviceExtension
,Srb
);
6761 KdPrint2((PRINT_PREFIX
6762 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
6763 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
6764 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6765 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6766 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6767 status
= IdeReadWrite(HwDeviceExtension
,
6771 case SCSIOP_START_STOP_UNIT
:
6773 KdPrint2((PRINT_PREFIX
6774 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6775 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6776 //Determine what type of operation we should perform
6777 cdb
= (PCDB
)Srb
->Cdb
;
6779 if (cdb
->START_STOP
.LoadEject
== 1){
6781 statusByte
= WaitOnBaseBusy(chan
);
6783 // first select device 0 or 1.
6784 SelectDrive(chan
, ldev
& 0x1);
6785 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
6787 status
= SRB_STATUS_SUCCESS
;
6790 case SCSIOP_MEDIUM_REMOVAL
:
6792 cdb
= (PCDB
)Srb
->Cdb
;
6794 statusByte
= WaitOnBaseBusy(chan
);
6796 SelectDrive(chan
, ldev
& 0x1);
6797 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
6798 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
6800 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
6802 status
= SRB_STATUS_SUCCESS
;
6805 // Note: I don't implement this, because NTFS driver too often issues this command
6806 // It causes awful performance degrade. However, if somebody wants, I will implement
6807 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
6810 case SCSIOP_FLUSH_BUFFER
:
6811 case SCSIOP_SYNCHRONIZE_CACHE
:
6813 SelectDrive(chan
, ldev
& 0x1);
6814 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
6815 status
= SRB_STATUS_SUCCESS
;
6816 // status = SRB_STATUS_PENDING;
6817 statusByte
= WaitOnBusy(chan
);
6821 case SCSIOP_REQUEST_SENSE
:
6822 // this function makes sense buffers to report the results
6823 // of the original GET_MEDIA_STATUS command
6825 KdPrint2((PRINT_PREFIX
6826 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6827 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6828 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6829 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
6832 status
= SRB_STATUS_INVALID_REQUEST
;
6836 case SCSIOP_ATA_PASSTHROUGH
:
6839 BOOLEAN use_dma
= FALSE
;
6842 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
6844 lChannel
= Srb
->TargetId
>> 1;
6846 regs
->bDriveHeadReg
&= 0x0f;
6847 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
6849 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
6851 KdPrint2((PRINT_PREFIX
6852 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6853 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6856 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6858 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
6859 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
6861 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6862 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
6863 (PUCHAR
)(Srb
->DataBuffer
),
6864 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
6870 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
6871 AtapiStallExecution(10);
6873 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6874 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6875 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6876 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6877 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6878 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6880 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
6881 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6882 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
6883 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6884 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
6885 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6886 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
6887 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6888 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
6889 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6891 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
6894 GetBaseStatus(chan
, statusByte
);
6895 if(statusByte
& IDE_STATUS_ERROR
) {
6896 goto passthrough_err
;
6898 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
6901 ScsiPortStallExecution(1); // wait for busy to be set
6903 if(regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) {
6904 to_lim
= Srb
->TimeOutValue
;
6906 if(Srb
->TimeOutValue
<= 2) {
6907 to_lim
= Srb
->TimeOutValue
*900;
6909 to_lim
= (Srb
->TimeOutValue
*999) - 500;
6912 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
6913 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
6914 GetBaseStatus(chan
, statusByte
);
6915 if(statusByte
& IDE_STATUS_ERROR
) {
6918 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6923 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
6925 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
6926 goto passthrough_err
;
6930 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
6932 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
6933 GetBaseStatus(chan
, statusByte
);
6935 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
6936 AtapiSuckPort2(chan
);
6938 if (Srb
->SenseInfoBuffer
) {
6940 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
6942 senseBuffer
->ErrorCode
= 0x70;
6943 senseBuffer
->Valid
= 1;
6944 senseBuffer
->AdditionalSenseLength
= 0xb;
6945 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
6946 senseBuffer
->AdditionalSenseCode
= 0;
6947 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6949 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
6950 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
6952 status
= SRB_STATUS_ERROR
;
6956 if (statusByte
& IDE_STATUS_DRQ
) {
6957 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6959 (PUSHORT
) Srb
->DataBuffer
,
6960 Srb
->DataTransferLength
/ 2,
6962 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6964 (PUSHORT
) Srb
->DataBuffer
,
6965 Srb
->DataTransferLength
/ 2,
6970 status
= SRB_STATUS_SUCCESS
;
6973 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6975 } else { // read task register
6977 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
6979 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
6981 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6982 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6983 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6984 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6985 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6986 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6988 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6989 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6990 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6991 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6992 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6993 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6994 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6995 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6996 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6997 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6999 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
7000 status
= SRB_STATUS_SUCCESS
;
7007 KdPrint2((PRINT_PREFIX
7008 "IdeSendCommand: Unsupported command %#x\n",
7011 status
= SRB_STATUS_INVALID_REQUEST
;
7015 if(status
== SRB_STATUS_PENDING
) {
7016 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
7017 if(CmdAction
& CMD_ACTION_EXEC
) {
7018 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
7019 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
7022 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
7023 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7028 } // end IdeSendCommand()
7033 Routine Description:
7034 Enables disables media status notification
7037 HwDeviceExtension - ATAPI driver storage.
7044 IN PVOID HwDeviceExtension
,
7048 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7050 UCHAR lChannel
= ldev
>> 1;
7051 UCHAR statusByte
,errorByte
;
7053 chan
= &(deviceExtension
->chan
[lChannel
]);
7055 if (EnableMSN
== TRUE
){
7057 // If supported enable Media Status Notification support
7058 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
7061 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7062 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7063 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7065 if (statusByte
& IDE_STATUS_ERROR
) {
7066 // Read the error register.
7067 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7069 KdPrint2((PRINT_PREFIX
7070 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
7074 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
7075 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
7076 chan
->ReturningMediaStatus
= 0;
7081 } else { // end if EnableMSN == TRUE
7083 // disable if previously enabled
7084 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
7086 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7087 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7088 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7089 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
7096 } // end IdeMediaStatus()
7101 Routine Description:
7103 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
7104 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
7107 HwDeviceExtension - ATAPI driver storage.
7108 Srb - System request block.
7112 SRB status (ALWAYS SUCCESS).
7117 IdeBuildSenseBuffer(
7118 IN PVOID HwDeviceExtension
,
7119 IN PSCSI_REQUEST_BLOCK Srb
7122 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7124 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
7125 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
7129 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
7131 senseBuffer
->ErrorCode
= 0x70;
7132 senseBuffer
->Valid
= 1;
7133 senseBuffer
->AdditionalSenseLength
= 0xb;
7134 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7135 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7136 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7137 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
7139 senseBuffer
->ErrorCode
= 0x70;
7140 senseBuffer
->Valid
= 1;
7141 senseBuffer
->AdditionalSenseLength
= 0xb;
7142 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7143 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7144 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7145 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
7147 senseBuffer
->ErrorCode
= 0x70;
7148 senseBuffer
->Valid
= 1;
7149 senseBuffer
->AdditionalSenseLength
= 0xb;
7150 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
7151 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
7152 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7153 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
7155 senseBuffer
->ErrorCode
= 0x70;
7156 senseBuffer
->Valid
= 1;
7157 senseBuffer
->AdditionalSenseLength
= 0xb;
7158 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
7159 senseBuffer
->AdditionalSenseCode
= 0;
7160 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7162 return SRB_STATUS_SUCCESS
;
7164 return SRB_STATUS_ERROR
;
7166 }// End of IdeBuildSenseBuffer
7170 UniataUserDeviceReset(
7171 PHW_DEVICE_EXTENSION deviceExtension
,
7172 PHW_LU_EXTENSION LunExt
,
7177 AtapiDisableInterrupts(deviceExtension
, PathId
);
7178 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
7179 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
7180 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), ldev
& 1);
7182 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
7183 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
7184 deviceExtension
->chan
[PathId
].lun
[0]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7185 deviceExtension
->chan
[PathId
].lun
[1]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7187 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7188 AtapiEnableInterrupts(deviceExtension
, PathId
);
7190 } // end UniataUserDeviceReset()
7195 PHW_DEVICE_EXTENSION deviceExtension
,
7200 BOOLEAN PostReq
= FALSE
;
7202 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
7203 if(chan
->queue_depth
> 0) {
7206 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
7207 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
7208 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
7210 status
= SRB_STATUS_BUSY
;
7219 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
7223 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
7226 } // end UniataNeedQueueing()
7230 Routine Description:
7232 This routine is called from the SCSI port driver synchronized
7233 with the kernel to start an IO request.
7237 HwDeviceExtension - HBA miniport driver's adapter data storage
7238 Srb - IO request packet
7248 IN PVOID HwDeviceExtension
,
7249 IN PSCSI_REQUEST_BLOCK Srb
7252 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
7253 } // end AtapiStartIo()
7258 IN PVOID HwDeviceExtension
,
7259 IN PSCSI_REQUEST_BLOCK Srb
,
7263 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7272 PSCSI_REQUEST_BLOCK tmpSrb
;
7273 BOOLEAN PostReq
= FALSE
;
7275 BOOLEAN commPort
= FALSE
;
7277 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
7278 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7279 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7280 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7282 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7284 /* KeBugCheckEx(0xc000000e,
7285 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7287 TopLevel, 0x80000001);
7289 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7290 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7291 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7296 lChannel
= GET_CHANNEL(Srb
);
7297 chan
= &(deviceExtension
->chan
[lChannel
]);
7298 ldev
= GET_LDEV(Srb
);
7300 //ASSERT(deviceExtension);
7303 KdPrint2((PRINT_PREFIX
7304 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7305 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7306 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7308 if(lChannel
== deviceExtension
->NumberChannels
&&
7309 !Srb
->Lun
&& !Srb
->TargetId
&&
7310 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
7311 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
7313 KdPrint2((PRINT_PREFIX
7314 "AtapiStartIo: Communication port\n"));
7315 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
7317 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7319 KdPrint2((PRINT_PREFIX
7321 // Zero INQUIRY data structure.
7322 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7324 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
7326 // Fill in vendor identification fields.
7327 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
7329 status
= SRB_STATUS_SUCCESS
;
7333 /* Pass IOCTL request down */
7335 if(GET_CDEV(Srb
) >= 2 ||
7336 ldev
>= deviceExtension
->NumberChannels
*2 ||
7337 lChannel
>= deviceExtension
->NumberChannels
||
7340 if(lChannel
>= deviceExtension
->NumberChannels
) {
7345 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7346 KdPrint3((PRINT_PREFIX
7347 "AtapiStartIo: SRB rejected\n"));
7348 // Indicate no device found at this address.
7349 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7350 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7355 atapiDev
= (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7358 if(!commPort
&& !(chan
->lun
[ldev
& 1])) {
7360 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7363 deviceExtension
->NumberChannels
);
7364 PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n",
7365 lChannel
, ldev
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7366 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7367 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7371 for(i=0; i<1000; i++) {
7372 AtapiStallExecution(3*1000);
7379 // Determine which function.
7380 switch (Srb
->Function
) {
7382 case SRB_FUNCTION_EXECUTE_SCSI
:
7384 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7385 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7386 // let passthrough go
7388 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7392 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7393 KdPrint2((PRINT_PREFIX
7394 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7395 // Indicate no device found at this address.
7396 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7397 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7404 if(Srb->DataTransferLength) {
7406 a = ((PUCHAR)(Srb->DataBuffer))[0];
7409 } __except(EXCEPTION_EXECUTE_HANDLER) {
7410 KdPrint3((PRINT_PREFIX
7411 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7412 // Indicate no device found at this address.
7413 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7414 status = SRB_STATUS_ERROR;
7415 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7420 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7424 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
7426 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7427 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
7429 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7431 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7432 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7434 /*KeBugCheckEx(0xc000000e,
7435 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7437 status, 0x80000001);*/
7438 if(status
== SRB_STATUS_BUSY
)
7439 status
= SRB_STATUS_PENDING
;
7440 // Insert requests AFTER they have been initialized on
7441 // CMD_ACTION_PREPARE stage
7442 // we should not check TopLevel here (it is always TRUE)
7443 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7444 UniataQueueRequest(chan
, Srb
);
7446 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7449 // Send command to device.
7450 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7452 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7453 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7454 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7455 //ASSERT(!AtaReq->Flags);
7456 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7457 UniataQueueRequest(chan
, Srb
);
7458 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7459 //ASSERT(!AtaReq->Flags);
7460 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7461 //ASSERT(!AtaReq->Flags);
7465 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7466 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7467 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, ldev
& 1)) {
7468 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, ldev
& 1, TRUE
)) {
7472 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7476 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7485 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7486 KdPrint3((PRINT_PREFIX
"Try ATAPI send\n"));
7487 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7489 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7494 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7501 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7503 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7505 /* KeBugCheckEx(0xc000000e,
7506 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7508 status, 0x80000002);*/
7516 case SRB_FUNCTION_ABORT_COMMAND
:
7518 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7520 // Verify that SRB to abort is still outstanding.
7521 if((tmpSrb
!= Srb
->NextSrb
) ||
7522 !chan
->queue_depth
) {
7524 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7526 // Complete abort SRB.
7527 status
= SRB_STATUS_ABORT_FAILED
;
7531 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7532 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7533 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7534 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7535 // Log reset failure.
7536 KdPrint3((PRINT_PREFIX
7537 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7538 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7540 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7541 status
= SRB_STATUS_ERROR
;
7544 status
= SRB_STATUS_SUCCESS
;
7547 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7548 if (tmpSrb
->SenseInfoBuffer
&&
7549 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7551 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7553 senseBuffer
->ErrorCode
= 0;
7554 senseBuffer
->Valid
= 1;
7555 senseBuffer
->AdditionalSenseLength
= 0xb;
7556 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7557 senseBuffer
->AdditionalSenseCode
= 0;
7558 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7560 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7562 AtapiDmaDBSync(chan
, tmpSrb
);
7563 UniataRemoveRequest(chan
, tmpSrb
);
7564 // Indicate command complete.
7565 ScsiPortNotification(RequestComplete
,
7568 status
= SRB_STATUS_SUCCESS
;
7572 // Abort function indicates that a request timed out.
7573 // Call reset routine. Card will only be reset if
7574 // status indicates something is wrong.
7575 // Fall through to reset code.
7577 case SRB_FUNCTION_RESET_DEVICE
:
7578 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7580 // Reset single device.
7581 // For now we support only Lun=0
7583 // Note: reset is immediate command, it cannot be queued since it is usually used to
7584 // revert not- responding device to operational state
7585 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7586 UniataUserDeviceReset(deviceExtension
, &(deviceExtension
->lun
[ldev
]), lChannel
, ldev
);
7587 status
= SRB_STATUS_SUCCESS
;
7590 case SRB_FUNCTION_RESET_BUS
:
7592 // Reset Atapi and SCSI bus.
7594 // Note: reset is immediate command, it cannot be queued since it is usually used to
7595 // revert not- responding device to operational state
7596 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7597 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7598 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7599 // Log reset failure.
7600 KdPrint3((PRINT_PREFIX
7601 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7602 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7604 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7605 status
= SRB_STATUS_ERROR
;
7608 status
= SRB_STATUS_SUCCESS
;
7613 case SRB_FUNCTION_SHUTDOWN
:
7615 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7616 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7617 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7620 // FLUSH ATAPI device - do nothing
7621 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7623 // FLUSH IDE/ATA device
7624 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7625 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7626 status
= AtaCommand(deviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
7627 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7628 // If supported & allowed, reset write cacheing
7629 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7631 // Disable write cache
7632 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7633 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7634 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7635 // Check for errors.
7636 if (status
& IDE_STATUS_ERROR
) {
7637 KdPrint2((PRINT_PREFIX
7638 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7641 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7643 // Re-enable write cache
7644 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7645 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7646 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7647 // Check for errors.
7648 if (status
& IDE_STATUS_ERROR
) {
7649 KdPrint2((PRINT_PREFIX
7650 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7652 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7654 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7658 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7660 status
= SRB_STATUS_SUCCESS
;
7664 case SRB_FUNCTION_FLUSH
:
7666 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7667 status
= SRB_STATUS_SUCCESS
;
7670 /* case SRB_FUNCTION_SHUTDOWN:
7671 case SRB_FUNCTION_FLUSH:
7673 // Flush device's cache.
7674 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7676 if (chan->CurrentSrb) {
7678 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7679 Srb->SrbStatus = SRB_STATUS_BUSY;
7680 ScsiPortNotification(RequestComplete,
7686 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
7687 status = SRB_STATUS_SUCCESS;
7689 status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb),
7690 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
7691 if (status & IDE_STATUS_DRQ) {
7692 status = SRB_STATUS_SUCCESS;
7694 status = SRB_STATUS_SELECTION_TIMEOUT;
7699 case SRB_FUNCTION_IO_CONTROL
: {
7703 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
7705 len
= Srb
->DataTransferLength
;
7707 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
7709 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
7710 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
7712 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7715 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
7717 // Version and revision per SMART 1.03
7719 versionParameters
->bVersion
= 1;
7720 versionParameters
->bRevision
= 1;
7721 versionParameters
->bReserved
= 0;
7723 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
7724 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
7726 // This is done because of how the IOCTL_SCSI_MINIPORT
7727 // determines 'targetid's'. Disk.sys places the real target id value
7728 // in the DeviceMap field. Once we do some parameter checking, the value passed
7729 // back to the application will be determined.
7731 deviceNumber
= versionParameters
->bIDEDeviceMap
;
7734 KdPrint2((PRINT_PREFIX
7735 "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
7736 // Indicate no device found at this address.
7737 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7738 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7742 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
7745 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7749 // NOTE: This will only set the bit
7750 // corresponding to this drive's target id.
7751 // The bit mask is as follows:
7757 if (deviceExtension
->NumberChannels
== 1) {
7758 if (chan
->PrimaryAddress
) {
7759 deviceNumber
= 1 << ldev
;
7761 deviceNumber
= 4 << ldev
;
7764 deviceNumber
= 1 << ldev
;
7767 versionParameters
->bIDEDeviceMap
= deviceNumber
;
7769 status
= SRB_STATUS_SUCCESS
;
7773 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
7775 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7776 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7779 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
7780 // Extract the target.
7781 targetId
= cmdInParameters
.bDriveNumber
;
7782 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
7783 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
7784 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7785 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
7786 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7790 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
7792 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
7793 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
7794 status
= SRB_STATUS_INVALID_REQUEST
;
7800 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
7801 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
7802 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
7803 status
= SRB_STATUS_INVALID_REQUEST
;
7807 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
7808 // Zero the output buffer
7809 RtlZeroMemory(cmdOutParameters
, len
);
7810 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
7811 ((PUCHAR)cmdOutParameters)[i] = 0;
7814 // Build status block.
7815 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
7816 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
7817 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
7819 // Extract the identify data from the device extension.
7820 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
7821 cmdOutParameters
->cBufferSize
);
7823 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
7825 status
= SRB_STATUS_SUCCESS
;
7829 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
7830 cmdInParameters
.irDriveRegs
.bCommandReg
));
7831 status
= SRB_STATUS_INVALID_REQUEST
;
7837 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
7838 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
7839 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
7840 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
7841 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
7842 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
7843 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
7844 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
7847 KdPrint2((PRINT_PREFIX
7848 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
7849 // Indicate no device found at this address.
7850 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7851 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7855 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7857 if(PostReq
|| TopLevel
) {
7858 UniataQueueRequest(chan
, Srb
);
7859 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7860 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7865 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
7866 status
= SRB_STATUS_PENDING
;
7868 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7871 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
7876 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
7877 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
7878 status
= SRB_STATUS_INVALID_REQUEST
;
7883 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
7885 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
7886 ULONG ldev
= GET_LDEV2(AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
, 0);
7887 PHW_LU_EXTENSION LunExt
;
7890 //chan = &(deviceExtension->chan[lChannel]);
7892 if(AtaCtl
->addr
.Lun
||
7893 ldev
>= deviceExtension
->NumberChannels
*2 ||
7894 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
7901 LunExt
= &(deviceExtension
->lun
[ldev
]);
7902 lChannel
= AtaCtl
->addr
.PathId
;
7903 chan
= &(deviceExtension
->chan
[lChannel
]);
7906 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl
->hdr
.ControlCode
, ldev
));
7908 /* check for valid LUN */
7909 switch (AtaCtl
->hdr
.ControlCode
) {
7910 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7911 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
7913 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
7914 AtaCtl
->addr
.TargetId
!= 0xff ||
7915 AtaCtl
->addr
.Lun
!= 0
7917 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
7918 ldev
< deviceExtension
->NumberChannels
*2) { // AtaCtl->addr.TargetId != 0xff
7919 LunExt
= &(deviceExtension
->lun
[ldev
]);
7922 goto handle_bad_ldev
;
7925 // this would be BUS reset
7926 lChannel
= AtaCtl
->addr
.PathId
;
7927 chan
= &(deviceExtension
->chan
[lChannel
]);
7929 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
7930 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7931 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
7932 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7933 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
7936 KdPrint2((PRINT_PREFIX
7937 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
7938 // Indicate no device found at this address.
7943 /* check if queueing is necessary */
7944 switch (AtaCtl
->hdr
.ControlCode
) {
7945 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7946 if(!LunExt
->nBadBlocks
) {
7949 goto uata_ctl_queue
;
7950 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7951 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
7954 goto uata_ctl_queue
;
7955 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7956 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
7958 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
7959 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7961 if(PostReq
|| TopLevel
) {
7962 UniataQueueRequest(chan
, Srb
);
7963 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7964 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7967 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
7968 status
= SRB_STATUS_PENDING
;
7970 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7973 } // end switch (AtaCtl->hdr.ControlCode)
7975 /* process request */
7976 switch (AtaCtl
->hdr
.ControlCode
) {
7977 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7979 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
7981 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
7982 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
7983 if(AtaCtl
->addr
.TargetId
!= 0xff) {
7984 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_HIDDEN
;
7989 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7990 AtapiStallExecution(1000 * 1000);
7993 FindDevices(HwDeviceExtension
,
7994 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
7995 ? UNIATA_FIND_DEV_UNHIDE
: 0,
7996 AtaCtl
->addr
.PathId
);
7997 status
= SRB_STATUS_SUCCESS
;
8001 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
8003 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
8005 deviceExtension
->lun
[ldev
].DeviceFlags
= 0;
8006 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
8007 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
8008 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_HIDDEN
;
8011 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
8012 AtapiStallExecution(1000 * 1000);
8015 status
= SRB_STATUS_SUCCESS
;
8018 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
8020 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
8022 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
8023 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
8025 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
8026 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
8027 if(LunExt
->LimitedTransferMode
>
8028 LunExt
->OrigTransferMode
) {
8029 // check for incorrect value
8030 LunExt
->LimitedTransferMode
=
8031 LunExt
->OrigTransferMode
;
8034 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
8036 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8037 if(AtaCtl
->SetMode
.ApplyImmediately
) {
8038 AtapiDmaInit__(deviceExtension
, ldev
);
8040 /* deviceExtension->lun[ldev].TransferMode =
8041 deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
8042 status
= SRB_STATUS_SUCCESS
;
8045 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
8047 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
8049 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
8050 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
8051 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
8053 status
= SRB_STATUS_SUCCESS
;
8056 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
8058 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
8060 AtaCtl
->AdapterInfo
.HeaderLength
= offsetof(ADAPTERINFO
, Chan
);
8062 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
8063 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
8064 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
8065 status
= SRB_STATUS_DATA_OVERRUN
;
8069 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
8070 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
8071 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
8072 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
8073 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
8074 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
8075 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
8076 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
8077 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
8078 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
8079 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
8080 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
8081 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
8082 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
8083 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
8084 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
8085 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
8086 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
8087 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
8088 if(deviceExtension
->FullDevName
) {
8089 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
8091 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
8093 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
8095 status
= SRB_STATUS_SUCCESS
;
8098 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
8100 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
8102 ForgetBadBlocks(LunExt
);
8104 status
= SRB_STATUS_SUCCESS
;
8107 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
8109 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
8114 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
, ldev
);
8117 status
= SRB_STATUS_SUCCESS
;
8121 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
8122 AtaCtl
->hdr
.ControlCode
));
8123 status
= SRB_STATUS_INVALID_REQUEST
;
8128 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
8129 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
8130 "SCSIDISK", "-UNIATA-"));
8132 status
= SRB_STATUS_INVALID_REQUEST
;
8137 } // end SRB_FUNCTION_IO_CONTROL
8140 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
8141 // Indicate unsupported command.
8142 status
= SRB_STATUS_INVALID_REQUEST
;
8150 PathId
= Srb
->PathId
;
8151 TargetId
= Srb
->TargetId
;
8154 if (status
!= SRB_STATUS_PENDING
) {
8156 KdPrint2((PRINT_PREFIX
8157 "AtapiStartIo: Srb %#x complete with status %#x\n",
8161 // Set status in SRB.
8162 Srb
->SrbStatus
= (UCHAR
)status
;
8164 AtapiDmaDBSync(chan
, Srb
);
8165 UniataRemoveRequest(chan
, Srb
);
8166 // Indicate command complete.
8167 ScsiPortNotification(RequestComplete
,
8171 // Remove current Srb & get next one
8172 if((Srb
= UniataGetCurRequest(chan
))) {
8173 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8174 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
8175 // current request is under precessing, thus
8176 // we should do nothing here
8184 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
8186 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
8188 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
8189 // Indicate ready for next request.
8190 ScsiPortNotification(NextRequest
,
8194 ScsiPortNotification(NextLuRequest
,
8202 } // end AtapiStartIo__()
8207 UniataInitAtaCommands()
8213 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
8215 for(i
=0; i
<256; i
++) {
8220 KdPrint2((PRINT_PREFIX
"cmd %2.2x: ", command
));
8223 case IDE_COMMAND_READ_DMA48
:
8224 case IDE_COMMAND_READ_DMA_Q48
:
8225 case IDE_COMMAND_READ_STREAM_DMA48
:
8226 case IDE_COMMAND_READ_STREAM48
:
8227 case IDE_COMMAND_WRITE_DMA48
:
8228 case IDE_COMMAND_WRITE_DMA_Q48
:
8229 case IDE_COMMAND_READ_DMA_Q
:
8230 case IDE_COMMAND_READ_DMA
:
8231 case IDE_COMMAND_WRITE_DMA
:
8232 case IDE_COMMAND_WRITE_DMA_Q
:
8233 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8234 case IDE_COMMAND_WRITE_STREAM48
:
8235 case IDE_COMMAND_WRITE_FUA_DMA48
:
8236 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8237 case IDE_COMMAND_READ_LOG_DMA48
:
8238 case IDE_COMMAND_WRITE_LOG_DMA48
:
8239 case IDE_COMMAND_TRUSTED_RCV_DMA
:
8240 case IDE_COMMAND_TRUSTED_SEND_DMA
:
8241 KdPrint2((PRINT_PREFIX
"DMA "));
8242 flags
|= ATA_CMD_FLAG_DMA
;
8246 case IDE_COMMAND_READ48
:
8247 case IDE_COMMAND_READ_DMA48
:
8248 case IDE_COMMAND_READ_DMA_Q48
:
8249 case IDE_COMMAND_READ_MUL48
:
8250 case IDE_COMMAND_READ_STREAM_DMA48
:
8251 case IDE_COMMAND_READ_STREAM48
:
8252 case IDE_COMMAND_WRITE48
:
8253 case IDE_COMMAND_WRITE_DMA48
:
8254 case IDE_COMMAND_WRITE_DMA_Q48
:
8255 case IDE_COMMAND_WRITE_MUL48
:
8256 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8257 case IDE_COMMAND_WRITE_STREAM48
:
8258 case IDE_COMMAND_WRITE_FUA_DMA48
:
8259 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8260 case IDE_COMMAND_WRITE_MUL_FUA48
:
8261 case IDE_COMMAND_FLUSH_CACHE48
:
8262 case IDE_COMMAND_VERIFY48
:
8264 KdPrint2((PRINT_PREFIX
"48 "));
8265 flags
|= ATA_CMD_FLAG_48
;
8268 case IDE_COMMAND_READ
:
8269 case IDE_COMMAND_READ_MULTIPLE
:
8270 case IDE_COMMAND_READ_DMA
:
8271 case IDE_COMMAND_READ_DMA_Q
:
8272 case IDE_COMMAND_WRITE
:
8273 case IDE_COMMAND_WRITE_MULTIPLE
:
8274 case IDE_COMMAND_WRITE_DMA
:
8275 case IDE_COMMAND_WRITE_DMA_Q
:
8276 case IDE_COMMAND_FLUSH_CACHE
:
8277 case IDE_COMMAND_VERIFY
:
8279 KdPrint2((PRINT_PREFIX
"LBA "));
8280 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
8283 flags
|= ATA_CMD_FLAG_48supp
;
8286 case IDE_COMMAND_READ
:
8287 command
= IDE_COMMAND_READ48
; break;
8288 case IDE_COMMAND_READ_MULTIPLE
:
8289 command
= IDE_COMMAND_READ_MUL48
; break;
8290 case IDE_COMMAND_READ_DMA
:
8291 command
= IDE_COMMAND_READ_DMA48
; break;
8292 case IDE_COMMAND_READ_DMA_Q
:
8293 command
= IDE_COMMAND_READ_DMA_Q48
; break;
8294 case IDE_COMMAND_WRITE
:
8295 command
= IDE_COMMAND_WRITE48
; break;
8296 case IDE_COMMAND_WRITE_MULTIPLE
:
8297 command
= IDE_COMMAND_WRITE_MUL48
; break;
8298 case IDE_COMMAND_WRITE_DMA
:
8299 command
= IDE_COMMAND_WRITE_DMA48
; break;
8300 case IDE_COMMAND_WRITE_DMA_Q
:
8301 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
8302 case IDE_COMMAND_FLUSH_CACHE
:
8303 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
8304 // case IDE_COMMAND_READ_NATIVE_SIZE:
8305 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
8306 case IDE_COMMAND_SET_NATIVE_SIZE
:
8307 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
8308 case IDE_COMMAND_VERIFY
:
8309 command
= IDE_COMMAND_VERIFY48
; break;
8311 KdPrint2((PRINT_PREFIX
"!28->48 "));
8312 flags
&= ~ATA_CMD_FLAG_48supp
;
8315 KdPrint2((PRINT_PREFIX
"\t -> %2.2x (%2.2x)\n", command
, flags
));
8316 AtaCommands48
[i
] = command
;
8317 AtaCommandFlags
[i
] = flags
;
8319 } // end UniataInitAtaCommands()
8323 Routine Description:
8325 Installable driver initialization entry point for system.
8333 Status from ScsiPortInitialize()
8340 IN PVOID DriverObject
,
8344 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
8347 ULONG statusToReturn
, newStatus
;
8348 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
8349 BOOLEAN ReEnter
= FALSE
;
8352 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
8353 BOOLEAN PrimaryClaimed
= FALSE
;
8354 BOOLEAN SecondaryClaimed
= FALSE
;
8356 LARGE_INTEGER t0
, t1
;
8359 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
8360 a
= (WCHAR
)strlen(ver_string
);
8362 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
8364 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
8367 if(!SavedDriverObject
) {
8368 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8369 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8371 KeQuerySystemTime(&t0
);
8373 KeQuerySystemTime(&t1
);
8374 } while(t0
.QuadPart
== t1
.QuadPart
);
8378 KeQuerySystemTime(&t1
);
8380 } while(t0
.QuadPart
== t1
.QuadPart
);
8381 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8382 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8385 KdPrint(("UniATA Init: ReEnter\n"));
8389 // (re)read bad block list
8390 InitBadBlocks(NULL
);
8393 // init ATA command translation table
8394 UniataInitAtaCommands();
8395 // get registry path to settings
8396 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8397 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8398 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8399 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8400 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8401 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8404 if(WinVer_Id() >= WinVer_2k
) {
8405 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
8406 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
8407 WinVer_WDM_Model
= TRUE
;
8409 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
8410 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
8411 WinVer_WDM_Model
= TRUE
;
8415 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8416 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8418 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8421 statusToReturn
= 0xffffffff;
8423 // Zero out structure.
8424 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8426 // Set size of hwInitializationData.
8427 hwInitializationData
.comm
.HwInitializationDataSize
=
8428 sizeof(hwInitializationData
.comm
) +
8429 // sizeof(hwInitializationData.nt4) +
8430 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8431 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
8433 // Set entry points.
8434 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8435 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8436 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8437 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8439 // Specify size of extensions.
8440 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8441 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8442 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8444 // Indicate PIO device.
8445 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8446 // Set PnP-specific API
8447 if(WinVer_Id() > WinVer_NT
) {
8448 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
8449 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8450 KdPrint(("set AtapiAdapterControl() ptr\n"));
8451 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8454 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8457 UniataEnumBusMasterController(DriverObject
, Argument2
);
8460 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8461 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8462 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8463 for (i
=0; i
<BMListLen
; i
++) {
8465 if(!BMList
[i
].MasterDev
) {
8466 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8469 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8473 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8474 if(BMList
[i
].ChanInitOk
& 0x03) {
8475 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8477 newStatus
= STATUS_SUCCESS
;
8481 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8483 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8484 PrimaryClaimed
= TRUE
;
8485 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8486 SecondaryClaimed
= TRUE
;
8489 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8491 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
8493 for(c
=0; c
<2; c
++) {
8495 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8499 if(PrimaryClaimed
) {
8500 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8505 if(SecondaryClaimed
) {
8506 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8511 if((WinVer_Id() < WinVer_2k
)) {
8512 // do not even try if already claimed
8514 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8517 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8520 if(!WinVer_WDM_Model
) {
8521 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8523 // in WDM model things are different....
8524 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
8525 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
8527 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8528 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8530 if(!WinVer_WDM_Model
) {
8531 BMList
[i
].channel
= (UCHAR
)c
;
8534 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8535 newStatus
= ScsiPortInitialize(DriverObject
,
8537 &hwInitializationData
.comm
,
8538 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8539 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8540 if (newStatus
< statusToReturn
) {
8541 statusToReturn
= newStatus
;
8543 if (newStatus
== STATUS_SUCCESS
) {
8544 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8546 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8547 c = 1; // this will break our for()
8548 BMList[i].ChanInitOk |= 0x01 << c;
8553 if(WinVer_Id() >= WinVer_2k
) {
8554 // the following doesn't work under higher OSes
8555 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8558 if(BMList
[i
].ChanInitOk
& 0x03) {
8559 // under NT we receive status immediately, so
8560 // we can omit alternative init method id STATUS_SUCCESS returned
8561 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8564 // if (WinVer_Id() == WinVer_NT) and some error occured
8565 // try alternative init method
8568 if(WinVer_WDM_Model
) {
8569 hwInitializationData
.comm
.HwFindAdapter
= UniataFindFakeBusMasterController
;
8570 hwInitializationData
.comm
.NumberOfAccessRanges
= 5;
8571 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8573 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8574 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8575 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8576 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8578 //BMList[i].channel = 0/*(UCHAR)c*/;
8580 KdPrint2((PRINT_PREFIX
"Try init fake: %4.4s %4.4s \n",
8581 hwInitializationData
.comm
.VendorId
,
8582 hwInitializationData
.comm
.DeviceId
));
8583 newStatus
= ScsiPortInitialize(DriverObject
,
8585 &hwInitializationData
.comm
,
8587 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8591 if(BMList
[i
].ChanInitOk
& 0x03) {
8592 _PrintNtConsole(" OK\n");
8594 _PrintNtConsole(" failed\n");
8600 /* KeBugCheckEx(0xc000000e,
8601 (i << 16) | BMList[0].ChanInitOk,
8603 newStatus, statusToReturn);*/
8605 // Look for PCI IDE controller
8606 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8607 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8608 for (; i
<BMListLen
; i
++) {
8610 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8613 /* if(BMList[i].MasterDev)
8616 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8617 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
8618 BMList
[i
].busNumber
,
8619 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
8620 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
8623 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8624 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8625 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8627 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8628 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8629 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8630 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8632 BMList
[i
].channel
= 0/*(UCHAR)c*/;
8634 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
8635 hwInitializationData
.comm
.VendorId
,
8636 hwInitializationData
.comm
.DeviceId
));
8637 newStatus
= ScsiPortInitialize(DriverObject
,
8639 &hwInitializationData
.comm
,
8641 if (newStatus
< statusToReturn
)
8642 statusToReturn
= newStatus
;
8645 if(newStatus
== STATUS_SUCCESS
) {
8646 _PrintNtConsole(" OK\n");
8648 _PrintNtConsole(" failed\n");
8654 /* KeBugCheckEx(0xc000000e,
8657 newStatus, statusToReturn);*/
8661 hwInitializationData
.comm
.VendorId
= 0;
8662 hwInitializationData
.comm
.VendorIdLength
= 0;
8663 hwInitializationData
.comm
.DeviceId
= 0;
8664 hwInitializationData
.comm
.DeviceIdLength
= 0;
8666 // The adapter count is used by the find adapter routine to track how
8667 // which adapter addresses have been tested.
8669 // Indicate 2 access ranges and reset FindAdapter.
8670 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
8671 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
8673 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
8674 // Indicate ISA bustype.
8675 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8678 // Call initialization for ISA bustype.
8679 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
8680 newStatus
= ScsiPortInitialize(DriverObject
,
8682 &hwInitializationData
.comm
,
8684 if (newStatus
< statusToReturn
)
8685 statusToReturn
= newStatus
;
8687 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
8689 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
8690 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
8693 newStatus
= ScsiPortInitialize(DriverObject
,
8695 &hwInitializationData
.comm
,
8697 if (newStatus
< statusToReturn
)
8698 statusToReturn
= newStatus
;
8700 InDriverEntry
= FALSE
;
8702 KdPrint2((PRINT_PREFIX
"\n\nLeave ATAPI IDE MiniPort DriverEntry with status %#x\n", statusToReturn
));
8704 return statusToReturn
;
8706 } // end DriverEntry()
8711 BuildMechanismStatusSrb(
8712 IN PVOID HwDeviceExtension
,
8713 IN PSCSI_REQUEST_BLOCK Srb
8716 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8717 PSCSI_REQUEST_BLOCK srb
;
8719 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8721 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8723 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8725 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8726 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8727 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8728 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8730 // Set flags to disable synchronous negociation.
8731 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8733 // Set timeout to 4 seconds.
8734 srb
->TimeOutValue
= 4;
8737 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
8738 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8739 srb
->SrbExtension
= AtaReq
;
8741 // Set CDB operation code.
8742 cdb
= (PCDB
)srb
->Cdb
;
8743 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
8744 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8747 } // end BuildMechanismStatusSrb()
8749 #endif //UNIATA_CORE
8753 BuildRequestSenseSrb (
8754 IN PVOID HwDeviceExtension
,
8755 IN PSCSI_REQUEST_BLOCK Srb
8758 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8759 PSCSI_REQUEST_BLOCK srb
;
8761 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8763 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8765 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8767 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8768 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8769 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8770 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8772 // Set flags to disable synchronous negociation.
8773 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8775 // Set timeout to 2 seconds.
8776 srb
->TimeOutValue
= 4;
8779 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
8780 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
8781 srb
->SrbExtension
= AtaReq
;
8783 // Set CDB operation code.
8784 cdb
= (PCDB
)srb
->Cdb
;
8785 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
8786 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
8789 } // end BuildRequestSenseSrb()
8795 AtapiRegCheckDevLunValue(
8796 IN PVOID HwDeviceExtension
,
8797 IN PCWCH NamePrefix
,
8805 ULONG val
= Default
;
8807 val
= AtapiRegCheckParameterValue(
8808 HwDeviceExtension
, NamePrefix
, Name
, val
);
8810 if(chan
!= CHAN_NOT_SPECIFIED
) {
8811 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
8812 val
= AtapiRegCheckParameterValue(
8813 HwDeviceExtension
, namex
, Name
, val
);
8814 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
8815 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
8816 val
= AtapiRegCheckParameterValue(
8817 HwDeviceExtension
, namex
, Name
, val
);
8821 } // end AtapiRegCheckDevLunValue()
8834 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
8853 swprintf(Buffer
+j
, L
"%2.2x", a
);
8861 } // end EncodeVendorStr()
8865 AtapiRegCheckDevValue(
8866 IN PVOID HwDeviceExtension
,
8873 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8875 // WCHAR name1[11+4+5];
8876 // WCHAR name2[11+4+4+10];
8877 // WCHAR name3[11+4+4+5+20];
8878 // WCHAR name3[11+4+4+5+20+1];
8887 IN ULONG SlotNumber
;
8889 ULONG val
= Default
;
8891 KdPrint(( " Parameter %ws\n", Name
));
8893 if(deviceExtension
) {
8894 VendorID
= deviceExtension
->DevID
& 0xffff;
8895 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
8896 SlotNumber
= deviceExtension
->slotNumber
;
8900 SlotNumber
= 0xffffffff;
8903 val
= AtapiRegCheckDevLunValue(
8904 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
8906 if(deviceExtension
) {
8907 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
8909 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
8910 swprintf(namex
, L
"Parameters%s", namev
);
8911 val
= AtapiRegCheckDevLunValue(
8912 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8915 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
8916 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
8917 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
8919 swprintf(namex
, L
"Parameters%s", namev
);
8920 val
= AtapiRegCheckDevLunValue(
8921 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8923 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
8924 val
= AtapiRegCheckDevLunValue(
8925 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8927 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
8928 val
= AtapiRegCheckDevLunValue(
8929 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8931 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
8933 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
8934 swprintf(namex
, L
"Parameters%s", namev
);
8935 val
= AtapiRegCheckDevLunValue(
8936 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8938 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
8939 swprintf(namex
, L
"Parameters%s", namev
);
8940 val
= AtapiRegCheckDevLunValue(
8941 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8944 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
8946 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
8947 swprintf(namex
, L
"Parameters%s", namev
);
8948 val
= AtapiRegCheckDevLunValue(
8949 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8951 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
8952 swprintf(namex
, L
"Parameters%s", namev
);
8953 val
= AtapiRegCheckDevLunValue(
8954 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8959 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
8962 } // end AtapiRegCheckDevValue()
8965 The user must specify that Xxx is to run on the platform
8966 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
8967 Services\UniATA\Xxx:REG_DWORD:Zzz.
8969 The user can override the global setting to enable or disable Xxx on a
8970 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
8971 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
8973 If this registry value does not exist or contains the value zero then
8974 the timer to check for media change does not run.
8978 RegistryPath - pointer to the unicode string inside
8979 ...\CurrentControlSet\Services\UniATA
8980 DeviceNumber - The number of the HBA device object
8982 Returns: Registry Key value
8986 AtapiRegCheckParameterValue(
8987 IN PVOID HwDeviceExtension
,
8988 IN PCWSTR PathSuffix
,
8993 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
8995 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8997 LONG zero
= Default
;
8999 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
9002 LONG doRun
= Default
;
9004 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
9006 UNICODE_STRING paramPath
;
9008 // <SavedRegPath>\<PathSuffix> -> <Name>
9009 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
9010 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
9012 paramPath
.Length
= 0;
9013 paramPath
.MaximumLength
= RegistryPath
->Length
+
9014 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
9015 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
9016 if(!paramPath
.Buffer
) {
9017 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
9021 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
9022 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
9023 RtlAppendUnicodeToString(¶mPath
, L
"\\");
9024 RtlAppendUnicodeToString(¶mPath
, PathSuffix
);
9026 // Check for the Xxx value.
9027 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
9029 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
9030 parameters
[0].Name
= Name
;
9031 parameters
[0].EntryContext
= &doRun
;
9032 parameters
[0].DefaultType
= REG_DWORD
;
9033 parameters
[0].DefaultData
= &zero
;
9034 parameters
[0].DefaultLength
= sizeof(ULONG
);
9036 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
9037 paramPath
.Buffer
, parameters
, NULL
, NULL
);
9038 //KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
9040 ExFreePool(paramPath
.Buffer
);
9042 if(!NT_SUCCESS(status
)) {
9048 #undef ITEMS_TO_QUERY
9050 } // end AtapiRegCheckParameterValue()
9053 SCSI_ADAPTER_CONTROL_STATUS
9055 AtapiAdapterControl(
9056 IN PVOID HwDeviceExtension
,
9057 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
9061 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9062 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
9063 ULONG numberChannels
= deviceExtension
->NumberChannels
;
9067 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
9069 switch(ControlType
) {
9070 case ScsiQuerySupportedControlTypes
: {
9071 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
9072 TRUE
, // ScsiQuerySupportedControlTypes
9073 TRUE
, // ScsiStopAdapter
9074 TRUE
, // ScsiRestartAdapter
9075 FALSE
, // ScsiSetBootConfig
9076 FALSE
// ScsiSetRunningConfig
9079 ULONG lim
= ScsiAdapterControlMax
;
9082 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
9084 if(pControlTypeList
->MaxControlType
< lim
) {
9085 lim
= pControlTypeList
->MaxControlType
;
9088 for(i
= 0; i
< lim
; i
++) {
9089 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
9095 case ScsiStopAdapter
: {
9097 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
9098 // Shut down all interrupts on the adapter. They'll get re-enabled
9099 // by the initialization routines.
9100 for (c
= 0; c
< numberChannels
; c
++) {
9101 AtapiResetController(deviceExtension
, c
);
9102 AtapiDisableInterrupts(deviceExtension
, c
);
9104 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9105 // we must never get here for non-PCI
9106 status
= UniataDisconnectIntr2(HwDeviceExtension
);
9107 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
9111 case ScsiRestartAdapter
: {
9113 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
9114 // Enable all the interrupts on the adapter while port driver call
9115 // for power up an HBA that was shut down for power management
9117 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
9118 status
= UniataConnectIntr2(HwDeviceExtension
);
9119 for (c
= 0; c
< numberChannels
; c
++) {
9120 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
9121 FindDevices(HwDeviceExtension
, 0, c
);
9122 AtapiEnableInterrupts(deviceExtension
, c
);
9123 AtapiHwInitialize__(deviceExtension
, c
);
9125 if(deviceExtension
->Isr2DevObj
) {
9126 // we must never get here for non-PCI
9127 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9134 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
9135 return ScsiAdapterControlUnsuccessful
;
9139 return ScsiAdapterControlSuccess
;
9140 } // end AtapiAdapterControl()
9142 #endif //UNIATA_CORE
9161 UCHAR dbg_print_tmp_buff
[512];
9162 // UNICODE_STRING msgBuff;
9164 va_start(ap
, DebugMessage
);
9166 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
9168 dbg_print_tmp_buff
[511] = 0;
9170 HalDisplayString(dbg_print_tmp_buff
);
9174 } // end PrintNtConsole()