3 Copyright (c) 2002-2008 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2) support
51 9. NT 3.51 support (binary compatibility)
62 static const CHAR ver_string
[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR
"\n";
64 static const CHAR uniata_comm_name
[] = UNIATA_COMM_PORT_VENDOR_STR
" \n";
66 UNICODE_STRING SavedRegPath
;
67 WCHAR SavedRegPathBuffer
[256];
71 UCHAR AtaCommands48
[256];
72 UCHAR AtaCommandFlags
[256];
75 ULONG ForceSimplex
= 0;
81 ULONG g_LogToDisplay
= 0;
84 ULONG g_WaitBusyInISR
= 1;
86 BOOLEAN InDriverEntry
= TRUE
;
88 BOOLEAN g_opt_Verbose
= 0;
90 BOOLEAN WinVer_WDM_Model
= FALSE
;
91 //UCHAR EnableDma = FALSE;
92 //UCHAR EnableReorder = FALSE;
98 AtapiResetController__(
99 IN PVOID HwDeviceExtension
,
101 IN UCHAR CompleteType
107 IN PHW_DEVICE_EXTENSION deviceExtension
,
111 #define RESET_COMPLETE_CURRENT 0x00
112 #define RESET_COMPLETE_ALL 0x01
113 #define RESET_COMPLETE_NONE 0x02
120 IN PVOID HwDeviceExtension
123 #ifdef UNIATA_USE_XXableInterrupts
124 #define RETTYPE_XXableInterrupts BOOLEAN
125 #define RETVAL_XXableInterrupts TRUE
127 #define RETTYPE_XXableInterrupts VOID
128 #define RETVAL_XXableInterrupts
131 RETTYPE_XXableInterrupts
134 IN PVOID HwDeviceExtension
137 RETTYPE_XXableInterrupts
139 AtapiEnableInterrupts__(
140 IN PVOID HwDeviceExtension
146 IN PVOID HwDeviceExtension
,
148 IN PHW_TIMER HwScsiTimer
,
149 IN ULONG MiniportTimerValue
152 SCSI_ADAPTER_CONTROL_STATUS
155 IN PVOID HwDeviceExtension
,
156 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
164 AtapiCheckInterrupt__(
165 IN PVOID HwDeviceExtension
,
174 AtapiRegGetStringParameterValue(
175 IN PWSTR RegistryPath
,
181 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
183 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
188 ustr
.MaximumLength
= (USHORT
)MaxLen
;
189 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
191 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
192 parameters
[0].Name
= Name
;
193 parameters
[0].EntryContext
= &ustr
;
194 parameters
[0].DefaultType
= REG_SZ
;
195 parameters
[0].DefaultData
= Str
;
196 parameters
[0].DefaultLength
= MaxLen
;
198 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
199 RegistryPath
, parameters
, NULL
, NULL
);
201 if(!NT_SUCCESS(status
))
206 #undef ITEMS_TO_QUERY
207 } // end AtapiRegGetStringParameterValue()
225 if(!nano
|| !g_Perf
|| !g_PerfDt
)
227 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
232 KeQuerySystemTime(&t0
);
235 } // end UniataNanoSleep()
238 #define AtapiWritePortN_template(_type, _Type, sz) \
241 AtapiWritePort##sz( \
242 IN PHW_CHANNEL chan, \
248 if(_port >= IDX_MAX_REG) { \
249 res = (PIORES)(_port); \
252 res = &chan->RegTranslation[_port]; \
254 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
258 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
260 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
261 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
266 AtapiWritePortN_template(ULONG
, Ulong
, 4);
267 AtapiWritePortN_template(USHORT
, Ushort
, 2);
268 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
270 #define AtapiWritePortExN_template(_type, _Type, sz) \
273 AtapiWritePortEx##sz( \
274 IN PHW_CHANNEL chan, \
281 if(_port >= IDX_MAX_REG) { \
282 res = (PIORES)(_port); \
285 res = &chan->RegTranslation[_port]; \
287 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
291 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
293 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
294 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
299 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
300 //AtapiWritePortExN_template(USHORT, Ushort, 2);
301 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
303 #define AtapiReadPortN_template(_type, _Type, sz) \
307 IN PHW_CHANNEL chan, \
312 if(_port >= IDX_MAX_REG) { \
313 res = (PIORES)(_port); \
316 res = &chan->RegTranslation[_port]; \
318 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
319 return (_type)(-1); \
322 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
323 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
325 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
326 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
330 AtapiReadPortN_template(ULONG
, Ulong
, 4);
331 AtapiReadPortN_template(USHORT
, Ushort
, 2);
332 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
334 #define AtapiReadPortExN_template(_type, _Type, sz) \
337 AtapiReadPortEx##sz( \
338 IN PHW_CHANNEL chan, \
344 if(_port >= IDX_MAX_REG) { \
345 res = (PIORES)(_port); \
348 res = &chan->RegTranslation[_port]; \
350 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
351 return (_type)(-1); \
354 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
356 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
357 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
361 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
362 //AtapiReadPortExN_template(USHORT, Ushort, 2);
363 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
365 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
368 AtapiReadBuffer##sz( \
369 IN PHW_CHANNEL chan, \
380 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
382 Buffer = ((_type*)Buffer)+1; \
383 UniataNanoSleep(Timing); \
388 if(_port >= IDX_MAX_REG) { \
389 res = (PIORES)(_port); \
392 res = &chan->RegTranslation[_port]; \
394 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
398 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
399 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
403 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
405 Buffer = ((_type*)Buffer)+1; \
410 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
413 AtapiWriteBuffer##sz( \
414 IN PHW_CHANNEL chan, \
425 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
426 Buffer = ((_type*)Buffer)+1; \
428 UniataNanoSleep(Timing); \
433 if(_port >= IDX_MAX_REG) { \
434 res = (PIORES)(_port); \
437 res = &chan->RegTranslation[_port]; \
439 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
443 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
444 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
448 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
450 Buffer = ((_type*)Buffer)+1; \
455 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
456 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
458 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
459 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
471 WaitOnBusyLong(chan
);
472 for (i
= 0; i
< 0x10000; i
++) {
474 GetStatus(chan
, statusByte
);
475 if (statusByte
& IDE_STATUS_DRQ
) {
476 // Suck out any remaining bytes and throw away.
477 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
483 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
486 } // AtapiSuckPort2()
496 for (i
=0; i
<200; i
++) {
497 GetStatus(chan
, Status
);
498 if (Status
& IDE_STATUS_BUSY
) {
499 AtapiStallExecution(10);
506 } // end WaitOnBusy()
517 Status
= WaitOnBusy(chan
);
518 if(!(Status
& IDE_STATUS_BUSY
))
520 for (i
=0; i
<2000; i
++) {
521 GetStatus(chan
, Status
);
522 if (Status
& IDE_STATUS_BUSY
) {
523 AtapiStallExecution(250);
530 } // end WaitOnBusyLong()
540 for (i
=0; i
<200; i
++) {
541 GetBaseStatus(chan
, Status
);
542 if (Status
& IDE_STATUS_BUSY
) {
543 AtapiStallExecution(10);
550 } // end WaitOnBaseBusy()
561 Status
= WaitOnBaseBusy(chan
);
562 if(!(Status
& IDE_STATUS_BUSY
))
564 for (i
=0; i
<2000; i
++) {
565 GetBaseStatus(chan
, Status
);
566 if (Status
& IDE_STATUS_BUSY
) {
567 AtapiStallExecution(250);
574 } // end WaitOnBaseBusyLong()
579 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
588 if(Status
& IDE_STATUS_BUSY
) {
591 // if(deviceExtension->HwFlags & UNIATA_SATA) {
592 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
593 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
597 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
598 if ((Status
& IDE_STATUS_BUSY
) ||
599 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
603 return IDE_STATUS_IDLE
;
604 } // end UniataIsIdle()
615 for (i
=0; i
<20000; i
++) {
616 GetStatus(chan
, Status
);
617 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
618 if(Status2
== 0xff) {
622 if(Status2
& IDE_STATUS_BUSY
) {
623 AtapiStallExecution(10);
630 } // end WaitForIdleLong()
640 for (i
=0; i
<1000; i
++) {
641 GetStatus(chan
, Status
);
642 if (Status
& IDE_STATUS_BUSY
) {
643 AtapiStallExecution(10);
644 } else if (Status
& IDE_STATUS_DRQ
) {
647 AtapiStallExecution(10);
651 } // end WaitForDrq()
661 for (i
=0; i
<2; i
++) {
662 GetStatus(chan
, Status
);
663 if (Status
& IDE_STATUS_BUSY
) {
664 AtapiStallExecution(10);
665 } else if (Status
& IDE_STATUS_DRQ
) {
668 AtapiStallExecution(10);
672 } // end WaitShortForDrq()
681 //ULONG c = chan->lChannel;
683 UCHAR dma_status
= 0;
684 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
687 GetBaseStatus(chan
, statusByte2
);
688 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
689 SelectDrive(chan
, DeviceNumber
);
690 AtapiStallExecution(10000);
691 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
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
);