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
;
655 BOOLEAN MemIo
= FALSE
;
657 KdPrint2((PRINT_PREFIX
" UniataAhciInit:\n"));
660 UniataDumpAhciRegs(deviceExtension
);
663 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
664 if(CAP2
& AHCI_CAP2_BOH
) {
665 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
666 KdPrint2((PRINT_PREFIX
" stage 1 BOHC %#x\n", BOHC
));
667 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
668 BOHC
| AHCI_BOHC_OOS
);
669 for(i
=0; i
<50; i
++) {
670 AtapiStallExecution(500);
671 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
672 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
673 if(BOHC
& AHCI_BOHC_BB
) {
676 if(!(BOHC
& AHCI_BOHC_BOS
)) {
680 KdPrint2((PRINT_PREFIX
" stage 2 BOHC %#x\n", BOHC
));
681 if(BOHC
& AHCI_BOHC_BB
) {
682 for(i
=0; i
<2000; i
++) {
683 AtapiStallExecution(1000);
684 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
685 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
686 if(!(BOHC
& AHCI_BOHC_BOS
)) {
691 KdPrint2((PRINT_PREFIX
" final BOHC %#x\n", BOHC
));
694 /* disable AHCI interrupts, for MSI compatibility issue
695 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
696 26. AHCI Reset and MSI Request
699 KdPrint2((PRINT_PREFIX
" get GHC\n"));
700 /* enable AHCI mode */
701 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
702 if(!(GHC
& AHCI_GHC_AE
)) {
703 KdPrint2((PRINT_PREFIX
" enable AHCI mode, disable intr, GHC %#x\n", GHC
));
704 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
705 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
707 KdPrint2((PRINT_PREFIX
" disable intr, GHC %#x\n", GHC
));
708 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
711 AtapiStallExecution(100);
713 /* read GHC again and reset AHCI controller */
714 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
715 KdPrint2((PRINT_PREFIX
" reset AHCI controller, GHC %#x\n", GHC
));
716 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
719 for(i
=0; i
<1000; i
++) {
720 AtapiStallExecution(1000);
721 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
722 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
723 if(!(GHC
& AHCI_GHC_HR
)) {
727 if(GHC
& AHCI_GHC_HR
) {
728 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
732 /* re-enable AHCI mode */
733 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
734 if(!(GHC
& AHCI_GHC_AE
)) {
735 KdPrint2((PRINT_PREFIX
" re-enable AHCI mode, GHC %#x\n", GHC
));
736 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
738 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
740 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
741 if(!(GHC
& AHCI_GHC_AE
)) {
742 KdPrint2((PRINT_PREFIX
" Can't enable AHCI mode\n"));
746 deviceExtension
->AHCI_CAP
=
747 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
748 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
749 if(CAP
& AHCI_CAP_S64A
) {
750 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
751 deviceExtension
->Host64
= TRUE
;
753 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
754 if(CAP
& AHCI_CAP_PMD
) {
755 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
757 if(CAP
& AHCI_CAP_SAM
) {
758 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
761 /* get the number of HW channels */
762 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
763 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
765 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
766 if(CAP2
& AHCI_CAP2_BOH
) {
767 KdPrint2((PRINT_PREFIX
" retry BOHC\n"));
768 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
769 KdPrint2((PRINT_PREFIX
" BOHC %#x\n", BOHC
));
770 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_BOHC
,
771 BOHC
| AHCI_BOHC_OOS
);
773 /* clear interrupts */
774 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
775 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
777 /* enable AHCI interrupts */
778 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
779 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
781 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
782 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
784 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
785 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
787 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
788 chan
= &deviceExtension
->chan
[c
];
789 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
791 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
793 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
795 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
797 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
798 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
800 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
801 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
802 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
803 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
804 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
805 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
806 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
807 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
808 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
809 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
810 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
812 UniataInitSyncBaseIO(chan
);
814 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
815 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
816 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
817 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
818 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
819 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
820 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
821 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
823 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
825 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
826 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
830 UniataAhciResume(chan
);
832 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
836 } // end UniataAhciInit()
840 UniAtaAhciValidateVersion(
841 IN PHW_DEVICE_EXTENSION deviceExtension
,
849 KdPrint((" wrong AHCI revision %#x\n", version
));
858 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
859 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
860 KdPrint((" AHCI revision excluded\n"));
865 } // end UniAtaAhciValidateVersion()
870 IN PVOID HwDeviceExtension
,
871 IN PPCI_COMMON_CONFIG pciData
, // optional
872 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
875 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
876 //ULONG slotNumber = deviceExtension->slotNumber;
877 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
888 ULONG NumberChannels
;
889 ULONG BaseMemAddress
;
890 BOOLEAN MemIo
= FALSE
;
891 BOOLEAN found
= FALSE
;
893 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
895 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
896 KdPrint((" AHCI excluded\n"));
899 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
901 if(!BaseMemAddress
) {
902 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
905 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
906 KdPrint2((PRINT_PREFIX
"MemIo\n"));
909 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
910 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
913 UniataDumpAhciRegs(deviceExtension
);
916 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
917 if(GHC
& AHCI_GHC_HR
) {
918 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
922 /* check AHCI mode. Save state and try enable */
924 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
925 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
927 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
929 if(!(GHC
& AHCI_GHC_AE
)) {
930 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
931 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
932 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
935 KdPrint2((PRINT_PREFIX
" try enable\n"));
936 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
937 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
938 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
940 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
941 if(!(GHC
& AHCI_GHC_AE
)) {
942 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
947 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
948 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
949 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
950 if(CAP
& AHCI_CAP_S64A
) {
951 KdPrint2((PRINT_PREFIX
" 64bit"));
952 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
955 if(CAP2
& AHCI_CAP2_BOH
) {
956 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
957 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
960 if(CAP
& AHCI_CAP_NCQ
) {
961 KdPrint2((PRINT_PREFIX
" NCQ"));
963 if(CAP
& AHCI_CAP_SNTF
) {
964 KdPrint2((PRINT_PREFIX
" SNTF"));
966 if(CAP
& AHCI_CAP_CCC
) {
967 KdPrint2((PRINT_PREFIX
" CCC"));
969 KdPrint2((PRINT_PREFIX
"\n"));
971 /* get the number of HW channels */
972 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
973 deviceExtension
->AHCI_PI
= PI
;
974 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
975 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
977 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
979 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
980 KdPrint2((PRINT_PREFIX
" Channels %d\n", n
));
982 switch(deviceExtension
->DevID
) {
995 if(!NumberChannels
) {
996 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
1002 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
1003 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
1005 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
1007 NumberChannels
, PI
));
1008 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
1011 if(CAP
& AHCI_CAP_SPM
) {
1012 KdPrint2((PRINT_PREFIX
" PM supported\n"));
1013 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
1014 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
1015 deviceExtension
->NumberLuns
= 1;
1016 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
1018 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
1019 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
1020 //deviceExtension->NumberLuns = 1;
1023 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
1024 deviceExtension
->NumberLuns
= 1;
1027 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
1031 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
1032 if(deviceExtension
->NumberChannels
< NumberChannels
) {
1033 deviceExtension
->NumberChannels
= NumberChannels
;
1035 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
1036 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
1038 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
1039 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
1044 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
1045 KdPrint((" AHCI detect status %d\n", found
));
1048 } // end UniataAhciDetect()
1053 IN PVOID HwDeviceExtension
,
1055 IN ULONG DeviceNumber
1058 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1059 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1060 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1064 SATA_SSTATUS_REG SStatus
;
1065 SATA_SERROR_REG SError
;
1066 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1069 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1071 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1072 KdPrint((" hIS %#x\n", hIS
));
1073 hIS
&= (1 << Channel
);
1075 return INTERRUPT_REASON_IGNORE
;
1077 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1078 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1079 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1080 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1081 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1083 /* clear interrupt(s) */
1084 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1085 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1086 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1088 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1089 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1091 /* do we have cold connect surprise */
1095 /* check for and handle connect events */
1097 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1100 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1102 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1103 chan
->AhciPrevCI
= CI
;
1104 chan
->AhciLastSError
= SError
.Reg
;
1105 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1106 chan
->AhciLastIS
= IS
.Reg
;
1107 if(CI
& (1 << tag
)) {
1109 UniataDumpAhciPortRegs(chan
);
1111 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1113 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1114 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1115 KdPrint((" AHCI: unexpected, error\n"));
1117 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1121 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1122 KdPrint2((" TFD %#x\n", TFD));
1123 if(TFD & IDE_STATUS_BUSY) {
1124 KdPrint2((" Seems to be interrupt on error\n"));
1125 return INTERRUPT_REASON_OUR;
1128 return INTERRUPT_REASON_UNEXPECTED
;
1131 return INTERRUPT_REASON_OUR
;
1133 } // end UniataAhciStatus()
1137 UniataAhciSnapAtaRegs(
1138 IN PHW_CHANNEL chan
,
1139 IN ULONG DeviceNumber
,
1140 IN OUT PIDEREGS_EX regs
1145 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1146 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1147 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1148 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1150 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1151 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1152 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1153 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1154 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1158 } // end UniataAhciSnapAtaRegs()
1162 UniataAhciSetupFIS_H2D(
1163 IN PHW_DEVICE_EXTENSION deviceExtension
,
1164 IN ULONG DeviceNumber
,
1176 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1178 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1180 plba
= (PUCHAR
)&lba
;
1182 RtlZeroMemory(fis
, 20);
1184 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1185 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1186 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1187 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1188 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1190 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1191 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1192 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1194 command
== IDE_COMMAND_ATAPI_PACKET
) {
1195 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1196 if(feature
& ATA_F_DMA
) {
1197 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1199 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1200 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1202 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1205 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1206 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1207 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1208 //return IDE_STATUS_ERROR;
1209 //return SRB_STATUS_ERROR;
1213 need48
= UniAta_need_lba48(command
, lba
, count
,
1214 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1216 /* translate command into 48bit version */
1218 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1219 command
= AtaCommands48
[command
];
1221 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1226 fis
[IDX_AHCI_o_Command
] = command
;
1227 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1229 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1230 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1231 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1233 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1237 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1239 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1240 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1241 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1243 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1245 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1247 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1250 //#pragma warning(push)
1251 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1253 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1254 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1256 //#pragma warning(pop)
1267 } // end UniataAhciSetupFIS_H2D()
1271 UniataAhciSetupFIS_H2D_Direct(
1272 IN PHW_DEVICE_EXTENSION deviceExtension
,
1273 IN ULONG DeviceNumber
,
1282 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1285 command
= regs
->bCommandReg
;
1287 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1289 //plba = (PUCHAR)&lba;
1291 RtlZeroMemory(fis
, 20);
1293 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1294 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1295 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1296 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1297 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1299 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1300 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1301 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1303 command
== IDE_COMMAND_ATAPI_PACKET
) {
1304 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1305 if(feature & ATA_F_DMA) {
1306 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1308 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1309 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1312 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1315 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1316 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1318 /* translate command into 48bit version */
1320 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1321 command
= AtaCommands48
[command
];
1323 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1328 fis
[IDX_AHCI_o_Command
] = command
;
1329 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1331 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1332 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1333 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1335 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1339 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1341 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1342 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1343 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1345 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1347 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1349 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1351 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1352 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1354 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1360 } // end UniataAhciSetupFIS_H2D_Direct()
1364 UniataAhciWaitCommandReady(
1365 IN PHW_CHANNEL chan
,
1378 for (i
=0; i
<timeout
; i
++) {
1379 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1380 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1381 if (!(( CI
>> tag
) & 0x01)) {
1384 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1385 //KdPrint((" IS %#x\n", IS.Reg));
1389 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1391 KdPrint((" AHCI: error %#x\n", SError
));
1395 AtapiStallExecution(200);
1397 KdPrint((" CI %#x\n", CI
));
1399 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1400 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1402 /* clear interrupt(s) */
1403 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1404 KdPrint((" IS %#x\n", IS
.Reg
));
1405 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1407 if (timeout
&& (i
>= timeout
)) {
1411 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1412 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1414 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1415 KdPrint2((" TFD %#x\n", TFD
));
1418 return IDE_STATUS_WRONG
;
1421 return IDE_STATUS_IDLE
;
1422 } // end UniataAhciWaitCommandReady()
1426 UniataAhciSendCommand(
1427 IN PVOID HwDeviceExtension
,
1429 IN ULONG DeviceNumber
,
1430 IN USHORT ahci_flags
,
1434 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1435 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1436 //ULONG Channel = deviceExtension->Channel + lChannel;
1439 //SATA_SSTATUS_REG SStatus;
1440 //SATA_SERROR_REG SError;
1441 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1445 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1447 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1449 AHCI_CL
->prd_length
= 0;
1450 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1451 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1453 AHCI_CL
->bytecount
= 0;
1454 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1455 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1456 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1459 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1460 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1462 return UniataAhciWaitCommandReady(chan
, timeout
);
1464 } // end UniataAhciSendCommand()
1468 UniataAhciSendPIOCommand(
1469 IN PVOID HwDeviceExtension
,
1471 IN ULONG DeviceNumber
,
1472 IN PSCSI_REQUEST_BLOCK Srb
,
1474 IN ULONG length
, /* bytes */
1477 IN USHORT bcount
, /* block count, just ATA register */
1479 IN USHORT ahci_flags
,
1480 IN ULONG wait_flags
,
1484 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1485 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1490 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1491 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1493 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1495 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1496 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1498 if(length
/DEV_BSIZE
!= bcount
) {
1499 KdPrint((" length/DEV_BSIZE != bcount\n"));
1503 //UniataDumpAhciPortRegs(chan);
1507 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1509 KdPrint((" !Srb\n"));
1510 return IDE_STATUS_WRONG
;
1512 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1513 //should be already called on init
1515 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1516 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1518 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1520 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1521 &(AHCI_CMD
->cfis
[0]),
1529 KdPrint2(("!fis_size\n"));
1530 return IDE_STATUS_WRONG
;
1533 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1534 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1535 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1538 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1539 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1540 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1541 KdPrint((" assume OUT\n"));
1543 AtaReq
->Flags
|= REQ_FLAG_READ
;
1544 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1545 KdPrint((" assume IN\n"));
1547 if(!AtapiDmaSetup(HwDeviceExtension
,
1549 lChannel
, // logical channel,
1553 KdPrint2((" can't setup buffer\n"));
1554 return IDE_STATUS_WRONG
;
1558 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1561 //UniataDumpAhciPortRegs(chan);
1564 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1567 //UniataDumpAhciPortRegs(chan);
1570 if(wait_flags
== ATA_IMMEDIATE
) {
1572 KdPrint2((" return imemdiately\n"));
1574 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1575 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1576 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1581 } // end UniataAhciSendPIOCommand()
1585 UniataAhciSendPIOCommandDirect(
1586 IN PVOID HwDeviceExtension
,
1588 IN ULONG DeviceNumber
,
1589 IN PSCSI_REQUEST_BLOCK Srb
,
1590 IN PIDEREGS_EX regs
,
1591 IN ULONG wait_flags
,
1595 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1596 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1601 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1602 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1603 USHORT ahci_flags
=0;
1606 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1608 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1609 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1611 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1612 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1616 //UniataDumpAhciPortRegs(chan);
1620 KdPrint((" !Srb\n"));
1621 return IDE_STATUS_WRONG
;
1622 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1623 //should be already called on init
1625 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1626 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1628 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1630 KdPrint((" !AHCI_CMD\n"));
1631 return IDE_STATUS_WRONG
;
1634 if(Srb
->DataTransferLength
) {
1635 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1636 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1637 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1639 AtaReq
->Flags
|= REQ_FLAG_READ
;
1643 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1644 &(AHCI_CMD
->cfis
[0]),
1648 KdPrint2(("!fis_size\n"));
1649 return IDE_STATUS_WRONG
;
1652 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1653 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1654 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1656 if(Srb
->DataTransferLength
) {
1657 if(!AtapiDmaSetup(HwDeviceExtension
,
1659 lChannel
, // logical channel,
1661 (PUCHAR
)(Srb
->DataBuffer
),
1662 Srb
->DataTransferLength
)) {
1663 KdPrint2((" can't setup buffer\n"));
1664 return IDE_STATUS_WRONG
;
1668 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1671 //UniataDumpAhciPortRegs(chan);
1674 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1677 //UniataDumpAhciPortRegs(chan);
1680 if(wait_flags
== ATA_IMMEDIATE
) {
1682 KdPrint2((" return imemdiately\n"));
1684 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1685 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1686 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1691 } // end UniataAhciSendPIOCommandDirect()
1695 UniataAhciAbortOperation(
1699 /* kick controller into sane state */
1700 if(!UniataAhciStop(chan
)) {
1703 if(!UniataAhciStopFR(chan
)) {
1706 if(!UniataAhciCLO(chan
)) {
1709 UniataAhciStartFR(chan
);
1710 UniataAhciStart(chan
);
1713 } // end UniataAhciAbortOperation()
1717 UniataAhciSoftReset(
1718 IN PVOID HwDeviceExtension
,
1720 IN ULONG DeviceNumber
1723 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1724 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1725 //ULONG Channel = deviceExtension->Channel + lChannel;
1731 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1733 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1734 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1736 /* kick controller into sane state */
1737 if(!UniataAhciAbortOperation(chan
)) {
1738 KdPrint2((" abort failed\n"));
1742 /* pull reset active */
1743 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1744 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1745 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1746 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1747 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1749 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1750 KdPrint2((" timeout\n"));
1753 AtapiStallExecution(50);
1755 /* pull reset inactive */
1756 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1757 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1758 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1759 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1760 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1761 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1762 KdPrint2((" timeout (2)\n"));
1766 UniataAhciWaitReady(chan
, 1);
1768 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1770 return UniataAhciUlongFromRFIS(RCV_FIS
);
1772 } // end UniataAhciSoftReset()
1776 UniataAhciWaitReady(
1777 IN PHW_CHANNEL chan
,
1784 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1786 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1788 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1789 for(i
=0; i
<timeout
&& (TFD
&
1790 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1791 AtapiStallExecution(1000);
1792 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1795 KdPrint2((" TFD %#x\n", TFD
));
1799 } // end UniataAhciWaitReady()
1803 UniataAhciHardReset(
1804 IN PVOID HwDeviceExtension
,
1806 OUT PULONG signature
1809 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1810 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1811 //ULONG Channel = deviceExtension->Channel + lChannel;
1815 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1817 (*signature
) = 0xffffffff;
1819 UniataAhciStop(chan
);
1820 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1821 KdPrint((" no PHY\n"));
1822 return IDE_STATUS_WRONG
;
1825 /* Wait for clearing busy status. */
1826 TFD
= UniataAhciWaitReady(chan
, 15000);
1827 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1828 KdPrint((" busy: TFD %#x\n", TFD
));
1831 KdPrint((" TFD %#x\n", TFD
));
1834 UniataDumpAhciPortRegs(chan
);
1837 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1838 KdPrint((" sig: %#x\n", *signature
));
1840 UniataAhciStart(chan
);
1844 } // end UniataAhciHardReset()
1849 IN PVOID HwDeviceExtension
,
1853 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1854 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1855 //ULONG Channel = deviceExtension->Channel + lChannel;
1856 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1861 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1863 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1865 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1867 /* Disable port interrupts */
1868 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1870 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1872 KdPrint((" No devices in all LUNs\n"));
1873 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1874 // Zero device fields to ensure that if earlier devices were found,
1875 // but not claimed, the fields are cleared.
1876 UniataForgetDevice(chan
->lun
[i
]);
1879 /* enable wanted port interrupts */
1880 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1881 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1885 /* enable wanted port interrupts */
1886 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1887 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1888 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1889 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1890 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1891 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1894 * Only probe for PortMultiplier if HW has support.
1895 * Ignore Marvell, which is not working,
1897 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1898 if ((CAP
& AHCI_CAP_SPM
) &&
1899 (VendorID
!= ATA_MARVELL_ID
)) {
1900 KdPrint((" check PM\n"));
1901 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1902 /* Workaround for some ATI chips, failing to soft-reset
1903 * when port multiplicator supported, but absent.
1904 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1905 if (signature
== 0xffffffff) {
1906 KdPrint((" re-check PM\n"));
1907 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1910 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1913 KdPrint((" signature %#x\n", signature
));
1914 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1915 switch (signature
>> 16) {
1917 KdPrint((" ATA dev\n"));
1918 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1923 if(deviceExtension
->NumberLuns
> 1) {
1924 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1925 UniataSataIdentifyPM(chan
);
1927 KdPrint((" no PM supported (1 lun/chan)\n"));
1931 KdPrint((" ATAPI dev\n"));
1932 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1935 default: /* SOS XXX */
1936 KdPrint((" default to ATA ???\n"));
1937 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1943 } // end UniataAhciReset()
1953 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1955 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1956 KdPrint2((" CMD %#x\n", CMD
));
1957 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1960 } // end UniataAhciStartFR()
1971 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
1973 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1974 KdPrint2((" CMD %#x\n", CMD
));
1975 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
1977 for(i
=0; i
<1000; i
++) {
1978 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1979 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
1980 KdPrint2((" final CMD %#x\n", CMD
));
1983 AtapiStallExecution(1000);
1985 KdPrint2((" CMD %#x\n", CMD
));
1986 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
1987 KdPrint2(("UniataAhciStopFR: timeout\n"));
1989 } // end UniataAhciStopFR()
1998 SATA_SERROR_REG SError
;
2000 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
2002 /* clear SATA error register */
2003 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
2005 /* clear any interrupts pending on this channel */
2006 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
2007 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
2009 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
2011 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2012 KdPrint2((" CMD %#x\n", CMD
));
2013 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2016 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
2019 } // end UniataAhciStart()
2027 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2028 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2030 //SATA_SERROR_REG SError;
2033 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
2035 /* issue Command List Override if supported */
2036 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
2037 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
2038 if(!(CAP
& AHCI_CAP_SCLO
)) {
2041 KdPrint2((" send CLO\n"));
2042 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2043 CMD
|= ATA_AHCI_P_CMD_CLO
;
2044 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2046 for(i
=0; i
<1000; i
++) {
2047 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2048 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
2049 KdPrint2((" final CMD %#x\n", CMD
));
2052 AtapiStallExecution(1000);
2054 KdPrint2((" CMD %#x\n", CMD
));
2055 KdPrint2(("UniataAhciCLO: timeout\n"));
2057 } // end UniataAhciCLO()
2066 //SATA_SERROR_REG SError;
2069 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2071 /* issue Command List Override if supported */
2072 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2073 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2074 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2076 for(i
=0; i
<1000; i
++) {
2077 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2078 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2079 KdPrint2((" final CMD %#x\n", CMD
));
2082 AtapiStallExecution(1000);
2084 KdPrint2((" CMD %#x\n", CMD
));
2085 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2086 KdPrint2(("UniataAhciStop: timeout\n"));
2088 } // end UniataAhciStop()
2092 UniataAhciBeginTransaction(
2093 IN PVOID HwDeviceExtension
,
2095 IN ULONG DeviceNumber
,
2096 IN PSCSI_REQUEST_BLOCK Srb
2099 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2100 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2101 //ULONG Channel = deviceExtension->Channel + lChannel;
2105 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2106 //SATA_SSTATUS_REG SStatus;
2107 //SATA_SERROR_REG SError;
2108 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2113 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2115 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2117 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2118 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2122 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2123 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2124 AHCI_CL
->bytecount
= 0;
2125 if(AtaReq
->ahci
.ahci_base64
) {
2126 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2127 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2129 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2130 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2131 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2132 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2133 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2134 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2135 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2137 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2138 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2141 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2142 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2147 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2148 AHCI_CL
->cmd_table_phys
));
2151 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2152 KdPrint2((" CMD %#x\n", CMD
));
2153 // switch controller to ATAPI mode for ATA_PACKET commands only
2154 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2155 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2156 KdPrint2((" ATAPI\n"));
2157 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2158 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2160 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2163 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2164 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2167 /* issue command to controller */
2168 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2169 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2170 chan
->AhciPrevCI
|= 0x01 << tag
;
2172 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2173 // TODO: check if we send ATA_RESET and wait for ready of so.
2174 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2178 for(i
=0; i
<1000000; i
++) {
2179 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2180 if(!(TFD
& IDE_STATUS_BUSY
)) {
2184 if(TFD
& IDE_STATUS_BUSY
) {
2185 KdPrint2((" timeout\n"));
2187 if(TFD
& IDE_STATUS_ERROR
) {
2188 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2190 AtaReq
->ahci
.in_status
= TFD
;
2192 return IDE_STATUS_SUCCESS
;
2196 return IDE_STATUS_IDLE
;
2198 } // end UniataAhciBeginTransaction()
2202 UniataAhciEndTransaction(
2203 IN PVOID HwDeviceExtension
,
2205 IN ULONG DeviceNumber
,
2206 IN PSCSI_REQUEST_BLOCK Srb
2209 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2210 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2211 //ULONG Channel = deviceExtension->Channel + lChannel;
2214 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2216 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2219 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2220 //PHW_LU_EXTENSION LunExt;
2222 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2224 //LunExt = chan->lun[DeviceNumber];
2226 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2227 KdPrint2((" TFD %#x\n", TFD
));
2229 if(TFD
& IDE_STATUS_ERROR
) {
2230 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2231 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2233 AtaReq
->ahci
.in_error
= 0;
2235 AtaReq
->ahci
.in_status
= TFD
;
2237 //if (request->flags & ATA_R_CONTROL) {
2239 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2240 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2241 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2242 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2243 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2244 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2245 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2247 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2248 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2249 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2251 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2253 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2254 KdPrint2(("RCV:\n"));
2255 KdDump(RCV_FIS, 24);
2256 KdPrint2(("PIO:\n"));
2257 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2259 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2260 if(!AHCI_CL->bytecount) {
2261 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2265 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2266 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2267 if(CI
& (1 << tag
)) {
2269 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2270 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2273 UniataDumpAhciPortRegs(chan
);
2275 if(!UniataAhciAbortOperation(chan
)) {
2276 KdPrint2((" Abort failed, need RESET\n"));
2279 UniataDumpAhciPortRegs(chan
);
2281 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2282 if(chan
->AhciPrevCI
) {
2283 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2286 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2287 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2293 } // end UniataAhciEndTransaction()
2303 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2306 //UniataDumpAhciPortRegs(chan);
2309 /* Disable port interrupts */
2310 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2312 /* setup work areas */
2313 base
= chan
->AHCI_CTL_PhAddr
;
2315 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2318 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2319 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2320 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2322 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2323 (ULONG
)(base
& 0xffffffff));
2324 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2325 (ULONG
)((base
>> 32) & 0xffffffff));
2327 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2328 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2329 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2330 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2332 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2333 (ULONG
)(base
& 0xffffffff));
2334 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2335 (ULONG
)((base
>> 32) & 0xffffffff));
2337 /* activate the channel and power/spin up device */
2338 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2339 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2340 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2341 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2345 //UniataDumpAhciPortRegs(chan);
2348 UniataAhciStartFR(chan
);
2349 UniataAhciStart(chan
);
2352 UniataDumpAhciPortRegs(chan
);
2356 } // end UniataAhciResume()
2366 SATA_SCONTROL_REG SControl
;
2368 KdPrint2(("UniataAhciSuspend:\n"));
2370 /* Disable port interrupts */
2371 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2373 /* Reset command register. */
2374 UniataAhciStop(chan
);
2375 UniataAhciStopFR(chan
);
2376 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2378 /* Allow everything including partial and slumber modes. */
2379 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2381 /* Request slumber mode transition and give some time to get there. */
2382 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2383 AtapiStallExecution(100);
2387 SControl
.DET
= SStatus_DET_Offline
;
2388 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2391 } // end UniataAhciSuspend()
2397 IN PHW_CHANNEL chan
,
2398 IN ULONG DeviceNumber
,
2403 //ULONG Channel = deviceExtension->Channel + lChannel;
2408 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2409 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2411 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2413 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2414 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2417 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2419 case IDX_SATA_SStatus
:
2421 case IDX_SATA_SError
:
2423 case IDX_SATA_SControl
:
2430 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2431 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2432 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2433 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2434 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2435 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2436 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2438 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2439 KdPrint2((" PM read failed\n"));
2443 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2445 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2448 } // end UniataAhciReadPM()
2453 IN PHW_CHANNEL chan
,
2454 IN ULONG DeviceNumber
,
2459 //ULONG Channel = deviceExtension->Channel + lChannel;
2465 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2466 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2468 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2470 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2471 UniataSataWritePort4(chan
, Reg
, value
, 0);
2474 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2476 case IDX_SATA_SStatus
:
2478 case IDX_SATA_SError
:
2480 case IDX_SATA_SControl
:
2483 return IDE_STATUS_WRONG
;
2487 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2488 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2489 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2490 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2491 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2492 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2494 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2495 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2496 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2497 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2499 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2501 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2502 KdPrint2((" PM write failed\n"));
2503 return IDE_STATUS_WRONG
;
2506 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2508 if(TFD
& IDE_STATUS_ERROR
) {
2509 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2511 return (UCHAR
)(TFD
>> 8);
2513 } // end UniataAhciWritePM()
2516 UniataAhciSetupCmdPtr(
2517 IN OUT PATA_REQ AtaReq
2522 ULONGLONG prd_base64
;
2526 ULONGLONG prd_base64_0
;
2532 prd_base64_0
= prd_base64
= 0;
2533 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2534 prd_base0
= prd_base
;
2536 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2539 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2540 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2543 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2544 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2545 } // end UniataAhciSetupCmdPtr()
2549 BuildAhciInternalSrb (
2550 IN PVOID HwDeviceExtension
,
2551 IN ULONG DeviceNumber
,
2557 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2558 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2559 PSCSI_REQUEST_BLOCK srb
;
2561 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2563 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2566 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2570 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2571 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2572 UniAtaClearAtaReq(AtaReq
);
2574 srb
= chan
->AhciInternalSrb
;
2576 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2578 srb
->PathId
= (UCHAR
)lChannel
;
2579 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2580 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2581 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2583 // Set flags to disable synchronous negociation.
2584 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2586 // Set timeout to 4 seconds.
2587 srb
->TimeOutValue
= 4;
2590 srb
->DataBuffer
= Buffer
;
2591 srb
->DataTransferLength
= Length
;
2592 srb
->SrbExtension
= AtaReq
;
2595 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2596 AtaReq
->TransferLength
= Length
;
2598 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2599 //UniataAhciSetupCmdPtr(AtaReq);
2600 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2601 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2603 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2604 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2606 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2607 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2609 /* // Set CDB operation code.
2610 cdb = (PCDB)srb->Cdb;
2611 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2612 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2615 } // end BuildAhciInternalSrb()