3 Copyright (c) 2008-2016 Alexandr A. Telyatnikov (Alter)
9 This module handles SATA- and AHCI-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.
45 IN PVOID HwDeviceExtension
,
46 IN ULONG lChannel
, // logical channel
47 IN ULONG pm_port
/* for port multipliers */
50 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
51 //ULONG Channel = deviceExtension->Channel + lChannel;
52 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
53 SATA_SSTATUS_REG SStatus
;
61 KdPrint2((PRINT_PREFIX
"UniataSataConnect:\n"));
63 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
64 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
65 return IDE_STATUS_IDLE
;
68 /* clear SATA error register, some controllers need this */
69 UniataSataWritePort4(chan
, IDX_SATA_SError
,
70 UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
), pm_port
);
71 /* wait up to 1 second for "connect well" */
72 for(i
=0; i
<100; i
++) {
73 SStatus
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SStatus
, pm_port
);
74 if(SStatus
.SPD
== SStatus_SPD_Gen1
||
75 SStatus
.SPD
== SStatus_SPD_Gen2
||
76 SStatus
.SPD
== SStatus_SPD_Gen3
) {
77 // SATA sets actual transfer rate in LunExt on init.
78 // There is no run-time SATA rate adjustment yet.
79 // On the other hand, we may turn SATA device in PIO mode
80 // TODO: make separate states for interface speed and transfer mode (DMA vs PIO)
81 chan
->lun
[0]->LimitedTransferMode
=
82 chan
->lun
[0]->PhyTransferMode
=
83 chan
->lun
[0]->TransferMode
= ATA_SA150
+ (UCHAR
)(SStatus
.SPD
- 1);
85 KdPrint2((PRINT_PREFIX
"SATA TransferMode %#x\n", chan
->lun
[0]->TransferMode
));
86 if(chan
->MaxTransferMode
< chan
->lun
[0]->TransferMode
) {
87 KdPrint2((PRINT_PREFIX
"SATA upd chan TransferMode\n"));
88 chan
->MaxTransferMode
= chan
->lun
[0]->TransferMode
;
90 if(deviceExtension
->MaxTransferMode
< chan
->lun
[0]->TransferMode
) {
91 KdPrint2((PRINT_PREFIX
"SATA upd controller TransferMode\n"));
92 deviceExtension
->MaxTransferMode
= chan
->lun
[0]->TransferMode
;
97 AtapiStallExecution(10000);
100 KdPrint2((PRINT_PREFIX
"UniataSataConnect: SStatus %8.8x\n", SStatus
.Reg
));
101 return IDE_STATUS_WRONG
;
103 /* clear SATA error register */
104 UniataSataWritePort4(chan
, IDX_SATA_SError
,
105 UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
), pm_port
);
107 Status
= WaitOnBaseBusyLong(chan
);
108 if(Status
& IDE_STATUS_BUSY
) {
112 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow);
113 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh);
115 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
118 KdPrint2((PRINT_PREFIX
"UniataSataConnect: OK, ATA status %#x\n", Status
));
119 return IDE_STATUS_IDLE
;
120 } // end UniataSataConnect()
125 IN PVOID HwDeviceExtension
,
126 IN ULONG lChannel
, // logical channel
127 IN ULONG pm_port
, /* for port multipliers */
131 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
132 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
133 SATA_SCONTROL_REG SControl
;
136 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable:\n"));
138 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
139 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
140 return IDE_STATUS_IDLE
;
143 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
144 KdPrint2((PRINT_PREFIX
"SControl %#x\n", SControl
.Reg
));
145 if(SControl
.DET
== SControl_DET_Idle
) {
147 return UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
151 for (retry
= 0; retry
< 10; retry
++) {
152 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry init %d\n", retry
));
153 for (loop
= 0; loop
< 10; loop
++) {
155 SControl
.DET
= SControl_DET_Init
;
156 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, pm_port
);
157 AtapiStallExecution(100);
158 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
159 KdPrint2((PRINT_PREFIX
" SControl %8.8x\n", SControl
.Reg
));
160 if(SControl
.DET
== SControl_DET_Init
) {
164 AtapiStallExecution(5000);
165 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry idle %d\n", retry
));
166 for (loop
= 0; loop
< 10; loop
++) {
168 SControl
.DET
= SControl_DET_DoNothing
;
169 SControl
.IPM
= SControl_IPM_NoPartialSlumber
;
170 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, pm_port
);
171 AtapiStallExecution(100);
172 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
173 KdPrint2((PRINT_PREFIX
" SControl %8.8x\n", SControl
.Reg
));
174 if(SControl
.DET
== SControl_DET_Idle
) {
175 return UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
180 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: failed\n"));
181 return IDE_STATUS_WRONG
;
182 } // end UniataSataPhyEnable()
187 IN PVOID HwDeviceExtension
,
188 IN ULONG lChannel
, // logical channel
189 IN BOOLEAN do_connect
,
190 IN ULONG pm_port
/* for port multipliers */
193 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
194 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
195 //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
196 SATA_SSTATUS_REG SStatus
;
197 SATA_SERROR_REG SError
;
199 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
200 //if(ChipFlags & UNIATA_SATA) {
202 SStatus
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SStatus
, pm_port
);
203 SError
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
);
206 KdPrint2((PRINT_PREFIX
" SStatus %#x\n", SStatus
.Reg
));
209 KdPrint2((PRINT_PREFIX
" SError %#x\n", SError
.Reg
));
210 /* clear error bits/interrupt */
211 UniataSataWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
, pm_port
);
214 /* if we have a connection event deal with it */
216 KdPrint2((PRINT_PREFIX
" catch SATA connect/disconnect\n"));
217 if(SStatus
.SPD
>= SStatus_SPD_Gen1
) {
218 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, pm_port
);
220 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, pm_port
);
229 } // end UniataSataClearErr()
234 IN PVOID HwDeviceExtension
,
235 IN ULONG lChannel
, // logical channel
237 IN ULONG pm_port
/* for port multipliers */
240 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
242 ULONG DeviceNumber
= (pm_port
? 1 : 0);
244 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
249 case UNIATA_SATA_EVENT_ATTACH
:
250 KdPrint2((PRINT_PREFIX
" CONNECTED\n"));
251 Status
= UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
252 KdPrint2((PRINT_PREFIX
" Status %#x\n", Status
));
253 if(Status
!= IDE_STATUS_IDLE
) {
256 CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
/*dev*/, FALSE
);
259 case UNIATA_SATA_EVENT_DETACH
:
260 KdPrint2((PRINT_PREFIX
" DISCONNECTED\n"));
261 UniataForgetDevice(deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
]);
266 } // end UniataSataEvent()
272 IN ULONG io_port_ndx
,
273 IN ULONG pm_port
/* for port multipliers */
276 if(chan
&& (io_port_ndx
< IDX_MAX_REG
) &&
277 chan
->RegTranslation
[io_port_ndx
].Proc
) {
279 KdPrint3((PRINT_PREFIX
" UniataSataReadPort4 %#x[%d]\n", io_port_ndx
, pm_port
));
281 PHW_DEVICE_EXTENSION deviceExtension
= chan
->DeviceExtension
;
282 PVOID HwDeviceExtension
= (PVOID
)deviceExtension
;
283 ULONG slotNumber
= deviceExtension
->slotNumber
;
284 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
285 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
292 if(deviceExtension
->HwFlags
& ICH5
) {
293 offs
= 0x50+chan
->lun
[p
]->SATA_lun_map
*0x10;
294 KdPrint3((PRINT_PREFIX
" ICH5 way, offs %#x\n", offs
));
295 switch(io_port_ndx
) {
296 case IDX_SATA_SStatus
:
299 case IDX_SATA_SError
:
302 case IDX_SATA_SControl
:
308 SetPciConfig4(0xa0, offs
);
309 GetPciConfig4(0xa4, offs
);
312 if(deviceExtension
->HwFlags
& ICH7
) {
313 offs
= 0x100+chan
->lun
[p
]->SATA_lun_map
*0x80;
314 KdPrint3((PRINT_PREFIX
" ICH7 way, offs %#x\n", offs
));
315 switch(io_port_ndx
) {
316 case IDX_SATA_SStatus
:
317 offs
+= IDX_AHCI_P_SStatus
;
319 case IDX_SATA_SError
:
320 offs
+= IDX_AHCI_P_SError
;
322 case IDX_SATA_SControl
:
323 offs
+= IDX_AHCI_P_SControl
;
328 return AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), offs
);
330 offs
= ((deviceExtension
->Channel
+chan
->lChannel
)*2+p
) * 0x100;
331 KdPrint3((PRINT_PREFIX
" def way, offs %#x\n", offs
));
332 switch(io_port_ndx
) {
333 case IDX_SATA_SStatus
:
336 case IDX_SATA_SControl
:
339 case IDX_SATA_SError
:
345 AtapiWritePort4(chan
, IDX_INDEXED_ADDR
, offs
);
346 return AtapiReadPort4(chan
, IDX_INDEXED_DATA
);
349 } // end switch(VendorID)
352 return AtapiReadPort4(chan
, io_port_ndx
);
353 } // end UniataSataReadPort4()
357 UniataSataWritePort4(
359 IN ULONG io_port_ndx
,
361 IN ULONG pm_port
/* for port multipliers */
364 if(chan
&& (io_port_ndx
< IDX_MAX_REG
) &&
365 chan
->RegTranslation
[io_port_ndx
].Proc
) {
367 KdPrint3((PRINT_PREFIX
" UniataSataWritePort4 %#x[%d]\n", io_port_ndx
, pm_port
));
369 PHW_DEVICE_EXTENSION deviceExtension
= chan
->DeviceExtension
;
370 PVOID HwDeviceExtension
= (PVOID
)deviceExtension
;
371 ULONG slotNumber
= deviceExtension
->slotNumber
;
372 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
373 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
380 if(deviceExtension
->HwFlags
& ICH5
) {
381 offs
= 0x50+chan
->lun
[p
]->SATA_lun_map
*0x10;
382 KdPrint3((PRINT_PREFIX
" ICH5 way, offs %#x\n", offs
));
383 switch(io_port_ndx
) {
384 case IDX_SATA_SStatus
:
387 case IDX_SATA_SError
:
390 case IDX_SATA_SControl
:
396 SetPciConfig4(0xa0, offs
);
397 SetPciConfig4(0xa4, data
);
400 if(deviceExtension
->HwFlags
& ICH7
) {
401 offs
= 0x100+chan
->lun
[p
]->SATA_lun_map
*0x80;
402 KdPrint3((PRINT_PREFIX
" ICH7 way, offs %#x\n", offs
));
403 switch(io_port_ndx
) {
404 case IDX_SATA_SStatus
:
405 offs
+= IDX_AHCI_P_SStatus
;
407 case IDX_SATA_SError
:
408 offs
+= IDX_AHCI_P_SError
;
410 case IDX_SATA_SControl
:
411 offs
+= IDX_AHCI_P_SControl
;
416 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), offs
, data
);
419 offs
= ((deviceExtension
->Channel
+chan
->lChannel
)*2+p
) * 0x100;
420 KdPrint3((PRINT_PREFIX
" def way, offs %#x\n", offs
));
421 switch(io_port_ndx
) {
422 case IDX_SATA_SStatus
:
425 case IDX_SATA_SControl
:
428 case IDX_SATA_SError
:
434 AtapiWritePort4(chan
, IDX_INDEXED_ADDR
, offs
);
435 AtapiWritePort4(chan
, IDX_INDEXED_DATA
, data
);
438 } // end switch(VendorID)
441 AtapiWritePort4(chan
, io_port_ndx
, data
);
442 } // end UniataSataWritePort4()
448 IN ULONG DeviceNumber
,
453 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
454 return UniataAhciReadPM(chan
, DeviceNumber
, Reg
, result
);
457 } // end UniataSataReadPM()
463 IN ULONG DeviceNumber
,
468 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
469 return UniataAhciWritePM(chan
, DeviceNumber
, Reg
, value
);
471 return IDE_STATUS_WRONG
;
472 } // end UniataSataWritePM()
477 IN PVOID HwDeviceExtension
,
479 IN ULONG DeviceNumber
482 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
484 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
485 return UniataAhciSoftReset(HwDeviceExtension
, lChannel
, DeviceNumber
);
488 } // end UniataSataSoftReset()
491 UniataSataIdentifyPM(
500 PHW_LU_EXTENSION LunExt
;
502 KdPrint((PRINT_PREFIX
"UniataSataIdentifyPM:\n"));
506 /* get PM vendor & product data */
507 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 0, &PM_DeviceId
)) {
508 KdPrint2((PRINT_PREFIX
" error getting PM vendor data\n"));
511 /* get PM revision data */
512 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 1, &PM_RevId
)) {
513 KdPrint2((PRINT_PREFIX
" error getting PM revison data\n"));
516 /* get number of HW ports on the PM */
517 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 2, &PM_Ports
)) {
518 KdPrint2((PRINT_PREFIX
" error getting PM port info\n"));
522 PM_Ports
&= 0x0000000f;
524 switch(PM_DeviceId
) {
526 /* This PM declares 6 ports, while only 5 of them are real.
527 * Port 5 is enclosure management bridge port, which has implementation
528 * problems, causing probe faults. Hide it for now. */
529 KdPrint2((PRINT_PREFIX
" SiI 3726 (rev=%#x) Port Multiplier with %d (5) ports\n",
530 PM_RevId
, PM_Ports
));
534 /* This PM declares 7 ports, while only 5 of them are real.
535 * Port 5 is some fake "Config Disk" with 640 sectors size,
536 * port 6 is enclosure management bridge port.
537 * Both fake ports has implementation problems, causing
538 * probe faults. Hide them for now. */
539 KdPrint2((PRINT_PREFIX
" SiI 4726 (rev=%#x) Port Multiplier with %d (5) ports\n",
540 PM_RevId
, PM_Ports
));
544 KdPrint2((PRINT_PREFIX
" Port Multiplier (id=%08x rev=%#x) with %d ports\n",
545 PM_DeviceId
, PM_RevId
, PM_Ports
));
550 for(i
=0; i
<PM_Ports
; i
++) {
552 LunExt
= chan
->lun
[i
];
554 KdPrint2((PRINT_PREFIX
" Port %d\n", i
));
555 if(UniataSataPhyEnable(chan
->DeviceExtension
, chan
->lChannel
, i
, UNIATA_SATA_RESET_ENABLE
) != IDE_STATUS_IDLE
) {
556 LunExt
->DeviceFlags
&= ~DFLAGS_DEVICE_PRESENT
;
560 * XXX: I have no idea how to properly wait for PMP port hardreset
561 * completion. Without this delay soft reset does not completes
564 AtapiStallExecution(1000000);
566 signature
= UniataSataSoftReset(chan
->DeviceExtension
, chan
->lChannel
, i
);
567 KdPrint2((PRINT_PREFIX
" signature %#x\n", signature
));
569 LunExt
->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
570 chan
->PmLunMap
|= (1 << i
);
571 /* figure out whats there */
572 switch (signature
>> 16) {
574 LunExt
->DeviceFlags
&= ~DFLAGS_ATAPI_DEVICE
;
577 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_DEVICE
;
583 } // end UniataSataIdentifyPM()
589 IN PHW_DEVICE_EXTENSION deviceExtension
595 KdPrint2((PRINT_PREFIX
596 " AHCI Base: %#x MemIo %d Proc %d\n",
597 deviceExtension
->BaseIoAHCI_0
.Addr
,
598 deviceExtension
->BaseIoAHCI_0
.MemIo
,
599 deviceExtension
->BaseIoAHCI_0
.Proc
));
601 for(j
=0; j
<=IDX_AHCI_VS
; j
+=sizeof(ULONG
)) {
602 xReg
= AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)&deviceExtension
->BaseIoAHCI_0
, j
);
603 KdPrint2((PRINT_PREFIX
604 " AHCI_%#x (%#x) = %#x\n",
606 (deviceExtension
->BaseIoAHCI_0
.Addr
+j
),
610 } // end UniataDumpAhciRegs()
615 UniataDumpAhciPortRegs(
622 KdPrint2((PRINT_PREFIX
623 " AHCI port %d Base: %#x MemIo %d Proc %d\n",
625 chan
->BaseIoAHCI_Port
.Addr
,
626 chan
->BaseIoAHCI_Port
.MemIo
,
627 chan
->BaseIoAHCI_Port
.Proc
));
629 for(j
=0; j
<=IDX_AHCI_P_SNTF
; j
+=sizeof(ULONG
)) {
630 xReg
= AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)&chan
->BaseIoAHCI_Port
, j
);
631 KdPrint2((PRINT_PREFIX
632 " AHCI%d_%#x (%#x) = %#x\n",
635 (chan
->BaseIoAHCI_Port
.Addr
+j
),
639 } // end UniataDumpAhciPortRegs()
646 IN PVOID HwDeviceExtension
649 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
653 ULONG BaseMemAddress
;
659 BOOLEAN MemIo
= FALSE
;
661 KdPrint2((PRINT_PREFIX
" UniataAhciInit:\n"));
664 UniataDumpAhciRegs(deviceExtension
);
667 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
668 if(CAP2
& AHCI_CAP2_BOH
) {
669 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
670 KdPrint2((PRINT_PREFIX
" stage 1 BOHC %#x\n", BOHC
));
671 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
672 BOHC
| AHCI_BOHC_OOS
);
673 for(i
=0; i
<50; i
++) {
674 AtapiStallExecution(500);
675 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
676 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
677 if(BOHC
& AHCI_BOHC_BB
) {
680 if(!(BOHC
& AHCI_BOHC_BOS
)) {
684 KdPrint2((PRINT_PREFIX
" stage 2 BOHC %#x\n", BOHC
));
685 if(BOHC
& AHCI_BOHC_BB
) {
686 for(i
=0; i
<2000; i
++) {
687 AtapiStallExecution(1000);
688 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
689 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
690 if(!(BOHC
& AHCI_BOHC_BOS
)) {
695 KdPrint2((PRINT_PREFIX
" final BOHC %#x\n", BOHC
));
698 /* disable AHCI interrupts, for MSI compatibility issue
699 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
700 26. AHCI Reset and MSI Request
703 KdPrint2((PRINT_PREFIX
" get GHC\n"));
704 /* enable AHCI mode */
705 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
706 if(!(GHC
& AHCI_GHC_AE
)) {
707 KdPrint2((PRINT_PREFIX
" enable AHCI mode, disable intr, GHC %#x\n", GHC
));
708 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
709 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
711 KdPrint2((PRINT_PREFIX
" disable intr, GHC %#x\n", GHC
));
712 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
715 AtapiStallExecution(100);
717 /* read GHC again and reset AHCI controller */
718 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
719 KdPrint2((PRINT_PREFIX
" reset AHCI controller, GHC %#x\n", GHC
));
720 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
723 for(i
=0; i
<1000; i
++) {
724 AtapiStallExecution(1000);
725 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
726 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
727 if(!(GHC
& AHCI_GHC_HR
)) {
731 if(GHC
& AHCI_GHC_HR
) {
732 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
736 /* re-enable AHCI mode */
737 /* Linux: Some controllers need AHCI_EN to be written multiple times.
738 * Try a few times before giving up.
740 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
742 if(!(GHC
& AHCI_GHC_AE
)) {
743 KdPrint2((PRINT_PREFIX
" re-enable AHCI mode, GHC %#x\n", GHC
));
744 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
746 AtapiStallExecution(1000);
747 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
752 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
753 if(!(GHC
& AHCI_GHC_AE
)) {
754 KdPrint2((PRINT_PREFIX
" Can't enable AHCI mode\n"));
758 deviceExtension
->AHCI_CAP
=
759 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
760 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
761 if(CAP
& AHCI_CAP_S64A
) {
762 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
763 deviceExtension
->Host64
= TRUE
;
765 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
766 if(CAP
& AHCI_CAP_PMD
) {
767 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
769 if(CAP
& AHCI_CAP_SAM
) {
770 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
773 /* get the number of HW channels */
774 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
775 deviceExtension
->AHCI_PI
= PI
;
776 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
777 KdPrint2((PRINT_PREFIX
" AHCI PI mask %#x\n", deviceExtension
->AHCI_PI_mask
));
778 deviceExtension
->AHCI_PI
= PI
= PI
& deviceExtension
->AHCI_PI_mask
;
779 KdPrint2((PRINT_PREFIX
" masked AHCI PI %#x\n", PI
));
781 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
782 if(CAP2
& AHCI_CAP2_BOH
) {
783 KdPrint2((PRINT_PREFIX
" retry BOHC\n"));
784 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
785 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
786 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
787 BOHC
| AHCI_BOHC_OOS
);
789 /* clear interrupts */
790 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
791 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
793 /* enable AHCI interrupts */
794 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
795 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
797 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
798 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
800 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
801 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
803 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
804 chan
= &deviceExtension
->chan
[c
];
805 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
807 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
809 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
811 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
813 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
814 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
816 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
817 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
818 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
819 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
820 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
821 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
822 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
823 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
824 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
825 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
826 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
828 UniataInitSyncBaseIO(chan
);
830 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
831 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
832 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
833 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
834 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
835 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
836 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
837 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
839 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
841 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
842 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
846 UniataAhciResume(chan
);
848 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
852 } // end UniataAhciInit()
856 UniAtaAhciValidateVersion(
857 IN PHW_DEVICE_EXTENSION deviceExtension
,
865 KdPrint((" wrong AHCI revision %#x\n", version
));
874 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
875 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
876 KdPrint((" AHCI revision excluded\n"));
881 } // end UniAtaAhciValidateVersion()
886 IN PVOID HwDeviceExtension
,
887 IN PPCI_COMMON_CONFIG pciData
, // optional
888 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
891 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
892 //ULONG slotNumber = deviceExtension->slotNumber;
893 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
904 ULONG NumberChannels
;
906 ULONG_PTR BaseMemAddress
;
908 ULONG BaseMemAddress
;
910 BOOLEAN MemIo
= FALSE
;
911 BOOLEAN found
= FALSE
;
913 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
915 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
916 KdPrint((" AHCI excluded\n"));
919 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
921 if(!BaseMemAddress
) {
922 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
925 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
926 KdPrint2((PRINT_PREFIX
"MemIo\n"));
929 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
930 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
933 UniataDumpAhciRegs(deviceExtension
);
936 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
937 if(GHC
& AHCI_GHC_HR
) {
938 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
942 /* check AHCI mode. Save state and try enable */
944 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
945 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
947 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
949 if(!(GHC
& AHCI_GHC_AE
)) {
950 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
951 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
952 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
955 KdPrint2((PRINT_PREFIX
" try enable\n"));
956 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
957 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
958 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
960 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
961 if(!(GHC
& AHCI_GHC_AE
)) {
962 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
967 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
968 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
969 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
970 if(CAP
& AHCI_CAP_S64A
) {
971 KdPrint2((PRINT_PREFIX
" 64bit"));
972 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
975 if(CAP2
& AHCI_CAP2_BOH
) {
976 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
977 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
980 if(CAP
& AHCI_CAP_NCQ
) {
981 KdPrint2((PRINT_PREFIX
" NCQ"));
983 if(CAP
& AHCI_CAP_SNTF
) {
984 KdPrint2((PRINT_PREFIX
" SNTF"));
986 if(CAP
& AHCI_CAP_CCC
) {
987 KdPrint2((PRINT_PREFIX
" CCC"));
989 KdPrint2((PRINT_PREFIX
"\n"));
991 /* get the number of HW channels */
993 /* CAP.NOP sometimes indicate the index of the last enabled
994 * port, at other times, that of the last possible port, so
995 * determining the maximum port number requires looking at
996 * both CAP.NOP and PI.
998 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
999 deviceExtension
->AHCI_PI
= deviceExtension
->AHCI_PI_mask
= PI
;
1000 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
1002 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1) {
1003 if(AtapiRegCheckDevValue(deviceExtension
, n
, DEVNUM_NOT_SPECIFIED
, L
"Exclude", 0)) {
1004 KdPrint2((PRINT_PREFIX
"Channel %d excluded\n", n
));
1005 deviceExtension
->AHCI_PI
&= ~((ULONG
)1 << n
);
1006 deviceExtension
->AHCI_PI_mask
&= ~((ULONG
)1 << n
);
1009 deviceExtension
->AHCI_PI_mask
=
1010 AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PortMask", deviceExtension
->AHCI_PI_mask
);
1011 KdPrint2((PRINT_PREFIX
"Force PortMask %#x\n", deviceExtension
->AHCI_PI_mask
));
1013 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
1015 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
1017 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
1018 KdPrint2((PRINT_PREFIX
" Detected Channels %d / %d\n", NumberChannels
, n
));
1020 switch(deviceExtension
->DevID
) {
1022 KdPrint2((PRINT_PREFIX
" Marvell M88SE6111 -> 1\n"));
1026 KdPrint2((PRINT_PREFIX
" Marvell M88SE6121 -> 2\n"));
1027 NumberChannels
= min(NumberChannels
, 2);
1032 KdPrint2((PRINT_PREFIX
" Marvell M88SE614x/9123 -> 4\n"));
1033 NumberChannels
= min(NumberChannels
, 4);
1037 if(!NumberChannels
) {
1038 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
1042 KdPrint2((PRINT_PREFIX
" Adjusted Channels %d\n", NumberChannels
));
1045 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
1046 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
1048 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
1050 NumberChannels
, PI
));
1051 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
1054 if(CAP
& AHCI_CAP_SPM
) {
1055 KdPrint2((PRINT_PREFIX
" PM supported\n"));
1056 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
1057 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
1058 deviceExtension
->NumberLuns
= 1;
1059 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
1061 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
1062 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
1063 //deviceExtension->NumberLuns = 1;
1066 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
1067 deviceExtension
->NumberLuns
= 1;
1070 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
1074 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
1075 if(deviceExtension
->NumberChannels
< NumberChannels
) {
1076 deviceExtension
->NumberChannels
= NumberChannels
;
1078 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
1079 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
1081 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
1082 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
1087 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
1088 KdPrint((" AHCI detect status %d\n", found
));
1091 } // end UniataAhciDetect()
1096 IN PVOID HwDeviceExtension
,
1098 IN ULONG DeviceNumber
1101 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1102 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1103 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1107 SATA_SSTATUS_REG SStatus
;
1108 SATA_SERROR_REG SError
;
1109 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1112 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1114 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1115 KdPrint((" hIS %#x\n", hIS
));
1116 hIS
&= (1 << Channel
);
1118 return INTERRUPT_REASON_IGNORE
;
1120 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1121 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1122 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1123 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1124 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1126 /* clear interrupt(s) */
1127 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1128 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1129 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1131 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1132 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1134 /* do we have cold connect surprise */
1138 /* check for and handle connect events */
1140 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1143 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1145 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1146 chan
->AhciPrevCI
= CI
;
1147 chan
->AhciLastSError
= SError
.Reg
;
1148 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1149 chan
->AhciLastIS
= IS
.Reg
;
1150 if(CI
& (1 << tag
)) {
1152 UniataDumpAhciPortRegs(chan
);
1154 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1156 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1157 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1158 KdPrint((" AHCI: unexpected, error\n"));
1160 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1164 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1165 KdPrint2((" TFD %#x\n", TFD));
1166 if(TFD & IDE_STATUS_BUSY) {
1167 KdPrint2((" Seems to be interrupt on error\n"));
1168 return INTERRUPT_REASON_OUR;
1171 return INTERRUPT_REASON_UNEXPECTED
;
1174 return INTERRUPT_REASON_OUR
;
1176 } // end UniataAhciStatus()
1180 UniataAhciSnapAtaRegs(
1181 IN PHW_CHANNEL chan
,
1182 IN ULONG DeviceNumber
,
1183 IN OUT PIDEREGS_EX regs
1188 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1189 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1190 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1191 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1193 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1194 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1195 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1196 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1197 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1201 } // end UniataAhciSnapAtaRegs()
1205 UniataAhciSetupFIS_H2D(
1206 IN PHW_DEVICE_EXTENSION deviceExtension
,
1207 IN ULONG DeviceNumber
,
1219 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1221 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1223 plba
= (PUCHAR
)&lba
;
1225 RtlZeroMemory(fis
, 20);
1227 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1228 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1229 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1230 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1231 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1233 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1234 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1235 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1237 command
== IDE_COMMAND_ATAPI_PACKET
) {
1238 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1239 if(feature
& ATA_F_DMA
) {
1240 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1242 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1243 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1245 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1248 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1249 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1250 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1254 need48
= UniAta_need_lba48(command
, lba
, count
,
1255 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1257 /* translate command into 48bit version */
1259 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1260 command
= AtaCommands48
[command
];
1262 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1267 fis
[IDX_AHCI_o_Command
] = command
;
1268 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1270 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1271 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1272 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1274 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1278 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1280 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1281 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1282 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1284 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1286 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1288 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1290 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1291 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1301 } // end UniataAhciSetupFIS_H2D()
1305 UniataAhciSetupFIS_H2D_Direct(
1306 IN PHW_DEVICE_EXTENSION deviceExtension
,
1307 IN ULONG DeviceNumber
,
1316 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1319 command
= regs
->bCommandReg
;
1321 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1323 //plba = (PUCHAR)&lba;
1325 RtlZeroMemory(fis
, 20);
1327 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1328 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1329 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1330 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1331 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1333 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1334 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1335 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1337 command
== IDE_COMMAND_ATAPI_PACKET
) {
1338 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1339 if(feature & ATA_F_DMA) {
1340 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1342 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1343 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1346 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1349 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1350 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1352 /* translate command into 48bit version */
1354 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1355 command
= AtaCommands48
[command
];
1357 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1362 fis
[IDX_AHCI_o_Command
] = command
;
1363 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1365 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1366 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1367 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1369 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1373 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1375 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1376 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1377 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1379 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1381 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1383 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1385 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1386 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1388 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1394 } // end UniataAhciSetupFIS_H2D_Direct()
1398 UniataAhciWaitCommandReady(
1399 IN PHW_CHANNEL chan
,
1412 for (i
=0; i
<timeout
; i
++) {
1413 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1414 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1415 if (!(( CI
>> tag
) & 0x01)) {
1418 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1419 //KdPrint((" IS %#x\n", IS.Reg));
1423 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1425 KdPrint((" AHCI: error %#x\n", SError
));
1429 AtapiStallExecution(200);
1431 KdPrint((" CI %#x\n", CI
));
1433 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1434 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1436 /* clear interrupt(s) */
1437 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1438 KdPrint((" IS %#x\n", IS
.Reg
));
1439 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1441 if (timeout
&& (i
>= timeout
)) {
1445 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1446 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1448 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1449 KdPrint2((" TFD %#x\n", TFD
));
1452 return IDE_STATUS_WRONG
;
1455 return IDE_STATUS_IDLE
;
1456 } // end UniataAhciWaitCommandReady()
1460 UniataAhciSendCommand(
1461 IN PVOID HwDeviceExtension
,
1463 IN ULONG DeviceNumber
,
1464 IN USHORT ahci_flags
,
1468 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1469 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1470 //ULONG Channel = deviceExtension->Channel + lChannel;
1473 //SATA_SSTATUS_REG SStatus;
1474 //SATA_SERROR_REG SError;
1475 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1479 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1481 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1483 AHCI_CL
->prd_length
= 0;
1484 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1485 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1487 AHCI_CL
->bytecount
= 0;
1488 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1489 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1490 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1493 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1494 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1496 return UniataAhciWaitCommandReady(chan
, timeout
);
1498 } // end UniataAhciSendCommand()
1502 UniataAhciSendPIOCommand(
1503 IN PVOID HwDeviceExtension
,
1505 IN ULONG DeviceNumber
,
1506 IN PSCSI_REQUEST_BLOCK Srb
,
1508 IN ULONG length
, /* bytes */
1511 IN USHORT bcount
, /* block count, just ATA register */
1513 IN USHORT ahci_flags
,
1514 IN ULONG wait_flags
,
1518 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1519 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1524 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1525 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1527 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1529 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1530 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1532 if(length
/DEV_BSIZE
!= bcount
) {
1533 KdPrint((" length/DEV_BSIZE != bcount\n"));
1537 //UniataDumpAhciPortRegs(chan);
1541 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1543 KdPrint((" !Srb\n"));
1544 return IDE_STATUS_WRONG
;
1546 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1547 //should be already called on init
1549 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1550 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1552 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1554 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1555 &(AHCI_CMD
->cfis
[0]),
1563 KdPrint2(("!fis_size\n"));
1564 return IDE_STATUS_WRONG
;
1567 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1568 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1569 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1572 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1573 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1574 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1575 KdPrint((" assume OUT\n"));
1577 AtaReq
->Flags
|= REQ_FLAG_READ
;
1578 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1579 KdPrint((" assume IN\n"));
1581 if(!AtapiDmaSetup(HwDeviceExtension
,
1583 lChannel
, // logical channel,
1587 KdPrint2((" can't setup buffer\n"));
1588 return IDE_STATUS_WRONG
;
1592 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1595 //UniataDumpAhciPortRegs(chan);
1598 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1601 //UniataDumpAhciPortRegs(chan);
1604 if(wait_flags
== ATA_IMMEDIATE
) {
1606 KdPrint2((" return imemdiately\n"));
1608 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1609 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1610 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1615 } // end UniataAhciSendPIOCommand()
1619 UniataAhciSendPIOCommandDirect(
1620 IN PVOID HwDeviceExtension
,
1622 IN ULONG DeviceNumber
,
1623 IN PSCSI_REQUEST_BLOCK Srb
,
1624 IN PIDEREGS_EX regs
,
1625 IN ULONG wait_flags
,
1629 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1630 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1635 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1636 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1637 USHORT ahci_flags
=0;
1640 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1642 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1643 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1645 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1646 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1650 //UniataDumpAhciPortRegs(chan);
1654 KdPrint((" !Srb\n"));
1655 return IDE_STATUS_WRONG
;
1656 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1657 //should be already called on init
1659 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1660 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1662 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1664 KdPrint((" !AHCI_CMD\n"));
1665 return IDE_STATUS_WRONG
;
1668 if(Srb
->DataTransferLength
) {
1669 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1670 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1671 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1673 AtaReq
->Flags
|= REQ_FLAG_READ
;
1677 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1678 &(AHCI_CMD
->cfis
[0]),
1682 KdPrint2(("!fis_size\n"));
1683 return IDE_STATUS_WRONG
;
1686 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1687 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1688 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1690 if(Srb
->DataTransferLength
) {
1691 if(!AtapiDmaSetup(HwDeviceExtension
,
1693 lChannel
, // logical channel,
1695 (PUCHAR
)(Srb
->DataBuffer
),
1696 Srb
->DataTransferLength
)) {
1697 KdPrint2((" can't setup buffer\n"));
1698 return IDE_STATUS_WRONG
;
1702 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1705 //UniataDumpAhciPortRegs(chan);
1708 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1711 //UniataDumpAhciPortRegs(chan);
1714 if(wait_flags
== ATA_IMMEDIATE
) {
1716 KdPrint2((" return imemdiately\n"));
1718 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1719 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1720 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1725 } // end UniataAhciSendPIOCommandDirect()
1729 UniataAhciAbortOperation(
1733 /* kick controller into sane state */
1734 if(!UniataAhciStop(chan
)) {
1737 if(!UniataAhciStopFR(chan
)) {
1740 if(!UniataAhciCLO(chan
)) {
1743 UniataAhciStartFR(chan
);
1744 UniataAhciStart(chan
);
1747 } // end UniataAhciAbortOperation()
1751 UniataAhciSoftReset(
1752 IN PVOID HwDeviceExtension
,
1754 IN ULONG DeviceNumber
1757 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1758 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1759 //ULONG Channel = deviceExtension->Channel + lChannel;
1765 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1767 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1768 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1770 /* kick controller into sane state */
1771 if(!UniataAhciAbortOperation(chan
)) {
1772 KdPrint2((" abort failed\n"));
1776 /* pull reset active */
1777 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1778 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1779 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1780 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1781 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1783 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1784 KdPrint2((" timeout\n"));
1787 AtapiStallExecution(50);
1789 /* pull reset inactive */
1790 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1791 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1792 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1793 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1794 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1795 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1796 KdPrint2((" timeout (2)\n"));
1800 UniataAhciWaitReady(chan
, 1);
1802 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1804 return UniataAhciUlongFromRFIS(RCV_FIS
);
1806 } // end UniataAhciSoftReset()
1810 UniataAhciWaitReady(
1811 IN PHW_CHANNEL chan
,
1818 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1820 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1822 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1823 for(i
=0; i
<timeout
&& (TFD
&
1824 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1825 AtapiStallExecution(1000);
1826 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1829 KdPrint2((" TFD %#x\n", TFD
));
1833 } // end UniataAhciWaitReady()
1837 UniataAhciHardReset(
1838 IN PVOID HwDeviceExtension
,
1840 OUT PULONG signature
1843 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1844 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1845 //ULONG Channel = deviceExtension->Channel + lChannel;
1849 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1851 (*signature
) = 0xffffffff;
1853 UniataAhciStop(chan
);
1854 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1855 KdPrint((" no PHY\n"));
1856 return IDE_STATUS_WRONG
;
1859 /* Wait for clearing busy status. */
1860 TFD
= UniataAhciWaitReady(chan
, 15000);
1861 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1862 KdPrint((" busy: TFD %#x\n", TFD
));
1865 KdPrint((" TFD %#x\n", TFD
));
1868 UniataDumpAhciPortRegs(chan
);
1871 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1872 KdPrint((" sig: %#x\n", *signature
));
1874 UniataAhciStart(chan
);
1878 } // end UniataAhciHardReset()
1883 IN PVOID HwDeviceExtension
,
1887 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1888 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1889 //ULONG Channel = deviceExtension->Channel + lChannel;
1890 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1895 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1897 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1899 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1901 /* Disable port interrupts */
1902 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1904 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1906 KdPrint((" No devices in all LUNs\n"));
1907 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1908 // Zero device fields to ensure that if earlier devices were found,
1909 // but not claimed, the fields are cleared.
1910 UniataForgetDevice(chan
->lun
[i
]);
1913 /* enable wanted port interrupts */
1914 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1915 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1919 /* enable wanted port interrupts */
1920 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1921 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1922 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1923 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1924 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1925 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1928 * Only probe for PortMultiplier if HW has support.
1929 * Ignore Marvell, which is not working,
1931 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1932 if ((CAP
& AHCI_CAP_SPM
) &&
1933 (VendorID
!= ATA_MARVELL_ID
)) {
1934 KdPrint((" check PM\n"));
1935 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1936 /* Workaround for some ATI chips, failing to soft-reset
1937 * when port multiplicator supported, but absent.
1938 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1939 if (signature
== 0xffffffff) {
1940 KdPrint((" re-check PM\n"));
1941 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1944 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1947 KdPrint((" signature %#x\n", signature
));
1948 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1949 switch (signature
>> 16) {
1951 KdPrint((" ATA dev\n"));
1952 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1957 if(deviceExtension
->NumberLuns
> 1) {
1958 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1959 UniataSataIdentifyPM(chan
);
1961 KdPrint((" no PM supported (1 lun/chan)\n"));
1965 KdPrint((" ATAPI dev\n"));
1966 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1969 default: /* SOS XXX */
1970 KdPrint((" default to ATA ???\n"));
1971 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1977 } // end UniataAhciReset()
1987 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1989 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1990 KdPrint2((" CMD %#x\n", CMD
));
1991 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1992 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
1995 } // end UniataAhciStartFR()
2006 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
2008 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2009 KdPrint2((" CMD %#x\n", CMD
));
2010 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
2012 for(i
=0; i
<1000; i
++) {
2013 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2014 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
2015 KdPrint2((" final CMD %#x\n", CMD
));
2018 AtapiStallExecution(1000);
2020 KdPrint2((" CMD %#x\n", CMD
));
2021 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2022 KdPrint2(("UniataAhciStopFR: timeout\n"));
2024 } // end UniataAhciStopFR()
2033 SATA_SERROR_REG SError
;
2035 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
2037 /* clear SATA error register */
2038 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
2040 /* clear any interrupts pending on this channel */
2041 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
2042 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
2044 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
2046 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2047 KdPrint2((" CMD %#x\n", CMD
));
2048 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2051 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
2052 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2055 } // end UniataAhciStart()
2063 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2064 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2066 //SATA_SERROR_REG SError;
2069 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
2071 /* issue Command List Override if supported */
2072 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
2073 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
2074 if(!(CAP
& AHCI_CAP_SCLO
)) {
2077 KdPrint2((" send CLO\n"));
2078 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2079 CMD
|= ATA_AHCI_P_CMD_CLO
;
2080 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2082 for(i
=0; i
<1000; i
++) {
2083 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2084 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
2085 KdPrint2((" final CMD %#x\n", CMD
));
2088 AtapiStallExecution(1000);
2090 KdPrint2((" CMD %#x\n", CMD
));
2091 KdPrint2(("UniataAhciCLO: timeout\n"));
2093 } // end UniataAhciCLO()
2102 //SATA_SERROR_REG SError;
2105 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2107 /* issue Command List Override if supported */
2108 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2109 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2110 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2112 for(i
=0; i
<1000; i
++) {
2113 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2114 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2115 KdPrint2((" final CMD %#x\n", CMD
));
2118 AtapiStallExecution(1000);
2120 KdPrint2((" CMD %#x\n", CMD
));
2121 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2122 KdPrint2(("UniataAhciStop: timeout\n"));
2124 } // end UniataAhciStop()
2128 UniataAhciBeginTransaction(
2129 IN PVOID HwDeviceExtension
,
2131 IN ULONG DeviceNumber
,
2132 IN PSCSI_REQUEST_BLOCK Srb
2135 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2136 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2137 //ULONG Channel = deviceExtension->Channel + lChannel;
2141 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2142 //SATA_SSTATUS_REG SStatus;
2143 //SATA_SERROR_REG SError;
2144 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2149 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2151 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2153 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2154 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2158 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2159 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2160 AHCI_CL
->bytecount
= 0;
2161 if(AtaReq
->ahci
.ahci_base64
) {
2162 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2163 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2165 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2166 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2167 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2168 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2169 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2170 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2171 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2173 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2174 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2177 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2178 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2183 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2184 AHCI_CL
->cmd_table_phys
));
2187 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2188 KdPrint2((" CMD %#x\n", CMD
));
2189 // switch controller to ATAPI mode for ATA_PACKET commands only
2190 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2191 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2192 KdPrint2((" ATAPI\n"));
2193 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2194 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2196 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2199 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2200 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2201 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2204 /* issue command to controller */
2205 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2206 KdPrint2((" Set CI\n"));
2207 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2208 chan
->AhciPrevCI
|= 0x01 << tag
;
2211 CMD
|= ATA_AHCI_P_CMD_ST
|
2212 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0);
2214 KdPrint2((" Send CMD START\n"));
2215 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2216 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2218 KdPrint2((" No CMD START, already active\n"));
2221 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2222 // TODO: check if we send ATAPI_RESET and wait for ready of so.
2223 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2227 for(i
=0; i
<1000000; i
++) {
2228 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2229 if(!(TFD
& IDE_STATUS_BUSY
)) {
2233 if(TFD
& IDE_STATUS_BUSY
) {
2234 KdPrint2((" timeout\n"));
2236 if(TFD
& IDE_STATUS_ERROR
) {
2237 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2239 AtaReq
->ahci
.in_status
= TFD
;
2241 return IDE_STATUS_SUCCESS
;
2245 return IDE_STATUS_IDLE
;
2247 } // end UniataAhciBeginTransaction()
2251 UniataAhciEndTransaction(
2252 IN PVOID HwDeviceExtension
,
2254 IN ULONG DeviceNumber
,
2255 IN PSCSI_REQUEST_BLOCK Srb
2258 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2259 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2260 //ULONG Channel = deviceExtension->Channel + lChannel;
2263 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2265 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2268 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2269 //PHW_LU_EXTENSION LunExt;
2271 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2273 //LunExt = chan->lun[DeviceNumber];
2275 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2276 KdPrint2((" TFD %#x\n", TFD
));
2278 if(TFD
& IDE_STATUS_ERROR
) {
2279 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2280 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2282 AtaReq
->ahci
.in_error
= 0;
2284 AtaReq
->ahci
.in_status
= TFD
;
2286 //if (request->flags & ATA_R_CONTROL) {
2288 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2289 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2290 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2291 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2292 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2293 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2294 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2296 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2297 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2298 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2300 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2302 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2303 KdPrint2(("RCV:\n"));
2304 KdDump(RCV_FIS, 24);
2305 KdPrint2(("PIO:\n"));
2306 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2308 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2309 if(!AHCI_CL->bytecount) {
2310 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2314 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2315 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2316 if(CI
& (1 << tag
)) {
2318 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2319 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2322 UniataDumpAhciPortRegs(chan
);
2324 if(!UniataAhciAbortOperation(chan
)) {
2325 KdPrint2((" Abort failed, need RESET\n"));
2328 UniataDumpAhciPortRegs(chan
);
2330 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2331 if(chan
->AhciPrevCI
) {
2332 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2335 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2336 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2342 } // end UniataAhciEndTransaction()
2352 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2355 //UniataDumpAhciPortRegs(chan);
2358 /* Disable port interrupts */
2359 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2361 /* setup work areas */
2362 base
= chan
->AHCI_CTL_PhAddr
;
2364 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2367 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2368 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2369 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2371 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2372 (ULONG
)(base
& 0xffffffff));
2373 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2374 (ULONG
)((base
>> 32) & 0xffffffff));
2376 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2377 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2378 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2379 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2381 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2382 (ULONG
)(base
& 0xffffffff));
2383 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2384 (ULONG
)((base
>> 32) & 0xffffffff));
2386 /* activate the channel and power/spin up device */
2387 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2388 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2389 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2390 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2392 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2395 //UniataDumpAhciPortRegs(chan);
2398 UniataAhciStartFR(chan
);
2399 UniataAhciStart(chan
);
2402 UniataDumpAhciPortRegs(chan
);
2406 } // end UniataAhciResume()
2416 SATA_SCONTROL_REG SControl
;
2418 KdPrint2(("UniataAhciSuspend:\n"));
2420 /* Disable port interrupts */
2421 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2423 /* Reset command register. */
2424 UniataAhciStop(chan
);
2425 UniataAhciStopFR(chan
);
2426 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2427 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2429 /* Allow everything including partial and slumber modes. */
2430 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2432 /* Request slumber mode transition and give some time to get there. */
2433 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2434 AtapiStallExecution(100);
2438 SControl
.DET
= SStatus_DET_Offline
;
2439 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2442 } // end UniataAhciSuspend()
2448 IN PHW_CHANNEL chan
,
2449 IN ULONG DeviceNumber
,
2454 //ULONG Channel = deviceExtension->Channel + lChannel;
2459 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2460 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2462 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2464 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2465 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2468 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2470 case IDX_SATA_SStatus
:
2472 case IDX_SATA_SError
:
2474 case IDX_SATA_SControl
:
2481 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2482 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2483 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2484 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2485 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2486 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2487 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2489 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2490 KdPrint2((" PM read failed\n"));
2494 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2496 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2499 } // end UniataAhciReadPM()
2504 IN PHW_CHANNEL chan
,
2505 IN ULONG DeviceNumber
,
2510 //ULONG Channel = deviceExtension->Channel + lChannel;
2516 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2517 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2519 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2521 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2522 UniataSataWritePort4(chan
, Reg
, value
, 0);
2525 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2527 case IDX_SATA_SStatus
:
2529 case IDX_SATA_SError
:
2531 case IDX_SATA_SControl
:
2534 return IDE_STATUS_WRONG
;
2538 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2539 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2540 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2541 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2542 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2543 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2545 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2546 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2547 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2548 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2550 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2552 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2553 KdPrint2((" PM write failed\n"));
2554 return IDE_STATUS_WRONG
;
2557 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2559 if(TFD
& IDE_STATUS_ERROR
) {
2560 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2562 return (UCHAR
)(TFD
>> 8);
2564 } // end UniataAhciWritePM()
2567 UniataAhciSetupCmdPtr(
2568 IN OUT PATA_REQ AtaReq
2573 ULONGLONG prd_base64
;
2577 ULONGLONG prd_base64_0
;
2583 prd_base64_0
= prd_base64
= 0;
2584 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2585 prd_base0
= prd_base
;
2587 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2590 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2591 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2594 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2595 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2596 } // end UniataAhciSetupCmdPtr()
2600 BuildAhciInternalSrb (
2601 IN PVOID HwDeviceExtension
,
2602 IN ULONG DeviceNumber
,
2608 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2609 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2610 PSCSI_REQUEST_BLOCK srb
;
2612 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2614 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2617 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2621 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2622 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2623 UniAtaClearAtaReq(AtaReq
);
2625 srb
= chan
->AhciInternalSrb
;
2627 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2629 srb
->PathId
= (UCHAR
)lChannel
;
2630 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2631 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2632 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2634 // Set flags to disable synchronous negociation.
2635 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2637 // Set timeout to 4 seconds.
2638 srb
->TimeOutValue
= 4;
2641 srb
->DataBuffer
= Buffer
;
2642 srb
->DataTransferLength
= Length
;
2643 srb
->SrbExtension
= AtaReq
;
2646 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2647 AtaReq
->TransferLength
= Length
;
2649 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2650 //UniataAhciSetupCmdPtr(AtaReq);
2651 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2652 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2654 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2655 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2657 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2658 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2660 /* // Set CDB operation code.
2661 cdb = (PCDB)srb->Cdb;
2662 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2663 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2666 } // end BuildAhciInternalSrb()