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
<200; i
++) {
497 GetStatus(chan
, Status
);
498 if (Status
& IDE_STATUS_BUSY
) {
499 AtapiStallExecution(10);
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
<200; i
++) {
541 GetBaseStatus(chan
, Status
);
542 if (Status
& IDE_STATUS_BUSY
) {
543 AtapiStallExecution(10);
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(10);
644 } else if (Status
& IDE_STATUS_DRQ
) {
647 AtapiStallExecution(10);
651 } // end WaitForDrq()
661 for (i
=0; i
<2; i
++) {
662 GetStatus(chan
, Status
);
663 if (Status
& IDE_STATUS_BUSY
) {
664 AtapiStallExecution(10);
665 } else if (Status
& IDE_STATUS_DRQ
) {
668 AtapiStallExecution(10);
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 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
695 AtapiStallExecution(30);
697 SelectDrive(chan
, DeviceNumber
);
699 GetBaseStatus(chan
, statusByte2
);
700 AtapiStallExecution(500);
702 GetBaseStatus(chan
, statusByte2
);
703 if(chan
&& chan
->DeviceExtension
) {
704 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
705 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
707 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
709 if(dma_status
& BM_STATUS_INTR
) {
710 // bullshit, we have DMA interrupt, but had never initiate DMA operation
711 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
712 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
713 GetBaseStatus(chan
, statusByte2
);
715 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
716 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
720 } // end AtapiSoftReset()
723 Send command to device.
724 Translate to 48-Lba form if required
729 IN PHW_DEVICE_EXTENSION deviceExtension
,
730 IN ULONG DeviceNumber
,
739 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
741 ULONG ldev
= lChannel
*2 + DeviceNumber
;
745 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
746 deviceExtension
->DevIndex
, deviceExtension
->Channel
, ldev
, command
, lba
, count
, feature
));
748 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
749 SelectDrive(chan
, DeviceNumber
);
751 statusByte
= WaitOnBusy(chan
);
753 /* ready to issue command ? */
754 if (statusByte
& IDE_STATUS_BUSY
) {
755 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
759 // !!! We should not check ERROR condition here
760 // ERROR bit may be asserted durring previous operation
761 // and not cleared after SELECT
763 //>>>>>> NV: 2006/08/03
764 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
765 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
766 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
767 return IDE_STATUS_ERROR
;
768 //return SRB_STATUS_ERROR;
770 //<<<<<< NV: 2006/08/03
772 /* only use 48bit addressing if needed because of the overhead */
773 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
774 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
776 KdPrint2((PRINT_PREFIX
" ldev %#x USE_LBA_48\n", ldev
));
777 /* translate command into 48bit version */
778 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
779 command
= AtaCommands48
[command
];
781 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
785 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
788 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
789 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
790 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
791 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
792 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
793 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
794 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
795 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
796 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
797 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
799 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
800 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
803 plba
= (PUCHAR
)&lba
; //ktp
804 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
807 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
808 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
810 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
811 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
812 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
813 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
814 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
815 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
816 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
818 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
819 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
823 // write command code to device
824 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
829 // caller requested wait for interrupt
832 statusByte
= WaitForDrq(chan
);
833 if (statusByte
& IDE_STATUS_DRQ
)
835 AtapiStallExecution(500);
836 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
843 // caller requested wait for entering Wait state
844 for (i
=0; i
<30 * 1000; i
++) {
846 GetStatus(chan
, statusByte
);
847 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
848 if(statusByte
== 0xff) {
852 if(statusByte
& IDE_STATUS_ERROR
) {
855 if(statusByte
& IDE_STATUS_BUSY
) {
856 AtapiStallExecution(100);
859 if(statusByte
== IDE_STATUS_IDLE
) {
862 //if(deviceExtension->HwFlags & UNIATA_SATA) {
863 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
866 AtapiStallExecution(100);
869 //statusByte |= IDE_STATUS_BUSY;
873 statusByte
= WaitOnBusyLong(chan
);
875 case ATA_WAIT_BASE_READY
:
876 statusByte
= WaitOnBaseBusyLong(chan
);
879 GetStatus(chan
, statusByte
);
880 if (statusByte
& IDE_STATUS_ERROR
) {
881 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
882 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
885 KdPrint2((PRINT_PREFIX
" try to continue\n"));
886 statusByte
&= ~IDE_STATUS_ERROR
;
888 chan
->ExpectingInterrupt
= TRUE
;
890 InterlockedExchange(&(chan
->CheckIntr
),
896 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
899 } // end AtaCommand48()
902 Send command to device.
903 This is simply wrapper for AtaCommand48()
908 IN PHW_DEVICE_EXTENSION deviceExtension
,
909 IN ULONG DeviceNumber
,
920 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
922 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
923 count
, feature
, flags
);
924 } // end AtaCommand()
928 AtaPio2Mode(LONG pio
)
931 default: return ATA_PIO
;
932 case 0: return ATA_PIO0
;
933 case 1: return ATA_PIO1
;
934 case 2: return ATA_PIO2
;
935 case 3: return ATA_PIO3
;
936 case 4: return ATA_PIO4
;
937 case 5: return ATA_PIO5
;
939 } // end AtaPio2Mode()
943 AtaPioMode(PIDENTIFY_DATA2 ident
)
945 if (ident
->PioTimingsValid
) {
946 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
948 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
950 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
953 if (ident
->PioCycleTimingMode
== 2)
955 if (ident
->PioCycleTimingMode
== 1)
957 if (ident
->PioCycleTimingMode
== 0)
960 } // end AtaPioMode()
964 AtaWmode(PIDENTIFY_DATA2 ident
)
966 if (ident
->MultiWordDMASupport
& 0x04)
968 if (ident
->MultiWordDMASupport
& 0x02)
970 if (ident
->MultiWordDMASupport
& 0x01)
977 AtaUmode(PIDENTIFY_DATA2 ident
)
979 if (!ident
->UdmaModesValid
)
981 if (ident
->UltraDMASupport
& 0x40)
983 if (ident
->UltraDMASupport
& 0x20)
985 if (ident
->UltraDMASupport
& 0x10)
987 if (ident
->UltraDMASupport
& 0x08)
989 if (ident
->UltraDMASupport
& 0x04)
991 if (ident
->UltraDMASupport
& 0x02)
993 if (ident
->UltraDMASupport
& 0x01)
1004 IN PVOID HwDeviceExtension
1007 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1008 PHW_TIMER HwScsiTimer
;
1010 ULONG MiniportTimerValue
;
1011 BOOLEAN recall
= FALSE
;
1015 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1017 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1018 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1019 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1022 chan
= &deviceExtension
->chan
[lChannel
];
1026 HwScsiTimer
= chan
->HwScsiTimer
;
1027 chan
->HwScsiTimer
= NULL
;
1029 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1030 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1034 HwScsiTimer(HwDeviceExtension
);
1036 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1038 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1039 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1040 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1041 deviceExtension
->FirstDpcChan
=
1042 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1046 KeQuerySystemTime(&time
);
1047 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1049 chan
= &deviceExtension
->chan
[lChannel
];
1050 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1052 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1053 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1060 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1061 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1062 if(!MiniportTimerValue
)
1063 MiniportTimerValue
= 1;
1065 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1066 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1073 } // end AtapiTimerDpc()
1076 Wrapper for ScsiPort, that implements smart Dpc
1077 queueing. We need it to allow parallel functioning
1078 of IDE channles with shared interrupt. Standard Dpc mechanism
1079 cancels previous Dpc request (if any), but we need Dpc queue.
1084 IN PVOID HwDeviceExtension
,
1086 IN PHW_TIMER HwScsiTimer
,
1087 IN ULONG MiniportTimerValue
1090 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1092 LARGE_INTEGER time2
;
1094 PHW_CHANNEL prev_chan
;
1096 // BOOLEAN UseRequestTimerCall = TRUE;
1098 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1099 KeQuerySystemTime(&time
);
1101 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1102 time
.QuadPart
+= MiniportTimerValue
*10;
1103 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1105 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1107 i
= deviceExtension
->FirstDpcChan
;
1108 chan
= prev_chan
= NULL
;
1109 while(i
!= CHAN_NOT_SPECIFIED
) {
1111 chan
= &deviceExtension
->chan
[i
];
1112 if(chan
->DpcTime
> time
.QuadPart
) {
1115 i
= chan
->NextDpcChan
;
1117 chan
= &deviceExtension
->chan
[lChannel
];
1119 deviceExtension
->FirstDpcChan
= lChannel
;
1121 prev_chan
->NextDpcChan
= lChannel
;
1123 chan
->NextDpcChan
= i
;
1124 chan
->HwScsiTimer
= HwScsiTimer
;
1125 chan
->DpcTime
= time
.QuadPart
;
1127 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1128 if(time
.QuadPart
<= time2
.QuadPart
) {
1129 MiniportTimerValue
= 1;
1131 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1134 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1135 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1137 MiniportTimerValue
);
1139 } // end AtapiQueueTimerDpc()
1141 #endif //UNIATA_CORE
1150 UCHAR statusByteAlt
;
1152 GetStatus(chan
, statusByteAlt
);
1153 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1155 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1156 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1157 KdPrint2((PRINT_PREFIX
1158 " Reg_%#x (%#x) = %#x\n",
1160 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1163 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1164 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1165 KdPrint2((PRINT_PREFIX
1166 " BM_%#x (%#x) = %#x\n",
1168 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1172 } // end UniataDumpATARegs()
1176 Routine Description:
1178 Issue IDENTIFY command to a device.
1182 HwDeviceExtension - HBA miniport driver's adapter data storage
1183 DeviceNumber - Indicates which device.
1184 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1188 TRUE if all goes well.
1194 IN PVOID HwDeviceExtension
,
1195 IN ULONG DeviceNumber
,
1201 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1202 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1203 ULONG waitCount
= 50000;
1209 BOOLEAN atapiDev
= FALSE
;
1210 ULONG ldev
= (lChannel
* 2) + DeviceNumber
;
1211 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
1213 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1214 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1217 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1218 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1222 SelectDrive(chan
, DeviceNumber
);
1223 AtapiStallExecution(10);
1224 statusByte
= WaitOnBusyLong(chan
);
1225 // Check that the status register makes sense.
1226 GetBaseStatus(chan
, statusByte2
);
1228 UniataDumpATARegs(chan
);
1230 if (Command
== IDE_COMMAND_IDENTIFY
) {
1231 // Mask status byte ERROR bits.
1232 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1233 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1234 // Check if register value is reasonable.
1236 if(statusByte
!= IDE_STATUS_IDLE
) {
1238 // No reset here !!!
1239 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1241 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1242 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1243 SelectDrive(chan
, DeviceNumber
);
1244 WaitOnBusyLong(chan
);
1246 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1247 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1249 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1250 signatureHigh
== ATAPI_MAGIC_MSB
) {
1252 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (ldev %d)\n", ldev
));
1256 // We really should wait up to 31 seconds
1257 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1258 // (30 seconds for device 1)
1260 // Wait for Busy to drop.
1261 AtapiStallExecution(100);
1262 GetStatus(chan
, statusByte
);
1264 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1265 GetBaseStatus(chan
, statusByte2
);
1267 SelectDrive(chan
, DeviceNumber
);
1269 GetBaseStatus(chan
, statusByte2
);
1271 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1273 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1274 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1276 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1277 signatureHigh
== ATAPI_MAGIC_MSB
) {
1278 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev
));
1283 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1284 if (statusByte
!= IDE_STATUS_IDLE
) {
1286 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (ldev %d)\n", ldev
));
1291 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1292 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1293 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1294 statusByte
= WaitForIdleLong(chan
);
1295 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1300 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1301 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1306 for (; j
< 4*2; j
++) {
1307 // Send IDENTIFY command.
1308 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1311 if (statusByte
& IDE_STATUS_DRQ
) {
1312 // Read status to acknowledge any interrupts generated.
1313 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1314 GetBaseStatus(chan
, statusByte
);
1315 // One last check for Atapi.
1316 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1317 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1319 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1320 signatureHigh
== ATAPI_MAGIC_MSB
) {
1321 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev
));
1327 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1328 if (Command
== IDE_COMMAND_IDENTIFY
) {
1329 // Check the signature. If DRQ didn't come up it's likely Atapi.
1330 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1331 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1333 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1334 signatureHigh
== ATAPI_MAGIC_MSB
) {
1336 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev
));
1340 // Device didn't respond correctly. It will be given one more chances.
1341 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1342 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1343 GetBaseStatus(chan
, statusByte
);
1344 AtapiSoftReset(chan
,DeviceNumber
);
1346 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1347 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1349 GetBaseStatus(chan
, statusByte
);
1350 //GetStatus(chan, statusByte);
1351 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1354 // Check for error on really stupid master devices that assert random
1355 // patterns of bits in the status register at the slave address.
1356 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1357 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1361 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1362 // Suck out 256 words. After waiting for one model that asserts busy
1363 // after receiving the Packet Identify command.
1364 statusByte
= WaitForDrq(chan
);
1365 statusByte
= WaitOnBusyLong(chan
);
1366 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1368 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1369 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1370 GetBaseStatus(chan
, statusByte
);
1373 GetBaseStatus(chan
, statusByte
);
1374 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1376 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1378 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1382 // ATI/SII chipsets with memory-mapped IO hangs when
1383 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1384 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1385 KdPrint2((PRINT_PREFIX
1386 " IO_%#x (%#x), %s:\n",
1388 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1389 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1390 for(i
=0; i
<256; i
++) {
1392 KdPrint2((PRINT_PREFIX
1395 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1397 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1398 KdPrint2((PRINT_PREFIX
1400 AtapiStallExecution(1);
1401 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1404 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1406 // Work around for some IDE and one model Atapi that will present more than
1407 // 256 bytes for the Identify data.
1408 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1409 statusByte
= AtapiSuckPort2(chan
);
1411 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1412 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1415 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1416 statusByte
= WaitForDrq(chan
);
1417 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1418 GetBaseStatus(chan
, statusByte
);
1420 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1423 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1427 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1428 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1429 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1430 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1431 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1432 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1434 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1435 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1436 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1437 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1439 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1441 // Check out a few capabilities / limitations of the device.
1442 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1443 // Determine if this drive supports the MSN functions.
1444 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1446 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1447 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1449 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1450 // Determine max. block transfer for this device.
1451 LunExt
->MaximumBlockXfer
=
1452 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1454 LunExt
->NumOfSectors
= 0;
1455 if (Command
== IDE_COMMAND_IDENTIFY
) {
1456 ULONGLONG NumOfSectors
=0;
1457 ULONGLONG NativeNumOfSectors
=0;
1458 ULONGLONG cylinders
=0;
1459 ULONGLONG tmp_cylinders
=0;
1460 // Read very-old-style drive geometry
1461 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1462 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1463 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1464 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1466 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1467 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1468 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1469 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1470 // Check for HDDs > 8Gb
1471 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1472 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1473 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1474 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1476 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1477 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1478 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1480 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1482 NumOfSectors
= cylinders
*
1483 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1484 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1486 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1490 // Check for LBA mode
1491 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1492 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1493 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1494 if ( deviceExtension
->FullIdentifyData
.SupportLba
1496 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1497 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1498 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1499 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1500 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1502 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1503 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1504 goto skip_lba_staff
;
1506 // Check for LBA48 support
1507 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1508 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1509 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1510 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1512 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1514 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1515 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1516 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1518 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1520 NativeNumOfSectors
= cylinders
*
1521 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1522 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1524 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1526 if(NativeNumOfSectors
> NumOfSectors
) {
1527 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1528 NumOfSectors
= NativeNumOfSectors
;
1532 // Check drive capacity report for LBA48-capable drives.
1533 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1534 ULONG hNativeNumOfSectors
;
1535 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1537 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1538 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1540 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1541 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1542 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1543 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1545 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1548 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1549 NativeNumOfSectors
|=
1550 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1551 hNativeNumOfSectors
=
1552 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1553 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1554 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1556 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1558 // Some drives report LBA48 capability while has capacity below 128Gb
1559 // Probably they support large block-counters.
1560 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1561 // Here we check this
1562 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1563 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1565 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1566 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1568 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1569 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1570 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1571 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1572 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1573 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1574 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1578 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1579 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1580 NativeNumOfSectors
= 0;
1584 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1585 NativeNumOfSectors
> NumOfSectors
) {
1587 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1588 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1590 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1591 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1592 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1593 NumOfSectors
= NativeNumOfSectors
;
1599 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1600 // check for native LBA size
1601 // some drives report ~32Gb in Identify Block
1602 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1604 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1605 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1607 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1608 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1609 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1610 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1611 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1613 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1615 if(NativeNumOfSectors
> NumOfSectors
) {
1617 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1618 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1620 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1621 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1622 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1623 NumOfSectors
= NativeNumOfSectors
;
1629 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1631 // fill IdentifyData with bogus geometry
1632 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1633 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1634 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1635 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1636 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1637 // ok, we can keep original values
1638 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1639 LunExt
->opt_GeomType
= GEOM_ORIG
;
1642 tmp_cylinders
= NumOfSectors
/ (255*63);
1643 if(tmp_cylinders
< 0xffff) {
1644 // we can use generic values for H/S for generic geometry approach
1645 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1646 LunExt
->opt_GeomType
= GEOM_STD
;
1649 // we should use UNIATA geometry approach
1650 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1651 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1655 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1657 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1658 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1659 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1661 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1662 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1664 cylinders
= NumOfSectors
/ (255*63);
1665 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1667 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1668 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1670 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1671 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1672 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1674 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1676 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1677 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1678 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1680 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1682 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1683 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1684 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1686 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1688 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1689 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1690 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1692 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1693 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1694 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1697 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1698 cylinders
= tmp_cylinders
;
1700 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1701 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1705 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1706 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1707 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1709 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1710 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1711 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1713 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1714 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1715 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1719 LunExt
->NumOfSectors
= NumOfSectors
;
1720 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1721 deviceExtension->FullIdentifyData.DoubleWordIo) {
1722 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1726 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1727 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1729 InitBadBlocks(LunExt
);
1731 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1732 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1734 // This device interrupts with the assertion of DRQ after receiving
1735 // Atapi Packet Command
1736 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1737 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1740 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1743 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1745 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1747 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1748 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1750 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1751 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1752 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1753 // set CD default costs
1754 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1755 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1756 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1757 statusByte
= WaitForDrq(chan
);
1759 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1760 LunExt
->IdentifyData
.DeviceType
));
1763 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1766 GetBaseStatus(chan
, statusByte
);
1767 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1770 } // end IssueIdentify()
1775 Routine Description:
1776 Set drive parameters using the IDENTIFY data.
1779 HwDeviceExtension - HBA miniport driver's adapter data storage
1780 DeviceNumber - Indicates which device.
1783 TRUE if all goes well.
1789 IN PVOID HwDeviceExtension
,
1790 IN ULONG DeviceNumber
,
1794 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1795 PIDENTIFY_DATA2 identifyData
= &deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].IdentifyData
;
1800 if(deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].DeviceFlags
&
1801 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1804 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1805 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1807 // Send SET PARAMETER command.
1808 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1809 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1810 (identifyData
->NumberOfHeads
- 1), 0,
1811 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1813 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1814 if(statusByte
& IDE_STATUS_ERROR
) {
1815 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1816 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1817 errorByte
, statusByte
));
1821 if(statusByte
== IDE_STATUS_IDLE
) {
1827 } // end SetDriveParameters()
1832 PHW_LU_EXTENSION LunExt
1835 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
1836 } // end UniataForgetDevice()
1841 Routine Description:
1842 Reset IDE controller and/or Atapi device.
1845 HwDeviceExtension - HBA miniport driver's adapter data storage
1854 AtapiResetController(
1855 IN PVOID HwDeviceExtension
,
1859 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1860 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1861 } // end AtapiResetController()
1866 AtapiResetController__(
1867 IN PVOID HwDeviceExtension
,
1869 IN BOOLEAN CompleteType
1872 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1873 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1874 PHW_CHANNEL chan
= NULL
;
1878 PSCSI_REQUEST_BLOCK CurSrb
;
1879 ULONG ChannelCtrlFlags
;
1880 UCHAR dma_status
= 0;
1882 ULONG slotNumber
= deviceExtension
->slotNumber
;
1883 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1884 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1886 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1888 //ULONG RevID = deviceExtension->RevID;
1889 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1893 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1895 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
1896 // we shall reset both channels on SimplexOnly devices,
1897 // It's not worth doing so on normal controllers
1899 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
1902 numberChannels
= deviceExtension
->NumberChannels
;
1905 for (; j
< numberChannels
; j
++) {
1907 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
1908 chan
= &deviceExtension
->chan
[j
];
1909 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
1910 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
1911 if(CompleteType
!= RESET_COMPLETE_NONE
) {
1913 while((CurSrb
= UniataGetCurRequest(chan
))) {
1915 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
1917 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
1918 // Check and see if we are processing an internal srb
1919 if (AtaReq
->OriginalSrb
) {
1920 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
1921 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
1922 AtaReq
->OriginalSrb
= NULL
;
1923 // NOTE: internal SRB doesn't get to SRB queue !!!
1924 CurSrb
= AtaReq
->Srb
;
1927 // Remove current request from queue
1928 UniataRemoveRequest(chan
, CurSrb
);
1930 // Check if request is in progress.
1931 ASSERT(AtaReq
->Srb
== CurSrb
);
1933 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1934 UCHAR PathId
= CurSrb
->PathId
;
1935 UCHAR TargetId
= CurSrb
->TargetId
;
1936 UCHAR Lun
= CurSrb
->Lun
;
1938 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
1939 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
1941 if (CurSrb
->SenseInfoBuffer
) {
1943 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
1945 senseBuffer
->ErrorCode
= 0x70;
1946 senseBuffer
->Valid
= 1;
1947 senseBuffer
->AdditionalSenseLength
= 0xb;
1948 if(CompleteType
== RESET_COMPLETE_ALL
) {
1949 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1950 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
1951 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
1952 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
1954 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1955 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
1956 senseBuffer
->AdditionalSenseCode
= 0;
1957 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
1961 // Clear request tracking fields.
1962 AtaReq
->WordsLeft
= 0;
1963 AtaReq
->DataBuffer
= NULL
;
1964 AtaReq
->TransferLength
= 0;
1966 ScsiPortNotification(RequestComplete
,
1970 // Indicate ready for next request.
1971 ScsiPortNotification(NextLuRequest
,
1977 if(CompleteType
!= RESET_COMPLETE_ALL
)
1980 #endif //UNIATA_CORE
1981 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1983 // Save control flags
1984 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
1985 // Clear expecting interrupt flag.
1986 chan
->ExpectingInterrupt
= FALSE
;
1988 chan
->ChannelCtrlFlags
= 0;
1989 InterlockedExchange(&(chan
->CheckIntr
),
1993 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
1994 AtapiDisableInterrupts(deviceExtension
, j
);
1995 KdPrint2((PRINT_PREFIX
" done\n"));
1997 case ATA_INTEL_ID
: {
2000 if(!(ChipFlags
& UNIATA_SATA
))
2002 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2006 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2007 if(ChipFlags
& UNIATA_AHCI
) {
2010 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2011 GetPciConfig1(0x90, tmp8
);
2018 ChangePciConfig2(0x92, a
& ~mask
);
2019 AtapiStallExecution(10);
2020 ChangePciConfig2(0x92, a
| mask
);
2023 AtapiStallExecution(10000);
2024 GetPciConfig2(0x92, tmp16
);
2025 if ((tmp16
& (mask
<< 4)) == (mask
<< 4)) {
2026 AtapiStallExecution(10000);
2032 case ATA_NVIDIA_ID
: {
2033 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2034 if(!(ChipFlags
& UNIATA_SATA
))
2037 case ATA_SILICON_IMAGE_ID
: {
2039 ULONG Channel
= deviceExtension
->Channel
+ j
;
2040 if(!(ChipFlags
& UNIATA_SATA
))
2042 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2043 /* disable PHY state change interrupt */
2044 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2046 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2048 /* reset controller part for this channel */
2049 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2050 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2051 AtapiStallExecution(1000);
2052 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2053 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2057 case ATA_PROMISE_ID
: {
2060 if(ChipFlags
& UNIATA_SATA
) {
2061 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2062 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2065 KdPrint2((PRINT_PREFIX
" send reset\n"));
2066 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2067 IDE_DC_RESET_CONTROLLER
);
2068 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2069 AtapiStallExecution(10000);
2070 // Disable interrupts
2071 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2072 AtapiDisableInterrupts(deviceExtension
, j
);
2073 AtapiStallExecution(100);
2074 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2075 AtapiEnableInterrupts(deviceExtension
, j
);
2076 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2077 AtapiStallExecution(100000);
2078 KdPrint2((PRINT_PREFIX
" done\n"));
2083 //if(!(ChipFlags & UNIATA_SATA)) {
2084 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2085 // Reset DMA engine if active
2086 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2087 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2088 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2089 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2090 (dma_status
& BM_STATUS_INTR
)) {
2091 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2095 // all these shall be performed inside AtapiHwInitialize__() ?
2097 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2098 // Do special processing for ATAPI and IDE disk devices.
2099 for (i
= 0; i
< max_ldev
; i
++) {
2101 // Check if device present.
2102 if (!(deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2106 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2107 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2110 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2114 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2115 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2116 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2121 SelectDrive(chan
, i
);
2122 AtapiStallExecution(10);
2123 statusByte
= WaitOnBusyLong(chan
);
2124 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2125 if(statusByte
== 0xff) {
2126 KdPrint2((PRINT_PREFIX
2127 "no drive, status %#x\n",
2129 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2131 // Check for ATAPI disk.
2132 if (deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2133 // Issue soft reset and issue identify.
2134 GetStatus(chan
, statusByte
);
2135 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2138 AtapiDisableInterrupts(deviceExtension
, j
);
2139 AtapiSoftReset(chan
, i
);
2140 AtapiEnableInterrupts(deviceExtension
, j
);
2142 GetStatus(chan
, statusByte
);
2144 if(statusByte
== IDE_STATUS_SUCCESS
) {
2146 IssueIdentify(HwDeviceExtension
,
2148 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2151 KdPrint2((PRINT_PREFIX
2152 "AtapiResetController: Status after soft reset %#x\n",
2155 GetBaseStatus(chan
, statusByte
);
2158 // Issue identify and reinit after channel reset.
2160 if (statusByte
!= IDE_STATUS_IDLE
&&
2161 statusByte
!= IDE_STATUS_SUCCESS
&&
2162 statusByte
!= IDE_STATUS_DRDY
) {
2164 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2166 if(!IssueIdentify(HwDeviceExtension
,
2168 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2170 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2172 // Set disk geometry parameters.
2173 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2174 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2176 GetBaseStatus(chan
, statusByte
);
2178 // force DMA mode reinit
2179 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
|= DFLAGS_REINIT_DMA
;
2183 // Enable interrupts, note, the we can have here recursive disable
2184 AtapiStallExecution(10);
2185 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2187 chan
->DisableIntr
));
2188 AtapiEnableInterrupts(deviceExtension
, j
);
2190 // Call the HwInitialize routine to setup multi-block.
2191 AtapiHwInitialize__(deviceExtension
, j
);
2193 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2197 } // end AtapiResetController__()
2202 Routine Description:
2203 This routine maps ATAPI and IDE errors to specific SRB statuses.
2206 HwDeviceExtension - HBA miniport driver's adapter data storage
2207 Srb - IO request packet
2216 IN PVOID HwDeviceExtension
,
2217 IN PSCSI_REQUEST_BLOCK Srb
2220 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2221 ULONG lChannel
= GET_CHANNEL(Srb
);
2222 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2225 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2227 ULONG ldev
= GET_LDEV(Srb
);
2229 // Read the error register.
2231 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2232 KdPrint2((PRINT_PREFIX
2233 "MapError: Error register is %#x\n",
2236 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2238 switch (errorByte
>> 4) {
2239 case SCSI_SENSE_NO_SENSE
:
2241 KdPrint2((PRINT_PREFIX
2242 "ATAPI: No sense information\n"));
2243 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2244 srbStatus
= SRB_STATUS_ERROR
;
2247 case SCSI_SENSE_RECOVERED_ERROR
:
2249 KdPrint2((PRINT_PREFIX
2250 "ATAPI: Recovered error\n"));
2252 srbStatus
= SRB_STATUS_SUCCESS
;
2255 case SCSI_SENSE_NOT_READY
:
2257 KdPrint2((PRINT_PREFIX
2258 "ATAPI: Device not ready\n"));
2259 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2260 srbStatus
= SRB_STATUS_ERROR
;
2263 case SCSI_SENSE_MEDIUM_ERROR
:
2265 KdPrint2((PRINT_PREFIX
2266 "ATAPI: Media error\n"));
2267 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2268 srbStatus
= SRB_STATUS_ERROR
;
2271 case SCSI_SENSE_HARDWARE_ERROR
:
2273 KdPrint2((PRINT_PREFIX
2274 "ATAPI: Hardware error\n"));
2275 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2276 srbStatus
= SRB_STATUS_ERROR
;
2279 case SCSI_SENSE_ILLEGAL_REQUEST
:
2281 KdPrint2((PRINT_PREFIX
2282 "ATAPI: Illegal request\n"));
2283 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2284 srbStatus
= SRB_STATUS_ERROR
;
2287 case SCSI_SENSE_UNIT_ATTENTION
:
2289 KdPrint2((PRINT_PREFIX
2290 "ATAPI: Unit attention\n"));
2291 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2292 srbStatus
= SRB_STATUS_ERROR
;
2295 case SCSI_SENSE_DATA_PROTECT
:
2297 KdPrint2((PRINT_PREFIX
2298 "ATAPI: Data protect\n"));
2299 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2300 srbStatus
= SRB_STATUS_ERROR
;
2303 case SCSI_SENSE_BLANK_CHECK
:
2305 KdPrint2((PRINT_PREFIX
2306 "ATAPI: Blank check\n"));
2307 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2308 srbStatus
= SRB_STATUS_ERROR
;
2311 case SCSI_SENSE_ABORTED_COMMAND
:
2312 KdPrint2((PRINT_PREFIX
2313 "Atapi: Command Aborted\n"));
2314 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2315 srbStatus
= SRB_STATUS_ERROR
;
2320 KdPrint2((PRINT_PREFIX
2321 "ATAPI: Invalid sense information\n"));
2323 srbStatus
= SRB_STATUS_ERROR
;
2331 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2332 chan
->ReturningMediaStatus
= errorByte
;
2334 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2335 KdPrint2((PRINT_PREFIX
2336 "IDE: Media change\n"));
2337 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2338 srbStatus
= SRB_STATUS_ERROR
;
2340 if (Srb
->SenseInfoBuffer
) {
2342 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2344 senseBuffer
->ErrorCode
= 0x70;
2345 senseBuffer
->Valid
= 1;
2346 senseBuffer
->AdditionalSenseLength
= 0xb;
2347 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2348 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2349 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2351 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2354 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2355 KdPrint2((PRINT_PREFIX
2356 "IDE: Command abort\n"));
2357 srbStatus
= SRB_STATUS_ABORTED
;
2358 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2360 if (Srb
->SenseInfoBuffer
) {
2362 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2364 senseBuffer
->ErrorCode
= 0x70;
2365 senseBuffer
->Valid
= 1;
2366 senseBuffer
->AdditionalSenseLength
= 0xb;
2367 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2368 senseBuffer
->AdditionalSenseCode
= 0;
2369 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2371 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2374 deviceExtension
->lun
[ldev
].ErrorCount
++;
2376 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2378 KdPrint2((PRINT_PREFIX
2379 "IDE: End of media\n"));
2380 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2381 srbStatus
= SRB_STATUS_ERROR
;
2383 if (Srb
->SenseInfoBuffer
) {
2385 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2387 senseBuffer
->ErrorCode
= 0x70;
2388 senseBuffer
->Valid
= 1;
2389 senseBuffer
->AdditionalSenseLength
= 0xb;
2390 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2391 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2392 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2393 senseBuffer
->EndOfMedia
= 1;
2395 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2398 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2399 deviceExtension
->lun
[ldev
].ErrorCount
++;
2402 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2404 KdPrint2((PRINT_PREFIX
2405 "IDE: Illegal length\n"));
2406 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2408 if (Srb
->SenseInfoBuffer
) {
2410 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2412 senseBuffer
->ErrorCode
= 0x70;
2413 senseBuffer
->Valid
= 1;
2414 senseBuffer
->AdditionalSenseLength
= 0xb;
2415 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2416 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2417 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2418 senseBuffer
->IncorrectLength
= 1;
2420 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2423 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2425 KdPrint2((PRINT_PREFIX
2426 "IDE: Bad block\n"));
2427 srbStatus
= SRB_STATUS_ERROR
;
2428 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2429 if (Srb
->SenseInfoBuffer
) {
2431 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2433 senseBuffer
->ErrorCode
= 0x70;
2434 senseBuffer
->Valid
= 1;
2435 senseBuffer
->AdditionalSenseLength
= 0xb;
2436 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2437 senseBuffer
->AdditionalSenseCode
= 0;
2438 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2440 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2443 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2445 KdPrint2((PRINT_PREFIX
2446 "IDE: Id not found\n"));
2447 srbStatus
= SRB_STATUS_ERROR
;
2448 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2450 if (Srb
->SenseInfoBuffer
) {
2452 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2454 senseBuffer
->ErrorCode
= 0x70;
2455 senseBuffer
->Valid
= 1;
2456 senseBuffer
->AdditionalSenseLength
= 0xb;
2457 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2458 senseBuffer
->AdditionalSenseCode
= 0;
2459 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2461 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2464 deviceExtension
->lun
[ldev
].ErrorCount
++;
2466 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2468 KdPrint2((PRINT_PREFIX
2469 "IDE: Media change\n"));
2470 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2471 srbStatus
= SRB_STATUS_ERROR
;
2473 if (Srb
->SenseInfoBuffer
) {
2475 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2477 senseBuffer
->ErrorCode
= 0x70;
2478 senseBuffer
->Valid
= 1;
2479 senseBuffer
->AdditionalSenseLength
= 0xb;
2480 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2481 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2482 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2484 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2487 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2489 KdPrint2((PRINT_PREFIX
2490 "IDE: Data error\n"));
2491 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2492 srbStatus
= SRB_STATUS_ERROR
;
2494 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2495 deviceExtension
->lun
[ldev
].ErrorCount
++;
2498 // Build sense buffer
2499 if (Srb
->SenseInfoBuffer
) {
2501 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2503 senseBuffer
->ErrorCode
= 0x70;
2504 senseBuffer
->Valid
= 1;
2505 senseBuffer
->AdditionalSenseLength
= 0xb;
2506 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2507 senseBuffer
->AdditionalSenseCode
= 0;
2508 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2510 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2514 if (deviceExtension
->lun
[ldev
].ErrorCount
>= MAX_ERRORS
) {
2515 // deviceExtension->DWordIO = FALSE;
2517 KdPrint2((PRINT_PREFIX
2518 "MapError: ErrorCount >= MAX_ERRORS\n"));
2520 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2521 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2524 KdPrint2((PRINT_PREFIX
2525 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2528 KdPrint2((PRINT_PREFIX
2529 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2538 ScsiPortLogError( HwDeviceExtension
,
2546 // Reprogram to not use Multi-sector.
2549 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2550 !(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2552 statusByte
= AtaCommand(deviceExtension
, ldev
& 0x1, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2554 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2555 // command was aborted.
2556 if (statusByte
& IDE_STATUS_ERROR
) {
2558 // Read the error register.
2559 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2561 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2565 // Adjust the devExt. value, if necessary.
2566 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2574 // Set SCSI status to indicate a check condition.
2575 Srb
->ScsiStatus
= scsiStatus
;
2584 Routine Description:
2587 HwDeviceExtension - HBA miniport driver's adapter data storage
2590 TRUE - if initialization successful.
2591 FALSE - if initialization unsuccessful.
2597 IN PVOID HwDeviceExtension
2600 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2601 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2604 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2606 if(WinVer_WDM_Model
) {
2607 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2610 /* do extra chipset specific setups */
2611 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2613 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2614 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2615 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2618 for (c
= 0; c
< numberChannels
; c
++) {
2619 AtapiHwInitialize__(deviceExtension
, c
);
2621 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2623 } // end AtapiHwInitialize()
2627 AtapiHwInitialize__(
2628 IN PHW_DEVICE_EXTENSION deviceExtension
,
2633 UCHAR statusByte
, errorByte
;
2634 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2635 PHW_LU_EXTENSION LunExt
;
2637 ULONG PreferedMode
= 0xffffffff;
2639 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2640 FindDevices(deviceExtension
, 0, lChannel
);
2642 for (i
= lChannel
*2; i
< (lChannel
+1)*2; i
++) {
2644 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2646 LunExt
= &(deviceExtension
->lun
[i
]);
2648 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2652 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2653 AtapiStallExecution(1);
2655 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2657 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2658 // Enable media status notification
2659 IdeMediaStatus(TRUE
,deviceExtension
,(UCHAR
)i
);
2661 // If supported, setup Multi-block transfers.
2662 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2663 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2664 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2666 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2667 // command was aborted.
2668 if (statusByte
& IDE_STATUS_ERROR
) {
2670 // Read the error register.
2671 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2673 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2677 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2678 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2679 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2681 if (statusByte
& IDE_STATUS_ERROR
) {
2682 // Read the error register.
2683 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2685 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2689 // Adjust the devExt. value, if necessary.
2690 LunExt
->MaximumBlockXfer
= 0;
2693 KdPrint2((PRINT_PREFIX
2694 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2696 LunExt
->MaximumBlockXfer
));
2699 if(LunExt
->IdentifyData
.MajorRevision
) {
2701 if(LunExt
->opt_ReadCacheEnable
) {
2702 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2703 // If supported, setup read/write cacheing
2704 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2705 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2706 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2708 // Check for errors.
2709 if (statusByte
& IDE_STATUS_ERROR
) {
2710 KdPrint2((PRINT_PREFIX
2711 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2713 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2715 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2718 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2719 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2720 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2721 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2722 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2724 if(LunExt
->opt_WriteCacheEnable
) {
2725 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2726 // If supported & allowed, setup write cacheing
2727 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2728 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2729 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2730 // Check for errors.
2731 if (statusByte
& IDE_STATUS_ERROR
) {
2732 KdPrint2((PRINT_PREFIX
2733 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2735 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2737 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2740 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2741 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2742 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2743 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2744 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2748 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2751 BOOLEAN isSanyo
= FALSE
;
2754 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2756 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2757 for (j
= 0; j
< 26; j
+= 2) {
2759 // Build a buffer based on the identify data.
2760 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2763 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2765 // Inquiry string for older model had a '-', newer is '_'
2766 if (vendorId
[12] == 'C') {
2768 // Torisan changer. Set the bit. This will be used in several places
2769 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2770 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2771 LunExt
->DiscsPresent
= 3;
2777 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2778 if(PreferedMode
== 0xffffffff) {
2779 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2780 PreferedMode
= chan
->MaxTransferMode
;
2783 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2784 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2785 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2788 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2789 LunExt
->OrigTransferMode
=
2790 LunExt
->LimitedTransferMode
=
2791 LunExt
->TransferMode
=
2794 AtapiDmaInit__(deviceExtension
, i
);
2796 LunExt
->OrigTransferMode
=
2797 LunExt
->LimitedTransferMode
=
2798 LunExt
->TransferMode
;
2799 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2801 // We need to get our device ready for action before
2802 // returning from this function
2804 // According to the atapi spec 2.5 or 2.6, an atapi device
2805 // clears its status BSY bit when it is ready for atapi commands.
2806 // However, some devices (Panasonic SQ-TC500N) are still
2807 // not ready even when the status BSY is clear. They don't react
2808 // to atapi commands.
2810 // Since there is really no other indication that tells us
2811 // the drive is really ready for action. We are going to check BSY
2812 // is clear and then just wait for an arbitrary amount of time!
2814 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2817 // have to get out of the loop sometime!
2818 // 10000 * 100us = 1000,000us = 1000ms = 1s
2820 GetStatus(chan
, statusByte
);
2821 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2823 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2824 // Wait for Busy to drop.
2825 AtapiStallExecution(100);
2826 GetStatus(chan
, statusByte
);
2830 // 5000 * 100us = 500,000us = 500ms = 0.5s
2833 AtapiStallExecution(100);
2834 } while (waitCount
--);
2836 GetBaseStatus(chan
, statusByte
);
2837 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2838 AtapiStallExecution(10);
2843 } // end AtapiHwInitialize()
2850 AtapiHwInitializeChanger(
2851 IN PVOID HwDeviceExtension
,
2852 IN PSCSI_REQUEST_BLOCK Srb
,
2853 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2855 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2856 ULONG ldev
= GET_LDEV(Srb
);
2858 if (MechanismStatus
) {
2859 deviceExtension
->lun
[ldev
].DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2860 if (deviceExtension
->lun
[ldev
].DiscsPresent
> 1) {
2861 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
2865 } // end AtapiHwInitializeChanger()
2870 Routine Description:
2871 This routine will parse the string for a match on the keyword, then
2872 calculate the value for the keyword and return it to the caller.
2875 String - The ASCII string to parse.
2876 KeyWord - The keyword for the value desired.
2879 Zero if value not found
2880 Value converted from ASCII to binary.
2885 AtapiParseArgumentString(
2893 ULONG stringLength
= 0;
2894 ULONG keyWordLength
= 0;
2904 // Calculate the string length.
2910 // Calculate the keyword length.
2916 if (keyWordLength
> stringLength
) {
2918 // Can't possibly have a match.
2922 // Now setup and start the compare.
2927 // The input string may start with white space. Skip it.
2928 while (*cptr
== ' ' || *cptr
== '\t') {
2932 if (*cptr
== '\0') {
2938 while ((*cptr
== *kptr
) ||
2939 (*cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
2940 (*cptr
>= 'a' && *cptr
- ('a' - 'A') == *kptr
)) {
2944 if (*cptr
== '\0') {
2950 if (*kptr
== '\0') {
2952 // May have a match backup and check for blank or equals.
2953 while (*cptr
== ' ' || *cptr
== '\t') {
2957 // Found a match. Make sure there is an equals.
2960 // Not a match so move to the next semicolon.
2962 if (*cptr
++ == ';') {
2963 goto ContinueSearch
;
2968 // Skip the equals sign.
2971 // Skip white space.
2972 while ((*cptr
== ' ') || (*cptr
== '\t')) {
2976 if (*cptr
== '\0') {
2977 // Early end of string, return not found
2982 // This isn't it either.
2984 goto ContinueSearch
;
2988 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
2989 // Value is in Hex. Skip the "0x"
2991 for (index
= 0; *(cptr
+ index
); index
++) {
2993 if (*(cptr
+ index
) == ' ' ||
2994 *(cptr
+ index
) == '\t' ||
2995 *(cptr
+ index
) == ';') {
2999 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3000 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3002 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3003 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3004 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3005 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3007 // Syntax error, return not found.
3014 // Value is in Decimal.
3015 for (index
= 0; *(cptr
+ index
); index
++) {
3017 if (*(cptr
+ index
) == ' ' ||
3018 *(cptr
+ index
) == '\t' ||
3019 *(cptr
+ index
) == ';') {
3023 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3024 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3027 // Syntax error return not found.
3036 // Not a match check for ';' to continue search.
3038 if (*cptr
++ == ';') {
3039 goto ContinueSearch
;
3045 } // end AtapiParseArgumentString()_
3053 IN PVOID HwDeviceExtension
,
3058 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3059 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3062 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3065 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3066 // If the last command was DSC restrictive, see if it's set. If so, the device is
3067 // ready for a new request. Otherwise, reset the timer and come back to here later.
3069 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3070 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3071 // we shall have no problem with interrupt handler.
3072 if (!srb
|| chan
->ExpectingInterrupt
) {
3073 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3074 chan
->DpcState
= DPC_STATE_TIMER
;
3075 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3076 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3077 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3079 goto ReturnCallback
;
3083 if (!IS_RDP((srb
->Cdb
[0]))) {
3084 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3088 goto ReturnEnableIntr
;
3090 GetStatus(chan
, statusByte
);
3091 if (statusByte
& IDE_STATUS_DSC
) {
3093 UCHAR PathId
= srb
->PathId
;
3094 UCHAR TargetId
= srb
->TargetId
;
3095 UCHAR Lun
= srb
->Lun
;
3097 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3098 AtapiDmaDBSync(chan
, srb
);
3099 UniataRemoveRequest(chan
, srb
);
3100 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3101 // Clear current SRB.
3102 if(!deviceExtension
->simplexOnly
) {
3103 srb
= UniataGetCurRequest(chan
);
3109 // Ask for next request.
3110 ScsiPortNotification(NextLuRequest
,
3115 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3118 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3122 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3125 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3129 goto ReturnCallback
;
3134 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3135 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3136 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3137 #ifdef UNIATA_USE_XXableInterrupts
3138 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3139 // must be called on DISPATCH_LEVEL
3140 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3141 AtapiEnableInterrupts__
);
3143 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3144 InterlockedExchange(&(chan
->CheckIntr
),
3146 // Will raise IRQL to DIRQL
3147 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3148 AtapiEnableInterrupts__
,
3150 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3151 #endif // UNIATA_USE_XXableInterrupts
3153 //ASSERT(!deviceExtension->simplexOnly);
3158 // Check other channel
3159 // In simplex mode no interrupts must appear on other channels
3160 for(_c
=0; _c
<deviceExtension
->NumberChannels
-1; _c
++) {
3161 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3163 chan
= &(deviceExtension
->chan
[c
]);
3165 if((ULONG
)InterlockedCompareExchange(&chan
->CheckIntr
,
3167 CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
) {
3168 //ASSERT(!deviceExtension->simplexOnly);
3169 chan
->DpcState
= DPC_STATE_ISR
;
3170 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3171 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3175 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3178 } // end AtapiCallBack__()
3183 IN PVOID HwDeviceExtension
3186 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3189 #endif //UNIATA_CORE
3193 Routine Description:
3195 This is the interrupt service routine for ATAPI IDE miniport driver.
3199 HwDeviceExtension - HBA miniport driver's adapter data storage
3203 TRUE if expecting an interrupt.
3209 IN PVOID HwDeviceExtension
3212 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3214 BOOLEAN status
= FALSE
;
3218 BOOLEAN checked
[AHCI_MAX_PORT
];
3220 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
3222 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3223 checked
[_c
] = FALSE
;
3226 // atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
3227 for(pass
=0; pass
<2; pass
++) {
3228 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3230 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3231 //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags)
3232 // & DFLAGS_DEVICE_PRESENT;
3237 // check non-empty and expecting interrupt channels first
3238 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3243 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3245 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3246 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3249 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3251 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3252 // c_state = deviceExtension->chan[c].CheckIntr;
3253 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3254 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3256 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3258 CHECK_INTR_DETECTED
);
3259 if(c_state
== CHECK_INTR_IDLE
) {
3260 // c_state = deviceExtension->chan[c].CheckIntr;
3261 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3262 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3264 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3268 } while(c_state
== CHECK_INTR_CHECK
);
3269 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3270 // check if already serviced
3271 if(c_state
== CHECK_INTR_ACTIVE
) {
3272 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3276 if((c_state
== CHECK_INTR_DETECTED
) ||
3277 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3280 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3281 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3284 // disable interrupts on other channel of legacy mode
3285 // ISA-bridged onboard controller
3286 if(deviceExtension
->simplexOnly
/*||
3287 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3288 AtapiDisableInterrupts(deviceExtension
, !c
);
3291 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3292 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3293 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3294 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3297 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3298 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3301 // re-enable interrupts on other channel
3302 if(deviceExtension
->simplexOnly
/*||
3303 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3304 AtapiEnableInterrupts(deviceExtension
, !c
);
3308 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3309 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3314 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3316 deviceExtension
->FirstChannelToCheck
++;
3317 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3318 deviceExtension
->FirstChannelToCheck
= 0;
3321 } // end AtapiInterrupt()
3329 IN PKINTERRUPT Interrupt
,
3330 IN PVOID Isr2HwDeviceExtension
3334 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3335 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3337 BOOLEAN status
= FALSE
;
3341 // we should never get here for ISA/MCA
3342 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3343 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3347 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3348 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3350 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3351 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3355 if((ULONG
)CrNtInterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3357 CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
) {
3358 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3359 // hunt on unexpected intr (Some devices generate double interrupts,
3360 // some controllers (at least CMD649) interrupt twice with small delay.
3361 // If interrupts are disabled, they queue interrupt and re-issue it later,
3362 // when we do not expect it.
3367 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3369 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3371 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3372 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3377 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3379 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3382 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3383 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3384 // there is an active ISR/DPC for one channel, but
3385 // we have an interrupt from another one
3386 // Lets inform current ISR/DPC about new interrupt
3387 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3391 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3394 } // end AtapiInterrupt2()
3396 RETTYPE_XXableInterrupts
3399 IN PVOID HwDeviceExtension
3402 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3405 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3406 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3408 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3410 if((ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3412 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3417 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3420 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3421 AtapiDisableInterrupts(deviceExtension, lChannel);
3424 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3425 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3426 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3429 return RETVAL_XXableInterrupts
;
3430 } // end AtapiInterruptDpc()
3433 RETTYPE_XXableInterrupts
3435 AtapiEnableInterrupts__(
3436 IN PVOID HwDeviceExtension
3439 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3440 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3442 PHW_CHANNEL chan
= NULL
;
3444 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3445 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3446 chan
= &(deviceExtension
->chan
[c
]);
3448 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3449 // enable intrs on requested channel
3450 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3451 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3452 InterlockedExchange(&(chan
->CheckIntr
),
3455 // check if current or other channel(s) interrupted
3456 //AtapiInterrupt(HwDeviceExtension);
3458 if(deviceExtension
->simplexOnly
) {
3462 // check if other channel(s) interrupted
3463 // must do nothing in simplex mode
3464 if((ULONG
)CrNtInterlockedCompareExchange(&(chan
->CheckIntr
),
3466 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3469 //ASSERT(!deviceExtension->simplexOnly);
3470 chan
->DpcState
= DPC_STATE_ISR
;
3471 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3472 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3476 // In simplex mode next command must be sent to device here
3477 if(deviceExtension
->simplexOnly
&& chan
) {
3478 PSCSI_REQUEST_BLOCK srb
;
3479 chan
= UniataGetNextChannel(chan
);
3481 srb
= UniataGetCurRequest(chan
);
3486 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3490 return RETVAL_XXableInterrupts
;
3492 } // end AtapiEnableInterrupts__()
3494 #endif //UNIATA_CORE
3499 AtapiEnableInterrupts(
3500 IN PVOID HwDeviceExtension
,
3504 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3505 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3506 if(c
>= deviceExtension
->NumberChannels
) {
3509 if(!InterlockedDecrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3510 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3512 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3514 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3515 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3518 } // end AtapiEnableInterrupts()
3522 AtapiDisableInterrupts(
3523 IN PVOID HwDeviceExtension
,
3527 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3528 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3529 // mark channel as busy
3530 if(c
>= deviceExtension
->NumberChannels
) {
3533 if(InterlockedIncrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3534 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3535 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3536 deviceExtension
->chan
[c
].ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
3540 } // end AtapiDisableInterrupts()
3544 Check hardware for interrupt state
3548 AtapiCheckInterrupt__(
3549 IN PVOID HwDeviceExtension
,
3550 IN UCHAR c
// logical channel
3553 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3554 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3555 PHW_LU_EXTENSION LunExt
;
3557 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
3558 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
3561 ULONG pr_status
= 0;
3562 UCHAR dma_status
= 0;
3566 ULONG slotNumber
= deviceExtension
->slotNumber
;
3567 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
3568 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
3571 BOOLEAN DmaTransfer
= FALSE
;
3572 BOOLEAN OurInterrupt
= FALSE
;
3574 UCHAR interruptReason
;
3575 BOOLEAN EarlyIntr
= FALSE
;
3577 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
3580 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3582 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
3584 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
3585 deviceExtension
->Channel
+ c
, c
));
3587 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
3588 deviceExtension
->Channel
+ c
, c
));
3589 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3590 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
3593 // do controller-specific interrupt servicing staff
3594 if(deviceExtension
->UnknownDev
) {
3595 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
3599 if((ChipFlags
& UNIATA_AHCI
) &&
3600 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3601 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
);
3602 return OurInterrupt
;
3606 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
3607 // Such behavior was observed with Intel ICH-xxx chips
3608 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
3612 case ATA_PROMISE_ID
: {
3616 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
3620 ((Channel
) ? 0x00004000 : 0x00000400))) {
3621 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
3626 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
3627 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
3630 if(!(status
& 0x20)) {
3631 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
3636 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
3637 if(ChipFlags
& PRSATA
) {
3638 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
3639 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
3641 if(pr_status
& (0x11 << Channel
)) {
3642 // TODO: reset channel
3643 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
3646 if(!(status
& (0x01 << Channel
))) {
3647 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
3650 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
3654 case ATA_NVIDIA_ID
: {
3655 if(!(ChipFlags
& UNIATA_SATA
))
3658 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
3660 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
3661 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
3663 /* get and clear interrupt status */
3664 if(ChipFlags
& NVQ
) {
3665 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3666 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
3668 pr_status
= AtapiReadPortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3669 AtapiWritePortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
3671 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
3673 /* check for and handle connect events */
3674 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
3675 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
3677 /* check for and handle disconnect events */
3678 if((pr_status
& (0x08UL
<< shift
)) &&
3679 !((pr_status
& (0x04UL
<< shift
) &&
3680 AtapiReadPort4(chan
, IDX_SATA_SStatus
))) ) {
3681 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
3683 /* do we have any device action ? */
3684 if(!(pr_status
& (0x01UL
<< shift
))) {
3685 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
3686 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3695 KdPrint2((PRINT_PREFIX
"ATI\n"));
3696 if(ChipType
== SIIMIO
) {
3701 case ATA_SILICON_IMAGE_ID
:
3703 if(ChipType
== SIIMIO
) {
3705 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
3706 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
3707 if(reg32
== 0xffffffff) {
3708 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
3711 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
))) {
3712 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
3716 if(ChipFlags
& UNIATA_SATA
) {
3717 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
3719 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
3720 * controllers continue to assert IRQ as long as
3721 * SError bits are pending. Clear SError immediately.
3723 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3731 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3732 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
3733 return OurInterrupt
;
3735 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
3736 goto skip_dma_stat_check
;
3739 if(!(deviceExtension
->HwFlags
& SIIINTR
))
3741 GetPciConfig1(0x71, reg8
);
3742 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
3744 (Channel
? 0x08 : 0x04))) {
3748 KdPrint2((PRINT_PREFIX
" cmd our\n"));
3751 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
3758 //dma_status = GetDmaStatus(deviceExtension, lChannel);
3759 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3760 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
3763 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
3764 AtapiStallExecution(1);
3765 AtapiWritePort1(chan
, IDX_BM_Command
,
3766 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
3767 goto skip_dma_stat_check
;
3769 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3770 if(ChipFlags
& UNIATA_AHCI
) {
3773 if(ChipFlags
& UNIATA_SATA
) {
3774 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3781 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
3783 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3784 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
3785 if(dma_status
& BM_STATUS_ERR
) {
3786 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
3789 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3790 GetStatus(chan
, statusByte
);
3791 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3792 if(statusByte
& IDE_STATUS_ERROR
) {
3793 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
3801 if(dma_status
& BM_STATUS_INTR
) {
3802 // bullshit, we have DMA interrupt, but had never initiate DMA operation
3803 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
3804 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
3809 skip_dma_stat_check
:
3810 if(!(ChipFlags
& UNIATA_SATA
)) {
3811 AtapiStallExecution(1);
3814 LunExt
= &(deviceExtension
->lun
[c
*2 + chan
->cur_cdev
]);
3815 /* if drive is busy it didn't interrupt */
3816 /* the exception is DCS + BSY state of ATAPI devices */
3817 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3818 GetStatus(chan
, statusByte
);
3819 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3820 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
3822 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
3824 if (statusByte
== 0xff) {
3825 // interrupt from empty controller ?
3827 if (statusByte
& IDE_STATUS_BUSY
) {
3828 if(!chan
->ExpectingInterrupt
) {
3829 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
3830 return OurInterrupt
;
3833 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3834 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3836 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
3839 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
3840 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
3843 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
3844 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
3850 if(dma_status
& BM_STATUS_INTR
) {
3851 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
3852 /* clear interrupt and get status */
3853 GetBaseStatus(chan
, statusByte
);
3854 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
3858 if(g_WaitBusyInISR
) {
3859 GetStatus(chan
, statusByte
);
3860 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
3861 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3862 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
3863 if (!(statusByte
& IDE_STATUS_BUSY
)) {
3864 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
3866 if (statusByte
& IDE_STATUS_BUSY
) {
3867 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
3874 /* clear interrupt and get status */
3875 GetBaseStatus(chan
, statusByte
);
3876 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
3877 if (statusByte
== 0xff) {
3878 // interrupt from empty controller ?
3880 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
3881 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
3882 return OurInterrupt
;
3885 #ifndef UNIATA_PIO_ONLY
3887 if(!EarlyIntr
|| g_WaitBusyInISR
) {
3888 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
3890 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3891 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3895 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
3897 AtaReq
->ReqState
= REQ_STATE_EARLY_INTR
;
3903 if (!(chan
->ExpectingInterrupt
)) {
3905 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
3907 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3908 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3910 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
3911 return OurInterrupt
;
3913 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
3914 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
3915 return OurInterrupt
;
3917 //ASSERT(!chan->queue_depth || chan->cur_req);
3919 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
3922 } // end AtapiCheckInterrupt__()
3928 IN PVOID HwDeviceExtension
,
3932 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3933 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3935 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3936 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3938 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
3939 ULONG status
= SRB_STATUS_SUCCESS
;
3940 UCHAR dma_status
= 0;
3943 UCHAR statusByte
= 0,interruptReason
;
3945 BOOLEAN atapiDev
= FALSE
;
3950 BOOLEAN DmaTransfer
= FALSE
;
3952 ULONG TimerValue
= 1000;
3953 #ifdef UNIATA_USE_XXableInterrupts
3954 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
3956 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
3957 #endif // UNIATA_USE_XXableInterrupts
3958 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
3959 // BOOLEAN RestoreUseDpc = FALSE;
3960 BOOLEAN DataOverrun
= FALSE
;
3961 BOOLEAN NoStartIo
= TRUE
;
3963 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
3965 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
3966 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
3972 UCHAR OldReqState
= REQ_STATE_NONE
;
3974 PHW_LU_EXTENSION LunExt
;
3977 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3979 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
3981 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
3982 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ) {
3984 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
3988 PathId
= srb
->PathId
;
3989 TargetId
= srb
->TargetId
;
3995 goto enqueue_next_req
;
3998 ldev
= GET_LDEV2(PathId
, TargetId
, Lun
);
3999 DeviceNumber
= (UCHAR
)(ldev
& 1);
4000 LunExt
= &(deviceExtension
->lun
[ldev
]);
4001 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4002 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4004 // check if we are in ISR DPC
4006 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4007 goto ServiceInterrupt
;
4011 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4014 if (!(chan
->ExpectingInterrupt
)) {
4016 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4020 // change request state
4022 OldReqState
= AtaReq
->ReqState
;
4023 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4024 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4027 // We don't want using DPC for fast operations, like
4028 // DMA completion, sending CDB, short ATAPI transfers, etc.
4030 // We MUST use DPC, because of interprocessor synchronization
4031 // on multiprocessor platforms
4034 goto ServiceInterrupt
;
4036 switch(OldReqState
) {
4037 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4038 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4039 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4040 case REQ_STATE_DPC_WAIT_BUSY0
:
4041 case REQ_STATE_DPC_WAIT_BUSY1
:
4042 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4043 goto ServiceInterrupt
;
4044 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4045 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4049 if(!DmaTransfer
&& !atapiDev
) {
4050 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4057 goto ServiceInterrupt
;
4059 #ifdef UNIATA_USE_XXableInterrupts
4061 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4063 // shall never get here
4068 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4070 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4071 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4073 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4076 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4077 goto ServiceInterrupt
;
4078 #endif // UNIATA_USE_XXableInterrupts
4083 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4084 // We always get here when are called from timer callback, which is invoked on DRQL.
4085 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4087 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4088 // disable interrupts for this channel,
4089 // but avoid recursion and double-disable
4090 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4091 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4094 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4096 #ifdef UNIATA_USE_XXableInterrupts
4097 // Will lower IRQL to DISPATCH_LEVEL
4098 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4099 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4100 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4102 // Will raise IRQL to DIRQL
4103 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4106 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4107 #endif // UNIATA_USE_XXableInterrupts
4112 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4114 // Will raise IRQL to DIRQL
4115 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4119 #endif //UNIATA_CORE
4123 if(AtaReq
&& InDpc
) {
4124 switch(AtaReq
->ReqState
) {
4125 case REQ_STATE_DPC_WAIT_DRQ0
:
4127 case REQ_STATE_DPC_WAIT_BUSY
:
4129 case REQ_STATE_DPC_WAIT_DRQ
:
4131 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4133 case REQ_STATE_DPC_WAIT_BUSY0
:
4134 case REQ_STATE_DPC_WAIT_BUSY1
:
4135 // continue normal execution
4141 #endif //UNIATA_CORE
4143 // make additional delay for old devices (if we are not in DPC)
4144 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4148 !(deviceExtension->HwFlags & UNIATA_SATA)
4150 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4151 AtapiStallExecution(10);
4154 /* clear interrupt and get status */
4155 GetBaseStatus(chan
, statusByte
);
4157 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4159 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4163 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4169 if (statusByte
& IDE_STATUS_BUSY
) {
4170 if (deviceExtension
->DriverMustPoll
) {
4171 // Crashdump is polling and we got caught with busy asserted.
4172 // Just go away, and we will be polled again shortly.
4173 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4174 goto ReturnEnableIntr
;
4177 // Ensure BUSY is non-asserted.
4178 // make a very small idle before falling to DPC
4179 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4181 for (i
= 0; i
< k
; i
++) {
4183 GetBaseStatus(chan
, statusByte
);
4184 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4187 AtapiStallExecution(10);
4190 if (!InDpc
&& UseDpc
&& i
== 2) {
4192 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4195 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4200 AtapiStallExecution(TimerValue
);
4201 goto ServiceInterrupt
;
4202 #endif //UNIATA_CORE
4204 if (InDpc
&& i
== k
) {
4205 // reset the controller.
4206 KdPrint2((PRINT_PREFIX
4207 " Resetting due to BUSY on entry - %#x.\n",
4209 goto IntrPrepareResetController
;
4214 if(!LunExt
->IdentifyData
.MajorRevision
&&
4217 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4219 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices (2)\n"));
4220 AtapiStallExecution(10);
4222 if (statusByte
& IDE_STATUS_BUSY
) {
4223 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {
4224 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting\n"));
4226 GetStatus(chan
, statusByte
);
4227 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4228 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4229 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
4230 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4231 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4235 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4237 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4239 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4241 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4243 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4248 AtapiStallExecution(TimerValue
);
4249 #endif //UNIATA_CORE
4252 AtapiStallExecution(10);
4254 if (statusByte
& IDE_STATUS_BUSY
) {
4255 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4261 if(AtaReq
&& DmaTransfer
) {
4262 switch(OldReqState
) {
4263 case REQ_STATE_EARLY_INTR
:
4264 case REQ_STATE_DPC_WAIT_BUSY0
:
4266 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4267 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4268 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4275 // Check for error conditions.
4276 if ((statusByte
& IDE_STATUS_ERROR
) ||
4277 (dma_status
& BM_STATUS_ERR
)) {
4279 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4280 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4282 if(error & IDE_STATUS_CORRECTED_ERROR) {
4283 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4284 statusByte &= ~IDE_STATUS_ERROR;
4289 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4291 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4296 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4297 AtapiStallExecution(100);
4299 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4300 AtapiStallExecution(10);
4304 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4305 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4307 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4308 GetStatus(chan
, statusByte
);
4309 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4310 AtapiStallExecution(100);
4317 /* if this is a UDMA CRC error, reinject request */
4320 if(AtaReq
->retry
< MAX_RETRIES
) {
4321 #ifdef IO_STATISTICS
4322 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
4323 #endif //IO_STATISTICS
4325 (error & IDE_ERROR_ICRC)*/) {
4326 if(AtaReq
->retry
< MAX_RETRIES
) {
4328 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4329 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4330 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4331 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4335 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4338 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
4342 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4343 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
4345 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
4346 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
4347 if(AtaReq
->retry
< MAX_RETRIES
) {
4349 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4350 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4351 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4352 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4356 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4359 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
4363 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
4364 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
4365 // Fail this request.
4366 status
= SRB_STATUS_ERROR
;
4367 goto CompleteRequest
;
4369 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
4372 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
4373 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
4374 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
4376 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
4377 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
4378 #ifdef IO_STATISTICS
4379 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
]++;
4380 if(chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->IoCount
/3 ||
4381 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
4384 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
4385 #endif //IO_STATISTICS
4386 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", deviceExtension
->lun
[DeviceNumber
].TransferMode
));
4387 deviceExtension
->lun
[DeviceNumber
].LimitedTransferMode
=
4388 deviceExtension
->lun
[DeviceNumber
].TransferMode
;
4391 #ifdef IO_STATISTICS
4392 chan
->lun
[DeviceNumber
]->IoCount
++;
4393 #endif //IO_STATISTICS
4397 // check reason for this interrupt.
4400 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
4403 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4404 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4406 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4408 wordsThisInterrupt
= DEV_BSIZE
/2;
4416 // simulate DRQ for DMA transfers
4417 statusByte
|= IDE_STATUS_DRQ
;
4419 if (statusByte
& IDE_STATUS_DRQ
) {
4422 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4424 if (LunExt
->MaximumBlockXfer
) {
4425 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
4428 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4430 interruptReason
= 0x2;
4432 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4433 interruptReason
= 0x0;
4436 status
= SRB_STATUS_ERROR
;
4437 goto CompleteRequest
;
4440 } else if (statusByte
& IDE_STATUS_BUSY
) {
4442 //AtapiEnableInterrupts(deviceExtension, lChannel);
4443 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
4448 if (AtaReq
->WordsLeft
) {
4450 // Funky behaviour seen with PCI IDE (not all, just one).
4452 // The ISR hits with DRQ low, but comes up later.
4453 for (k
= 0; k
< 5000; k
++) {
4454 GetStatus(chan
, statusByte
);
4455 if (statusByte
& IDE_STATUS_DRQ
) {
4460 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
4462 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
4466 AtapiStallExecution(TimerValue
);
4467 goto ServiceInterrupt
;
4468 #endif //UNIATA_CORE
4470 AtapiStallExecution(100);
4473 // reset the controller.
4474 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
4476 IntrPrepareResetController
:
4477 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
4478 goto ReturnEnableIntr
;
4481 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
4485 // Command complete - verify, write, or the SMART enable/disable.
4486 // Also get_media_status
4487 interruptReason
= 0x3;
4492 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
4493 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
4494 // Write the packet.
4495 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
4496 // Send CDB to device.
4497 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
, 6, 0);
4498 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4500 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
4501 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
4502 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, srb
);
4505 goto ReturnEnableIntr
;
4507 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
4512 // Pick up bytes to transfer and convert to words.
4514 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4517 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
4519 // Covert bytes to words.
4521 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
4523 if (wordCount
!= AtaReq
->WordsLeft
) {
4524 KdPrint2((PRINT_PREFIX
4525 "AtapiInterrupt: %d words requested; %d words xferred\n",
4530 // Verify this makes sense.
4531 if (wordCount
> AtaReq
->WordsLeft
) {
4532 wordCount
= AtaReq
->WordsLeft
;
4533 KdPrint2((PRINT_PREFIX
4534 "AtapiInterrupt: Write underrun\n"));
4540 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
4541 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4543 // Transfer only words requested.
4544 wordCount
= AtaReq
->WordsLeft
;
4548 // Transfer next block.
4549 wordCount
= wordsThisInterrupt
;
4553 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4554 //ASSERT(AtaReq->WordsLeft == wordCount);
4555 AtaReq
->WordsLeft
= 0;
4556 status
= SRB_STATUS_SUCCESS
;
4557 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4558 goto CompleteRequest
;
4560 // Ensure that this is a write command.
4561 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4563 KdPrint2((PRINT_PREFIX
4564 "AtapiInterrupt: Write interrupt\n"));
4566 statusByte
= WaitOnBusy(chan
);
4568 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4573 UniataGetPioTiming(LunExt
));
4577 (PULONG
)(AtaReq
->DataBuffer
),
4579 UniataGetPioTiming(LunExt
));
4583 KdPrint3((PRINT_PREFIX
4584 "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
4588 // Fail this request.
4589 status
= SRB_STATUS_ERROR
;
4590 goto CompleteRequest
;
4593 // Advance data buffer pointer and bytes left.
4594 AtaReq
->DataBuffer
+= wordCount
;
4595 AtaReq
->WordsLeft
-= wordCount
;
4598 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4601 goto ReturnEnableIntr
;
4603 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
4608 // Pick up bytes to transfer and convert to words.
4610 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
4611 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
4613 // Covert bytes to words.
4615 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
4617 if (wordCount
!= AtaReq
->WordsLeft
) {
4618 KdPrint2((PRINT_PREFIX
4619 "AtapiInterrupt: %d words requested; %d words xferred\n",
4624 // Verify this makes sense.
4625 if (wordCount
> AtaReq
->WordsLeft
) {
4626 wordCount
= AtaReq
->WordsLeft
;
4632 // Check if words left is at least 256.
4633 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4635 // Transfer only words requested.
4636 wordCount
= AtaReq
->WordsLeft
;
4640 // Transfer next block.
4641 wordCount
= wordsThisInterrupt
;
4645 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4646 //ASSERT(AtaReq->WordsLeft == wordCount);
4647 AtaReq
->WordsLeft
= 0;
4648 status
= SRB_STATUS_SUCCESS
;
4649 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4650 goto CompleteRequest
;
4652 // Ensure that this is a read command.
4653 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4656 "AtapiInterrupt: Read interrupt\n"));*/
4658 statusByte
= WaitOnBusy(chan
);
4660 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4661 KdPrint2((PRINT_PREFIX
4662 "IdeIntr: Read %#x words\n", wordCount
));
4667 UniataGetPioTiming(LunExt
));
4668 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
4669 //KdDump(AtaReq->DataBuffer, wordCount*2);
4670 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
4671 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
4674 GetStatus(chan
, statusByte
);
4675 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4678 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
4679 AtapiSuckPort2(chan
);
4683 KdPrint2((PRINT_PREFIX
4684 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
4687 (PULONG
)(AtaReq
->DataBuffer
),
4689 UniataGetPioTiming(LunExt
));
4693 KdPrint3((PRINT_PREFIX
4694 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
4698 // Fail this request.
4699 status
= SRB_STATUS_ERROR
;
4700 goto CompleteRequest
;
4703 // Advance data buffer pointer and bytes left.
4704 AtaReq
->DataBuffer
+= wordCount
;
4705 AtaReq
->WordsLeft
-= wordCount
;
4707 // Check for read command complete.
4708 if (AtaReq
->WordsLeft
== 0) {
4710 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
4713 // Work around to make many atapi devices return correct sector size
4714 // of 2048. Also certain devices will have sector count == 0x00, check
4716 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
4717 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
4719 AtaReq
->DataBuffer
-= wordCount
;
4720 if (AtaReq
->DataBuffer
[0] == 0x00) {
4722 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
4726 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
4727 AtaReq
->DataBuffer
+= wordCount
;
4732 // Completion for IDE drives.
4733 if (AtaReq->WordsLeft) {
4734 status = SRB_STATUS_DATA_OVERRUN;
4736 status = SRB_STATUS_SUCCESS;
4739 goto CompleteRequest;
4741 status
= SRB_STATUS_SUCCESS
;
4742 goto CompleteRequest
;
4747 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4751 goto ReturnEnableIntr
;
4753 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
4755 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
4756 // Command complete.
4758 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
4759 AtaReq
->WordsLeft
= 0;
4761 if (AtaReq
->WordsLeft
) {
4762 status
= SRB_STATUS_DATA_OVERRUN
;
4764 status
= SRB_STATUS_SUCCESS
;
4767 #ifdef UNIATA_DUMP_ATAPI
4769 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4773 PCHAR ModeSelectData
;
4775 PSCSI_REQUEST_BLOCK Srb
= srb
;
4777 Cdb
= (PCDB
)(Srb
->Cdb
);
4778 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
4779 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
4780 CdbDataLen
= Srb
->DataTransferLength
;
4782 if(CdbDataLen
> 0x1000) {
4783 CdbDataLen
= 0x1000;
4787 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
4788 KdPrint2(("P:T:D=%d:%d:%d\n",
4792 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
4795 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
4796 KdPrint(("ModeSense 6\n"));
4797 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4798 ModeSelectData
= CdbData
+4;
4799 KdDump(CdbData
, CdbDataLen
);
4801 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
4802 KdPrint(("ModeSense 10\n"));
4803 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4804 ModeSelectData
= CdbData
+8;
4805 KdDump(CdbData
, CdbDataLen
);
4807 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4808 KdPrint(("Read buffer from device:\n"));
4809 KdDump(CdbData
, CdbDataLen
);
4814 #endif //UNIATA_DUMP_ATAPI
4818 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest\n"));
4819 // Check and see if we are processing our secret (mechanism status/request sense) srb
4820 if (AtaReq
->OriginalSrb
) {
4824 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
4825 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
4827 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
4828 if (status
== SRB_STATUS_SUCCESS
) {
4830 AtapiHwInitializeChanger (HwDeviceExtension
,
4832 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
4834 // Get ready to issue the original srb
4835 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4836 AtaReq
->OriginalSrb
= NULL
;
4839 // failed! Get the sense key and maybe try again
4840 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
4842 AtaReq
->OriginalSrb
);
4845 // do not enable interrupts in DPC, do not waste time, do it now!
4846 if(UseDpc && chan->DisableIntr) {
4847 AtapiEnableInterrupts(HwDeviceExtension, c);
4849 RestoreUseDpc = TRUE;
4852 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4854 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
4856 if (srbStatus
== SRB_STATUS_PENDING
) {
4857 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
4858 goto ReturnEnableIntr
;
4862 // restore state on error
4864 AtapiDisableInterrupts(HwDeviceExtension, c);
4868 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
4870 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
4872 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
4873 if (status
== SRB_STATUS_DATA_OVERRUN
) {
4874 // Check to see if we at least get mininum number of bytes
4875 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
4876 (offsetof (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
4877 status
= SRB_STATUS_SUCCESS
;
4881 if (status
== SRB_STATUS_SUCCESS
) {
4883 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
4884 chan
->MechStatusRetryCount
) {
4886 // The sense key doesn't say the last request is illegal, so try again
4887 chan
->MechStatusRetryCount
--;
4888 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
4890 AtaReq
->OriginalSrb
);
4893 // last request was illegal. No point trying again
4894 AtapiHwInitializeChanger (HwDeviceExtension
,
4896 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4898 // Get ready to issue the original srb
4899 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4900 AtaReq
->OriginalSrb
= NULL
;
4902 #endif //UNIATA_CORE
4904 // do not enable interrupts in DPC, do not waste time, do it now!
4905 if(UseDpc && chan->DisableIntr) {
4906 AtapiEnableInterrupts(HwDeviceExtension, c);
4908 RestoreUseDpc = TRUE;
4911 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4913 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
4915 if (srbStatus
== SRB_STATUS_PENDING
) {
4916 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
4917 goto ReturnEnableIntr
;
4921 // restore state on error
4923 AtapiDisableInterrupts(HwDeviceExtension, c);
4929 // If we get here, it means AtapiSendCommand() has failed
4930 // Can't recover. Pretend the original srb has failed and complete it.
4932 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
4934 if (AtaReq
->OriginalSrb
) {
4935 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
4936 AtapiHwInitializeChanger (HwDeviceExtension
,
4938 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4939 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4940 AtaReq
->OriginalSrb
= NULL
;
4943 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
4945 // fake an error and read no data
4946 status
= SRB_STATUS_ERROR
;
4947 srb
->ScsiStatus
= 0;
4948 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
4949 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
4952 } else if (status
== SRB_STATUS_ERROR
) {
4954 // Map error to specific SRB status and handle request sense.
4955 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
4956 status
= MapError(deviceExtension
,
4961 } else if(!DmaTransfer
) {
4963 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
4964 // Command complete.
4966 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
4967 // Wait for busy to drop.
4968 for (i
= 0; i
< 5*30; i
++) {
4969 GetStatus(chan
, statusByte
);
4970 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4975 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
4977 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
4981 AtapiStallExecution(TimerValue
);
4982 goto ServiceInterrupt
;
4983 #endif //UNIATA_CORE
4985 AtapiStallExecution(100);
4990 // reset the controller.
4991 KdPrint2((PRINT_PREFIX
4992 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
4994 goto IntrPrepareResetController
;
4996 // Check to see if DRQ is still up.
4997 if(statusByte
& IDE_STATUS_DRQ
) {
4998 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5000 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5001 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5003 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5006 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5009 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5011 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5013 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5014 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5015 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5019 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5020 //if ((statusByte & IDE_STATUS_DRQ)) {}
5021 if((statusByte
& IDE_STATUS_DRQ
) &&
5022 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5025 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5026 for (i
= 0; i
< 200; i
++) {
5027 GetStatus(chan
, statusByte
);
5028 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5033 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5034 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5039 AtapiStallExecution(TimerValue
);
5040 goto ServiceInterrupt
;
5041 #endif //UNIATA_CORE
5043 AtapiStallExecution(100);
5047 // reset the controller.
5048 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5050 goto IntrPrepareResetController
;
5054 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5055 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5056 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5058 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5059 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5063 // Clear interrupt expecting flag.
5064 chan
->ExpectingInterrupt
= FALSE
;
5065 InterlockedExchange(&(chan
->CheckIntr
),
5068 // Sanity check that there is a current request.
5070 // Set status in SRB.
5071 srb
->SrbStatus
= (UCHAR
)status
;
5073 // Check for underflow.
5074 if(AtaReq
->WordsLeft
) {
5076 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5077 // Subtract out residual words and update if filemark hit,
5078 // setmark hit , end of data, end of media...
5079 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5080 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5081 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5083 srb
->DataTransferLength
= 0;
5086 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5089 if(status
== SRB_STATUS_SUCCESS
) {
5090 AtaReq
->WordsTransfered
+= AtaReq
->bcount
* DEV_BSIZE
/2;
5092 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5093 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5094 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5095 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5096 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5099 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5100 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5104 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5107 // Indicate command complete.
5109 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5112 if (status
== SRB_STATUS_SUCCESS
&&
5113 srb
->SenseInfoBuffer
&&
5114 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5116 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5118 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5119 senseBuffer
->ErrorCode
= 0;
5120 senseBuffer
->Valid
= 1;
5121 senseBuffer
->AdditionalSenseLength
= 0xb;
5122 senseBuffer
->SenseKey
= 0;
5123 senseBuffer
->AdditionalSenseCode
= 0;
5124 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5126 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5128 AtapiDmaDBSync(chan
, srb
);
5129 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5130 UniataRemoveRequest(chan
, srb
);
5131 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5132 ScsiPortNotification(RequestComplete
,
5138 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5139 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5141 if (status
!= SRB_STATUS_SUCCESS
) {
5142 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5143 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5146 // Build the SMART status block depending upon the completion status.
5147 cmdOutParameters
->cBufferSize
= wordCount
;
5148 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5149 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5151 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5153 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5154 cmdOutParameters
->bBuffer
[0] = RETURN_SMART_STATUS
;
5155 cmdOutParameters
->bBuffer
[1] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
5156 cmdOutParameters
->bBuffer
[2] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Unused1
);
5157 cmdOutParameters
->bBuffer
[3] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5158 cmdOutParameters
->bBuffer
[4] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
);
5159 cmdOutParameters
->bBuffer
[5] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_DriveSelect
);
5160 cmdOutParameters
->bBuffer
[6] = SMART_CMD
;
5161 cmdOutParameters
->cBufferSize
= 8;
5164 // Indicate command complete.
5165 goto IntrCompleteReq
;
5170 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5175 for (i
= 0; i
< 5; i
++) {
5176 GetStatus(chan
, statusByte
);
5177 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5178 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5182 if (statusByte
& IDE_STATUS_DSC
) {
5183 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5187 AtapiStallExecution(50);
5190 // RDP can be cleared since previous check
5192 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5198 AtapiStallExecution(TimerValue
);
5199 goto ServiceInterrupt
;
5200 #endif //UNIATA_CORE
5203 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5206 srb
= UniataGetCurRequest(chan
);
5211 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5213 ScsiPortNotification(NextRequest
,
5217 ScsiPortNotification(NextLuRequest
,
5222 // in simplex mode next command must NOT be sent here
5223 if(!deviceExtension
->simplexOnly
) {
5224 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5227 // Try to get SRB fron any non-empty queue (later)
5228 if(deviceExtension
->simplexOnly
) {
5231 #endif //UNIATA_CORE
5233 goto ReturnEnableIntr
;
5237 // Unexpected int. Catch it
5238 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
5246 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
5248 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
5249 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
5250 #ifdef UNIATA_USE_XXableInterrupts
5251 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
5252 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
5253 // must be called on DISPATCH_LEVEL
5254 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
5255 AtapiEnableInterrupts__
);
5257 AtapiEnableInterrupts(HwDeviceExtension
, c
);
5258 InterlockedExchange(&(chan
->CheckIntr
),
5260 // Will raise IRQL to DIRQL
5262 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
5263 AtapiEnableInterrupts__
,
5265 #endif // UNIATA_CORE
5266 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5267 #endif // UNIATA_USE_XXableInterrupts
5271 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
5272 // in simplex mode next command must be sent here if
5274 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
5277 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
5278 chan
= UniataGetNextChannel(chan
);
5280 srb
= UniataGetCurRequest(chan
);
5284 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
5286 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5289 #endif //UNIATA_CORE
5292 } // end AtapiInterrupt__()
5298 Routine Description:
5300 This routine handles SMART enable, disable, read attributes and threshold commands.
5304 HwDeviceExtension - HBA miniport driver's adapter data storage
5305 Srb - IO request packet
5314 IdeSendSmartCommand(
5315 IN PVOID HwDeviceExtension
,
5316 IN PSCSI_REQUEST_BLOCK Srb
5319 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5320 ULONG c
= GET_CHANNEL(Srb
);
5321 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
5322 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5323 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5324 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5325 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
5327 UCHAR statusByte
,targetId
;
5330 if (regs
->bCommandReg
!= SMART_CMD
) {
5331 KdPrint2((PRINT_PREFIX
5332 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
5333 return SRB_STATUS_INVALID_REQUEST
;
5336 targetId
= cmdInParameters
.bDriveNumber
;
5338 //TODO optimize this check
5339 if ((!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) ||
5340 (deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
5342 return SRB_STATUS_SELECTION_TIMEOUT
;
5345 chan
->SmartCommand
= regs
->bFeaturesReg
;
5347 // Determine which of the commands to carry out.
5348 switch(regs
->bFeaturesReg
) {
5349 case READ_ATTRIBUTES
:
5350 case READ_THRESHOLDS
:
5352 statusByte
= WaitOnBusy(chan
);
5354 if (statusByte
& IDE_STATUS_BUSY
) {
5355 KdPrint2((PRINT_PREFIX
5356 "IdeSendSmartCommand: Returning BUSY status\n"));
5357 return SRB_STATUS_BUSY
;
5360 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5361 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
5363 // Set data buffer pointer and words left.
5364 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5365 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
5367 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5369 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5371 regs
->bSectorNumberReg
,
5372 regs
->bSectorCountReg
,
5376 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5377 // Wait for interrupt.
5378 return SRB_STATUS_PENDING
;
5380 return SRB_STATUS_ERROR
;
5384 case RETURN_SMART_STATUS
:
5385 case ENABLE_DISABLE_AUTOSAVE
:
5386 case EXECUTE_OFFLINE_DIAGS
:
5387 case SAVE_ATTRIBUTE_VALUES
:
5389 statusByte
= WaitOnBusy(chan
);
5391 if (statusByte
& IDE_STATUS_BUSY
) {
5392 KdPrint2((PRINT_PREFIX
5393 "IdeSendSmartCommand: Returning BUSY status\n"));
5394 return SRB_STATUS_BUSY
;
5397 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5398 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
5400 // Set data buffer pointer and indicate no data transfer.
5401 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5402 AtaReq
->WordsLeft
= 0;
5404 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5406 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5408 regs
->bSectorNumberReg
,
5409 regs
->bSectorCountReg
,
5413 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5414 // Wait for interrupt.
5415 return SRB_STATUS_PENDING
;
5417 return SRB_STATUS_ERROR
;
5418 } // end switch(regs->bFeaturesReg)
5420 return SRB_STATUS_INVALID_REQUEST
;
5422 } // end IdeSendSmartCommand()
5424 #endif //UNIATA_CORE
5428 UniAtaCalculateLBARegs(
5429 PHW_LU_EXTENSION LunExt
,
5430 ULONG startingSector
,
5434 UCHAR drvSelect
,sectorNumber
;
5440 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5441 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
5442 if(LunExt
->DeviceExtension
) {
5443 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
5446 return startingSector
;
5448 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5449 LunExt
->IdentifyData
.NumberOfHeads
;
5451 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5455 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
5457 cylinder
= (USHORT
)(startingSector
/ tmp
);
5458 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5459 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5460 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
5461 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
5462 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
5465 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5466 } // end UniAtaCalculateLBARegs()
5470 UniAtaCalculateLBARegsBack(
5471 PHW_LU_EXTENSION LunExt
,
5475 ULONG drvSelect
,sectorNumber
;
5479 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5482 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5483 LunExt
->IdentifyData
.NumberOfHeads
;
5485 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5486 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5487 sectorNumber
= (UCHAR
)(lba
& 0xff);
5489 lba
= sectorNumber
-1 +
5490 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5494 } // end UniAtaCalculateLBARegsBack()
5499 Routine Description:
5501 This routine handles IDE read and writes.
5505 HwDeviceExtension - HBA miniport driver's adapter data storage
5506 Srb - IO request packet
5516 IN PVOID HwDeviceExtension
,
5517 IN PSCSI_REQUEST_BLOCK Srb
,
5521 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5522 UCHAR lChannel
= GET_CHANNEL(Srb
);
5523 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5524 PHW_LU_EXTENSION LunExt
;
5525 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5526 ULONG ldev
= GET_LDEV(Srb
);
5527 UCHAR DeviceNumber
= (UCHAR
)(ldev
& 1);
5528 ULONG startingSector
;
5530 ULONG wordCount
= 0;
5531 UCHAR statusByte
,statusByte2
;
5534 BOOLEAN use_dma
= FALSE
;
5536 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5537 LunExt
= &deviceExtension
->lun
[ldev
];
5539 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5540 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5542 if(LunExt
->opt_ReadOnly
&&
5543 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
5544 if(LunExt
->opt_ReadOnly
== 1) {
5545 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
5546 return SRB_STATUS_ERROR
;
5548 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
5549 return SRB_STATUS_SUCCESS
;
5553 // Set data buffer pointer and words left.
5554 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5556 if(AtaReq
->WordsTransfered
) {
5557 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
5558 startingSector
= (ULONG
)(UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
5559 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
5560 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
5562 AtaReq
->TransferLength
/2,
5563 AtaReq
->WordsTransfered
,
5566 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
5567 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5568 // Set up 1st block.
5569 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5570 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5571 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
5573 AtaReq
->TransferLength
/2,
5576 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5579 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
5581 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
5582 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5584 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5591 // assume best case here
5592 // we cannot reinit Dma until previous request is completed
5593 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5595 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5596 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5597 (PUCHAR
)(AtaReq
->DataBuffer
),
5598 AtaReq
->bcount
* DEV_BSIZE
)) {
5602 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5603 } else { // exec_only
5604 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5607 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5611 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5612 return SRB_STATUS_PENDING
;
5615 // if this is queued request, reinit DMA and check
5616 // if DMA mode is still available
5617 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5618 if (/*EnableDma &&*/
5619 (LunExt
->TransferMode
>= ATA_DMA
)) {
5622 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5626 // Check if write request.
5627 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5629 // Prepare read command.
5631 cmd
= IDE_COMMAND_READ_DMA
;
5633 if(LunExt
->MaximumBlockXfer
) {
5634 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5636 cmd
= IDE_COMMAND_READ
;
5640 // Prepare write command.
5642 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
5643 cmd
= IDE_COMMAND_WRITE_DMA
;
5645 if (LunExt
->MaximumBlockXfer
) {
5646 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5648 if (AtaReq
->WordsLeft
< wordCount
) {
5649 // Transfer only words requested.
5650 wordCount
= AtaReq
->WordsLeft
;
5652 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5655 wordCount
= DEV_BSIZE
/2;
5656 cmd
= IDE_COMMAND_WRITE
;
5661 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5663 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5667 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5668 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5670 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5672 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5674 (USHORT
)(AtaReq
->bcount
),
5675 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5677 if(statusByte2
!= 0xff) {
5678 GetStatus(chan
, statusByte2
);
5680 if(statusByte2
& IDE_STATUS_ERROR
) {
5681 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5682 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5683 return SRB_STATUS_ERROR
;
5686 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5688 return SRB_STATUS_PENDING
;
5691 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5693 (USHORT
)(AtaReq
->bcount
),
5694 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5697 if (!(statusByte
& IDE_STATUS_DRQ
) ||
5698 statusByte
== 0xff) {
5700 if(statusByte
== 0xff) {
5701 KdPrint2((PRINT_PREFIX
5702 "IdeReadWrite: error sending command (%#x)\n",
5705 KdPrint2((PRINT_PREFIX
5706 "IdeReadWrite: DRQ never asserted (%#x)\n",
5710 AtaReq
->WordsLeft
= 0;
5712 // Clear interrupt expecting flag.
5713 chan
->ExpectingInterrupt
= FALSE
;
5714 InterlockedExchange(&(chan
->CheckIntr
),
5717 // Clear current SRB.
5718 UniataRemoveRequest(chan
, Srb
);
5720 return (statusByte
== 0xff) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
5723 chan
->ExpectingInterrupt
= TRUE
;
5724 InterlockedExchange(&(chan
->CheckIntr
),
5727 // Write next DEV_BSIZE/2*N words.
5728 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5729 KdPrint2((PRINT_PREFIX
5730 "IdeReadWrite: Write %#x words\n", wordCount
));
5735 UniataGetPioTiming(LunExt
));
5739 KdPrint2((PRINT_PREFIX
5740 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5743 (PULONG
)(AtaReq
->DataBuffer
),
5745 UniataGetPioTiming(LunExt
));
5748 // Adjust buffer address and words left count.
5749 AtaReq
->WordsLeft
-= wordCount
;
5750 AtaReq
->DataBuffer
+= wordCount
;
5752 // Wait for interrupt.
5753 return SRB_STATUS_PENDING
;
5755 } // end IdeReadWrite()
5761 Routine Description:
5762 This routine handles IDE Verify.
5765 HwDeviceExtension - HBA miniport driver's adapter data storage
5766 Srb - IO request packet
5775 IN PVOID HwDeviceExtension
,
5776 IN PSCSI_REQUEST_BLOCK Srb
5779 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5780 UCHAR lChannel
= GET_CHANNEL(Srb
);
5781 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5782 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5783 PHW_LU_EXTENSION LunExt
;
5784 ULONG ldev
= GET_LDEV(Srb
);
5786 ULONG startingSector
;
5793 LunExt
= &deviceExtension
->lun
[ldev
];
5794 // Drive has these number sectors.
5795 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
5796 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
5797 LunExt
->IdentifyData
.NumberOfHeads
*
5798 LunExt
->IdentifyData
.NumberOfCylinders
;
5801 KdPrint2((PRINT_PREFIX
5802 "IdeVerify: Total sectors %#x\n",
5805 // Get starting sector number from CDB.
5806 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5807 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5809 KdPrint2((PRINT_PREFIX
5810 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
5814 endSector
= startingSector
+ sectorCount
;
5816 KdPrint2((PRINT_PREFIX
5817 "IdeVerify: Ending sector %#x\n",
5820 if (endSector
> sectors
) {
5822 // Too big, round down.
5823 KdPrint2((PRINT_PREFIX
5824 "IdeVerify: Truncating request to %#x blocks\n",
5825 sectors
- startingSector
- 1));
5827 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
5831 // Set up sector count register. Round up to next block.
5832 if (sectorCount
> 0xFF) {
5833 sectorCount
= (USHORT
)0xFF;
5837 // Set data buffer pointer and words left.
5838 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5839 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5841 // Indicate expecting an interrupt.
5842 InterlockedExchange(&(chan
->CheckIntr
),
5845 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5847 statusByte
= AtaCommand48(deviceExtension
, ldev
& 0x01, GET_CHANNEL(Srb
),
5848 IDE_COMMAND_VERIFY
, lba
,
5852 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5853 // Wait for interrupt.
5854 return SRB_STATUS_PENDING
;
5856 return SRB_STATUS_ERROR
;
5858 } // end IdeVerify()
5860 #endif //UNIATA_CORE
5864 Routine Description:
5865 Send ATAPI packet command to device.
5868 HwDeviceExtension - HBA miniport driver's adapter data storage
5869 Srb - IO request packet
5877 IN PVOID HwDeviceExtension
,
5878 IN PSCSI_REQUEST_BLOCK Srb
,
5882 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5883 UCHAR lChannel
= GET_CHANNEL(Srb
);
5884 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5885 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5886 ULONG ldev
= GET_LDEV(Srb
);
5889 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
5890 BOOLEAN use_dma
= FALSE
;
5891 BOOLEAN dma_reinited
= FALSE
;
5892 BOOLEAN retried
= FALSE
;
5894 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
5895 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
5896 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
5898 #ifdef UNIATA_DUMP_ATAPI
5899 if(CmdAction
& CMD_ACTION_PREPARE
) {
5903 PCHAR ModeSelectData
;
5906 Cdb
= (PCDB
)(Srb
->Cdb
);
5907 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5908 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5909 CdbDataLen
= Srb
->DataTransferLength
;
5911 if(CdbDataLen
> 0x1000) {
5912 CdbDataLen
= 0x1000;
5916 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5917 KdPrint2(("P:T:D=%d:%d:%d\n",
5921 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
5924 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
5925 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
5926 Cdb
->WRITE_CD
.LBA
[0],
5927 Cdb
->WRITE_CD
.LBA
[1],
5928 Cdb
->WRITE_CD
.LBA
[2],
5929 Cdb
->WRITE_CD
.LBA
[3]
5932 if(ScsiCommand
== SCSIOP_WRITE12
) {
5933 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
5934 Cdb
->CDB12READWRITE
.LBA
[0],
5935 Cdb
->CDB12READWRITE
.LBA
[1],
5936 Cdb
->CDB12READWRITE
.LBA
[2],
5937 Cdb
->CDB12READWRITE
.LBA
[3]
5940 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
5941 KdPrint(("ModeSelect 6\n"));
5942 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5943 ModeSelectData
= CdbData
+4;
5944 KdDump(CdbData
, CdbDataLen
);
5946 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
5947 KdPrint(("ModeSelect 10\n"));
5948 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5949 ModeSelectData
= CdbData
+8;
5950 KdDump(CdbData
, CdbDataLen
);
5952 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5953 KdPrint(("Send buffer to device:\n"));
5954 KdDump(CdbData
, CdbDataLen
);
5959 #endif //UNIATA_DUMP_ATAPI
5962 if(CmdAction
== CMD_ACTION_PREPARE
) {
5963 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
5964 switch (Srb
->Cdb
[0]) {
5968 case SCSIOP_WRITE12
:
5972 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
5973 return SRB_STATUS_BUSY
;
5976 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5977 !AtaReq
->OriginalSrb
) {
5978 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
5979 return SRB_STATUS_BUSY
;
5983 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5984 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5986 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
5987 // Set data buffer pointer and words left.
5988 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5989 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5990 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5991 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5993 // check if reorderable
5994 switch(Srb
->Cdb
[0]) {
5996 case SCSIOP_WRITE12
:
5998 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6004 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6006 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6008 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6009 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6010 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
6011 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6015 // check if DMA read/write
6016 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6017 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6019 if(AtaReq
->TransferLength
) {
6021 switch(Srb
->Cdb
[0]) {
6023 case SCSIOP_WRITE12
:
6024 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
6030 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
6032 if(AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6033 (PUCHAR
)(AtaReq
->DataBuffer
),
6034 Srb
->DataTransferLength
6035 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
6037 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6042 case SCSIOP_READ_CD
:
6043 if(deviceExtension
->opt_AtapiDmaRawRead
)
6044 goto call_dma_setup
;
6048 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
6049 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6054 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
6055 KdPrint2((PRINT_PREFIX
"dma RO\n"));
6066 if(!AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6067 (PUCHAR
)(AtaReq
->DataBuffer
),
6068 Srb
->DataTransferLength
)) {
6069 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
6072 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6076 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
6080 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6081 // if this is queued request, reinit DMA and check
6082 // if DMA mode is still available
6083 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
6084 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6085 if (/*EnableDma &&*/
6086 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6087 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
6090 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6091 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
6094 dma_reinited
= TRUE
;
6098 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6099 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
6100 return SRB_STATUS_PENDING
;
6102 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6103 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6104 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6107 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6108 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
6110 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6111 //AtapiDmaReinit(deviceExtension, ldev, AtaReq);
6112 } if(AtaReq
->TransferLength
) {
6114 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
6115 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6116 if (/*EnableDma &&*/
6117 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6120 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6125 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
6127 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6128 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
6129 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
6130 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6133 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6134 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6135 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6138 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
6141 // We need to know how many platters our atapi cd-rom device might have.
6142 // Before anyone tries to send a srb to our target for the first time,
6143 // we must "secretly" send down a separate mechanism status srb in order to
6144 // initialize our device extension changer data. That's how we know how
6145 // many platters our target has.
6147 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6148 !AtaReq
->OriginalSrb
) {
6152 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6153 // Set this flag now. If the device hangs on the mech. status
6154 // command, we will not have the chance to set it.
6155 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6157 chan
->MechStatusRetryCount
= 3;
6158 AtaReq
->OriginalSrb
= Srb
;
6159 AtaReq
->Srb
= BuildMechanismStatusSrb (
6163 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6164 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6165 if (srbStatus
== SRB_STATUS_PENDING
) {
6166 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6169 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6170 AtaReq
->OriginalSrb
= NULL
;
6171 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6172 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6173 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6177 #endif //UNIATA_CORE
6179 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
6180 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
6182 // Make sure command is to ATAPI device.
6183 flags
= deviceExtension
->lun
[ldev
].DeviceFlags
;
6184 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6185 if((Srb
->Lun
) > (deviceExtension
->lun
[ldev
].DiscsPresent
- 1)) {
6187 // Indicate no device found at this address.
6188 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6189 return SRB_STATUS_SELECTION_TIMEOUT
;
6191 } else if(Srb
->Lun
> 0) {
6192 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6193 return SRB_STATUS_SELECTION_TIMEOUT
;
6196 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
6197 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6198 return SRB_STATUS_SELECTION_TIMEOUT
;
6201 // Select device 0 or 1.
6202 SelectDrive(chan
, ldev
& 0x1);
6204 // Verify that controller is ready for next command.
6205 GetStatus(chan
, statusByte
);
6206 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
6208 if(statusByte
== 0xff) {
6209 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
6212 if(statusByte
& IDE_STATUS_BUSY
) {
6213 if(statusByte
& IDE_STATUS_DSC
) {
6214 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
6216 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
6217 // We have to make reset here, since we are expecting device to be available
6218 //return SRB_STATUS_BUSY; // this cause queue freeze
6222 if(statusByte
& IDE_STATUS_ERROR
) {
6223 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
6225 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
6226 // Read the error reg. to clear it and fail this request.
6227 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6228 return MapError(deviceExtension
, Srb
);
6230 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
6233 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
6234 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
6235 if((!(statusByte
& IDE_STATUS_DSC
)) &&
6236 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6238 AtapiStallExecution(200);
6239 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6240 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6241 return SRB_STATUS_PENDING
;
6244 if(IS_RDP(Srb
->Cdb
[0])) {
6246 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6250 if(statusByte
& IDE_STATUS_DRQ
) {
6252 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6254 // Try to drain the data that one preliminary device thinks that it has
6255 // to transfer. Hopefully this random assertion of DRQ will not be present
6256 // in production devices.
6257 for (i
= 0; i
< 0x10000; i
++) {
6258 GetStatus(chan
, statusByte
);
6259 if(statusByte
& IDE_STATUS_DRQ
) {
6260 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6268 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6270 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6272 AtapiSoftReset(chan
, ldev
& 1);
6274 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6275 // Re-initialize Atapi device.
6276 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), ldev
& 1, TRUE
);
6278 IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb),
6279 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
6281 // Inform the port driver that the bus has been reset.
6282 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6283 // Clean up device extension fields that AtapiStartIo won't.
6284 chan
->ExpectingInterrupt
= FALSE
;
6286 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6289 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6291 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
6292 return SRB_STATUS_BUS_RESET;
6295 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
6299 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
6300 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6301 return SRB_STATUS_SELECTION_TIMEOUT
;
6305 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6306 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6307 Srb
->Cdb
[1] &= ~0xE0;
6308 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6309 // Torisan changer. TUR's are overloaded to be platter switches.
6310 Srb
->Cdb
[7] = Srb
->Lun
;
6317 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6319 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6322 statusByte
= WaitOnBusy(chan
);
6323 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6326 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6327 use_dma
? ATA_F_DMA
: 0);
6329 // Write transfer byte count to registers.
6330 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6331 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6333 if (Srb
->DataTransferLength
>= 0x10000) {
6334 byteCountLow
= byteCountHigh
= 0xFF;
6337 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6338 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6340 if (flags
& DFLAGS_INT_DRQ
) {
6342 // This device interrupts when ready to receive the packet.
6344 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6347 chan
->ExpectingInterrupt
= TRUE
;
6348 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6349 InterlockedExchange(&(chan
->CheckIntr
),
6352 // Write ATAPI packet command.
6353 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6355 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
6356 return SRB_STATUS_PENDING
;
6360 // This device quickly sets DRQ when ready to receive the packet.
6362 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6365 chan
->ExpectingInterrupt
= TRUE
;
6366 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6367 InterlockedExchange(&(chan
->CheckIntr
),
6370 //AtapiDisableInterrupts(deviceExtension, lChannel);
6372 // Write ATAPI packet command.
6373 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6377 statusByte
= WaitForDrq(chan
);
6379 // Need to read status register and clear interrupt (if any)
6380 GetBaseStatus(chan
, statusByte
);
6382 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6384 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6385 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6386 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6387 return SRB_STATUS_ERROR
;
6391 GetStatus(chan
, statusByte
);
6392 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6394 // Send CDB to device.
6395 statusByte
= WaitOnBaseBusy(chan
);
6397 // Indicate expecting an interrupt and wait for it.
6398 chan
->ExpectingInterrupt
= TRUE
;
6399 InterlockedExchange(&(chan
->CheckIntr
),
6401 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6403 GetBaseStatus(chan
, statusByte
);
6405 //AtapiEnableInterrupts(deviceExtension, lChannel);
6412 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6413 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
);
6416 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6418 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6419 return SRB_STATUS_PENDING
;
6421 } // end AtapiSendCommand()
6428 Routine Description:
6429 Program ATA registers for IDE disk transfer.
6432 HwDeviceExtension - ATAPI driver storage.
6433 Srb - System request block.
6436 SRB status (pending if all goes well).
6441 ULONG check_point
= 0;
6442 #define SetCheckPoint(cp) { check_point = (cp) ; }
6444 #define SetCheckPoint(cp)
6450 IN PVOID HwDeviceExtension
,
6451 IN PSCSI_REQUEST_BLOCK Srb
,
6456 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6459 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6467 UCHAR statusByte
,errorByte
;
6470 PMODE_PARAMETER_HEADER modeData
;
6474 //ULONG __ebp__ = 0;
6476 SetCheckPoint(0x20);
6477 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6482 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6483 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6484 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6485 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6486 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6488 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6489 Srb->SrbExtension));
6490 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6493 SetCheckPoint(0x30);
6494 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6496 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6498 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6500 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6502 lChannel
= GET_CHANNEL(Srb
);
6503 chan
= &(deviceExtension
->chan
[lChannel
]);
6504 ldev
= GET_LDEV(Srb
);
6506 SetCheckPoint(0x40);
6507 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6508 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6510 if(CmdAction
== CMD_ACTION_PREPARE
) {
6511 switch (Srb
->Cdb
[0]) {
6513 case SCSIOP_INQUIRY
: // now it requires device access
6515 case SCSIOP_READ_CAPACITY
:
6518 case SCSIOP_REQUEST_SENSE
:
6520 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6525 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6526 return SRB_STATUS_BUSY
;
6530 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6531 switch (Srb
->Cdb
[0]) {
6532 case SCSIOP_INQUIRY
:
6534 KdPrint2((PRINT_PREFIX
6535 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6536 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6537 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6538 // which support up to two devices.
6539 if ((Srb
->Lun
!= 0) ||
6540 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6541 (Srb
->TargetId
> 2) /*||
6542 (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) {
6544 KdPrint2((PRINT_PREFIX
6545 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6546 // Indicate no device found at this address.
6547 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6552 KdPrint2((PRINT_PREFIX
6553 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6554 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6555 PIDENTIFY_DATA2 identifyData
= &(deviceExtension
->lun
[ldev
].IdentifyData
);
6557 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6559 if(!CheckDevice(HwDeviceExtension
, lChannel
, ldev
& 1, FALSE
)) {
6560 KdPrint2((PRINT_PREFIX
6561 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6562 // Indicate no device found at this address.
6564 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6568 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, ldev
& 1)) {
6569 KdPrint2((PRINT_PREFIX
6570 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6571 // Indicate no device found at this address.
6572 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
6574 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6579 // Zero INQUIRY data structure.
6580 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6582 // Standard IDE interface only supports disks.
6583 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6585 // Set the removable bit, if applicable.
6586 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6587 KdPrint2((PRINT_PREFIX
6588 "RemovableMedia\n"));
6589 inquiryData
->RemovableMedia
= 1;
6591 // Set the Relative Addressing (LBA) bit, if applicable.
6592 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6593 inquiryData
->RelativeAddressing
= 1;
6594 KdPrint2((PRINT_PREFIX
6595 "RelativeAddressing\n"));
6597 // Set the CommandQueue bit
6598 inquiryData
->CommandQueue
= 1;
6600 // Fill in vendor identification fields.
6601 for (i
= 0; i
< 24; i
+= 2) {
6602 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6605 // Initialize unused portion of product id.
6606 for (i = 0; i < 4; i++) {
6607 inquiryData->ProductId[12+i] = ' ';
6610 // Move firmware revision from IDENTIFY data to
6611 // product revision in INQUIRY data.
6612 for (i
= 0; i
< 4; i
+= 2) {
6613 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6616 status
= SRB_STATUS_SUCCESS
;
6621 case SCSIOP_MODE_SENSE
:
6623 KdPrint2((PRINT_PREFIX
6624 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6625 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6626 // This is used to determine if the media is write-protected.
6627 // Since IDE does not support mode sense then we will modify just the portion we need
6628 // so the higher level driver can determine if media is protected.
6629 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6631 SelectDrive(chan
, ldev
& 0x1);
6632 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6633 statusByte
= WaitOnBusy(chan
);
6635 if (!(statusByte
& IDE_STATUS_ERROR
)){
6637 // no error occured return success, media is not protected
6638 chan
->ExpectingInterrupt
= FALSE
;
6639 InterlockedExchange(&(chan
->CheckIntr
),
6641 status
= SRB_STATUS_SUCCESS
;
6645 // error occured, handle it locally, clear interrupt
6646 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6648 GetBaseStatus(chan
, statusByte
);
6649 chan
->ExpectingInterrupt
= FALSE
;
6650 InterlockedExchange(&(chan
->CheckIntr
),
6652 status
= SRB_STATUS_SUCCESS
;
6654 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6656 //media is write-protected, set bit in mode sense buffer
6657 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6659 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6660 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6663 status
= SRB_STATUS_SUCCESS
;
6665 status
= SRB_STATUS_INVALID_REQUEST
;
6669 case SCSIOP_TEST_UNIT_READY
:
6671 KdPrint2((PRINT_PREFIX
6672 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6673 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6674 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6676 // Select device 0 or 1.
6677 SelectDrive(chan
, ldev
& 0x1);
6678 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6680 // Wait for busy. If media has not changed, return success
6681 statusByte
= WaitOnBusy(chan
);
6683 if (!(statusByte
& IDE_STATUS_ERROR
)){
6684 chan
->ExpectingInterrupt
= FALSE
;
6685 InterlockedExchange(&(chan
->CheckIntr
),
6687 status
= SRB_STATUS_SUCCESS
;
6689 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6690 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6692 // Special case: If current media is write-protected,
6693 // the 0xDA command will always fail since the write-protect bit
6694 // is sticky,so we can ignore this error
6695 GetBaseStatus(chan
, statusByte
);
6696 chan
->ExpectingInterrupt
= FALSE
;
6697 InterlockedExchange(&(chan
->CheckIntr
),
6699 status
= SRB_STATUS_SUCCESS
;
6703 // Request sense buffer to be build
6704 chan
->ExpectingInterrupt
= TRUE
;
6705 InterlockedExchange(&(chan
->CheckIntr
),
6707 status
= SRB_STATUS_PENDING
;
6711 status
= SRB_STATUS_SUCCESS
;
6716 case SCSIOP_READ_CAPACITY
:
6718 KdPrint2((PRINT_PREFIX
6719 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
6720 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6721 // Claim 512 byte blocks (big-endian).
6722 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
6724 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
6726 // Calculate last sector.
6727 if(!(i
= (ULONG
)deviceExtension
->lun
[ldev
].NumOfSectors
)) {
6728 i
= deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
*
6729 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
*
6730 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
;
6734 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
6735 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
6736 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
6738 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
6740 KdPrint2((PRINT_PREFIX
6741 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
6743 deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
,
6744 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
,
6745 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
));
6748 status
= SRB_STATUS_SUCCESS
;
6753 KdPrint2((PRINT_PREFIX
6754 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
6755 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6756 status
= IdeVerify(HwDeviceExtension
,Srb
);
6763 KdPrint2((PRINT_PREFIX
6764 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
6765 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
6766 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6767 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6768 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6769 status
= IdeReadWrite(HwDeviceExtension
,
6773 case SCSIOP_START_STOP_UNIT
:
6775 KdPrint2((PRINT_PREFIX
6776 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6777 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6778 //Determine what type of operation we should perform
6779 cdb
= (PCDB
)Srb
->Cdb
;
6781 if (cdb
->START_STOP
.LoadEject
== 1){
6783 statusByte
= WaitOnBaseBusy(chan
);
6785 // first select device 0 or 1.
6786 SelectDrive(chan
, ldev
& 0x1);
6787 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
6789 status
= SRB_STATUS_SUCCESS
;
6792 case SCSIOP_MEDIUM_REMOVAL
:
6794 cdb
= (PCDB
)Srb
->Cdb
;
6796 statusByte
= WaitOnBaseBusy(chan
);
6798 SelectDrive(chan
, ldev
& 0x1);
6799 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
6800 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
6802 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
6804 status
= SRB_STATUS_SUCCESS
;
6807 // Note: I don't implement this, because NTFS driver too often issues this command
6808 // It causes awful performance degrade. However, if somebody wants, I will implement
6809 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
6812 case SCSIOP_FLUSH_BUFFER
:
6813 case SCSIOP_SYNCHRONIZE_CACHE
:
6815 SelectDrive(chan
, ldev
& 0x1);
6816 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
6817 status
= SRB_STATUS_SUCCESS
;
6818 // status = SRB_STATUS_PENDING;
6819 statusByte
= WaitOnBusy(chan
);
6823 case SCSIOP_REQUEST_SENSE
:
6824 // this function makes sense buffers to report the results
6825 // of the original GET_MEDIA_STATUS command
6827 KdPrint2((PRINT_PREFIX
6828 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6829 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6830 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6831 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
6834 status
= SRB_STATUS_INVALID_REQUEST
;
6838 case SCSIOP_ATA_PASSTHROUGH
:
6841 BOOLEAN use_dma
= FALSE
;
6844 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
6846 lChannel
= Srb
->TargetId
>> 1;
6848 regs
->bDriveHeadReg
&= 0x0f;
6849 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
6851 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
6853 KdPrint2((PRINT_PREFIX
6854 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6855 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6858 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6860 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
6861 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
6863 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6864 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
6865 (PUCHAR
)(Srb
->DataBuffer
),
6866 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
6872 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
6873 AtapiStallExecution(10);
6875 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6876 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6877 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6878 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6879 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6880 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6882 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
6883 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6884 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
6885 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6886 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
6887 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6888 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
6889 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6890 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
6891 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6893 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
6896 GetBaseStatus(chan
, statusByte
);
6897 if(statusByte
& IDE_STATUS_ERROR
) {
6898 goto passthrough_err
;
6900 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
6903 ScsiPortStallExecution(1); // wait for busy to be set
6905 if(regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) {
6906 to_lim
= Srb
->TimeOutValue
;
6908 if(Srb
->TimeOutValue
<= 2) {
6909 to_lim
= Srb
->TimeOutValue
*900;
6911 to_lim
= (Srb
->TimeOutValue
*999) - 500;
6914 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
6915 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
6916 GetBaseStatus(chan
, statusByte
);
6917 if(statusByte
& IDE_STATUS_ERROR
) {
6920 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6925 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
6927 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
6928 goto passthrough_err
;
6932 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
6934 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
6935 GetBaseStatus(chan
, statusByte
);
6937 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
6938 AtapiSuckPort2(chan
);
6940 if (Srb
->SenseInfoBuffer
) {
6942 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
6944 senseBuffer
->ErrorCode
= 0x70;
6945 senseBuffer
->Valid
= 1;
6946 senseBuffer
->AdditionalSenseLength
= 0xb;
6947 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
6948 senseBuffer
->AdditionalSenseCode
= 0;
6949 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6951 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
6952 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
6954 status
= SRB_STATUS_ERROR
;
6958 if (statusByte
& IDE_STATUS_DRQ
) {
6959 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6961 (PUSHORT
) Srb
->DataBuffer
,
6962 Srb
->DataTransferLength
/ 2,
6964 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6966 (PUSHORT
) Srb
->DataBuffer
,
6967 Srb
->DataTransferLength
/ 2,
6972 status
= SRB_STATUS_SUCCESS
;
6975 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6977 } else { // read task register
6979 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
6981 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
6983 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6984 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6985 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6986 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6987 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6988 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6990 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6991 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6992 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6993 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6994 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6995 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6996 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6997 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6998 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6999 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
7001 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
7002 status
= SRB_STATUS_SUCCESS
;
7009 KdPrint2((PRINT_PREFIX
7010 "IdeSendCommand: Unsupported command %#x\n",
7013 status
= SRB_STATUS_INVALID_REQUEST
;
7017 if(status
== SRB_STATUS_PENDING
) {
7018 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
7019 if(CmdAction
& CMD_ACTION_EXEC
) {
7020 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
7021 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
7024 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
7025 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7030 } // end IdeSendCommand()
7035 Routine Description:
7036 Enables disables media status notification
7039 HwDeviceExtension - ATAPI driver storage.
7046 IN PVOID HwDeviceExtension
,
7050 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7052 UCHAR lChannel
= ldev
>> 1;
7053 UCHAR statusByte
,errorByte
;
7055 chan
= &(deviceExtension
->chan
[lChannel
]);
7057 if (EnableMSN
== TRUE
){
7059 // If supported enable Media Status Notification support
7060 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
7063 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7064 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7065 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7067 if (statusByte
& IDE_STATUS_ERROR
) {
7068 // Read the error register.
7069 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7071 KdPrint2((PRINT_PREFIX
7072 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
7076 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
7077 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
7078 chan
->ReturningMediaStatus
= 0;
7083 } else { // end if EnableMSN == TRUE
7085 // disable if previously enabled
7086 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
7088 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7089 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7090 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7091 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
7098 } // end IdeMediaStatus()
7103 Routine Description:
7105 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
7106 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
7109 HwDeviceExtension - ATAPI driver storage.
7110 Srb - System request block.
7114 SRB status (ALWAYS SUCCESS).
7119 IdeBuildSenseBuffer(
7120 IN PVOID HwDeviceExtension
,
7121 IN PSCSI_REQUEST_BLOCK Srb
7124 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7126 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
7127 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
7131 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
7133 senseBuffer
->ErrorCode
= 0x70;
7134 senseBuffer
->Valid
= 1;
7135 senseBuffer
->AdditionalSenseLength
= 0xb;
7136 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7137 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7138 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7139 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
7141 senseBuffer
->ErrorCode
= 0x70;
7142 senseBuffer
->Valid
= 1;
7143 senseBuffer
->AdditionalSenseLength
= 0xb;
7144 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7145 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7146 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7147 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
7149 senseBuffer
->ErrorCode
= 0x70;
7150 senseBuffer
->Valid
= 1;
7151 senseBuffer
->AdditionalSenseLength
= 0xb;
7152 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
7153 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
7154 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7155 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
7157 senseBuffer
->ErrorCode
= 0x70;
7158 senseBuffer
->Valid
= 1;
7159 senseBuffer
->AdditionalSenseLength
= 0xb;
7160 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
7161 senseBuffer
->AdditionalSenseCode
= 0;
7162 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7164 return SRB_STATUS_SUCCESS
;
7166 return SRB_STATUS_ERROR
;
7168 }// End of IdeBuildSenseBuffer
7172 UniataUserDeviceReset(
7173 PHW_DEVICE_EXTENSION deviceExtension
,
7174 PHW_LU_EXTENSION LunExt
,
7179 AtapiDisableInterrupts(deviceExtension
, PathId
);
7180 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
7181 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
7182 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), ldev
& 1);
7184 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
7185 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
7186 deviceExtension
->chan
[PathId
].lun
[0]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7187 deviceExtension
->chan
[PathId
].lun
[1]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7189 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7190 AtapiEnableInterrupts(deviceExtension
, PathId
);
7192 } // end UniataUserDeviceReset()
7197 PHW_DEVICE_EXTENSION deviceExtension
,
7202 BOOLEAN PostReq
= FALSE
;
7204 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
7205 if(chan
->queue_depth
> 0) {
7208 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
7209 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
7210 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
7212 status
= SRB_STATUS_BUSY
;
7221 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
7225 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
7228 } // end UniataNeedQueueing()
7232 Routine Description:
7234 This routine is called from the SCSI port driver synchronized
7235 with the kernel to start an IO request.
7239 HwDeviceExtension - HBA miniport driver's adapter data storage
7240 Srb - IO request packet
7250 IN PVOID HwDeviceExtension
,
7251 IN PSCSI_REQUEST_BLOCK Srb
7254 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
7255 } // end AtapiStartIo()
7260 IN PVOID HwDeviceExtension
,
7261 IN PSCSI_REQUEST_BLOCK Srb
,
7265 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7274 PSCSI_REQUEST_BLOCK tmpSrb
;
7275 BOOLEAN PostReq
= FALSE
;
7277 BOOLEAN commPort
= FALSE
;
7279 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
7280 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7281 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7282 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7284 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7286 /* KeBugCheckEx(0xc000000e,
7287 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7289 TopLevel, 0x80000001);
7291 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7292 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7293 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7298 lChannel
= GET_CHANNEL(Srb
);
7299 chan
= &(deviceExtension
->chan
[lChannel
]);
7300 ldev
= GET_LDEV(Srb
);
7302 //ASSERT(deviceExtension);
7305 KdPrint2((PRINT_PREFIX
7306 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7307 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7308 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7310 if(lChannel
== deviceExtension
->NumberChannels
&&
7311 !Srb
->Lun
&& !Srb
->TargetId
&&
7312 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
7313 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
7315 KdPrint2((PRINT_PREFIX
7316 "AtapiStartIo: Communication port\n"));
7317 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
7319 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7321 KdPrint2((PRINT_PREFIX
7323 // Zero INQUIRY data structure.
7324 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7326 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
7328 // Fill in vendor identification fields.
7329 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
7331 status
= SRB_STATUS_SUCCESS
;
7335 /* Pass IOCTL request down */
7337 if(GET_CDEV(Srb
) >= 2 ||
7338 ldev
>= deviceExtension
->NumberChannels
*2 ||
7339 lChannel
>= deviceExtension
->NumberChannels
||
7342 if(lChannel
>= deviceExtension
->NumberChannels
) {
7347 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7348 KdPrint3((PRINT_PREFIX
7349 "AtapiStartIo: SRB rejected\n"));
7350 // Indicate no device found at this address.
7351 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7352 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7357 atapiDev
= (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7360 if(!commPort
&& !(chan
->lun
[ldev
& 1])) {
7362 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7365 deviceExtension
->NumberChannels
);
7366 PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n",
7367 lChannel
, ldev
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7368 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7369 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7373 for(i=0; i<1000; i++) {
7374 AtapiStallExecution(3*1000);
7381 // Determine which function.
7382 switch (Srb
->Function
) {
7384 case SRB_FUNCTION_EXECUTE_SCSI
:
7386 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7387 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7388 // let passthrough go
7390 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7394 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7395 KdPrint2((PRINT_PREFIX
7396 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7397 // Indicate no device found at this address.
7398 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7399 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7406 if(Srb->DataTransferLength) {
7408 a = ((PUCHAR)(Srb->DataBuffer))[0];
7411 } __except(EXCEPTION_EXECUTE_HANDLER) {
7412 KdPrint3((PRINT_PREFIX
7413 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7414 // Indicate no device found at this address.
7415 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7416 status = SRB_STATUS_ERROR;
7417 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7422 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7426 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
7428 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7429 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
7431 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7433 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7434 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7436 /*KeBugCheckEx(0xc000000e,
7437 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7439 status, 0x80000001);*/
7440 if(status
== SRB_STATUS_BUSY
)
7441 status
= SRB_STATUS_PENDING
;
7442 // Insert requests AFTER they have been initialized on
7443 // CMD_ACTION_PREPARE stage
7444 // we should not check TopLevel here (it is always TRUE)
7445 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7446 UniataQueueRequest(chan
, Srb
);
7448 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7451 // Send command to device.
7452 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7454 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7455 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7456 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7457 //ASSERT(!AtaReq->Flags);
7458 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7459 UniataQueueRequest(chan
, Srb
);
7460 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7461 //ASSERT(!AtaReq->Flags);
7462 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7463 //ASSERT(!AtaReq->Flags);
7467 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7468 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7469 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, ldev
& 1)) {
7470 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, ldev
& 1, TRUE
)) {
7474 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7478 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7487 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7488 KdPrint3((PRINT_PREFIX
"Try ATAPI send\n"));
7489 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7491 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7496 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7503 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7505 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7507 /* KeBugCheckEx(0xc000000e,
7508 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7510 status, 0x80000002);*/
7518 case SRB_FUNCTION_ABORT_COMMAND
:
7520 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7522 // Verify that SRB to abort is still outstanding.
7523 if((tmpSrb
!= Srb
->NextSrb
) ||
7524 !chan
->queue_depth
) {
7526 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7528 // Complete abort SRB.
7529 status
= SRB_STATUS_ABORT_FAILED
;
7533 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7534 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7535 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7536 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7537 // Log reset failure.
7538 KdPrint3((PRINT_PREFIX
7539 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7540 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7542 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7543 status
= SRB_STATUS_ERROR
;
7546 status
= SRB_STATUS_SUCCESS
;
7549 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7550 if (tmpSrb
->SenseInfoBuffer
&&
7551 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7553 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7555 senseBuffer
->ErrorCode
= 0;
7556 senseBuffer
->Valid
= 1;
7557 senseBuffer
->AdditionalSenseLength
= 0xb;
7558 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7559 senseBuffer
->AdditionalSenseCode
= 0;
7560 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7562 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7564 AtapiDmaDBSync(chan
, tmpSrb
);
7565 UniataRemoveRequest(chan
, tmpSrb
);
7566 // Indicate command complete.
7567 ScsiPortNotification(RequestComplete
,
7570 status
= SRB_STATUS_SUCCESS
;
7574 // Abort function indicates that a request timed out.
7575 // Call reset routine. Card will only be reset if
7576 // status indicates something is wrong.
7577 // Fall through to reset code.
7579 case SRB_FUNCTION_RESET_DEVICE
:
7580 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7582 // Reset single device.
7583 // For now we support only Lun=0
7585 // Note: reset is immediate command, it cannot be queued since it is usually used to
7586 // revert not- responding device to operational state
7587 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7588 UniataUserDeviceReset(deviceExtension
, &(deviceExtension
->lun
[ldev
]), lChannel
, ldev
);
7589 status
= SRB_STATUS_SUCCESS
;
7592 case SRB_FUNCTION_RESET_BUS
:
7594 // Reset Atapi and SCSI bus.
7596 // Note: reset is immediate command, it cannot be queued since it is usually used to
7597 // revert not- responding device to operational state
7598 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7599 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7600 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7601 // Log reset failure.
7602 KdPrint3((PRINT_PREFIX
7603 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7604 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7606 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7607 status
= SRB_STATUS_ERROR
;
7610 status
= SRB_STATUS_SUCCESS
;
7615 case SRB_FUNCTION_SHUTDOWN
:
7617 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7618 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7619 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7622 // FLUSH ATAPI device - do nothing
7623 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7625 // FLUSH IDE/ATA device
7626 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7627 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7628 status
= AtaCommand(deviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
7629 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7630 // If supported & allowed, reset write cacheing
7631 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7633 // Disable write cache
7634 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7635 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7636 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7637 // Check for errors.
7638 if (status
& IDE_STATUS_ERROR
) {
7639 KdPrint2((PRINT_PREFIX
7640 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7643 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7645 // Re-enable write cache
7646 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7647 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7648 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7649 // Check for errors.
7650 if (status
& IDE_STATUS_ERROR
) {
7651 KdPrint2((PRINT_PREFIX
7652 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7654 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7656 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7660 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7662 status
= SRB_STATUS_SUCCESS
;
7666 case SRB_FUNCTION_FLUSH
:
7668 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7669 status
= SRB_STATUS_SUCCESS
;
7672 /* case SRB_FUNCTION_SHUTDOWN:
7673 case SRB_FUNCTION_FLUSH:
7675 // Flush device's cache.
7676 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7678 if (chan->CurrentSrb) {
7680 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7681 Srb->SrbStatus = SRB_STATUS_BUSY;
7682 ScsiPortNotification(RequestComplete,
7688 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
7689 status = SRB_STATUS_SUCCESS;
7691 status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb),
7692 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
7693 if (status & IDE_STATUS_DRQ) {
7694 status = SRB_STATUS_SUCCESS;
7696 status = SRB_STATUS_SELECTION_TIMEOUT;
7701 case SRB_FUNCTION_IO_CONTROL
: {
7705 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
7707 len
= Srb
->DataTransferLength
;
7709 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
7711 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
7712 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
7714 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7717 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
7719 // Version and revision per SMART 1.03
7721 versionParameters
->bVersion
= 1;
7722 versionParameters
->bRevision
= 1;
7723 versionParameters
->bReserved
= 0;
7725 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
7726 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
7728 // This is done because of how the IOCTL_SCSI_MINIPORT
7729 // determines 'targetid's'. Disk.sys places the real target id value
7730 // in the DeviceMap field. Once we do some parameter checking, the value passed
7731 // back to the application will be determined.
7733 deviceNumber
= versionParameters
->bIDEDeviceMap
;
7736 KdPrint2((PRINT_PREFIX
7737 "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
7738 // Indicate no device found at this address.
7739 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7740 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7744 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
7747 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7751 // NOTE: This will only set the bit
7752 // corresponding to this drive's target id.
7753 // The bit mask is as follows:
7759 if (deviceExtension
->NumberChannels
== 1) {
7760 if (chan
->PrimaryAddress
) {
7761 deviceNumber
= 1 << ldev
;
7763 deviceNumber
= 4 << ldev
;
7766 deviceNumber
= 1 << ldev
;
7769 versionParameters
->bIDEDeviceMap
= deviceNumber
;
7771 status
= SRB_STATUS_SUCCESS
;
7775 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
7777 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7778 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7781 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
7782 // Extract the target.
7783 targetId
= cmdInParameters
.bDriveNumber
;
7784 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
7785 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
7786 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7787 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
7788 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7792 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
7794 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
7795 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
7796 status
= SRB_STATUS_INVALID_REQUEST
;
7802 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
7803 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
7804 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
7805 status
= SRB_STATUS_INVALID_REQUEST
;
7809 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
7810 // Zero the output buffer
7811 RtlZeroMemory(cmdOutParameters
, len
);
7812 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
7813 ((PUCHAR)cmdOutParameters)[i] = 0;
7816 // Build status block.
7817 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
7818 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
7819 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
7821 // Extract the identify data from the device extension.
7822 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
7823 cmdOutParameters
->cBufferSize
);
7825 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
7827 status
= SRB_STATUS_SUCCESS
;
7831 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
7832 cmdInParameters
.irDriveRegs
.bCommandReg
));
7833 status
= SRB_STATUS_INVALID_REQUEST
;
7839 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
7840 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
7841 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
7842 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
7843 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
7844 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
7845 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
7846 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
7849 KdPrint2((PRINT_PREFIX
7850 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
7851 // Indicate no device found at this address.
7852 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7853 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7857 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7859 if(PostReq
|| TopLevel
) {
7860 UniataQueueRequest(chan
, Srb
);
7861 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7862 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7867 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
7868 status
= SRB_STATUS_PENDING
;
7870 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7873 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
7878 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
7879 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
7880 status
= SRB_STATUS_INVALID_REQUEST
;
7885 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
7887 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
7888 ULONG ldev
= GET_LDEV2(AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
, 0);
7889 PHW_LU_EXTENSION LunExt
;
7892 //chan = &(deviceExtension->chan[lChannel]);
7894 if(AtaCtl
->addr
.Lun
||
7895 ldev
>= deviceExtension
->NumberChannels
*2 ||
7896 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
7903 LunExt
= &(deviceExtension
->lun
[ldev
]);
7904 lChannel
= AtaCtl
->addr
.PathId
;
7905 chan
= &(deviceExtension
->chan
[lChannel
]);
7908 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl
->hdr
.ControlCode
, ldev
));
7910 /* check for valid LUN */
7911 switch (AtaCtl
->hdr
.ControlCode
) {
7912 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7913 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
7915 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
7916 AtaCtl
->addr
.TargetId
!= 0xff ||
7917 AtaCtl
->addr
.Lun
!= 0
7919 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
7920 ldev
< deviceExtension
->NumberChannels
*2) { // AtaCtl->addr.TargetId != 0xff
7921 LunExt
= &(deviceExtension
->lun
[ldev
]);
7924 goto handle_bad_ldev
;
7927 // this would be BUS reset
7928 lChannel
= AtaCtl
->addr
.PathId
;
7929 chan
= &(deviceExtension
->chan
[lChannel
]);
7931 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
7932 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7933 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
7934 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7935 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
7938 KdPrint2((PRINT_PREFIX
7939 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
7940 // Indicate no device found at this address.
7945 /* check if queueing is necessary */
7946 switch (AtaCtl
->hdr
.ControlCode
) {
7947 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7948 if(!LunExt
->nBadBlocks
) {
7951 goto uata_ctl_queue
;
7952 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7953 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
7956 goto uata_ctl_queue
;
7957 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7958 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
7960 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
7961 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7963 if(PostReq
|| TopLevel
) {
7964 UniataQueueRequest(chan
, Srb
);
7965 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7966 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7969 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
7970 status
= SRB_STATUS_PENDING
;
7972 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7975 } // end switch (AtaCtl->hdr.ControlCode)
7977 /* process request */
7978 switch (AtaCtl
->hdr
.ControlCode
) {
7979 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7981 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
7983 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
7984 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
7985 if(AtaCtl
->addr
.TargetId
!= 0xff) {
7986 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_HIDDEN
;
7991 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7992 AtapiStallExecution(1000 * 1000);
7995 FindDevices(HwDeviceExtension
,
7996 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
7997 ? UNIATA_FIND_DEV_UNHIDE
: 0,
7998 AtaCtl
->addr
.PathId
);
7999 status
= SRB_STATUS_SUCCESS
;
8003 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
8005 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
8007 deviceExtension
->lun
[ldev
].DeviceFlags
= 0;
8008 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
8009 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
8010 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_HIDDEN
;
8013 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
8014 AtapiStallExecution(1000 * 1000);
8017 status
= SRB_STATUS_SUCCESS
;
8020 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
8022 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
8024 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
8025 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
8027 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
8028 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
8029 if(LunExt
->LimitedTransferMode
>
8030 LunExt
->OrigTransferMode
) {
8031 // check for incorrect value
8032 LunExt
->LimitedTransferMode
=
8033 LunExt
->OrigTransferMode
;
8036 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
8038 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8039 if(AtaCtl
->SetMode
.ApplyImmediately
) {
8040 AtapiDmaInit__(deviceExtension
, ldev
);
8042 /* deviceExtension->lun[ldev].TransferMode =
8043 deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
8044 status
= SRB_STATUS_SUCCESS
;
8047 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
8049 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
8051 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
8052 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
8053 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
8055 status
= SRB_STATUS_SUCCESS
;
8058 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
8060 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
8062 AtaCtl
->AdapterInfo
.HeaderLength
= offsetof(ADAPTERINFO
, Chan
);
8064 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
8065 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
8066 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
8067 status
= SRB_STATUS_DATA_OVERRUN
;
8071 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
8072 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
8073 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
8074 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
8075 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
8076 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
8077 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
8078 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
8079 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
8080 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
8081 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
8082 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
8083 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
8084 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
8085 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
8086 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
8087 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
8088 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
8089 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
8090 if(deviceExtension
->FullDevName
) {
8091 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
8093 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
8095 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
8097 status
= SRB_STATUS_SUCCESS
;
8100 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
8102 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
8104 ForgetBadBlocks(LunExt
);
8106 status
= SRB_STATUS_SUCCESS
;
8109 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
8111 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
8116 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
, ldev
);
8119 status
= SRB_STATUS_SUCCESS
;
8123 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
8124 AtaCtl
->hdr
.ControlCode
));
8125 status
= SRB_STATUS_INVALID_REQUEST
;
8130 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
8131 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
8132 "SCSIDISK", "-UNIATA-"));
8134 status
= SRB_STATUS_INVALID_REQUEST
;
8139 } // end SRB_FUNCTION_IO_CONTROL
8142 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
8143 // Indicate unsupported command.
8144 status
= SRB_STATUS_INVALID_REQUEST
;
8152 PathId
= Srb
->PathId
;
8153 TargetId
= Srb
->TargetId
;
8156 if (status
!= SRB_STATUS_PENDING
) {
8158 KdPrint2((PRINT_PREFIX
8159 "AtapiStartIo: Srb %#x complete with status %#x\n",
8163 // Set status in SRB.
8164 Srb
->SrbStatus
= (UCHAR
)status
;
8166 AtapiDmaDBSync(chan
, Srb
);
8167 UniataRemoveRequest(chan
, Srb
);
8168 // Indicate command complete.
8169 ScsiPortNotification(RequestComplete
,
8173 // Remove current Srb & get next one
8174 if((Srb
= UniataGetCurRequest(chan
))) {
8175 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8176 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
8177 // current request is under precessing, thus
8178 // we should do nothing here
8186 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
8188 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
8190 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
8191 // Indicate ready for next request.
8192 ScsiPortNotification(NextRequest
,
8196 ScsiPortNotification(NextLuRequest
,
8204 } // end AtapiStartIo__()
8209 UniataInitAtaCommands()
8215 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
8217 for(i
=0; i
<256; i
++) {
8222 KdPrint2((PRINT_PREFIX
"cmd %2.2x: ", command
));
8225 case IDE_COMMAND_READ_DMA48
:
8226 case IDE_COMMAND_READ_DMA_Q48
:
8227 case IDE_COMMAND_READ_STREAM_DMA48
:
8228 case IDE_COMMAND_READ_STREAM48
:
8229 case IDE_COMMAND_WRITE_DMA48
:
8230 case IDE_COMMAND_WRITE_DMA_Q48
:
8231 case IDE_COMMAND_READ_DMA_Q
:
8232 case IDE_COMMAND_READ_DMA
:
8233 case IDE_COMMAND_WRITE_DMA
:
8234 case IDE_COMMAND_WRITE_DMA_Q
:
8235 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8236 case IDE_COMMAND_WRITE_STREAM48
:
8237 case IDE_COMMAND_WRITE_FUA_DMA48
:
8238 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8239 case IDE_COMMAND_READ_LOG_DMA48
:
8240 case IDE_COMMAND_WRITE_LOG_DMA48
:
8241 case IDE_COMMAND_TRUSTED_RCV_DMA
:
8242 case IDE_COMMAND_TRUSTED_SEND_DMA
:
8243 KdPrint2((PRINT_PREFIX
"DMA "));
8244 flags
|= ATA_CMD_FLAG_DMA
;
8248 case IDE_COMMAND_READ48
:
8249 case IDE_COMMAND_READ_DMA48
:
8250 case IDE_COMMAND_READ_DMA_Q48
:
8251 case IDE_COMMAND_READ_MUL48
:
8252 case IDE_COMMAND_READ_STREAM_DMA48
:
8253 case IDE_COMMAND_READ_STREAM48
:
8254 case IDE_COMMAND_WRITE48
:
8255 case IDE_COMMAND_WRITE_DMA48
:
8256 case IDE_COMMAND_WRITE_DMA_Q48
:
8257 case IDE_COMMAND_WRITE_MUL48
:
8258 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8259 case IDE_COMMAND_WRITE_STREAM48
:
8260 case IDE_COMMAND_WRITE_FUA_DMA48
:
8261 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8262 case IDE_COMMAND_WRITE_MUL_FUA48
:
8263 case IDE_COMMAND_FLUSH_CACHE48
:
8264 case IDE_COMMAND_VERIFY48
:
8266 KdPrint2((PRINT_PREFIX
"48 "));
8267 flags
|= ATA_CMD_FLAG_48
;
8270 case IDE_COMMAND_READ
:
8271 case IDE_COMMAND_READ_MULTIPLE
:
8272 case IDE_COMMAND_READ_DMA
:
8273 case IDE_COMMAND_READ_DMA_Q
:
8274 case IDE_COMMAND_WRITE
:
8275 case IDE_COMMAND_WRITE_MULTIPLE
:
8276 case IDE_COMMAND_WRITE_DMA
:
8277 case IDE_COMMAND_WRITE_DMA_Q
:
8278 case IDE_COMMAND_FLUSH_CACHE
:
8279 case IDE_COMMAND_VERIFY
:
8281 KdPrint2((PRINT_PREFIX
"LBA "));
8282 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
8285 flags
|= ATA_CMD_FLAG_48supp
;
8288 case IDE_COMMAND_READ
:
8289 command
= IDE_COMMAND_READ48
; break;
8290 case IDE_COMMAND_READ_MULTIPLE
:
8291 command
= IDE_COMMAND_READ_MUL48
; break;
8292 case IDE_COMMAND_READ_DMA
:
8293 command
= IDE_COMMAND_READ_DMA48
; break;
8294 case IDE_COMMAND_READ_DMA_Q
:
8295 command
= IDE_COMMAND_READ_DMA_Q48
; break;
8296 case IDE_COMMAND_WRITE
:
8297 command
= IDE_COMMAND_WRITE48
; break;
8298 case IDE_COMMAND_WRITE_MULTIPLE
:
8299 command
= IDE_COMMAND_WRITE_MUL48
; break;
8300 case IDE_COMMAND_WRITE_DMA
:
8301 command
= IDE_COMMAND_WRITE_DMA48
; break;
8302 case IDE_COMMAND_WRITE_DMA_Q
:
8303 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
8304 case IDE_COMMAND_FLUSH_CACHE
:
8305 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
8306 // case IDE_COMMAND_READ_NATIVE_SIZE:
8307 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
8308 case IDE_COMMAND_SET_NATIVE_SIZE
:
8309 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
8310 case IDE_COMMAND_VERIFY
:
8311 command
= IDE_COMMAND_VERIFY48
; break;
8313 KdPrint2((PRINT_PREFIX
"!28->48 "));
8314 flags
&= ~ATA_CMD_FLAG_48supp
;
8317 KdPrint2((PRINT_PREFIX
"\t -> %2.2x (%2.2x)\n", command
, flags
));
8318 AtaCommands48
[i
] = command
;
8319 AtaCommandFlags
[i
] = flags
;
8321 } // end UniataInitAtaCommands()
8325 Routine Description:
8327 Installable driver initialization entry point for system.
8335 Status from ScsiPortInitialize()
8342 IN PVOID DriverObject
,
8346 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
8349 ULONG statusToReturn
, newStatus
;
8350 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
8351 BOOLEAN ReEnter
= FALSE
;
8354 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
8355 BOOLEAN PrimaryClaimed
= FALSE
;
8356 BOOLEAN SecondaryClaimed
= FALSE
;
8358 LARGE_INTEGER t0
, t1
;
8361 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
8362 a
= (WCHAR
)strlen(ver_string
);
8364 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
8366 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
8369 if(!SavedDriverObject
) {
8370 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8371 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8373 KeQuerySystemTime(&t0
);
8375 KeQuerySystemTime(&t1
);
8376 } while(t0
.QuadPart
== t1
.QuadPart
);
8380 KeQuerySystemTime(&t1
);
8382 } while(t0
.QuadPart
== t1
.QuadPart
);
8383 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8384 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8387 KdPrint(("UniATA Init: ReEnter\n"));
8391 // (re)read bad block list
8392 InitBadBlocks(NULL
);
8395 // init ATA command translation table
8396 UniataInitAtaCommands();
8397 // get registry path to settings
8398 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8399 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8400 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8401 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8402 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8403 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8406 if(WinVer_Id() >= WinVer_2k
) {
8407 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
8408 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
8409 WinVer_WDM_Model
= TRUE
;
8411 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
8412 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
8413 WinVer_WDM_Model
= TRUE
;
8417 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8418 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8420 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8423 statusToReturn
= 0xffffffff;
8425 // Zero out structure.
8426 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8428 // Set size of hwInitializationData.
8429 hwInitializationData
.comm
.HwInitializationDataSize
=
8430 sizeof(hwInitializationData
.comm
) +
8431 // sizeof(hwInitializationData.nt4) +
8432 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8433 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
8435 // Set entry points.
8436 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8437 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8438 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8439 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8441 // Specify size of extensions.
8442 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8443 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8444 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8446 // Indicate PIO device.
8447 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8448 // Set PnP-specific API
8449 if(WinVer_Id() > WinVer_NT
) {
8450 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
8451 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8452 KdPrint(("set AtapiAdapterControl() ptr\n"));
8453 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8456 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8459 UniataEnumBusMasterController(DriverObject
, Argument2
);
8462 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8463 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8464 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8465 for (i
=0; i
<BMListLen
; i
++) {
8467 if(!BMList
[i
].MasterDev
) {
8468 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8471 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8475 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8476 if(BMList
[i
].ChanInitOk
& 0x03) {
8477 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8479 newStatus
= STATUS_SUCCESS
;
8483 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8485 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8486 PrimaryClaimed
= TRUE
;
8487 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8488 SecondaryClaimed
= TRUE
;
8491 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8493 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
8495 for(c
=0; c
<2; c
++) {
8497 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8501 if(PrimaryClaimed
) {
8502 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8507 if(SecondaryClaimed
) {
8508 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8513 if((WinVer_Id() < WinVer_2k
)) {
8514 // do not even try if already claimed
8516 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8519 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8522 if(!WinVer_WDM_Model
) {
8523 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8525 // in WDM model things are different....
8526 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
8527 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
8529 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8530 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8532 if(!WinVer_WDM_Model
) {
8533 BMList
[i
].channel
= (UCHAR
)c
;
8536 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8537 newStatus
= ScsiPortInitialize(DriverObject
,
8539 &hwInitializationData
.comm
,
8540 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8541 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8542 if (newStatus
< statusToReturn
) {
8543 statusToReturn
= newStatus
;
8545 if (newStatus
== STATUS_SUCCESS
) {
8546 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8548 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8549 c = 1; // this will break our for()
8550 BMList[i].ChanInitOk |= 0x01 << c;
8555 if(WinVer_Id() >= WinVer_2k
) {
8556 // the following doesn't work under higher OSes
8557 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8560 if(BMList
[i
].ChanInitOk
& 0x03) {
8561 // under NT we receive status immediately, so
8562 // we can omit alternative init method id STATUS_SUCCESS returned
8563 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8566 // if (WinVer_Id() == WinVer_NT) and some error occured
8567 // try alternative init method
8570 if(WinVer_WDM_Model
) {
8571 hwInitializationData
.comm
.HwFindAdapter
= UniataFindFakeBusMasterController
;
8572 hwInitializationData
.comm
.NumberOfAccessRanges
= 5;
8573 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8575 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8576 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8577 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8578 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8580 //BMList[i].channel = 0/*(UCHAR)c*/;
8582 KdPrint2((PRINT_PREFIX
"Try init fake: %4.4s %4.4s \n",
8583 hwInitializationData
.comm
.VendorId
,
8584 hwInitializationData
.comm
.DeviceId
));
8585 newStatus
= ScsiPortInitialize(DriverObject
,
8587 &hwInitializationData
.comm
,
8589 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8593 if(BMList
[i
].ChanInitOk
& 0x03) {
8594 _PrintNtConsole(" OK\n");
8596 _PrintNtConsole(" failed\n");
8602 /* KeBugCheckEx(0xc000000e,
8603 (i << 16) | BMList[0].ChanInitOk,
8605 newStatus, statusToReturn);*/
8607 // Look for PCI IDE controller
8608 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8609 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8610 for (; i
<BMListLen
; i
++) {
8612 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8615 /* if(BMList[i].MasterDev)
8618 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8619 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
8620 BMList
[i
].busNumber
,
8621 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
8622 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
8625 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8626 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8627 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8629 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8630 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8631 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8632 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8634 BMList
[i
].channel
= 0/*(UCHAR)c*/;
8636 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
8637 hwInitializationData
.comm
.VendorId
,
8638 hwInitializationData
.comm
.DeviceId
));
8639 newStatus
= ScsiPortInitialize(DriverObject
,
8641 &hwInitializationData
.comm
,
8643 if (newStatus
< statusToReturn
)
8644 statusToReturn
= newStatus
;
8647 if(newStatus
== STATUS_SUCCESS
) {
8648 _PrintNtConsole(" OK\n");
8650 _PrintNtConsole(" failed\n");
8656 /* KeBugCheckEx(0xc000000e,
8659 newStatus, statusToReturn);*/
8663 hwInitializationData
.comm
.VendorId
= 0;
8664 hwInitializationData
.comm
.VendorIdLength
= 0;
8665 hwInitializationData
.comm
.DeviceId
= 0;
8666 hwInitializationData
.comm
.DeviceIdLength
= 0;
8668 // The adapter count is used by the find adapter routine to track how
8669 // which adapter addresses have been tested.
8671 // Indicate 2 access ranges and reset FindAdapter.
8672 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
8673 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
8675 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
8676 // Indicate ISA bustype.
8677 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8680 // Call initialization for ISA bustype.
8681 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
8682 newStatus
= ScsiPortInitialize(DriverObject
,
8684 &hwInitializationData
.comm
,
8686 if (newStatus
< statusToReturn
)
8687 statusToReturn
= newStatus
;
8689 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
8691 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
8692 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
8695 newStatus
= ScsiPortInitialize(DriverObject
,
8697 &hwInitializationData
.comm
,
8699 if (newStatus
< statusToReturn
)
8700 statusToReturn
= newStatus
;
8702 InDriverEntry
= FALSE
;
8704 KdPrint2((PRINT_PREFIX
"\n\nLeave ATAPI IDE MiniPort DriverEntry with status %#x\n", statusToReturn
));
8706 return statusToReturn
;
8708 } // end DriverEntry()
8713 BuildMechanismStatusSrb(
8714 IN PVOID HwDeviceExtension
,
8715 IN PSCSI_REQUEST_BLOCK Srb
8718 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8719 PSCSI_REQUEST_BLOCK srb
;
8721 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8723 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8725 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8727 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8728 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8729 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8730 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8732 // Set flags to disable synchronous negociation.
8733 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8735 // Set timeout to 4 seconds.
8736 srb
->TimeOutValue
= 4;
8739 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
8740 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8741 srb
->SrbExtension
= AtaReq
;
8743 // Set CDB operation code.
8744 cdb
= (PCDB
)srb
->Cdb
;
8745 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
8746 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8749 } // end BuildMechanismStatusSrb()
8751 #endif //UNIATA_CORE
8755 BuildRequestSenseSrb (
8756 IN PVOID HwDeviceExtension
,
8757 IN PSCSI_REQUEST_BLOCK Srb
8760 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8761 PSCSI_REQUEST_BLOCK srb
;
8763 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8765 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8767 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8769 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8770 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8771 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8772 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8774 // Set flags to disable synchronous negociation.
8775 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8777 // Set timeout to 2 seconds.
8778 srb
->TimeOutValue
= 4;
8781 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
8782 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
8783 srb
->SrbExtension
= AtaReq
;
8785 // Set CDB operation code.
8786 cdb
= (PCDB
)srb
->Cdb
;
8787 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
8788 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
8791 } // end BuildRequestSenseSrb()
8797 AtapiRegCheckDevLunValue(
8798 IN PVOID HwDeviceExtension
,
8799 IN PCWCH NamePrefix
,
8807 ULONG val
= Default
;
8809 val
= AtapiRegCheckParameterValue(
8810 HwDeviceExtension
, NamePrefix
, Name
, val
);
8812 if(chan
!= CHAN_NOT_SPECIFIED
) {
8813 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
8814 val
= AtapiRegCheckParameterValue(
8815 HwDeviceExtension
, namex
, Name
, val
);
8816 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
8817 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
8818 val
= AtapiRegCheckParameterValue(
8819 HwDeviceExtension
, namex
, Name
, val
);
8823 } // end AtapiRegCheckDevLunValue()
8836 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
8855 swprintf(Buffer
+j
, L
"%2.2x", a
);
8863 } // end EncodeVendorStr()
8867 AtapiRegCheckDevValue(
8868 IN PVOID HwDeviceExtension
,
8875 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8877 // WCHAR name1[11+4+5];
8878 // WCHAR name2[11+4+4+10];
8879 // WCHAR name3[11+4+4+5+20];
8880 // WCHAR name3[11+4+4+5+20+1];
8889 IN ULONG SlotNumber
;
8891 ULONG val
= Default
;
8893 KdPrint(( " Parameter %ws\n", Name
));
8895 if(deviceExtension
) {
8896 VendorID
= deviceExtension
->DevID
& 0xffff;
8897 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
8898 SlotNumber
= deviceExtension
->slotNumber
;
8902 SlotNumber
= 0xffffffff;
8905 val
= AtapiRegCheckDevLunValue(
8906 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
8908 if(deviceExtension
) {
8909 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
8911 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
8912 swprintf(namex
, L
"Parameters%s", namev
);
8913 val
= AtapiRegCheckDevLunValue(
8914 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8917 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
8918 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
8919 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
8921 swprintf(namex
, L
"Parameters%s", namev
);
8922 val
= AtapiRegCheckDevLunValue(
8923 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8925 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
8926 val
= AtapiRegCheckDevLunValue(
8927 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8929 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
8930 val
= AtapiRegCheckDevLunValue(
8931 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8933 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
8935 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
8936 swprintf(namex
, L
"Parameters%s", namev
);
8937 val
= AtapiRegCheckDevLunValue(
8938 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8940 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
8941 swprintf(namex
, L
"Parameters%s", namev
);
8942 val
= AtapiRegCheckDevLunValue(
8943 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8946 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
8948 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
8949 swprintf(namex
, L
"Parameters%s", namev
);
8950 val
= AtapiRegCheckDevLunValue(
8951 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8953 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
8954 swprintf(namex
, L
"Parameters%s", namev
);
8955 val
= AtapiRegCheckDevLunValue(
8956 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8961 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
8964 } // end AtapiRegCheckDevValue()
8967 The user must specify that Xxx is to run on the platform
8968 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
8969 Services\UniATA\Xxx:REG_DWORD:Zzz.
8971 The user can override the global setting to enable or disable Xxx on a
8972 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
8973 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
8975 If this registry value does not exist or contains the value zero then
8976 the timer to check for media change does not run.
8980 RegistryPath - pointer to the unicode string inside
8981 ...\CurrentControlSet\Services\UniATA
8982 DeviceNumber - The number of the HBA device object
8984 Returns: Registry Key value
8988 AtapiRegCheckParameterValue(
8989 IN PVOID HwDeviceExtension
,
8990 IN PCWSTR PathSuffix
,
8995 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
8997 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8999 LONG zero
= Default
;
9001 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
9004 LONG doRun
= Default
;
9006 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
9008 UNICODE_STRING paramPath
;
9010 // <SavedRegPath>\<PathSuffix> -> <Name>
9011 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
9012 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
9014 paramPath
.Length
= 0;
9015 paramPath
.MaximumLength
= RegistryPath
->Length
+
9016 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
9017 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
9018 if(!paramPath
.Buffer
) {
9019 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
9023 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
9024 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
9025 RtlAppendUnicodeToString(¶mPath
, L
"\\");
9026 RtlAppendUnicodeToString(¶mPath
, PathSuffix
);
9028 // Check for the Xxx value.
9029 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
9031 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
9032 parameters
[0].Name
= Name
;
9033 parameters
[0].EntryContext
= &doRun
;
9034 parameters
[0].DefaultType
= REG_DWORD
;
9035 parameters
[0].DefaultData
= &zero
;
9036 parameters
[0].DefaultLength
= sizeof(ULONG
);
9038 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
9039 paramPath
.Buffer
, parameters
, NULL
, NULL
);
9040 //KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
9042 ExFreePool(paramPath
.Buffer
);
9044 if(!NT_SUCCESS(status
)) {
9050 #undef ITEMS_TO_QUERY
9052 } // end AtapiRegCheckParameterValue()
9055 SCSI_ADAPTER_CONTROL_STATUS
9057 AtapiAdapterControl(
9058 IN PVOID HwDeviceExtension
,
9059 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
9063 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9064 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
9065 ULONG numberChannels
= deviceExtension
->NumberChannels
;
9069 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
9071 switch(ControlType
) {
9072 case ScsiQuerySupportedControlTypes
: {
9073 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
9074 TRUE
, // ScsiQuerySupportedControlTypes
9075 TRUE
, // ScsiStopAdapter
9076 TRUE
, // ScsiRestartAdapter
9077 FALSE
, // ScsiSetBootConfig
9078 FALSE
// ScsiSetRunningConfig
9081 ULONG lim
= ScsiAdapterControlMax
;
9084 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
9086 if(pControlTypeList
->MaxControlType
< lim
) {
9087 lim
= pControlTypeList
->MaxControlType
;
9090 for(i
= 0; i
< lim
; i
++) {
9091 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
9097 case ScsiStopAdapter
: {
9099 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
9100 // Shut down all interrupts on the adapter. They'll get re-enabled
9101 // by the initialization routines.
9102 for (c
= 0; c
< numberChannels
; c
++) {
9103 AtapiResetController(deviceExtension
, c
);
9104 AtapiDisableInterrupts(deviceExtension
, c
);
9106 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9107 // we must never get here for non-PCI
9108 status
= UniataDisconnectIntr2(HwDeviceExtension
);
9109 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
9113 case ScsiRestartAdapter
: {
9115 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
9116 // Enable all the interrupts on the adapter while port driver call
9117 // for power up an HBA that was shut down for power management
9119 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
9120 status
= UniataConnectIntr2(HwDeviceExtension
);
9121 for (c
= 0; c
< numberChannels
; c
++) {
9122 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
9123 FindDevices(HwDeviceExtension
, 0, c
);
9124 AtapiEnableInterrupts(deviceExtension
, c
);
9125 AtapiHwInitialize__(deviceExtension
, c
);
9127 if(deviceExtension
->Isr2DevObj
) {
9128 // we must never get here for non-PCI
9129 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9136 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
9137 return ScsiAdapterControlUnsuccessful
;
9141 return ScsiAdapterControlSuccess
;
9142 } // end AtapiAdapterControl()
9144 #endif //UNIATA_CORE
9163 UCHAR dbg_print_tmp_buff
[512];
9164 // UNICODE_STRING msgBuff;
9166 va_start(ap
, DebugMessage
);
9168 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
9170 dbg_print_tmp_buff
[511] = 0;
9172 HalDisplayString(dbg_print_tmp_buff
);
9176 } // end PrintNtConsole()