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(50);
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
;
5436 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5437 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
5438 if(LunExt
->DeviceExtension
) {
5439 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
5442 return startingSector
;
5444 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5445 LunExt
->IdentifyData
.NumberOfHeads
;
5447 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5451 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
5453 cylinder
= (USHORT
)(startingSector
/ tmp
);
5454 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5455 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5456 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
5457 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
5458 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
5462 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5463 } // end UniAtaCalculateLBARegs()
5467 UniAtaCalculateLBARegsBack(
5468 PHW_LU_EXTENSION LunExt
,
5472 ULONG drvSelect
,sectorNumber
;
5476 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5479 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5480 LunExt
->IdentifyData
.NumberOfHeads
;
5482 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5483 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5484 sectorNumber
= (UCHAR
)(lba
& 0xff);
5486 lba
= sectorNumber
-1 +
5487 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5491 } // end UniAtaCalculateLBARegsBack()
5496 Routine Description:
5498 This routine handles IDE read and writes.
5502 HwDeviceExtension - HBA miniport driver's adapter data storage
5503 Srb - IO request packet
5513 IN PVOID HwDeviceExtension
,
5514 IN PSCSI_REQUEST_BLOCK Srb
,
5518 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5519 UCHAR lChannel
= GET_CHANNEL(Srb
);
5520 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5521 PHW_LU_EXTENSION LunExt
;
5522 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5523 ULONG ldev
= GET_LDEV(Srb
);
5524 UCHAR DeviceNumber
= (UCHAR
)(ldev
& 1);
5525 ULONG startingSector
;
5527 ULONG wordCount
= 0;
5528 UCHAR statusByte
,statusByte2
;
5531 BOOLEAN use_dma
= FALSE
;
5533 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5534 LunExt
= &deviceExtension
->lun
[ldev
];
5536 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5537 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5539 if(LunExt
->opt_ReadOnly
&&
5540 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
5541 if(LunExt
->opt_ReadOnly
== 1) {
5542 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
5543 return SRB_STATUS_ERROR
;
5545 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
5546 return SRB_STATUS_SUCCESS
;
5550 // Set data buffer pointer and words left.
5551 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5553 if(AtaReq
->WordsTransfered
) {
5554 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
5555 startingSector
= (ULONG
)(UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
5556 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
5557 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
5559 AtaReq
->TransferLength
/2,
5560 AtaReq
->WordsTransfered
,
5563 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
5564 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5565 // Set up 1st block.
5566 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5567 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5568 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
5570 AtaReq
->TransferLength
/2,
5573 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5576 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
5578 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
5579 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5581 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5588 // assume best case here
5589 // we cannot reinit Dma until previous request is completed
5590 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5592 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5593 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5594 (PUCHAR
)(AtaReq
->DataBuffer
),
5595 AtaReq
->bcount
* DEV_BSIZE
)) {
5599 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5600 } else { // exec_only
5601 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5604 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5608 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5609 return SRB_STATUS_PENDING
;
5612 // if this is queued request, reinit DMA and check
5613 // if DMA mode is still available
5614 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5615 if (/*EnableDma &&*/
5616 (LunExt
->TransferMode
>= ATA_DMA
)) {
5619 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5623 // Check if write request.
5624 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5626 // Prepare read command.
5628 cmd
= IDE_COMMAND_READ_DMA
;
5630 if(LunExt
->MaximumBlockXfer
) {
5631 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5633 cmd
= IDE_COMMAND_READ
;
5637 // Prepare write command.
5639 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
5640 cmd
= IDE_COMMAND_WRITE_DMA
;
5642 if (LunExt
->MaximumBlockXfer
) {
5643 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5645 if (AtaReq
->WordsLeft
< wordCount
) {
5646 // Transfer only words requested.
5647 wordCount
= AtaReq
->WordsLeft
;
5649 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5652 wordCount
= DEV_BSIZE
/2;
5653 cmd
= IDE_COMMAND_WRITE
;
5658 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5660 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5664 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5665 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5667 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5669 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5671 (USHORT
)(AtaReq
->bcount
),
5672 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5674 if(statusByte2
!= 0xff) {
5675 GetStatus(chan
, statusByte2
);
5677 if(statusByte2
& IDE_STATUS_ERROR
) {
5678 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5679 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5680 return SRB_STATUS_ERROR
;
5683 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5685 return SRB_STATUS_PENDING
;
5688 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5690 (USHORT
)(AtaReq
->bcount
),
5691 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5694 if (!(statusByte
& IDE_STATUS_DRQ
) ||
5695 statusByte
== 0xff) {
5697 if(statusByte
== 0xff) {
5698 KdPrint2((PRINT_PREFIX
5699 "IdeReadWrite: error sending command (%#x)\n",
5702 KdPrint2((PRINT_PREFIX
5703 "IdeReadWrite: DRQ never asserted (%#x)\n",
5707 AtaReq
->WordsLeft
= 0;
5709 // Clear interrupt expecting flag.
5710 chan
->ExpectingInterrupt
= FALSE
;
5711 InterlockedExchange(&(chan
->CheckIntr
),
5714 // Clear current SRB.
5715 UniataRemoveRequest(chan
, Srb
);
5717 return (statusByte
== 0xff) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
5720 chan
->ExpectingInterrupt
= TRUE
;
5721 InterlockedExchange(&(chan
->CheckIntr
),
5724 // Write next DEV_BSIZE/2*N words.
5725 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5726 KdPrint2((PRINT_PREFIX
5727 "IdeReadWrite: Write %#x words\n", wordCount
));
5732 UniataGetPioTiming(LunExt
));
5736 KdPrint2((PRINT_PREFIX
5737 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5740 (PULONG
)(AtaReq
->DataBuffer
),
5742 UniataGetPioTiming(LunExt
));
5745 // Adjust buffer address and words left count.
5746 AtaReq
->WordsLeft
-= wordCount
;
5747 AtaReq
->DataBuffer
+= wordCount
;
5749 // Wait for interrupt.
5750 return SRB_STATUS_PENDING
;
5752 } // end IdeReadWrite()
5758 Routine Description:
5759 This routine handles IDE Verify.
5762 HwDeviceExtension - HBA miniport driver's adapter data storage
5763 Srb - IO request packet
5772 IN PVOID HwDeviceExtension
,
5773 IN PSCSI_REQUEST_BLOCK Srb
5776 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5777 UCHAR lChannel
= GET_CHANNEL(Srb
);
5778 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5779 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5780 PHW_LU_EXTENSION LunExt
;
5781 ULONG ldev
= GET_LDEV(Srb
);
5783 ULONG startingSector
;
5790 LunExt
= &deviceExtension
->lun
[ldev
];
5791 // Drive has these number sectors.
5792 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
5793 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
5794 LunExt
->IdentifyData
.NumberOfHeads
*
5795 LunExt
->IdentifyData
.NumberOfCylinders
;
5798 KdPrint2((PRINT_PREFIX
5799 "IdeVerify: Total sectors %#x\n",
5802 // Get starting sector number from CDB.
5803 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5804 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5806 KdPrint2((PRINT_PREFIX
5807 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
5811 endSector
= startingSector
+ sectorCount
;
5813 KdPrint2((PRINT_PREFIX
5814 "IdeVerify: Ending sector %#x\n",
5817 if (endSector
> sectors
) {
5819 // Too big, round down.
5820 KdPrint2((PRINT_PREFIX
5821 "IdeVerify: Truncating request to %#x blocks\n",
5822 sectors
- startingSector
- 1));
5824 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
5828 // Set up sector count register. Round up to next block.
5829 if (sectorCount
> 0xFF) {
5830 sectorCount
= (USHORT
)0xFF;
5834 // Set data buffer pointer and words left.
5835 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5836 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5838 // Indicate expecting an interrupt.
5839 InterlockedExchange(&(chan
->CheckIntr
),
5842 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5844 statusByte
= AtaCommand48(deviceExtension
, ldev
& 0x01, GET_CHANNEL(Srb
),
5845 IDE_COMMAND_VERIFY
, lba
,
5849 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5850 // Wait for interrupt.
5851 return SRB_STATUS_PENDING
;
5853 return SRB_STATUS_ERROR
;
5855 } // end IdeVerify()
5857 #endif //UNIATA_CORE
5861 Routine Description:
5862 Send ATAPI packet command to device.
5865 HwDeviceExtension - HBA miniport driver's adapter data storage
5866 Srb - IO request packet
5874 IN PVOID HwDeviceExtension
,
5875 IN PSCSI_REQUEST_BLOCK Srb
,
5879 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5880 UCHAR lChannel
= GET_CHANNEL(Srb
);
5881 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5882 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5883 ULONG ldev
= GET_LDEV(Srb
);
5886 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
5887 BOOLEAN use_dma
= FALSE
;
5888 BOOLEAN dma_reinited
= FALSE
;
5889 BOOLEAN retried
= FALSE
;
5891 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
5892 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
5893 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
5895 #ifdef UNIATA_DUMP_ATAPI
5896 if(CmdAction
& CMD_ACTION_PREPARE
) {
5900 PCHAR ModeSelectData
;
5903 Cdb
= (PCDB
)(Srb
->Cdb
);
5904 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5905 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5906 CdbDataLen
= Srb
->DataTransferLength
;
5908 if(CdbDataLen
> 0x1000) {
5909 CdbDataLen
= 0x1000;
5913 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5914 KdPrint2(("P:T:D=%d:%d:%d\n",
5918 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
5921 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
5922 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
5923 Cdb
->WRITE_CD
.LBA
[0],
5924 Cdb
->WRITE_CD
.LBA
[1],
5925 Cdb
->WRITE_CD
.LBA
[2],
5926 Cdb
->WRITE_CD
.LBA
[3]
5929 if(ScsiCommand
== SCSIOP_WRITE12
) {
5930 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
5931 Cdb
->CDB12READWRITE
.LBA
[0],
5932 Cdb
->CDB12READWRITE
.LBA
[1],
5933 Cdb
->CDB12READWRITE
.LBA
[2],
5934 Cdb
->CDB12READWRITE
.LBA
[3]
5937 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
5938 KdPrint(("ModeSelect 6\n"));
5939 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5940 ModeSelectData
= CdbData
+4;
5941 KdDump(CdbData
, CdbDataLen
);
5943 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
5944 KdPrint(("ModeSelect 10\n"));
5945 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5946 ModeSelectData
= CdbData
+8;
5947 KdDump(CdbData
, CdbDataLen
);
5949 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5950 KdPrint(("Send buffer to device:\n"));
5951 KdDump(CdbData
, CdbDataLen
);
5956 #endif //UNIATA_DUMP_ATAPI
5959 if(CmdAction
== CMD_ACTION_PREPARE
) {
5960 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
5961 switch (Srb
->Cdb
[0]) {
5965 case SCSIOP_WRITE12
:
5969 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
5970 return SRB_STATUS_BUSY
;
5973 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5974 !AtaReq
->OriginalSrb
) {
5975 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
5976 return SRB_STATUS_BUSY
;
5980 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5981 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5983 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
5984 // Set data buffer pointer and words left.
5985 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5986 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5987 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5988 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5990 // check if reorderable
5991 switch(Srb
->Cdb
[0]) {
5993 case SCSIOP_WRITE12
:
5995 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6001 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6003 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6005 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6006 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6007 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
6008 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6012 // check if DMA read/write
6013 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6014 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6016 if(AtaReq
->TransferLength
) {
6018 switch(Srb
->Cdb
[0]) {
6020 case SCSIOP_WRITE12
:
6021 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
6027 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
6029 if(AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6030 (PUCHAR
)(AtaReq
->DataBuffer
),
6031 Srb
->DataTransferLength
6032 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
6034 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6039 case SCSIOP_READ_CD
:
6040 if(deviceExtension
->opt_AtapiDmaRawRead
)
6041 goto call_dma_setup
;
6045 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
6046 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6051 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
6052 KdPrint2((PRINT_PREFIX
"dma RO\n"));
6063 if(!AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6064 (PUCHAR
)(AtaReq
->DataBuffer
),
6065 Srb
->DataTransferLength
)) {
6066 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
6069 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6073 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
6077 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6078 // if this is queued request, reinit DMA and check
6079 // if DMA mode is still available
6080 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
6081 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6082 if (/*EnableDma &&*/
6083 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6084 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
6087 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6088 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
6091 dma_reinited
= TRUE
;
6095 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6096 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
6097 return SRB_STATUS_PENDING
;
6099 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6100 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6101 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6104 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6105 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
6107 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6108 //AtapiDmaReinit(deviceExtension, ldev, AtaReq);
6109 } if(AtaReq
->TransferLength
) {
6111 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
6112 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6113 if (/*EnableDma &&*/
6114 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6117 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6122 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
6124 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6125 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
6126 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
6127 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6130 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6131 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6132 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6135 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
6138 // We need to know how many platters our atapi cd-rom device might have.
6139 // Before anyone tries to send a srb to our target for the first time,
6140 // we must "secretly" send down a separate mechanism status srb in order to
6141 // initialize our device extension changer data. That's how we know how
6142 // many platters our target has.
6144 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6145 !AtaReq
->OriginalSrb
) {
6149 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6150 // Set this flag now. If the device hangs on the mech. status
6151 // command, we will not have the chance to set it.
6152 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6154 chan
->MechStatusRetryCount
= 3;
6155 AtaReq
->OriginalSrb
= Srb
;
6156 AtaReq
->Srb
= BuildMechanismStatusSrb (
6160 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6161 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6162 if (srbStatus
== SRB_STATUS_PENDING
) {
6163 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6166 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6167 AtaReq
->OriginalSrb
= NULL
;
6168 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6169 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6170 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6174 #endif //UNIATA_CORE
6176 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
6177 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
6179 // Make sure command is to ATAPI device.
6180 flags
= deviceExtension
->lun
[ldev
].DeviceFlags
;
6181 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6182 if((Srb
->Lun
) > (deviceExtension
->lun
[ldev
].DiscsPresent
- 1)) {
6184 // Indicate no device found at this address.
6185 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6186 return SRB_STATUS_SELECTION_TIMEOUT
;
6188 } else if(Srb
->Lun
> 0) {
6189 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6190 return SRB_STATUS_SELECTION_TIMEOUT
;
6193 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
6194 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6195 return SRB_STATUS_SELECTION_TIMEOUT
;
6198 // Select device 0 or 1.
6199 SelectDrive(chan
, ldev
& 0x1);
6201 // Verify that controller is ready for next command.
6202 GetStatus(chan
, statusByte
);
6203 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
6205 if(statusByte
== 0xff) {
6206 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
6209 if(statusByte
& IDE_STATUS_BUSY
) {
6210 if(statusByte
& IDE_STATUS_DSC
) {
6211 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
6213 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
6214 // We have to make reset here, since we are expecting device to be available
6215 //return SRB_STATUS_BUSY; // this cause queue freeze
6219 if(statusByte
& IDE_STATUS_ERROR
) {
6220 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
6222 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
6223 // Read the error reg. to clear it and fail this request.
6224 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6225 return MapError(deviceExtension
, Srb
);
6227 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
6230 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
6231 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
6232 if((!(statusByte
& IDE_STATUS_DSC
)) &&
6233 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6235 AtapiStallExecution(200);
6236 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6237 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6238 return SRB_STATUS_PENDING
;
6241 if(IS_RDP(Srb
->Cdb
[0])) {
6243 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6247 if(statusByte
& IDE_STATUS_DRQ
) {
6249 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6251 // Try to drain the data that one preliminary device thinks that it has
6252 // to transfer. Hopefully this random assertion of DRQ will not be present
6253 // in production devices.
6254 for (i
= 0; i
< 0x10000; i
++) {
6255 GetStatus(chan
, statusByte
);
6256 if(statusByte
& IDE_STATUS_DRQ
) {
6257 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6265 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6267 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6269 AtapiSoftReset(chan
, ldev
& 1);
6271 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6272 // Re-initialize Atapi device.
6273 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), ldev
& 1, TRUE
);
6275 IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb),
6276 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
6278 // Inform the port driver that the bus has been reset.
6279 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6280 // Clean up device extension fields that AtapiStartIo won't.
6281 chan
->ExpectingInterrupt
= FALSE
;
6283 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6286 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6288 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
6289 return SRB_STATUS_BUS_RESET;
6292 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
6296 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
6297 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6298 return SRB_STATUS_SELECTION_TIMEOUT
;
6302 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6303 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6304 Srb
->Cdb
[1] &= ~0xE0;
6305 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6306 // Torisan changer. TUR's are overloaded to be platter switches.
6307 Srb
->Cdb
[7] = Srb
->Lun
;
6314 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6316 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6319 statusByte
= WaitOnBusy(chan
);
6320 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6323 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6324 use_dma
? ATA_F_DMA
: 0);
6326 // Write transfer byte count to registers.
6327 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6328 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6330 if (Srb
->DataTransferLength
>= 0x10000) {
6331 byteCountLow
= byteCountHigh
= 0xFF;
6334 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6335 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6337 if (flags
& DFLAGS_INT_DRQ
) {
6339 // This device interrupts when ready to receive the packet.
6341 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6344 chan
->ExpectingInterrupt
= TRUE
;
6345 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6346 InterlockedExchange(&(chan
->CheckIntr
),
6349 // Write ATAPI packet command.
6350 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6352 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
6353 return SRB_STATUS_PENDING
;
6357 // This device quickly sets DRQ when ready to receive the packet.
6359 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6362 chan
->ExpectingInterrupt
= TRUE
;
6363 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6364 InterlockedExchange(&(chan
->CheckIntr
),
6367 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6369 // Write ATAPI packet command.
6370 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6374 statusByte
= WaitForDrq(chan
);
6376 // Need to read status register and clear interrupt (if any)
6377 GetBaseStatus(chan
, statusByte
);
6379 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6381 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6382 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6383 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6384 return SRB_STATUS_ERROR
;
6388 GetStatus(chan
, statusByte
);
6389 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6391 // Send CDB to device.
6392 statusByte
= WaitOnBaseBusy(chan
);
6394 // Indicate expecting an interrupt and wait for it.
6395 chan
->ExpectingInterrupt
= TRUE
;
6396 InterlockedExchange(&(chan
->CheckIntr
),
6398 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6400 GetBaseStatus(chan
, statusByte
);
6402 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6409 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6410 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
);
6413 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6415 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6416 return SRB_STATUS_PENDING
;
6418 } // end AtapiSendCommand()
6425 Routine Description:
6426 Program ATA registers for IDE disk transfer.
6429 HwDeviceExtension - ATAPI driver storage.
6430 Srb - System request block.
6433 SRB status (pending if all goes well).
6438 ULONG check_point
= 0;
6439 #define SetCheckPoint(cp) { check_point = (cp) ; }
6441 #define SetCheckPoint(cp)
6447 IN PVOID HwDeviceExtension
,
6448 IN PSCSI_REQUEST_BLOCK Srb
,
6453 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6456 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6464 UCHAR statusByte
,errorByte
;
6467 PMODE_PARAMETER_HEADER modeData
;
6471 //ULONG __ebp__ = 0;
6473 SetCheckPoint(0x20);
6474 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6479 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6480 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6481 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6482 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6483 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6485 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6486 Srb->SrbExtension));
6487 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6490 SetCheckPoint(0x30);
6491 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6493 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6495 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6497 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6499 lChannel
= GET_CHANNEL(Srb
);
6500 chan
= &(deviceExtension
->chan
[lChannel
]);
6501 ldev
= GET_LDEV(Srb
);
6503 SetCheckPoint(0x40);
6504 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6505 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6507 if(CmdAction
== CMD_ACTION_PREPARE
) {
6508 switch (Srb
->Cdb
[0]) {
6510 case SCSIOP_INQUIRY
: // now it requires device access
6512 case SCSIOP_READ_CAPACITY
:
6515 case SCSIOP_REQUEST_SENSE
:
6517 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6522 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6523 return SRB_STATUS_BUSY
;
6527 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6528 switch (Srb
->Cdb
[0]) {
6529 case SCSIOP_INQUIRY
:
6531 KdPrint2((PRINT_PREFIX
6532 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6533 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6534 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6535 // which support up to two devices.
6536 if ((Srb
->Lun
!= 0) ||
6537 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6538 (Srb
->TargetId
> 2) /*||
6539 (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) {
6541 KdPrint2((PRINT_PREFIX
6542 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6543 // Indicate no device found at this address.
6544 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6549 KdPrint2((PRINT_PREFIX
6550 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6551 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6552 PIDENTIFY_DATA2 identifyData
= &(deviceExtension
->lun
[ldev
].IdentifyData
);
6554 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6556 if(!CheckDevice(HwDeviceExtension
, lChannel
, ldev
& 1, FALSE
)) {
6557 KdPrint2((PRINT_PREFIX
6558 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6559 // Indicate no device found at this address.
6561 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6565 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, ldev
& 1)) {
6566 KdPrint2((PRINT_PREFIX
6567 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6568 // Indicate no device found at this address.
6569 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
6571 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6576 // Zero INQUIRY data structure.
6577 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6579 // Standard IDE interface only supports disks.
6580 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6582 // Set the removable bit, if applicable.
6583 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6584 KdPrint2((PRINT_PREFIX
6585 "RemovableMedia\n"));
6586 inquiryData
->RemovableMedia
= 1;
6588 // Set the Relative Addressing (LBA) bit, if applicable.
6589 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6590 inquiryData
->RelativeAddressing
= 1;
6591 KdPrint2((PRINT_PREFIX
6592 "RelativeAddressing\n"));
6594 // Set the CommandQueue bit
6595 inquiryData
->CommandQueue
= 1;
6597 // Fill in vendor identification fields.
6598 for (i
= 0; i
< 24; i
+= 2) {
6599 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6602 // Initialize unused portion of product id.
6603 for (i = 0; i < 4; i++) {
6604 inquiryData->ProductId[12+i] = ' ';
6607 // Move firmware revision from IDENTIFY data to
6608 // product revision in INQUIRY data.
6609 for (i
= 0; i
< 4; i
+= 2) {
6610 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6613 status
= SRB_STATUS_SUCCESS
;
6618 case SCSIOP_MODE_SENSE
:
6620 KdPrint2((PRINT_PREFIX
6621 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6622 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6623 // This is used to determine if the media is write-protected.
6624 // Since IDE does not support mode sense then we will modify just the portion we need
6625 // so the higher level driver can determine if media is protected.
6626 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6628 SelectDrive(chan
, ldev
& 0x1);
6629 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6630 statusByte
= WaitOnBusy(chan
);
6632 if (!(statusByte
& IDE_STATUS_ERROR
)){
6634 // no error occured return success, media is not protected
6635 chan
->ExpectingInterrupt
= FALSE
;
6636 InterlockedExchange(&(chan
->CheckIntr
),
6638 status
= SRB_STATUS_SUCCESS
;
6642 // error occured, handle it locally, clear interrupt
6643 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6645 GetBaseStatus(chan
, statusByte
);
6646 chan
->ExpectingInterrupt
= FALSE
;
6647 InterlockedExchange(&(chan
->CheckIntr
),
6649 status
= SRB_STATUS_SUCCESS
;
6651 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6653 //media is write-protected, set bit in mode sense buffer
6654 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6656 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6657 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6660 status
= SRB_STATUS_SUCCESS
;
6662 status
= SRB_STATUS_INVALID_REQUEST
;
6666 case SCSIOP_TEST_UNIT_READY
:
6668 KdPrint2((PRINT_PREFIX
6669 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6670 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6671 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6673 // Select device 0 or 1.
6674 SelectDrive(chan
, ldev
& 0x1);
6675 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6677 // Wait for busy. If media has not changed, return success
6678 statusByte
= WaitOnBusy(chan
);
6680 if (!(statusByte
& IDE_STATUS_ERROR
)){
6681 chan
->ExpectingInterrupt
= FALSE
;
6682 InterlockedExchange(&(chan
->CheckIntr
),
6684 status
= SRB_STATUS_SUCCESS
;
6686 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6687 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6689 // Special case: If current media is write-protected,
6690 // the 0xDA command will always fail since the write-protect bit
6691 // is sticky,so we can ignore this error
6692 GetBaseStatus(chan
, statusByte
);
6693 chan
->ExpectingInterrupt
= FALSE
;
6694 InterlockedExchange(&(chan
->CheckIntr
),
6696 status
= SRB_STATUS_SUCCESS
;
6700 // Request sense buffer to be build
6701 chan
->ExpectingInterrupt
= TRUE
;
6702 InterlockedExchange(&(chan
->CheckIntr
),
6704 status
= SRB_STATUS_PENDING
;
6708 status
= SRB_STATUS_SUCCESS
;
6713 case SCSIOP_READ_CAPACITY
:
6715 KdPrint2((PRINT_PREFIX
6716 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
6717 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6718 // Claim 512 byte blocks (big-endian).
6719 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
6721 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
6723 // Calculate last sector.
6724 if(!(i
= (ULONG
)deviceExtension
->lun
[ldev
].NumOfSectors
)) {
6725 i
= deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
*
6726 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
*
6727 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
;
6731 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
6732 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
6733 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
6735 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
6737 KdPrint2((PRINT_PREFIX
6738 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
6740 deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
,
6741 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
,
6742 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
));
6745 status
= SRB_STATUS_SUCCESS
;
6750 KdPrint2((PRINT_PREFIX
6751 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
6752 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6753 status
= IdeVerify(HwDeviceExtension
,Srb
);
6760 KdPrint2((PRINT_PREFIX
6761 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
6762 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
6763 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6764 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6765 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6766 status
= IdeReadWrite(HwDeviceExtension
,
6770 case SCSIOP_START_STOP_UNIT
:
6772 KdPrint2((PRINT_PREFIX
6773 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6774 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6775 //Determine what type of operation we should perform
6776 cdb
= (PCDB
)Srb
->Cdb
;
6778 if (cdb
->START_STOP
.LoadEject
== 1){
6780 statusByte
= WaitOnBaseBusy(chan
);
6782 // first select device 0 or 1.
6783 SelectDrive(chan
, ldev
& 0x1);
6784 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
6786 status
= SRB_STATUS_SUCCESS
;
6789 case SCSIOP_MEDIUM_REMOVAL
:
6791 cdb
= (PCDB
)Srb
->Cdb
;
6793 statusByte
= WaitOnBaseBusy(chan
);
6795 SelectDrive(chan
, ldev
& 0x1);
6796 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
6797 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
6799 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
6801 status
= SRB_STATUS_SUCCESS
;
6804 // Note: I don't implement this, because NTFS driver too often issues this command
6805 // It causes awful performance degrade. However, if somebody wants, I will implement
6806 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
6809 case SCSIOP_FLUSH_BUFFER
:
6810 case SCSIOP_SYNCHRONIZE_CACHE
:
6812 SelectDrive(chan
, ldev
& 0x1);
6813 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
6814 status
= SRB_STATUS_SUCCESS
;
6815 // status = SRB_STATUS_PENDING;
6816 statusByte
= WaitOnBusy(chan
);
6820 case SCSIOP_REQUEST_SENSE
:
6821 // this function makes sense buffers to report the results
6822 // of the original GET_MEDIA_STATUS command
6824 KdPrint2((PRINT_PREFIX
6825 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6826 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6827 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6828 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
6831 status
= SRB_STATUS_INVALID_REQUEST
;
6835 case SCSIOP_ATA_PASSTHROUGH
:
6838 BOOLEAN use_dma
= FALSE
;
6841 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
6843 lChannel
= Srb
->TargetId
>> 1;
6845 regs
->bDriveHeadReg
&= 0x0f;
6846 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
6848 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
6850 KdPrint2((PRINT_PREFIX
6851 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6852 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6855 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6857 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
6858 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
6860 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6861 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
6862 (PUCHAR
)(Srb
->DataBuffer
),
6863 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
6869 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
6870 AtapiStallExecution(10);
6872 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6873 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6874 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6875 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6876 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6877 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6879 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
6880 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6881 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
6882 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6883 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
6884 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6885 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
6886 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6887 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
6888 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6890 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
6893 GetBaseStatus(chan
, statusByte
);
6894 if(statusByte
& IDE_STATUS_ERROR
) {
6895 goto passthrough_err
;
6897 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
6900 ScsiPortStallExecution(1); // wait for busy to be set
6902 if(regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) {
6903 to_lim
= Srb
->TimeOutValue
;
6905 if(Srb
->TimeOutValue
<= 2) {
6906 to_lim
= Srb
->TimeOutValue
*900;
6908 to_lim
= (Srb
->TimeOutValue
*999) - 500;
6911 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
6912 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
6913 GetBaseStatus(chan
, statusByte
);
6914 if(statusByte
& IDE_STATUS_ERROR
) {
6917 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6922 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
6924 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
6925 goto passthrough_err
;
6929 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
6931 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
6932 GetBaseStatus(chan
, statusByte
);
6934 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
6935 AtapiSuckPort2(chan
);
6937 if (Srb
->SenseInfoBuffer
) {
6939 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
6941 senseBuffer
->ErrorCode
= 0x70;
6942 senseBuffer
->Valid
= 1;
6943 senseBuffer
->AdditionalSenseLength
= 0xb;
6944 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
6945 senseBuffer
->AdditionalSenseCode
= 0;
6946 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6948 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
6949 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
6951 status
= SRB_STATUS_ERROR
;
6955 if (statusByte
& IDE_STATUS_DRQ
) {
6956 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6958 (PUSHORT
) Srb
->DataBuffer
,
6959 Srb
->DataTransferLength
/ 2,
6961 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6963 (PUSHORT
) Srb
->DataBuffer
,
6964 Srb
->DataTransferLength
/ 2,
6969 status
= SRB_STATUS_SUCCESS
;
6972 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6974 } else { // read task register
6976 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
6978 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
6980 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6981 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6982 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6983 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6984 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6985 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6987 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6988 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6989 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6990 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6991 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6992 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6993 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6994 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6995 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6996 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6998 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
6999 status
= SRB_STATUS_SUCCESS
;
7006 KdPrint2((PRINT_PREFIX
7007 "IdeSendCommand: Unsupported command %#x\n",
7010 status
= SRB_STATUS_INVALID_REQUEST
;
7014 if(status
== SRB_STATUS_PENDING
) {
7015 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
7016 if(CmdAction
& CMD_ACTION_EXEC
) {
7017 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
7018 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
7021 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
7022 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7027 } // end IdeSendCommand()
7032 Routine Description:
7033 Enables disables media status notification
7036 HwDeviceExtension - ATAPI driver storage.
7043 IN PVOID HwDeviceExtension
,
7047 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7049 UCHAR lChannel
= ldev
>> 1;
7050 UCHAR statusByte
,errorByte
;
7052 chan
= &(deviceExtension
->chan
[lChannel
]);
7054 if (EnableMSN
== TRUE
){
7056 // If supported enable Media Status Notification support
7057 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
7060 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7061 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7062 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7064 if (statusByte
& IDE_STATUS_ERROR
) {
7065 // Read the error register.
7066 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7068 KdPrint2((PRINT_PREFIX
7069 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
7073 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
7074 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
7075 chan
->ReturningMediaStatus
= 0;
7080 } else { // end if EnableMSN == TRUE
7082 // disable if previously enabled
7083 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
7085 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7086 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7087 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7088 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
7095 } // end IdeMediaStatus()
7100 Routine Description:
7102 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
7103 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
7106 HwDeviceExtension - ATAPI driver storage.
7107 Srb - System request block.
7111 SRB status (ALWAYS SUCCESS).
7116 IdeBuildSenseBuffer(
7117 IN PVOID HwDeviceExtension
,
7118 IN PSCSI_REQUEST_BLOCK Srb
7121 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7123 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
7124 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
7128 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
7130 senseBuffer
->ErrorCode
= 0x70;
7131 senseBuffer
->Valid
= 1;
7132 senseBuffer
->AdditionalSenseLength
= 0xb;
7133 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7134 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7135 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7136 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
7138 senseBuffer
->ErrorCode
= 0x70;
7139 senseBuffer
->Valid
= 1;
7140 senseBuffer
->AdditionalSenseLength
= 0xb;
7141 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7142 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7143 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7144 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
7146 senseBuffer
->ErrorCode
= 0x70;
7147 senseBuffer
->Valid
= 1;
7148 senseBuffer
->AdditionalSenseLength
= 0xb;
7149 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
7150 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
7151 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7152 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
7154 senseBuffer
->ErrorCode
= 0x70;
7155 senseBuffer
->Valid
= 1;
7156 senseBuffer
->AdditionalSenseLength
= 0xb;
7157 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
7158 senseBuffer
->AdditionalSenseCode
= 0;
7159 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7161 return SRB_STATUS_SUCCESS
;
7163 return SRB_STATUS_ERROR
;
7165 }// End of IdeBuildSenseBuffer
7169 UniataUserDeviceReset(
7170 PHW_DEVICE_EXTENSION deviceExtension
,
7171 PHW_LU_EXTENSION LunExt
,
7176 AtapiDisableInterrupts(deviceExtension
, PathId
);
7177 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
7178 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
7179 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), ldev
& 1);
7181 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
7182 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
7183 deviceExtension
->chan
[PathId
].lun
[0]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7184 deviceExtension
->chan
[PathId
].lun
[1]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7186 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7187 AtapiEnableInterrupts(deviceExtension
, PathId
);
7189 } // end UniataUserDeviceReset()
7194 PHW_DEVICE_EXTENSION deviceExtension
,
7199 BOOLEAN PostReq
= FALSE
;
7201 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
7202 if(chan
->queue_depth
> 0) {
7205 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
7206 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
7207 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
7209 status
= SRB_STATUS_BUSY
;
7218 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
7222 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
7225 } // end UniataNeedQueueing()
7229 Routine Description:
7231 This routine is called from the SCSI port driver synchronized
7232 with the kernel to start an IO request.
7236 HwDeviceExtension - HBA miniport driver's adapter data storage
7237 Srb - IO request packet
7247 IN PVOID HwDeviceExtension
,
7248 IN PSCSI_REQUEST_BLOCK Srb
7251 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
7252 } // end AtapiStartIo()
7257 IN PVOID HwDeviceExtension
,
7258 IN PSCSI_REQUEST_BLOCK Srb
,
7262 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7271 PSCSI_REQUEST_BLOCK tmpSrb
;
7272 BOOLEAN PostReq
= FALSE
;
7274 BOOLEAN commPort
= FALSE
;
7276 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
7277 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7278 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7279 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7281 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7283 /* KeBugCheckEx(0xc000000e,
7284 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7286 TopLevel, 0x80000001);
7288 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7289 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7290 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7295 lChannel
= GET_CHANNEL(Srb
);
7296 chan
= &(deviceExtension
->chan
[lChannel
]);
7297 ldev
= GET_LDEV(Srb
);
7299 //ASSERT(deviceExtension);
7302 KdPrint2((PRINT_PREFIX
7303 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7304 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7305 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7307 if(lChannel
== deviceExtension
->NumberChannels
&&
7308 !Srb
->Lun
&& !Srb
->TargetId
&&
7309 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
7310 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
7312 KdPrint2((PRINT_PREFIX
7313 "AtapiStartIo: Communication port\n"));
7314 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
7316 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7318 KdPrint2((PRINT_PREFIX
7320 // Zero INQUIRY data structure.
7321 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7323 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
7325 // Fill in vendor identification fields.
7326 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
7328 status
= SRB_STATUS_SUCCESS
;
7332 /* Pass IOCTL request down */
7334 if(GET_CDEV(Srb
) >= 2 ||
7335 ldev
>= deviceExtension
->NumberChannels
*2 ||
7336 lChannel
>= deviceExtension
->NumberChannels
||
7339 if(lChannel
>= deviceExtension
->NumberChannels
) {
7344 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7345 KdPrint3((PRINT_PREFIX
7346 "AtapiStartIo: SRB rejected\n"));
7347 // Indicate no device found at this address.
7348 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7349 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7354 atapiDev
= (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7357 if(!commPort
&& !(chan
->lun
[ldev
& 1])) {
7359 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7362 deviceExtension
->NumberChannels
);
7363 PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n",
7364 lChannel
, ldev
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7365 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7366 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7370 for(i=0; i<1000; i++) {
7371 AtapiStallExecution(3*1000);
7378 // Determine which function.
7379 switch (Srb
->Function
) {
7381 case SRB_FUNCTION_EXECUTE_SCSI
:
7383 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7384 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7385 // let passthrough go
7387 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7391 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7392 KdPrint2((PRINT_PREFIX
7393 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7394 // Indicate no device found at this address.
7395 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7396 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7403 if(Srb->DataTransferLength) {
7405 a = ((PUCHAR)(Srb->DataBuffer))[0];
7408 } __except(EXCEPTION_EXECUTE_HANDLER) {
7409 KdPrint3((PRINT_PREFIX
7410 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7411 // Indicate no device found at this address.
7412 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7413 status = SRB_STATUS_ERROR;
7414 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7419 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7423 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
7425 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7426 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
7428 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7430 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7431 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7433 /*KeBugCheckEx(0xc000000e,
7434 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7436 status, 0x80000001);*/
7437 if(status
== SRB_STATUS_BUSY
)
7438 status
= SRB_STATUS_PENDING
;
7439 // Insert requests AFTER they have been initialized on
7440 // CMD_ACTION_PREPARE stage
7441 // we should not check TopLevel here (it is always TRUE)
7442 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7443 UniataQueueRequest(chan
, Srb
);
7445 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7448 // Send command to device.
7449 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7451 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7452 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7453 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7454 //ASSERT(!AtaReq->Flags);
7455 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7456 UniataQueueRequest(chan
, Srb
);
7457 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7458 //ASSERT(!AtaReq->Flags);
7459 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7460 //ASSERT(!AtaReq->Flags);
7464 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7465 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7466 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, ldev
& 1)) {
7467 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, ldev
& 1, TRUE
)) {
7471 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7475 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7484 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7485 KdPrint3((PRINT_PREFIX
"Try ATAPI send\n"));
7486 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7488 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7493 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7500 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7502 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7504 /* KeBugCheckEx(0xc000000e,
7505 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7507 status, 0x80000002);*/
7515 case SRB_FUNCTION_ABORT_COMMAND
:
7517 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7519 // Verify that SRB to abort is still outstanding.
7520 if((tmpSrb
!= Srb
->NextSrb
) ||
7521 !chan
->queue_depth
) {
7523 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7525 // Complete abort SRB.
7526 status
= SRB_STATUS_ABORT_FAILED
;
7530 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7531 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7532 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7533 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7534 // Log reset failure.
7535 KdPrint3((PRINT_PREFIX
7536 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7537 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7539 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7540 status
= SRB_STATUS_ERROR
;
7543 status
= SRB_STATUS_SUCCESS
;
7546 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7547 if (tmpSrb
->SenseInfoBuffer
&&
7548 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7550 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7552 senseBuffer
->ErrorCode
= 0;
7553 senseBuffer
->Valid
= 1;
7554 senseBuffer
->AdditionalSenseLength
= 0xb;
7555 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7556 senseBuffer
->AdditionalSenseCode
= 0;
7557 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7559 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7561 AtapiDmaDBSync(chan
, tmpSrb
);
7562 UniataRemoveRequest(chan
, tmpSrb
);
7563 // Indicate command complete.
7564 ScsiPortNotification(RequestComplete
,
7567 status
= SRB_STATUS_SUCCESS
;
7571 // Abort function indicates that a request timed out.
7572 // Call reset routine. Card will only be reset if
7573 // status indicates something is wrong.
7574 // Fall through to reset code.
7576 case SRB_FUNCTION_RESET_DEVICE
:
7577 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7579 // Reset single device.
7580 // For now we support only Lun=0
7582 // Note: reset is immediate command, it cannot be queued since it is usually used to
7583 // revert not- responding device to operational state
7584 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7585 UniataUserDeviceReset(deviceExtension
, &(deviceExtension
->lun
[ldev
]), lChannel
, ldev
);
7586 status
= SRB_STATUS_SUCCESS
;
7589 case SRB_FUNCTION_RESET_BUS
:
7591 // Reset Atapi and SCSI bus.
7593 // Note: reset is immediate command, it cannot be queued since it is usually used to
7594 // revert not- responding device to operational state
7595 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7596 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7597 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7598 // Log reset failure.
7599 KdPrint3((PRINT_PREFIX
7600 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7601 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7603 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7604 status
= SRB_STATUS_ERROR
;
7607 status
= SRB_STATUS_SUCCESS
;
7612 case SRB_FUNCTION_SHUTDOWN
:
7614 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7615 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7616 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7619 // FLUSH ATAPI device - do nothing
7620 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7622 // FLUSH IDE/ATA device
7623 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7624 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7625 status
= AtaCommand(deviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
7626 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7627 // If supported & allowed, reset write cacheing
7628 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7630 // Disable write cache
7631 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7632 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7633 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7634 // Check for errors.
7635 if (status
& IDE_STATUS_ERROR
) {
7636 KdPrint2((PRINT_PREFIX
7637 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7640 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7642 // Re-enable write cache
7643 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7644 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7645 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7646 // Check for errors.
7647 if (status
& IDE_STATUS_ERROR
) {
7648 KdPrint2((PRINT_PREFIX
7649 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7651 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7653 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7657 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7659 status
= SRB_STATUS_SUCCESS
;
7663 case SRB_FUNCTION_FLUSH
:
7665 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7666 status
= SRB_STATUS_SUCCESS
;
7669 /* case SRB_FUNCTION_SHUTDOWN:
7670 case SRB_FUNCTION_FLUSH:
7672 // Flush device's cache.
7673 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7675 if (chan->CurrentSrb) {
7677 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7678 Srb->SrbStatus = SRB_STATUS_BUSY;
7679 ScsiPortNotification(RequestComplete,
7685 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
7686 status = SRB_STATUS_SUCCESS;
7688 status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb),
7689 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
7690 if (status & IDE_STATUS_DRQ) {
7691 status = SRB_STATUS_SUCCESS;
7693 status = SRB_STATUS_SELECTION_TIMEOUT;
7698 case SRB_FUNCTION_IO_CONTROL
: {
7702 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
7704 len
= Srb
->DataTransferLength
;
7706 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
7708 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
7709 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
7711 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7714 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
7716 // Version and revision per SMART 1.03
7718 versionParameters
->bVersion
= 1;
7719 versionParameters
->bRevision
= 1;
7720 versionParameters
->bReserved
= 0;
7722 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
7723 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
7725 // This is done because of how the IOCTL_SCSI_MINIPORT
7726 // determines 'targetid's'. Disk.sys places the real target id value
7727 // in the DeviceMap field. Once we do some parameter checking, the value passed
7728 // back to the application will be determined.
7730 deviceNumber
= versionParameters
->bIDEDeviceMap
;
7733 KdPrint2((PRINT_PREFIX
7734 "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
7735 // Indicate no device found at this address.
7736 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7737 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7741 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
7744 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7748 // NOTE: This will only set the bit
7749 // corresponding to this drive's target id.
7750 // The bit mask is as follows:
7756 if (deviceExtension
->NumberChannels
== 1) {
7757 if (chan
->PrimaryAddress
) {
7758 deviceNumber
= 1 << ldev
;
7760 deviceNumber
= 4 << ldev
;
7763 deviceNumber
= 1 << ldev
;
7766 versionParameters
->bIDEDeviceMap
= deviceNumber
;
7768 status
= SRB_STATUS_SUCCESS
;
7772 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
7774 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7775 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7778 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
7779 // Extract the target.
7780 targetId
= cmdInParameters
.bDriveNumber
;
7781 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
7782 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
7783 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7784 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
7785 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7789 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
7791 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
7792 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
7793 status
= SRB_STATUS_INVALID_REQUEST
;
7799 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
7800 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
7801 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
7802 status
= SRB_STATUS_INVALID_REQUEST
;
7806 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
7807 // Zero the output buffer
7808 RtlZeroMemory(cmdOutParameters
, len
);
7809 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
7810 ((PUCHAR)cmdOutParameters)[i] = 0;
7813 // Build status block.
7814 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
7815 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
7816 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
7818 // Extract the identify data from the device extension.
7819 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
7820 cmdOutParameters
->cBufferSize
);
7822 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
7824 status
= SRB_STATUS_SUCCESS
;
7828 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
7829 cmdInParameters
.irDriveRegs
.bCommandReg
));
7830 status
= SRB_STATUS_INVALID_REQUEST
;
7836 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
7837 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
7838 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
7839 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
7840 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
7841 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
7842 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
7843 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
7846 KdPrint2((PRINT_PREFIX
7847 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
7848 // Indicate no device found at this address.
7849 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7850 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7854 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7856 if(PostReq
|| TopLevel
) {
7857 UniataQueueRequest(chan
, Srb
);
7858 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7859 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7864 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
7865 status
= SRB_STATUS_PENDING
;
7867 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7870 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
7875 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
7876 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
7877 status
= SRB_STATUS_INVALID_REQUEST
;
7882 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
7884 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
7885 ULONG ldev
= GET_LDEV2(AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
, 0);
7886 PHW_LU_EXTENSION LunExt
;
7889 //chan = &(deviceExtension->chan[lChannel]);
7891 if(AtaCtl
->addr
.Lun
||
7892 ldev
>= deviceExtension
->NumberChannels
*2 ||
7893 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
7900 LunExt
= &(deviceExtension
->lun
[ldev
]);
7901 lChannel
= AtaCtl
->addr
.PathId
;
7902 chan
= &(deviceExtension
->chan
[lChannel
]);
7905 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl
->hdr
.ControlCode
, ldev
));
7907 /* check for valid LUN */
7908 switch (AtaCtl
->hdr
.ControlCode
) {
7909 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7910 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
7912 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
7913 AtaCtl
->addr
.TargetId
!= 0xff ||
7914 AtaCtl
->addr
.Lun
!= 0
7916 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
7917 ldev
< deviceExtension
->NumberChannels
*2) { // AtaCtl->addr.TargetId != 0xff
7918 LunExt
= &(deviceExtension
->lun
[ldev
]);
7921 goto handle_bad_ldev
;
7924 // this would be BUS reset
7925 lChannel
= AtaCtl
->addr
.PathId
;
7926 chan
= &(deviceExtension
->chan
[lChannel
]);
7928 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
7929 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7930 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
7931 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7932 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
7935 KdPrint2((PRINT_PREFIX
7936 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
7937 // Indicate no device found at this address.
7942 /* check if queueing is necessary */
7943 switch (AtaCtl
->hdr
.ControlCode
) {
7944 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7945 if(!LunExt
->nBadBlocks
) {
7948 goto uata_ctl_queue
;
7949 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7950 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
7953 goto uata_ctl_queue
;
7954 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7955 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
7957 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
7958 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7960 if(PostReq
|| TopLevel
) {
7961 UniataQueueRequest(chan
, Srb
);
7962 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7963 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7966 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
7967 status
= SRB_STATUS_PENDING
;
7969 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7972 } // end switch (AtaCtl->hdr.ControlCode)
7974 /* process request */
7975 switch (AtaCtl
->hdr
.ControlCode
) {
7976 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7978 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
7980 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
7981 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
7982 if(AtaCtl
->addr
.TargetId
!= 0xff) {
7983 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_HIDDEN
;
7988 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7989 AtapiStallExecution(1000 * 1000);
7992 FindDevices(HwDeviceExtension
,
7993 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
7994 ? UNIATA_FIND_DEV_UNHIDE
: 0,
7995 AtaCtl
->addr
.PathId
);
7996 status
= SRB_STATUS_SUCCESS
;
8000 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
8002 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
8004 deviceExtension
->lun
[ldev
].DeviceFlags
= 0;
8005 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
8006 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
8007 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_HIDDEN
;
8010 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
8011 AtapiStallExecution(1000 * 1000);
8014 status
= SRB_STATUS_SUCCESS
;
8017 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
8019 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
8021 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
8022 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
8024 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
8025 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
8026 if(LunExt
->LimitedTransferMode
>
8027 LunExt
->OrigTransferMode
) {
8028 // check for incorrect value
8029 LunExt
->LimitedTransferMode
=
8030 LunExt
->OrigTransferMode
;
8033 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
8035 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8036 if(AtaCtl
->SetMode
.ApplyImmediately
) {
8037 AtapiDmaInit__(deviceExtension
, ldev
);
8039 /* deviceExtension->lun[ldev].TransferMode =
8040 deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
8041 status
= SRB_STATUS_SUCCESS
;
8044 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
8046 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
8048 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
8049 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
8050 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
8052 status
= SRB_STATUS_SUCCESS
;
8055 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
8057 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
8059 AtaCtl
->AdapterInfo
.HeaderLength
= offsetof(ADAPTERINFO
, Chan
);
8061 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
8062 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
8063 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
8064 status
= SRB_STATUS_DATA_OVERRUN
;
8068 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
8069 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
8070 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
8071 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
8072 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
8073 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
8074 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
8075 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
8076 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
8077 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
8078 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
8079 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
8080 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
8081 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
8082 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
8083 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
8084 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
8085 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
8086 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
8087 if(deviceExtension
->FullDevName
) {
8088 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
8090 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
8092 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
8094 status
= SRB_STATUS_SUCCESS
;
8097 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
8099 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
8101 ForgetBadBlocks(LunExt
);
8103 status
= SRB_STATUS_SUCCESS
;
8106 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
8108 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
8113 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
, ldev
);
8116 status
= SRB_STATUS_SUCCESS
;
8120 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
8121 AtaCtl
->hdr
.ControlCode
));
8122 status
= SRB_STATUS_INVALID_REQUEST
;
8127 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
8128 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
8129 "SCSIDISK", "-UNIATA-"));
8131 status
= SRB_STATUS_INVALID_REQUEST
;
8136 } // end SRB_FUNCTION_IO_CONTROL
8139 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
8140 // Indicate unsupported command.
8141 status
= SRB_STATUS_INVALID_REQUEST
;
8149 PathId
= Srb
->PathId
;
8150 TargetId
= Srb
->TargetId
;
8153 if (status
!= SRB_STATUS_PENDING
) {
8155 KdPrint2((PRINT_PREFIX
8156 "AtapiStartIo: Srb %#x complete with status %#x\n",
8160 // Set status in SRB.
8161 Srb
->SrbStatus
= (UCHAR
)status
;
8163 AtapiDmaDBSync(chan
, Srb
);
8164 UniataRemoveRequest(chan
, Srb
);
8165 // Indicate command complete.
8166 ScsiPortNotification(RequestComplete
,
8170 // Remove current Srb & get next one
8171 if((Srb
= UniataGetCurRequest(chan
))) {
8172 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8173 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
8174 // current request is under precessing, thus
8175 // we should do nothing here
8183 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
8185 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
8187 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
8188 // Indicate ready for next request.
8189 ScsiPortNotification(NextRequest
,
8193 ScsiPortNotification(NextLuRequest
,
8201 } // end AtapiStartIo__()
8206 UniataInitAtaCommands()
8212 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
8214 for(i
=0; i
<256; i
++) {
8219 KdPrint2((PRINT_PREFIX
"cmd %2.2x: ", command
));
8222 case IDE_COMMAND_READ_DMA48
:
8223 case IDE_COMMAND_READ_DMA_Q48
:
8224 case IDE_COMMAND_READ_STREAM_DMA48
:
8225 case IDE_COMMAND_READ_STREAM48
:
8226 case IDE_COMMAND_WRITE_DMA48
:
8227 case IDE_COMMAND_WRITE_DMA_Q48
:
8228 case IDE_COMMAND_READ_DMA_Q
:
8229 case IDE_COMMAND_READ_DMA
:
8230 case IDE_COMMAND_WRITE_DMA
:
8231 case IDE_COMMAND_WRITE_DMA_Q
:
8232 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8233 case IDE_COMMAND_WRITE_STREAM48
:
8234 case IDE_COMMAND_WRITE_FUA_DMA48
:
8235 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8236 case IDE_COMMAND_READ_LOG_DMA48
:
8237 case IDE_COMMAND_WRITE_LOG_DMA48
:
8238 case IDE_COMMAND_TRUSTED_RCV_DMA
:
8239 case IDE_COMMAND_TRUSTED_SEND_DMA
:
8240 KdPrint2((PRINT_PREFIX
"DMA "));
8241 flags
|= ATA_CMD_FLAG_DMA
;
8245 case IDE_COMMAND_READ48
:
8246 case IDE_COMMAND_READ_DMA48
:
8247 case IDE_COMMAND_READ_DMA_Q48
:
8248 case IDE_COMMAND_READ_MUL48
:
8249 case IDE_COMMAND_READ_STREAM_DMA48
:
8250 case IDE_COMMAND_READ_STREAM48
:
8251 case IDE_COMMAND_WRITE48
:
8252 case IDE_COMMAND_WRITE_DMA48
:
8253 case IDE_COMMAND_WRITE_DMA_Q48
:
8254 case IDE_COMMAND_WRITE_MUL48
:
8255 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8256 case IDE_COMMAND_WRITE_STREAM48
:
8257 case IDE_COMMAND_WRITE_FUA_DMA48
:
8258 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8259 case IDE_COMMAND_WRITE_MUL_FUA48
:
8260 case IDE_COMMAND_FLUSH_CACHE48
:
8261 case IDE_COMMAND_VERIFY48
:
8263 KdPrint2((PRINT_PREFIX
"48 "));
8264 flags
|= ATA_CMD_FLAG_48
;
8267 case IDE_COMMAND_READ
:
8268 case IDE_COMMAND_READ_MULTIPLE
:
8269 case IDE_COMMAND_READ_DMA
:
8270 case IDE_COMMAND_READ_DMA_Q
:
8271 case IDE_COMMAND_WRITE
:
8272 case IDE_COMMAND_WRITE_MULTIPLE
:
8273 case IDE_COMMAND_WRITE_DMA
:
8274 case IDE_COMMAND_WRITE_DMA_Q
:
8275 case IDE_COMMAND_FLUSH_CACHE
:
8276 case IDE_COMMAND_VERIFY
:
8278 KdPrint2((PRINT_PREFIX
"LBA "));
8279 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
8282 flags
|= ATA_CMD_FLAG_48supp
;
8285 case IDE_COMMAND_READ
:
8286 command
= IDE_COMMAND_READ48
; break;
8287 case IDE_COMMAND_READ_MULTIPLE
:
8288 command
= IDE_COMMAND_READ_MUL48
; break;
8289 case IDE_COMMAND_READ_DMA
:
8290 command
= IDE_COMMAND_READ_DMA48
; break;
8291 case IDE_COMMAND_READ_DMA_Q
:
8292 command
= IDE_COMMAND_READ_DMA_Q48
; break;
8293 case IDE_COMMAND_WRITE
:
8294 command
= IDE_COMMAND_WRITE48
; break;
8295 case IDE_COMMAND_WRITE_MULTIPLE
:
8296 command
= IDE_COMMAND_WRITE_MUL48
; break;
8297 case IDE_COMMAND_WRITE_DMA
:
8298 command
= IDE_COMMAND_WRITE_DMA48
; break;
8299 case IDE_COMMAND_WRITE_DMA_Q
:
8300 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
8301 case IDE_COMMAND_FLUSH_CACHE
:
8302 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
8303 // case IDE_COMMAND_READ_NATIVE_SIZE:
8304 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
8305 case IDE_COMMAND_SET_NATIVE_SIZE
:
8306 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
8307 case IDE_COMMAND_VERIFY
:
8308 command
= IDE_COMMAND_VERIFY48
; break;
8310 KdPrint2((PRINT_PREFIX
"!28->48 "));
8311 flags
&= ~ATA_CMD_FLAG_48supp
;
8314 KdPrint2((PRINT_PREFIX
"\t -> %2.2x (%2.2x)\n", command
, flags
));
8315 AtaCommands48
[i
] = command
;
8316 AtaCommandFlags
[i
] = flags
;
8318 } // end UniataInitAtaCommands()
8322 Routine Description:
8324 Installable driver initialization entry point for system.
8332 Status from ScsiPortInitialize()
8339 IN PVOID DriverObject
,
8343 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
8346 ULONG statusToReturn
, newStatus
;
8347 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
8348 BOOLEAN ReEnter
= FALSE
;
8351 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
8352 BOOLEAN PrimaryClaimed
= FALSE
;
8353 BOOLEAN SecondaryClaimed
= FALSE
;
8355 LARGE_INTEGER t0
, t1
;
8358 KdPrint2((PRINT_PREFIX (PCCHAR
)ver_string
));
8359 a
= (WCHAR
)strlen(ver_string
);
8361 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
8363 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
8366 if(!SavedDriverObject
) {
8367 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8368 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8370 KeQuerySystemTime(&t0
);
8372 KeQuerySystemTime(&t1
);
8373 } while(t0
.QuadPart
== t1
.QuadPart
);
8377 KeQuerySystemTime(&t1
);
8379 } while(t0
.QuadPart
== t1
.QuadPart
);
8380 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8381 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8384 KdPrint(("UniATA Init: ReEnter\n"));
8388 // (re)read bad block list
8389 InitBadBlocks(NULL
);
8392 // init ATA command translation table
8393 UniataInitAtaCommands();
8394 // get registry path to settings
8395 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8396 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8397 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8398 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8399 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8400 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8403 if(WinVer_Id() >= WinVer_2k
) {
8404 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
8405 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
8406 WinVer_WDM_Model
= TRUE
;
8408 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
8409 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
8410 WinVer_WDM_Model
= TRUE
;
8414 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8415 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8417 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8420 statusToReturn
= 0xffffffff;
8422 // Zero out structure.
8423 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8425 // Set size of hwInitializationData.
8426 hwInitializationData
.comm
.HwInitializationDataSize
=
8427 sizeof(hwInitializationData
.comm
) +
8428 // sizeof(hwInitializationData.nt4) +
8429 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8430 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
8432 // Set entry points.
8433 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8434 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8435 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8436 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8438 // Specify size of extensions.
8439 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8440 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8441 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8443 // Indicate PIO device.
8444 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8445 // Set PnP-specific API
8446 if(WinVer_Id() > WinVer_NT
) {
8447 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
8448 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8449 KdPrint(("set AtapiAdapterControl() ptr\n"));
8450 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8453 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8456 UniataEnumBusMasterController(DriverObject
, Argument2
);
8459 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8460 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8461 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8462 for (i
=0; i
<BMListLen
; i
++) {
8464 if(!BMList
[i
].MasterDev
) {
8465 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8468 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8472 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8473 if(BMList
[i
].ChanInitOk
& 0x03) {
8474 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8476 newStatus
= STATUS_SUCCESS
;
8480 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8482 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8483 PrimaryClaimed
= TRUE
;
8484 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8485 SecondaryClaimed
= TRUE
;
8488 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8490 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
8492 for(c
=0; c
<2; c
++) {
8494 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8498 if(PrimaryClaimed
) {
8499 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8504 if(SecondaryClaimed
) {
8505 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8510 if((WinVer_Id() < WinVer_2k
)) {
8511 // do not even try if already claimed
8513 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8516 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8519 if(!WinVer_WDM_Model
) {
8520 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8522 // in WDM model things are different....
8523 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
8524 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
8526 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8527 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8529 if(!WinVer_WDM_Model
) {
8530 BMList
[i
].channel
= (UCHAR
)c
;
8533 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8534 newStatus
= ScsiPortInitialize(DriverObject
,
8536 &hwInitializationData
.comm
,
8537 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8538 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8539 if (newStatus
< statusToReturn
) {
8540 statusToReturn
= newStatus
;
8542 if (newStatus
== STATUS_SUCCESS
) {
8543 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8545 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8546 c = 1; // this will break our for()
8547 BMList[i].ChanInitOk |= 0x01 << c;
8552 if(WinVer_Id() >= WinVer_2k
) {
8553 // the following doesn't work under higher OSes
8554 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8557 if(BMList
[i
].ChanInitOk
& 0x03) {
8558 // under NT we receive status immediately, so
8559 // we can omit alternative init method id STATUS_SUCCESS returned
8560 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8563 // if (WinVer_Id() == WinVer_NT) and some error occured
8564 // try alternative init method
8567 if(WinVer_WDM_Model
) {
8568 hwInitializationData
.comm
.HwFindAdapter
= UniataFindFakeBusMasterController
;
8569 hwInitializationData
.comm
.NumberOfAccessRanges
= 5;
8570 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8572 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8573 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8574 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8575 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8577 //BMList[i].channel = 0/*(UCHAR)c*/;
8579 KdPrint2((PRINT_PREFIX
"Try init fake: %4.4s %4.4s \n",
8580 hwInitializationData
.comm
.VendorId
,
8581 hwInitializationData
.comm
.DeviceId
));
8582 newStatus
= ScsiPortInitialize(DriverObject
,
8584 &hwInitializationData
.comm
,
8586 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8590 if(BMList
[i
].ChanInitOk
& 0x03) {
8591 _PrintNtConsole(" OK\n");
8593 _PrintNtConsole(" failed\n");
8599 /* KeBugCheckEx(0xc000000e,
8600 (i << 16) | BMList[0].ChanInitOk,
8602 newStatus, statusToReturn);*/
8604 // Look for PCI IDE controller
8605 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8606 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8607 for (; i
<BMListLen
; i
++) {
8609 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8612 /* if(BMList[i].MasterDev)
8615 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8616 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
8617 BMList
[i
].busNumber
,
8618 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
8619 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
8622 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8623 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8624 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8626 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8627 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8628 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8629 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8631 BMList
[i
].channel
= 0/*(UCHAR)c*/;
8633 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
8634 hwInitializationData
.comm
.VendorId
,
8635 hwInitializationData
.comm
.DeviceId
));
8636 newStatus
= ScsiPortInitialize(DriverObject
,
8638 &hwInitializationData
.comm
,
8640 if (newStatus
< statusToReturn
)
8641 statusToReturn
= newStatus
;
8644 if(newStatus
== STATUS_SUCCESS
) {
8645 _PrintNtConsole(" OK\n");
8647 _PrintNtConsole(" failed\n");
8653 /* KeBugCheckEx(0xc000000e,
8656 newStatus, statusToReturn);*/
8660 hwInitializationData
.comm
.VendorId
= 0;
8661 hwInitializationData
.comm
.VendorIdLength
= 0;
8662 hwInitializationData
.comm
.DeviceId
= 0;
8663 hwInitializationData
.comm
.DeviceIdLength
= 0;
8665 // The adapter count is used by the find adapter routine to track how
8666 // which adapter addresses have been tested.
8668 // Indicate 2 access ranges and reset FindAdapter.
8669 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
8670 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
8672 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
8673 // Indicate ISA bustype.
8674 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8677 // Call initialization for ISA bustype.
8678 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
8679 newStatus
= ScsiPortInitialize(DriverObject
,
8681 &hwInitializationData
.comm
,
8683 if (newStatus
< statusToReturn
)
8684 statusToReturn
= newStatus
;
8686 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
8688 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
8689 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
8692 newStatus
= ScsiPortInitialize(DriverObject
,
8694 &hwInitializationData
.comm
,
8696 if (newStatus
< statusToReturn
)
8697 statusToReturn
= newStatus
;
8699 InDriverEntry
= FALSE
;
8701 KdPrint2((PRINT_PREFIX
"\n\nLeave ATAPI IDE MiniPort DriverEntry with status %#x\n", statusToReturn
));
8703 return statusToReturn
;
8705 } // end DriverEntry()
8710 BuildMechanismStatusSrb(
8711 IN PVOID HwDeviceExtension
,
8712 IN PSCSI_REQUEST_BLOCK Srb
8715 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8716 PSCSI_REQUEST_BLOCK srb
;
8718 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8720 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8722 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8724 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8725 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8726 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8727 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8729 // Set flags to disable synchronous negociation.
8730 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8732 // Set timeout to 4 seconds.
8733 srb
->TimeOutValue
= 4;
8736 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
8737 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8738 srb
->SrbExtension
= AtaReq
;
8740 // Set CDB operation code.
8741 cdb
= (PCDB
)srb
->Cdb
;
8742 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
8743 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8746 } // end BuildMechanismStatusSrb()
8748 #endif //UNIATA_CORE
8752 BuildRequestSenseSrb (
8753 IN PVOID HwDeviceExtension
,
8754 IN PSCSI_REQUEST_BLOCK Srb
8757 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8758 PSCSI_REQUEST_BLOCK srb
;
8760 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8762 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8764 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8766 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8767 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8768 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8769 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8771 // Set flags to disable synchronous negociation.
8772 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8774 // Set timeout to 2 seconds.
8775 srb
->TimeOutValue
= 4;
8778 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
8779 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
8780 srb
->SrbExtension
= AtaReq
;
8782 // Set CDB operation code.
8783 cdb
= (PCDB
)srb
->Cdb
;
8784 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
8785 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
8788 } // end BuildRequestSenseSrb()
8794 AtapiRegCheckDevLunValue(
8795 IN PVOID HwDeviceExtension
,
8796 IN PCWCH NamePrefix
,
8804 ULONG val
= Default
;
8806 val
= AtapiRegCheckParameterValue(
8807 HwDeviceExtension
, NamePrefix
, Name
, val
);
8809 if(chan
!= CHAN_NOT_SPECIFIED
) {
8810 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
8811 val
= AtapiRegCheckParameterValue(
8812 HwDeviceExtension
, namex
, Name
, val
);
8813 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
8814 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
8815 val
= AtapiRegCheckParameterValue(
8816 HwDeviceExtension
, namex
, Name
, val
);
8820 } // end AtapiRegCheckDevLunValue()
8833 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
8852 swprintf(Buffer
+j
, L
"%2.2x", a
);
8860 } // end EncodeVendorStr()
8864 AtapiRegCheckDevValue(
8865 IN PVOID HwDeviceExtension
,
8872 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8874 // WCHAR name1[11+4+5];
8875 // WCHAR name2[11+4+4+10];
8876 // WCHAR name3[11+4+4+5+20];
8877 // WCHAR name3[11+4+4+5+20+1];
8886 IN ULONG SlotNumber
;
8888 ULONG val
= Default
;
8890 KdPrint(( " Parameter %ws\n", Name
));
8892 if(deviceExtension
) {
8893 VendorID
= deviceExtension
->DevID
& 0xffff;
8894 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
8895 SlotNumber
= deviceExtension
->slotNumber
;
8899 SlotNumber
= 0xffffffff;
8902 val
= AtapiRegCheckDevLunValue(
8903 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
8905 if(deviceExtension
) {
8906 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
8908 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
8909 swprintf(namex
, L
"Parameters%s", namev
);
8910 val
= AtapiRegCheckDevLunValue(
8911 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8914 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
8915 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
8916 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
8918 swprintf(namex
, L
"Parameters%s", namev
);
8919 val
= AtapiRegCheckDevLunValue(
8920 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8922 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
8923 val
= AtapiRegCheckDevLunValue(
8924 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8926 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
8927 val
= AtapiRegCheckDevLunValue(
8928 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8930 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
8932 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
8933 swprintf(namex
, L
"Parameters%s", namev
);
8934 val
= AtapiRegCheckDevLunValue(
8935 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8937 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
8938 swprintf(namex
, L
"Parameters%s", namev
);
8939 val
= AtapiRegCheckDevLunValue(
8940 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8943 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
8945 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
8946 swprintf(namex
, L
"Parameters%s", namev
);
8947 val
= AtapiRegCheckDevLunValue(
8948 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8950 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
8951 swprintf(namex
, L
"Parameters%s", namev
);
8952 val
= AtapiRegCheckDevLunValue(
8953 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8958 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
8961 } // end AtapiRegCheckDevValue()
8964 The user must specify that Xxx is to run on the platform
8965 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
8966 Services\UniATA\Xxx:REG_DWORD:Zzz.
8968 The user can override the global setting to enable or disable Xxx on a
8969 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
8970 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
8972 If this registry value does not exist or contains the value zero then
8973 the timer to check for media change does not run.
8977 RegistryPath - pointer to the unicode string inside
8978 ...\CurrentControlSet\Services\UniATA
8979 DeviceNumber - The number of the HBA device object
8981 Returns: Registry Key value
8985 AtapiRegCheckParameterValue(
8986 IN PVOID HwDeviceExtension
,
8987 IN PCWSTR PathSuffix
,
8992 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
8994 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8996 LONG zero
= Default
;
8998 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
9001 LONG doRun
= Default
;
9003 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
9005 UNICODE_STRING paramPath
;
9007 // <SavedRegPath>\<PathSuffix> -> <Name>
9008 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
9009 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
9011 paramPath
.Length
= 0;
9012 paramPath
.MaximumLength
= RegistryPath
->Length
+
9013 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
9014 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
9015 if(!paramPath
.Buffer
) {
9016 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
9020 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
9021 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
9022 RtlAppendUnicodeToString(¶mPath
, L
"\\");
9023 RtlAppendUnicodeToString(¶mPath
, PathSuffix
);
9025 // Check for the Xxx value.
9026 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
9028 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
9029 parameters
[0].Name
= Name
;
9030 parameters
[0].EntryContext
= &doRun
;
9031 parameters
[0].DefaultType
= REG_DWORD
;
9032 parameters
[0].DefaultData
= &zero
;
9033 parameters
[0].DefaultLength
= sizeof(ULONG
);
9035 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
9036 paramPath
.Buffer
, parameters
, NULL
, NULL
);
9037 //KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
9039 ExFreePool(paramPath
.Buffer
);
9041 if(!NT_SUCCESS(status
)) {
9047 #undef ITEMS_TO_QUERY
9049 } // end AtapiRegCheckParameterValue()
9052 SCSI_ADAPTER_CONTROL_STATUS
9054 AtapiAdapterControl(
9055 IN PVOID HwDeviceExtension
,
9056 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
9060 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9061 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
9062 ULONG numberChannels
= deviceExtension
->NumberChannels
;
9066 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
9068 switch(ControlType
) {
9069 case ScsiQuerySupportedControlTypes
: {
9070 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
9071 TRUE
, // ScsiQuerySupportedControlTypes
9072 TRUE
, // ScsiStopAdapter
9073 TRUE
, // ScsiRestartAdapter
9074 FALSE
, // ScsiSetBootConfig
9075 FALSE
// ScsiSetRunningConfig
9078 ULONG lim
= ScsiAdapterControlMax
;
9081 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
9083 if(pControlTypeList
->MaxControlType
< lim
) {
9084 lim
= pControlTypeList
->MaxControlType
;
9087 for(i
= 0; i
< lim
; i
++) {
9088 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
9094 case ScsiStopAdapter
: {
9096 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
9097 // Shut down all interrupts on the adapter. They'll get re-enabled
9098 // by the initialization routines.
9099 for (c
= 0; c
< numberChannels
; c
++) {
9100 AtapiResetController(deviceExtension
, c
);
9101 AtapiDisableInterrupts(deviceExtension
, c
);
9103 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9104 // we must never get here for non-PCI
9105 status
= UniataDisconnectIntr2(HwDeviceExtension
);
9106 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
9110 case ScsiRestartAdapter
: {
9112 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
9113 // Enable all the interrupts on the adapter while port driver call
9114 // for power up an HBA that was shut down for power management
9116 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
9117 status
= UniataConnectIntr2(HwDeviceExtension
);
9118 for (c
= 0; c
< numberChannels
; c
++) {
9119 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
9120 FindDevices(HwDeviceExtension
, 0, c
);
9121 AtapiEnableInterrupts(deviceExtension
, c
);
9122 AtapiHwInitialize__(deviceExtension
, c
);
9124 if(deviceExtension
->Isr2DevObj
) {
9125 // we must never get here for non-PCI
9126 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9133 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
9134 return ScsiAdapterControlUnsuccessful
;
9138 return ScsiAdapterControlSuccess
;
9139 } // end AtapiAdapterControl()
9141 #endif //UNIATA_CORE
9160 UCHAR dbg_print_tmp_buff
[512];
9161 // UNICODE_STRING msgBuff;
9163 va_start(ap
, DebugMessage
);
9165 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
9167 dbg_print_tmp_buff
[511] = 0;
9169 HalDisplayString(dbg_print_tmp_buff
);
9173 } // end PrintNtConsole()