3 Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter)
9 This module handles SATA-related staff
12 Alexander A. Telyatnikov (Alter)
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 IN PVOID HwDeviceExtension
,
40 IN ULONG lChannel
, // logical channel
41 IN ULONG pm_port
/* for port multipliers */
44 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
45 //ULONG Channel = deviceExtension->Channel + lChannel;
46 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
47 SATA_SSTATUS_REG SStatus
;
55 KdPrint2((PRINT_PREFIX
"UniataSataConnect:\n"));
57 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
58 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
59 return IDE_STATUS_IDLE
;
62 /* clear SATA error register, some controllers need this */
63 UniataSataWritePort4(chan
, IDX_SATA_SError
,
64 UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
), pm_port
);
65 /* wait up to 1 second for "connect well" */
66 for(i
=0; i
<100; i
++) {
67 SStatus
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SStatus
, pm_port
);
68 if(SStatus
.SPD
== SStatus_SPD_Gen1
||
69 SStatus
.SPD
== SStatus_SPD_Gen2
||
70 SStatus
.SPD
== SStatus_SPD_Gen3
) {
71 chan
->lun
[0]->TransferMode
= ATA_SA150
+ (UCHAR
)(SStatus
.SPD
- 1);
72 KdPrint2((PRINT_PREFIX
"SATA TransferMode %#x\n", chan
->lun
[0]->TransferMode
));
75 AtapiStallExecution(10000);
78 KdPrint2((PRINT_PREFIX
"UniataSataConnect: SStatus %8.8x\n", SStatus
.Reg
));
81 /* clear SATA error register */
82 UniataSataWritePort4(chan
, IDX_SATA_SError
,
83 UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
), pm_port
);
85 Status
= WaitOnBaseBusyLong(chan
);
86 if(Status
& IDE_STATUS_BUSY
) {
90 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow);
91 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh);
93 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
96 KdPrint2((PRINT_PREFIX
"UniataSataConnect: OK, ATA status %#x\n", Status
));
97 return IDE_STATUS_IDLE
;
98 } // end UniataSataConnect()
103 IN PVOID HwDeviceExtension
,
104 IN ULONG lChannel
, // logical channel
105 IN ULONG pm_port
, /* for port multipliers */
109 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
110 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
111 SATA_SCONTROL_REG SControl
;
114 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable:\n"));
116 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
117 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
118 return IDE_STATUS_IDLE
;
121 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
122 KdPrint2((PRINT_PREFIX
"SControl %#x\n", SControl
.Reg
));
123 if(SControl
.DET
== SControl_DET_Idle
) {
125 return UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
129 for (retry
= 0; retry
< 10; retry
++) {
130 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry init %d\n", retry
));
131 for (loop
= 0; loop
< 10; loop
++) {
133 SControl
.DET
= SControl_DET_Init
;
134 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, pm_port
);
135 AtapiStallExecution(100);
136 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
137 KdPrint2((PRINT_PREFIX
" SControl %8.8x\n", SControl
.Reg
));
138 if(SControl
.DET
== SControl_DET_Init
) {
142 AtapiStallExecution(5000);
143 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry idle %d\n", retry
));
144 for (loop
= 0; loop
< 10; loop
++) {
146 SControl
.DET
= SControl_DET_DoNothing
;
147 SControl
.IPM
= SControl_IPM_NoPartialSlumber
;
148 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, pm_port
);
149 AtapiStallExecution(100);
150 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
151 KdPrint2((PRINT_PREFIX
" SControl %8.8x\n", SControl
.Reg
));
152 if(SControl
.DET
== SControl_DET_Idle
) {
153 return UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
158 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: failed\n"));
160 } // end UniataSataPhyEnable()
165 IN PVOID HwDeviceExtension
,
166 IN ULONG lChannel
, // logical channel
167 IN BOOLEAN do_connect
,
168 IN ULONG pm_port
/* for port multipliers */
171 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
172 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
173 //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
174 SATA_SSTATUS_REG SStatus
;
175 SATA_SERROR_REG SError
;
177 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
178 //if(ChipFlags & UNIATA_SATA) {
180 SStatus
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SStatus
, pm_port
);
181 SError
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
);
184 KdPrint2((PRINT_PREFIX
" SStatus %#x\n", SStatus
.Reg
));
187 KdPrint2((PRINT_PREFIX
" SError %#x\n", SError
.Reg
));
188 /* clear error bits/interrupt */
189 UniataSataWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
, pm_port
);
192 /* if we have a connection event deal with it */
194 KdPrint2((PRINT_PREFIX
" catch SATA connect/disconnect\n"));
195 if(SStatus
.SPD
>= SStatus_SPD_Gen1
) {
196 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, pm_port
);
198 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, pm_port
);
206 } // end UniataSataClearErr()
211 IN PVOID HwDeviceExtension
,
212 IN ULONG lChannel
, // logical channel
214 IN ULONG pm_port
/* for port multipliers */
217 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
219 ULONG DeviceNumber
= (pm_port
? 1 : 0);
221 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
226 case UNIATA_SATA_EVENT_ATTACH
:
227 KdPrint2((PRINT_PREFIX
" CONNECTED\n"));
228 Status
= UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
229 KdPrint2((PRINT_PREFIX
" Status %#x\n", Status
));
230 if(Status
!= IDE_STATUS_IDLE
) {
233 CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
/*dev*/, FALSE
);
236 case UNIATA_SATA_EVENT_DETACH
:
237 KdPrint2((PRINT_PREFIX
" DISCONNECTED\n"));
238 UniataForgetDevice(deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
]);
243 } // end UniataSataEvent()
249 IN ULONG io_port_ndx
,
250 IN ULONG pm_port
/* for port multipliers */
253 if(chan
&& (io_port_ndx
< IDX_MAX_REG
) &&
254 chan
->RegTranslation
[io_port_ndx
].Proc
) {
256 KdPrint3((PRINT_PREFIX
" UniataSataReadPort4 %#x[%d]\n", io_port_ndx
, pm_port
));
258 PHW_DEVICE_EXTENSION deviceExtension
= chan
->DeviceExtension
;
259 PVOID HwDeviceExtension
= (PVOID
)deviceExtension
;
260 ULONG slotNumber
= deviceExtension
->slotNumber
;
261 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
262 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
269 if(deviceExtension
->HwFlags
& ICH5
) {
270 offs
= 0x50+chan
->lun
[p
]->SATA_lun_map
*0x10;
271 KdPrint3((PRINT_PREFIX
" ICH5 way, offs %#x\n", offs
));
272 switch(io_port_ndx
) {
273 case IDX_SATA_SStatus
:
276 case IDX_SATA_SError
:
279 case IDX_SATA_SControl
:
285 SetPciConfig4(0xa0, offs
);
286 GetPciConfig4(0xa4, offs
);
289 offs
= ((deviceExtension
->Channel
+chan
->lChannel
)*2+p
) * 0x100;
290 KdPrint3((PRINT_PREFIX
" def way, offs %#x\n", offs
));
291 switch(io_port_ndx
) {
292 case IDX_SATA_SStatus
:
295 case IDX_SATA_SControl
:
298 case IDX_SATA_SError
:
304 AtapiWritePort4(chan
, IDX_INDEXED_ADDR
, offs
);
305 return AtapiReadPort4(chan
, IDX_INDEXED_DATA
);
308 } // end switch(VendorID)
311 return AtapiReadPort4(chan
, io_port_ndx
);
312 } // end UniataSataReadPort4()
316 UniataSataWritePort4(
318 IN ULONG io_port_ndx
,
320 IN ULONG pm_port
/* for port multipliers */
323 if(chan
&& (io_port_ndx
< IDX_MAX_REG
) &&
324 chan
->RegTranslation
[io_port_ndx
].Proc
) {
326 KdPrint3((PRINT_PREFIX
" UniataSataWritePort4 %#x[%d]\n", io_port_ndx
, pm_port
));
328 PHW_DEVICE_EXTENSION deviceExtension
= chan
->DeviceExtension
;
329 PVOID HwDeviceExtension
= (PVOID
)deviceExtension
;
330 ULONG slotNumber
= deviceExtension
->slotNumber
;
331 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
332 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
339 if(deviceExtension
->HwFlags
& ICH5
) {
340 offs
= 0x50+chan
->lun
[p
]->SATA_lun_map
*0x10;
341 KdPrint3((PRINT_PREFIX
" ICH5 way, offs %#x\n", offs
));
342 switch(io_port_ndx
) {
343 case IDX_SATA_SStatus
:
346 case IDX_SATA_SError
:
349 case IDX_SATA_SControl
:
355 SetPciConfig4(0xa0, offs
);
356 SetPciConfig4(0xa4, data
);
359 offs
= ((deviceExtension
->Channel
+chan
->lChannel
)*2+p
) * 0x100;
360 KdPrint3((PRINT_PREFIX
" def way, offs %#x\n", offs
));
361 switch(io_port_ndx
) {
362 case IDX_SATA_SStatus
:
365 case IDX_SATA_SControl
:
368 case IDX_SATA_SError
:
374 AtapiWritePort4(chan
, IDX_INDEXED_ADDR
, offs
);
375 AtapiWritePort4(chan
, IDX_INDEXED_DATA
, data
);
378 } // end switch(VendorID)
381 AtapiWritePort4(chan
, io_port_ndx
, data
);
382 } // end UniataSataWritePort4()
388 IN ULONG DeviceNumber
,
393 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
394 return UniataAhciReadPM(chan
, DeviceNumber
, Reg
, result
);
397 } // end UniataSataReadPM()
403 IN ULONG DeviceNumber
,
408 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
409 return UniataAhciWritePM(chan
, DeviceNumber
, Reg
, value
);
412 } // end UniataSataWritePM()
417 IN PVOID HwDeviceExtension
,
419 IN ULONG DeviceNumber
422 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
424 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
425 return UniataAhciSoftReset(HwDeviceExtension
, lChannel
, DeviceNumber
);
428 } // end UniataSataSoftReset()
431 UniataSataIdentifyPM(
440 PHW_LU_EXTENSION LunExt
;
442 KdPrint((PRINT_PREFIX
"UniataSataIdentifyPM:\n"));
446 /* get PM vendor & product data */
447 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 0, &PM_DeviceId
)) {
448 KdPrint2((PRINT_PREFIX
" error getting PM vendor data\n"));
451 /* get PM revision data */
452 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 1, &PM_RevId
)) {
453 KdPrint2((PRINT_PREFIX
" error getting PM revison data\n"));
456 /* get number of HW ports on the PM */
457 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 2, &PM_Ports
)) {
458 KdPrint2((PRINT_PREFIX
" error getting PM port info\n"));
462 PM_Ports
&= 0x0000000f;
464 switch(PM_DeviceId
) {
466 /* This PM declares 6 ports, while only 5 of them are real.
467 * Port 5 is enclosure management bridge port, which has implementation
468 * problems, causing probe faults. Hide it for now. */
469 KdPrint2((PRINT_PREFIX
" SiI 3726 (rev=%#x) Port Multiplier with %d (5) ports\n",
470 PM_RevId
, PM_Ports
));
474 /* This PM declares 7 ports, while only 5 of them are real.
475 * Port 5 is some fake "Config Disk" with 640 sectors size,
476 * port 6 is enclosure management bridge port.
477 * Both fake ports has implementation problems, causing
478 * probe faults. Hide them for now. */
479 KdPrint2((PRINT_PREFIX
" SiI 4726 (rev=%#x) Port Multiplier with %d (5) ports\n",
480 PM_RevId
, PM_Ports
));
484 KdPrint2((PRINT_PREFIX
" Port Multiplier (id=%08x rev=%#x) with %d ports\n",
485 PM_DeviceId
, PM_RevId
, PM_Ports
));
490 for(i
=0; i
<PM_Ports
; i
++) {
492 LunExt
= chan
->lun
[i
];
494 KdPrint2((PRINT_PREFIX
" Port %d\n", i
));
495 if(UniataSataPhyEnable(chan
->DeviceExtension
, chan
->lChannel
, i
, UNIATA_SATA_RESET_ENABLE
) != IDE_STATUS_IDLE
) {
496 LunExt
->DeviceFlags
&= ~DFLAGS_DEVICE_PRESENT
;
500 * XXX: I have no idea how to properly wait for PMP port hardreset
501 * completion. Without this delay soft reset does not completes
504 AtapiStallExecution(1000000);
506 signature
= UniataSataSoftReset(chan
->DeviceExtension
, chan
->lChannel
, i
);
507 KdPrint2((PRINT_PREFIX
" signature %#x\n", signature
));
509 LunExt
->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
510 chan
->PmLunMap
|= (1 << i
);
511 /* figure out whats there */
512 switch (signature
>> 16) {
514 LunExt
->DeviceFlags
&= ~DFLAGS_ATAPI_DEVICE
;
517 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_DEVICE
;
523 } // end UniataSataIdentifyPM()
529 IN PHW_DEVICE_EXTENSION deviceExtension
535 KdPrint2((PRINT_PREFIX
536 " AHCI Base: %#x MemIo %d Proc %d\n",
537 deviceExtension
->BaseIoAHCI_0
.Addr
,
538 deviceExtension
->BaseIoAHCI_0
.MemIo
,
539 deviceExtension
->BaseIoAHCI_0
.Proc
));
541 for(j
=0; j
<=IDX_AHCI_VS
; j
+=sizeof(ULONG
)) {
542 xReg
= AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)&deviceExtension
->BaseIoAHCI_0
, j
);
543 KdPrint2((PRINT_PREFIX
544 " AHCI_%#x (%#x) = %#x\n",
546 (deviceExtension
->BaseIoAHCI_0
.Addr
+j
),
550 } // end UniataDumpAhciRegs()
555 UniataDumpAhciPortRegs(
562 KdPrint2((PRINT_PREFIX
563 " AHCI port %d Base: %#x MemIo %d Proc %d\n",
565 chan
->BaseIoAHCI_Port
.Addr
,
566 chan
->BaseIoAHCI_Port
.MemIo
,
567 chan
->BaseIoAHCI_Port
.Proc
));
569 for(j
=0; j
<=IDX_AHCI_P_SNTF
; j
+=sizeof(ULONG
)) {
570 xReg
= AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)&chan
->BaseIoAHCI_Port
, j
);
571 KdPrint2((PRINT_PREFIX
572 " AHCI%d_%#x (%#x) = %#x\n",
575 (chan
->BaseIoAHCI_Port
.Addr
+j
),
579 } // end UniataDumpAhciPortRegs()
586 IN PVOID HwDeviceExtension
589 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
593 ULONG BaseMemAddress
;
597 BOOLEAN MemIo
= FALSE
;
599 KdPrint2((PRINT_PREFIX
" UniataAhciInit:\n"));
602 UniataDumpAhciRegs(deviceExtension
);
605 /* reset AHCI controller */
606 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
607 KdPrint2((PRINT_PREFIX
" reset AHCI controller, GHC %#x\n", GHC
));
608 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
611 for(i
=0; i
<1000; i
++) {
612 AtapiStallExecution(1000);
613 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
614 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
615 if(!(GHC
& AHCI_GHC_HR
)) {
619 if(GHC
& AHCI_GHC_HR
) {
620 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
624 /* enable AHCI mode */
625 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
626 KdPrint2((PRINT_PREFIX
" enable AHCI mode, GHC %#x\n", GHC
));
627 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
629 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
630 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
632 deviceExtension
->AHCI_CAP
=
633 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
634 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
635 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
636 if(CAP
& AHCI_CAP_S64A
) {
637 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
638 deviceExtension
->Host64
= TRUE
;
640 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
641 if(CAP
& AHCI_CAP_PMD
) {
642 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
644 if(CAP
& AHCI_CAP_SAM
) {
645 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
647 /* get the number of HW channels */
648 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
649 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
651 /* clear interrupts */
652 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
653 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
655 /* enable AHCI interrupts */
656 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
657 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
659 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
660 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
662 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
663 chan
= &deviceExtension
->chan
[c
];
664 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
666 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
668 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
670 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
671 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
673 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
674 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
675 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
676 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
677 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
678 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
679 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
680 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
681 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
682 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
683 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
685 UniataInitSyncBaseIO(chan
);
687 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
688 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
689 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
690 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
691 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
692 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
693 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
694 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
696 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
698 UniataAhciResume(chan
);
700 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
704 } // end UniataAhciInit()
709 IN PVOID HwDeviceExtension
,
710 IN PPCI_COMMON_CONFIG pciData
, // optional
711 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
714 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
715 //ULONG slotNumber = deviceExtension->slotNumber;
716 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
722 ULONG NumberChannels
;
724 ULONG BaseMemAddress
;
727 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
729 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 1 /* DEBUG */)) {
730 KdPrint((" AHCI excluded\n"));
733 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
735 if(!BaseMemAddress
) {
736 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
739 if(BaseMemAddress
&& (*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
740 KdPrint2((PRINT_PREFIX
"MemIo\n"));
743 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
744 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
747 UniataDumpAhciRegs(deviceExtension
);
750 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
751 if(GHC
& AHCI_GHC_HR
) {
752 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
756 /* enable AHCI mode */
757 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
758 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
759 if(!(GHC
& AHCI_GHC_AE
)) {
760 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
764 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
765 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
766 if(CAP
& AHCI_CAP_S64A
) {
767 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
768 //deviceExtension->Host64 = TRUE;
771 /* get the number of HW channels */
772 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
773 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
774 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
776 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
778 KdPrint2((PRINT_PREFIX
" Channels %d\n", n
));
780 switch(deviceExtension
->DevID
) {
793 if(!NumberChannels
) {
794 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
798 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
799 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
800 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
802 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
804 NumberChannels
, PI
));
806 if(CAP
& AHCI_CAP_SPM
) {
807 KdPrint2((PRINT_PREFIX
" PM supported\n"));
808 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
809 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
810 deviceExtension
->NumberLuns
= 2;
811 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
813 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
814 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
815 //deviceExtension->NumberLuns = 1;
818 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
819 deviceExtension
->NumberLuns
= 1;
822 if((v_Mj
!= 0x01) || (v_Mn
> 0x20)) {
823 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
824 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", 1)) {
825 KdPrint((" AHCI revision excluded\n"));
830 deviceExtension
->HwFlags
|= UNIATA_SATA
;
831 deviceExtension
->HwFlags
|= UNIATA_AHCI
;
832 if(deviceExtension
->NumberChannels
< NumberChannels
) {
833 deviceExtension
->NumberChannels
= NumberChannels
;
837 } // end UniataAhciDetect()
842 IN PVOID HwDeviceExtension
,
844 IN ULONG DeviceNumber
847 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
848 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
849 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
853 SATA_SSTATUS_REG SStatus
;
854 SATA_SERROR_REG SError
;
855 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
858 KdPrint(("UniataAhciStatus:\n"));
860 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
861 KdPrint((" hIS %#x\n", hIS
));
862 hIS
&= (1 << Channel
);
864 return INTERRUPT_REASON_IGNORE
;
866 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
867 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
868 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
869 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
871 /* clear interrupt(s) */
872 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
873 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
874 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
876 KdPrint((" AHCI: status=%08x sstatus=%08x error=%08x CI=%08x\n",
877 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
));
879 /* do we have cold connect surprise */
883 /* check for and handle connect events */
885 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
888 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
890 if(CI
& (1 << tag
)) {
891 return INTERRUPT_REASON_OUR
;
893 KdPrint((" AHCI: unexpected\n"));
894 return INTERRUPT_REASON_UNEXPECTED
;
896 } // end UniataAhciStatus()
900 UniataAhciSetupFIS_H2D(
901 IN PHW_DEVICE_EXTENSION deviceExtension
,
902 IN ULONG DeviceNumber
,
915 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
917 KdPrint2((PRINT_PREFIX
" AHCI setup FIS ch %d, dev %d\n", lChannel
, DeviceNumber
));
921 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
922 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
923 fis
[7] = IDE_USE_LBA
;
924 fis
[15] = IDE_DC_A_4BIT
;
926 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
927 fis
[2] = IDE_COMMAND_ATAPI_PACKET
;
928 if(feature
& ATA_F_DMA
) {
929 fis
[3] = (UCHAR
)(feature
& 0xff);
931 fis
[5] = (UCHAR
)(count
& 0xff);
932 fis
[6] = (UCHAR
)(count
>>8) & 0xff;
936 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
937 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
938 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
939 //return IDE_STATUS_ERROR;
940 //return SRB_STATUS_ERROR;
944 need48
= UniAta_need_lba48(command
, lba
, count
,
945 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
947 /* translate command into 48bit version */
949 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
950 command
= AtaCommands48
[command
];
952 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
958 fis
[3] = (UCHAR
)feature
;
967 #pragma warning(push)
968 #pragma warning(disable:4333) // right shift by too large amount, data loss
970 fis
[7] |= IDE_DRIVE_1
| ((plba
[3] >> 24) & 0x0f);
979 fis
[11] = (UCHAR
)(feature
>>8) & 0xff;
981 fis
[12] = (UCHAR
)count
& 0xff;
982 fis
[13] = (UCHAR
)(count
>>8) & 0xff;
990 } // end UniataAhciSetupFIS_H2D()
994 UniataAhciSendCommand(
995 IN PVOID HwDeviceExtension
,
997 IN ULONG DeviceNumber
,
1002 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1003 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1004 //ULONG Channel = deviceExtension->Channel + lChannel;
1009 //SATA_SSTATUS_REG SStatus;
1010 //SATA_SERROR_REG SError;
1011 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1016 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1018 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1020 AHCI_CL
->prd_length
= 0;
1021 AHCI_CL
->cmd_flags
= (20 / sizeof(ULONG
)) | flags
| (DeviceNumber
<< 12);
1022 AHCI_CL
->bytecount
= 0;
1023 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1024 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1025 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1028 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, ATA_AHCI_P_CMD_ST
);
1030 for (i
=0; i
<timeout
; i
++) {
1031 AtapiStallExecution(1000);
1032 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1033 if (!(CI
& ATA_AHCI_P_CMD_ST
)) {
1037 KdPrint((" CI %#x\n", CI
));
1039 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1040 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1042 /* clear interrupt(s) */
1043 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1044 KdPrint((" IS %#x\n", IS
.Reg
));
1045 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1047 if (timeout
&& (i
>= timeout
)) {
1048 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1049 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1053 return IDE_STATUS_IDLE
;
1055 } // end UniataAhciSendCommand()
1059 UniataAhciSoftReset(
1060 IN PVOID HwDeviceExtension
,
1062 IN ULONG DeviceNumber
1065 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1066 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1067 //ULONG Channel = deviceExtension->Channel + lChannel;
1073 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1075 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1076 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1079 UniataDumpAhciPortRegs(chan
);
1082 /* kick controller into sane state */
1083 UniataAhciStop(chan
);
1084 UniataAhciCLO(chan
);
1085 UniataAhciStart(chan
);
1088 UniataDumpAhciPortRegs(chan
);
1091 /* pull reset active */
1092 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1093 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1094 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1095 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1096 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1098 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == 0xff) {
1099 KdPrint2((" timeout\n"));
1102 AtapiStallExecution(50);
1104 /* pull reset inactive */
1105 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1106 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1107 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1108 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1109 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1110 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == 0xff) {
1111 KdPrint2((" timeout (2)\n"));
1115 UniataAhciWaitReady(chan
, 1);
1117 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1119 return UniataAhciUlongFromRFIS(RCV_FIS
);
1121 } // end UniataAhciSoftReset()
1125 UniataAhciWaitReady(
1126 IN PHW_CHANNEL chan
,
1133 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1135 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1137 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1138 for(i
=0; i
<timeout
&& (TFD
&
1139 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1140 AtapiStallExecution(1000);
1141 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1144 KdPrint2((" TFD %#x\n", TFD
));
1148 } // end UniataAhciWaitReady()
1152 UniataAhciHardReset(
1153 IN PVOID HwDeviceExtension
,
1155 OUT PULONG signature
1158 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1159 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1160 //ULONG Channel = deviceExtension->Channel + lChannel;
1164 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1166 (*signature
) = 0xffffffff;
1168 UniataAhciStop(chan
);
1169 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == 0xff) {
1170 KdPrint((" no PHY\n"));
1174 /* Wait for clearing busy status. */
1175 TFD
= UniataAhciWaitReady(chan
, 15000);
1176 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1177 KdPrint((" busy: TFD %#x\n", TFD
));
1180 KdPrint((" TFD %#x\n", TFD
));
1183 UniataDumpAhciPortRegs(chan
);
1186 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1187 KdPrint((" sig: %#x\n", *signature
));
1189 UniataAhciStart(chan
);
1193 } // end UniataAhciHardReset()
1198 IN PVOID HwDeviceExtension
,
1202 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1203 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1204 //ULONG Channel = deviceExtension->Channel + lChannel;
1205 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1210 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1212 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1214 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1216 /* Disable port interrupts */
1217 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1219 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1221 KdPrint((" No devices in all LUNs\n"));
1222 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1223 // Zero device fields to ensure that if earlier devices were found,
1224 // but not claimed, the fields are cleared.
1225 UniataForgetDevice(chan
->lun
[i
]);
1228 /* enable wanted port interrupts */
1229 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1230 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1234 /* enable wanted port interrupts */
1235 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1236 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1237 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1238 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1239 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1240 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1243 * Only probe for PortMultiplier if HW has support.
1244 * Ignore Marvell, which is not working,
1246 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1247 if ((CAP
& AHCI_CAP_SPM
) &&
1248 (VendorID
!= ATA_MARVELL_ID
)) {
1249 KdPrint((" check PM\n"));
1250 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1251 /* Workaround for some ATI chips, failing to soft-reset
1252 * when port multiplicator supported, but absent.
1253 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1254 if (signature
== 0xffffffff) {
1255 KdPrint((" re-check PM\n"));
1256 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1259 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1262 KdPrint((" signature %#x\n", signature
));
1263 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1264 switch (signature
>> 16) {
1266 KdPrint((" ATA dev\n"));
1267 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1272 if(deviceExtension
->NumberLuns
> 1) {
1273 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1274 UniataSataIdentifyPM(chan
);
1276 KdPrint((" no PM supported (1 lun/chan)\n"));
1280 KdPrint((" ATAPI dev\n"));
1281 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1284 default: /* SOS XXX */
1285 KdPrint((" default to ATA ???\n"));
1286 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1292 } // end UniataAhciReset()
1302 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1304 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1305 KdPrint2((" CMD %#x\n", CMD
));
1306 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1309 } // end UniataAhciStartFR()
1320 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
1322 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1323 KdPrint2((" CMD %#x\n", CMD
));
1324 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
1326 for(i
=0; i
<1000; i
++) {
1327 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1328 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
1329 KdPrint2((" final CMD %#x\n", CMD
));
1332 AtapiStallExecution(1000);
1334 KdPrint2((" CMD %#x\n", CMD
));
1335 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
1336 KdPrint2(("UniataAhciStopFR: timeout\n"));
1338 } // end UniataAhciStopFR()
1347 SATA_SERROR_REG SError
;
1349 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
1351 /* clear SATA error register */
1352 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1354 /* clear any interrupts pending on this channel */
1355 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1356 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
1358 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
1360 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1361 KdPrint2((" CMD %#x\n", CMD
));
1362 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
1365 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
1368 } // end UniataAhciStart()
1376 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1377 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1379 //SATA_SERROR_REG SError;
1382 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
1384 /* issue Command List Override if supported */
1385 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1386 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
1387 if(!(CAP
& AHCI_CAP_SCLO
)) {
1390 KdPrint2((" send CLO\n"));
1391 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1392 CMD
|= ATA_AHCI_P_CMD_CLO
;
1393 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
1395 for(i
=0; i
<1000; i
++) {
1396 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1397 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
1398 KdPrint2((" final CMD %#x\n", CMD
));
1401 AtapiStallExecution(1000);
1403 KdPrint2((" CMD %#x\n", CMD
));
1404 KdPrint2(("UniataAhciCLO: timeout\n"));
1406 } // end UniataAhciCLO()
1415 //SATA_SERROR_REG SError;
1418 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
1420 /* issue Command List Override if supported */
1421 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1422 CMD
&= ~ATA_AHCI_P_CMD_ST
;
1423 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
1425 for(i
=0; i
<1000; i
++) {
1426 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1427 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
1428 KdPrint2((" final CMD %#x\n", CMD
));
1431 AtapiStallExecution(1000);
1433 KdPrint2((" CMD %#x\n", CMD
));
1434 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
1435 KdPrint2(("UniataAhciStop: timeout\n"));
1437 } // end UniataAhciStop()
1441 UniataAhciBeginTransaction(
1442 IN PVOID HwDeviceExtension
,
1444 IN ULONG DeviceNumber
,
1445 IN PSCSI_REQUEST_BLOCK Srb
1448 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1449 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1450 //ULONG Channel = deviceExtension->Channel + lChannel;
1454 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1455 //SATA_SSTATUS_REG SStatus;
1456 //SATA_SERROR_REG SError;
1457 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1462 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1464 KdPrint2(("UniataAhciBeginTransaction: lChan %d\n", chan
->lChannel
));
1466 if(AtaReq
->dma_entries
> (USHORT
)0xffff) {
1467 KdPrint2(("UniataAhciBeginTransaction too long DMA tab\n"));
1471 AHCI_CL
->prd_length
= (USHORT
)AtaReq
->dma_entries
;
1472 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
1473 AHCI_CL
->bytecount
= 0;
1474 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
1475 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1476 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1479 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1480 KdPrint2((" CMD %#x\n", CMD
));
1481 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
1482 KdPrint2((" send CMD %#x\n", CMD
));
1483 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
1485 /* issue command to controller */
1486 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, ATA_AHCI_P_CMD_ST
);
1488 if(!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
1489 // TODO: check if we send ATA_RESET and wait for ready of so.
1490 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
1494 for(i
=0; i
<1000000; i
++) {
1495 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1496 if(!(TFD
& IDE_STATUS_BUSY
)) {
1500 if(TFD
& IDE_STATUS_BUSY
) {
1501 KdPrint2((" timeout\n"));
1503 if(TFD
& IDE_STATUS_ERROR
) {
1504 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
1506 AtaReq
->ahci
.in_status
= TFD
;
1512 return IDE_STATUS_IDLE
;
1514 } // end UniataAhciBeginTransaction()
1518 UniataAhciEndTransaction(
1519 IN PVOID HwDeviceExtension
,
1521 IN ULONG DeviceNumber
,
1522 IN PSCSI_REQUEST_BLOCK Srb
1525 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1526 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1527 //ULONG Channel = deviceExtension->Channel + lChannel;
1529 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1531 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1533 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
1535 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1536 KdPrint2((" TFD %#x\n", TFD
));
1538 if(TFD
& IDE_STATUS_ERROR
) {
1539 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
1541 AtaReq
->ahci
.in_status
= TFD
;
1543 //if (request->flags & ATA_R_CONTROL) {
1545 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
1546 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
1547 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
1548 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
1549 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
1550 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
1551 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
1553 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
1554 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
1555 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
1562 } // end UniataAhciEndTransaction()
1572 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
1575 UniataDumpAhciPortRegs(chan
);
1578 /* Disable port interrupts */
1579 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1581 /* setup work areas */
1582 base
= chan
->AHCI_CTL_PhAddr
;
1584 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
1587 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
1588 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
1589 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
1591 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
1592 (ULONG
)(base
& 0xffffffff));
1593 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
1594 (ULONG
)((base
>> 32) & 0xffffffff));
1596 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
1597 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
1598 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
1599 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
1601 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
1602 (ULONG
)(base
& 0xffffffff));
1603 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
1604 (ULONG
)((base
>> 32) & 0xffffffff));
1606 /* activate the channel and power/spin up device */
1607 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
1608 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
1609 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
1610 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
1614 UniataDumpAhciPortRegs(chan
);
1617 UniataAhciStartFR(chan
);
1618 UniataAhciStart(chan
);
1621 UniataDumpAhciPortRegs(chan
);
1625 } // end UniataAhciResume()
1635 SATA_SCONTROL_REG SControl
;
1637 KdPrint2(("UniataAhciSuspend:\n"));
1639 /* Disable port interrupts */
1640 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1642 /* Reset command register. */
1643 UniataAhciStop(chan
);
1644 UniataAhciStopFR(chan
);
1645 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
1647 /* Allow everything including partial and slumber modes. */
1648 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
1650 /* Request slumber mode transition and give some time to get there. */
1651 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
1652 AtapiStallExecution(100);
1656 SControl
.DET
= SStatus_DET_Offline
;
1657 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
1660 } // end UniataAhciSuspend()
1666 IN PHW_CHANNEL chan
,
1667 IN ULONG DeviceNumber
,
1672 //ULONG Channel = deviceExtension->Channel + lChannel;
1677 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1678 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1680 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
1682 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
1683 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
1686 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
1688 case IDX_SATA_SStatus
:
1690 case IDX_SATA_SError
:
1692 case IDX_SATA_SControl
:
1699 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1700 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1701 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
1702 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
1703 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
1704 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
1705 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
1707 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == 0xff) {
1708 KdPrint2((" PM read failed\n"));
1712 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1714 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
1717 } // end UniataAhciReadPM()
1722 IN PHW_CHANNEL chan
,
1723 IN ULONG DeviceNumber
,
1728 //ULONG Channel = deviceExtension->Channel + lChannel;
1734 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1735 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
1737 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
1739 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
1740 UniataSataWritePort4(chan
, Reg
, value
, 0);
1743 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
1745 case IDX_SATA_SStatus
:
1747 case IDX_SATA_SError
:
1749 case IDX_SATA_SControl
:
1756 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1757 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1758 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
1759 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
1760 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
1761 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
1763 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
1764 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
1765 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
1766 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
1768 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
1770 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == 0xff) {
1771 KdPrint2((" PM write failed\n"));
1775 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1777 if(TFD
& IDE_STATUS_ERROR
) {
1778 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
1780 return (UCHAR
)(TFD
>> 8);
1782 } // end UniataAhciWritePM()
1785 UniataAhciSetupCmdPtr(
1786 IN OUT PATA_REQ AtaReq
1791 ULONGLONG prd_base64
;
1795 ULONGLONG prd_base64_0
;
1799 prd_base64_0
= prd_base64
= 0;
1800 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
1801 prd_base0
= prd_base
;
1803 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
1805 d
= (ULONG
)(prd_base64
- prd_base64_0
);
1806 KdPrint2((PRINT_PREFIX
" aligned %I64x, d=%x\n", prd_base64
, d
));
1808 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
1809 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
1810 } // end UniataAhciSetupCmdPtr()