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
));
764 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
765 if(CAP2
& AHCI_CAP2_BOH
) {
766 KdPrint2((PRINT_PREFIX
" retry BOHC\n"));
767 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
768 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
769 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
770 BOHC
| AHCI_BOHC_OOS
);
772 /* clear interrupts */
773 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
774 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
776 /* enable AHCI interrupts */
777 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
778 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
780 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
781 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
783 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
784 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
786 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
787 chan
= &deviceExtension
->chan
[c
];
788 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
790 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
792 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
794 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
796 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
797 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
799 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
800 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
801 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
802 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
803 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
804 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
805 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
806 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
807 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
808 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
809 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
811 UniataInitSyncBaseIO(chan
);
813 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
814 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
815 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
816 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
817 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
818 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
819 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
820 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
822 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
824 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
825 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
829 UniataAhciResume(chan
);
831 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
835 } // end UniataAhciInit()
839 UniAtaAhciValidateVersion(
840 IN PHW_DEVICE_EXTENSION deviceExtension
,
848 KdPrint((" wrong AHCI revision %#x\n", version
));
857 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
858 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
859 KdPrint((" AHCI revision excluded\n"));
864 } // end UniAtaAhciValidateVersion()
869 IN PVOID HwDeviceExtension
,
870 IN PPCI_COMMON_CONFIG pciData
, // optional
871 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
874 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
875 //ULONG slotNumber = deviceExtension->slotNumber;
876 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
887 ULONG NumberChannels
;
888 ULONG BaseMemAddress
;
889 BOOLEAN MemIo
= FALSE
;
890 BOOLEAN found
= FALSE
;
892 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
894 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
895 KdPrint((" AHCI excluded\n"));
898 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
900 if(!BaseMemAddress
) {
901 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
904 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
905 KdPrint2((PRINT_PREFIX
"MemIo\n"));
908 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
909 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
912 UniataDumpAhciRegs(deviceExtension
);
915 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
916 if(GHC
& AHCI_GHC_HR
) {
917 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
921 /* check AHCI mode. Save state and try enable */
923 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
924 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
926 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
928 if(!(GHC
& AHCI_GHC_AE
)) {
929 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
930 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
931 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
934 KdPrint2((PRINT_PREFIX
" try enable\n"));
935 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
936 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
937 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
939 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
940 if(!(GHC
& AHCI_GHC_AE
)) {
941 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
946 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
947 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
948 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
949 if(CAP
& AHCI_CAP_S64A
) {
950 KdPrint2((PRINT_PREFIX
" 64bit"));
951 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
954 if(CAP2
& AHCI_CAP2_BOH
) {
955 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
956 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
959 if(CAP
& AHCI_CAP_NCQ
) {
960 KdPrint2((PRINT_PREFIX
" NCQ"));
962 if(CAP
& AHCI_CAP_SNTF
) {
963 KdPrint2((PRINT_PREFIX
" SNTF"));
965 if(CAP
& AHCI_CAP_CCC
) {
966 KdPrint2((PRINT_PREFIX
" CCC"));
968 KdPrint2((PRINT_PREFIX
"\n"));
970 /* get the number of HW channels */
971 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
972 deviceExtension
->AHCI_PI
= PI
;
973 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
974 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
976 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
978 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
979 KdPrint2((PRINT_PREFIX
" Detected Channels %d / %d\n", NumberChannels
, n
));
981 switch(deviceExtension
->DevID
) {
983 KdPrint2((PRINT_PREFIX
" Marvell M88SE6111 -> 1\n"));
987 KdPrint2((PRINT_PREFIX
" Marvell M88SE6121 -> 2\n"));
988 NumberChannels
= min(NumberChannels
, 2);
993 KdPrint2((PRINT_PREFIX
" Marvell M88SE614x/9123 -> 4\n"));
994 NumberChannels
= min(NumberChannels
, 4);
998 if(!NumberChannels
) {
999 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
1003 KdPrint2((PRINT_PREFIX
" Adjusted Channels %d\n", NumberChannels
));
1006 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
1007 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
1009 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
1011 NumberChannels
, PI
));
1012 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
1015 if(CAP
& AHCI_CAP_SPM
) {
1016 KdPrint2((PRINT_PREFIX
" PM supported\n"));
1017 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
1018 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
1019 deviceExtension
->NumberLuns
= 1;
1020 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
1022 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
1023 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
1024 //deviceExtension->NumberLuns = 1;
1027 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
1028 deviceExtension
->NumberLuns
= 1;
1031 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
1035 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
1036 if(deviceExtension
->NumberChannels
< NumberChannels
) {
1037 deviceExtension
->NumberChannels
= NumberChannels
;
1039 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
1040 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
1042 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
1043 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
1048 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
1049 KdPrint((" AHCI detect status %d\n", found
));
1052 } // end UniataAhciDetect()
1057 IN PVOID HwDeviceExtension
,
1059 IN ULONG DeviceNumber
1062 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1063 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1064 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1068 SATA_SSTATUS_REG SStatus
;
1069 SATA_SERROR_REG SError
;
1070 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1073 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1075 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1076 KdPrint((" hIS %#x\n", hIS
));
1077 hIS
&= (1 << Channel
);
1079 return INTERRUPT_REASON_IGNORE
;
1081 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1082 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1083 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1084 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1085 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1087 /* clear interrupt(s) */
1088 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1089 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1090 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1092 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1093 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1095 /* do we have cold connect surprise */
1099 /* check for and handle connect events */
1101 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1104 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1106 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1107 chan
->AhciPrevCI
= CI
;
1108 chan
->AhciLastSError
= SError
.Reg
;
1109 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1110 chan
->AhciLastIS
= IS
.Reg
;
1111 if(CI
& (1 << tag
)) {
1113 UniataDumpAhciPortRegs(chan
);
1115 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1117 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1118 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1119 KdPrint((" AHCI: unexpected, error\n"));
1121 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1125 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1126 KdPrint2((" TFD %#x\n", TFD));
1127 if(TFD & IDE_STATUS_BUSY) {
1128 KdPrint2((" Seems to be interrupt on error\n"));
1129 return INTERRUPT_REASON_OUR;
1132 return INTERRUPT_REASON_UNEXPECTED
;
1135 return INTERRUPT_REASON_OUR
;
1137 } // end UniataAhciStatus()
1141 UniataAhciSnapAtaRegs(
1142 IN PHW_CHANNEL chan
,
1143 IN ULONG DeviceNumber
,
1144 IN OUT PIDEREGS_EX regs
1149 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1150 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1151 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1152 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1154 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1155 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1156 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1157 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1158 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1162 } // end UniataAhciSnapAtaRegs()
1166 UniataAhciSetupFIS_H2D(
1167 IN PHW_DEVICE_EXTENSION deviceExtension
,
1168 IN ULONG DeviceNumber
,
1180 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1182 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1184 plba
= (PUCHAR
)&lba
;
1186 RtlZeroMemory(fis
, 20);
1188 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1189 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1190 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1191 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1192 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1194 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1195 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1196 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1198 command
== IDE_COMMAND_ATAPI_PACKET
) {
1199 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1200 if(feature
& ATA_F_DMA
) {
1201 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1203 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1204 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1206 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1209 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1210 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1211 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1212 //return IDE_STATUS_ERROR;
1213 //return SRB_STATUS_ERROR;
1217 need48
= UniAta_need_lba48(command
, lba
, count
,
1218 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1220 /* translate command into 48bit version */
1222 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1223 command
= AtaCommands48
[command
];
1225 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1230 fis
[IDX_AHCI_o_Command
] = command
;
1231 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1233 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1234 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1235 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1237 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1241 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1243 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1244 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1245 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1247 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1249 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1251 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1254 //#pragma warning(push)
1255 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1257 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1258 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1260 //#pragma warning(pop)
1271 } // end UniataAhciSetupFIS_H2D()
1275 UniataAhciSetupFIS_H2D_Direct(
1276 IN PHW_DEVICE_EXTENSION deviceExtension
,
1277 IN ULONG DeviceNumber
,
1286 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1289 command
= regs
->bCommandReg
;
1291 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1293 //plba = (PUCHAR)&lba;
1295 RtlZeroMemory(fis
, 20);
1297 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1298 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1299 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1300 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1301 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1303 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1304 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1305 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1307 command
== IDE_COMMAND_ATAPI_PACKET
) {
1308 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1309 if(feature & ATA_F_DMA) {
1310 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1312 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1313 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1316 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1319 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1320 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1322 /* translate command into 48bit version */
1324 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1325 command
= AtaCommands48
[command
];
1327 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1332 fis
[IDX_AHCI_o_Command
] = command
;
1333 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1335 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1336 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1337 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1339 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1343 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1345 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1346 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1347 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1349 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1351 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1353 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1355 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1356 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1358 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1364 } // end UniataAhciSetupFIS_H2D_Direct()
1368 UniataAhciWaitCommandReady(
1369 IN PHW_CHANNEL chan
,
1382 for (i
=0; i
<timeout
; i
++) {
1383 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1384 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1385 if (!(( CI
>> tag
) & 0x01)) {
1388 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1389 //KdPrint((" IS %#x\n", IS.Reg));
1393 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1395 KdPrint((" AHCI: error %#x\n", SError
));
1399 AtapiStallExecution(200);
1401 KdPrint((" CI %#x\n", CI
));
1403 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1404 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1406 /* clear interrupt(s) */
1407 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1408 KdPrint((" IS %#x\n", IS
.Reg
));
1409 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1411 if (timeout
&& (i
>= timeout
)) {
1415 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1416 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1418 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1419 KdPrint2((" TFD %#x\n", TFD
));
1422 return IDE_STATUS_WRONG
;
1425 return IDE_STATUS_IDLE
;
1426 } // end UniataAhciWaitCommandReady()
1430 UniataAhciSendCommand(
1431 IN PVOID HwDeviceExtension
,
1433 IN ULONG DeviceNumber
,
1434 IN USHORT ahci_flags
,
1438 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1439 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1440 //ULONG Channel = deviceExtension->Channel + lChannel;
1443 //SATA_SSTATUS_REG SStatus;
1444 //SATA_SERROR_REG SError;
1445 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1449 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1451 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1453 AHCI_CL
->prd_length
= 0;
1454 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1455 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1457 AHCI_CL
->bytecount
= 0;
1458 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1459 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1460 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1463 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1464 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1466 return UniataAhciWaitCommandReady(chan
, timeout
);
1468 } // end UniataAhciSendCommand()
1472 UniataAhciSendPIOCommand(
1473 IN PVOID HwDeviceExtension
,
1475 IN ULONG DeviceNumber
,
1476 IN PSCSI_REQUEST_BLOCK Srb
,
1478 IN ULONG length
, /* bytes */
1481 IN USHORT bcount
, /* block count, just ATA register */
1483 IN USHORT ahci_flags
,
1484 IN ULONG wait_flags
,
1488 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1489 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1494 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1495 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1497 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1499 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1500 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1502 if(length
/DEV_BSIZE
!= bcount
) {
1503 KdPrint((" length/DEV_BSIZE != bcount\n"));
1507 //UniataDumpAhciPortRegs(chan);
1511 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1513 KdPrint((" !Srb\n"));
1514 return IDE_STATUS_WRONG
;
1516 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1517 //should be already called on init
1519 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1520 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1522 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1524 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1525 &(AHCI_CMD
->cfis
[0]),
1533 KdPrint2(("!fis_size\n"));
1534 return IDE_STATUS_WRONG
;
1537 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1538 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1539 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1542 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1543 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1544 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1545 KdPrint((" assume OUT\n"));
1547 AtaReq
->Flags
|= REQ_FLAG_READ
;
1548 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1549 KdPrint((" assume IN\n"));
1551 if(!AtapiDmaSetup(HwDeviceExtension
,
1553 lChannel
, // logical channel,
1557 KdPrint2((" can't setup buffer\n"));
1558 return IDE_STATUS_WRONG
;
1562 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1565 //UniataDumpAhciPortRegs(chan);
1568 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1571 //UniataDumpAhciPortRegs(chan);
1574 if(wait_flags
== ATA_IMMEDIATE
) {
1576 KdPrint2((" return imemdiately\n"));
1578 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1579 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1580 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1585 } // end UniataAhciSendPIOCommand()
1589 UniataAhciSendPIOCommandDirect(
1590 IN PVOID HwDeviceExtension
,
1592 IN ULONG DeviceNumber
,
1593 IN PSCSI_REQUEST_BLOCK Srb
,
1594 IN PIDEREGS_EX regs
,
1595 IN ULONG wait_flags
,
1599 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1600 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1605 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1606 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1607 USHORT ahci_flags
=0;
1610 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1612 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1613 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1615 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1616 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1620 //UniataDumpAhciPortRegs(chan);
1624 KdPrint((" !Srb\n"));
1625 return IDE_STATUS_WRONG
;
1626 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1627 //should be already called on init
1629 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1630 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1632 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1634 KdPrint((" !AHCI_CMD\n"));
1635 return IDE_STATUS_WRONG
;
1638 if(Srb
->DataTransferLength
) {
1639 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1640 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1641 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1643 AtaReq
->Flags
|= REQ_FLAG_READ
;
1647 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1648 &(AHCI_CMD
->cfis
[0]),
1652 KdPrint2(("!fis_size\n"));
1653 return IDE_STATUS_WRONG
;
1656 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1657 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1658 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1660 if(Srb
->DataTransferLength
) {
1661 if(!AtapiDmaSetup(HwDeviceExtension
,
1663 lChannel
, // logical channel,
1665 (PUCHAR
)(Srb
->DataBuffer
),
1666 Srb
->DataTransferLength
)) {
1667 KdPrint2((" can't setup buffer\n"));
1668 return IDE_STATUS_WRONG
;
1672 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1675 //UniataDumpAhciPortRegs(chan);
1678 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1681 //UniataDumpAhciPortRegs(chan);
1684 if(wait_flags
== ATA_IMMEDIATE
) {
1686 KdPrint2((" return imemdiately\n"));
1688 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1689 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1690 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1695 } // end UniataAhciSendPIOCommandDirect()
1699 UniataAhciAbortOperation(
1703 /* kick controller into sane state */
1704 if(!UniataAhciStop(chan
)) {
1707 if(!UniataAhciStopFR(chan
)) {
1710 if(!UniataAhciCLO(chan
)) {
1713 UniataAhciStartFR(chan
);
1714 UniataAhciStart(chan
);
1717 } // end UniataAhciAbortOperation()
1721 UniataAhciSoftReset(
1722 IN PVOID HwDeviceExtension
,
1724 IN ULONG DeviceNumber
1727 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1728 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1729 //ULONG Channel = deviceExtension->Channel + lChannel;
1735 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1737 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1738 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1740 /* kick controller into sane state */
1741 if(!UniataAhciAbortOperation(chan
)) {
1742 KdPrint2((" abort failed\n"));
1746 /* pull reset active */
1747 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1748 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1749 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1750 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1751 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1753 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1754 KdPrint2((" timeout\n"));
1757 AtapiStallExecution(50);
1759 /* pull reset inactive */
1760 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1761 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1762 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1763 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1764 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1765 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1766 KdPrint2((" timeout (2)\n"));
1770 UniataAhciWaitReady(chan
, 1);
1772 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1774 return UniataAhciUlongFromRFIS(RCV_FIS
);
1776 } // end UniataAhciSoftReset()
1780 UniataAhciWaitReady(
1781 IN PHW_CHANNEL chan
,
1788 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1790 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1792 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1793 for(i
=0; i
<timeout
&& (TFD
&
1794 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1795 AtapiStallExecution(1000);
1796 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1799 KdPrint2((" TFD %#x\n", TFD
));
1803 } // end UniataAhciWaitReady()
1807 UniataAhciHardReset(
1808 IN PVOID HwDeviceExtension
,
1810 OUT PULONG signature
1813 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1814 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1815 //ULONG Channel = deviceExtension->Channel + lChannel;
1819 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1821 (*signature
) = 0xffffffff;
1823 UniataAhciStop(chan
);
1824 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1825 KdPrint((" no PHY\n"));
1826 return IDE_STATUS_WRONG
;
1829 /* Wait for clearing busy status. */
1830 TFD
= UniataAhciWaitReady(chan
, 15000);
1831 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1832 KdPrint((" busy: TFD %#x\n", TFD
));
1835 KdPrint((" TFD %#x\n", TFD
));
1838 UniataDumpAhciPortRegs(chan
);
1841 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1842 KdPrint((" sig: %#x\n", *signature
));
1844 UniataAhciStart(chan
);
1848 } // end UniataAhciHardReset()
1853 IN PVOID HwDeviceExtension
,
1857 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1858 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1859 //ULONG Channel = deviceExtension->Channel + lChannel;
1860 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1865 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1867 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1869 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1871 /* Disable port interrupts */
1872 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1874 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1876 KdPrint((" No devices in all LUNs\n"));
1877 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1878 // Zero device fields to ensure that if earlier devices were found,
1879 // but not claimed, the fields are cleared.
1880 UniataForgetDevice(chan
->lun
[i
]);
1883 /* enable wanted port interrupts */
1884 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1885 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1889 /* enable wanted port interrupts */
1890 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1891 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1892 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1893 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1894 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1895 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1898 * Only probe for PortMultiplier if HW has support.
1899 * Ignore Marvell, which is not working,
1901 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1902 if ((CAP
& AHCI_CAP_SPM
) &&
1903 (VendorID
!= ATA_MARVELL_ID
)) {
1904 KdPrint((" check PM\n"));
1905 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1906 /* Workaround for some ATI chips, failing to soft-reset
1907 * when port multiplicator supported, but absent.
1908 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1909 if (signature
== 0xffffffff) {
1910 KdPrint((" re-check PM\n"));
1911 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1914 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1917 KdPrint((" signature %#x\n", signature
));
1918 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1919 switch (signature
>> 16) {
1921 KdPrint((" ATA dev\n"));
1922 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1927 if(deviceExtension
->NumberLuns
> 1) {
1928 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1929 UniataSataIdentifyPM(chan
);
1931 KdPrint((" no PM supported (1 lun/chan)\n"));
1935 KdPrint((" ATAPI dev\n"));
1936 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1939 default: /* SOS XXX */
1940 KdPrint((" default to ATA ???\n"));
1941 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1947 } // end UniataAhciReset()
1957 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1959 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1960 KdPrint2((" CMD %#x\n", CMD
));
1961 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1964 } // end UniataAhciStartFR()
1975 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
1977 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1978 KdPrint2((" CMD %#x\n", CMD
));
1979 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
1981 for(i
=0; i
<1000; i
++) {
1982 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1983 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
1984 KdPrint2((" final CMD %#x\n", CMD
));
1987 AtapiStallExecution(1000);
1989 KdPrint2((" CMD %#x\n", CMD
));
1990 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
1991 KdPrint2(("UniataAhciStopFR: timeout\n"));
1993 } // end UniataAhciStopFR()
2002 SATA_SERROR_REG SError
;
2004 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
2006 /* clear SATA error register */
2007 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
2009 /* clear any interrupts pending on this channel */
2010 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
2011 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
2013 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
2015 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2016 KdPrint2((" CMD %#x\n", CMD
));
2017 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2020 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
2023 } // end UniataAhciStart()
2031 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2032 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2034 //SATA_SERROR_REG SError;
2037 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
2039 /* issue Command List Override if supported */
2040 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
2041 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
2042 if(!(CAP
& AHCI_CAP_SCLO
)) {
2045 KdPrint2((" send CLO\n"));
2046 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2047 CMD
|= ATA_AHCI_P_CMD_CLO
;
2048 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2050 for(i
=0; i
<1000; i
++) {
2051 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2052 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
2053 KdPrint2((" final CMD %#x\n", CMD
));
2056 AtapiStallExecution(1000);
2058 KdPrint2((" CMD %#x\n", CMD
));
2059 KdPrint2(("UniataAhciCLO: timeout\n"));
2061 } // end UniataAhciCLO()
2070 //SATA_SERROR_REG SError;
2073 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2075 /* issue Command List Override if supported */
2076 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2077 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2078 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2080 for(i
=0; i
<1000; i
++) {
2081 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2082 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2083 KdPrint2((" final CMD %#x\n", CMD
));
2086 AtapiStallExecution(1000);
2088 KdPrint2((" CMD %#x\n", CMD
));
2089 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2090 KdPrint2(("UniataAhciStop: timeout\n"));
2092 } // end UniataAhciStop()
2096 UniataAhciBeginTransaction(
2097 IN PVOID HwDeviceExtension
,
2099 IN ULONG DeviceNumber
,
2100 IN PSCSI_REQUEST_BLOCK Srb
2103 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2104 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2105 //ULONG Channel = deviceExtension->Channel + lChannel;
2109 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2110 //SATA_SSTATUS_REG SStatus;
2111 //SATA_SERROR_REG SError;
2112 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2117 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2119 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2121 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2122 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2126 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2127 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2128 AHCI_CL
->bytecount
= 0;
2129 if(AtaReq
->ahci
.ahci_base64
) {
2130 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2131 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2133 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2134 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2135 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2136 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2137 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2138 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2139 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2141 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2142 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2145 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2146 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2151 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2152 AHCI_CL
->cmd_table_phys
));
2155 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2156 KdPrint2((" CMD %#x\n", CMD
));
2157 // switch controller to ATAPI mode for ATA_PACKET commands only
2158 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2159 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2160 KdPrint2((" ATAPI\n"));
2161 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2162 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2164 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2167 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2168 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2171 /* issue command to controller */
2172 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2173 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2174 chan
->AhciPrevCI
|= 0x01 << tag
;
2176 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2177 // TODO: check if we send ATA_RESET and wait for ready of so.
2178 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2182 for(i
=0; i
<1000000; i
++) {
2183 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2184 if(!(TFD
& IDE_STATUS_BUSY
)) {
2188 if(TFD
& IDE_STATUS_BUSY
) {
2189 KdPrint2((" timeout\n"));
2191 if(TFD
& IDE_STATUS_ERROR
) {
2192 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2194 AtaReq
->ahci
.in_status
= TFD
;
2196 return IDE_STATUS_SUCCESS
;
2200 return IDE_STATUS_IDLE
;
2202 } // end UniataAhciBeginTransaction()
2206 UniataAhciEndTransaction(
2207 IN PVOID HwDeviceExtension
,
2209 IN ULONG DeviceNumber
,
2210 IN PSCSI_REQUEST_BLOCK Srb
2213 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2214 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2215 //ULONG Channel = deviceExtension->Channel + lChannel;
2218 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2220 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2223 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2224 //PHW_LU_EXTENSION LunExt;
2226 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2228 //LunExt = chan->lun[DeviceNumber];
2230 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2231 KdPrint2((" TFD %#x\n", TFD
));
2233 if(TFD
& IDE_STATUS_ERROR
) {
2234 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2235 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2237 AtaReq
->ahci
.in_error
= 0;
2239 AtaReq
->ahci
.in_status
= TFD
;
2241 //if (request->flags & ATA_R_CONTROL) {
2243 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2244 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2245 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2246 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2247 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2248 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2249 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2251 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2252 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2253 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2255 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2257 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2258 KdPrint2(("RCV:\n"));
2259 KdDump(RCV_FIS, 24);
2260 KdPrint2(("PIO:\n"));
2261 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2263 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2264 if(!AHCI_CL->bytecount) {
2265 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2269 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2270 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2271 if(CI
& (1 << tag
)) {
2273 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2274 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2277 UniataDumpAhciPortRegs(chan
);
2279 if(!UniataAhciAbortOperation(chan
)) {
2280 KdPrint2((" Abort failed, need RESET\n"));
2283 UniataDumpAhciPortRegs(chan
);
2285 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2286 if(chan
->AhciPrevCI
) {
2287 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2290 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2291 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2297 } // end UniataAhciEndTransaction()
2307 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2310 //UniataDumpAhciPortRegs(chan);
2313 /* Disable port interrupts */
2314 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2316 /* setup work areas */
2317 base
= chan
->AHCI_CTL_PhAddr
;
2319 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2322 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2323 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2324 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2326 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2327 (ULONG
)(base
& 0xffffffff));
2328 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2329 (ULONG
)((base
>> 32) & 0xffffffff));
2331 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2332 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2333 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2334 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2336 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2337 (ULONG
)(base
& 0xffffffff));
2338 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2339 (ULONG
)((base
>> 32) & 0xffffffff));
2341 /* activate the channel and power/spin up device */
2342 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2343 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2344 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2345 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2349 //UniataDumpAhciPortRegs(chan);
2352 UniataAhciStartFR(chan
);
2353 UniataAhciStart(chan
);
2356 UniataDumpAhciPortRegs(chan
);
2360 } // end UniataAhciResume()
2370 SATA_SCONTROL_REG SControl
;
2372 KdPrint2(("UniataAhciSuspend:\n"));
2374 /* Disable port interrupts */
2375 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2377 /* Reset command register. */
2378 UniataAhciStop(chan
);
2379 UniataAhciStopFR(chan
);
2380 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2382 /* Allow everything including partial and slumber modes. */
2383 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2385 /* Request slumber mode transition and give some time to get there. */
2386 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2387 AtapiStallExecution(100);
2391 SControl
.DET
= SStatus_DET_Offline
;
2392 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2395 } // end UniataAhciSuspend()
2401 IN PHW_CHANNEL chan
,
2402 IN ULONG DeviceNumber
,
2407 //ULONG Channel = deviceExtension->Channel + lChannel;
2412 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2413 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2415 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2417 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2418 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2421 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2423 case IDX_SATA_SStatus
:
2425 case IDX_SATA_SError
:
2427 case IDX_SATA_SControl
:
2434 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2435 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2436 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2437 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2438 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2439 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2440 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2442 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2443 KdPrint2((" PM read failed\n"));
2447 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2449 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2452 } // end UniataAhciReadPM()
2457 IN PHW_CHANNEL chan
,
2458 IN ULONG DeviceNumber
,
2463 //ULONG Channel = deviceExtension->Channel + lChannel;
2469 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2470 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2472 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2474 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2475 UniataSataWritePort4(chan
, Reg
, value
, 0);
2478 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2480 case IDX_SATA_SStatus
:
2482 case IDX_SATA_SError
:
2484 case IDX_SATA_SControl
:
2487 return IDE_STATUS_WRONG
;
2491 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2492 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2493 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2494 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2495 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2496 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2498 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2499 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2500 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2501 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2503 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2505 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2506 KdPrint2((" PM write failed\n"));
2507 return IDE_STATUS_WRONG
;
2510 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2512 if(TFD
& IDE_STATUS_ERROR
) {
2513 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2515 return (UCHAR
)(TFD
>> 8);
2517 } // end UniataAhciWritePM()
2520 UniataAhciSetupCmdPtr(
2521 IN OUT PATA_REQ AtaReq
2526 ULONGLONG prd_base64
;
2530 ULONGLONG prd_base64_0
;
2536 prd_base64_0
= prd_base64
= 0;
2537 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2538 prd_base0
= prd_base
;
2540 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2543 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2544 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2547 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2548 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2549 } // end UniataAhciSetupCmdPtr()
2553 BuildAhciInternalSrb (
2554 IN PVOID HwDeviceExtension
,
2555 IN ULONG DeviceNumber
,
2561 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2562 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2563 PSCSI_REQUEST_BLOCK srb
;
2565 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2567 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2570 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2574 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2575 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2576 UniAtaClearAtaReq(AtaReq
);
2578 srb
= chan
->AhciInternalSrb
;
2580 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2582 srb
->PathId
= (UCHAR
)lChannel
;
2583 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2584 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2585 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2587 // Set flags to disable synchronous negociation.
2588 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2590 // Set timeout to 4 seconds.
2591 srb
->TimeOutValue
= 4;
2594 srb
->DataBuffer
= Buffer
;
2595 srb
->DataTransferLength
= Length
;
2596 srb
->SrbExtension
= AtaReq
;
2599 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2600 AtaReq
->TransferLength
= Length
;
2602 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2603 //UniataAhciSetupCmdPtr(AtaReq);
2604 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2605 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2607 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2608 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2610 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2611 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2613 /* // Set CDB operation code.
2614 cdb = (PCDB)srb->Cdb;
2615 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2616 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2619 } // end BuildAhciInternalSrb()