3 Copyright (c) 2008-2014 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 // SATA sets actual transfer rate in LunExt on init.
72 // There is no run-time SATA rate adjustment yet.
73 // On the other hand, we may turn SATA device in PIO mode
74 // TODO: make separate states for interface speed and transfer mode (DMA vs PIO)
75 chan
->lun
[0]->LimitedTransferMode
=
76 chan
->lun
[0]->PhyTransferMode
=
77 chan
->lun
[0]->TransferMode
= ATA_SA150
+ (UCHAR
)(SStatus
.SPD
- 1);
79 KdPrint2((PRINT_PREFIX
"SATA TransferMode %#x\n", chan
->lun
[0]->TransferMode
));
80 if(chan
->MaxTransferMode
< chan
->lun
[0]->TransferMode
) {
81 KdPrint2((PRINT_PREFIX
"SATA upd chan TransferMode\n"));
82 chan
->MaxTransferMode
= chan
->lun
[0]->TransferMode
;
84 if(deviceExtension
->MaxTransferMode
< chan
->lun
[0]->TransferMode
) {
85 KdPrint2((PRINT_PREFIX
"SATA upd controller TransferMode\n"));
86 deviceExtension
->MaxTransferMode
= chan
->lun
[0]->TransferMode
;
91 AtapiStallExecution(10000);
94 KdPrint2((PRINT_PREFIX
"UniataSataConnect: SStatus %8.8x\n", SStatus
.Reg
));
95 return IDE_STATUS_WRONG
;
97 /* clear SATA error register */
98 UniataSataWritePort4(chan
, IDX_SATA_SError
,
99 UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
), pm_port
);
101 Status
= WaitOnBaseBusyLong(chan
);
102 if(Status
& IDE_STATUS_BUSY
) {
106 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow);
107 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh);
109 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
112 KdPrint2((PRINT_PREFIX
"UniataSataConnect: OK, ATA status %#x\n", Status
));
113 return IDE_STATUS_IDLE
;
114 } // end UniataSataConnect()
119 IN PVOID HwDeviceExtension
,
120 IN ULONG lChannel
, // logical channel
121 IN ULONG pm_port
, /* for port multipliers */
125 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
126 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
127 SATA_SCONTROL_REG SControl
;
130 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable:\n"));
132 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
133 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
134 return IDE_STATUS_IDLE
;
137 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
138 KdPrint2((PRINT_PREFIX
"SControl %#x\n", SControl
.Reg
));
139 if(SControl
.DET
== SControl_DET_Idle
) {
141 return UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
145 for (retry
= 0; retry
< 10; retry
++) {
146 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry init %d\n", retry
));
147 for (loop
= 0; loop
< 10; loop
++) {
149 SControl
.DET
= SControl_DET_Init
;
150 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, pm_port
);
151 AtapiStallExecution(100);
152 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
153 KdPrint2((PRINT_PREFIX
" SControl %8.8x\n", SControl
.Reg
));
154 if(SControl
.DET
== SControl_DET_Init
) {
158 AtapiStallExecution(5000);
159 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry idle %d\n", retry
));
160 for (loop
= 0; loop
< 10; loop
++) {
162 SControl
.DET
= SControl_DET_DoNothing
;
163 SControl
.IPM
= SControl_IPM_NoPartialSlumber
;
164 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, pm_port
);
165 AtapiStallExecution(100);
166 SControl
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SControl
, pm_port
);
167 KdPrint2((PRINT_PREFIX
" SControl %8.8x\n", SControl
.Reg
));
168 if(SControl
.DET
== SControl_DET_Idle
) {
169 return UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
174 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: failed\n"));
175 return IDE_STATUS_WRONG
;
176 } // end UniataSataPhyEnable()
181 IN PVOID HwDeviceExtension
,
182 IN ULONG lChannel
, // logical channel
183 IN BOOLEAN do_connect
,
184 IN ULONG pm_port
/* for port multipliers */
187 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
188 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
189 //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
190 SATA_SSTATUS_REG SStatus
;
191 SATA_SERROR_REG SError
;
193 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
194 //if(ChipFlags & UNIATA_SATA) {
196 SStatus
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SStatus
, pm_port
);
197 SError
.Reg
= UniataSataReadPort4(chan
, IDX_SATA_SError
, pm_port
);
200 KdPrint2((PRINT_PREFIX
" SStatus %#x\n", SStatus
.Reg
));
203 KdPrint2((PRINT_PREFIX
" SError %#x\n", SError
.Reg
));
204 /* clear error bits/interrupt */
205 UniataSataWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
, pm_port
);
208 /* if we have a connection event deal with it */
210 KdPrint2((PRINT_PREFIX
" catch SATA connect/disconnect\n"));
211 if(SStatus
.SPD
>= SStatus_SPD_Gen1
) {
212 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, pm_port
);
214 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, pm_port
);
223 } // end UniataSataClearErr()
228 IN PVOID HwDeviceExtension
,
229 IN ULONG lChannel
, // logical channel
231 IN ULONG pm_port
/* for port multipliers */
234 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
236 ULONG DeviceNumber
= (pm_port
? 1 : 0);
238 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
243 case UNIATA_SATA_EVENT_ATTACH
:
244 KdPrint2((PRINT_PREFIX
" CONNECTED\n"));
245 Status
= UniataSataConnect(HwDeviceExtension
, lChannel
, pm_port
);
246 KdPrint2((PRINT_PREFIX
" Status %#x\n", Status
));
247 if(Status
!= IDE_STATUS_IDLE
) {
250 CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
/*dev*/, FALSE
);
253 case UNIATA_SATA_EVENT_DETACH
:
254 KdPrint2((PRINT_PREFIX
" DISCONNECTED\n"));
255 UniataForgetDevice(deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
]);
260 } // end UniataSataEvent()
266 IN ULONG io_port_ndx
,
267 IN ULONG pm_port
/* for port multipliers */
270 if(chan
&& (io_port_ndx
< IDX_MAX_REG
) &&
271 chan
->RegTranslation
[io_port_ndx
].Proc
) {
273 KdPrint3((PRINT_PREFIX
" UniataSataReadPort4 %#x[%d]\n", io_port_ndx
, pm_port
));
275 PHW_DEVICE_EXTENSION deviceExtension
= chan
->DeviceExtension
;
276 PVOID HwDeviceExtension
= (PVOID
)deviceExtension
;
277 ULONG slotNumber
= deviceExtension
->slotNumber
;
278 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
279 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
286 if(deviceExtension
->HwFlags
& ICH5
) {
287 offs
= 0x50+chan
->lun
[p
]->SATA_lun_map
*0x10;
288 KdPrint3((PRINT_PREFIX
" ICH5 way, offs %#x\n", offs
));
289 switch(io_port_ndx
) {
290 case IDX_SATA_SStatus
:
293 case IDX_SATA_SError
:
296 case IDX_SATA_SControl
:
302 SetPciConfig4(0xa0, offs
);
303 GetPciConfig4(0xa4, offs
);
306 if(deviceExtension
->HwFlags
& ICH7
) {
307 offs
= 0x100+chan
->lun
[p
]->SATA_lun_map
*0x80;
308 KdPrint3((PRINT_PREFIX
" ICH7 way, offs %#x\n", offs
));
309 switch(io_port_ndx
) {
310 case IDX_SATA_SStatus
:
311 offs
+= IDX_AHCI_P_SStatus
;
313 case IDX_SATA_SError
:
314 offs
+= IDX_AHCI_P_SError
;
316 case IDX_SATA_SControl
:
317 offs
+= IDX_AHCI_P_SControl
;
322 return AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), offs
);
324 offs
= ((deviceExtension
->Channel
+chan
->lChannel
)*2+p
) * 0x100;
325 KdPrint3((PRINT_PREFIX
" def way, offs %#x\n", offs
));
326 switch(io_port_ndx
) {
327 case IDX_SATA_SStatus
:
330 case IDX_SATA_SControl
:
333 case IDX_SATA_SError
:
339 AtapiWritePort4(chan
, IDX_INDEXED_ADDR
, offs
);
340 return AtapiReadPort4(chan
, IDX_INDEXED_DATA
);
343 } // end switch(VendorID)
346 return AtapiReadPort4(chan
, io_port_ndx
);
347 } // end UniataSataReadPort4()
351 UniataSataWritePort4(
353 IN ULONG io_port_ndx
,
355 IN ULONG pm_port
/* for port multipliers */
358 if(chan
&& (io_port_ndx
< IDX_MAX_REG
) &&
359 chan
->RegTranslation
[io_port_ndx
].Proc
) {
361 KdPrint3((PRINT_PREFIX
" UniataSataWritePort4 %#x[%d]\n", io_port_ndx
, pm_port
));
363 PHW_DEVICE_EXTENSION deviceExtension
= chan
->DeviceExtension
;
364 PVOID HwDeviceExtension
= (PVOID
)deviceExtension
;
365 ULONG slotNumber
= deviceExtension
->slotNumber
;
366 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
367 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
374 if(deviceExtension
->HwFlags
& ICH5
) {
375 offs
= 0x50+chan
->lun
[p
]->SATA_lun_map
*0x10;
376 KdPrint3((PRINT_PREFIX
" ICH5 way, offs %#x\n", offs
));
377 switch(io_port_ndx
) {
378 case IDX_SATA_SStatus
:
381 case IDX_SATA_SError
:
384 case IDX_SATA_SControl
:
390 SetPciConfig4(0xa0, offs
);
391 SetPciConfig4(0xa4, data
);
394 if(deviceExtension
->HwFlags
& ICH7
) {
395 offs
= 0x100+chan
->lun
[p
]->SATA_lun_map
*0x80;
396 KdPrint3((PRINT_PREFIX
" ICH7 way, offs %#x\n", offs
));
397 switch(io_port_ndx
) {
398 case IDX_SATA_SStatus
:
399 offs
+= IDX_AHCI_P_SStatus
;
401 case IDX_SATA_SError
:
402 offs
+= IDX_AHCI_P_SError
;
404 case IDX_SATA_SControl
:
405 offs
+= IDX_AHCI_P_SControl
;
410 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), offs
, data
);
413 offs
= ((deviceExtension
->Channel
+chan
->lChannel
)*2+p
) * 0x100;
414 KdPrint3((PRINT_PREFIX
" def way, offs %#x\n", offs
));
415 switch(io_port_ndx
) {
416 case IDX_SATA_SStatus
:
419 case IDX_SATA_SControl
:
422 case IDX_SATA_SError
:
428 AtapiWritePort4(chan
, IDX_INDEXED_ADDR
, offs
);
429 AtapiWritePort4(chan
, IDX_INDEXED_DATA
, data
);
432 } // end switch(VendorID)
435 AtapiWritePort4(chan
, io_port_ndx
, data
);
436 } // end UniataSataWritePort4()
442 IN ULONG DeviceNumber
,
447 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
448 return UniataAhciReadPM(chan
, DeviceNumber
, Reg
, result
);
451 } // end UniataSataReadPM()
457 IN ULONG DeviceNumber
,
462 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
463 return UniataAhciWritePM(chan
, DeviceNumber
, Reg
, value
);
465 return IDE_STATUS_WRONG
;
466 } // end UniataSataWritePM()
471 IN PVOID HwDeviceExtension
,
473 IN ULONG DeviceNumber
476 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
478 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
479 return UniataAhciSoftReset(HwDeviceExtension
, lChannel
, DeviceNumber
);
482 } // end UniataSataSoftReset()
485 UniataSataIdentifyPM(
494 PHW_LU_EXTENSION LunExt
;
496 KdPrint((PRINT_PREFIX
"UniataSataIdentifyPM:\n"));
500 /* get PM vendor & product data */
501 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 0, &PM_DeviceId
)) {
502 KdPrint2((PRINT_PREFIX
" error getting PM vendor data\n"));
505 /* get PM revision data */
506 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 1, &PM_RevId
)) {
507 KdPrint2((PRINT_PREFIX
" error getting PM revison data\n"));
510 /* get number of HW ports on the PM */
511 if(!UniataSataReadPM(chan
, AHCI_DEV_SEL_PM
, 2, &PM_Ports
)) {
512 KdPrint2((PRINT_PREFIX
" error getting PM port info\n"));
516 PM_Ports
&= 0x0000000f;
518 switch(PM_DeviceId
) {
520 /* This PM declares 6 ports, while only 5 of them are real.
521 * Port 5 is enclosure management bridge port, which has implementation
522 * problems, causing probe faults. Hide it for now. */
523 KdPrint2((PRINT_PREFIX
" SiI 3726 (rev=%#x) Port Multiplier with %d (5) ports\n",
524 PM_RevId
, PM_Ports
));
528 /* This PM declares 7 ports, while only 5 of them are real.
529 * Port 5 is some fake "Config Disk" with 640 sectors size,
530 * port 6 is enclosure management bridge port.
531 * Both fake ports has implementation problems, causing
532 * probe faults. Hide them for now. */
533 KdPrint2((PRINT_PREFIX
" SiI 4726 (rev=%#x) Port Multiplier with %d (5) ports\n",
534 PM_RevId
, PM_Ports
));
538 KdPrint2((PRINT_PREFIX
" Port Multiplier (id=%08x rev=%#x) with %d ports\n",
539 PM_DeviceId
, PM_RevId
, PM_Ports
));
544 for(i
=0; i
<PM_Ports
; i
++) {
546 LunExt
= chan
->lun
[i
];
548 KdPrint2((PRINT_PREFIX
" Port %d\n", i
));
549 if(UniataSataPhyEnable(chan
->DeviceExtension
, chan
->lChannel
, i
, UNIATA_SATA_RESET_ENABLE
) != IDE_STATUS_IDLE
) {
550 LunExt
->DeviceFlags
&= ~DFLAGS_DEVICE_PRESENT
;
554 * XXX: I have no idea how to properly wait for PMP port hardreset
555 * completion. Without this delay soft reset does not completes
558 AtapiStallExecution(1000000);
560 signature
= UniataSataSoftReset(chan
->DeviceExtension
, chan
->lChannel
, i
);
561 KdPrint2((PRINT_PREFIX
" signature %#x\n", signature
));
563 LunExt
->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
564 chan
->PmLunMap
|= (1 << i
);
565 /* figure out whats there */
566 switch (signature
>> 16) {
568 LunExt
->DeviceFlags
&= ~DFLAGS_ATAPI_DEVICE
;
571 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_DEVICE
;
577 } // end UniataSataIdentifyPM()
583 IN PHW_DEVICE_EXTENSION deviceExtension
589 KdPrint2((PRINT_PREFIX
590 " AHCI Base: %#x MemIo %d Proc %d\n",
591 deviceExtension
->BaseIoAHCI_0
.Addr
,
592 deviceExtension
->BaseIoAHCI_0
.MemIo
,
593 deviceExtension
->BaseIoAHCI_0
.Proc
));
595 for(j
=0; j
<=IDX_AHCI_VS
; j
+=sizeof(ULONG
)) {
596 xReg
= AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)&deviceExtension
->BaseIoAHCI_0
, j
);
597 KdPrint2((PRINT_PREFIX
598 " AHCI_%#x (%#x) = %#x\n",
600 (deviceExtension
->BaseIoAHCI_0
.Addr
+j
),
604 } // end UniataDumpAhciRegs()
609 UniataDumpAhciPortRegs(
616 KdPrint2((PRINT_PREFIX
617 " AHCI port %d Base: %#x MemIo %d Proc %d\n",
619 chan
->BaseIoAHCI_Port
.Addr
,
620 chan
->BaseIoAHCI_Port
.MemIo
,
621 chan
->BaseIoAHCI_Port
.Proc
));
623 for(j
=0; j
<=IDX_AHCI_P_SNTF
; j
+=sizeof(ULONG
)) {
624 xReg
= AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)&chan
->BaseIoAHCI_Port
, j
);
625 KdPrint2((PRINT_PREFIX
626 " AHCI%d_%#x (%#x) = %#x\n",
629 (chan
->BaseIoAHCI_Port
.Addr
+j
),
633 } // end UniataDumpAhciPortRegs()
640 IN PVOID HwDeviceExtension
643 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
647 ULONG BaseMemAddress
;
653 BOOLEAN MemIo
= FALSE
;
655 KdPrint2((PRINT_PREFIX
" UniataAhciInit:\n"));
658 UniataDumpAhciRegs(deviceExtension
);
661 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
662 if(CAP2
& AHCI_CAP2_BOH
) {
663 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
664 KdPrint2((PRINT_PREFIX
" stage 1 BOHC %#x\n", BOHC
));
665 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
666 BOHC
| AHCI_BOHC_OOS
);
667 for(i
=0; i
<50; i
++) {
668 AtapiStallExecution(500);
669 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
670 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
671 if(BOHC
& AHCI_BOHC_BB
) {
674 if(!(BOHC
& AHCI_BOHC_BOS
)) {
678 KdPrint2((PRINT_PREFIX
" stage 2 BOHC %#x\n", BOHC
));
679 if(BOHC
& AHCI_BOHC_BB
) {
680 for(i
=0; i
<2000; i
++) {
681 AtapiStallExecution(1000);
682 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
683 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
684 if(!(BOHC
& AHCI_BOHC_BOS
)) {
689 KdPrint2((PRINT_PREFIX
" final BOHC %#x\n", BOHC
));
692 /* disable AHCI interrupts, for MSI compatibility issue
693 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
694 26. AHCI Reset and MSI Request
697 KdPrint2((PRINT_PREFIX
" get GHC\n"));
698 /* enable AHCI mode */
699 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
700 if(!(GHC
& AHCI_GHC_AE
)) {
701 KdPrint2((PRINT_PREFIX
" enable AHCI mode, disable intr, GHC %#x\n", GHC
));
702 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
703 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
705 KdPrint2((PRINT_PREFIX
" disable intr, GHC %#x\n", GHC
));
706 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
709 AtapiStallExecution(100);
711 /* read GHC again and reset AHCI controller */
712 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
713 KdPrint2((PRINT_PREFIX
" reset AHCI controller, GHC %#x\n", GHC
));
714 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
717 for(i
=0; i
<1000; i
++) {
718 AtapiStallExecution(1000);
719 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
720 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
721 if(!(GHC
& AHCI_GHC_HR
)) {
725 if(GHC
& AHCI_GHC_HR
) {
726 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
730 /* re-enable AHCI mode */
731 /* Linux: Some controllers need AHCI_EN to be written multiple times.
732 * Try a few times before giving up.
734 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
736 if(!(GHC
& AHCI_GHC_AE
)) {
737 KdPrint2((PRINT_PREFIX
" re-enable AHCI mode, GHC %#x\n", GHC
));
738 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
740 AtapiStallExecution(1000);
741 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
746 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
747 if(!(GHC
& AHCI_GHC_AE
)) {
748 KdPrint2((PRINT_PREFIX
" Can't enable AHCI mode\n"));
752 deviceExtension
->AHCI_CAP
=
753 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
754 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
755 if(CAP
& AHCI_CAP_S64A
) {
756 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
757 deviceExtension
->Host64
= TRUE
;
759 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
760 if(CAP
& AHCI_CAP_PMD
) {
761 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
763 if(CAP
& AHCI_CAP_SAM
) {
764 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
767 /* get the number of HW channels */
768 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
769 deviceExtension
->AHCI_PI
= PI
;
770 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
771 KdPrint2((PRINT_PREFIX
" AHCI PI mask %#x\n", deviceExtension
->AHCI_PI_mask
));
772 deviceExtension
->AHCI_PI
= PI
= PI
& deviceExtension
->AHCI_PI_mask
;
773 KdPrint2((PRINT_PREFIX
" masked AHCI PI %#x\n", PI
));
775 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
776 if(CAP2
& AHCI_CAP2_BOH
) {
777 KdPrint2((PRINT_PREFIX
" retry BOHC\n"));
778 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
779 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
780 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
781 BOHC
| AHCI_BOHC_OOS
);
783 /* clear interrupts */
784 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
785 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
787 /* enable AHCI interrupts */
788 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
789 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
791 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
792 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
794 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
795 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
797 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
798 chan
= &deviceExtension
->chan
[c
];
799 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
801 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
803 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
805 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
807 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
808 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
810 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
811 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
812 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
813 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
814 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
815 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
816 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
817 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
818 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
819 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
820 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
822 UniataInitSyncBaseIO(chan
);
824 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
825 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
826 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
827 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
828 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
829 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
830 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
831 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
833 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
835 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
836 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
840 UniataAhciResume(chan
);
842 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
846 } // end UniataAhciInit()
850 UniAtaAhciValidateVersion(
851 IN PHW_DEVICE_EXTENSION deviceExtension
,
859 KdPrint((" wrong AHCI revision %#x\n", version
));
868 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
869 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
870 KdPrint((" AHCI revision excluded\n"));
875 } // end UniAtaAhciValidateVersion()
880 IN PVOID HwDeviceExtension
,
881 IN PPCI_COMMON_CONFIG pciData
, // optional
882 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
885 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
886 //ULONG slotNumber = deviceExtension->slotNumber;
887 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
898 ULONG NumberChannels
;
899 ULONG BaseMemAddress
;
900 BOOLEAN MemIo
= FALSE
;
901 BOOLEAN found
= FALSE
;
903 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
905 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
906 KdPrint((" AHCI excluded\n"));
909 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
911 if(!BaseMemAddress
) {
912 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
915 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
916 KdPrint2((PRINT_PREFIX
"MemIo\n"));
919 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
920 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
923 UniataDumpAhciRegs(deviceExtension
);
926 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
927 if(GHC
& AHCI_GHC_HR
) {
928 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
932 /* check AHCI mode. Save state and try enable */
934 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
935 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
937 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
939 if(!(GHC
& AHCI_GHC_AE
)) {
940 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
941 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
942 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
945 KdPrint2((PRINT_PREFIX
" try enable\n"));
946 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
947 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
948 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
950 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
951 if(!(GHC
& AHCI_GHC_AE
)) {
952 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
957 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
958 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
959 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
960 if(CAP
& AHCI_CAP_S64A
) {
961 KdPrint2((PRINT_PREFIX
" 64bit"));
962 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
965 if(CAP2
& AHCI_CAP2_BOH
) {
966 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
967 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
970 if(CAP
& AHCI_CAP_NCQ
) {
971 KdPrint2((PRINT_PREFIX
" NCQ"));
973 if(CAP
& AHCI_CAP_SNTF
) {
974 KdPrint2((PRINT_PREFIX
" SNTF"));
976 if(CAP
& AHCI_CAP_CCC
) {
977 KdPrint2((PRINT_PREFIX
" CCC"));
979 KdPrint2((PRINT_PREFIX
"\n"));
981 /* get the number of HW channels */
983 /* CAP.NOP sometimes indicate the index of the last enabled
984 * port, at other times, that of the last possible port, so
985 * determining the maximum port number requires looking at
986 * both CAP.NOP and PI.
988 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
989 deviceExtension
->AHCI_PI
= deviceExtension
->AHCI_PI_mask
= PI
;
990 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
992 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1) {
993 if(AtapiRegCheckDevValue(deviceExtension
, n
, DEVNUM_NOT_SPECIFIED
, L
"Exclude", 0)) {
994 KdPrint2((PRINT_PREFIX
"Channel %d excluded\n", n
));
995 deviceExtension
->AHCI_PI
&= ~((ULONG
)1 << n
);
996 deviceExtension
->AHCI_PI_mask
&= ~((ULONG
)1 << n
);
999 deviceExtension
->AHCI_PI_mask
=
1000 AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PortMask", deviceExtension
->AHCI_PI_mask
);
1001 KdPrint2((PRINT_PREFIX
"Force PortMask %#x\n", deviceExtension
->AHCI_PI_mask
));
1003 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
1005 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
1007 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
1008 KdPrint2((PRINT_PREFIX
" Detected Channels %d / %d\n", NumberChannels
, n
));
1010 switch(deviceExtension
->DevID
) {
1012 KdPrint2((PRINT_PREFIX
" Marvell M88SE6111 -> 1\n"));
1016 KdPrint2((PRINT_PREFIX
" Marvell M88SE6121 -> 2\n"));
1017 NumberChannels
= min(NumberChannels
, 2);
1022 KdPrint2((PRINT_PREFIX
" Marvell M88SE614x/9123 -> 4\n"));
1023 NumberChannels
= min(NumberChannels
, 4);
1027 if(!NumberChannels
) {
1028 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
1032 KdPrint2((PRINT_PREFIX
" Adjusted Channels %d\n", NumberChannels
));
1035 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
1036 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
1038 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
1040 NumberChannels
, PI
));
1041 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
1044 if(CAP
& AHCI_CAP_SPM
) {
1045 KdPrint2((PRINT_PREFIX
" PM supported\n"));
1046 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
1047 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
1048 deviceExtension
->NumberLuns
= 1;
1049 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
1051 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
1052 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
1053 //deviceExtension->NumberLuns = 1;
1056 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
1057 deviceExtension
->NumberLuns
= 1;
1060 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
1064 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
1065 if(deviceExtension
->NumberChannels
< NumberChannels
) {
1066 deviceExtension
->NumberChannels
= NumberChannels
;
1068 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
1069 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
1071 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
1072 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
1077 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
1078 KdPrint((" AHCI detect status %d\n", found
));
1081 } // end UniataAhciDetect()
1086 IN PVOID HwDeviceExtension
,
1088 IN ULONG DeviceNumber
1091 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1092 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1093 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1097 SATA_SSTATUS_REG SStatus
;
1098 SATA_SERROR_REG SError
;
1099 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1102 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1104 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1105 KdPrint((" hIS %#x\n", hIS
));
1106 hIS
&= (1 << Channel
);
1108 return INTERRUPT_REASON_IGNORE
;
1110 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1111 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1112 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1113 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1114 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1116 /* clear interrupt(s) */
1117 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1118 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1119 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1121 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1122 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1124 /* do we have cold connect surprise */
1128 /* check for and handle connect events */
1130 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1133 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1135 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1136 chan
->AhciPrevCI
= CI
;
1137 chan
->AhciLastSError
= SError
.Reg
;
1138 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1139 chan
->AhciLastIS
= IS
.Reg
;
1140 if(CI
& (1 << tag
)) {
1142 UniataDumpAhciPortRegs(chan
);
1144 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1146 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1147 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1148 KdPrint((" AHCI: unexpected, error\n"));
1150 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1154 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1155 KdPrint2((" TFD %#x\n", TFD));
1156 if(TFD & IDE_STATUS_BUSY) {
1157 KdPrint2((" Seems to be interrupt on error\n"));
1158 return INTERRUPT_REASON_OUR;
1161 return INTERRUPT_REASON_UNEXPECTED
;
1164 return INTERRUPT_REASON_OUR
;
1166 } // end UniataAhciStatus()
1170 UniataAhciSnapAtaRegs(
1171 IN PHW_CHANNEL chan
,
1172 IN ULONG DeviceNumber
,
1173 IN OUT PIDEREGS_EX regs
1178 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1179 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1180 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1181 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1183 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1184 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1185 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1186 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1187 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1191 } // end UniataAhciSnapAtaRegs()
1195 UniataAhciSetupFIS_H2D(
1196 IN PHW_DEVICE_EXTENSION deviceExtension
,
1197 IN ULONG DeviceNumber
,
1209 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1211 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1213 plba
= (PUCHAR
)&lba
;
1215 RtlZeroMemory(fis
, 20);
1217 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1218 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1219 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1220 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1221 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1223 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1224 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1225 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1227 command
== IDE_COMMAND_ATAPI_PACKET
) {
1228 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1229 if(feature
& ATA_F_DMA
) {
1230 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1232 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1233 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1235 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1238 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1239 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1240 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1241 //return IDE_STATUS_ERROR;
1242 //return SRB_STATUS_ERROR;
1246 need48
= UniAta_need_lba48(command
, lba
, count
,
1247 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1249 /* translate command into 48bit version */
1251 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1252 command
= AtaCommands48
[command
];
1254 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1259 fis
[IDX_AHCI_o_Command
] = command
;
1260 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1262 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1263 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1264 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1266 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1270 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1272 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1273 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1274 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1276 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1278 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1280 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1283 //#pragma warning(push)
1284 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1286 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1287 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1289 //#pragma warning(pop)
1300 } // end UniataAhciSetupFIS_H2D()
1304 UniataAhciSetupFIS_H2D_Direct(
1305 IN PHW_DEVICE_EXTENSION deviceExtension
,
1306 IN ULONG DeviceNumber
,
1315 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1318 command
= regs
->bCommandReg
;
1320 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1322 //plba = (PUCHAR)&lba;
1324 RtlZeroMemory(fis
, 20);
1326 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1327 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1328 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1329 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1330 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1332 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1333 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1334 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1336 command
== IDE_COMMAND_ATAPI_PACKET
) {
1337 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1338 if(feature & ATA_F_DMA) {
1339 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1341 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1342 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1345 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1348 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1349 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1351 /* translate command into 48bit version */
1353 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1354 command
= AtaCommands48
[command
];
1356 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1361 fis
[IDX_AHCI_o_Command
] = command
;
1362 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1364 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1365 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1366 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1368 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1372 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1374 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1375 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1376 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1378 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1380 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1382 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1384 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1385 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1387 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1393 } // end UniataAhciSetupFIS_H2D_Direct()
1397 UniataAhciWaitCommandReady(
1398 IN PHW_CHANNEL chan
,
1411 for (i
=0; i
<timeout
; i
++) {
1412 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1413 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1414 if (!(( CI
>> tag
) & 0x01)) {
1417 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1418 //KdPrint((" IS %#x\n", IS.Reg));
1422 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1424 KdPrint((" AHCI: error %#x\n", SError
));
1428 AtapiStallExecution(200);
1430 KdPrint((" CI %#x\n", CI
));
1432 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1433 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1435 /* clear interrupt(s) */
1436 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1437 KdPrint((" IS %#x\n", IS
.Reg
));
1438 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1440 if (timeout
&& (i
>= timeout
)) {
1444 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1445 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1447 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1448 KdPrint2((" TFD %#x\n", TFD
));
1451 return IDE_STATUS_WRONG
;
1454 return IDE_STATUS_IDLE
;
1455 } // end UniataAhciWaitCommandReady()
1459 UniataAhciSendCommand(
1460 IN PVOID HwDeviceExtension
,
1462 IN ULONG DeviceNumber
,
1463 IN USHORT ahci_flags
,
1467 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1468 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1469 //ULONG Channel = deviceExtension->Channel + lChannel;
1472 //SATA_SSTATUS_REG SStatus;
1473 //SATA_SERROR_REG SError;
1474 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1478 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1480 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1482 AHCI_CL
->prd_length
= 0;
1483 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1484 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1486 AHCI_CL
->bytecount
= 0;
1487 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1488 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1489 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1492 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1493 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1495 return UniataAhciWaitCommandReady(chan
, timeout
);
1497 } // end UniataAhciSendCommand()
1501 UniataAhciSendPIOCommand(
1502 IN PVOID HwDeviceExtension
,
1504 IN ULONG DeviceNumber
,
1505 IN PSCSI_REQUEST_BLOCK Srb
,
1507 IN ULONG length
, /* bytes */
1510 IN USHORT bcount
, /* block count, just ATA register */
1512 IN USHORT ahci_flags
,
1513 IN ULONG wait_flags
,
1517 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1518 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1523 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1524 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1526 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1528 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1529 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1531 if(length
/DEV_BSIZE
!= bcount
) {
1532 KdPrint((" length/DEV_BSIZE != bcount\n"));
1536 //UniataDumpAhciPortRegs(chan);
1540 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1542 KdPrint((" !Srb\n"));
1543 return IDE_STATUS_WRONG
;
1545 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1546 //should be already called on init
1548 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1549 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1551 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1553 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1554 &(AHCI_CMD
->cfis
[0]),
1562 KdPrint2(("!fis_size\n"));
1563 return IDE_STATUS_WRONG
;
1566 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1567 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1568 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1571 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1572 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1573 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1574 KdPrint((" assume OUT\n"));
1576 AtaReq
->Flags
|= REQ_FLAG_READ
;
1577 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1578 KdPrint((" assume IN\n"));
1580 if(!AtapiDmaSetup(HwDeviceExtension
,
1582 lChannel
, // logical channel,
1586 KdPrint2((" can't setup buffer\n"));
1587 return IDE_STATUS_WRONG
;
1591 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1594 //UniataDumpAhciPortRegs(chan);
1597 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1600 //UniataDumpAhciPortRegs(chan);
1603 if(wait_flags
== ATA_IMMEDIATE
) {
1605 KdPrint2((" return imemdiately\n"));
1607 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1608 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1609 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1614 } // end UniataAhciSendPIOCommand()
1618 UniataAhciSendPIOCommandDirect(
1619 IN PVOID HwDeviceExtension
,
1621 IN ULONG DeviceNumber
,
1622 IN PSCSI_REQUEST_BLOCK Srb
,
1623 IN PIDEREGS_EX regs
,
1624 IN ULONG wait_flags
,
1628 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1629 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1634 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1635 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1636 USHORT ahci_flags
=0;
1639 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1641 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1642 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1644 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1645 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1649 //UniataDumpAhciPortRegs(chan);
1653 KdPrint((" !Srb\n"));
1654 return IDE_STATUS_WRONG
;
1655 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1656 //should be already called on init
1658 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1659 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1661 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1663 KdPrint((" !AHCI_CMD\n"));
1664 return IDE_STATUS_WRONG
;
1667 if(Srb
->DataTransferLength
) {
1668 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1669 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1670 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1672 AtaReq
->Flags
|= REQ_FLAG_READ
;
1676 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1677 &(AHCI_CMD
->cfis
[0]),
1681 KdPrint2(("!fis_size\n"));
1682 return IDE_STATUS_WRONG
;
1685 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1686 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1687 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1689 if(Srb
->DataTransferLength
) {
1690 if(!AtapiDmaSetup(HwDeviceExtension
,
1692 lChannel
, // logical channel,
1694 (PUCHAR
)(Srb
->DataBuffer
),
1695 Srb
->DataTransferLength
)) {
1696 KdPrint2((" can't setup buffer\n"));
1697 return IDE_STATUS_WRONG
;
1701 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1704 //UniataDumpAhciPortRegs(chan);
1707 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1710 //UniataDumpAhciPortRegs(chan);
1713 if(wait_flags
== ATA_IMMEDIATE
) {
1715 KdPrint2((" return imemdiately\n"));
1717 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1718 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1719 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1724 } // end UniataAhciSendPIOCommandDirect()
1728 UniataAhciAbortOperation(
1732 /* kick controller into sane state */
1733 if(!UniataAhciStop(chan
)) {
1736 if(!UniataAhciStopFR(chan
)) {
1739 if(!UniataAhciCLO(chan
)) {
1742 UniataAhciStartFR(chan
);
1743 UniataAhciStart(chan
);
1746 } // end UniataAhciAbortOperation()
1750 UniataAhciSoftReset(
1751 IN PVOID HwDeviceExtension
,
1753 IN ULONG DeviceNumber
1756 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1757 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1758 //ULONG Channel = deviceExtension->Channel + lChannel;
1764 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1766 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1767 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1769 /* kick controller into sane state */
1770 if(!UniataAhciAbortOperation(chan
)) {
1771 KdPrint2((" abort failed\n"));
1775 /* pull reset active */
1776 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1777 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1778 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1779 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1780 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1782 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1783 KdPrint2((" timeout\n"));
1786 AtapiStallExecution(50);
1788 /* pull reset inactive */
1789 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1790 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1791 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1792 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1793 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1794 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1795 KdPrint2((" timeout (2)\n"));
1799 UniataAhciWaitReady(chan
, 1);
1801 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1803 return UniataAhciUlongFromRFIS(RCV_FIS
);
1805 } // end UniataAhciSoftReset()
1809 UniataAhciWaitReady(
1810 IN PHW_CHANNEL chan
,
1817 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1819 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1821 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1822 for(i
=0; i
<timeout
&& (TFD
&
1823 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1824 AtapiStallExecution(1000);
1825 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1828 KdPrint2((" TFD %#x\n", TFD
));
1832 } // end UniataAhciWaitReady()
1836 UniataAhciHardReset(
1837 IN PVOID HwDeviceExtension
,
1839 OUT PULONG signature
1842 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1843 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1844 //ULONG Channel = deviceExtension->Channel + lChannel;
1848 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1850 (*signature
) = 0xffffffff;
1852 UniataAhciStop(chan
);
1853 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1854 KdPrint((" no PHY\n"));
1855 return IDE_STATUS_WRONG
;
1858 /* Wait for clearing busy status. */
1859 TFD
= UniataAhciWaitReady(chan
, 15000);
1860 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1861 KdPrint((" busy: TFD %#x\n", TFD
));
1864 KdPrint((" TFD %#x\n", TFD
));
1867 UniataDumpAhciPortRegs(chan
);
1870 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1871 KdPrint((" sig: %#x\n", *signature
));
1873 UniataAhciStart(chan
);
1877 } // end UniataAhciHardReset()
1882 IN PVOID HwDeviceExtension
,
1886 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1887 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1888 //ULONG Channel = deviceExtension->Channel + lChannel;
1889 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1894 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1896 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1898 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1900 /* Disable port interrupts */
1901 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1903 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1905 KdPrint((" No devices in all LUNs\n"));
1906 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1907 // Zero device fields to ensure that if earlier devices were found,
1908 // but not claimed, the fields are cleared.
1909 UniataForgetDevice(chan
->lun
[i
]);
1912 /* enable wanted port interrupts */
1913 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1914 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1918 /* enable wanted port interrupts */
1919 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1920 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1921 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1922 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1923 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1924 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1927 * Only probe for PortMultiplier if HW has support.
1928 * Ignore Marvell, which is not working,
1930 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1931 if ((CAP
& AHCI_CAP_SPM
) &&
1932 (VendorID
!= ATA_MARVELL_ID
)) {
1933 KdPrint((" check PM\n"));
1934 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1935 /* Workaround for some ATI chips, failing to soft-reset
1936 * when port multiplicator supported, but absent.
1937 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1938 if (signature
== 0xffffffff) {
1939 KdPrint((" re-check PM\n"));
1940 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1943 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1946 KdPrint((" signature %#x\n", signature
));
1947 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1948 switch (signature
>> 16) {
1950 KdPrint((" ATA dev\n"));
1951 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1956 if(deviceExtension
->NumberLuns
> 1) {
1957 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1958 UniataSataIdentifyPM(chan
);
1960 KdPrint((" no PM supported (1 lun/chan)\n"));
1964 KdPrint((" ATAPI dev\n"));
1965 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1968 default: /* SOS XXX */
1969 KdPrint((" default to ATA ???\n"));
1970 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1976 } // end UniataAhciReset()
1986 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1988 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1989 KdPrint2((" CMD %#x\n", CMD
));
1990 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1991 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
1994 } // end UniataAhciStartFR()
2005 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
2007 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2008 KdPrint2((" CMD %#x\n", CMD
));
2009 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
2011 for(i
=0; i
<1000; i
++) {
2012 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2013 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
2014 KdPrint2((" final CMD %#x\n", CMD
));
2017 AtapiStallExecution(1000);
2019 KdPrint2((" CMD %#x\n", CMD
));
2020 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2021 KdPrint2(("UniataAhciStopFR: timeout\n"));
2023 } // end UniataAhciStopFR()
2032 SATA_SERROR_REG SError
;
2034 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
2036 /* clear SATA error register */
2037 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
2039 /* clear any interrupts pending on this channel */
2040 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
2041 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
2043 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
2045 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2046 KdPrint2((" CMD %#x\n", CMD
));
2047 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2050 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
2051 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2054 } // end UniataAhciStart()
2062 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2063 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2065 //SATA_SERROR_REG SError;
2068 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
2070 /* issue Command List Override if supported */
2071 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
2072 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
2073 if(!(CAP
& AHCI_CAP_SCLO
)) {
2076 KdPrint2((" send CLO\n"));
2077 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2078 CMD
|= ATA_AHCI_P_CMD_CLO
;
2079 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2081 for(i
=0; i
<1000; i
++) {
2082 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2083 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
2084 KdPrint2((" final CMD %#x\n", CMD
));
2087 AtapiStallExecution(1000);
2089 KdPrint2((" CMD %#x\n", CMD
));
2090 KdPrint2(("UniataAhciCLO: timeout\n"));
2092 } // end UniataAhciCLO()
2101 //SATA_SERROR_REG SError;
2104 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2106 /* issue Command List Override if supported */
2107 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2108 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2109 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2111 for(i
=0; i
<1000; i
++) {
2112 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2113 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2114 KdPrint2((" final CMD %#x\n", CMD
));
2117 AtapiStallExecution(1000);
2119 KdPrint2((" CMD %#x\n", CMD
));
2120 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2121 KdPrint2(("UniataAhciStop: timeout\n"));
2123 } // end UniataAhciStop()
2127 UniataAhciBeginTransaction(
2128 IN PVOID HwDeviceExtension
,
2130 IN ULONG DeviceNumber
,
2131 IN PSCSI_REQUEST_BLOCK Srb
2134 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2135 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2136 //ULONG Channel = deviceExtension->Channel + lChannel;
2140 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2141 //SATA_SSTATUS_REG SStatus;
2142 //SATA_SERROR_REG SError;
2143 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2148 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2150 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2152 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2153 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2157 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2158 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2159 AHCI_CL
->bytecount
= 0;
2160 if(AtaReq
->ahci
.ahci_base64
) {
2161 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2162 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2164 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2165 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2166 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2167 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2168 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2169 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2170 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2172 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2173 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2176 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2177 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2182 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2183 AHCI_CL
->cmd_table_phys
));
2186 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2187 KdPrint2((" CMD %#x\n", CMD
));
2188 // switch controller to ATAPI mode for ATA_PACKET commands only
2189 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2190 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2191 KdPrint2((" ATAPI\n"));
2192 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2193 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2195 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2198 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2199 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2200 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2203 /* issue command to controller */
2204 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2205 KdPrint2((" Set CI\n"));
2206 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2207 chan
->AhciPrevCI
|= 0x01 << tag
;
2209 KdPrint2((" Send CMD START\n"));
2210 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2213 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
2214 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2216 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2217 // TODO: check if we send ATAPI_RESET and wait for ready of so.
2218 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2222 for(i
=0; i
<1000000; i
++) {
2223 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2224 if(!(TFD
& IDE_STATUS_BUSY
)) {
2228 if(TFD
& IDE_STATUS_BUSY
) {
2229 KdPrint2((" timeout\n"));
2231 if(TFD
& IDE_STATUS_ERROR
) {
2232 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2234 AtaReq
->ahci
.in_status
= TFD
;
2236 return IDE_STATUS_SUCCESS
;
2240 return IDE_STATUS_IDLE
;
2242 } // end UniataAhciBeginTransaction()
2246 UniataAhciEndTransaction(
2247 IN PVOID HwDeviceExtension
,
2249 IN ULONG DeviceNumber
,
2250 IN PSCSI_REQUEST_BLOCK Srb
2253 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2254 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2255 //ULONG Channel = deviceExtension->Channel + lChannel;
2258 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2260 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2263 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2264 //PHW_LU_EXTENSION LunExt;
2266 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2268 //LunExt = chan->lun[DeviceNumber];
2270 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2271 KdPrint2((" TFD %#x\n", TFD
));
2273 if(TFD
& IDE_STATUS_ERROR
) {
2274 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2275 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2277 AtaReq
->ahci
.in_error
= 0;
2279 AtaReq
->ahci
.in_status
= TFD
;
2281 //if (request->flags & ATA_R_CONTROL) {
2283 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2284 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2285 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2286 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2287 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2288 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2289 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2291 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2292 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2293 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2295 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2297 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2298 KdPrint2(("RCV:\n"));
2299 KdDump(RCV_FIS, 24);
2300 KdPrint2(("PIO:\n"));
2301 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2303 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2304 if(!AHCI_CL->bytecount) {
2305 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2309 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2310 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2311 if(CI
& (1 << tag
)) {
2313 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2314 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2317 UniataDumpAhciPortRegs(chan
);
2319 if(!UniataAhciAbortOperation(chan
)) {
2320 KdPrint2((" Abort failed, need RESET\n"));
2323 UniataDumpAhciPortRegs(chan
);
2325 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2326 if(chan
->AhciPrevCI
) {
2327 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2330 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2331 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2337 } // end UniataAhciEndTransaction()
2347 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2350 //UniataDumpAhciPortRegs(chan);
2353 /* Disable port interrupts */
2354 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2356 /* setup work areas */
2357 base
= chan
->AHCI_CTL_PhAddr
;
2359 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2362 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2363 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2364 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2366 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2367 (ULONG
)(base
& 0xffffffff));
2368 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2369 (ULONG
)((base
>> 32) & 0xffffffff));
2371 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2372 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2373 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2374 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2376 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2377 (ULONG
)(base
& 0xffffffff));
2378 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2379 (ULONG
)((base
>> 32) & 0xffffffff));
2381 /* activate the channel and power/spin up device */
2382 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2383 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2384 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2385 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2387 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2390 //UniataDumpAhciPortRegs(chan);
2393 UniataAhciStartFR(chan
);
2394 UniataAhciStart(chan
);
2397 UniataDumpAhciPortRegs(chan
);
2401 } // end UniataAhciResume()
2411 SATA_SCONTROL_REG SControl
;
2413 KdPrint2(("UniataAhciSuspend:\n"));
2415 /* Disable port interrupts */
2416 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2418 /* Reset command register. */
2419 UniataAhciStop(chan
);
2420 UniataAhciStopFR(chan
);
2421 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2422 UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
); /* flush */
2424 /* Allow everything including partial and slumber modes. */
2425 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2427 /* Request slumber mode transition and give some time to get there. */
2428 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2429 AtapiStallExecution(100);
2433 SControl
.DET
= SStatus_DET_Offline
;
2434 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2437 } // end UniataAhciSuspend()
2443 IN PHW_CHANNEL chan
,
2444 IN ULONG DeviceNumber
,
2449 //ULONG Channel = deviceExtension->Channel + lChannel;
2454 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2455 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2457 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2459 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2460 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2463 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2465 case IDX_SATA_SStatus
:
2467 case IDX_SATA_SError
:
2469 case IDX_SATA_SControl
:
2476 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2477 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2478 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2479 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2480 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2481 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2482 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2484 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2485 KdPrint2((" PM read failed\n"));
2489 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2491 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2494 } // end UniataAhciReadPM()
2499 IN PHW_CHANNEL chan
,
2500 IN ULONG DeviceNumber
,
2505 //ULONG Channel = deviceExtension->Channel + lChannel;
2511 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2512 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2514 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2516 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2517 UniataSataWritePort4(chan
, Reg
, value
, 0);
2520 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2522 case IDX_SATA_SStatus
:
2524 case IDX_SATA_SError
:
2526 case IDX_SATA_SControl
:
2529 return IDE_STATUS_WRONG
;
2533 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2534 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2535 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2536 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2537 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2538 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2540 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2541 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2542 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2543 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2545 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2547 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2548 KdPrint2((" PM write failed\n"));
2549 return IDE_STATUS_WRONG
;
2552 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2554 if(TFD
& IDE_STATUS_ERROR
) {
2555 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2557 return (UCHAR
)(TFD
>> 8);
2559 } // end UniataAhciWritePM()
2562 UniataAhciSetupCmdPtr(
2563 IN OUT PATA_REQ AtaReq
2568 ULONGLONG prd_base64
;
2572 ULONGLONG prd_base64_0
;
2578 prd_base64_0
= prd_base64
= 0;
2579 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2580 prd_base0
= prd_base
;
2582 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2585 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2586 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2589 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2590 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2591 } // end UniataAhciSetupCmdPtr()
2595 BuildAhciInternalSrb (
2596 IN PVOID HwDeviceExtension
,
2597 IN ULONG DeviceNumber
,
2603 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2604 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2605 PSCSI_REQUEST_BLOCK srb
;
2607 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2609 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2612 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2616 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2617 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2618 UniAtaClearAtaReq(AtaReq
);
2620 srb
= chan
->AhciInternalSrb
;
2622 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2624 srb
->PathId
= (UCHAR
)lChannel
;
2625 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2626 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2627 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2629 // Set flags to disable synchronous negociation.
2630 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2632 // Set timeout to 4 seconds.
2633 srb
->TimeOutValue
= 4;
2636 srb
->DataBuffer
= Buffer
;
2637 srb
->DataTransferLength
= Length
;
2638 srb
->SrbExtension
= AtaReq
;
2641 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2642 AtaReq
->TransferLength
= Length
;
2644 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2645 //UniataAhciSetupCmdPtr(AtaReq);
2646 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2647 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2649 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2650 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2652 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2653 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2655 /* // Set CDB operation code.
2656 cdb = (PCDB)srb->Cdb;
2657 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2658 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2661 } // end BuildAhciInternalSrb()