3 Copyright (c) 2002-2008 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2) support
51 9. NT 3.51 support (binary compatibility)
62 static const CHAR ver_string
[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR
"\n";
64 static const CHAR uniata_comm_name
[] = UNIATA_COMM_PORT_VENDOR_STR
" \n";
66 UNICODE_STRING SavedRegPath
;
67 WCHAR SavedRegPathBuffer
[256];
71 UCHAR AtaCommands48
[256];
72 UCHAR AtaCommandFlags
[256];
75 ULONG ForceSimplex
= 0;
81 ULONG g_LogToDisplay
= 0;
84 ULONG g_WaitBusyInISR
= 1;
86 BOOLEAN InDriverEntry
= TRUE
;
88 BOOLEAN g_opt_Verbose
= 0;
90 BOOLEAN WinVer_WDM_Model
= FALSE
;
91 //UCHAR EnableDma = FALSE;
92 //UCHAR EnableReorder = FALSE;
98 AtapiResetController__(
99 IN PVOID HwDeviceExtension
,
101 IN UCHAR CompleteType
107 IN PHW_DEVICE_EXTENSION deviceExtension
,
111 #define RESET_COMPLETE_CURRENT 0x00
112 #define RESET_COMPLETE_ALL 0x01
113 #define RESET_COMPLETE_NONE 0x02
120 IN PVOID HwDeviceExtension
123 #ifdef UNIATA_USE_XXableInterrupts
124 #define RETTYPE_XXableInterrupts BOOLEAN
125 #define RETVAL_XXableInterrupts TRUE
127 #define RETTYPE_XXableInterrupts VOID
128 #define RETVAL_XXableInterrupts
131 RETTYPE_XXableInterrupts
134 IN PVOID HwDeviceExtension
137 RETTYPE_XXableInterrupts
139 AtapiEnableInterrupts__(
140 IN PVOID HwDeviceExtension
146 IN PVOID HwDeviceExtension
,
148 IN PHW_TIMER HwScsiTimer
,
149 IN ULONG MiniportTimerValue
152 SCSI_ADAPTER_CONTROL_STATUS
155 IN PVOID HwDeviceExtension
,
156 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
164 AtapiCheckInterrupt__(
165 IN PVOID HwDeviceExtension
,
174 AtapiRegGetStringParameterValue(
175 IN PWSTR RegistryPath
,
181 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
183 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
188 ustr
.MaximumLength
= (USHORT
)MaxLen
;
189 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
191 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
192 parameters
[0].Name
= Name
;
193 parameters
[0].EntryContext
= &ustr
;
194 parameters
[0].DefaultType
= REG_SZ
;
195 parameters
[0].DefaultData
= Str
;
196 parameters
[0].DefaultLength
= MaxLen
;
198 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
199 RegistryPath
, parameters
, NULL
, NULL
);
201 if(!NT_SUCCESS(status
))
206 #undef ITEMS_TO_QUERY
207 } // end AtapiRegGetStringParameterValue()
225 if(!nano
|| !g_Perf
|| !g_PerfDt
)
227 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
232 KeQuerySystemTime(&t0
);
235 } // end UniataNanoSleep()
238 #define AtapiWritePortN_template(_type, _Type, sz) \
241 AtapiWritePort##sz( \
242 IN PHW_CHANNEL chan, \
248 if(_port >= IDX_MAX_REG) { \
249 res = (PIORES)(_port); \
252 res = &chan->RegTranslation[_port]; \
254 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
258 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
260 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
261 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
266 AtapiWritePortN_template(ULONG
, Ulong
, 4);
267 AtapiWritePortN_template(USHORT
, Ushort
, 2);
268 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
270 #define AtapiWritePortExN_template(_type, _Type, sz) \
273 AtapiWritePortEx##sz( \
274 IN PHW_CHANNEL chan, \
281 if(_port >= IDX_MAX_REG) { \
282 res = (PIORES)(_port); \
285 res = &chan->RegTranslation[_port]; \
287 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
291 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
293 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
294 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
299 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
300 //AtapiWritePortExN_template(USHORT, Ushort, 2);
301 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
303 #define AtapiReadPortN_template(_type, _Type, sz) \
307 IN PHW_CHANNEL chan, \
312 if(_port >= IDX_MAX_REG) { \
313 res = (PIORES)(_port); \
316 res = &chan->RegTranslation[_port]; \
318 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
319 return (_type)(-1); \
322 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
323 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
325 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
326 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
330 AtapiReadPortN_template(ULONG
, Ulong
, 4);
331 AtapiReadPortN_template(USHORT
, Ushort
, 2);
332 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
334 #define AtapiReadPortExN_template(_type, _Type, sz) \
337 AtapiReadPortEx##sz( \
338 IN PHW_CHANNEL chan, \
344 if(_port >= IDX_MAX_REG) { \
345 res = (PIORES)(_port); \
348 res = &chan->RegTranslation[_port]; \
350 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
351 return (_type)(-1); \
354 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
356 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
357 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
361 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
362 //AtapiReadPortExN_template(USHORT, Ushort, 2);
363 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
365 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
368 AtapiReadBuffer##sz( \
369 IN PHW_CHANNEL chan, \
380 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
382 Buffer = ((_type*)Buffer)+1; \
383 UniataNanoSleep(Timing); \
388 if(_port >= IDX_MAX_REG) { \
389 res = (PIORES)(_port); \
392 res = &chan->RegTranslation[_port]; \
394 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
398 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
399 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
403 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
405 Buffer = ((_type*)Buffer)+1; \
410 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
413 AtapiWriteBuffer##sz( \
414 IN PHW_CHANNEL chan, \
425 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
426 Buffer = ((_type*)Buffer)+1; \
428 UniataNanoSleep(Timing); \
433 if(_port >= IDX_MAX_REG) { \
434 res = (PIORES)(_port); \
437 res = &chan->RegTranslation[_port]; \
439 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
443 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
444 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
448 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
450 Buffer = ((_type*)Buffer)+1; \
455 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
456 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
458 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
459 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
471 WaitOnBusyLong(chan
);
472 for (i
= 0; i
< 0x10000; i
++) {
474 GetStatus(chan
, statusByte
);
475 if (statusByte
& IDE_STATUS_DRQ
) {
476 // Suck out any remaining bytes and throw away.
477 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
483 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
486 } // AtapiSuckPort2()
496 for (i
=0; i
<200; i
++) {
497 GetStatus(chan
, Status
);
498 if (Status
& IDE_STATUS_BUSY
) {
499 AtapiStallExecution(10);
506 } // end WaitOnBusy()
517 Status
= WaitOnBusy(chan
);
518 if(!(Status
& IDE_STATUS_BUSY
))
520 for (i
=0; i
<2000; i
++) {
521 GetStatus(chan
, Status
);
522 if (Status
& IDE_STATUS_BUSY
) {
523 AtapiStallExecution(250);
530 } // end WaitOnBusyLong()
540 for (i
=0; i
<200; i
++) {
541 GetBaseStatus(chan
, Status
);
542 if (Status
& IDE_STATUS_BUSY
) {
543 AtapiStallExecution(10);
550 } // end WaitOnBaseBusy()
561 Status
= WaitOnBaseBusy(chan
);
562 if(!(Status
& IDE_STATUS_BUSY
))
564 for (i
=0; i
<2000; i
++) {
565 GetBaseStatus(chan
, Status
);
566 if (Status
& IDE_STATUS_BUSY
) {
567 AtapiStallExecution(250);
574 } // end WaitOnBaseBusyLong()
579 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
588 if(Status
& IDE_STATUS_BUSY
) {
591 // if(deviceExtension->HwFlags & UNIATA_SATA) {
592 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
593 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
597 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
598 if ((Status
& IDE_STATUS_BUSY
) ||
599 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
603 return IDE_STATUS_IDLE
;
604 } // end UniataIsIdle()
615 for (i
=0; i
<20000; i
++) {
616 GetStatus(chan
, Status
);
617 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
618 if(Status2
== 0xff) {
622 if(Status2
& IDE_STATUS_BUSY
) {
623 AtapiStallExecution(10);
630 } // end WaitForIdleLong()
640 for (i
=0; i
<1000; i
++) {
641 GetStatus(chan
, Status
);
642 if (Status
& IDE_STATUS_BUSY
) {
643 AtapiStallExecution(10);
644 } else if (Status
& IDE_STATUS_DRQ
) {
647 AtapiStallExecution(10);
651 } // end WaitForDrq()
661 for (i
=0; i
<2; i
++) {
662 GetStatus(chan
, Status
);
663 if (Status
& IDE_STATUS_BUSY
) {
664 AtapiStallExecution(10);
665 } else if (Status
& IDE_STATUS_DRQ
) {
668 AtapiStallExecution(10);
672 } // end WaitShortForDrq()
681 //ULONG c = chan->lChannel;
683 UCHAR dma_status
= 0;
684 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
687 GetBaseStatus(chan
, statusByte2
);
688 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
689 SelectDrive(chan
, DeviceNumber
);
690 AtapiStallExecution(10000);
691 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
692 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
695 AtapiStallExecution(30);
697 SelectDrive(chan
, DeviceNumber
);
699 GetBaseStatus(chan
, statusByte2
);
700 AtapiStallExecution(500);
702 GetBaseStatus(chan
, statusByte2
);
703 if(chan
&& chan
->DeviceExtension
) {
704 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
705 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
707 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
709 if(dma_status
& BM_STATUS_INTR
) {
710 // bullshit, we have DMA interrupt, but had never initiate DMA operation
711 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
712 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
713 GetBaseStatus(chan
, statusByte2
);
715 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
716 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
720 } // end AtapiSoftReset()
723 Send command to device.
724 Translate to 48-Lba form if required
729 IN PHW_DEVICE_EXTENSION deviceExtension
,
730 IN ULONG DeviceNumber
,
739 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
741 ULONG ldev
= lChannel
*2 + DeviceNumber
;
745 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
746 deviceExtension
->DevIndex
, deviceExtension
->Channel
, ldev
, command
, lba
, count
, feature
));
748 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
749 SelectDrive(chan
, DeviceNumber
);
751 statusByte
= WaitOnBusy(chan
);
753 /* ready to issue command ? */
754 if (statusByte
& IDE_STATUS_BUSY
) {
755 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
759 // !!! We should not check ERROR condition here
760 // ERROR bit may be asserted durring previous operation
761 // and not cleared after SELECT
763 //>>>>>> NV: 2006/08/03
764 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
765 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
766 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
767 return IDE_STATUS_ERROR
;
768 //return SRB_STATUS_ERROR;
770 //<<<<<< NV: 2006/08/03
772 /* only use 48bit addressing if needed because of the overhead */
773 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
774 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
776 KdPrint2((PRINT_PREFIX
" ldev %#x USE_LBA_48\n", ldev
));
777 /* translate command into 48bit version */
778 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
779 command
= AtaCommands48
[command
];
781 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
785 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
788 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
789 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
790 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
791 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
792 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
793 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
794 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
795 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
796 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
797 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
799 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
800 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
803 plba
= (PUCHAR
)&lba
; //ktp
804 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
807 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
808 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
810 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
811 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
812 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
813 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
814 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
815 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
816 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
818 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
819 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
823 // write command code to device
824 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
829 // caller requested wait for interrupt
832 statusByte
= WaitForDrq(chan
);
833 if (statusByte
& IDE_STATUS_DRQ
)
835 AtapiStallExecution(500);
836 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
843 // caller requested wait for entering Wait state
844 for (i
=0; i
<30 * 1000; i
++) {
846 GetStatus(chan
, statusByte
);
847 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
848 if(statusByte
== 0xff) {
852 if(statusByte
& IDE_STATUS_ERROR
) {
855 if(statusByte
& IDE_STATUS_BUSY
) {
856 AtapiStallExecution(100);
859 if(statusByte
== IDE_STATUS_IDLE
) {
862 //if(deviceExtension->HwFlags & UNIATA_SATA) {
863 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
866 AtapiStallExecution(100);
869 //statusByte |= IDE_STATUS_BUSY;
873 statusByte
= WaitOnBusyLong(chan
);
875 case ATA_WAIT_BASE_READY
:
876 statusByte
= WaitOnBaseBusyLong(chan
);
879 GetStatus(chan
, statusByte
);
880 if (statusByte
& IDE_STATUS_ERROR
) {
881 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
882 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
885 KdPrint2((PRINT_PREFIX
" try to continue\n"));
886 statusByte
&= ~IDE_STATUS_ERROR
;
888 chan
->ExpectingInterrupt
= TRUE
;
890 InterlockedExchange(&(chan
->CheckIntr
),
896 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
899 } // end AtaCommand48()
902 Send command to device.
903 This is simply wrapper for AtaCommand48()
908 IN PHW_DEVICE_EXTENSION deviceExtension
,
909 IN ULONG DeviceNumber
,
920 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
922 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
923 count
, feature
, flags
);
924 } // end AtaCommand()
928 AtaPio2Mode(LONG pio
)
931 default: return ATA_PIO
;
932 case 0: return ATA_PIO0
;
933 case 1: return ATA_PIO1
;
934 case 2: return ATA_PIO2
;
935 case 3: return ATA_PIO3
;
936 case 4: return ATA_PIO4
;
937 case 5: return ATA_PIO5
;
939 } // end AtaPio2Mode()
943 AtaPioMode(PIDENTIFY_DATA2 ident
)
945 if (ident
->PioTimingsValid
) {
946 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
948 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
950 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
953 if (ident
->PioCycleTimingMode
== 2)
955 if (ident
->PioCycleTimingMode
== 1)
957 if (ident
->PioCycleTimingMode
== 0)
960 } // end AtaPioMode()
964 AtaWmode(PIDENTIFY_DATA2 ident
)
966 if (ident
->MultiWordDMASupport
& 0x04)
968 if (ident
->MultiWordDMASupport
& 0x02)
970 if (ident
->MultiWordDMASupport
& 0x01)
977 AtaUmode(PIDENTIFY_DATA2 ident
)
979 if (!ident
->UdmaModesValid
)
981 if (ident
->UltraDMASupport
& 0x40)
983 if (ident
->UltraDMASupport
& 0x20)
985 if (ident
->UltraDMASupport
& 0x10)
987 if (ident
->UltraDMASupport
& 0x08)
989 if (ident
->UltraDMASupport
& 0x04)
991 if (ident
->UltraDMASupport
& 0x02)
993 if (ident
->UltraDMASupport
& 0x01)
1004 IN PVOID HwDeviceExtension
1007 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1008 PHW_TIMER HwScsiTimer
;
1010 ULONG MiniportTimerValue
;
1011 BOOLEAN recall
= FALSE
;
1015 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1017 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1018 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1019 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1022 chan
= &deviceExtension
->chan
[lChannel
];
1026 HwScsiTimer
= chan
->HwScsiTimer
;
1027 chan
->HwScsiTimer
= NULL
;
1029 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1030 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1034 HwScsiTimer(HwDeviceExtension
);
1036 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1038 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1039 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1040 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1041 deviceExtension
->FirstDpcChan
=
1042 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1046 KeQuerySystemTime(&time
);
1047 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1049 chan
= &deviceExtension
->chan
[lChannel
];
1050 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1052 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1053 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1060 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1061 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1062 if(!MiniportTimerValue
)
1063 MiniportTimerValue
= 1;
1065 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1066 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1073 } // end AtapiTimerDpc()
1076 Wrapper for ScsiPort, that implements smart Dpc
1077 queueing. We need it to allow parallel functioning
1078 of IDE channles with shared interrupt. Standard Dpc mechanism
1079 cancels previous Dpc request (if any), but we need Dpc queue.
1084 IN PVOID HwDeviceExtension
,
1086 IN PHW_TIMER HwScsiTimer
,
1087 IN ULONG MiniportTimerValue
1090 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1092 LARGE_INTEGER time2
;
1094 PHW_CHANNEL prev_chan
;
1096 // BOOLEAN UseRequestTimerCall = TRUE;
1098 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1099 KeQuerySystemTime(&time
);
1101 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1102 time
.QuadPart
+= MiniportTimerValue
*10;
1103 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1105 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1107 i
= deviceExtension
->FirstDpcChan
;
1108 chan
= prev_chan
= NULL
;
1109 while(i
!= CHAN_NOT_SPECIFIED
) {
1111 chan
= &deviceExtension
->chan
[i
];
1112 if(chan
->DpcTime
> time
.QuadPart
) {
1115 i
= chan
->NextDpcChan
;
1117 chan
= &deviceExtension
->chan
[lChannel
];
1119 deviceExtension
->FirstDpcChan
= lChannel
;
1121 prev_chan
->NextDpcChan
= lChannel
;
1123 chan
->NextDpcChan
= i
;
1124 chan
->HwScsiTimer
= HwScsiTimer
;
1125 chan
->DpcTime
= time
.QuadPart
;
1127 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1128 if(time
.QuadPart
<= time2
.QuadPart
) {
1129 MiniportTimerValue
= 1;
1131 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1134 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1135 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1137 MiniportTimerValue
);
1139 } // end AtapiQueueTimerDpc()
1141 #endif //UNIATA_CORE
1150 UCHAR statusByteAlt
;
1152 GetStatus(chan
, statusByteAlt
);
1153 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1155 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1156 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1157 KdPrint2((PRINT_PREFIX
1158 " Reg_%#x (%#x) = %#x\n",
1160 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1163 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1164 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1165 KdPrint2((PRINT_PREFIX
1166 " BM_%#x (%#x) = %#x\n",
1168 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1172 } // end UniataDumpATARegs()
1176 Routine Description:
1178 Issue IDENTIFY command to a device.
1182 HwDeviceExtension - HBA miniport driver's adapter data storage
1183 DeviceNumber - Indicates which device.
1184 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1188 TRUE if all goes well.
1194 IN PVOID HwDeviceExtension
,
1195 IN ULONG DeviceNumber
,
1201 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1202 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1203 ULONG waitCount
= 50000;
1209 BOOLEAN atapiDev
= FALSE
;
1210 ULONG ldev
= (lChannel
* 2) + DeviceNumber
;
1211 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
1213 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1214 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1217 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1218 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1222 SelectDrive(chan
, DeviceNumber
);
1223 AtapiStallExecution(10);
1224 statusByte
= WaitOnBusyLong(chan
);
1225 // Check that the status register makes sense.
1226 GetBaseStatus(chan
, statusByte2
);
1228 UniataDumpATARegs(chan
);
1230 if (Command
== IDE_COMMAND_IDENTIFY
) {
1231 // Mask status byte ERROR bits.
1232 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1233 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1234 // Check if register value is reasonable.
1236 if(statusByte
!= IDE_STATUS_IDLE
) {
1238 // No reset here !!!
1239 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1241 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1242 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1243 SelectDrive(chan
, DeviceNumber
);
1244 WaitOnBusyLong(chan
);
1246 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1247 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1249 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1250 signatureHigh
== ATAPI_MAGIC_MSB
) {
1252 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (ldev %d)\n", ldev
));
1256 // We really should wait up to 31 seconds
1257 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1258 // (30 seconds for device 1)
1260 // Wait for Busy to drop.
1261 AtapiStallExecution(100);
1262 GetStatus(chan
, statusByte
);
1264 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1265 GetBaseStatus(chan
, statusByte2
);
1267 SelectDrive(chan
, DeviceNumber
);
1269 GetBaseStatus(chan
, statusByte2
);
1271 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1273 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1274 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1276 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1277 signatureHigh
== ATAPI_MAGIC_MSB
) {
1278 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev
));
1283 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1284 if (statusByte
!= IDE_STATUS_IDLE
) {
1286 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (ldev %d)\n", ldev
));
1291 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1292 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1293 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1294 statusByte
= WaitForIdleLong(chan
);
1295 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1300 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1301 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1306 for (; j
< 4*2; j
++) {
1307 // Send IDENTIFY command.
1308 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1311 if (statusByte
& IDE_STATUS_DRQ
) {
1312 // Read status to acknowledge any interrupts generated.
1313 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1314 GetBaseStatus(chan
, statusByte
);
1315 // One last check for Atapi.
1316 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1317 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1319 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1320 signatureHigh
== ATAPI_MAGIC_MSB
) {
1321 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev
));
1327 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1328 if (Command
== IDE_COMMAND_IDENTIFY
) {
1329 // Check the signature. If DRQ didn't come up it's likely Atapi.
1330 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1331 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1333 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1334 signatureHigh
== ATAPI_MAGIC_MSB
) {
1336 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev
));
1340 // Device didn't respond correctly. It will be given one more chances.
1341 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1342 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1343 GetBaseStatus(chan
, statusByte
);
1344 AtapiSoftReset(chan
,DeviceNumber
);
1346 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1347 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1349 GetBaseStatus(chan
, statusByte
);
1350 //GetStatus(chan, statusByte);
1351 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1354 // Check for error on really stupid master devices that assert random
1355 // patterns of bits in the status register at the slave address.
1356 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1357 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1361 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1362 // Suck out 256 words. After waiting for one model that asserts busy
1363 // after receiving the Packet Identify command.
1364 statusByte
= WaitForDrq(chan
);
1365 statusByte
= WaitOnBusyLong(chan
);
1366 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1368 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1369 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1370 GetBaseStatus(chan
, statusByte
);
1373 GetBaseStatus(chan
, statusByte
);
1374 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1376 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1378 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1382 // ATI/SII chipsets with memory-mapped IO hangs when
1383 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1384 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1385 KdPrint2((PRINT_PREFIX
1386 " IO_%#x (%#x), %s:\n",
1388 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1389 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1390 for(i
=0; i
<256; i
++) {
1392 KdPrint2((PRINT_PREFIX
1395 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1397 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1398 KdPrint2((PRINT_PREFIX
1400 AtapiStallExecution(1);
1401 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1404 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1406 // Work around for some IDE and one model Atapi that will present more than
1407 // 256 bytes for the Identify data.
1408 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1409 statusByte
= AtapiSuckPort2(chan
);
1411 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1412 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1415 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1416 statusByte
= WaitForDrq(chan
);
1417 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1418 GetBaseStatus(chan
, statusByte
);
1420 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1423 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1427 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1428 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1429 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1430 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1431 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1432 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1434 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1435 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1436 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1437 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1439 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1441 // Check out a few capabilities / limitations of the device.
1442 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1443 // Determine if this drive supports the MSN functions.
1444 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1446 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1447 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1449 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1450 // Determine max. block transfer for this device.
1451 LunExt
->MaximumBlockXfer
=
1452 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1454 LunExt
->NumOfSectors
= 0;
1455 if (Command
== IDE_COMMAND_IDENTIFY
) {
1456 ULONGLONG NumOfSectors
=0;
1457 ULONGLONG NativeNumOfSectors
=0;
1458 ULONGLONG cylinders
=0;
1459 ULONGLONG tmp_cylinders
=0;
1460 // Read very-old-style drive geometry
1461 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1462 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1463 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1464 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1466 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1467 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1468 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1469 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1470 // Check for HDDs > 8Gb
1471 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1472 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1473 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1474 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1476 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1477 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1478 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1480 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1482 NumOfSectors
= cylinders
*
1483 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1484 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1486 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1490 // Check for LBA mode
1491 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1492 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1493 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1494 if ( deviceExtension
->FullIdentifyData
.SupportLba
1496 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1497 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1498 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1499 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1500 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1502 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1503 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1504 goto skip_lba_staff
;
1506 // Check for LBA48 support
1507 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1508 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1509 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1510 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1512 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1514 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1515 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1516 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1518 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1520 NativeNumOfSectors
= cylinders
*
1521 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1522 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1524 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1526 if(NativeNumOfSectors
> NumOfSectors
) {
1527 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1528 NumOfSectors
= NativeNumOfSectors
;
1532 // Check drive capacity report for LBA48-capable drives.
1533 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1534 ULONG hNativeNumOfSectors
;
1535 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1537 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1538 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1540 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1541 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1542 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1543 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1545 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1548 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1549 NativeNumOfSectors
|=
1550 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1551 hNativeNumOfSectors
=
1552 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1553 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1554 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1556 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1558 // Some drives report LBA48 capability while has capacity below 128Gb
1559 // Probably they support large block-counters.
1560 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1561 // Here we check this
1562 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1563 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1565 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1566 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1568 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1569 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1570 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1571 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1572 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1573 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1574 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1578 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1579 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1580 NativeNumOfSectors
= 0;
1584 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1585 NativeNumOfSectors
> NumOfSectors
) {
1587 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1588 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1590 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1591 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1592 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1593 NumOfSectors
= NativeNumOfSectors
;
1599 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1600 // check for native LBA size
1601 // some drives report ~32Gb in Identify Block
1602 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1604 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1605 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1607 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1608 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1609 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1610 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1611 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1613 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1615 if(NativeNumOfSectors
> NumOfSectors
) {
1617 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1618 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1620 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1621 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1622 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1623 NumOfSectors
= NativeNumOfSectors
;
1629 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1631 // fill IdentifyData with bogus geometry
1632 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1633 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1634 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1635 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1636 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1637 // ok, we can keep original values
1638 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1639 LunExt
->opt_GeomType
= GEOM_ORIG
;
1642 tmp_cylinders
= NumOfSectors
/ (255*63);
1643 if(tmp_cylinders
< 0xffff) {
1644 // we can use generic values for H/S for generic geometry approach
1645 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1646 LunExt
->opt_GeomType
= GEOM_STD
;
1649 // we should use UNIATA geometry approach
1650 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1651 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1655 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1657 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1658 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1659 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1661 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1662 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1664 cylinders
= NumOfSectors
/ (255*63);
1665 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1667 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1668 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1670 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1671 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1672 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1674 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1676 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1677 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1678 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1680 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1682 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1683 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1684 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1686 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1688 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1689 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1690 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1692 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1693 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1694 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1697 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1698 cylinders
= tmp_cylinders
;
1700 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1701 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1705 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1706 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1707 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1709 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1710 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1711 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1713 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1714 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1715 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1719 LunExt
->NumOfSectors
= NumOfSectors
;
1720 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1721 deviceExtension->FullIdentifyData.DoubleWordIo) {
1722 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1726 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1727 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1729 InitBadBlocks(LunExt
);
1731 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1732 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1734 // This device interrupts with the assertion of DRQ after receiving
1735 // Atapi Packet Command
1736 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1737 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1740 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1743 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1745 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1747 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1748 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1750 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1751 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1752 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1753 // set CD default costs
1754 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1755 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1756 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1757 statusByte
= WaitForDrq(chan
);
1759 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1760 LunExt
->IdentifyData
.DeviceType
));
1763 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1766 GetBaseStatus(chan
, statusByte
);
1767 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1770 } // end IssueIdentify()
1775 Routine Description:
1776 Set drive parameters using the IDENTIFY data.
1779 HwDeviceExtension - HBA miniport driver's adapter data storage
1780 DeviceNumber - Indicates which device.
1783 TRUE if all goes well.
1789 IN PVOID HwDeviceExtension
,
1790 IN ULONG DeviceNumber
,
1794 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1795 PIDENTIFY_DATA2 identifyData
= &deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].IdentifyData
;
1800 if(deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].DeviceFlags
&
1801 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1804 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1805 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1807 // Send SET PARAMETER command.
1808 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1809 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1810 (identifyData
->NumberOfHeads
- 1), 0,
1811 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1813 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1814 if(statusByte
& IDE_STATUS_ERROR
) {
1815 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1816 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1817 errorByte
, statusByte
));
1821 if(statusByte
== IDE_STATUS_IDLE
) {
1827 } // end SetDriveParameters()
1832 PHW_LU_EXTENSION LunExt
1835 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
1836 } // end UniataForgetDevice()
1841 Routine Description:
1842 Reset IDE controller and/or Atapi device.
1845 HwDeviceExtension - HBA miniport driver's adapter data storage
1854 AtapiResetController(
1855 IN PVOID HwDeviceExtension
,
1859 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1860 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1861 } // end AtapiResetController()
1866 AtapiResetController__(
1867 IN PVOID HwDeviceExtension
,
1869 IN BOOLEAN CompleteType
1872 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1873 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1874 PHW_CHANNEL chan
= NULL
;
1878 PSCSI_REQUEST_BLOCK CurSrb
;
1879 ULONG ChannelCtrlFlags
;
1880 UCHAR dma_status
= 0;
1882 ULONG slotNumber
= deviceExtension
->slotNumber
;
1883 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1884 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1886 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1888 //ULONG RevID = deviceExtension->RevID;
1889 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1893 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1895 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
1896 // we shall reset both channels on SimplexOnly devices,
1897 // It's not worth doing so on normal controllers
1899 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
1902 numberChannels
= deviceExtension
->NumberChannels
;
1905 for (; j
< numberChannels
; j
++) {
1907 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
1908 chan
= &deviceExtension
->chan
[j
];
1909 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
1910 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
1911 if(CompleteType
!= RESET_COMPLETE_NONE
) {
1913 while((CurSrb
= UniataGetCurRequest(chan
))) {
1915 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
1917 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
1918 // Check and see if we are processing an internal srb
1919 if (AtaReq
->OriginalSrb
) {
1920 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
1921 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
1922 AtaReq
->OriginalSrb
= NULL
;
1923 // NOTE: internal SRB doesn't get to SRB queue !!!
1924 CurSrb
= AtaReq
->Srb
;
1927 // Remove current request from queue
1928 UniataRemoveRequest(chan
, CurSrb
);
1930 // Check if request is in progress.
1931 ASSERT(AtaReq
->Srb
== CurSrb
);
1933 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1934 UCHAR PathId
= CurSrb
->PathId
;
1935 UCHAR TargetId
= CurSrb
->TargetId
;
1936 UCHAR Lun
= CurSrb
->Lun
;
1938 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
1939 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
1941 if (CurSrb
->SenseInfoBuffer
) {
1943 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
1945 senseBuffer
->ErrorCode
= 0x70;
1946 senseBuffer
->Valid
= 1;
1947 senseBuffer
->AdditionalSenseLength
= 0xb;
1948 if(CompleteType
== RESET_COMPLETE_ALL
) {
1949 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1950 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
1951 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
1952 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
1954 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1955 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
1956 senseBuffer
->AdditionalSenseCode
= 0;
1957 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
1961 // Clear request tracking fields.
1962 AtaReq
->WordsLeft
= 0;
1963 AtaReq
->DataBuffer
= NULL
;
1964 AtaReq
->TransferLength
= 0;
1966 ScsiPortNotification(RequestComplete
,
1970 // Indicate ready for next request.
1971 ScsiPortNotification(NextLuRequest
,
1977 if(CompleteType
!= RESET_COMPLETE_ALL
)
1980 #endif //UNIATA_CORE
1981 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1983 // Save control flags
1984 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
1985 // Clear expecting interrupt flag.
1986 chan
->ExpectingInterrupt
= FALSE
;
1988 chan
->ChannelCtrlFlags
= 0;
1989 InterlockedExchange(&(chan
->CheckIntr
),
1993 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
1994 AtapiDisableInterrupts(deviceExtension
, j
);
1995 KdPrint2((PRINT_PREFIX
" done\n"));
1997 case ATA_INTEL_ID
: {
2000 if(!(ChipFlags
& UNIATA_SATA
))
2002 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2006 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2007 if(ChipFlags
& UNIATA_AHCI
) {
2010 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2011 GetPciConfig1(0x90, tmp8
);
2018 ChangePciConfig2(0x92, a
& ~mask
);
2019 AtapiStallExecution(10);
2020 ChangePciConfig2(0x92, a
| mask
);
2023 AtapiStallExecution(10000);
2024 GetPciConfig2(0x92, tmp16
);
2025 if ((tmp16
& (mask
<< 4)) == (mask
<< 4)) {
2026 AtapiStallExecution(10000);
2032 case ATA_NVIDIA_ID
: {
2033 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2034 if(!(ChipFlags
& UNIATA_SATA
))
2037 case ATA_SILICON_IMAGE_ID
: {
2039 ULONG Channel
= deviceExtension
->Channel
+ j
;
2040 if(!(ChipFlags
& UNIATA_SATA
))
2042 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2043 /* disable PHY state change interrupt */
2044 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2046 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2048 /* reset controller part for this channel */
2049 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2050 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2051 AtapiStallExecution(1000);
2052 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2053 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2057 case ATA_PROMISE_ID
: {
2060 if(ChipFlags
& UNIATA_SATA
) {
2061 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2062 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2065 KdPrint2((PRINT_PREFIX
" send reset\n"));
2066 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2067 IDE_DC_RESET_CONTROLLER
);
2068 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2069 AtapiStallExecution(10000);
2070 // Disable interrupts
2071 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2072 AtapiDisableInterrupts(deviceExtension
, j
);
2073 AtapiStallExecution(100);
2074 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2075 AtapiEnableInterrupts(deviceExtension
, j
);
2076 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2077 AtapiStallExecution(100000);
2078 KdPrint2((PRINT_PREFIX
" done\n"));
2083 //if(!(ChipFlags & UNIATA_SATA)) {
2084 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2085 // Reset DMA engine if active
2086 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2087 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2088 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2089 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2090 (dma_status
& BM_STATUS_INTR
)) {
2091 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2095 // all these shall be performed inside AtapiHwInitialize__() ?
2097 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2098 // Do special processing for ATAPI and IDE disk devices.
2099 for (i
= 0; i
< max_ldev
; i
++) {
2101 // Check if device present.
2102 if (!(deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2106 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2107 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2110 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2114 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2115 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2116 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2121 SelectDrive(chan
, i
);
2122 AtapiStallExecution(10);
2123 statusByte
= WaitOnBusyLong(chan
);
2124 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2125 if(statusByte
== 0xff) {
2126 KdPrint2((PRINT_PREFIX
2127 "no drive, status %#x\n",
2129 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2131 // Check for ATAPI disk.
2132 if (deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2133 // Issue soft reset and issue identify.
2134 GetStatus(chan
, statusByte
);
2135 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2138 AtapiDisableInterrupts(deviceExtension
, j
);
2139 AtapiSoftReset(chan
, i
);
2140 AtapiEnableInterrupts(deviceExtension
, j
);
2142 GetStatus(chan
, statusByte
);
2144 if(statusByte
== IDE_STATUS_SUCCESS
) {
2146 IssueIdentify(HwDeviceExtension
,
2148 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2151 KdPrint2((PRINT_PREFIX
2152 "AtapiResetController: Status after soft reset %#x\n",
2155 GetBaseStatus(chan
, statusByte
);
2158 // Issue identify and reinit after channel reset.
2160 if (statusByte
!= IDE_STATUS_IDLE
&&
2161 statusByte
!= IDE_STATUS_SUCCESS
&&
2162 statusByte
!= IDE_STATUS_DRDY
) {
2164 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2166 if(!IssueIdentify(HwDeviceExtension
,
2168 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2170 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2172 // Set disk geometry parameters.
2173 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2174 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2176 GetBaseStatus(chan
, statusByte
);
2178 // force DMA mode reinit
2179 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
|= DFLAGS_REINIT_DMA
;
2183 // Enable interrupts, note, the we can have here recursive disable
2184 AtapiStallExecution(10);
2185 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2187 chan
->DisableIntr
));
2188 AtapiEnableInterrupts(deviceExtension
, j
);
2190 // Call the HwInitialize routine to setup multi-block.
2191 AtapiHwInitialize__(deviceExtension
, j
);
2193 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2197 } // end AtapiResetController__()
2202 Routine Description:
2203 This routine maps ATAPI and IDE errors to specific SRB statuses.
2206 HwDeviceExtension - HBA miniport driver's adapter data storage
2207 Srb - IO request packet
2216 IN PVOID HwDeviceExtension
,
2217 IN PSCSI_REQUEST_BLOCK Srb
2220 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2221 ULONG lChannel
= GET_CHANNEL(Srb
);
2222 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2225 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2227 ULONG ldev
= GET_LDEV(Srb
);
2229 // Read the error register.
2231 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2232 KdPrint2((PRINT_PREFIX
2233 "MapError: Error register is %#x\n",
2236 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2238 switch (errorByte
>> 4) {
2239 case SCSI_SENSE_NO_SENSE
:
2241 KdPrint2((PRINT_PREFIX
2242 "ATAPI: No sense information\n"));
2243 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2244 srbStatus
= SRB_STATUS_ERROR
;
2247 case SCSI_SENSE_RECOVERED_ERROR
:
2249 KdPrint2((PRINT_PREFIX
2250 "ATAPI: Recovered error\n"));
2252 srbStatus
= SRB_STATUS_SUCCESS
;
2255 case SCSI_SENSE_NOT_READY
:
2257 KdPrint2((PRINT_PREFIX
2258 "ATAPI: Device not ready\n"));
2259 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2260 srbStatus
= SRB_STATUS_ERROR
;
2263 case SCSI_SENSE_MEDIUM_ERROR
:
2265 KdPrint2((PRINT_PREFIX
2266 "ATAPI: Media error\n"));
2267 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2268 srbStatus
= SRB_STATUS_ERROR
;
2271 case SCSI_SENSE_HARDWARE_ERROR
:
2273 KdPrint2((PRINT_PREFIX
2274 "ATAPI: Hardware error\n"));
2275 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2276 srbStatus
= SRB_STATUS_ERROR
;
2279 case SCSI_SENSE_ILLEGAL_REQUEST
:
2281 KdPrint2((PRINT_PREFIX
2282 "ATAPI: Illegal request\n"));
2283 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2284 srbStatus
= SRB_STATUS_ERROR
;
2287 case SCSI_SENSE_UNIT_ATTENTION
:
2289 KdPrint2((PRINT_PREFIX
2290 "ATAPI: Unit attention\n"));
2291 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2292 srbStatus
= SRB_STATUS_ERROR
;
2295 case SCSI_SENSE_DATA_PROTECT
:
2297 KdPrint2((PRINT_PREFIX
2298 "ATAPI: Data protect\n"));
2299 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2300 srbStatus
= SRB_STATUS_ERROR
;
2303 case SCSI_SENSE_BLANK_CHECK
:
2305 KdPrint2((PRINT_PREFIX
2306 "ATAPI: Blank check\n"));
2307 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2308 srbStatus
= SRB_STATUS_ERROR
;
2311 case SCSI_SENSE_ABORTED_COMMAND
:
2312 KdPrint2((PRINT_PREFIX
2313 "Atapi: Command Aborted\n"));
2314 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2315 srbStatus
= SRB_STATUS_ERROR
;
2320 KdPrint2((PRINT_PREFIX
2321 "ATAPI: Invalid sense information\n"));
2323 srbStatus
= SRB_STATUS_ERROR
;
2331 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2332 chan
->ReturningMediaStatus
= errorByte
;
2334 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2335 KdPrint2((PRINT_PREFIX
2336 "IDE: Media change\n"));
2337 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2338 srbStatus
= SRB_STATUS_ERROR
;
2340 if (Srb
->SenseInfoBuffer
) {
2342 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2344 senseBuffer
->ErrorCode
= 0x70;
2345 senseBuffer
->Valid
= 1;
2346 senseBuffer
->AdditionalSenseLength
= 0xb;
2347 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2348 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2349 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2351 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2354 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2355 KdPrint2((PRINT_PREFIX
2356 "IDE: Command abort\n"));
2357 srbStatus
= SRB_STATUS_ABORTED
;
2358 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2360 if (Srb
->SenseInfoBuffer
) {
2362 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2364 senseBuffer
->ErrorCode
= 0x70;
2365 senseBuffer
->Valid
= 1;
2366 senseBuffer
->AdditionalSenseLength
= 0xb;
2367 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2368 senseBuffer
->AdditionalSenseCode
= 0;
2369 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2371 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2374 deviceExtension
->lun
[ldev
].ErrorCount
++;
2376 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2378 KdPrint2((PRINT_PREFIX
2379 "IDE: End of media\n"));
2380 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2381 srbStatus
= SRB_STATUS_ERROR
;
2383 if (Srb
->SenseInfoBuffer
) {
2385 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2387 senseBuffer
->ErrorCode
= 0x70;
2388 senseBuffer
->Valid
= 1;
2389 senseBuffer
->AdditionalSenseLength
= 0xb;
2390 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2391 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2392 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2393 senseBuffer
->EndOfMedia
= 1;
2395 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2398 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2399 deviceExtension
->lun
[ldev
].ErrorCount
++;
2402 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2404 KdPrint2((PRINT_PREFIX
2405 "IDE: Illegal length\n"));
2406 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2408 if (Srb
->SenseInfoBuffer
) {
2410 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2412 senseBuffer
->ErrorCode
= 0x70;
2413 senseBuffer
->Valid
= 1;
2414 senseBuffer
->AdditionalSenseLength
= 0xb;
2415 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2416 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2417 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2418 senseBuffer
->IncorrectLength
= 1;
2420 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2423 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2425 KdPrint2((PRINT_PREFIX
2426 "IDE: Bad block\n"));
2427 srbStatus
= SRB_STATUS_ERROR
;
2428 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2429 if (Srb
->SenseInfoBuffer
) {
2431 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2433 senseBuffer
->ErrorCode
= 0x70;
2434 senseBuffer
->Valid
= 1;
2435 senseBuffer
->AdditionalSenseLength
= 0xb;
2436 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2437 senseBuffer
->AdditionalSenseCode
= 0;
2438 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2440 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2443 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2445 KdPrint2((PRINT_PREFIX
2446 "IDE: Id not found\n"));
2447 srbStatus
= SRB_STATUS_ERROR
;
2448 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2450 if (Srb
->SenseInfoBuffer
) {
2452 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2454 senseBuffer
->ErrorCode
= 0x70;
2455 senseBuffer
->Valid
= 1;
2456 senseBuffer
->AdditionalSenseLength
= 0xb;
2457 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2458 senseBuffer
->AdditionalSenseCode
= 0;
2459 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2461 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2464 deviceExtension
->lun
[ldev
].ErrorCount
++;
2466 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2468 KdPrint2((PRINT_PREFIX
2469 "IDE: Media change\n"));
2470 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2471 srbStatus
= SRB_STATUS_ERROR
;
2473 if (Srb
->SenseInfoBuffer
) {
2475 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2477 senseBuffer
->ErrorCode
= 0x70;
2478 senseBuffer
->Valid
= 1;
2479 senseBuffer
->AdditionalSenseLength
= 0xb;
2480 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2481 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2482 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2484 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2487 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2489 KdPrint2((PRINT_PREFIX
2490 "IDE: Data error\n"));
2491 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2492 srbStatus
= SRB_STATUS_ERROR
;
2494 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2495 deviceExtension
->lun
[ldev
].ErrorCount
++;
2498 // Build sense buffer
2499 if (Srb
->SenseInfoBuffer
) {
2501 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2503 senseBuffer
->ErrorCode
= 0x70;
2504 senseBuffer
->Valid
= 1;
2505 senseBuffer
->AdditionalSenseLength
= 0xb;
2506 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2507 senseBuffer
->AdditionalSenseCode
= 0;
2508 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2510 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2514 if (deviceExtension
->lun
[ldev
].ErrorCount
>= MAX_ERRORS
) {
2515 // deviceExtension->DWordIO = FALSE;
2517 KdPrint2((PRINT_PREFIX
2518 "MapError: ErrorCount >= MAX_ERRORS\n"));
2520 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2521 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2524 KdPrint2((PRINT_PREFIX
2525 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2528 KdPrint2((PRINT_PREFIX
2529 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2538 ScsiPortLogError( HwDeviceExtension
,
2546 // Reprogram to not use Multi-sector.
2549 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2550 !(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2552 statusByte
= AtaCommand(deviceExtension
, ldev
& 0x1, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2554 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2555 // command was aborted.
2556 if (statusByte
& IDE_STATUS_ERROR
) {
2558 // Read the error register.
2559 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2561 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2565 // Adjust the devExt. value, if necessary.
2566 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2574 // Set SCSI status to indicate a check condition.
2575 Srb
->ScsiStatus
= scsiStatus
;
2584 Routine Description:
2587 HwDeviceExtension - HBA miniport driver's adapter data storage
2590 TRUE - if initialization successful.
2591 FALSE - if initialization unsuccessful.
2597 IN PVOID HwDeviceExtension
2600 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2601 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2604 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2606 if(WinVer_WDM_Model
) {
2607 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2610 /* do extra chipset specific setups */
2611 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2613 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2614 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2615 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2618 for (c
= 0; c
< numberChannels
; c
++) {
2619 AtapiHwInitialize__(deviceExtension
, c
);
2621 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2623 } // end AtapiHwInitialize()
2627 AtapiHwInitialize__(
2628 IN PHW_DEVICE_EXTENSION deviceExtension
,
2633 UCHAR statusByte
, errorByte
;
2634 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2635 PHW_LU_EXTENSION LunExt
;
2637 ULONG PreferedMode
= 0xffffffff;
2639 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2640 FindDevices(deviceExtension
, 0, lChannel
);
2642 for (i
= lChannel
*2; i
< (lChannel
+1)*2; i
++) {
2644 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2646 LunExt
= &(deviceExtension
->lun
[i
]);
2648 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2652 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2653 AtapiStallExecution(1);
2655 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2657 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2658 // Enable media status notification
2659 IdeMediaStatus(TRUE
,deviceExtension
,(UCHAR
)i
);
2661 // If supported, setup Multi-block transfers.
2662 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2663 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2664 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2666 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2667 // command was aborted.
2668 if (statusByte
& IDE_STATUS_ERROR
) {
2670 // Read the error register.
2671 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2673 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2677 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2678 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2679 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2681 if (statusByte
& IDE_STATUS_ERROR
) {
2682 // Read the error register.
2683 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2685 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2689 // Adjust the devExt. value, if necessary.
2690 LunExt
->MaximumBlockXfer
= 0;
2693 KdPrint2((PRINT_PREFIX
2694 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2696 LunExt
->MaximumBlockXfer
));
2699 if(LunExt
->IdentifyData
.MajorRevision
) {
2701 if(LunExt
->opt_ReadCacheEnable
) {
2702 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2703 // If supported, setup read/write cacheing
2704 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2705 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2706 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2708 // Check for errors.
2709 if (statusByte
& IDE_STATUS_ERROR
) {
2710 KdPrint2((PRINT_PREFIX
2711 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2713 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2715 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2718 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2719 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2720 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2721 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2722 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2724 if(LunExt
->opt_WriteCacheEnable
) {
2725 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2726 // If supported & allowed, setup write cacheing
2727 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2728 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2729 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2730 // Check for errors.
2731 if (statusByte
& IDE_STATUS_ERROR
) {
2732 KdPrint2((PRINT_PREFIX
2733 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2735 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2737 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2740 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2741 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2742 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2743 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2744 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2748 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2751 BOOLEAN isSanyo
= FALSE
;
2754 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2756 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2757 for (j
= 0; j
< 26; j
+= 2) {
2759 // Build a buffer based on the identify data.
2760 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2763 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2765 // Inquiry string for older model had a '-', newer is '_'
2766 if (vendorId
[12] == 'C') {
2768 // Torisan changer. Set the bit. This will be used in several places
2769 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2770 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2771 LunExt
->DiscsPresent
= 3;
2777 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2778 if(PreferedMode
== 0xffffffff) {
2779 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2780 PreferedMode
= chan
->MaxTransferMode
;
2783 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2784 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2785 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2788 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2789 LunExt
->OrigTransferMode
=
2790 LunExt
->LimitedTransferMode
=
2791 LunExt
->TransferMode
=
2794 AtapiDmaInit__(deviceExtension
, i
);
2796 LunExt
->OrigTransferMode
=
2797 LunExt
->LimitedTransferMode
=
2798 LunExt
->TransferMode
;
2799 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2801 // We need to get our device ready for action before
2802 // returning from this function
2804 // According to the atapi spec 2.5 or 2.6, an atapi device
2805 // clears its status BSY bit when it is ready for atapi commands.
2806 // However, some devices (Panasonic SQ-TC500N) are still
2807 // not ready even when the status BSY is clear. They don't react
2808 // to atapi commands.
2810 // Since there is really no other indication that tells us
2811 // the drive is really ready for action. We are going to check BSY
2812 // is clear and then just wait for an arbitrary amount of time!
2814 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2817 // have to get out of the loop sometime!
2818 // 10000 * 100us = 1000,000us = 1000ms = 1s
2820 GetStatus(chan
, statusByte
);
2821 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2823 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2824 // Wait for Busy to drop.
2825 AtapiStallExecution(100);
2826 GetStatus(chan
, statusByte
);
2830 // 5000 * 100us = 500,000us = 500ms = 0.5s
2833 AtapiStallExecution(100);
2834 } while (waitCount
--);
2836 GetBaseStatus(chan
, statusByte
);
2837 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2838 AtapiStallExecution(10);
2843 } // end AtapiHwInitialize()
2850 AtapiHwInitializeChanger(
2851 IN PVOID HwDeviceExtension
,
2852 IN PSCSI_REQUEST_BLOCK Srb
,
2853 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2855 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2856 ULONG ldev
= GET_LDEV(Srb
);
2858 if (MechanismStatus
) {
2859 deviceExtension
->lun
[ldev
].DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2860 if (deviceExtension
->lun
[ldev
].DiscsPresent
> 1) {
2861 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
2865 } // end AtapiHwInitializeChanger()
2870 Routine Description:
2871 This routine will parse the string for a match on the keyword, then
2872 calculate the value for the keyword and return it to the caller.
2875 String - The ASCII string to parse.
2876 KeyWord - The keyword for the value desired.
2879 Zero if value not found
2880 Value converted from ASCII to binary.
2885 AtapiParseArgumentString(
2893 ULONG stringLength
= 0;
2894 ULONG keyWordLength
= 0;
2904 // Calculate the string length.
2910 // Calculate the keyword length.
2916 if (keyWordLength
> stringLength
) {
2918 // Can't possibly have a match.
2922 // Now setup and start the compare.
2927 // The input string may start with white space. Skip it.
2928 while (*cptr
== ' ' || *cptr
== '\t') {
2932 if (*cptr
== '\0') {
2938 while ((*cptr
== *kptr
) ||
2939 (*cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
2940 (*cptr
>= 'a' && *cptr
- ('a' - 'A') == *kptr
)) {
2944 if (*cptr
== '\0') {
2950 if (*kptr
== '\0') {
2952 // May have a match backup and check for blank or equals.
2953 while (*cptr
== ' ' || *cptr
== '\t') {
2957 // Found a match. Make sure there is an equals.
2960 // Not a match so move to the next semicolon.
2962 if (*cptr
++ == ';') {
2963 goto ContinueSearch
;
2968 // Skip the equals sign.
2971 // Skip white space.
2972 while ((*cptr
== ' ') || (*cptr
== '\t')) {
2976 if (*cptr
== '\0') {
2977 // Early end of string, return not found
2982 // This isn't it either.
2984 goto ContinueSearch
;
2988 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
2989 // Value is in Hex. Skip the "0x"
2991 for (index
= 0; *(cptr
+ index
); index
++) {
2993 if (*(cptr
+ index
) == ' ' ||
2994 *(cptr
+ index
) == '\t' ||
2995 *(cptr
+ index
) == ';') {
2999 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3000 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3002 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3003 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3004 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3005 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3007 // Syntax error, return not found.
3014 // Value is in Decimal.
3015 for (index
= 0; *(cptr
+ index
); index
++) {
3017 if (*(cptr
+ index
) == ' ' ||
3018 *(cptr
+ index
) == '\t' ||
3019 *(cptr
+ index
) == ';') {
3023 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3024 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3027 // Syntax error return not found.
3036 // Not a match check for ';' to continue search.
3038 if (*cptr
++ == ';') {
3039 goto ContinueSearch
;
3045 } // end AtapiParseArgumentString()_
3053 IN PVOID HwDeviceExtension
,
3058 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3059 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3062 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3065 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3066 // If the last command was DSC restrictive, see if it's set. If so, the device is
3067 // ready for a new request. Otherwise, reset the timer and come back to here later.
3069 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3070 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3071 // we shall have no problem with interrupt handler.
3072 if (!srb
|| chan
->ExpectingInterrupt
) {
3073 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3074 chan
->DpcState
= DPC_STATE_TIMER
;
3075 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3076 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3077 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3079 goto ReturnCallback
;
3083 if (!IS_RDP((srb
->Cdb
[0]))) {
3084 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3088 goto ReturnEnableIntr
;
3090 GetStatus(chan
, statusByte
);
3091 if (statusByte
& IDE_STATUS_DSC
) {
3093 UCHAR PathId
= srb
->PathId
;
3094 UCHAR TargetId
= srb
->TargetId
;
3095 UCHAR Lun
= srb
->Lun
;
3097 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3098 AtapiDmaDBSync(chan
, srb
);
3099 UniataRemoveRequest(chan
, srb
);
3100 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3101 // Clear current SRB.
3102 if(!deviceExtension
->simplexOnly
) {
3103 srb
= UniataGetCurRequest(chan
);