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 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
732 if(!(GHC
& AHCI_GHC_AE
)) {
733 KdPrint2((PRINT_PREFIX
" re-enable AHCI mode, GHC %#x\n", GHC
));
734 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
736 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
738 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
739 if(!(GHC
& AHCI_GHC_AE
)) {
740 KdPrint2((PRINT_PREFIX
" Can't enable AHCI mode\n"));
744 deviceExtension
->AHCI_CAP
=
745 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
746 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
747 if(CAP
& AHCI_CAP_S64A
) {
748 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
749 deviceExtension
->Host64
= TRUE
;
751 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
752 if(CAP
& AHCI_CAP_PMD
) {
753 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
755 if(CAP
& AHCI_CAP_SAM
) {
756 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
759 /* get the number of HW channels */
760 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
761 deviceExtension
->AHCI_PI
= PI
;
762 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
763 KdPrint2((PRINT_PREFIX
" AHCI PI mask %#x\n", deviceExtension
->AHCI_PI_mask
));
764 deviceExtension
->AHCI_PI
= PI
= PI
& deviceExtension
->AHCI_PI_mask
;
765 KdPrint2((PRINT_PREFIX
" masked AHCI PI %#x\n", PI
));
767 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
768 if(CAP2
& AHCI_CAP2_BOH
) {
769 KdPrint2((PRINT_PREFIX
" retry BOHC\n"));
770 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
771 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
772 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
773 BOHC
| AHCI_BOHC_OOS
);
775 /* clear interrupts */
776 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
777 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
779 /* enable AHCI interrupts */
780 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
781 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
783 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
784 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
786 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
787 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
789 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
790 chan
= &deviceExtension
->chan
[c
];
791 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
793 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
795 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
797 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
799 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
800 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
802 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
803 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
804 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
805 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
806 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
807 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
808 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
809 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
810 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
811 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
812 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
814 UniataInitSyncBaseIO(chan
);
816 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
817 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
818 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
819 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
820 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
821 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
822 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
823 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
825 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
827 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
828 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
832 UniataAhciResume(chan
);
834 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
838 } // end UniataAhciInit()
842 UniAtaAhciValidateVersion(
843 IN PHW_DEVICE_EXTENSION deviceExtension
,
851 KdPrint((" wrong AHCI revision %#x\n", version
));
860 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
861 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
862 KdPrint((" AHCI revision excluded\n"));
867 } // end UniAtaAhciValidateVersion()
872 IN PVOID HwDeviceExtension
,
873 IN PPCI_COMMON_CONFIG pciData
, // optional
874 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
877 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
878 //ULONG slotNumber = deviceExtension->slotNumber;
879 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
890 ULONG NumberChannels
;
891 ULONG BaseMemAddress
;
892 BOOLEAN MemIo
= FALSE
;
893 BOOLEAN found
= FALSE
;
895 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
897 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
898 KdPrint((" AHCI excluded\n"));
901 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
903 if(!BaseMemAddress
) {
904 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
907 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
908 KdPrint2((PRINT_PREFIX
"MemIo\n"));
911 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
912 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
915 UniataDumpAhciRegs(deviceExtension
);
918 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
919 if(GHC
& AHCI_GHC_HR
) {
920 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
924 /* check AHCI mode. Save state and try enable */
926 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
927 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
929 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
931 if(!(GHC
& AHCI_GHC_AE
)) {
932 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
933 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
934 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
937 KdPrint2((PRINT_PREFIX
" try enable\n"));
938 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
939 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
940 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
942 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
943 if(!(GHC
& AHCI_GHC_AE
)) {
944 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
949 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
950 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
951 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
952 if(CAP
& AHCI_CAP_S64A
) {
953 KdPrint2((PRINT_PREFIX
" 64bit"));
954 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
957 if(CAP2
& AHCI_CAP2_BOH
) {
958 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
959 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
962 if(CAP
& AHCI_CAP_NCQ
) {
963 KdPrint2((PRINT_PREFIX
" NCQ"));
965 if(CAP
& AHCI_CAP_SNTF
) {
966 KdPrint2((PRINT_PREFIX
" SNTF"));
968 if(CAP
& AHCI_CAP_CCC
) {
969 KdPrint2((PRINT_PREFIX
" CCC"));
971 KdPrint2((PRINT_PREFIX
"\n"));
973 /* get the number of HW channels */
975 /* CAP.NOP sometimes indicate the index of the last enabled
976 * port, at other times, that of the last possible port, so
977 * determining the maximum port number requires looking at
978 * both CAP.NOP and PI.
980 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
981 deviceExtension
->AHCI_PI
= deviceExtension
->AHCI_PI_mask
= PI
;
982 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
984 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1) {
985 if(AtapiRegCheckDevValue(deviceExtension
, n
, DEVNUM_NOT_SPECIFIED
, L
"Exclude", 0)) {
986 KdPrint2((PRINT_PREFIX
"Channel %d excluded\n", n
));
987 deviceExtension
->AHCI_PI
&= ~((ULONG
)1 << n
);
988 deviceExtension
->AHCI_PI_mask
&= ~((ULONG
)1 << n
);
991 deviceExtension
->AHCI_PI_mask
=
992 AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PortMask", deviceExtension
->AHCI_PI_mask
);
993 KdPrint2((PRINT_PREFIX
"Force PortMask %#x\n", deviceExtension
->AHCI_PI_mask
));
995 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
997 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
999 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
1000 KdPrint2((PRINT_PREFIX
" Detected Channels %d / %d\n", NumberChannels
, n
));
1002 switch(deviceExtension
->DevID
) {
1004 KdPrint2((PRINT_PREFIX
" Marvell M88SE6111 -> 1\n"));
1008 KdPrint2((PRINT_PREFIX
" Marvell M88SE6121 -> 2\n"));
1009 NumberChannels
= min(NumberChannels
, 2);
1014 KdPrint2((PRINT_PREFIX
" Marvell M88SE614x/9123 -> 4\n"));
1015 NumberChannels
= min(NumberChannels
, 4);
1019 if(!NumberChannels
) {
1020 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
1024 KdPrint2((PRINT_PREFIX
" Adjusted Channels %d\n", NumberChannels
));
1027 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
1028 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
1030 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
1032 NumberChannels
, PI
));
1033 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
1036 if(CAP
& AHCI_CAP_SPM
) {
1037 KdPrint2((PRINT_PREFIX
" PM supported\n"));
1038 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
1039 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
1040 deviceExtension
->NumberLuns
= 1;
1041 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
1043 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
1044 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
1045 //deviceExtension->NumberLuns = 1;
1048 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
1049 deviceExtension
->NumberLuns
= 1;
1052 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
1056 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
1057 if(deviceExtension
->NumberChannels
< NumberChannels
) {
1058 deviceExtension
->NumberChannels
= NumberChannels
;
1060 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
1061 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
1063 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
1064 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
1069 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
1070 KdPrint((" AHCI detect status %d\n", found
));
1073 } // end UniataAhciDetect()
1078 IN PVOID HwDeviceExtension
,
1080 IN ULONG DeviceNumber
1083 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1084 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1085 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1089 SATA_SSTATUS_REG SStatus
;
1090 SATA_SERROR_REG SError
;
1091 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1094 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1096 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1097 KdPrint((" hIS %#x\n", hIS
));
1098 hIS
&= (1 << Channel
);
1100 return INTERRUPT_REASON_IGNORE
;
1102 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1103 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1104 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1105 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1106 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1108 /* clear interrupt(s) */
1109 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1110 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1111 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1113 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1114 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1116 /* do we have cold connect surprise */
1120 /* check for and handle connect events */
1122 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1125 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1127 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1128 chan
->AhciPrevCI
= CI
;
1129 chan
->AhciLastSError
= SError
.Reg
;
1130 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1131 chan
->AhciLastIS
= IS
.Reg
;
1132 if(CI
& (1 << tag
)) {
1134 UniataDumpAhciPortRegs(chan
);
1136 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1138 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1139 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1140 KdPrint((" AHCI: unexpected, error\n"));
1142 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1146 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1147 KdPrint2((" TFD %#x\n", TFD));
1148 if(TFD & IDE_STATUS_BUSY) {
1149 KdPrint2((" Seems to be interrupt on error\n"));
1150 return INTERRUPT_REASON_OUR;
1153 return INTERRUPT_REASON_UNEXPECTED
;
1156 return INTERRUPT_REASON_OUR
;
1158 } // end UniataAhciStatus()
1162 UniataAhciSnapAtaRegs(
1163 IN PHW_CHANNEL chan
,
1164 IN ULONG DeviceNumber
,
1165 IN OUT PIDEREGS_EX regs
1170 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1171 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1172 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1173 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1175 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1176 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1177 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1178 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1179 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1183 } // end UniataAhciSnapAtaRegs()
1187 UniataAhciSetupFIS_H2D(
1188 IN PHW_DEVICE_EXTENSION deviceExtension
,
1189 IN ULONG DeviceNumber
,
1201 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1203 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1205 plba
= (PUCHAR
)&lba
;
1207 RtlZeroMemory(fis
, 20);
1209 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1210 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1211 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1212 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1213 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1215 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1216 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1217 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1219 command
== IDE_COMMAND_ATAPI_PACKET
) {
1220 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1221 if(feature
& ATA_F_DMA
) {
1222 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1224 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1225 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1227 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1230 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1231 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1232 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1233 //return IDE_STATUS_ERROR;
1234 //return SRB_STATUS_ERROR;
1238 need48
= UniAta_need_lba48(command
, lba
, count
,
1239 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1241 /* translate command into 48bit version */
1243 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1244 command
= AtaCommands48
[command
];
1246 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1251 fis
[IDX_AHCI_o_Command
] = command
;
1252 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1254 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1255 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1256 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1258 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1262 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1264 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1265 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1266 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1268 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1270 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1272 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1275 //#pragma warning(push)
1276 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1278 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1279 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1281 //#pragma warning(pop)
1292 } // end UniataAhciSetupFIS_H2D()
1296 UniataAhciSetupFIS_H2D_Direct(
1297 IN PHW_DEVICE_EXTENSION deviceExtension
,
1298 IN ULONG DeviceNumber
,
1307 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1310 command
= regs
->bCommandReg
;
1312 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1314 //plba = (PUCHAR)&lba;
1316 RtlZeroMemory(fis
, 20);
1318 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1319 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1320 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1321 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1322 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1324 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1325 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1326 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1328 command
== IDE_COMMAND_ATAPI_PACKET
) {
1329 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1330 if(feature & ATA_F_DMA) {
1331 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1333 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1334 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1337 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1340 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1341 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1343 /* translate command into 48bit version */
1345 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1346 command
= AtaCommands48
[command
];
1348 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1353 fis
[IDX_AHCI_o_Command
] = command
;
1354 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1356 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1357 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1358 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1360 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1364 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1366 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1367 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1368 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1370 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1372 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1374 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1376 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1377 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1379 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1385 } // end UniataAhciSetupFIS_H2D_Direct()
1389 UniataAhciWaitCommandReady(
1390 IN PHW_CHANNEL chan
,
1403 for (i
=0; i
<timeout
; i
++) {
1404 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1405 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1406 if (!(( CI
>> tag
) & 0x01)) {
1409 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1410 //KdPrint((" IS %#x\n", IS.Reg));
1414 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1416 KdPrint((" AHCI: error %#x\n", SError
));
1420 AtapiStallExecution(200);
1422 KdPrint((" CI %#x\n", CI
));
1424 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1425 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1427 /* clear interrupt(s) */
1428 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1429 KdPrint((" IS %#x\n", IS
.Reg
));
1430 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1432 if (timeout
&& (i
>= timeout
)) {
1436 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1437 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1439 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1440 KdPrint2((" TFD %#x\n", TFD
));
1443 return IDE_STATUS_WRONG
;
1446 return IDE_STATUS_IDLE
;
1447 } // end UniataAhciWaitCommandReady()
1451 UniataAhciSendCommand(
1452 IN PVOID HwDeviceExtension
,
1454 IN ULONG DeviceNumber
,
1455 IN USHORT ahci_flags
,
1459 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1460 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1461 //ULONG Channel = deviceExtension->Channel + lChannel;
1464 //SATA_SSTATUS_REG SStatus;
1465 //SATA_SERROR_REG SError;
1466 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1470 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1472 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1474 AHCI_CL
->prd_length
= 0;
1475 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1476 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1478 AHCI_CL
->bytecount
= 0;
1479 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1480 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1481 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1484 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1485 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1487 return UniataAhciWaitCommandReady(chan
, timeout
);
1489 } // end UniataAhciSendCommand()
1493 UniataAhciSendPIOCommand(
1494 IN PVOID HwDeviceExtension
,
1496 IN ULONG DeviceNumber
,
1497 IN PSCSI_REQUEST_BLOCK Srb
,
1499 IN ULONG length
, /* bytes */
1502 IN USHORT bcount
, /* block count, just ATA register */
1504 IN USHORT ahci_flags
,
1505 IN ULONG wait_flags
,
1509 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1510 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1515 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1516 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1518 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1520 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1521 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1523 if(length
/DEV_BSIZE
!= bcount
) {
1524 KdPrint((" length/DEV_BSIZE != bcount\n"));
1528 //UniataDumpAhciPortRegs(chan);
1532 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1534 KdPrint((" !Srb\n"));
1535 return IDE_STATUS_WRONG
;
1537 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1538 //should be already called on init
1540 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1541 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1543 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1545 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1546 &(AHCI_CMD
->cfis
[0]),
1554 KdPrint2(("!fis_size\n"));
1555 return IDE_STATUS_WRONG
;
1558 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1559 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1560 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1563 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1564 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1565 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1566 KdPrint((" assume OUT\n"));
1568 AtaReq
->Flags
|= REQ_FLAG_READ
;
1569 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1570 KdPrint((" assume IN\n"));
1572 if(!AtapiDmaSetup(HwDeviceExtension
,
1574 lChannel
, // logical channel,
1578 KdPrint2((" can't setup buffer\n"));
1579 return IDE_STATUS_WRONG
;
1583 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1586 //UniataDumpAhciPortRegs(chan);
1589 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1592 //UniataDumpAhciPortRegs(chan);
1595 if(wait_flags
== ATA_IMMEDIATE
) {
1597 KdPrint2((" return imemdiately\n"));
1599 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1600 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1601 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1606 } // end UniataAhciSendPIOCommand()
1610 UniataAhciSendPIOCommandDirect(
1611 IN PVOID HwDeviceExtension
,
1613 IN ULONG DeviceNumber
,
1614 IN PSCSI_REQUEST_BLOCK Srb
,
1615 IN PIDEREGS_EX regs
,
1616 IN ULONG wait_flags
,
1620 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1621 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1626 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1627 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1628 USHORT ahci_flags
=0;
1631 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1633 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1634 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1636 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1637 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1641 //UniataDumpAhciPortRegs(chan);
1645 KdPrint((" !Srb\n"));
1646 return IDE_STATUS_WRONG
;
1647 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1648 //should be already called on init
1650 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1651 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1653 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1655 KdPrint((" !AHCI_CMD\n"));
1656 return IDE_STATUS_WRONG
;
1659 if(Srb
->DataTransferLength
) {
1660 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1661 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1662 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1664 AtaReq
->Flags
|= REQ_FLAG_READ
;
1668 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1669 &(AHCI_CMD
->cfis
[0]),
1673 KdPrint2(("!fis_size\n"));
1674 return IDE_STATUS_WRONG
;
1677 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1678 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1679 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1681 if(Srb
->DataTransferLength
) {
1682 if(!AtapiDmaSetup(HwDeviceExtension
,
1684 lChannel
, // logical channel,
1686 (PUCHAR
)(Srb
->DataBuffer
),
1687 Srb
->DataTransferLength
)) {
1688 KdPrint2((" can't setup buffer\n"));
1689 return IDE_STATUS_WRONG
;
1693 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1696 //UniataDumpAhciPortRegs(chan);
1699 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1702 //UniataDumpAhciPortRegs(chan);
1705 if(wait_flags
== ATA_IMMEDIATE
) {
1707 KdPrint2((" return imemdiately\n"));
1709 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1710 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1711 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1716 } // end UniataAhciSendPIOCommandDirect()
1720 UniataAhciAbortOperation(
1724 /* kick controller into sane state */
1725 if(!UniataAhciStop(chan
)) {
1728 if(!UniataAhciStopFR(chan
)) {
1731 if(!UniataAhciCLO(chan
)) {
1734 UniataAhciStartFR(chan
);
1735 UniataAhciStart(chan
);
1738 } // end UniataAhciAbortOperation()
1742 UniataAhciSoftReset(
1743 IN PVOID HwDeviceExtension
,
1745 IN ULONG DeviceNumber
1748 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1749 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1750 //ULONG Channel = deviceExtension->Channel + lChannel;
1756 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1758 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1759 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1761 /* kick controller into sane state */
1762 if(!UniataAhciAbortOperation(chan
)) {
1763 KdPrint2((" abort failed\n"));
1767 /* pull reset active */
1768 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1769 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1770 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1771 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1772 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1774 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1775 KdPrint2((" timeout\n"));
1778 AtapiStallExecution(50);
1780 /* pull reset inactive */
1781 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1782 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1783 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1784 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1785 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1786 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1787 KdPrint2((" timeout (2)\n"));
1791 UniataAhciWaitReady(chan
, 1);
1793 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1795 return UniataAhciUlongFromRFIS(RCV_FIS
);
1797 } // end UniataAhciSoftReset()
1801 UniataAhciWaitReady(
1802 IN PHW_CHANNEL chan
,
1809 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1811 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1813 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1814 for(i
=0; i
<timeout
&& (TFD
&
1815 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1816 AtapiStallExecution(1000);
1817 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1820 KdPrint2((" TFD %#x\n", TFD
));
1824 } // end UniataAhciWaitReady()
1828 UniataAhciHardReset(
1829 IN PVOID HwDeviceExtension
,
1831 OUT PULONG signature
1834 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1835 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1836 //ULONG Channel = deviceExtension->Channel + lChannel;
1840 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1842 (*signature
) = 0xffffffff;
1844 UniataAhciStop(chan
);
1845 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1846 KdPrint((" no PHY\n"));
1847 return IDE_STATUS_WRONG
;
1850 /* Wait for clearing busy status. */
1851 TFD
= UniataAhciWaitReady(chan
, 15000);
1852 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1853 KdPrint((" busy: TFD %#x\n", TFD
));
1856 KdPrint((" TFD %#x\n", TFD
));
1859 UniataDumpAhciPortRegs(chan
);
1862 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1863 KdPrint((" sig: %#x\n", *signature
));
1865 UniataAhciStart(chan
);
1869 } // end UniataAhciHardReset()
1874 IN PVOID HwDeviceExtension
,
1878 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1879 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1880 //ULONG Channel = deviceExtension->Channel + lChannel;
1881 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1886 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1888 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1890 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1892 /* Disable port interrupts */
1893 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1895 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1897 KdPrint((" No devices in all LUNs\n"));
1898 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1899 // Zero device fields to ensure that if earlier devices were found,
1900 // but not claimed, the fields are cleared.
1901 UniataForgetDevice(chan
->lun
[i
]);
1904 /* enable wanted port interrupts */
1905 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1906 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1910 /* enable wanted port interrupts */
1911 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1912 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1913 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1914 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1915 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1916 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1919 * Only probe for PortMultiplier if HW has support.
1920 * Ignore Marvell, which is not working,
1922 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1923 if ((CAP
& AHCI_CAP_SPM
) &&
1924 (VendorID
!= ATA_MARVELL_ID
)) {
1925 KdPrint((" check PM\n"));
1926 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1927 /* Workaround for some ATI chips, failing to soft-reset
1928 * when port multiplicator supported, but absent.
1929 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1930 if (signature
== 0xffffffff) {
1931 KdPrint((" re-check PM\n"));
1932 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1935 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1938 KdPrint((" signature %#x\n", signature
));
1939 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1940 switch (signature
>> 16) {
1942 KdPrint((" ATA dev\n"));
1943 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1948 if(deviceExtension
->NumberLuns
> 1) {
1949 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1950 UniataSataIdentifyPM(chan
);
1952 KdPrint((" no PM supported (1 lun/chan)\n"));
1956 KdPrint((" ATAPI dev\n"));
1957 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1960 default: /* SOS XXX */
1961 KdPrint((" default to ATA ???\n"));
1962 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1968 } // end UniataAhciReset()
1978 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1980 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1981 KdPrint2((" CMD %#x\n", CMD
));
1982 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1985 } // end UniataAhciStartFR()
1996 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
1998 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1999 KdPrint2((" CMD %#x\n", CMD
));
2000 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
2002 for(i
=0; i
<1000; i
++) {
2003 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2004 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
2005 KdPrint2((" final CMD %#x\n", CMD
));
2008 AtapiStallExecution(1000);
2010 KdPrint2((" CMD %#x\n", CMD
));
2011 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2012 KdPrint2(("UniataAhciStopFR: timeout\n"));
2014 } // end UniataAhciStopFR()
2023 SATA_SERROR_REG SError
;
2025 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
2027 /* clear SATA error register */
2028 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
2030 /* clear any interrupts pending on this channel */
2031 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
2032 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
2034 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
2036 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2037 KdPrint2((" CMD %#x\n", CMD
));
2038 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2041 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
2044 } // end UniataAhciStart()
2052 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2053 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2055 //SATA_SERROR_REG SError;
2058 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
2060 /* issue Command List Override if supported */
2061 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
2062 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
2063 if(!(CAP
& AHCI_CAP_SCLO
)) {
2066 KdPrint2((" send CLO\n"));
2067 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2068 CMD
|= ATA_AHCI_P_CMD_CLO
;
2069 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2071 for(i
=0; i
<1000; i
++) {
2072 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2073 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
2074 KdPrint2((" final CMD %#x\n", CMD
));
2077 AtapiStallExecution(1000);
2079 KdPrint2((" CMD %#x\n", CMD
));
2080 KdPrint2(("UniataAhciCLO: timeout\n"));
2082 } // end UniataAhciCLO()
2091 //SATA_SERROR_REG SError;
2094 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2096 /* issue Command List Override if supported */
2097 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2098 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2099 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2101 for(i
=0; i
<1000; i
++) {
2102 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2103 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2104 KdPrint2((" final CMD %#x\n", CMD
));
2107 AtapiStallExecution(1000);
2109 KdPrint2((" CMD %#x\n", CMD
));
2110 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2111 KdPrint2(("UniataAhciStop: timeout\n"));
2113 } // end UniataAhciStop()
2117 UniataAhciBeginTransaction(
2118 IN PVOID HwDeviceExtension
,
2120 IN ULONG DeviceNumber
,
2121 IN PSCSI_REQUEST_BLOCK Srb
2124 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2125 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2126 //ULONG Channel = deviceExtension->Channel + lChannel;
2130 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2131 //SATA_SSTATUS_REG SStatus;
2132 //SATA_SERROR_REG SError;
2133 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2138 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2140 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2142 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2143 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2147 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2148 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2149 AHCI_CL
->bytecount
= 0;
2150 if(AtaReq
->ahci
.ahci_base64
) {
2151 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2152 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2154 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2155 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2156 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2157 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2158 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2159 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2160 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2162 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2163 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2166 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2167 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2172 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2173 AHCI_CL
->cmd_table_phys
));
2176 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2177 KdPrint2((" CMD %#x\n", CMD
));
2178 // switch controller to ATAPI mode for ATA_PACKET commands only
2179 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2180 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2181 KdPrint2((" ATAPI\n"));
2182 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2183 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2185 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2188 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2189 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2192 /* issue command to controller */
2193 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2194 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2195 chan
->AhciPrevCI
|= 0x01 << tag
;
2197 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2198 // TODO: check if we send ATA_RESET and wait for ready of so.
2199 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2203 for(i
=0; i
<1000000; i
++) {
2204 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2205 if(!(TFD
& IDE_STATUS_BUSY
)) {
2209 if(TFD
& IDE_STATUS_BUSY
) {
2210 KdPrint2((" timeout\n"));
2212 if(TFD
& IDE_STATUS_ERROR
) {
2213 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2215 AtaReq
->ahci
.in_status
= TFD
;
2217 return IDE_STATUS_SUCCESS
;
2221 return IDE_STATUS_IDLE
;
2223 } // end UniataAhciBeginTransaction()
2227 UniataAhciEndTransaction(
2228 IN PVOID HwDeviceExtension
,
2230 IN ULONG DeviceNumber
,
2231 IN PSCSI_REQUEST_BLOCK Srb
2234 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2235 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2236 //ULONG Channel = deviceExtension->Channel + lChannel;
2239 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2241 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2244 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2245 //PHW_LU_EXTENSION LunExt;
2247 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2249 //LunExt = chan->lun[DeviceNumber];
2251 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2252 KdPrint2((" TFD %#x\n", TFD
));
2254 if(TFD
& IDE_STATUS_ERROR
) {
2255 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2256 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2258 AtaReq
->ahci
.in_error
= 0;
2260 AtaReq
->ahci
.in_status
= TFD
;
2262 //if (request->flags & ATA_R_CONTROL) {
2264 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2265 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2266 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2267 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2268 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2269 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2270 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2272 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2273 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2274 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2276 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2278 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2279 KdPrint2(("RCV:\n"));
2280 KdDump(RCV_FIS, 24);
2281 KdPrint2(("PIO:\n"));
2282 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2284 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2285 if(!AHCI_CL->bytecount) {
2286 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2290 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2291 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2292 if(CI
& (1 << tag
)) {
2294 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2295 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2298 UniataDumpAhciPortRegs(chan
);
2300 if(!UniataAhciAbortOperation(chan
)) {
2301 KdPrint2((" Abort failed, need RESET\n"));
2304 UniataDumpAhciPortRegs(chan
);
2306 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2307 if(chan
->AhciPrevCI
) {
2308 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2311 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2312 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2318 } // end UniataAhciEndTransaction()
2328 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2331 //UniataDumpAhciPortRegs(chan);
2334 /* Disable port interrupts */
2335 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2337 /* setup work areas */
2338 base
= chan
->AHCI_CTL_PhAddr
;
2340 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2343 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2344 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2345 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2347 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2348 (ULONG
)(base
& 0xffffffff));
2349 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2350 (ULONG
)((base
>> 32) & 0xffffffff));
2352 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2353 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2354 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2355 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2357 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2358 (ULONG
)(base
& 0xffffffff));
2359 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2360 (ULONG
)((base
>> 32) & 0xffffffff));
2362 /* activate the channel and power/spin up device */
2363 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2364 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2365 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2366 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2370 //UniataDumpAhciPortRegs(chan);
2373 UniataAhciStartFR(chan
);
2374 UniataAhciStart(chan
);
2377 UniataDumpAhciPortRegs(chan
);
2381 } // end UniataAhciResume()
2391 SATA_SCONTROL_REG SControl
;
2393 KdPrint2(("UniataAhciSuspend:\n"));
2395 /* Disable port interrupts */
2396 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2398 /* Reset command register. */
2399 UniataAhciStop(chan
);
2400 UniataAhciStopFR(chan
);
2401 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2403 /* Allow everything including partial and slumber modes. */
2404 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2406 /* Request slumber mode transition and give some time to get there. */
2407 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2408 AtapiStallExecution(100);
2412 SControl
.DET
= SStatus_DET_Offline
;
2413 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2416 } // end UniataAhciSuspend()
2422 IN PHW_CHANNEL chan
,
2423 IN ULONG DeviceNumber
,
2428 //ULONG Channel = deviceExtension->Channel + lChannel;
2433 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2434 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2436 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2438 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2439 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2442 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2444 case IDX_SATA_SStatus
:
2446 case IDX_SATA_SError
:
2448 case IDX_SATA_SControl
:
2455 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2456 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2457 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2458 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2459 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2460 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2461 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2463 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2464 KdPrint2((" PM read failed\n"));
2468 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2470 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2473 } // end UniataAhciReadPM()
2478 IN PHW_CHANNEL chan
,
2479 IN ULONG DeviceNumber
,
2484 //ULONG Channel = deviceExtension->Channel + lChannel;
2490 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2491 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2493 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2495 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2496 UniataSataWritePort4(chan
, Reg
, value
, 0);
2499 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2501 case IDX_SATA_SStatus
:
2503 case IDX_SATA_SError
:
2505 case IDX_SATA_SControl
:
2508 return IDE_STATUS_WRONG
;
2512 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2513 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2514 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2515 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2516 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2517 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2519 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2520 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2521 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2522 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2524 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2526 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2527 KdPrint2((" PM write failed\n"));
2528 return IDE_STATUS_WRONG
;
2531 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2533 if(TFD
& IDE_STATUS_ERROR
) {
2534 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2536 return (UCHAR
)(TFD
>> 8);
2538 } // end UniataAhciWritePM()
2541 UniataAhciSetupCmdPtr(
2542 IN OUT PATA_REQ AtaReq
2547 ULONGLONG prd_base64
;
2551 ULONGLONG prd_base64_0
;
2557 prd_base64_0
= prd_base64
= 0;
2558 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2559 prd_base0
= prd_base
;
2561 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2564 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2565 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2568 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2569 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2570 } // end UniataAhciSetupCmdPtr()
2574 BuildAhciInternalSrb (
2575 IN PVOID HwDeviceExtension
,
2576 IN ULONG DeviceNumber
,
2582 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2583 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2584 PSCSI_REQUEST_BLOCK srb
;
2586 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2588 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2591 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2595 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2596 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2597 UniAtaClearAtaReq(AtaReq
);
2599 srb
= chan
->AhciInternalSrb
;
2601 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2603 srb
->PathId
= (UCHAR
)lChannel
;
2604 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2605 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2606 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2608 // Set flags to disable synchronous negociation.
2609 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2611 // Set timeout to 4 seconds.
2612 srb
->TimeOutValue
= 4;
2615 srb
->DataBuffer
= Buffer
;
2616 srb
->DataTransferLength
= Length
;
2617 srb
->SrbExtension
= AtaReq
;
2620 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2621 AtaReq
->TransferLength
= Length
;
2623 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2624 //UniataAhciSetupCmdPtr(AtaReq);
2625 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2626 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2628 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2629 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2631 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2632 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2634 /* // Set CDB operation code.
2635 cdb = (PCDB)srb->Cdb;
2636 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2637 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2640 } // end BuildAhciInternalSrb()