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
<20000; i
++) {
541 GetBaseStatus(chan
, Status
);
542 if (Status
& IDE_STATUS_BUSY
) {
543 AtapiStallExecution(150);
550 } // end WaitOnBaseBusy()
561 Status
= WaitOnBaseBusy(chan
);
562 if(!(Status
& IDE_STATUS_BUSY
))
564 for (i
=0; i
<2000; i
++) {
565 GetBaseStatus(chan
, Status
);
566 if (Status
& IDE_STATUS_BUSY
) {
567 AtapiStallExecution(250);
574 } // end WaitOnBaseBusyLong()
579 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
588 if(Status
& IDE_STATUS_BUSY
) {
591 // if(deviceExtension->HwFlags & UNIATA_SATA) {
592 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
593 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
597 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
598 if ((Status
& IDE_STATUS_BUSY
) ||
599 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
603 return IDE_STATUS_IDLE
;
604 } // end UniataIsIdle()
615 for (i
=0; i
<20000; i
++) {
616 GetStatus(chan
, Status
);
617 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
618 if(Status2
== 0xff) {
622 if(Status2
& IDE_STATUS_BUSY
) {
623 AtapiStallExecution(10);
630 } // end WaitForIdleLong()
640 for (i
=0; i
<1000; i
++) {
641 GetStatus(chan
, Status
);
642 if (Status
& IDE_STATUS_BUSY
) {
643 AtapiStallExecution(100);
644 } else if (Status
& IDE_STATUS_DRQ
) {
647 AtapiStallExecution(200);
651 } // end WaitForDrq()
661 for (i
=0; i
<2; i
++) {
662 GetStatus(chan
, Status
);
663 if (Status
& IDE_STATUS_BUSY
) {
664 AtapiStallExecution(100);
665 } else if (Status
& IDE_STATUS_DRQ
) {
668 AtapiStallExecution(100);
672 } // end WaitShortForDrq()
681 //ULONG c = chan->lChannel;
683 UCHAR dma_status
= 0;
684 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
687 GetBaseStatus(chan
, statusByte2
);
688 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
689 SelectDrive(chan
, DeviceNumber
);
690 AtapiStallExecution(500);
691 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
693 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
694 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
695 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
696 // implementation. (which is around 1 second)
697 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
700 AtapiStallExecution(30);
703 SelectDrive(chan
, DeviceNumber
);
705 GetBaseStatus(chan
, statusByte2
);
706 AtapiStallExecution(500);
708 GetBaseStatus(chan
, statusByte2
);
709 if(chan
&& chan
->DeviceExtension
) {
710 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
711 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
713 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
715 if(dma_status
& BM_STATUS_INTR
) {
716 // bullshit, we have DMA interrupt, but had never initiate DMA operation
717 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
718 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
719 GetBaseStatus(chan
, statusByte2
);
721 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
722 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
726 } // end AtapiSoftReset()
729 Send command to device.
730 Translate to 48-Lba form if required
735 IN PHW_DEVICE_EXTENSION deviceExtension
,
736 IN ULONG DeviceNumber
,
745 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
747 ULONG ldev
= lChannel
*2 + DeviceNumber
;
751 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
752 deviceExtension
->DevIndex
, deviceExtension
->Channel
, ldev
, command
, lba
, count
, feature
));
754 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
755 SelectDrive(chan
, DeviceNumber
);
757 statusByte
= WaitOnBusy(chan
);
759 /* ready to issue command ? */
760 if (statusByte
& IDE_STATUS_BUSY
) {
761 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
765 // !!! We should not check ERROR condition here
766 // ERROR bit may be asserted durring previous operation
767 // and not cleared after SELECT
769 //>>>>>> NV: 2006/08/03
770 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
771 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
772 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
773 return IDE_STATUS_ERROR
;
774 //return SRB_STATUS_ERROR;
776 //<<<<<< NV: 2006/08/03
778 /* only use 48bit addressing if needed because of the overhead */
779 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
780 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
782 KdPrint2((PRINT_PREFIX
" ldev %#x USE_LBA_48\n", ldev
));
783 /* translate command into 48bit version */
784 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
785 command
= AtaCommands48
[command
];
787 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
791 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
794 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
795 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
796 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
797 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
798 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
799 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
800 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
801 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
802 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
803 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
805 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
806 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
809 plba
= (PUCHAR
)&lba
; //ktp
810 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
813 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
814 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
816 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
817 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
818 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
819 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
820 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
821 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
822 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
824 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
825 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
829 // write command code to device
830 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
835 // caller requested wait for interrupt
838 statusByte
= WaitForDrq(chan
);
839 if (statusByte
& IDE_STATUS_DRQ
)
841 AtapiStallExecution(500);
842 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
849 // caller requested wait for entering Wait state
850 for (i
=0; i
<30 * 1000; i
++) {
852 GetStatus(chan
, statusByte
);
853 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
854 if(statusByte
== 0xff) {
858 if(statusByte
& IDE_STATUS_ERROR
) {
861 if(statusByte
& IDE_STATUS_BUSY
) {
862 AtapiStallExecution(100);
865 if(statusByte
== IDE_STATUS_IDLE
) {
868 //if(deviceExtension->HwFlags & UNIATA_SATA) {
869 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
872 AtapiStallExecution(100);
875 //statusByte |= IDE_STATUS_BUSY;
879 statusByte
= WaitOnBusyLong(chan
);
881 case ATA_WAIT_BASE_READY
:
882 statusByte
= WaitOnBaseBusyLong(chan
);
885 GetStatus(chan
, statusByte
);
886 if (statusByte
& IDE_STATUS_ERROR
) {
887 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
888 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
891 KdPrint2((PRINT_PREFIX
" try to continue\n"));
892 statusByte
&= ~IDE_STATUS_ERROR
;
894 chan
->ExpectingInterrupt
= TRUE
;
896 InterlockedExchange(&(chan
->CheckIntr
),
902 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
905 } // end AtaCommand48()
908 Send command to device.
909 This is simply wrapper for AtaCommand48()
914 IN PHW_DEVICE_EXTENSION deviceExtension
,
915 IN ULONG DeviceNumber
,
926 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
928 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
929 count
, feature
, flags
);
930 } // end AtaCommand()
934 AtaPio2Mode(LONG pio
)
937 default: return ATA_PIO
;
938 case 0: return ATA_PIO0
;
939 case 1: return ATA_PIO1
;
940 case 2: return ATA_PIO2
;
941 case 3: return ATA_PIO3
;
942 case 4: return ATA_PIO4
;
943 case 5: return ATA_PIO5
;
945 } // end AtaPio2Mode()
949 AtaPioMode(PIDENTIFY_DATA2 ident
)
951 if (ident
->PioTimingsValid
) {
952 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
954 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
956 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
959 if (ident
->PioCycleTimingMode
== 2)
961 if (ident
->PioCycleTimingMode
== 1)
963 if (ident
->PioCycleTimingMode
== 0)
966 } // end AtaPioMode()
970 AtaWmode(PIDENTIFY_DATA2 ident
)
972 if (ident
->MultiWordDMASupport
& 0x04)
974 if (ident
->MultiWordDMASupport
& 0x02)
976 if (ident
->MultiWordDMASupport
& 0x01)
983 AtaUmode(PIDENTIFY_DATA2 ident
)
985 if (!ident
->UdmaModesValid
)
987 if (ident
->UltraDMASupport
& 0x40)
989 if (ident
->UltraDMASupport
& 0x20)
991 if (ident
->UltraDMASupport
& 0x10)
993 if (ident
->UltraDMASupport
& 0x08)
995 if (ident
->UltraDMASupport
& 0x04)
997 if (ident
->UltraDMASupport
& 0x02)
999 if (ident
->UltraDMASupport
& 0x01)
1010 IN PVOID HwDeviceExtension
1013 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1014 PHW_TIMER HwScsiTimer
;
1016 ULONG MiniportTimerValue
;
1017 BOOLEAN recall
= FALSE
;
1021 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1023 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1024 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1025 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1028 chan
= &deviceExtension
->chan
[lChannel
];
1032 HwScsiTimer
= chan
->HwScsiTimer
;
1033 chan
->HwScsiTimer
= NULL
;
1035 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1036 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1040 HwScsiTimer(HwDeviceExtension
);
1042 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1044 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1045 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1046 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1047 deviceExtension
->FirstDpcChan
=
1048 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1052 KeQuerySystemTime(&time
);
1053 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1055 chan
= &deviceExtension
->chan
[lChannel
];
1056 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1058 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1059 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1066 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1067 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1068 if(!MiniportTimerValue
)
1069 MiniportTimerValue
= 1;
1071 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1072 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1079 } // end AtapiTimerDpc()
1082 Wrapper for ScsiPort, that implements smart Dpc
1083 queueing. We need it to allow parallel functioning
1084 of IDE channles with shared interrupt. Standard Dpc mechanism
1085 cancels previous Dpc request (if any), but we need Dpc queue.
1090 IN PVOID HwDeviceExtension
,
1092 IN PHW_TIMER HwScsiTimer
,
1093 IN ULONG MiniportTimerValue
1096 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1098 LARGE_INTEGER time2
;
1100 PHW_CHANNEL prev_chan
;
1102 // BOOLEAN UseRequestTimerCall = TRUE;
1104 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1105 KeQuerySystemTime(&time
);
1107 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1108 time
.QuadPart
+= MiniportTimerValue
*10;
1109 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1111 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1113 i
= deviceExtension
->FirstDpcChan
;
1114 chan
= prev_chan
= NULL
;
1115 while(i
!= CHAN_NOT_SPECIFIED
) {
1117 chan
= &deviceExtension
->chan
[i
];
1118 if(chan
->DpcTime
> time
.QuadPart
) {
1121 i
= chan
->NextDpcChan
;
1123 chan
= &deviceExtension
->chan
[lChannel
];
1125 deviceExtension
->FirstDpcChan
= lChannel
;
1127 prev_chan
->NextDpcChan
= lChannel
;
1129 chan
->NextDpcChan
= i
;
1130 chan
->HwScsiTimer
= HwScsiTimer
;
1131 chan
->DpcTime
= time
.QuadPart
;
1133 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1134 if(time
.QuadPart
<= time2
.QuadPart
) {
1135 MiniportTimerValue
= 1;
1137 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1140 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1141 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1143 MiniportTimerValue
);
1145 } // end AtapiQueueTimerDpc()
1147 #endif //UNIATA_CORE
1156 UCHAR statusByteAlt
;
1158 GetStatus(chan
, statusByteAlt
);
1159 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1161 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1162 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1163 KdPrint2((PRINT_PREFIX
1164 " Reg_%#x (%#x) = %#x\n",
1166 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1169 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1170 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1171 KdPrint2((PRINT_PREFIX
1172 " BM_%#x (%#x) = %#x\n",
1174 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1178 } // end UniataDumpATARegs()
1182 Routine Description:
1184 Issue IDENTIFY command to a device.
1188 HwDeviceExtension - HBA miniport driver's adapter data storage
1189 DeviceNumber - Indicates which device.
1190 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1194 TRUE if all goes well.
1200 IN PVOID HwDeviceExtension
,
1201 IN ULONG DeviceNumber
,
1207 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1208 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1209 ULONG waitCount
= 50000;
1215 BOOLEAN atapiDev
= FALSE
;
1216 ULONG ldev
= (lChannel
* 2) + DeviceNumber
;
1217 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
1219 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1220 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1223 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1224 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1228 SelectDrive(chan
, DeviceNumber
);
1229 AtapiStallExecution(10);
1230 statusByte
= WaitOnBusyLong(chan
);
1231 // Check that the status register makes sense.
1232 GetBaseStatus(chan
, statusByte2
);
1234 UniataDumpATARegs(chan
);
1236 if (Command
== IDE_COMMAND_IDENTIFY
) {
1237 // Mask status byte ERROR bits.
1238 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1239 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1240 // Check if register value is reasonable.
1242 if(statusByte
!= IDE_STATUS_IDLE
) {
1244 // No reset here !!!
1245 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1247 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1248 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1249 SelectDrive(chan
, DeviceNumber
);
1250 WaitOnBusyLong(chan
);
1252 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1253 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1255 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1256 signatureHigh
== ATAPI_MAGIC_MSB
) {
1258 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (ldev %d)\n", ldev
));
1262 // We really should wait up to 31 seconds
1263 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1264 // (30 seconds for device 1)
1266 // Wait for Busy to drop.
1267 AtapiStallExecution(100);
1268 GetStatus(chan
, statusByte
);
1270 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1271 GetBaseStatus(chan
, statusByte2
);
1273 SelectDrive(chan
, DeviceNumber
);
1275 GetBaseStatus(chan
, statusByte2
);
1277 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1279 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1280 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1282 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1283 signatureHigh
== ATAPI_MAGIC_MSB
) {
1284 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev
));
1289 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1290 if (statusByte
!= IDE_STATUS_IDLE
) {
1292 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (ldev %d)\n", ldev
));
1297 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1298 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1299 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1300 statusByte
= WaitForIdleLong(chan
);
1301 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1306 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1307 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1312 for (; j
< 4*2; j
++) {
1313 // Send IDENTIFY command.
1314 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1317 if (statusByte
& IDE_STATUS_DRQ
) {
1318 // Read status to acknowledge any interrupts generated.
1319 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1320 GetBaseStatus(chan
, statusByte
);
1321 // One last check for Atapi.
1322 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1323 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1325 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1326 signatureHigh
== ATAPI_MAGIC_MSB
) {
1327 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev
));
1333 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1334 if (Command
== IDE_COMMAND_IDENTIFY
) {
1335 // Check the signature. If DRQ didn't come up it's likely Atapi.
1336 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1337 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1339 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1340 signatureHigh
== ATAPI_MAGIC_MSB
) {
1342 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev
));
1346 // Device didn't respond correctly. It will be given one more chances.
1347 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1348 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1349 GetBaseStatus(chan
, statusByte
);
1350 AtapiSoftReset(chan
,DeviceNumber
);
1352 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1353 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1355 GetBaseStatus(chan
, statusByte
);
1356 //GetStatus(chan, statusByte);
1357 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1360 // Check for error on really stupid master devices that assert random
1361 // patterns of bits in the status register at the slave address.
1362 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1363 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1367 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1368 // Suck out 256 words. After waiting for one model that asserts busy
1369 // after receiving the Packet Identify command.
1370 statusByte
= WaitForDrq(chan
);
1371 statusByte
= WaitOnBusyLong(chan
);
1372 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1374 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1375 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1376 GetBaseStatus(chan
, statusByte
);
1379 GetBaseStatus(chan
, statusByte
);
1380 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1382 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1384 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1388 // ATI/SII chipsets with memory-mapped IO hangs when
1389 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1390 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1391 KdPrint2((PRINT_PREFIX
1392 " IO_%#x (%#x), %s:\n",
1394 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1395 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1396 for(i
=0; i
<256; i
++) {
1398 KdPrint2((PRINT_PREFIX
1401 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1403 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1404 KdPrint2((PRINT_PREFIX
1406 AtapiStallExecution(1);
1407 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1410 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1412 // Work around for some IDE and one model Atapi that will present more than
1413 // 256 bytes for the Identify data.
1414 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1415 statusByte
= AtapiSuckPort2(chan
);
1417 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1418 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1421 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1422 statusByte
= WaitForDrq(chan
);
1423 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1424 GetBaseStatus(chan
, statusByte
);
1426 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1429 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1433 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1434 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1435 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1436 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1437 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1438 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1440 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1441 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1442 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1443 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1445 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1447 // Check out a few capabilities / limitations of the device.
1448 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1449 // Determine if this drive supports the MSN functions.
1450 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1452 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1453 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1455 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1456 // Determine max. block transfer for this device.
1457 LunExt
->MaximumBlockXfer
=
1458 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1460 LunExt
->NumOfSectors
= 0;
1461 if (Command
== IDE_COMMAND_IDENTIFY
) {
1462 ULONGLONG NumOfSectors
=0;
1463 ULONGLONG NativeNumOfSectors
=0;
1464 ULONGLONG cylinders
=0;
1465 ULONGLONG tmp_cylinders
=0;
1466 // Read very-old-style drive geometry
1467 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1468 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1469 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1470 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1472 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1473 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1474 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1475 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1476 // Check for HDDs > 8Gb
1477 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1478 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1479 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1480 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1482 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1483 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1484 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1486 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1488 NumOfSectors
= cylinders
*
1489 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1490 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1492 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1496 // Check for LBA mode
1497 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1498 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1499 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1500 if ( deviceExtension
->FullIdentifyData
.SupportLba
1502 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1503 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1504 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1505 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1506 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1508 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1509 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1510 goto skip_lba_staff
;
1512 // Check for LBA48 support
1513 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1514 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1515 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1516 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1518 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1520 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1521 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1522 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1524 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1526 NativeNumOfSectors
= cylinders
*
1527 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1528 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1530 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1532 if(NativeNumOfSectors
> NumOfSectors
) {
1533 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1534 NumOfSectors
= NativeNumOfSectors
;
1538 // Check drive capacity report for LBA48-capable drives.
1539 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1540 ULONG hNativeNumOfSectors
;
1541 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1543 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1544 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1546 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1547 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1548 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1549 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1551 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1554 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1555 NativeNumOfSectors
|=
1556 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1557 hNativeNumOfSectors
=
1558 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1559 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1560 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1562 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1564 // Some drives report LBA48 capability while has capacity below 128Gb
1565 // Probably they support large block-counters.
1566 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1567 // Here we check this
1568 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1569 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1571 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1572 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1574 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1575 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1576 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1577 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1578 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1579 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1580 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1584 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1585 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1586 NativeNumOfSectors
= 0;
1590 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1591 NativeNumOfSectors
> NumOfSectors
) {
1593 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1594 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1596 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1597 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1598 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1599 NumOfSectors
= NativeNumOfSectors
;
1605 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1606 // check for native LBA size
1607 // some drives report ~32Gb in Identify Block
1608 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1610 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1611 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1613 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1614 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1615 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1616 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1617 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1619 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1621 if(NativeNumOfSectors
> NumOfSectors
) {
1623 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1624 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1626 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1627 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1628 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1629 NumOfSectors
= NativeNumOfSectors
;
1635 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1637 // fill IdentifyData with bogus geometry
1638 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1639 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1640 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1641 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1642 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1643 // ok, we can keep original values
1644 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1645 LunExt
->opt_GeomType
= GEOM_ORIG
;
1648 tmp_cylinders
= NumOfSectors
/ (255*63);
1649 if(tmp_cylinders
< 0xffff) {
1650 // we can use generic values for H/S for generic geometry approach
1651 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1652 LunExt
->opt_GeomType
= GEOM_STD
;
1655 // we should use UNIATA geometry approach
1656 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1657 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1661 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1663 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1664 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1665 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1667 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1668 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1670 cylinders
= NumOfSectors
/ (255*63);
1671 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1673 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1674 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1676 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1677 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1678 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1680 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1682 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1683 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1684 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1686 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1688 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1689 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1690 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1692 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1694 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1695 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1696 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1698 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1699 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1700 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1703 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1704 cylinders
= tmp_cylinders
;
1706 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1707 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1711 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1712 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1713 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1715 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1716 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1717 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1719 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1720 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1721 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1725 LunExt
->NumOfSectors
= NumOfSectors
;
1726 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1727 deviceExtension->FullIdentifyData.DoubleWordIo) {
1728 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1732 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1733 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1735 InitBadBlocks(LunExt
);
1737 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1738 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1740 // This device interrupts with the assertion of DRQ after receiving
1741 // Atapi Packet Command
1742 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1743 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1746 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1749 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1751 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1753 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1754 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1756 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1757 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1758 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1759 // set CD default costs
1760 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1761 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1762 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1763 statusByte
= WaitForDrq(chan
);
1765 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1766 LunExt
->IdentifyData
.DeviceType
));
1769 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1772 GetBaseStatus(chan
, statusByte
);
1773 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1776 } // end IssueIdentify()
1781 Routine Description:
1782 Set drive parameters using the IDENTIFY data.
1785 HwDeviceExtension - HBA miniport driver's adapter data storage
1786 DeviceNumber - Indicates which device.
1789 TRUE if all goes well.
1795 IN PVOID HwDeviceExtension
,
1796 IN ULONG DeviceNumber
,
1800 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1801 PIDENTIFY_DATA2 identifyData
= &deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].IdentifyData
;
1806 if(deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].DeviceFlags
&
1807 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1810 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1811 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1813 // Send SET PARAMETER command.
1814 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1815 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1816 (identifyData
->NumberOfHeads
- 1), 0,
1817 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1819 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1820 if(statusByte
& IDE_STATUS_ERROR
) {
1821 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1822 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1823 errorByte
, statusByte
));
1827 if(statusByte
== IDE_STATUS_IDLE
) {
1833 } // end SetDriveParameters()
1838 PHW_LU_EXTENSION LunExt
1841 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
1842 } // end UniataForgetDevice()
1847 Routine Description:
1848 Reset IDE controller and/or Atapi device.
1851 HwDeviceExtension - HBA miniport driver's adapter data storage
1860 AtapiResetController(
1861 IN PVOID HwDeviceExtension
,
1865 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1866 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1867 } // end AtapiResetController()
1872 AtapiResetController__(
1873 IN PVOID HwDeviceExtension
,
1875 IN BOOLEAN CompleteType
1878 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1879 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1880 PHW_CHANNEL chan
= NULL
;
1884 PSCSI_REQUEST_BLOCK CurSrb
;
1885 ULONG ChannelCtrlFlags
;
1886 UCHAR dma_status
= 0;
1888 ULONG slotNumber
= deviceExtension
->slotNumber
;
1889 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1890 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1892 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1894 //ULONG RevID = deviceExtension->RevID;
1895 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1899 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1901 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
1902 // we shall reset both channels on SimplexOnly devices,
1903 // It's not worth doing so on normal controllers
1905 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
1908 numberChannels
= deviceExtension
->NumberChannels
;
1911 for (; j
< numberChannels
; j
++) {
1913 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
1914 chan
= &deviceExtension
->chan
[j
];
1915 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
1916 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
1917 if(CompleteType
!= RESET_COMPLETE_NONE
) {
1919 while((CurSrb
= UniataGetCurRequest(chan
))) {
1921 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
1923 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
1924 // Check and see if we are processing an internal srb
1925 if (AtaReq
->OriginalSrb
) {
1926 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
1927 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
1928 AtaReq
->OriginalSrb
= NULL
;
1929 // NOTE: internal SRB doesn't get to SRB queue !!!
1930 CurSrb
= AtaReq
->Srb
;
1933 // Remove current request from queue
1934 UniataRemoveRequest(chan
, CurSrb
);
1936 // Check if request is in progress.
1937 ASSERT(AtaReq
->Srb
== CurSrb
);
1939 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1940 UCHAR PathId
= CurSrb
->PathId
;
1941 UCHAR TargetId
= CurSrb
->TargetId
;
1942 UCHAR Lun
= CurSrb
->Lun
;
1944 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
1945 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
1947 if (CurSrb
->SenseInfoBuffer
) {
1949 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
1951 senseBuffer
->ErrorCode
= 0x70;
1952 senseBuffer
->Valid
= 1;
1953 senseBuffer
->AdditionalSenseLength
= 0xb;
1954 if(CompleteType
== RESET_COMPLETE_ALL
) {
1955 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1956 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
1957 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
1958 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
1960 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1961 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
1962 senseBuffer
->AdditionalSenseCode
= 0;
1963 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
1967 // Clear request tracking fields.
1968 AtaReq
->WordsLeft
= 0;
1969 AtaReq
->DataBuffer
= NULL
;
1970 AtaReq
->TransferLength
= 0;
1972 ScsiPortNotification(RequestComplete
,
1976 // Indicate ready for next request.
1977 ScsiPortNotification(NextLuRequest
,
1983 if(CompleteType
!= RESET_COMPLETE_ALL
)
1986 #endif //UNIATA_CORE
1987 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1989 // Save control flags
1990 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
1991 // Clear expecting interrupt flag.
1992 chan
->ExpectingInterrupt
= FALSE
;
1994 chan
->ChannelCtrlFlags
= 0;
1995 InterlockedExchange(&(chan
->CheckIntr
),
1999 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2000 AtapiDisableInterrupts(deviceExtension
, j
);
2001 KdPrint2((PRINT_PREFIX
" done\n"));
2003 case ATA_INTEL_ID
: {
2006 if(!(ChipFlags
& UNIATA_SATA
))
2008 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2012 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2013 if(ChipFlags
& UNIATA_AHCI
) {
2016 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2017 GetPciConfig1(0x90, tmp8
);
2024 ChangePciConfig2(0x92, a
& ~mask
);
2025 AtapiStallExecution(10);
2026 ChangePciConfig2(0x92, a
| mask
);
2029 AtapiStallExecution(10000);
2030 GetPciConfig2(0x92, tmp16
);
2031 if ((tmp16
& (mask
<< 4)) == (mask
<< 4)) {
2032 AtapiStallExecution(10000);
2038 case ATA_NVIDIA_ID
: {
2039 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2040 if(!(ChipFlags
& UNIATA_SATA
))
2043 case ATA_SILICON_IMAGE_ID
: {
2045 ULONG Channel
= deviceExtension
->Channel
+ j
;
2046 if(!(ChipFlags
& UNIATA_SATA
))
2048 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2049 /* disable PHY state change interrupt */
2050 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2052 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2054 /* reset controller part for this channel */
2055 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2056 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2057 AtapiStallExecution(1000);
2058 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2059 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2063 case ATA_PROMISE_ID
: {
2066 if(ChipFlags
& UNIATA_SATA
) {
2067 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2068 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2071 KdPrint2((PRINT_PREFIX
" send reset\n"));
2072 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2073 IDE_DC_RESET_CONTROLLER
);
2074 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2075 AtapiStallExecution(10000);
2076 // Disable interrupts
2077 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2078 AtapiDisableInterrupts(deviceExtension
, j
);
2079 AtapiStallExecution(100);
2080 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2081 AtapiEnableInterrupts(deviceExtension
, j
);
2082 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2083 AtapiStallExecution(100000);
2084 KdPrint2((PRINT_PREFIX
" done\n"));
2089 //if(!(ChipFlags & UNIATA_SATA)) {
2090 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2091 // Reset DMA engine if active
2092 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2093 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2094 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2095 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2096 (dma_status
& BM_STATUS_INTR
)) {
2097 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2101 // all these shall be performed inside AtapiHwInitialize__() ?
2103 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2104 // Do special processing for ATAPI and IDE disk devices.
2105 for (i
= 0; i
< max_ldev
; i
++) {
2107 // Check if device present.
2108 if (!(deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2112 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2113 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2116 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2120 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2121 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2122 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2127 SelectDrive(chan
, i
);
2128 AtapiStallExecution(10);
2129 statusByte
= WaitOnBusyLong(chan
);
2130 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2131 if(statusByte
== 0xff) {
2132 KdPrint2((PRINT_PREFIX
2133 "no drive, status %#x\n",
2135 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2137 // Check for ATAPI disk.
2138 if (deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2139 // Issue soft reset and issue identify.
2140 GetStatus(chan
, statusByte
);
2141 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2144 AtapiDisableInterrupts(deviceExtension
, j
);
2145 AtapiSoftReset(chan
, i
);
2146 AtapiEnableInterrupts(deviceExtension
, j
);
2148 GetStatus(chan
, statusByte
);
2150 if(statusByte
== IDE_STATUS_SUCCESS
) {
2152 IssueIdentify(HwDeviceExtension
,
2154 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2157 KdPrint2((PRINT_PREFIX
2158 "AtapiResetController: Status after soft reset %#x\n",
2161 GetBaseStatus(chan
, statusByte
);
2164 // Issue identify and reinit after channel reset.
2166 if (statusByte
!= IDE_STATUS_IDLE
&&
2167 statusByte
!= IDE_STATUS_SUCCESS
&&
2168 statusByte
!= IDE_STATUS_DRDY
) {
2170 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2172 if(!IssueIdentify(HwDeviceExtension
,
2174 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2176 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2178 // Set disk geometry parameters.
2179 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2180 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2182 GetBaseStatus(chan
, statusByte
);
2184 // force DMA mode reinit
2185 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
|= DFLAGS_REINIT_DMA
;
2189 // Enable interrupts, note, the we can have here recursive disable
2190 AtapiStallExecution(10);
2191 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2193 chan
->DisableIntr
));
2194 AtapiEnableInterrupts(deviceExtension
, j
);
2196 // Call the HwInitialize routine to setup multi-block.
2197 AtapiHwInitialize__(deviceExtension
, j
);
2199 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2203 } // end AtapiResetController__()
2208 Routine Description:
2209 This routine maps ATAPI and IDE errors to specific SRB statuses.
2212 HwDeviceExtension - HBA miniport driver's adapter data storage
2213 Srb - IO request packet
2222 IN PVOID HwDeviceExtension
,
2223 IN PSCSI_REQUEST_BLOCK Srb
2226 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2227 ULONG lChannel
= GET_CHANNEL(Srb
);
2228 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2231 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2233 ULONG ldev
= GET_LDEV(Srb
);
2235 // Read the error register.
2237 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2238 KdPrint2((PRINT_PREFIX
2239 "MapError: Error register is %#x\n",
2242 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2244 switch (errorByte
>> 4) {
2245 case SCSI_SENSE_NO_SENSE
:
2247 KdPrint2((PRINT_PREFIX
2248 "ATAPI: No sense information\n"));
2249 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2250 srbStatus
= SRB_STATUS_ERROR
;
2253 case SCSI_SENSE_RECOVERED_ERROR
:
2255 KdPrint2((PRINT_PREFIX
2256 "ATAPI: Recovered error\n"));
2258 srbStatus
= SRB_STATUS_SUCCESS
;
2261 case SCSI_SENSE_NOT_READY
:
2263 KdPrint2((PRINT_PREFIX
2264 "ATAPI: Device not ready\n"));
2265 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2266 srbStatus
= SRB_STATUS_ERROR
;
2269 case SCSI_SENSE_MEDIUM_ERROR
:
2271 KdPrint2((PRINT_PREFIX
2272 "ATAPI: Media error\n"));
2273 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2274 srbStatus
= SRB_STATUS_ERROR
;
2277 case SCSI_SENSE_HARDWARE_ERROR
:
2279 KdPrint2((PRINT_PREFIX
2280 "ATAPI: Hardware error\n"));
2281 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2282 srbStatus
= SRB_STATUS_ERROR
;
2285 case SCSI_SENSE_ILLEGAL_REQUEST
:
2287 KdPrint2((PRINT_PREFIX
2288 "ATAPI: Illegal request\n"));
2289 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2290 srbStatus
= SRB_STATUS_ERROR
;
2293 case SCSI_SENSE_UNIT_ATTENTION
:
2295 KdPrint2((PRINT_PREFIX
2296 "ATAPI: Unit attention\n"));
2297 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2298 srbStatus
= SRB_STATUS_ERROR
;
2301 case SCSI_SENSE_DATA_PROTECT
:
2303 KdPrint2((PRINT_PREFIX
2304 "ATAPI: Data protect\n"));
2305 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2306 srbStatus
= SRB_STATUS_ERROR
;
2309 case SCSI_SENSE_BLANK_CHECK
:
2311 KdPrint2((PRINT_PREFIX
2312 "ATAPI: Blank check\n"));
2313 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2314 srbStatus
= SRB_STATUS_ERROR
;
2317 case SCSI_SENSE_ABORTED_COMMAND
:
2318 KdPrint2((PRINT_PREFIX
2319 "Atapi: Command Aborted\n"));
2320 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2321 srbStatus
= SRB_STATUS_ERROR
;
2326 KdPrint2((PRINT_PREFIX
2327 "ATAPI: Invalid sense information\n"));
2329 srbStatus
= SRB_STATUS_ERROR
;
2337 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2338 chan
->ReturningMediaStatus
= errorByte
;
2340 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2341 KdPrint2((PRINT_PREFIX
2342 "IDE: Media change\n"));
2343 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2344 srbStatus
= SRB_STATUS_ERROR
;
2346 if (Srb
->SenseInfoBuffer
) {
2348 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2350 senseBuffer
->ErrorCode
= 0x70;
2351 senseBuffer
->Valid
= 1;
2352 senseBuffer
->AdditionalSenseLength
= 0xb;
2353 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2354 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2355 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2357 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2360 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2361 KdPrint2((PRINT_PREFIX
2362 "IDE: Command abort\n"));
2363 srbStatus
= SRB_STATUS_ABORTED
;
2364 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2366 if (Srb
->SenseInfoBuffer
) {
2368 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2370 senseBuffer
->ErrorCode
= 0x70;
2371 senseBuffer
->Valid
= 1;
2372 senseBuffer
->AdditionalSenseLength
= 0xb;
2373 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2374 senseBuffer
->AdditionalSenseCode
= 0;
2375 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2377 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2380 deviceExtension
->lun
[ldev
].ErrorCount
++;
2382 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2384 KdPrint2((PRINT_PREFIX
2385 "IDE: End of media\n"));
2386 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2387 srbStatus
= SRB_STATUS_ERROR
;
2389 if (Srb
->SenseInfoBuffer
) {
2391 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2393 senseBuffer
->ErrorCode
= 0x70;
2394 senseBuffer
->Valid
= 1;
2395 senseBuffer
->AdditionalSenseLength
= 0xb;
2396 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2397 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2398 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2399 senseBuffer
->EndOfMedia
= 1;
2401 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2404 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2405 deviceExtension
->lun
[ldev
].ErrorCount
++;
2408 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2410 KdPrint2((PRINT_PREFIX
2411 "IDE: Illegal length\n"));
2412 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2414 if (Srb
->SenseInfoBuffer
) {
2416 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2418 senseBuffer
->ErrorCode
= 0x70;
2419 senseBuffer
->Valid
= 1;
2420 senseBuffer
->AdditionalSenseLength
= 0xb;
2421 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2422 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2423 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2424 senseBuffer
->IncorrectLength
= 1;
2426 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2429 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2431 KdPrint2((PRINT_PREFIX
2432 "IDE: Bad block\n"));
2433 srbStatus
= SRB_STATUS_ERROR
;
2434 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2435 if (Srb
->SenseInfoBuffer
) {
2437 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2439 senseBuffer
->ErrorCode
= 0x70;
2440 senseBuffer
->Valid
= 1;
2441 senseBuffer
->AdditionalSenseLength
= 0xb;
2442 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2443 senseBuffer
->AdditionalSenseCode
= 0;
2444 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2446 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2449 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2451 KdPrint2((PRINT_PREFIX
2452 "IDE: Id not found\n"));
2453 srbStatus
= SRB_STATUS_ERROR
;
2454 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2456 if (Srb
->SenseInfoBuffer
) {
2458 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2460 senseBuffer
->ErrorCode
= 0x70;
2461 senseBuffer
->Valid
= 1;
2462 senseBuffer
->AdditionalSenseLength
= 0xb;
2463 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2464 senseBuffer
->AdditionalSenseCode
= 0;
2465 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2467 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2470 deviceExtension
->lun
[ldev
].ErrorCount
++;
2472 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2474 KdPrint2((PRINT_PREFIX
2475 "IDE: Media change\n"));
2476 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2477 srbStatus
= SRB_STATUS_ERROR
;
2479 if (Srb
->SenseInfoBuffer
) {
2481 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2483 senseBuffer
->ErrorCode
= 0x70;
2484 senseBuffer
->Valid
= 1;
2485 senseBuffer
->AdditionalSenseLength
= 0xb;
2486 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2487 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2488 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2490 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2493 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2495 KdPrint2((PRINT_PREFIX
2496 "IDE: Data error\n"));
2497 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2498 srbStatus
= SRB_STATUS_ERROR
;
2500 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2501 deviceExtension
->lun
[ldev
].ErrorCount
++;
2504 // Build sense buffer
2505 if (Srb
->SenseInfoBuffer
) {
2507 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2509 senseBuffer
->ErrorCode
= 0x70;
2510 senseBuffer
->Valid
= 1;
2511 senseBuffer
->AdditionalSenseLength
= 0xb;
2512 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2513 senseBuffer
->AdditionalSenseCode
= 0;
2514 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2516 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2520 if (deviceExtension
->lun
[ldev
].ErrorCount
>= MAX_ERRORS
) {
2521 // deviceExtension->DWordIO = FALSE;
2523 KdPrint2((PRINT_PREFIX
2524 "MapError: ErrorCount >= MAX_ERRORS\n"));
2526 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2527 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2530 KdPrint2((PRINT_PREFIX
2531 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2534 KdPrint2((PRINT_PREFIX
2535 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2544 ScsiPortLogError( HwDeviceExtension
,
2552 // Reprogram to not use Multi-sector.
2555 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2556 !(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2558 statusByte
= AtaCommand(deviceExtension
, ldev
& 0x1, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2560 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2561 // command was aborted.
2562 if (statusByte
& IDE_STATUS_ERROR
) {
2564 // Read the error register.
2565 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2567 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2571 // Adjust the devExt. value, if necessary.
2572 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2580 // Set SCSI status to indicate a check condition.
2581 Srb
->ScsiStatus
= scsiStatus
;
2590 Routine Description:
2593 HwDeviceExtension - HBA miniport driver's adapter data storage
2596 TRUE - if initialization successful.
2597 FALSE - if initialization unsuccessful.
2603 IN PVOID HwDeviceExtension
2606 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2607 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2610 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2612 if(WinVer_WDM_Model
) {
2613 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2616 /* do extra chipset specific setups */
2617 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2619 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2620 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2621 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2624 for (c
= 0; c
< numberChannels
; c
++) {
2625 AtapiHwInitialize__(deviceExtension
, c
);
2627 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2629 } // end AtapiHwInitialize()
2633 AtapiHwInitialize__(
2634 IN PHW_DEVICE_EXTENSION deviceExtension
,
2639 UCHAR statusByte
, errorByte
;
2640 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2641 PHW_LU_EXTENSION LunExt
;
2643 ULONG PreferedMode
= 0xffffffff;
2645 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2646 FindDevices(deviceExtension
, 0, lChannel
);
2648 for (i
= lChannel
*2; i
< (lChannel
+1)*2; i
++) {
2650 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2652 LunExt
= &(deviceExtension
->lun
[i
]);
2654 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2658 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2659 AtapiStallExecution(1);
2661 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2663 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2664 // Enable media status notification
2665 IdeMediaStatus(TRUE
,deviceExtension
,(UCHAR
)i
);
2667 // If supported, setup Multi-block transfers.
2668 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2669 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2670 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2672 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2673 // command was aborted.
2674 if (statusByte
& IDE_STATUS_ERROR
) {
2676 // Read the error register.
2677 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2679 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2683 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2684 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2685 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2687 if (statusByte
& IDE_STATUS_ERROR
) {
2688 // Read the error register.
2689 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2691 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2695 // Adjust the devExt. value, if necessary.
2696 LunExt
->MaximumBlockXfer
= 0;
2699 KdPrint2((PRINT_PREFIX
2700 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2702 LunExt
->MaximumBlockXfer
));
2705 if(LunExt
->IdentifyData
.MajorRevision
) {
2707 if(LunExt
->opt_ReadCacheEnable
) {
2708 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2709 // If supported, setup read/write cacheing
2710 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2711 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2712 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2714 // Check for errors.
2715 if (statusByte
& IDE_STATUS_ERROR
) {
2716 KdPrint2((PRINT_PREFIX
2717 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2719 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2721 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2724 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2725 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2726 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2727 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2728 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2730 if(LunExt
->opt_WriteCacheEnable
) {
2731 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2732 // If supported & allowed, setup write cacheing
2733 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2734 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2735 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2736 // Check for errors.
2737 if (statusByte
& IDE_STATUS_ERROR
) {
2738 KdPrint2((PRINT_PREFIX
2739 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2741 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2743 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2746 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2747 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2748 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2749 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2750 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2754 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2757 BOOLEAN isSanyo
= FALSE
;
2760 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2762 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2763 for (j
= 0; j
< 26; j
+= 2) {
2765 // Build a buffer based on the identify data.
2766 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2769 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2771 // Inquiry string for older model had a '-', newer is '_'
2772 if (vendorId
[12] == 'C') {
2774 // Torisan changer. Set the bit. This will be used in several places
2775 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2776 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2777 LunExt
->DiscsPresent
= 3;
2783 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2784 if(PreferedMode
== 0xffffffff) {
2785 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2786 PreferedMode
= chan
->MaxTransferMode
;
2789 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2790 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2791 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2794 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2795 LunExt
->OrigTransferMode
=
2796 LunExt
->LimitedTransferMode
=
2797 LunExt
->TransferMode
=
2800 AtapiDmaInit__(deviceExtension
, i
);
2802 LunExt
->OrigTransferMode
=
2803 LunExt
->LimitedTransferMode
=
2804 LunExt
->TransferMode
;
2805 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2807 // We need to get our device ready for action before
2808 // returning from this function
2810 // According to the atapi spec 2.5 or 2.6, an atapi device
2811 // clears its status BSY bit when it is ready for atapi commands.
2812 // However, some devices (Panasonic SQ-TC500N) are still
2813 // not ready even when the status BSY is clear. They don't react
2814 // to atapi commands.
2816 // Since there is really no other indication that tells us
2817 // the drive is really ready for action. We are going to check BSY
2818 // is clear and then just wait for an arbitrary amount of time!
2820 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2823 // have to get out of the loop sometime!
2824 // 10000 * 100us = 1000,000us = 1000ms = 1s
2826 GetStatus(chan
, statusByte
);
2827 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2829 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2830 // Wait for Busy to drop.
2831 AtapiStallExecution(100);
2832 GetStatus(chan
, statusByte
);
2836 // 5000 * 100us = 500,000us = 500ms = 0.5s
2839 AtapiStallExecution(100);
2840 } while (waitCount
--);
2842 GetBaseStatus(chan
, statusByte
);
2843 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2844 AtapiStallExecution(10);
2849 } // end AtapiHwInitialize()
2856 AtapiHwInitializeChanger(
2857 IN PVOID HwDeviceExtension
,
2858 IN PSCSI_REQUEST_BLOCK Srb
,
2859 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2861 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2862 ULONG ldev
= GET_LDEV(Srb
);
2864 if (MechanismStatus
) {
2865 deviceExtension
->lun
[ldev
].DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2866 if (deviceExtension
->lun
[ldev
].DiscsPresent
> 1) {
2867 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
2871 } // end AtapiHwInitializeChanger()
2876 Routine Description:
2877 This routine will parse the string for a match on the keyword, then
2878 calculate the value for the keyword and return it to the caller.
2881 String - The ASCII string to parse.
2882 KeyWord - The keyword for the value desired.
2885 Zero if value not found
2886 Value converted from ASCII to binary.
2891 AtapiParseArgumentString(
2899 ULONG stringLength
= 0;
2900 ULONG keyWordLength
= 0;
2910 // Calculate the string length.
2916 // Calculate the keyword length.
2922 if (keyWordLength
> stringLength
) {
2924 // Can't possibly have a match.
2928 // Now setup and start the compare.
2933 // The input string may start with white space. Skip it.
2934 while (*cptr
== ' ' || *cptr
== '\t') {
2938 if (*cptr
== '\0') {
2944 while ((*cptr
== *kptr
) ||
2945 (*cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
2946 (*cptr
>= 'a' && *cptr
- ('a' - 'A') == *kptr
)) {
2950 if (*cptr
== '\0') {
2956 if (*kptr
== '\0') {
2958 // May have a match backup and check for blank or equals.
2959 while (*cptr
== ' ' || *cptr
== '\t') {
2963 // Found a match. Make sure there is an equals.
2966 // Not a match so move to the next semicolon.
2968 if (*cptr
++ == ';') {
2969 goto ContinueSearch
;
2974 // Skip the equals sign.
2977 // Skip white space.
2978 while ((*cptr
== ' ') || (*cptr
== '\t')) {
2982 if (*cptr
== '\0') {
2983 // Early end of string, return not found
2988 // This isn't it either.
2990 goto ContinueSearch
;
2994 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
2995 // Value is in Hex. Skip the "0x"
2997 for (index
= 0; *(cptr
+ index
); index
++) {
2999 if (*(cptr
+ index
) == ' ' ||
3000 *(cptr
+ index
) == '\t' ||
3001 *(cptr
+ index
) == ';') {
3005 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3006 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3008 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3009 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3010 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3011 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3013 // Syntax error, return not found.
3020 // Value is in Decimal.
3021 for (index
= 0; *(cptr
+ index
); index
++) {
3023 if (*(cptr
+ index
) == ' ' ||
3024 *(cptr
+ index
) == '\t' ||
3025 *(cptr
+ index
) == ';') {
3029 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3030 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3033 // Syntax error return not found.
3042 // Not a match check for ';' to continue search.
3044 if (*cptr
++ == ';') {
3045 goto ContinueSearch
;
3051 } // end AtapiParseArgumentString()_
3059 IN PVOID HwDeviceExtension
,
3064 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3065 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3068 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3071 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3072 // If the last command was DSC restrictive, see if it's set. If so, the device is
3073 // ready for a new request. Otherwise, reset the timer and come back to here later.
3075 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3076 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3077 // we shall have no problem with interrupt handler.
3078 if (!srb
|| chan
->ExpectingInterrupt
) {
3079 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3080 chan
->DpcState
= DPC_STATE_TIMER
;
3081 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3082 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3083 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3085 goto ReturnCallback
;
3089 if (!IS_RDP((srb
->Cdb
[0]))) {
3090 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3094 goto ReturnEnableIntr
;
3096 GetStatus(chan
, statusByte
);
3097 if (statusByte
& IDE_STATUS_DSC
) {
3099 UCHAR PathId
= srb
->PathId
;
3100 UCHAR TargetId
= srb
->TargetId
;
3101 UCHAR Lun
= srb
->Lun
;
3103 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3104 AtapiDmaDBSync(chan
, srb
);
3105 UniataRemoveRequest(chan
, srb
);
3106 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3107 // Clear current SRB.
3108 if(!deviceExtension
->simplexOnly
) {
3109 srb
= UniataGetCurRequest(chan
);
3115 // Ask for next request.
3116 ScsiPortNotification(NextLuRequest
,
3121 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3124 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3128 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3131 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3135 goto ReturnCallback
;
3140 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3141 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3142 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3143 #ifdef UNIATA_USE_XXableInterrupts
3144 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3145 // must be called on DISPATCH_LEVEL
3146 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3147 AtapiEnableInterrupts__
);
3149 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3150 InterlockedExchange(&(chan
->CheckIntr
),
3152 // Will raise IRQL to DIRQL
3153 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3154 AtapiEnableInterrupts__
,
3156 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3157 #endif // UNIATA_USE_XXableInterrupts
3159 //ASSERT(!deviceExtension->simplexOnly);
3164 // Check other channel
3165 // In simplex mode no interrupts must appear on other channels
3166 for(_c
=0; _c
<deviceExtension
->NumberChannels
-1; _c
++) {
3167 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3169 chan
= &(deviceExtension
->chan
[c
]);
3171 if((ULONG
)InterlockedCompareExchange(&chan
->CheckIntr
,
3173 CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
) {
3174 //ASSERT(!deviceExtension->simplexOnly);
3175 chan
->DpcState
= DPC_STATE_ISR
;
3176 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3177 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3181 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3184 } // end AtapiCallBack__()
3189 IN PVOID HwDeviceExtension
3192 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3195 #endif //UNIATA_CORE
3199 Routine Description:
3201 This is the interrupt service routine for ATAPI IDE miniport driver.
3205 HwDeviceExtension - HBA miniport driver's adapter data storage
3209 TRUE if expecting an interrupt.
3215 IN PVOID HwDeviceExtension
3218 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3220 BOOLEAN status
= FALSE
;
3224 BOOLEAN checked
[AHCI_MAX_PORT
];
3226 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
3228 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3229 checked
[_c
] = FALSE
;
3232 // atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
3233 for(pass
=0; pass
<2; pass
++) {
3234 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3236 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3237 //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags)
3238 // & DFLAGS_DEVICE_PRESENT;
3243 // check non-empty and expecting interrupt channels first
3244 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3249 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3251 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3252 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3255 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3257 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3258 // c_state = deviceExtension->chan[c].CheckIntr;
3259 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3260 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3262 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3264 CHECK_INTR_DETECTED
);
3265 if(c_state
== CHECK_INTR_IDLE
) {
3266 // c_state = deviceExtension->chan[c].CheckIntr;
3267 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3268 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3270 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3274 } while(c_state
== CHECK_INTR_CHECK
);
3275 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3276 // check if already serviced
3277 if(c_state
== CHECK_INTR_ACTIVE
) {
3278 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3282 if((c_state
== CHECK_INTR_DETECTED
) ||
3283 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3286 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3287 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3290 // disable interrupts on other channel of legacy mode
3291 // ISA-bridged onboard controller
3292 if(deviceExtension
->simplexOnly
/*||
3293 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3294 AtapiDisableInterrupts(deviceExtension
, !c
);
3297 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3298 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3299 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3300 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3303 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3304 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3307 // re-enable interrupts on other channel
3308 if(deviceExtension
->simplexOnly
/*||
3309 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3310 AtapiEnableInterrupts(deviceExtension
, !c
);
3314 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3315 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3320 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3322 deviceExtension
->FirstChannelToCheck
++;
3323 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3324 deviceExtension
->FirstChannelToCheck
= 0;
3327 } // end AtapiInterrupt()
3335 IN PKINTERRUPT Interrupt
,
3336 IN PVOID Isr2HwDeviceExtension
3340 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3341 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3343 BOOLEAN status
= FALSE
;
3347 // we should never get here for ISA/MCA
3348 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3349 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3353 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3354 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3356 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3357 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3361 if((ULONG
)CrNtInterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3363 CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
) {
3364 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3365 // hunt on unexpected intr (Some devices generate double interrupts,
3366 // some controllers (at least CMD649) interrupt twice with small delay.
3367 // If interrupts are disabled, they queue interrupt and re-issue it later,
3368 // when we do not expect it.
3373 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3375 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3377 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3378 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3383 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3385 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3388 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3389 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3390 // there is an active ISR/DPC for one channel, but
3391 // we have an interrupt from another one
3392 // Lets inform current ISR/DPC about new interrupt
3393 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3397 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3400 } // end AtapiInterrupt2()
3402 RETTYPE_XXableInterrupts
3405 IN PVOID HwDeviceExtension
3408 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3411 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3412 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3414 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3416 if((ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3418 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3423 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3426 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3427 AtapiDisableInterrupts(deviceExtension, lChannel);
3430 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3431 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3432 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3435 return RETVAL_XXableInterrupts
;
3436 } // end AtapiInterruptDpc()
3439 RETTYPE_XXableInterrupts
3441 AtapiEnableInterrupts__(
3442 IN PVOID HwDeviceExtension
3445 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3446 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3448 PHW_CHANNEL chan
= NULL
;
3450 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3451 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3452 chan
= &(deviceExtension
->chan
[c
]);
3454 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3455 // enable intrs on requested channel
3456 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3457 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3458 InterlockedExchange(&(chan
->CheckIntr
),
3461 // check if current or other channel(s) interrupted
3462 //AtapiInterrupt(HwDeviceExtension);
3464 if(deviceExtension
->simplexOnly
) {
3468 // check if other channel(s) interrupted
3469 // must do nothing in simplex mode
3470 if((ULONG
)CrNtInterlockedCompareExchange(&(chan
->CheckIntr
),
3472 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3475 //ASSERT(!deviceExtension->simplexOnly);
3476 chan
->DpcState
= DPC_STATE_ISR
;
3477 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3478 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3482 // In simplex mode next command must be sent to device here
3483 if(deviceExtension
->simplexOnly
&& chan
) {
3484 PSCSI_REQUEST_BLOCK srb
;
3485 chan
= UniataGetNextChannel(chan
);
3487 srb
= UniataGetCurRequest(chan
);
3492 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3496 return RETVAL_XXableInterrupts
;
3498 } // end AtapiEnableInterrupts__()
3500 #endif //UNIATA_CORE
3505 AtapiEnableInterrupts(
3506 IN PVOID HwDeviceExtension
,
3510 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3511 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3512 if(c
>= deviceExtension
->NumberChannels
) {
3515 if(!InterlockedDecrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3516 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3518 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3520 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3521 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3524 } // end AtapiEnableInterrupts()
3528 AtapiDisableInterrupts(
3529 IN PVOID HwDeviceExtension
,
3533 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3534 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3535 // mark channel as busy
3536 if(c
>= deviceExtension
->NumberChannels
) {
3539 if(InterlockedIncrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3540 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3541 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3542 deviceExtension
->chan
[c
].ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
3546 } // end AtapiDisableInterrupts()
3550 Check hardware for interrupt state
3554 AtapiCheckInterrupt__(
3555 IN PVOID HwDeviceExtension
,
3556 IN UCHAR c
// logical channel
3559 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3560 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3561 PHW_LU_EXTENSION LunExt
;
3563 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
3564 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
3567 ULONG pr_status
= 0;
3568 UCHAR dma_status
= 0;
3572 ULONG slotNumber
= deviceExtension
->slotNumber
;
3573 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
3574 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
3577 BOOLEAN DmaTransfer
= FALSE
;
3578 BOOLEAN OurInterrupt
= FALSE
;
3580 UCHAR interruptReason
;
3581 BOOLEAN EarlyIntr
= FALSE
;
3583 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
3586 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3588 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
3590 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
3591 deviceExtension
->Channel
+ c
, c
));
3593 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
3594 deviceExtension
->Channel
+ c
, c
));
3595 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3596 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
3599 // do controller-specific interrupt servicing staff
3600 if(deviceExtension
->UnknownDev
) {
3601 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
3605 if((ChipFlags
& UNIATA_AHCI
) &&
3606 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3607 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
);
3608 return OurInterrupt
;
3612 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
3613 // Such behavior was observed with Intel ICH-xxx chips
3614 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
3618 case ATA_PROMISE_ID
: {
3622 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
3626 ((Channel
) ? 0x00004000 : 0x00000400))) {
3627 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
3632 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
3633 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
3636 if(!(status
& 0x20)) {
3637 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
3642 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
3643 if(ChipFlags
& PRSATA
) {
3644 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
3645 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
3647 if(pr_status
& (0x11 << Channel
)) {
3648 // TODO: reset channel
3649 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
3652 if(!(status
& (0x01 << Channel
))) {
3653 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
3656 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
3660 case ATA_NVIDIA_ID
: {
3661 if(!(ChipFlags
& UNIATA_SATA
))
3664 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
3666 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
3667 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
3669 /* get and clear interrupt status */
3670 if(ChipFlags
& NVQ
) {
3671 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3672 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
3674 pr_status
= AtapiReadPortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3675 AtapiWritePortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
3677 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
3679 /* check for and handle connect events */
3680 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
3681 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
3683 /* check for and handle disconnect events */
3684 if((pr_status
& (0x08UL
<< shift
)) &&
3685 !((pr_status
& (0x04UL
<< shift
) &&
3686 AtapiReadPort4(chan
, IDX_SATA_SStatus
))) ) {
3687 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
3689 /* do we have any device action ? */
3690 if(!(pr_status
& (0x01UL
<< shift
))) {
3691 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
3692 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3701 KdPrint2((PRINT_PREFIX
"ATI\n"));
3702 if(ChipType
== SIIMIO
) {
3707 case ATA_SILICON_IMAGE_ID
:
3709 if(ChipType
== SIIMIO
) {
3711 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
3712 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
3713 if(reg32
== 0xffffffff) {
3714 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
3717 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
))) {
3718 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
3722 if(ChipFlags
& UNIATA_SATA
) {
3723 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
3725 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
3726 * controllers continue to assert IRQ as long as
3727 * SError bits are pending. Clear SError immediately.
3729 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3737 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3738 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
3739 return OurInterrupt
;
3741 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
3742 goto skip_dma_stat_check
;
3745 if(!(deviceExtension
->HwFlags
& SIIINTR
))
3747 GetPciConfig1(0x71, reg8
);
3748 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
3750 (Channel
? 0x08 : 0x04))) {
3754 KdPrint2((PRINT_PREFIX
" cmd our\n"));
3757 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
3764 //dma_status = GetDmaStatus(deviceExtension, lChannel);
3765 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3766 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
3769 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
3770 AtapiStallExecution(1);
3771 AtapiWritePort1(chan
, IDX_BM_Command
,
3772 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
3773 goto skip_dma_stat_check
;
3775 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3776 if(ChipFlags
& UNIATA_AHCI
) {
3779 if(ChipFlags
& UNIATA_SATA
) {
3780 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3787 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
3789 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3790 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
3791 if(dma_status
& BM_STATUS_ERR
) {
3792 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
3795 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3796 GetStatus(chan
, statusByte
);
3797 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3798 if(statusByte
& IDE_STATUS_ERROR
) {
3799 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
3807 if(dma_status
& BM_STATUS_INTR
) {
3808 // bullshit, we have DMA interrupt, but had never initiate DMA operation
3809 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
3810 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
3815 skip_dma_stat_check
:
3816 if(!(ChipFlags
& UNIATA_SATA
)) {
3817 AtapiStallExecution(1);
3820 LunExt
= &(deviceExtension
->lun
[c
*2 + chan
->cur_cdev
]);
3821 /* if drive is busy it didn't interrupt */
3822 /* the exception is DCS + BSY state of ATAPI devices */
3823 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3824 GetStatus(chan
, statusByte
);
3825 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3826 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
3828 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
3830 if (statusByte
== 0xff) {
3831 // interrupt from empty controller ?
3833 if (statusByte
& IDE_STATUS_BUSY
) {
3834 if(!chan
->ExpectingInterrupt
) {
3835 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
3836 return OurInterrupt
;
3839 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3840 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3842 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
3845 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
3846 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
3849 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
3850 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
3856 if(dma_status
& BM_STATUS_INTR
) {
3857 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
3858 /* clear interrupt and get status */
3859 GetBaseStatus(chan
, statusByte
);
3860 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
3864 if(g_WaitBusyInISR
) {
3865 GetStatus(chan
, statusByte
);
3866 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
3867 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3868 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
3869 if (!(statusByte
& IDE_STATUS_BUSY
)) {
3870 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
3872 if (statusByte
& IDE_STATUS_BUSY
) {
3873 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
3880 /* clear interrupt and get status */
3881 GetBaseStatus(chan
, statusByte
);
3882 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
3883 if (statusByte
== 0xff) {
3884 // interrupt from empty controller ?
3886 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
3887 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
3888 return OurInterrupt
;
3891 #ifndef UNIATA_PIO_ONLY
3893 if(!EarlyIntr
|| g_WaitBusyInISR
) {
3894 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
3896 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3897 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3901 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
3903 AtaReq
->ReqState
= REQ_STATE_EARLY_INTR
;
3909 if (!(chan
->ExpectingInterrupt
)) {
3911 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
3913 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3914 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3916 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
3917 return OurInterrupt
;
3919 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
3920 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
3921 return OurInterrupt
;
3923 //ASSERT(!chan->queue_depth || chan->cur_req);
3925 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
3928 } // end AtapiCheckInterrupt__()
3934 IN PVOID HwDeviceExtension
,
3938 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3939 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3941 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3942 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3944 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
3945 ULONG status
= SRB_STATUS_SUCCESS
;
3946 UCHAR dma_status
= 0;
3949 UCHAR statusByte
= 0,interruptReason
;
3951 BOOLEAN atapiDev
= FALSE
;
3956 BOOLEAN DmaTransfer
= FALSE
;
3958 ULONG TimerValue
= 1000;
3959 #ifdef UNIATA_USE_XXableInterrupts
3960 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
3962 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
3963 #endif // UNIATA_USE_XXableInterrupts
3964 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
3965 // BOOLEAN RestoreUseDpc = FALSE;
3966 BOOLEAN DataOverrun
= FALSE
;
3967 BOOLEAN NoStartIo
= TRUE
;
3969 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
3971 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
3972 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
3978 UCHAR OldReqState
= REQ_STATE_NONE
;
3980 PHW_LU_EXTENSION LunExt
;
3983 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3985 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
3987 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
3988 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ) {
3990 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
3994 PathId
= srb
->PathId
;
3995 TargetId
= srb
->TargetId
;
4001 goto enqueue_next_req
;
4004 ldev
= GET_LDEV2(PathId
, TargetId
, Lun
);
4005 DeviceNumber
= (UCHAR
)(ldev
& 1);
4006 LunExt
= &(deviceExtension
->lun
[ldev
]);
4007 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4008 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4010 // check if we are in ISR DPC
4012 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4013 goto ServiceInterrupt
;
4017 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4020 if (!(chan
->ExpectingInterrupt
)) {
4022 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4026 // change request state
4028 OldReqState
= AtaReq
->ReqState
;
4029 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4030 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4033 // We don't want using DPC for fast operations, like
4034 // DMA completion, sending CDB, short ATAPI transfers, etc.
4036 // We MUST use DPC, because of interprocessor synchronization
4037 // on multiprocessor platforms
4040 goto ServiceInterrupt
;
4042 switch(OldReqState
) {
4043 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4044 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4045 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4046 case REQ_STATE_DPC_WAIT_BUSY0
:
4047 case REQ_STATE_DPC_WAIT_BUSY1
:
4048 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4049 goto ServiceInterrupt
;
4050 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4051 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4055 if(!DmaTransfer
&& !atapiDev
) {
4056 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4063 goto ServiceInterrupt
;
4065 #ifdef UNIATA_USE_XXableInterrupts
4067 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4069 // shall never get here
4074 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4076 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4077 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4079 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4082 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4083 goto ServiceInterrupt
;
4084 #endif // UNIATA_USE_XXableInterrupts
4089 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4090 // We always get here when are called from timer callback, which is invoked on DRQL.
4091 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4093 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4094 // disable interrupts for this channel,
4095 // but avoid recursion and double-disable
4096 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4097 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4100 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4102 #ifdef UNIATA_USE_XXableInterrupts
4103 // Will lower IRQL to DISPATCH_LEVEL
4104 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4105 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4106 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4108 // Will raise IRQL to DIRQL
4109 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4112 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4113 #endif // UNIATA_USE_XXableInterrupts
4118 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4120 // Will raise IRQL to DIRQL
4121 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4125 #endif //UNIATA_CORE
4129 if(AtaReq
&& InDpc
) {
4130 switch(AtaReq
->ReqState
) {
4131 case REQ_STATE_DPC_WAIT_DRQ0
:
4133 case REQ_STATE_DPC_WAIT_BUSY
:
4135 case REQ_STATE_DPC_WAIT_DRQ
:
4137 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4139 case REQ_STATE_DPC_WAIT_BUSY0
:
4140 case REQ_STATE_DPC_WAIT_BUSY1
:
4141 // continue normal execution
4147 #endif //UNIATA_CORE
4149 // make additional delay for old devices (if we are not in DPC)
4150 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4154 !(deviceExtension->HwFlags & UNIATA_SATA)
4156 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4157 AtapiStallExecution(10);
4160 /* clear interrupt and get status */
4161 GetBaseStatus(chan
, statusByte
);
4163 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4165 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4169 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4175 if (statusByte
& IDE_STATUS_BUSY
) {
4176 if (deviceExtension
->DriverMustPoll
) {
4177 // Crashdump is polling and we got caught with busy asserted.
4178 // Just go away, and we will be polled again shortly.
4179 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4180 goto ReturnEnableIntr
;
4183 // Ensure BUSY is non-asserted.
4184 // make a very small idle before falling to DPC
4185 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4187 for (i
= 0; i
< k
; i
++) {
4189 GetBaseStatus(chan
, statusByte
);
4190 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4193 AtapiStallExecution(10);
4196 if (!InDpc
&& UseDpc
&& i
== 2) {
4198 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4201 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4206 AtapiStallExecution(TimerValue
);
4207 goto ServiceInterrupt
;
4208 #endif //UNIATA_CORE
4210 if (InDpc
&& i
== k
) {
4211 // reset the controller.
4212 KdPrint2((PRINT_PREFIX
4213 " Resetting due to BUSY on entry - %#x.\n",
4215 goto IntrPrepareResetController
;
4220 if(!LunExt
->IdentifyData
.MajorRevision
&&
4223 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4225 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices (2)\n"));
4226 AtapiStallExecution(10);
4228 if (statusByte
& IDE_STATUS_BUSY
) {
4229 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {
4230 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting\n"));
4232 GetStatus(chan
, statusByte
);
4233 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4234 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4235 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
4236 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4237 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4241 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4243 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4245 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4247 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4249 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4254 AtapiStallExecution(TimerValue
);
4255 #endif //UNIATA_CORE
4258 AtapiStallExecution(10);
4260 if (statusByte
& IDE_STATUS_BUSY
) {
4261 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4267 if(AtaReq
&& DmaTransfer
) {
4268 switch(OldReqState
) {
4269 case REQ_STATE_EARLY_INTR
:
4270 case REQ_STATE_DPC_WAIT_BUSY0
:
4272 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4273 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4274 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4281 // Check for error conditions.
4282 if ((statusByte
& IDE_STATUS_ERROR
) ||
4283 (dma_status
& BM_STATUS_ERR
)) {
4285 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4286 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4288 if(error & IDE_STATUS_CORRECTED_ERROR) {
4289 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4290 statusByte &= ~IDE_STATUS_ERROR;
4295 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4297 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4302 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4303 AtapiStallExecution(100);
4305 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4306 AtapiStallExecution(10);
4310 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4311 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4313 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4314 GetStatus(chan
, statusByte
);
4315 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4316 AtapiStallExecution(100);
4323 /* if this is a UDMA CRC error, reinject request */
4326 if(AtaReq
->retry
< MAX_RETRIES
) {
4327 #ifdef IO_STATISTICS
4328 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
4329 #endif //IO_STATISTICS
4331 (error & IDE_ERROR_ICRC)*/) {
4332 if(AtaReq
->retry
< MAX_RETRIES
) {
4334 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4335 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4336 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4337 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4341 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4344 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
4348 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4349 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
4351 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
4352 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
4353 if(AtaReq
->retry
< MAX_RETRIES
) {
4355 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4356 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4357 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4358 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4362 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4365 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
4369 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
4370 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
4371 // Fail this request.
4372 status
= SRB_STATUS_ERROR
;
4373 goto CompleteRequest
;
4375 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
4378 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
4379 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
4380 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
4382 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
4383 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
4384 #ifdef IO_STATISTICS
4385 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
]++;
4386 if(chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->IoCount
/3 ||
4387 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
4390 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
4391 #endif //IO_STATISTICS
4392 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", deviceExtension
->lun
[DeviceNumber
].TransferMode
));
4393 deviceExtension
->lun
[DeviceNumber
].LimitedTransferMode
=
4394 deviceExtension
->lun
[DeviceNumber
].TransferMode
;
4397 #ifdef IO_STATISTICS
4398 chan
->lun
[DeviceNumber
]->IoCount
++;
4399 #endif //IO_STATISTICS
4403 // check reason for this interrupt.
4406 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
4409 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4410 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4412 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4414 wordsThisInterrupt
= DEV_BSIZE
/2;
4422 // simulate DRQ for DMA transfers
4423 statusByte
|= IDE_STATUS_DRQ
;
4425 if (statusByte
& IDE_STATUS_DRQ
) {
4428 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4430 if (LunExt
->MaximumBlockXfer
) {
4431 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
4434 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4436 interruptReason
= 0x2;
4438 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4439 interruptReason
= 0x0;
4442 status
= SRB_STATUS_ERROR
;
4443 goto CompleteRequest
;
4446 } else if (statusByte
& IDE_STATUS_BUSY
) {
4448 //AtapiEnableInterrupts(deviceExtension, lChannel);
4449 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
4454 if (AtaReq
->WordsLeft
) {
4456 // Funky behaviour seen with PCI IDE (not all, just one).
4458 // The ISR hits with DRQ low, but comes up later.
4459 for (k
= 0; k
< 5000; k
++) {
4460 GetStatus(chan
, statusByte
);
4461 if (statusByte
& IDE_STATUS_DRQ
) {
4466 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
4468 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
4472 AtapiStallExecution(TimerValue
);
4473 goto ServiceInterrupt
;
4474 #endif //UNIATA_CORE
4476 AtapiStallExecution(100);
4479 // reset the controller.
4480 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
4482 IntrPrepareResetController
:
4483 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
4484 goto ReturnEnableIntr
;
4487 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
4491 // Command complete - verify, write, or the SMART enable/disable.
4492 // Also get_media_status
4493 interruptReason
= 0x3;
4498 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
4499 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
4500 // Write the packet.
4501 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
4502 // Send CDB to device.
4503 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
, 6, 0);
4504 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4506 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
4507 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
4508 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, srb
);
4511 goto ReturnEnableIntr
;
4513 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
4518 // Pick up bytes to transfer and convert to words.
4520 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4523 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
4525 // Covert bytes to words.
4527 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
4529 if (wordCount
!= AtaReq
->WordsLeft
) {
4530 KdPrint2((PRINT_PREFIX
4531 "AtapiInterrupt: %d words requested; %d words xferred\n",
4536 // Verify this makes sense.
4537 if (wordCount
> AtaReq
->WordsLeft
) {
4538 wordCount
= AtaReq
->WordsLeft
;
4539 KdPrint2((PRINT_PREFIX
4540 "AtapiInterrupt: Write underrun\n"));
4546 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
4547 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4549 // Transfer only words requested.
4550 wordCount
= AtaReq
->WordsLeft
;
4554 // Transfer next block.
4555 wordCount
= wordsThisInterrupt
;
4559 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4560 //ASSERT(AtaReq->WordsLeft == wordCount);
4561 AtaReq
->WordsLeft
= 0;
4562 status
= SRB_STATUS_SUCCESS
;
4563 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4564 goto CompleteRequest
;
4566 // Ensure that this is a write command.
4567 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4569 KdPrint2((PRINT_PREFIX
4570 "AtapiInterrupt: Write interrupt\n"));
4572 statusByte
= WaitOnBusy(chan
);
4574 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4579 UniataGetPioTiming(LunExt
));
4583 (PULONG
)(AtaReq
->DataBuffer
),
4585 UniataGetPioTiming(LunExt
));
4589 KdPrint3((PRINT_PREFIX
4590 "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
4594 // Fail this request.
4595 status
= SRB_STATUS_ERROR
;
4596 goto CompleteRequest
;
4599 // Advance data buffer pointer and bytes left.
4600 AtaReq
->DataBuffer
+= wordCount
;
4601 AtaReq
->WordsLeft
-= wordCount
;
4604 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4607 goto ReturnEnableIntr
;
4609 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
4614 // Pick up bytes to transfer and convert to words.
4616 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
4617 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
4619 // Covert bytes to words.
4621 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
4623 if (wordCount
!= AtaReq
->WordsLeft
) {
4624 KdPrint2((PRINT_PREFIX
4625 "AtapiInterrupt: %d words requested; %d words xferred\n",
4630 // Verify this makes sense.
4631 if (wordCount
> AtaReq
->WordsLeft
) {
4632 wordCount
= AtaReq
->WordsLeft
;
4638 // Check if words left is at least 256.
4639 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4641 // Transfer only words requested.
4642 wordCount
= AtaReq
->WordsLeft
;
4646 // Transfer next block.
4647 wordCount
= wordsThisInterrupt
;
4651 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4652 //ASSERT(AtaReq->WordsLeft == wordCount);
4653 AtaReq
->WordsLeft
= 0;
4654 status
= SRB_STATUS_SUCCESS
;
4655 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4656 goto CompleteRequest
;
4658 // Ensure that this is a read command.
4659 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4662 "AtapiInterrupt: Read interrupt\n"));*/
4664 statusByte
= WaitOnBusy(chan
);
4666 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4667 KdPrint2((PRINT_PREFIX
4668 "IdeIntr: Read %#x words\n", wordCount
));
4673 UniataGetPioTiming(LunExt
));
4674 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
4675 //KdDump(AtaReq->DataBuffer, wordCount*2);
4676 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
4677 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
4680 GetStatus(chan
, statusByte
);
4681 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4684 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
4685 AtapiSuckPort2(chan
);
4689 KdPrint2((PRINT_PREFIX
4690 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
4693 (PULONG
)(AtaReq
->DataBuffer
),
4695 UniataGetPioTiming(LunExt
));
4699 KdPrint3((PRINT_PREFIX
4700 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
4704 // Fail this request.
4705 status
= SRB_STATUS_ERROR
;
4706 goto CompleteRequest
;
4709 // Advance data buffer pointer and bytes left.
4710 AtaReq
->DataBuffer
+= wordCount
;
4711 AtaReq
->WordsLeft
-= wordCount
;
4713 // Check for read command complete.
4714 if (AtaReq
->WordsLeft
== 0) {
4716 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
4719 // Work around to make many atapi devices return correct sector size
4720 // of 2048. Also certain devices will have sector count == 0x00, check
4722 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
4723 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
4725 AtaReq
->DataBuffer
-= wordCount
;
4726 if (AtaReq
->DataBuffer
[0] == 0x00) {
4728 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
4732 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
4733 AtaReq
->DataBuffer
+= wordCount
;
4738 // Completion for IDE drives.
4739 if (AtaReq->WordsLeft) {
4740 status = SRB_STATUS_DATA_OVERRUN;
4742 status = SRB_STATUS_SUCCESS;
4745 goto CompleteRequest;
4747 status
= SRB_STATUS_SUCCESS
;
4748 goto CompleteRequest
;
4753 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4757 goto ReturnEnableIntr
;
4759 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
4761 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
4762 // Command complete.
4764 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
4765 AtaReq
->WordsLeft
= 0;
4767 if (AtaReq
->WordsLeft
) {
4768 status
= SRB_STATUS_DATA_OVERRUN
;
4770 status
= SRB_STATUS_SUCCESS
;
4773 #ifdef UNIATA_DUMP_ATAPI
4775 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4779 PCHAR ModeSelectData
;
4781 PSCSI_REQUEST_BLOCK Srb
= srb
;
4783 Cdb
= (PCDB
)(Srb
->Cdb
);
4784 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
4785 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
4786 CdbDataLen
= Srb
->DataTransferLength
;
4788 if(CdbDataLen
> 0x1000) {
4789 CdbDataLen
= 0x1000;
4793 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
4794 KdPrint2(("P:T:D=%d:%d:%d\n",
4798 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
4801 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
4802 KdPrint(("ModeSense 6\n"));
4803 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4804 ModeSelectData
= CdbData
+4;
4805 KdDump(CdbData
, CdbDataLen
);
4807 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
4808 KdPrint(("ModeSense 10\n"));
4809 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4810 ModeSelectData
= CdbData
+8;
4811 KdDump(CdbData
, CdbDataLen
);
4813 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4814 KdPrint(("Read buffer from device:\n"));
4815 KdDump(CdbData
, CdbDataLen
);
4820 #endif //UNIATA_DUMP_ATAPI
4824 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest\n"));
4825 // Check and see if we are processing our secret (mechanism status/request sense) srb
4826 if (AtaReq
->OriginalSrb
) {
4830 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
4831 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
4833 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
4834 if (status
== SRB_STATUS_SUCCESS
) {
4836 AtapiHwInitializeChanger (HwDeviceExtension
,
4838 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
4840 // Get ready to issue the original srb
4841 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4842 AtaReq
->OriginalSrb
= NULL
;
4845 // failed! Get the sense key and maybe try again
4846 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
4848 AtaReq
->OriginalSrb
);
4851 // do not enable interrupts in DPC, do not waste time, do it now!
4852 if(UseDpc && chan->DisableIntr) {
4853 AtapiEnableInterrupts(HwDeviceExtension, c);
4855 RestoreUseDpc = TRUE;
4858 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4860 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
4862 if (srbStatus
== SRB_STATUS_PENDING
) {
4863 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
4864 goto ReturnEnableIntr
;
4868 // restore state on error
4870 AtapiDisableInterrupts(HwDeviceExtension, c);
4874 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
4876 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
4878 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
4879 if (status
== SRB_STATUS_DATA_OVERRUN
) {
4880 // Check to see if we at least get mininum number of bytes
4881 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
4882 (offsetof (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
4883 status
= SRB_STATUS_SUCCESS
;
4887 if (status
== SRB_STATUS_SUCCESS
) {
4889 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
4890 chan
->MechStatusRetryCount
) {
4892 // The sense key doesn't say the last request is illegal, so try again
4893 chan
->MechStatusRetryCount
--;
4894 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
4896 AtaReq
->OriginalSrb
);
4899 // last request was illegal. No point trying again
4900 AtapiHwInitializeChanger (HwDeviceExtension
,
4902 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4904 // Get ready to issue the original srb
4905 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4906 AtaReq
->OriginalSrb
= NULL
;
4908 #endif //UNIATA_CORE
4910 // do not enable interrupts in DPC, do not waste time, do it now!
4911 if(UseDpc && chan->DisableIntr) {
4912 AtapiEnableInterrupts(HwDeviceExtension, c);
4914 RestoreUseDpc = TRUE;
4917 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4919 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
4921 if (srbStatus
== SRB_STATUS_PENDING
) {
4922 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
4923 goto ReturnEnableIntr
;
4927 // restore state on error
4929 AtapiDisableInterrupts(HwDeviceExtension, c);
4935 // If we get here, it means AtapiSendCommand() has failed
4936 // Can't recover. Pretend the original srb has failed and complete it.
4938 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
4940 if (AtaReq
->OriginalSrb
) {
4941 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
4942 AtapiHwInitializeChanger (HwDeviceExtension
,
4944 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4945 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4946 AtaReq
->OriginalSrb
= NULL
;
4949 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
4951 // fake an error and read no data
4952 status
= SRB_STATUS_ERROR
;
4953 srb
->ScsiStatus
= 0;
4954 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
4955 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
4958 } else if (status
== SRB_STATUS_ERROR
) {
4960 // Map error to specific SRB status and handle request sense.
4961 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
4962 status
= MapError(deviceExtension
,
4967 } else if(!DmaTransfer
) {
4969 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
4970 // Command complete.
4972 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
4973 // Wait for busy to drop.
4974 for (i
= 0; i
< 5*30; i
++) {
4975 GetStatus(chan
, statusByte
);
4976 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4981 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
4983 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
4987 AtapiStallExecution(TimerValue
);
4988 goto ServiceInterrupt
;
4989 #endif //UNIATA_CORE
4991 AtapiStallExecution(100);
4996 // reset the controller.
4997 KdPrint2((PRINT_PREFIX
4998 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5000 goto IntrPrepareResetController
;
5002 // Check to see if DRQ is still up.
5003 if(statusByte
& IDE_STATUS_DRQ
) {
5004 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5006 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5007 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5009 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5012 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5015 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5017 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5019 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5020 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5021 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5025 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5026 //if ((statusByte & IDE_STATUS_DRQ)) {}
5027 if((statusByte
& IDE_STATUS_DRQ
) &&
5028 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5031 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5032 for (i
= 0; i
< 200; i
++) {
5033 GetStatus(chan
, statusByte
);
5034 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5039 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5040 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5045 AtapiStallExecution(TimerValue
);
5046 goto ServiceInterrupt
;
5047 #endif //UNIATA_CORE
5049 AtapiStallExecution(100);
5053 // reset the controller.
5054 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5056 goto IntrPrepareResetController
;
5060 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5061 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5062 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5064 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5065 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5069 // Clear interrupt expecting flag.
5070 chan
->ExpectingInterrupt
= FALSE
;
5071 InterlockedExchange(&(chan
->CheckIntr
),
5074 // Sanity check that there is a current request.
5076 // Set status in SRB.
5077 srb
->SrbStatus
= (UCHAR
)status
;
5079 // Check for underflow.
5080 if(AtaReq
->WordsLeft
) {
5082 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5083 // Subtract out residual words and update if filemark hit,
5084 // setmark hit , end of data, end of media...
5085 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5086 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5087 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5089 srb
->DataTransferLength
= 0;
5092 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5095 if(status
== SRB_STATUS_SUCCESS
) {
5096 AtaReq
->WordsTransfered
+= AtaReq
->bcount
* DEV_BSIZE
/2;
5098 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5099 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5100 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5101 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5102 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5105 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5106 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5110 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5113 // Indicate command complete.
5115 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5118 if (status
== SRB_STATUS_SUCCESS
&&
5119 srb
->SenseInfoBuffer
&&
5120 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5122 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5124 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5125 senseBuffer
->ErrorCode
= 0;
5126 senseBuffer
->Valid
= 1;
5127 senseBuffer
->AdditionalSenseLength
= 0xb;
5128 senseBuffer
->SenseKey
= 0;
5129 senseBuffer
->AdditionalSenseCode
= 0;
5130 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5132 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5134 AtapiDmaDBSync(chan
, srb
);
5135 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5136 UniataRemoveRequest(chan
, srb
);
5137 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5138 ScsiPortNotification(RequestComplete
,
5144 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5145 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5147 if (status
!= SRB_STATUS_SUCCESS
) {
5148 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5149 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5152 // Build the SMART status block depending upon the completion status.
5153 cmdOutParameters
->cBufferSize
= wordCount
;
5154 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5155 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5157 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5159 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5160 cmdOutParameters
->bBuffer
[0] = RETURN_SMART_STATUS
;
5161 cmdOutParameters
->bBuffer
[1] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
5162 cmdOutParameters
->bBuffer
[2] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Unused1
);
5163 cmdOutParameters
->bBuffer
[3] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5164 cmdOutParameters
->bBuffer
[4] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
);
5165 cmdOutParameters
->bBuffer
[5] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_DriveSelect
);
5166 cmdOutParameters
->bBuffer
[6] = SMART_CMD
;
5167 cmdOutParameters
->cBufferSize
= 8;
5170 // Indicate command complete.
5171 goto IntrCompleteReq
;
5176 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5181 for (i
= 0; i
< 5; i
++) {
5182 GetStatus(chan
, statusByte
);
5183 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5184 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5188 if (statusByte
& IDE_STATUS_DSC
) {
5189 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5193 AtapiStallExecution(50);
5196 // RDP can be cleared since previous check
5198 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5204 AtapiStallExecution(TimerValue
);
5205 goto ServiceInterrupt
;
5206 #endif //UNIATA_CORE
5209 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5212 srb
= UniataGetCurRequest(chan
);
5217 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5219 ScsiPortNotification(NextRequest
,
5223 ScsiPortNotification(NextLuRequest
,
5228 // in simplex mode next command must NOT be sent here
5229 if(!deviceExtension
->simplexOnly
) {
5230 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5233 // Try to get SRB fron any non-empty queue (later)
5234 if(deviceExtension
->simplexOnly
) {
5237 #endif //UNIATA_CORE
5239 goto ReturnEnableIntr
;
5243 // Unexpected int. Catch it
5244 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
5252 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
5254 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
5255 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
5256 #ifdef UNIATA_USE_XXableInterrupts
5257 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
5258 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
5259 // must be called on DISPATCH_LEVEL
5260 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
5261 AtapiEnableInterrupts__
);
5263 AtapiEnableInterrupts(HwDeviceExtension
, c
);
5264 InterlockedExchange(&(chan
->CheckIntr
),
5266 // Will raise IRQL to DIRQL
5268 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
5269 AtapiEnableInterrupts__
,
5271 #endif // UNIATA_CORE
5272 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5273 #endif // UNIATA_USE_XXableInterrupts
5277 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
5278 // in simplex mode next command must be sent here if
5280 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
5283 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
5284 chan
= UniataGetNextChannel(chan
);
5286 srb
= UniataGetCurRequest(chan
);
5290 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
5292 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5295 #endif //UNIATA_CORE
5298 } // end AtapiInterrupt__()
5304 Routine Description:
5306 This routine handles SMART enable, disable, read attributes and threshold commands.
5310 HwDeviceExtension - HBA miniport driver's adapter data storage
5311 Srb - IO request packet
5320 IdeSendSmartCommand(
5321 IN PVOID HwDeviceExtension
,
5322 IN PSCSI_REQUEST_BLOCK Srb
5325 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5326 ULONG c
= GET_CHANNEL(Srb
);
5327 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
5328 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5329 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5330 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5331 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
5333 UCHAR statusByte
,targetId
;
5336 if (regs
->bCommandReg
!= SMART_CMD
) {
5337 KdPrint2((PRINT_PREFIX
5338 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
5339 return SRB_STATUS_INVALID_REQUEST
;
5342 targetId
= cmdInParameters
.bDriveNumber
;
5344 //TODO optimize this check
5345 if ((!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) ||
5346 (deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
5348 return SRB_STATUS_SELECTION_TIMEOUT
;
5351 chan
->SmartCommand
= regs
->bFeaturesReg
;
5353 // Determine which of the commands to carry out.
5354 switch(regs
->bFeaturesReg
) {
5355 case READ_ATTRIBUTES
:
5356 case READ_THRESHOLDS
:
5358 statusByte
= WaitOnBusy(chan
);
5360 if (statusByte
& IDE_STATUS_BUSY
) {
5361 KdPrint2((PRINT_PREFIX
5362 "IdeSendSmartCommand: Returning BUSY status\n"));
5363 return SRB_STATUS_BUSY
;
5366 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5367 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
5369 // Set data buffer pointer and words left.
5370 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5371 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
5373 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5375 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5377 regs
->bSectorNumberReg
,
5378 regs
->bSectorCountReg
,
5382 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5383 // Wait for interrupt.
5384 return SRB_STATUS_PENDING
;
5386 return SRB_STATUS_ERROR
;
5390 case RETURN_SMART_STATUS
:
5391 case ENABLE_DISABLE_AUTOSAVE
:
5392 case EXECUTE_OFFLINE_DIAGS
:
5393 case SAVE_ATTRIBUTE_VALUES
:
5395 statusByte
= WaitOnBusy(chan
);
5397 if (statusByte
& IDE_STATUS_BUSY
) {
5398 KdPrint2((PRINT_PREFIX
5399 "IdeSendSmartCommand: Returning BUSY status\n"));
5400 return SRB_STATUS_BUSY
;
5403 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5404 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
5406 // Set data buffer pointer and indicate no data transfer.
5407 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5408 AtaReq
->WordsLeft
= 0;
5410 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5412 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5414 regs
->bSectorNumberReg
,
5415 regs
->bSectorCountReg
,
5419 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5420 // Wait for interrupt.
5421 return SRB_STATUS_PENDING
;
5423 return SRB_STATUS_ERROR
;
5424 } // end switch(regs->bFeaturesReg)
5426 return SRB_STATUS_INVALID_REQUEST
;
5428 } // end IdeSendSmartCommand()
5430 #endif //UNIATA_CORE
5434 UniAtaCalculateLBARegs(
5435 PHW_LU_EXTENSION LunExt
,
5436 ULONG startingSector
,
5440 UCHAR drvSelect
,sectorNumber
;
5446 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5447 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
5448 if(LunExt
->DeviceExtension
) {
5449 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
5452 return startingSector
;
5454 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5455 LunExt
->IdentifyData
.NumberOfHeads
;
5457 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5461 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
5463 cylinder
= (USHORT
)(startingSector
/ tmp
);
5464 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5465 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5466 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
5467 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
5468 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
5471 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5472 } // end UniAtaCalculateLBARegs()
5476 UniAtaCalculateLBARegsBack(
5477 PHW_LU_EXTENSION LunExt
,
5481 ULONG drvSelect
,sectorNumber
;
5485 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5488 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5489 LunExt
->IdentifyData
.NumberOfHeads
;
5491 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5492 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5493 sectorNumber
= (UCHAR
)(lba
& 0xff);
5495 lba
= sectorNumber
-1 +
5496 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5500 } // end UniAtaCalculateLBARegsBack()
5505 Routine Description:
5507 This routine handles IDE read and writes.
5511 HwDeviceExtension - HBA miniport driver's adapter data storage
5512 Srb - IO request packet
5522 IN PVOID HwDeviceExtension
,
5523 IN PSCSI_REQUEST_BLOCK Srb
,
5527 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5528 UCHAR lChannel
= GET_CHANNEL(Srb
);
5529 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5530 PHW_LU_EXTENSION LunExt
;
5531 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5532 ULONG ldev
= GET_LDEV(Srb
);
5533 UCHAR DeviceNumber
= (UCHAR
)(ldev
& 1);
5534 ULONG startingSector
;
5536 ULONG wordCount
= 0;
5537 UCHAR statusByte
,statusByte2
;
5540 BOOLEAN use_dma
= FALSE
;
5542 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5543 LunExt
= &deviceExtension
->lun
[ldev
];
5545 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5546 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5548 if(LunExt
->opt_ReadOnly
&&
5549 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
5550 if(LunExt
->opt_ReadOnly
== 1) {
5551 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
5552 return SRB_STATUS_ERROR
;
5554 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
5555 return SRB_STATUS_SUCCESS
;
5559 // Set data buffer pointer and words left.
5560 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5562 if(AtaReq
->WordsTransfered
) {
5563 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
5564 startingSector
= (ULONG
)(UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
5565 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
5566 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
5568 AtaReq
->TransferLength
/2,
5569 AtaReq
->WordsTransfered
,
5572 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
5573 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5574 // Set up 1st block.
5575 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5576 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5577 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
5579 AtaReq
->TransferLength
/2,
5582 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5585 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
5587 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
5588 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5590 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5597 // assume best case here
5598 // we cannot reinit Dma until previous request is completed
5599 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5601 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5602 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5603 (PUCHAR
)(AtaReq
->DataBuffer
),
5604 AtaReq
->bcount
* DEV_BSIZE
)) {
5608 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5609 } else { // exec_only
5610 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5613 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5617 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5618 return SRB_STATUS_PENDING
;
5621 // if this is queued request, reinit DMA and check
5622 // if DMA mode is still available
5623 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5624 if (/*EnableDma &&*/
5625 (LunExt
->TransferMode
>= ATA_DMA
)) {
5628 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5632 // Check if write request.
5633 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5635 // Prepare read command.
5637 cmd
= IDE_COMMAND_READ_DMA
;
5639 if(LunExt
->MaximumBlockXfer
) {
5640 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5642 cmd
= IDE_COMMAND_READ
;
5646 // Prepare write command.
5648 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
5649 cmd
= IDE_COMMAND_WRITE_DMA
;
5651 if (LunExt
->MaximumBlockXfer
) {
5652 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5654 if (AtaReq
->WordsLeft
< wordCount
) {
5655 // Transfer only words requested.
5656 wordCount
= AtaReq
->WordsLeft
;
5658 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5661 wordCount
= DEV_BSIZE
/2;
5662 cmd
= IDE_COMMAND_WRITE
;
5667 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5669 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5673 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5674 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5676 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5678 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5680 (USHORT
)(AtaReq
->bcount
),
5681 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5683 if(statusByte2
!= 0xff) {
5684 GetStatus(chan
, statusByte2
);
5686 if(statusByte2
& IDE_STATUS_ERROR
) {
5687 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5688 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5689 return SRB_STATUS_ERROR
;
5692 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5694 return SRB_STATUS_PENDING
;
5697 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5699 (USHORT
)(AtaReq
->bcount
),
5700 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5703 if (!(statusByte
& IDE_STATUS_DRQ
) ||
5704 statusByte
== 0xff) {
5706 if(statusByte
== 0xff) {
5707 KdPrint2((PRINT_PREFIX
5708 "IdeReadWrite: error sending command (%#x)\n",
5711 KdPrint2((PRINT_PREFIX
5712 "IdeReadWrite: DRQ never asserted (%#x)\n",
5716 AtaReq
->WordsLeft
= 0;
5718 // Clear interrupt expecting flag.
5719 chan
->ExpectingInterrupt
= FALSE
;
5720 InterlockedExchange(&(chan
->CheckIntr
),
5723 // Clear current SRB.
5724 UniataRemoveRequest(chan
, Srb
);
5726 return (statusByte
== 0xff) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
5729 chan
->ExpectingInterrupt
= TRUE
;
5730 InterlockedExchange(&(chan
->CheckIntr
),
5733 // Write next DEV_BSIZE/2*N words.
5734 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5735 KdPrint2((PRINT_PREFIX
5736 "IdeReadWrite: Write %#x words\n", wordCount
));
5741 UniataGetPioTiming(LunExt
));
5745 KdPrint2((PRINT_PREFIX
5746 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5749 (PULONG
)(AtaReq
->DataBuffer
),
5751 UniataGetPioTiming(LunExt
));
5754 // Adjust buffer address and words left count.
5755 AtaReq
->WordsLeft
-= wordCount
;
5756 AtaReq
->DataBuffer
+= wordCount
;
5758 // Wait for interrupt.
5759 return SRB_STATUS_PENDING
;
5761 } // end IdeReadWrite()
5767 Routine Description:
5768 This routine handles IDE Verify.
5771 HwDeviceExtension - HBA miniport driver's adapter data storage
5772 Srb - IO request packet
5781 IN PVOID HwDeviceExtension
,
5782 IN PSCSI_REQUEST_BLOCK Srb
5785 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5786 UCHAR lChannel
= GET_CHANNEL(Srb
);
5787 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5788 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5789 PHW_LU_EXTENSION LunExt
;
5790 ULONG ldev
= GET_LDEV(Srb
);
5792 ULONG startingSector
;
5799 LunExt
= &deviceExtension
->lun
[ldev
];
5800 // Drive has these number sectors.
5801 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
5802 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
5803 LunExt
->IdentifyData
.NumberOfHeads
*
5804 LunExt
->IdentifyData
.NumberOfCylinders
;
5807 KdPrint2((PRINT_PREFIX
5808 "IdeVerify: Total sectors %#x\n",
5811 // Get starting sector number from CDB.
5812 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5813 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5815 KdPrint2((PRINT_PREFIX
5816 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
5820 endSector
= startingSector
+ sectorCount
;
5822 KdPrint2((PRINT_PREFIX
5823 "IdeVerify: Ending sector %#x\n",
5826 if (endSector
> sectors
) {
5828 // Too big, round down.
5829 KdPrint2((PRINT_PREFIX
5830 "IdeVerify: Truncating request to %#x blocks\n",
5831 sectors
- startingSector
- 1));
5833 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
5837 // Set up sector count register. Round up to next block.
5838 if (sectorCount
> 0xFF) {
5839 sectorCount
= (USHORT
)0xFF;
5843 // Set data buffer pointer and words left.
5844 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5845 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5847 // Indicate expecting an interrupt.
5848 InterlockedExchange(&(chan
->CheckIntr
),
5851 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5853 statusByte
= AtaCommand48(deviceExtension
, ldev
& 0x01, GET_CHANNEL(Srb
),
5854 IDE_COMMAND_VERIFY
, lba
,
5858 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5859 // Wait for interrupt.
5860 return SRB_STATUS_PENDING
;
5862 return SRB_STATUS_ERROR
;
5864 } // end IdeVerify()
5866 #endif //UNIATA_CORE
5870 Routine Description:
5871 Send ATAPI packet command to device.
5874 HwDeviceExtension - HBA miniport driver's adapter data storage
5875 Srb - IO request packet
5883 IN PVOID HwDeviceExtension
,
5884 IN PSCSI_REQUEST_BLOCK Srb
,
5888 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5889 UCHAR lChannel
= GET_CHANNEL(Srb
);
5890 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5891 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5892 ULONG ldev
= GET_LDEV(Srb
);
5895 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
5896 BOOLEAN use_dma
= FALSE
;
5897 BOOLEAN dma_reinited
= FALSE
;
5898 BOOLEAN retried
= FALSE
;
5900 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
5901 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
5902 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
5904 #ifdef UNIATA_DUMP_ATAPI
5905 if(CmdAction
& CMD_ACTION_PREPARE
) {
5909 PCHAR ModeSelectData
;
5912 Cdb
= (PCDB
)(Srb
->Cdb
);
5913 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5914 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5915 CdbDataLen
= Srb
->DataTransferLength
;
5917 if(CdbDataLen
> 0x1000) {
5918 CdbDataLen
= 0x1000;
5922 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5923 KdPrint2(("P:T:D=%d:%d:%d\n",
5927 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
5930 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
5931 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
5932 Cdb
->WRITE_CD
.LBA
[0],
5933 Cdb
->WRITE_CD
.LBA
[1],
5934 Cdb
->WRITE_CD
.LBA
[2],
5935 Cdb
->WRITE_CD
.LBA
[3]
5938 if(ScsiCommand
== SCSIOP_WRITE12
) {
5939 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
5940 Cdb
->CDB12READWRITE
.LBA
[0],
5941 Cdb
->CDB12READWRITE
.LBA
[1],
5942 Cdb
->CDB12READWRITE
.LBA
[2],
5943 Cdb
->CDB12READWRITE
.LBA
[3]
5946 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
5947 KdPrint(("ModeSelect 6\n"));
5948 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5949 ModeSelectData
= CdbData
+4;
5950 KdDump(CdbData
, CdbDataLen
);
5952 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
5953 KdPrint(("ModeSelect 10\n"));
5954 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5955 ModeSelectData
= CdbData
+8;
5956 KdDump(CdbData
, CdbDataLen
);
5958 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5959 KdPrint(("Send buffer to device:\n"));
5960 KdDump(CdbData
, CdbDataLen
);
5965 #endif //UNIATA_DUMP_ATAPI
5968 if(CmdAction
== CMD_ACTION_PREPARE
) {
5969 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
5970 switch (Srb
->Cdb
[0]) {
5974 case SCSIOP_WRITE12
:
5978 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
5979 return SRB_STATUS_BUSY
;
5982 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5983 !AtaReq
->OriginalSrb
) {
5984 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
5985 return SRB_STATUS_BUSY
;
5989 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5990 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5992 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
5993 // Set data buffer pointer and words left.
5994 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5995 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5996 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5997 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5999 // check if reorderable
6000 switch(Srb
->Cdb
[0]) {
6002 case SCSIOP_WRITE12
:
6004 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6010 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6012 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6014 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6015 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6016 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
6017 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6021 // check if DMA read/write
6022 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6023 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6025 if(AtaReq
->TransferLength
) {
6027 switch(Srb
->Cdb
[0]) {
6029 case SCSIOP_WRITE12
:
6030 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
6036 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
6038 if(AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6039 (PUCHAR
)(AtaReq
->DataBuffer
),
6040 Srb
->DataTransferLength
6041 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
6043 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6048 case SCSIOP_READ_CD
:
6049 if(deviceExtension
->opt_AtapiDmaRawRead
)
6050 goto call_dma_setup
;
6054 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
6055 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6060 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
6061 KdPrint2((PRINT_PREFIX
"dma RO\n"));
6072 if(!AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6073 (PUCHAR
)(AtaReq
->DataBuffer
),
6074 Srb
->DataTransferLength
)) {
6075 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
6078 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6082 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
6086 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6087 // if this is queued request, reinit DMA and check
6088 // if DMA mode is still available
6089 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
6090 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6091 if (/*EnableDma &&*/
6092 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6093 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
6096 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6097 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
6100 dma_reinited
= TRUE
;
6104 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6105 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
6106 return SRB_STATUS_PENDING
;
6108 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6109 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6110 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6113 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6114 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
6116 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6117 //AtapiDmaReinit(deviceExtension, ldev, AtaReq);
6118 } if(AtaReq
->TransferLength
) {
6120 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
6121 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6122 if (/*EnableDma &&*/
6123 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6126 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6131 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
6133 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6134 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
6135 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
6136 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6139 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6140 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6141 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6144 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
6147 // We need to know how many platters our atapi cd-rom device might have.
6148 // Before anyone tries to send a srb to our target for the first time,
6149 // we must "secretly" send down a separate mechanism status srb in order to
6150 // initialize our device extension changer data. That's how we know how
6151 // many platters our target has.
6153 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6154 !AtaReq
->OriginalSrb
) {
6158 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6159 // Set this flag now. If the device hangs on the mech. status
6160 // command, we will not have the chance to set it.
6161 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6163 chan
->MechStatusRetryCount
= 3;
6164 AtaReq
->OriginalSrb
= Srb
;
6165 AtaReq
->Srb
= BuildMechanismStatusSrb (
6169 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6170 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6171 if (srbStatus
== SRB_STATUS_PENDING
) {
6172 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6175 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6176 AtaReq
->OriginalSrb
= NULL
;
6177 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6178 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6179 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6183 #endif //UNIATA_CORE
6185 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
6186 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
6188 // Make sure command is to ATAPI device.
6189 flags
= deviceExtension
->lun
[ldev
].DeviceFlags
;
6190 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6191 if((Srb
->Lun
) > (deviceExtension
->lun
[ldev
].DiscsPresent
- 1)) {
6193 // Indicate no device found at this address.
6194 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6195 return SRB_STATUS_SELECTION_TIMEOUT
;
6197 } else if(Srb
->Lun
> 0) {
6198 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6199 return SRB_STATUS_SELECTION_TIMEOUT
;
6202 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
6203 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6204 return SRB_STATUS_SELECTION_TIMEOUT
;
6207 // Select device 0 or 1.
6208 SelectDrive(chan
, ldev
& 0x1);
6210 // Verify that controller is ready for next command.
6211 GetStatus(chan
, statusByte
);
6212 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
6214 if(statusByte
== 0xff) {
6215 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
6218 if(statusByte
& IDE_STATUS_BUSY
) {
6219 if(statusByte
& IDE_STATUS_DSC
) {
6220 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
6222 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
6223 // We have to make reset here, since we are expecting device to be available
6224 //return SRB_STATUS_BUSY; // this cause queue freeze
6228 if(statusByte
& IDE_STATUS_ERROR
) {
6229 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
6231 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
6232 // Read the error reg. to clear it and fail this request.
6233 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6234 return MapError(deviceExtension
, Srb
);
6236 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
6239 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
6240 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
6241 if((!(statusByte
& IDE_STATUS_DSC
)) &&
6242 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6244 AtapiStallExecution(200);
6245 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6246 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6247 return SRB_STATUS_PENDING
;
6250 if(IS_RDP(Srb
->Cdb
[0])) {
6252 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6256 if(statusByte
& IDE_STATUS_DRQ
) {
6258 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6260 // Try to drain the data that one preliminary device thinks that it has
6261 // to transfer. Hopefully this random assertion of DRQ will not be present
6262 // in production devices.
6263 for (i
= 0; i
< 0x10000; i
++) {
6264 GetStatus(chan
, statusByte
);
6265 if(statusByte
& IDE_STATUS_DRQ
) {
6266 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6274 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6276 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6278 AtapiSoftReset(chan
, ldev
& 1);
6280 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6281 // Re-initialize Atapi device.
6282 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), ldev
& 1, TRUE
);
6284 IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb),
6285 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
6287 // Inform the port driver that the bus has been reset.
6288 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6289 // Clean up device extension fields that AtapiStartIo won't.
6290 chan
->ExpectingInterrupt
= FALSE
;
6292 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6295 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6297 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
6298 return SRB_STATUS_BUS_RESET;
6301 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
6305 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
6306 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6307 return SRB_STATUS_SELECTION_TIMEOUT
;
6311 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6312 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6313 Srb
->Cdb
[1] &= ~0xE0;
6314 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6315 // Torisan changer. TUR's are overloaded to be platter switches.
6316 Srb
->Cdb
[7] = Srb
->Lun
;
6323 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6325 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6328 statusByte
= WaitOnBusy(chan
);
6329 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6332 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6333 use_dma
? ATA_F_DMA
: 0);
6335 // Write transfer byte count to registers.
6336 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6337 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6339 if (Srb
->DataTransferLength
>= 0x10000) {
6340 byteCountLow
= byteCountHigh
= 0xFF;
6343 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6344 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6346 if (flags
& DFLAGS_INT_DRQ
) {
6348 // This device interrupts when ready to receive the packet.
6350 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6353 chan
->ExpectingInterrupt
= TRUE
;
6354 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6355 InterlockedExchange(&(chan
->CheckIntr
),
6358 // Write ATAPI packet command.
6359 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6361 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
6362 return SRB_STATUS_PENDING
;
6366 // This device quickly sets DRQ when ready to receive the packet.
6368 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6371 chan
->ExpectingInterrupt
= TRUE
;
6372 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6373 InterlockedExchange(&(chan
->CheckIntr
),
6376 //AtapiDisableInterrupts(deviceExtension, lChannel);
6378 // Write ATAPI packet command.
6379 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6383 statusByte
= WaitForDrq(chan
);
6385 // Need to read status register and clear interrupt (if any)
6386 GetBaseStatus(chan
, statusByte
);
6388 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6390 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6391 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6392 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6393 return SRB_STATUS_ERROR
;
6397 GetStatus(chan
, statusByte
);
6398 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6400 // Send CDB to device.
6401 statusByte
= WaitOnBaseBusy(chan
);
6403 // Indicate expecting an interrupt and wait for it.
6404 chan
->ExpectingInterrupt
= TRUE
;
6405 InterlockedExchange(&(chan
->CheckIntr
),
6407 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6409 GetBaseStatus(chan
, statusByte
);
6411 //AtapiEnableInterrupts(deviceExtension, lChannel);
6418 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6419 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
);
6422 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6424 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6425 return SRB_STATUS_PENDING
;
6427 } // end AtapiSendCommand()
6434 Routine Description:
6435 Program ATA registers for IDE disk transfer.
6438 HwDeviceExtension - ATAPI driver storage.
6439 Srb - System request block.
6442 SRB status (pending if all goes well).
6447 ULONG check_point
= 0;
6448 #define SetCheckPoint(cp) { check_point = (cp) ; }
6450 #define SetCheckPoint(cp)
6456 IN PVOID HwDeviceExtension
,
6457 IN PSCSI_REQUEST_BLOCK Srb
,
6462 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6465 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6473 UCHAR statusByte
,errorByte
;
6476 PMODE_PARAMETER_HEADER modeData
;
6480 //ULONG __ebp__ = 0;
6482 SetCheckPoint(0x20);
6483 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6488 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6489 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6490 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6491 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6492 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6494 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6495 Srb->SrbExtension));
6496 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6499 SetCheckPoint(0x30);
6500 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6502 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6504 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6506 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6508 lChannel
= GET_CHANNEL(Srb
);
6509 chan
= &(deviceExtension
->chan
[lChannel
]);
6510 ldev
= GET_LDEV(Srb
);
6512 SetCheckPoint(0x40);
6513 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6514 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6516 if(CmdAction
== CMD_ACTION_PREPARE
) {
6517 switch (Srb
->Cdb
[0]) {
6519 case SCSIOP_INQUIRY
: // now it requires device access
6521 case SCSIOP_READ_CAPACITY
:
6524 case SCSIOP_REQUEST_SENSE
:
6526 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6531 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6532 return SRB_STATUS_BUSY
;
6536 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6537 switch (Srb
->Cdb
[0]) {
6538 case SCSIOP_INQUIRY
:
6540 KdPrint2((PRINT_PREFIX
6541 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6542 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6543 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6544 // which support up to two devices.
6545 if ((Srb
->Lun
!= 0) ||
6546 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6547 (Srb
->TargetId
> 2) /*||
6548 (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) {
6550 KdPrint2((PRINT_PREFIX
6551 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6552 // Indicate no device found at this address.
6553 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6558 KdPrint2((PRINT_PREFIX
6559 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6560 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6561 PIDENTIFY_DATA2 identifyData
= &(deviceExtension
->lun
[ldev
].IdentifyData
);
6563 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6565 if(!CheckDevice(HwDeviceExtension
, lChannel
, ldev
& 1, FALSE
)) {
6566 KdPrint2((PRINT_PREFIX
6567 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6568 // Indicate no device found at this address.
6570 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6574 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, ldev
& 1)) {
6575 KdPrint2((PRINT_PREFIX
6576 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6577 // Indicate no device found at this address.
6578 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
6580 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6585 // Zero INQUIRY data structure.
6586 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6588 // Standard IDE interface only supports disks.
6589 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6591 // Set the removable bit, if applicable.
6592 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6593 KdPrint2((PRINT_PREFIX
6594 "RemovableMedia\n"));
6595 inquiryData
->RemovableMedia
= 1;
6597 // Set the Relative Addressing (LBA) bit, if applicable.
6598 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6599 inquiryData
->RelativeAddressing
= 1;
6600 KdPrint2((PRINT_PREFIX
6601 "RelativeAddressing\n"));
6603 // Set the CommandQueue bit
6604 inquiryData
->CommandQueue
= 1;
6606 // Fill in vendor identification fields.
6607 for (i
= 0; i
< 24; i
+= 2) {
6608 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6611 // Initialize unused portion of product id.
6612 for (i = 0; i < 4; i++) {
6613 inquiryData->ProductId[12+i] = ' ';
6616 // Move firmware revision from IDENTIFY data to
6617 // product revision in INQUIRY data.
6618 for (i
= 0; i
< 4; i
+= 2) {
6619 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6622 status
= SRB_STATUS_SUCCESS
;
6627 case SCSIOP_MODE_SENSE
:
6629 KdPrint2((PRINT_PREFIX
6630 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6631 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6632 // This is used to determine if the media is write-protected.
6633 // Since IDE does not support mode sense then we will modify just the portion we need
6634 // so the higher level driver can determine if media is protected.
6635 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6637 SelectDrive(chan
, ldev
& 0x1);
6638 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6639 statusByte
= WaitOnBusy(chan
);
6641 if (!(statusByte
& IDE_STATUS_ERROR
)){
6643 // no error occured return success, media is not protected
6644 chan
->ExpectingInterrupt
= FALSE
;
6645 InterlockedExchange(&(chan
->CheckIntr
),
6647 status
= SRB_STATUS_SUCCESS
;
6651 // error occured, handle it locally, clear interrupt
6652 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6654 GetBaseStatus(chan
, statusByte
);
6655 chan
->ExpectingInterrupt
= FALSE
;
6656 InterlockedExchange(&(chan
->CheckIntr
),
6658 status
= SRB_STATUS_SUCCESS
;
6660 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6662 //media is write-protected, set bit in mode sense buffer
6663 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6665 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6666 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6669 status
= SRB_STATUS_SUCCESS
;
6671 status
= SRB_STATUS_INVALID_REQUEST
;
6675 case SCSIOP_TEST_UNIT_READY
:
6677 KdPrint2((PRINT_PREFIX
6678 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6679 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6680 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6682 // Select device 0 or 1.
6683 SelectDrive(chan
, ldev
& 0x1);
6684 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6686 // Wait for busy. If media has not changed, return success
6687 statusByte
= WaitOnBusy(chan
);
6689 if (!(statusByte
& IDE_STATUS_ERROR
)){
6690 chan
->ExpectingInterrupt
= FALSE
;
6691 InterlockedExchange(&(chan
->CheckIntr
),
6693 status
= SRB_STATUS_SUCCESS
;
6695 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6696 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6698 // Special case: If current media is write-protected,
6699 // the 0xDA command will always fail since the write-protect bit
6700 // is sticky,so we can ignore this error
6701 GetBaseStatus(chan
, statusByte
);
6702 chan
->ExpectingInterrupt
= FALSE
;
6703 InterlockedExchange(&(chan
->CheckIntr
),
6705 status
= SRB_STATUS_SUCCESS
;
6709 // Request sense buffer to be build
6710 chan
->ExpectingInterrupt
= TRUE
;
6711 InterlockedExchange(&(chan
->CheckIntr
),
6713 status
= SRB_STATUS_PENDING
;
6717 status
= SRB_STATUS_SUCCESS
;
6722 case SCSIOP_READ_CAPACITY
:
6724 KdPrint2((PRINT_PREFIX
6725 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
6726 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6727 // Claim 512 byte blocks (big-endian).
6728 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
6730 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
6732 // Calculate last sector.
6733 if(!(i
= (ULONG
)deviceExtension
->lun
[ldev
].NumOfSectors
)) {
6734 i
= deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
*
6735 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
*
6736 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
;
6740 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
6741 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
6742 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
6744 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
6746 KdPrint2((PRINT_PREFIX
6747 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
6749 deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
,
6750 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
,
6751 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
));
6754 status
= SRB_STATUS_SUCCESS
;
6759 KdPrint2((PRINT_PREFIX
6760 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
6761 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6762 status
= IdeVerify(HwDeviceExtension
,Srb
);
6769 KdPrint2((PRINT_PREFIX
6770 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
6771 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
6772 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6773 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6774 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6775 status
= IdeReadWrite(HwDeviceExtension
,
6779 case SCSIOP_START_STOP_UNIT
:
6781 KdPrint2((PRINT_PREFIX
6782 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6783 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6784 //Determine what type of operation we should perform
6785 cdb
= (PCDB
)Srb
->Cdb
;
6787 if (cdb
->START_STOP
.LoadEject
== 1){
6789 statusByte
= WaitOnBaseBusy(chan
);
6791 // first select device 0 or 1.
6792 SelectDrive(chan
, ldev
& 0x1);
6793 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
6795 status
= SRB_STATUS_SUCCESS
;
6798 case SCSIOP_MEDIUM_REMOVAL
:
6800 cdb
= (PCDB
)Srb
->Cdb
;
6802 statusByte
= WaitOnBaseBusy(chan
);
6804 SelectDrive(chan
, ldev
& 0x1);
6805 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
6806 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
6808 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
6810 status
= SRB_STATUS_SUCCESS
;
6813 // Note: I don't implement this, because NTFS driver too often issues this command
6814 // It causes awful performance degrade. However, if somebody wants, I will implement
6815 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
6818 case SCSIOP_FLUSH_BUFFER
:
6819 case SCSIOP_SYNCHRONIZE_CACHE
:
6821 SelectDrive(chan
, ldev
& 0x1);
6822 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
6823 status
= SRB_STATUS_SUCCESS
;
6824 // status = SRB_STATUS_PENDING;
6825 statusByte
= WaitOnBusy(chan
);
6829 case SCSIOP_REQUEST_SENSE
:
6830 // this function makes sense buffers to report the results
6831 // of the original GET_MEDIA_STATUS command
6833 KdPrint2((PRINT_PREFIX
6834 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6835 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6836 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6837 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
6840 status
= SRB_STATUS_INVALID_REQUEST
;
6844 case SCSIOP_ATA_PASSTHROUGH
:
6847 BOOLEAN use_dma
= FALSE
;
6850 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
6852 lChannel
= Srb
->TargetId
>> 1;
6854 regs
->bDriveHeadReg
&= 0x0f;
6855 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
6857 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
6859 KdPrint2((PRINT_PREFIX
6860 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6861 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6864 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6866 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
6867 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
6869 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6870 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
6871 (PUCHAR
)(Srb
->DataBuffer
),
6872 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
6878 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
6879 AtapiStallExecution(10);
6881 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6882 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6883 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6884 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6885 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6886 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6888 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
6889 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6890 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
6891 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6892 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
6893 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6894 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
6895 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6896 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
6897 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6899 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
6902 GetBaseStatus(chan
, statusByte
);
6903 if(statusByte
& IDE_STATUS_ERROR
) {
6904 goto passthrough_err
;
6906 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
6909 ScsiPortStallExecution(1); // wait for busy to be set
6911 if(regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) {
6912 to_lim
= Srb
->TimeOutValue
;
6914 if(Srb
->TimeOutValue
<= 2) {
6915 to_lim
= Srb
->TimeOutValue
*900;
6917 to_lim
= (Srb
->TimeOutValue
*999) - 500;
6920 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
6921 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
6922 GetBaseStatus(chan
, statusByte
);
6923 if(statusByte
& IDE_STATUS_ERROR
) {
6926 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6931 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
6933 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
6934 goto passthrough_err
;
6938 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
6940 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
6941 GetBaseStatus(chan
, statusByte
);
6943 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
6944 AtapiSuckPort2(chan
);
6946 if (Srb
->SenseInfoBuffer
) {
6948 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
6950 senseBuffer
->ErrorCode
= 0x70;
6951 senseBuffer
->Valid
= 1;
6952 senseBuffer
->AdditionalSenseLength
= 0xb;
6953 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
6954 senseBuffer
->AdditionalSenseCode
= 0;
6955 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6957 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
6958 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
6960 status
= SRB_STATUS_ERROR
;
6964 if (statusByte
& IDE_STATUS_DRQ
) {
6965 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6967 (PUSHORT
) Srb
->DataBuffer
,
6968 Srb
->DataTransferLength
/ 2,
6970 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6972 (PUSHORT
) Srb
->DataBuffer
,
6973 Srb
->DataTransferLength
/ 2,
6978 status
= SRB_STATUS_SUCCESS
;
6981 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6983 } else { // read task register
6985 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
6987 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
6989 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6990 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6991 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6992 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6993 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6994 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6996 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6997 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6998 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6999 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
7000 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
7001 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
7002 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
7003 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
7004 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
7005 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
7007 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
7008 status
= SRB_STATUS_SUCCESS
;
7015 KdPrint2((PRINT_PREFIX
7016 "IdeSendCommand: Unsupported command %#x\n",
7019 status
= SRB_STATUS_INVALID_REQUEST
;
7023 if(status
== SRB_STATUS_PENDING
) {
7024 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
7025 if(CmdAction
& CMD_ACTION_EXEC
) {
7026 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
7027 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
7030 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
7031 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7036 } // end IdeSendCommand()
7041 Routine Description:
7042 Enables disables media status notification
7045 HwDeviceExtension - ATAPI driver storage.
7052 IN PVOID HwDeviceExtension
,
7056 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7058 UCHAR lChannel
= ldev
>> 1;
7059 UCHAR statusByte
,errorByte
;
7061 chan
= &(deviceExtension
->chan
[lChannel
]);
7063 if (EnableMSN
== TRUE
){
7065 // If supported enable Media Status Notification support
7066 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
7069 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7070 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7071 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7073 if (statusByte
& IDE_STATUS_ERROR
) {
7074 // Read the error register.
7075 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7077 KdPrint2((PRINT_PREFIX
7078 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
7082 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
7083 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
7084 chan
->ReturningMediaStatus
= 0;
7089 } else { // end if EnableMSN == TRUE
7091 // disable if previously enabled
7092 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
7094 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7095 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7096 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7097 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
7104 } // end IdeMediaStatus()
7109 Routine Description:
7111 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
7112 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
7115 HwDeviceExtension - ATAPI driver storage.
7116 Srb - System request block.
7120 SRB status (ALWAYS SUCCESS).
7125 IdeBuildSenseBuffer(
7126 IN PVOID HwDeviceExtension
,
7127 IN PSCSI_REQUEST_BLOCK Srb
7130 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7132 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
7133 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
7137 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
7139 senseBuffer
->ErrorCode
= 0x70;
7140 senseBuffer
->Valid
= 1;
7141 senseBuffer
->AdditionalSenseLength
= 0xb;
7142 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7143 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7144 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7145 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
7147 senseBuffer
->ErrorCode
= 0x70;
7148 senseBuffer
->Valid
= 1;
7149 senseBuffer
->AdditionalSenseLength
= 0xb;
7150 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7151 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7152 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7153 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
7155 senseBuffer
->ErrorCode
= 0x70;
7156 senseBuffer
->Valid
= 1;
7157 senseBuffer
->AdditionalSenseLength
= 0xb;
7158 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
7159 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
7160 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7161 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
7163 senseBuffer
->ErrorCode
= 0x70;
7164 senseBuffer
->Valid
= 1;
7165 senseBuffer
->AdditionalSenseLength
= 0xb;
7166 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
7167 senseBuffer
->AdditionalSenseCode
= 0;
7168 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7170 return SRB_STATUS_SUCCESS
;
7172 return SRB_STATUS_ERROR
;
7174 }// End of IdeBuildSenseBuffer
7178 UniataUserDeviceReset(
7179 PHW_DEVICE_EXTENSION deviceExtension
,
7180 PHW_LU_EXTENSION LunExt
,
7185 AtapiDisableInterrupts(deviceExtension
, PathId
);
7186 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
7187 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
7188 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), ldev
& 1);
7190 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
7191 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
7192 deviceExtension
->chan
[PathId
].lun
[0]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7193 deviceExtension
->chan
[PathId
].lun
[1]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7195 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7196 AtapiEnableInterrupts(deviceExtension
, PathId
);
7198 } // end UniataUserDeviceReset()
7203 PHW_DEVICE_EXTENSION deviceExtension
,
7208 BOOLEAN PostReq
= FALSE
;
7210 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
7211 if(chan
->queue_depth
> 0) {
7214 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
7215 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
7216 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
7218 status
= SRB_STATUS_BUSY
;
7227 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
7231 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
7234 } // end UniataNeedQueueing()
7238 Routine Description:
7240 This routine is called from the SCSI port driver synchronized
7241 with the kernel to start an IO request.
7245 HwDeviceExtension - HBA miniport driver's adapter data storage
7246 Srb - IO request packet
7256 IN PVOID HwDeviceExtension
,
7257 IN PSCSI_REQUEST_BLOCK Srb
7260 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
7261 } // end AtapiStartIo()
7266 IN PVOID HwDeviceExtension
,
7267 IN PSCSI_REQUEST_BLOCK Srb
,
7271 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7280 PSCSI_REQUEST_BLOCK tmpSrb
;
7281 BOOLEAN PostReq
= FALSE
;
7283 BOOLEAN commPort
= FALSE
;
7285 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
7286 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7287 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7288 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7290 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7292 /* KeBugCheckEx(0xc000000e,
7293 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7295 TopLevel, 0x80000001);
7297 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7298 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7299 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7304 lChannel
= GET_CHANNEL(Srb
);
7305 chan
= &(deviceExtension
->chan
[lChannel
]);
7306 ldev
= GET_LDEV(Srb
);
7308 //ASSERT(deviceExtension);
7311 KdPrint2((PRINT_PREFIX
7312 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7313 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7314 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7316 if(lChannel
== deviceExtension
->NumberChannels
&&
7317 !Srb
->Lun
&& !Srb
->TargetId
&&
7318 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
7319 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
7321 KdPrint2((PRINT_PREFIX
7322 "AtapiStartIo: Communication port\n"));
7323 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
7325 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7327 KdPrint2((PRINT_PREFIX
7329 // Zero INQUIRY data structure.
7330 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7332 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
7334 // Fill in vendor identification fields.
7335 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
7337 status
= SRB_STATUS_SUCCESS
;
7341 /* Pass IOCTL request down */
7343 if(GET_CDEV(Srb
) >= 2 ||
7344 ldev
>= deviceExtension
->NumberChannels
*2 ||
7345 lChannel
>= deviceExtension
->NumberChannels
||
7348 if(lChannel
>= deviceExtension
->NumberChannels
) {
7353 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7354 KdPrint3((PRINT_PREFIX
7355 "AtapiStartIo: SRB rejected\n"));
7356 // Indicate no device found at this address.
7357 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7358 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7363 atapiDev
= (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7366 if(!commPort
&& !(chan
->lun
[ldev
& 1])) {
7368 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7371 deviceExtension
->NumberChannels
);
7372 PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n",
7373 lChannel
, ldev
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7374 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7375 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7379 for(i=0; i<1000; i++) {
7380 AtapiStallExecution(3*1000);
7387 // Determine which function.
7388 switch (Srb
->Function
) {
7390 case SRB_FUNCTION_EXECUTE_SCSI
:
7392 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7393 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7394 // let passthrough go
7396 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7400 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7401 KdPrint2((PRINT_PREFIX
7402 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7403 // Indicate no device found at this address.
7404 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7405 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7412 if(Srb->DataTransferLength) {
7414 a = ((PUCHAR)(Srb->DataBuffer))[0];
7417 } __except(EXCEPTION_EXECUTE_HANDLER) {
7418 KdPrint3((PRINT_PREFIX
7419 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7420 // Indicate no device found at this address.
7421 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7422 status = SRB_STATUS_ERROR;
7423 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7428 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7432 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
7434 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7435 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
7437 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7439 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7440 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7442 /*KeBugCheckEx(0xc000000e,
7443 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7445 status, 0x80000001);*/
7446 if(status
== SRB_STATUS_BUSY
)
7447 status
= SRB_STATUS_PENDING
;
7448 // Insert requests AFTER they have been initialized on
7449 // CMD_ACTION_PREPARE stage
7450 // we should not check TopLevel here (it is always TRUE)
7451 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7452 UniataQueueRequest(chan
, Srb
);
7454 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7457 // Send command to device.
7458 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7460 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7461 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7462 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7463 //ASSERT(!AtaReq->Flags);
7464 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7465 UniataQueueRequest(chan
, Srb
);
7466 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7467 //ASSERT(!AtaReq->Flags);
7468 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7469 //ASSERT(!AtaReq->Flags);
7473 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7474 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7475 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, ldev
& 1)) {
7476 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, ldev
& 1, TRUE
)) {
7480 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7484 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7493 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7494 KdPrint3((PRINT_PREFIX
"Try ATAPI send\n"));
7495 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7497 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7502 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7509 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7511 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7513 /* KeBugCheckEx(0xc000000e,
7514 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7516 status, 0x80000002);*/
7524 case SRB_FUNCTION_ABORT_COMMAND
:
7526 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7528 // Verify that SRB to abort is still outstanding.
7529 if((tmpSrb
!= Srb
->NextSrb
) ||
7530 !chan
->queue_depth
) {
7532 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7534 // Complete abort SRB.
7535 status
= SRB_STATUS_ABORT_FAILED
;
7539 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7540 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7541 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7542 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7543 // Log reset failure.
7544 KdPrint3((PRINT_PREFIX
7545 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7546 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7548 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7549 status
= SRB_STATUS_ERROR
;
7552 status
= SRB_STATUS_SUCCESS
;
7555 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7556 if (tmpSrb
->SenseInfoBuffer
&&
7557 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7559 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7561 senseBuffer
->ErrorCode
= 0;
7562 senseBuffer
->Valid
= 1;
7563 senseBuffer
->AdditionalSenseLength
= 0xb;
7564 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7565 senseBuffer
->AdditionalSenseCode
= 0;
7566 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7568 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7570 AtapiDmaDBSync(chan
, tmpSrb
);
7571 UniataRemoveRequest(chan
, tmpSrb
);
7572 // Indicate command complete.
7573 ScsiPortNotification(RequestComplete
,
7576 status
= SRB_STATUS_SUCCESS
;
7580 // Abort function indicates that a request timed out.
7581 // Call reset routine. Card will only be reset if
7582 // status indicates something is wrong.
7583 // Fall through to reset code.
7585 case SRB_FUNCTION_RESET_DEVICE
:
7586 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7588 // Reset single device.
7589 // For now we support only Lun=0
7591 // Note: reset is immediate command, it cannot be queued since it is usually used to
7592 // revert not- responding device to operational state
7593 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7594 UniataUserDeviceReset(deviceExtension
, &(deviceExtension
->lun
[ldev
]), lChannel
, ldev
);
7595 status
= SRB_STATUS_SUCCESS
;
7598 case SRB_FUNCTION_RESET_BUS
:
7600 // Reset Atapi and SCSI bus.
7602 // Note: reset is immediate command, it cannot be queued since it is usually used to
7603 // revert not- responding device to operational state
7604 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7605 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7606 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7607 // Log reset failure.
7608 KdPrint3((PRINT_PREFIX
7609 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7610 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7612 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7613 status
= SRB_STATUS_ERROR
;
7616 status
= SRB_STATUS_SUCCESS
;
7621 case SRB_FUNCTION_SHUTDOWN
:
7623 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7624 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7625 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7628 // FLUSH ATAPI device - do nothing
7629 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7631 // FLUSH IDE/ATA device
7632 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7633 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7634 status
= AtaCommand(deviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
7635 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7636 // If supported & allowed, reset write cacheing
7637 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7639 // Disable write cache
7640 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7641 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7642 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7643 // Check for errors.
7644 if (status
& IDE_STATUS_ERROR
) {
7645 KdPrint2((PRINT_PREFIX
7646 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7649 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7651 // Re-enable write cache
7652 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7653 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7654 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7655 // Check for errors.
7656 if (status
& IDE_STATUS_ERROR
) {
7657 KdPrint2((PRINT_PREFIX
7658 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7660 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7662 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7666 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7668 status
= SRB_STATUS_SUCCESS
;
7672 case SRB_FUNCTION_FLUSH
:
7674 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7675 status
= SRB_STATUS_SUCCESS
;
7678 /* case SRB_FUNCTION_SHUTDOWN:
7679 case SRB_FUNCTION_FLUSH:
7681 // Flush device's cache.
7682 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7684 if (chan->CurrentSrb) {
7686 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7687 Srb->SrbStatus = SRB_STATUS_BUSY;
7688 ScsiPortNotification(RequestComplete,
7694 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
7695 status = SRB_STATUS_SUCCESS;
7697 status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb),
7698 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
7699 if (status & IDE_STATUS_DRQ) {
7700 status = SRB_STATUS_SUCCESS;
7702 status = SRB_STATUS_SELECTION_TIMEOUT;
7707 case SRB_FUNCTION_IO_CONTROL
: {
7711 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
7713 len
= Srb
->DataTransferLength
;
7715 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
7717 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
7718 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
7720 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7723 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
7725 // Version and revision per SMART 1.03
7727 versionParameters
->bVersion
= 1;
7728 versionParameters
->bRevision
= 1;
7729 versionParameters
->bReserved
= 0;
7731 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
7732 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
7734 // This is done because of how the IOCTL_SCSI_MINIPORT
7735 // determines 'targetid's'. Disk.sys places the real target id value
7736 // in the DeviceMap field. Once we do some parameter checking, the value passed
7737 // back to the application will be determined.
7739 deviceNumber
= versionParameters
->bIDEDeviceMap
;
7742 KdPrint2((PRINT_PREFIX
7743 "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
7744 // Indicate no device found at this address.
7745 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7746 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7750 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
7753 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7757 // NOTE: This will only set the bit
7758 // corresponding to this drive's target id.
7759 // The bit mask is as follows:
7765 if (deviceExtension
->NumberChannels
== 1) {
7766 if (chan
->PrimaryAddress
) {
7767 deviceNumber
= 1 << ldev
;
7769 deviceNumber
= 4 << ldev
;
7772 deviceNumber
= 1 << ldev
;
7775 versionParameters
->bIDEDeviceMap
= deviceNumber
;
7777 status
= SRB_STATUS_SUCCESS
;
7781 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
7783 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7784 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7787 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
7788 // Extract the target.
7789 targetId
= cmdInParameters
.bDriveNumber
;
7790 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
7791 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
7792 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7793 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
7794 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7798 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
7800 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
7801 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
7802 status
= SRB_STATUS_INVALID_REQUEST
;
7808 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
7809 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
7810 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
7811 status
= SRB_STATUS_INVALID_REQUEST
;
7815 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
7816 // Zero the output buffer
7817 RtlZeroMemory(cmdOutParameters
, len
);
7818 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
7819 ((PUCHAR)cmdOutParameters)[i] = 0;
7822 // Build status block.
7823 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
7824 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
7825 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
7827 // Extract the identify data from the device extension.
7828 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
7829 cmdOutParameters
->cBufferSize
);
7831 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
7833 status
= SRB_STATUS_SUCCESS
;
7837 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
7838 cmdInParameters
.irDriveRegs
.bCommandReg
));
7839 status
= SRB_STATUS_INVALID_REQUEST
;
7845 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
7846 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
7847 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
7848 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
7849 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
7850 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
7851 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
7852 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
7855 KdPrint2((PRINT_PREFIX
7856 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
7857 // Indicate no device found at this address.
7858 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7859 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7863 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7865 if(PostReq
|| TopLevel
) {
7866 UniataQueueRequest(chan
, Srb
);
7867 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7868 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7873 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
7874 status
= SRB_STATUS_PENDING
;
7876 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7879 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
7884 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
7885 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
7886 status
= SRB_STATUS_INVALID_REQUEST
;
7891 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
7893 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
7894 ULONG ldev
= GET_LDEV2(AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
, 0);
7895 PHW_LU_EXTENSION LunExt
;
7898 //chan = &(deviceExtension->chan[lChannel]);
7900 if(AtaCtl
->addr
.Lun
||
7901 ldev
>= deviceExtension
->NumberChannels
*2 ||
7902 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
7909 LunExt
= &(deviceExtension
->lun
[ldev
]);
7910 lChannel
= AtaCtl
->addr
.PathId
;
7911 chan
= &(deviceExtension
->chan
[lChannel
]);
7914 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl
->hdr
.ControlCode
, ldev
));
7916 /* check for valid LUN */
7917 switch (AtaCtl
->hdr
.ControlCode
) {
7918 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7919 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
7921 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
7922 AtaCtl
->addr
.TargetId
!= 0xff ||
7923 AtaCtl
->addr
.Lun
!= 0
7925 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
7926 ldev
< deviceExtension
->NumberChannels
*2) { // AtaCtl->addr.TargetId != 0xff
7927 LunExt
= &(deviceExtension
->lun
[ldev
]);
7930 goto handle_bad_ldev
;
7933 // this would be BUS reset
7934 lChannel
= AtaCtl
->addr
.PathId
;
7935 chan
= &(deviceExtension
->chan
[lChannel
]);
7937 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
7938 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7939 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
7940 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7941 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
7944 KdPrint2((PRINT_PREFIX
7945 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
7946 // Indicate no device found at this address.
7951 /* check if queueing is necessary */
7952 switch (AtaCtl
->hdr
.ControlCode
) {
7953 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7954 if(!LunExt
->nBadBlocks
) {
7957 goto uata_ctl_queue
;
7958 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7959 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
7962 goto uata_ctl_queue
;
7963 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7964 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
7966 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
7967 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7969 if(PostReq
|| TopLevel
) {
7970 UniataQueueRequest(chan
, Srb
);
7971 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7972 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7975 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
7976 status
= SRB_STATUS_PENDING
;
7978 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7981 } // end switch (AtaCtl->hdr.ControlCode)
7983 /* process request */
7984 switch (AtaCtl
->hdr
.ControlCode
) {
7985 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7987 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
7989 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
7990 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
7991 if(AtaCtl
->addr
.TargetId
!= 0xff) {
7992 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_HIDDEN
;
7997 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7998 AtapiStallExecution(1000 * 1000);
8001 FindDevices(HwDeviceExtension
,
8002 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
8003 ? UNIATA_FIND_DEV_UNHIDE
: 0,
8004 AtaCtl
->addr
.PathId
);
8005 status
= SRB_STATUS_SUCCESS
;
8009 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
8011 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
8013 deviceExtension
->lun
[ldev
].DeviceFlags
= 0;
8014 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
8015 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
8016 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_HIDDEN
;
8019 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
8020 AtapiStallExecution(1000 * 1000);
8023 status
= SRB_STATUS_SUCCESS
;
8026 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
8028 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
8030 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
8031 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
8033 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
8034 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
8035 if(LunExt
->LimitedTransferMode
>
8036 LunExt
->OrigTransferMode
) {
8037 // check for incorrect value
8038 LunExt
->LimitedTransferMode
=
8039 LunExt
->OrigTransferMode
;
8042 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
8044 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8045 if(AtaCtl
->SetMode
.ApplyImmediately
) {
8046 AtapiDmaInit__(deviceExtension
, ldev
);
8048 /* deviceExtension->lun[ldev].TransferMode =
8049 deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
8050 status
= SRB_STATUS_SUCCESS
;
8053 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
8055 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
8057 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
8058 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
8059 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
8061 status
= SRB_STATUS_SUCCESS
;
8064 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
8066 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
8068 AtaCtl
->AdapterInfo
.HeaderLength
= offsetof(ADAPTERINFO
, Chan
);
8070 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
8071 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
8072 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
8073 status
= SRB_STATUS_DATA_OVERRUN
;
8077 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
8078 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
8079 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
8080 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
8081 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
8082 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
8083 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
8084 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
8085 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
8086 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
8087 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
8088 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
8089 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
8090 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
8091 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
8092 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
8093 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
8094 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
8095 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
8096 if(deviceExtension
->FullDevName
) {
8097 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
8099 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
8101 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
8103 status
= SRB_STATUS_SUCCESS
;
8106 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
8108 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
8110 ForgetBadBlocks(LunExt
);
8112 status
= SRB_STATUS_SUCCESS
;
8115 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
8117 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
8122 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
, ldev
);
8125 status
= SRB_STATUS_SUCCESS
;
8129 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
8130 AtaCtl
->hdr
.ControlCode
));
8131 status
= SRB_STATUS_INVALID_REQUEST
;
8136 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
8137 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
8138 "SCSIDISK", "-UNIATA-"));
8140 status
= SRB_STATUS_INVALID_REQUEST
;
8145 } // end SRB_FUNCTION_IO_CONTROL
8148 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
8149 // Indicate unsupported command.
8150 status
= SRB_STATUS_INVALID_REQUEST
;
8158 PathId
= Srb
->PathId
;
8159 TargetId
= Srb
->TargetId
;
8162 if (status
!= SRB_STATUS_PENDING
) {
8164 KdPrint2((PRINT_PREFIX
8165 "AtapiStartIo: Srb %#x complete with status %#x\n",
8169 // Set status in SRB.
8170 Srb
->SrbStatus
= (UCHAR
)status
;
8172 AtapiDmaDBSync(chan
, Srb
);
8173 UniataRemoveRequest(chan
, Srb
);
8174 // Indicate command complete.
8175 ScsiPortNotification(RequestComplete
,
8179 // Remove current Srb & get next one
8180 if((Srb
= UniataGetCurRequest(chan
))) {
8181 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8182 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
8183 // current request is under precessing, thus
8184 // we should do nothing here
8192 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
8194 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
8196 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
8197 // Indicate ready for next request.
8198 ScsiPortNotification(NextRequest
,
8202 ScsiPortNotification(NextLuRequest
,
8210 } // end AtapiStartIo__()
8215 UniataInitAtaCommands()
8221 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
8223 for(i
=0; i
<256; i
++) {
8228 KdPrint2((PRINT_PREFIX
"cmd %2.2x: ", command
));
8231 case IDE_COMMAND_READ_DMA48
:
8232 case IDE_COMMAND_READ_DMA_Q48
:
8233 case IDE_COMMAND_READ_STREAM_DMA48
:
8234 case IDE_COMMAND_READ_STREAM48
:
8235 case IDE_COMMAND_WRITE_DMA48
:
8236 case IDE_COMMAND_WRITE_DMA_Q48
:
8237 case IDE_COMMAND_READ_DMA_Q
:
8238 case IDE_COMMAND_READ_DMA
:
8239 case IDE_COMMAND_WRITE_DMA
:
8240 case IDE_COMMAND_WRITE_DMA_Q
:
8241 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8242 case IDE_COMMAND_WRITE_STREAM48
:
8243 case IDE_COMMAND_WRITE_FUA_DMA48
:
8244 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8245 case IDE_COMMAND_READ_LOG_DMA48
:
8246 case IDE_COMMAND_WRITE_LOG_DMA48
:
8247 case IDE_COMMAND_TRUSTED_RCV_DMA
:
8248 case IDE_COMMAND_TRUSTED_SEND_DMA
:
8249 KdPrint2((PRINT_PREFIX
"DMA "));
8250 flags
|= ATA_CMD_FLAG_DMA
;
8254 case IDE_COMMAND_READ48
:
8255 case IDE_COMMAND_READ_DMA48
:
8256 case IDE_COMMAND_READ_DMA_Q48
:
8257 case IDE_COMMAND_READ_MUL48
:
8258 case IDE_COMMAND_READ_STREAM_DMA48
:
8259 case IDE_COMMAND_READ_STREAM48
:
8260 case IDE_COMMAND_WRITE48
:
8261 case IDE_COMMAND_WRITE_DMA48
:
8262 case IDE_COMMAND_WRITE_DMA_Q48
:
8263 case IDE_COMMAND_WRITE_MUL48
:
8264 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8265 case IDE_COMMAND_WRITE_STREAM48
:
8266 case IDE_COMMAND_WRITE_FUA_DMA48
:
8267 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8268 case IDE_COMMAND_WRITE_MUL_FUA48
:
8269 case IDE_COMMAND_FLUSH_CACHE48
:
8270 case IDE_COMMAND_VERIFY48
:
8272 KdPrint2((PRINT_PREFIX
"48 "));
8273 flags
|= ATA_CMD_FLAG_48
;
8276 case IDE_COMMAND_READ
:
8277 case IDE_COMMAND_READ_MULTIPLE
:
8278 case IDE_COMMAND_READ_DMA
:
8279 case IDE_COMMAND_READ_DMA_Q
:
8280 case IDE_COMMAND_WRITE
:
8281 case IDE_COMMAND_WRITE_MULTIPLE
:
8282 case IDE_COMMAND_WRITE_DMA
:
8283 case IDE_COMMAND_WRITE_DMA_Q
:
8284 case IDE_COMMAND_FLUSH_CACHE
:
8285 case IDE_COMMAND_VERIFY
:
8287 KdPrint2((PRINT_PREFIX
"LBA "));
8288 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
8291 flags
|= ATA_CMD_FLAG_48supp
;
8294 case IDE_COMMAND_READ
:
8295 command
= IDE_COMMAND_READ48
; break;
8296 case IDE_COMMAND_READ_MULTIPLE
:
8297 command
= IDE_COMMAND_READ_MUL48
; break;
8298 case IDE_COMMAND_READ_DMA
:
8299 command
= IDE_COMMAND_READ_DMA48
; break;
8300 case IDE_COMMAND_READ_DMA_Q
:
8301 command
= IDE_COMMAND_READ_DMA_Q48
; break;
8302 case IDE_COMMAND_WRITE
:
8303 command
= IDE_COMMAND_WRITE48
; break;
8304 case IDE_COMMAND_WRITE_MULTIPLE
:
8305 command
= IDE_COMMAND_WRITE_MUL48
; break;
8306 case IDE_COMMAND_WRITE_DMA
:
8307 command
= IDE_COMMAND_WRITE_DMA48
; break;
8308 case IDE_COMMAND_WRITE_DMA_Q
:
8309 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
8310 case IDE_COMMAND_FLUSH_CACHE
:
8311 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
8312 // case IDE_COMMAND_READ_NATIVE_SIZE:
8313 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
8314 case IDE_COMMAND_SET_NATIVE_SIZE
:
8315 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
8316 case IDE_COMMAND_VERIFY
:
8317 command
= IDE_COMMAND_VERIFY48
; break;
8319 KdPrint2((PRINT_PREFIX
"!28->48 "));
8320 flags
&= ~ATA_CMD_FLAG_48supp
;
8323 KdPrint2((PRINT_PREFIX
"\t -> %2.2x (%2.2x)\n", command
, flags
));
8324 AtaCommands48
[i
] = command
;
8325 AtaCommandFlags
[i
] = flags
;
8327 } // end UniataInitAtaCommands()
8331 Routine Description:
8333 Installable driver initialization entry point for system.
8341 Status from ScsiPortInitialize()
8348 IN PVOID DriverObject
,
8352 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
8355 ULONG statusToReturn
, newStatus
;
8356 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
8357 BOOLEAN ReEnter
= FALSE
;
8360 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
8361 BOOLEAN PrimaryClaimed
= FALSE
;
8362 BOOLEAN SecondaryClaimed
= FALSE
;
8364 LARGE_INTEGER t0
, t1
;
8367 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
8368 a
= (WCHAR
)strlen(ver_string
);
8370 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
8372 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
8375 if(!SavedDriverObject
) {
8376 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8377 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8379 KeQuerySystemTime(&t0
);
8381 KeQuerySystemTime(&t1
);
8382 } while(t0
.QuadPart
== t1
.QuadPart
);
8386 KeQuerySystemTime(&t1
);
8388 } while(t0
.QuadPart
== t1
.QuadPart
);
8389 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8390 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8393 KdPrint(("UniATA Init: ReEnter\n"));
8397 // (re)read bad block list
8398 InitBadBlocks(NULL
);
8401 // init ATA command translation table
8402 UniataInitAtaCommands();
8403 // get registry path to settings
8404 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8405 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8406 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8407 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8408 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8409 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8412 if(WinVer_Id() >= WinVer_2k
) {
8413 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
8414 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
8415 WinVer_WDM_Model
= TRUE
;
8417 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
8418 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
8419 WinVer_WDM_Model
= TRUE
;
8423 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8424 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8426 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8429 statusToReturn
= 0xffffffff;
8431 // Zero out structure.
8432 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8434 // Set size of hwInitializationData.
8435 hwInitializationData
.comm
.HwInitializationDataSize
=
8436 sizeof(hwInitializationData
.comm
) +
8437 // sizeof(hwInitializationData.nt4) +
8438 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8439 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
8441 // Set entry points.
8442 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8443 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8444 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8445 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8447 // Specify size of extensions.
8448 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8449 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8450 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8452 // Indicate PIO device.
8453 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8454 // Set PnP-specific API
8455 if(WinVer_Id() > WinVer_NT
) {
8456 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
8457 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8458 KdPrint(("set AtapiAdapterControl() ptr\n"));
8459 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8462 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8465 UniataEnumBusMasterController(DriverObject
, Argument2
);
8468 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8469 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8470 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8471 for (i
=0; i
<BMListLen
; i
++) {
8473 if(!BMList
[i
].MasterDev
) {
8474 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8477 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8481 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8482 if(BMList
[i
].ChanInitOk
& 0x03) {
8483 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8485 newStatus
= STATUS_SUCCESS
;
8489 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8491 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8492 PrimaryClaimed
= TRUE
;
8493 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8494 SecondaryClaimed
= TRUE
;
8497 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8499 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
8501 for(c
=0; c
<2; c
++) {
8503 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8507 if(PrimaryClaimed
) {
8508 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8513 if(SecondaryClaimed
) {
8514 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8519 if((WinVer_Id() < WinVer_2k
)) {
8520 // do not even try if already claimed
8522 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8525 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8528 if(!WinVer_WDM_Model
) {
8529 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8531 // in WDM model things are different....
8532 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
8533 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
8535 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8536 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8538 if(!WinVer_WDM_Model
) {
8539 BMList
[i
].channel
= (UCHAR
)c
;
8542 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8543 newStatus
= ScsiPortInitialize(DriverObject
,
8545 &hwInitializationData
.comm
,
8546 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8547 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8548 if (newStatus
< statusToReturn
) {
8549 statusToReturn
= newStatus
;
8551 if (newStatus
== STATUS_SUCCESS
) {
8552 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8554 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8555 c = 1; // this will break our for()
8556 BMList[i].ChanInitOk |= 0x01 << c;
8561 if(WinVer_Id() >= WinVer_2k
) {
8562 // the following doesn't work under higher OSes
8563 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8566 if(BMList
[i
].ChanInitOk
& 0x03) {
8567 // under NT we receive status immediately, so
8568 // we can omit alternative init method id STATUS_SUCCESS returned
8569 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8572 // if (WinVer_Id() == WinVer_NT) and some error occured
8573 // try alternative init method
8576 if(WinVer_WDM_Model
) {
8577 hwInitializationData
.comm
.HwFindAdapter
= UniataFindFakeBusMasterController
;
8578 hwInitializationData
.comm
.NumberOfAccessRanges
= 5;
8579 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8581 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8582 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8583 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8584 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8586 //BMList[i].channel = 0/*(UCHAR)c*/;
8588 KdPrint2((PRINT_PREFIX
"Try init fake: %4.4s %4.4s \n",
8589 hwInitializationData
.comm
.VendorId
,
8590 hwInitializationData
.comm
.DeviceId
));
8591 newStatus
= ScsiPortInitialize(DriverObject
,
8593 &hwInitializationData
.comm
,
8595 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8599 if(BMList
[i
].ChanInitOk
& 0x03) {
8600 _PrintNtConsole(" OK\n");
8602 _PrintNtConsole(" failed\n");
8608 /* KeBugCheckEx(0xc000000e,
8609 (i << 16) | BMList[0].ChanInitOk,
8611 newStatus, statusToReturn);*/
8613 // Look for PCI IDE controller
8614 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8615 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8616 for (; i
<BMListLen
; i
++) {
8618 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8621 /* if(BMList[i].MasterDev)
8624 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8625 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
8626 BMList
[i
].busNumber
,
8627 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
8628 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
8631 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8632 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8633 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8635 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8636 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8637 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8638 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8640 BMList
[i
].channel
= 0/*(UCHAR)c*/;
8642 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
8643 hwInitializationData
.comm
.VendorId
,
8644 hwInitializationData
.comm
.DeviceId
));
8645 newStatus
= ScsiPortInitialize(DriverObject
,
8647 &hwInitializationData
.comm
,
8649 if (newStatus
< statusToReturn
)
8650 statusToReturn
= newStatus
;
8653 if(newStatus
== STATUS_SUCCESS
) {
8654 _PrintNtConsole(" OK\n");
8656 _PrintNtConsole(" failed\n");
8662 /* KeBugCheckEx(0xc000000e,
8665 newStatus, statusToReturn);*/
8669 hwInitializationData
.comm
.VendorId
= 0;
8670 hwInitializationData
.comm
.VendorIdLength
= 0;
8671 hwInitializationData
.comm
.DeviceId
= 0;
8672 hwInitializationData
.comm
.DeviceIdLength
= 0;
8674 // The adapter count is used by the find adapter routine to track how
8675 // which adapter addresses have been tested.
8677 // Indicate 2 access ranges and reset FindAdapter.
8678 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
8679 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
8681 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
8682 // Indicate ISA bustype.
8683 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8686 // Call initialization for ISA bustype.
8687 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
8688 newStatus
= ScsiPortInitialize(DriverObject
,
8690 &hwInitializationData
.comm
,
8692 if (newStatus
< statusToReturn
)
8693 statusToReturn
= newStatus
;
8695 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
8697 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
8698 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
8701 newStatus
= ScsiPortInitialize(DriverObject
,
8703 &hwInitializationData
.comm
,
8705 if (newStatus
< statusToReturn
)
8706 statusToReturn
= newStatus
;
8708 InDriverEntry
= FALSE
;
8710 KdPrint2((PRINT_PREFIX
"\n\nLeave ATAPI IDE MiniPort DriverEntry with status %#x\n", statusToReturn
));
8712 return statusToReturn
;
8714 } // end DriverEntry()
8719 BuildMechanismStatusSrb(
8720 IN PVOID HwDeviceExtension
,
8721 IN PSCSI_REQUEST_BLOCK Srb
8724 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8725 PSCSI_REQUEST_BLOCK srb
;
8727 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8729 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8731 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8733 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8734 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8735 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8736 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8738 // Set flags to disable synchronous negociation.
8739 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8741 // Set timeout to 4 seconds.
8742 srb
->TimeOutValue
= 4;
8745 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
8746 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8747 srb
->SrbExtension
= AtaReq
;
8749 // Set CDB operation code.
8750 cdb
= (PCDB
)srb
->Cdb
;
8751 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
8752 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8755 } // end BuildMechanismStatusSrb()
8757 #endif //UNIATA_CORE
8761 BuildRequestSenseSrb (
8762 IN PVOID HwDeviceExtension
,
8763 IN PSCSI_REQUEST_BLOCK Srb
8766 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8767 PSCSI_REQUEST_BLOCK srb
;
8769 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8771 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8773 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8775 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8776 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8777 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8778 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8780 // Set flags to disable synchronous negociation.
8781 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8783 // Set timeout to 2 seconds.
8784 srb
->TimeOutValue
= 4;
8787 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
8788 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
8789 srb
->SrbExtension
= AtaReq
;
8791 // Set CDB operation code.
8792 cdb
= (PCDB
)srb
->Cdb
;
8793 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
8794 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
8797 } // end BuildRequestSenseSrb()
8803 AtapiRegCheckDevLunValue(
8804 IN PVOID HwDeviceExtension
,
8805 IN PCWCH NamePrefix
,
8813 ULONG val
= Default
;
8815 val
= AtapiRegCheckParameterValue(
8816 HwDeviceExtension
, NamePrefix
, Name
, val
);
8818 if(chan
!= CHAN_NOT_SPECIFIED
) {
8819 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
8820 val
= AtapiRegCheckParameterValue(
8821 HwDeviceExtension
, namex
, Name
, val
);
8822 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
8823 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
8824 val
= AtapiRegCheckParameterValue(
8825 HwDeviceExtension
, namex
, Name
, val
);
8829 } // end AtapiRegCheckDevLunValue()
8842 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
8861 swprintf(Buffer
+j
, L
"%2.2x", a
);
8869 } // end EncodeVendorStr()
8873 AtapiRegCheckDevValue(
8874 IN PVOID HwDeviceExtension
,
8881 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8883 // WCHAR name1[11+4+5];
8884 // WCHAR name2[11+4+4+10];
8885 // WCHAR name3[11+4+4+5+20];
8886 // WCHAR name3[11+4+4+5+20+1];
8895 IN ULONG SlotNumber
;
8897 ULONG val
= Default
;
8899 KdPrint(( " Parameter %ws\n", Name
));
8901 if(deviceExtension
) {
8902 VendorID
= deviceExtension
->DevID
& 0xffff;
8903 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
8904 SlotNumber
= deviceExtension
->slotNumber
;
8908 SlotNumber
= 0xffffffff;
8911 val
= AtapiRegCheckDevLunValue(
8912 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
8914 if(deviceExtension
) {
8915 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
8917 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
8918 swprintf(namex
, L
"Parameters%s", namev
);
8919 val
= AtapiRegCheckDevLunValue(
8920 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8923 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
8924 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
8925 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
8927 swprintf(namex
, L
"Parameters%s", namev
);
8928 val
= AtapiRegCheckDevLunValue(
8929 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8931 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
8932 val
= AtapiRegCheckDevLunValue(
8933 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8935 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
8936 val
= AtapiRegCheckDevLunValue(
8937 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8939 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
8941 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
8942 swprintf(namex
, L
"Parameters%s", namev
);
8943 val
= AtapiRegCheckDevLunValue(
8944 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8946 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
8947 swprintf(namex
, L
"Parameters%s", namev
);
8948 val
= AtapiRegCheckDevLunValue(
8949 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8952 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
8954 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
8955 swprintf(namex
, L
"Parameters%s", namev
);
8956 val
= AtapiRegCheckDevLunValue(
8957 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8959 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
8960 swprintf(namex
, L
"Parameters%s", namev
);
8961 val
= AtapiRegCheckDevLunValue(
8962 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8967 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
8970 } // end AtapiRegCheckDevValue()
8973 The user must specify that Xxx is to run on the platform
8974 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
8975 Services\UniATA\Xxx:REG_DWORD:Zzz.
8977 The user can override the global setting to enable or disable Xxx on a
8978 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
8979 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
8981 If this registry value does not exist or contains the value zero then
8982 the timer to check for media change does not run.
8986 RegistryPath - pointer to the unicode string inside
8987 ...\CurrentControlSet\Services\UniATA
8988 DeviceNumber - The number of the HBA device object
8990 Returns: Registry Key value
8994 AtapiRegCheckParameterValue(
8995 IN PVOID HwDeviceExtension
,
8996 IN PCWSTR PathSuffix
,
9001 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
9003 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
9005 LONG zero
= Default
;
9007 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
9010 LONG doRun
= Default
;
9012 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
9014 UNICODE_STRING paramPath
;
9016 // <SavedRegPath>\<PathSuffix> -> <Name>
9017 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
9018 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
9020 paramPath
.Length
= 0;
9021 paramPath
.MaximumLength
= RegistryPath
->Length
+
9022 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
9023 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
9024 if(!paramPath
.Buffer
) {
9025 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
9029 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
9030 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
9031 RtlAppendUnicodeToString(¶mPath
, L
"\\");
9032 RtlAppendUnicodeToString(¶mPath
, PathSuffix
);
9034 // Check for the Xxx value.
9035 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
9037 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
9038 parameters
[0].Name
= Name
;
9039 parameters
[0].EntryContext
= &doRun
;
9040 parameters
[0].DefaultType
= REG_DWORD
;
9041 parameters
[0].DefaultData
= &zero
;
9042 parameters
[0].DefaultLength
= sizeof(ULONG
);
9044 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
9045 paramPath
.Buffer
, parameters
, NULL
, NULL
);
9046 //KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
9048 ExFreePool(paramPath
.Buffer
);
9050 if(!NT_SUCCESS(status
)) {
9056 #undef ITEMS_TO_QUERY
9058 } // end AtapiRegCheckParameterValue()
9061 SCSI_ADAPTER_CONTROL_STATUS
9063 AtapiAdapterControl(
9064 IN PVOID HwDeviceExtension
,
9065 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
9069 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
9070 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
9071 ULONG numberChannels
= deviceExtension
->NumberChannels
;
9075 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
9077 switch(ControlType
) {
9078 case ScsiQuerySupportedControlTypes
: {
9079 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
9080 TRUE
, // ScsiQuerySupportedControlTypes
9081 TRUE
, // ScsiStopAdapter
9082 TRUE
, // ScsiRestartAdapter
9083 FALSE
, // ScsiSetBootConfig
9084 FALSE
// ScsiSetRunningConfig
9087 ULONG lim
= ScsiAdapterControlMax
;
9090 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
9092 if(pControlTypeList
->MaxControlType
< lim
) {
9093 lim
= pControlTypeList
->MaxControlType
;
9096 for(i
= 0; i
< lim
; i
++) {
9097 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
9103 case ScsiStopAdapter
: {
9105 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
9106 // Shut down all interrupts on the adapter. They'll get re-enabled
9107 // by the initialization routines.
9108 for (c
= 0; c
< numberChannels
; c
++) {
9109 AtapiResetController(deviceExtension
, c
);
9110 AtapiDisableInterrupts(deviceExtension
, c
);
9112 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9113 // we must never get here for non-PCI
9114 status
= UniataDisconnectIntr2(HwDeviceExtension
);
9115 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
9119 case ScsiRestartAdapter
: {
9121 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
9122 // Enable all the interrupts on the adapter while port driver call
9123 // for power up an HBA that was shut down for power management
9125 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
9126 status
= UniataConnectIntr2(HwDeviceExtension
);
9127 for (c
= 0; c
< numberChannels
; c
++) {
9128 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
9129 FindDevices(HwDeviceExtension
, 0, c
);
9130 AtapiEnableInterrupts(deviceExtension
, c
);
9131 AtapiHwInitialize__(deviceExtension
, c
);
9133 if(deviceExtension
->Isr2DevObj
) {
9134 // we must never get here for non-PCI
9135 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9142 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
9143 return ScsiAdapterControlUnsuccessful
;
9147 return ScsiAdapterControlSuccess
;
9148 } // end AtapiAdapterControl()
9150 #endif //UNIATA_CORE
9169 UCHAR dbg_print_tmp_buff
[512];
9170 // UNICODE_STRING msgBuff;
9172 va_start(ap
, DebugMessage
);
9174 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
9176 dbg_print_tmp_buff
[511] = 0;
9178 HalDisplayString(dbg_print_tmp_buff
);
9182 } // end PrintNtConsole()