3 Copyright (c) 2008-2012 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
;
651 BOOLEAN MemIo
= FALSE
;
653 KdPrint2((PRINT_PREFIX
" UniataAhciInit:\n"));
656 UniataDumpAhciRegs(deviceExtension
);
659 /* disable AHCI interrupts, for MSI compatibility issue
660 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
661 26. AHCI Reset and MSI Request
664 KdPrint2((PRINT_PREFIX
" get GHC\n"));
665 /* enable AHCI mode */
666 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
667 if(!(GHC
& AHCI_GHC_AE
)) {
668 KdPrint2((PRINT_PREFIX
" enable AHCI mode, disable intr, GHC %#x\n", GHC
));
669 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
670 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
672 KdPrint2((PRINT_PREFIX
" disable intr, GHC %#x\n", GHC
));
673 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
676 AtapiStallExecution(100);
678 /* read GHC again and reset AHCI controller */
679 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
680 KdPrint2((PRINT_PREFIX
" reset AHCI controller, GHC %#x\n", GHC
));
681 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
684 for(i
=0; i
<1000; i
++) {
685 AtapiStallExecution(1000);
686 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
687 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
688 if(!(GHC
& AHCI_GHC_HR
)) {
692 if(GHC
& AHCI_GHC_HR
) {
693 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
697 /* re-enable AHCI mode */
698 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
699 if(!(GHC
& AHCI_GHC_AE
)) {
700 KdPrint2((PRINT_PREFIX
" re-enable AHCI mode, GHC %#x\n", GHC
));
701 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
703 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
705 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
706 if(!(GHC
& AHCI_GHC_AE
)) {
707 KdPrint2((PRINT_PREFIX
" Can't enable AHCI mode\n"));
711 deviceExtension
->AHCI_CAP
=
712 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
713 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
714 if(CAP
& AHCI_CAP_S64A
) {
715 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
716 deviceExtension
->Host64
= TRUE
;
718 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
719 if(CAP
& AHCI_CAP_PMD
) {
720 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
722 if(CAP
& AHCI_CAP_SAM
) {
723 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
725 /* get the number of HW channels */
726 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
727 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
729 /* clear interrupts */
730 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
731 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
733 /* enable AHCI interrupts */
734 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
735 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
737 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
738 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
740 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
741 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
743 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
744 chan
= &deviceExtension
->chan
[c
];
745 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
747 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
749 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
751 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
753 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
754 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
756 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
757 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
758 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
759 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
760 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
761 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
762 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
763 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
764 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
765 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
766 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
768 UniataInitSyncBaseIO(chan
);
770 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
771 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
772 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
773 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
774 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
775 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
776 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
777 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
779 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
781 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
782 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
786 UniataAhciResume(chan
);
788 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
792 } // end UniataAhciInit()
796 UniAtaAhciValidateVersion(
797 IN PHW_DEVICE_EXTENSION deviceExtension
,
805 KdPrint((" wrong AHCI revision %#x\n", version
));
814 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
815 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
816 KdPrint((" AHCI revision excluded\n"));
821 } // end UniAtaAhciValidateVersion()
826 IN PVOID HwDeviceExtension
,
827 IN PPCI_COMMON_CONFIG pciData
, // optional
828 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
831 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
832 //ULONG slotNumber = deviceExtension->slotNumber;
833 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
841 ULONG NumberChannels
;
843 ULONG BaseMemAddress
;
844 BOOLEAN MemIo
= FALSE
;
845 BOOLEAN found
= FALSE
;
847 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
849 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
850 KdPrint((" AHCI excluded\n"));
853 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
855 if(!BaseMemAddress
) {
856 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
859 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
860 KdPrint2((PRINT_PREFIX
"MemIo\n"));
863 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
864 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
867 UniataDumpAhciRegs(deviceExtension
);
870 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
871 if(GHC
& AHCI_GHC_HR
) {
872 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
876 /* check AHCI mode. Save state and try enable */
878 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
879 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
881 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
883 if(!(GHC
& AHCI_GHC_AE
)) {
884 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
885 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
886 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
889 KdPrint2((PRINT_PREFIX
" try enable\n"));
890 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
891 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
892 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
894 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
895 if(!(GHC
& AHCI_GHC_AE
)) {
896 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
901 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
902 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
903 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
904 if(CAP
& AHCI_CAP_S64A
) {
905 KdPrint2((PRINT_PREFIX
" 64bit"));
906 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
908 if(CAP2
& AHCI_CAP2_BOH
) {
909 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
910 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
912 if(CAP
& AHCI_CAP_NCQ
) {
913 KdPrint2((PRINT_PREFIX
" NCQ"));
915 if(CAP
& AHCI_CAP_SNTF
) {
916 KdPrint2((PRINT_PREFIX
" SNTF"));
918 if(CAP
& AHCI_CAP_CCC
) {
919 KdPrint2((PRINT_PREFIX
" CCC"));
921 KdPrint2((PRINT_PREFIX
"\n"));
923 /* get the number of HW channels */
924 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
925 deviceExtension
->AHCI_PI
= PI
;
926 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
927 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
929 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
931 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
932 KdPrint2((PRINT_PREFIX
" Channels %d\n", n
));
934 switch(deviceExtension
->DevID
) {
947 if(!NumberChannels
) {
948 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
953 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
954 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
956 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
958 NumberChannels
, PI
));
959 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
961 if(CAP
& AHCI_CAP_SPM
) {
962 KdPrint2((PRINT_PREFIX
" PM supported\n"));
963 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
964 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
965 deviceExtension
->NumberLuns
= 1;
966 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
968 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
969 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
970 //deviceExtension->NumberLuns = 1;
973 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
974 deviceExtension
->NumberLuns
= 1;
977 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
981 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
982 if(deviceExtension
->NumberChannels
< NumberChannels
) {
983 deviceExtension
->NumberChannels
= NumberChannels
;
985 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
986 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
988 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
989 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
994 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
995 KdPrint((" AHCI detect status %d\n", found
));
998 } // end UniataAhciDetect()
1003 IN PVOID HwDeviceExtension
,
1005 IN ULONG DeviceNumber
1008 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1009 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1010 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1014 SATA_SSTATUS_REG SStatus
;
1015 SATA_SERROR_REG SError
;
1016 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1019 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1021 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1022 KdPrint((" hIS %#x\n", hIS
));
1023 hIS
&= (1 << Channel
);
1025 return INTERRUPT_REASON_IGNORE
;
1027 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1028 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1029 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1030 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1031 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1033 /* clear interrupt(s) */
1034 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1035 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1036 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1038 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1039 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1041 /* do we have cold connect surprise */
1045 /* check for and handle connect events */
1047 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1050 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1052 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1053 chan
->AhciPrevCI
= CI
;
1054 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1055 chan
->AhciLastIS
= IS
.Reg
;
1056 if(CI
& (1 << tag
)) {
1058 UniataDumpAhciPortRegs(chan
);
1060 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1062 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1063 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1064 KdPrint((" AHCI: unexpected, error\n"));
1066 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1070 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1071 KdPrint2((" TFD %#x\n", TFD));
1072 if(TFD & IDE_STATUS_BUSY) {
1073 KdPrint2((" Seems to be interrupt on error\n"));
1074 return INTERRUPT_REASON_OUR;
1077 return INTERRUPT_REASON_UNEXPECTED
;
1080 return INTERRUPT_REASON_OUR
;
1082 } // end UniataAhciStatus()
1086 UniataAhciSnapAtaRegs(
1087 IN PHW_CHANNEL chan
,
1088 IN ULONG DeviceNumber
,
1089 IN OUT PIDEREGS_EX regs
1094 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1095 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1096 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1097 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1099 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1100 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1101 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1102 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1103 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1107 } // end UniataAhciSnapAtaRegs()
1111 UniataAhciSetupFIS_H2D(
1112 IN PHW_DEVICE_EXTENSION deviceExtension
,
1113 IN ULONG DeviceNumber
,
1125 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1127 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1129 plba
= (PUCHAR
)&lba
;
1131 RtlZeroMemory(fis
, 20);
1133 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1134 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1135 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1136 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1137 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1139 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1140 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1141 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1143 command
== IDE_COMMAND_ATAPI_PACKET
) {
1144 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1145 if(feature
& ATA_F_DMA
) {
1146 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1148 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1149 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1151 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1154 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1155 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1156 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1157 //return IDE_STATUS_ERROR;
1158 //return SRB_STATUS_ERROR;
1162 need48
= UniAta_need_lba48(command
, lba
, count
,
1163 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1165 /* translate command into 48bit version */
1167 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1168 command
= AtaCommands48
[command
];
1170 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1175 fis
[IDX_AHCI_o_Command
] = command
;
1176 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1178 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1179 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1180 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1182 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1186 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1188 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1189 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1190 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1192 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1194 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1196 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1199 //#pragma warning(push)
1200 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1202 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1203 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1205 //#pragma warning(pop)
1216 } // end UniataAhciSetupFIS_H2D()
1220 UniataAhciSetupFIS_H2D_Direct(
1221 IN PHW_DEVICE_EXTENSION deviceExtension
,
1222 IN ULONG DeviceNumber
,
1231 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1234 command
= regs
->bCommandReg
;
1236 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1238 //plba = (PUCHAR)&lba;
1240 RtlZeroMemory(fis
, 20);
1242 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1243 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1244 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1245 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1246 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1248 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1249 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1250 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1252 command
== IDE_COMMAND_ATAPI_PACKET
) {
1253 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1254 if(feature & ATA_F_DMA) {
1255 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1257 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1258 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1261 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1264 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1265 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1267 /* translate command into 48bit version */
1269 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1270 command
= AtaCommands48
[command
];
1272 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1277 fis
[IDX_AHCI_o_Command
] = command
;
1278 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1280 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1281 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1282 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1284 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1288 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1290 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1291 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1292 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1294 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1296 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1298 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1300 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1301 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1303 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1309 } // end UniataAhciSetupFIS_H2D_Direct()
1313 UniataAhciWaitCommandReady(
1314 IN PHW_CHANNEL chan
,
1327 for (i
=0; i
<timeout
; i
++) {
1328 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1329 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1330 if (!(( CI
>> tag
) & 0x01)) {
1333 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1334 //KdPrint((" IS %#x\n", IS.Reg));
1338 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1340 KdPrint((" AHCI: error %#x\n", SError
));
1344 AtapiStallExecution(200);
1346 KdPrint((" CI %#x\n", CI
));
1348 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1349 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1351 /* clear interrupt(s) */
1352 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1353 KdPrint((" IS %#x\n", IS
.Reg
));
1354 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1356 if (timeout
&& (i
>= timeout
)) {
1360 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1361 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1363 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1364 KdPrint2((" TFD %#x\n", TFD
));
1367 return IDE_STATUS_WRONG
;
1370 return IDE_STATUS_IDLE
;
1371 } // end UniataAhciWaitCommandReady()
1375 UniataAhciSendCommand(
1376 IN PVOID HwDeviceExtension
,
1378 IN ULONG DeviceNumber
,
1379 IN USHORT ahci_flags
,
1383 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1384 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1385 //ULONG Channel = deviceExtension->Channel + lChannel;
1388 //SATA_SSTATUS_REG SStatus;
1389 //SATA_SERROR_REG SError;
1390 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1394 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1396 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1398 AHCI_CL
->prd_length
= 0;
1399 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1400 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1402 AHCI_CL
->bytecount
= 0;
1403 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1404 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1405 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1408 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1409 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1411 return UniataAhciWaitCommandReady(chan
, timeout
);
1413 } // end UniataAhciSendCommand()
1417 UniataAhciSendPIOCommand(
1418 IN PVOID HwDeviceExtension
,
1420 IN ULONG DeviceNumber
,
1421 IN PSCSI_REQUEST_BLOCK Srb
,
1423 IN ULONG length
, /* bytes */
1426 IN USHORT bcount
, /* block count, just ATA register */
1428 IN USHORT ahci_flags
,
1429 IN ULONG wait_flags
,
1433 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1434 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1439 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1440 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1442 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1444 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1445 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1447 if(length
/DEV_BSIZE
!= bcount
) {
1448 KdPrint((" length/DEV_BSIZE != bcount\n"));
1452 //UniataDumpAhciPortRegs(chan);
1456 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1458 KdPrint((" !Srb\n"));
1459 return IDE_STATUS_WRONG
;
1461 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1462 //should be already called on init
1464 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1465 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1467 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1469 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1470 &(AHCI_CMD
->cfis
[0]),
1478 KdPrint2(("!fis_size\n"));
1479 return IDE_STATUS_WRONG
;
1482 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1483 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1484 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1487 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1488 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1489 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1490 KdPrint((" assume OUT\n"));
1492 AtaReq
->Flags
|= REQ_FLAG_READ
;
1493 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1494 KdPrint((" assume IN\n"));
1496 if(!AtapiDmaSetup(HwDeviceExtension
,
1498 lChannel
, // logical channel,
1502 KdPrint2((" can't setup buffer\n"));
1503 return IDE_STATUS_WRONG
;
1507 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1510 //UniataDumpAhciPortRegs(chan);
1513 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1516 //UniataDumpAhciPortRegs(chan);
1519 if(wait_flags
== ATA_IMMEDIATE
) {
1521 KdPrint2((" return imemdiately\n"));
1523 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1524 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1525 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1530 } // end UniataAhciSendPIOCommand()
1534 UniataAhciSendPIOCommandDirect(
1535 IN PVOID HwDeviceExtension
,
1537 IN ULONG DeviceNumber
,
1538 IN PSCSI_REQUEST_BLOCK Srb
,
1539 IN PIDEREGS_EX regs
,
1540 IN ULONG wait_flags
,
1544 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1545 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1550 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1551 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1552 USHORT ahci_flags
=0;
1555 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1557 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1558 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1560 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1561 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1565 //UniataDumpAhciPortRegs(chan);
1569 KdPrint((" !Srb\n"));
1570 return IDE_STATUS_WRONG
;
1571 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1572 //should be already called on init
1574 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1575 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1577 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1579 KdPrint((" !AHCI_CMD\n"));
1580 return IDE_STATUS_WRONG
;
1583 if(Srb
->DataTransferLength
) {
1584 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1585 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1586 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1588 AtaReq
->Flags
|= REQ_FLAG_READ
;
1592 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1593 &(AHCI_CMD
->cfis
[0]),
1597 KdPrint2(("!fis_size\n"));
1598 return IDE_STATUS_WRONG
;
1601 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1602 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1603 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1605 if(Srb
->DataTransferLength
) {
1606 if(!AtapiDmaSetup(HwDeviceExtension
,
1608 lChannel
, // logical channel,
1610 (PUCHAR
)(Srb
->DataBuffer
),
1611 Srb
->DataTransferLength
)) {
1612 KdPrint2((" can't setup buffer\n"));
1613 return IDE_STATUS_WRONG
;
1617 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1620 //UniataDumpAhciPortRegs(chan);
1623 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1626 //UniataDumpAhciPortRegs(chan);
1629 if(wait_flags
== ATA_IMMEDIATE
) {
1631 KdPrint2((" return imemdiately\n"));
1633 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1634 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1635 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1640 } // end UniataAhciSendPIOCommandDirect()
1644 UniataAhciAbortOperation(
1648 /* kick controller into sane state */
1649 if(!UniataAhciStop(chan
)) {
1652 if(!UniataAhciStopFR(chan
)) {
1655 if(!UniataAhciCLO(chan
)) {
1658 UniataAhciStartFR(chan
);
1659 UniataAhciStart(chan
);
1662 } // end UniataAhciAbortOperation()
1666 UniataAhciSoftReset(
1667 IN PVOID HwDeviceExtension
,
1669 IN ULONG DeviceNumber
1672 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1673 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1674 //ULONG Channel = deviceExtension->Channel + lChannel;
1680 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1682 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1683 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1685 /* kick controller into sane state */
1686 if(!UniataAhciAbortOperation(chan
)) {
1687 KdPrint2((" abort failed\n"));
1691 /* pull reset active */
1692 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1693 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1694 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1695 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1696 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1698 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1699 KdPrint2((" timeout\n"));
1702 AtapiStallExecution(50);
1704 /* pull reset inactive */
1705 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1706 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1707 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1708 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1709 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1710 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1711 KdPrint2((" timeout (2)\n"));
1715 UniataAhciWaitReady(chan
, 1);
1717 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1719 return UniataAhciUlongFromRFIS(RCV_FIS
);
1721 } // end UniataAhciSoftReset()
1725 UniataAhciWaitReady(
1726 IN PHW_CHANNEL chan
,
1733 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1735 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1737 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1738 for(i
=0; i
<timeout
&& (TFD
&
1739 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1740 AtapiStallExecution(1000);
1741 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1744 KdPrint2((" TFD %#x\n", TFD
));
1748 } // end UniataAhciWaitReady()
1752 UniataAhciHardReset(
1753 IN PVOID HwDeviceExtension
,
1755 OUT PULONG signature
1758 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1759 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1760 //ULONG Channel = deviceExtension->Channel + lChannel;
1764 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1766 (*signature
) = 0xffffffff;
1768 UniataAhciStop(chan
);
1769 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1770 KdPrint((" no PHY\n"));
1771 return IDE_STATUS_WRONG
;
1774 /* Wait for clearing busy status. */
1775 TFD
= UniataAhciWaitReady(chan
, 15000);
1776 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1777 KdPrint((" busy: TFD %#x\n", TFD
));
1780 KdPrint((" TFD %#x\n", TFD
));
1783 UniataDumpAhciPortRegs(chan
);
1786 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1787 KdPrint((" sig: %#x\n", *signature
));
1789 UniataAhciStart(chan
);
1793 } // end UniataAhciHardReset()
1798 IN PVOID HwDeviceExtension
,
1802 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1803 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1804 //ULONG Channel = deviceExtension->Channel + lChannel;
1805 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1810 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1812 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1814 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1816 /* Disable port interrupts */
1817 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1819 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1821 KdPrint((" No devices in all LUNs\n"));
1822 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1823 // Zero device fields to ensure that if earlier devices were found,
1824 // but not claimed, the fields are cleared.
1825 UniataForgetDevice(chan
->lun
[i
]);
1828 /* enable wanted port interrupts */
1829 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1830 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1834 /* enable wanted port interrupts */
1835 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1836 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1837 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1838 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1839 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1840 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1843 * Only probe for PortMultiplier if HW has support.
1844 * Ignore Marvell, which is not working,
1846 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1847 if ((CAP
& AHCI_CAP_SPM
) &&
1848 (VendorID
!= ATA_MARVELL_ID
)) {
1849 KdPrint((" check PM\n"));
1850 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1851 /* Workaround for some ATI chips, failing to soft-reset
1852 * when port multiplicator supported, but absent.
1853 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1854 if (signature
== 0xffffffff) {
1855 KdPrint((" re-check PM\n"));
1856 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1859 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1862 KdPrint((" signature %#x\n", signature
));
1863 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1864 switch (signature
>> 16) {
1866 KdPrint((" ATA dev\n"));
1867 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1872 if(deviceExtension
->NumberLuns
> 1) {
1873 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1874 UniataSataIdentifyPM(chan
);
1876 KdPrint((" no PM supported (1 lun/chan)\n"));
1880 KdPrint((" ATAPI dev\n"));
1881 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1884 default: /* SOS XXX */
1885 KdPrint((" default to ATA ???\n"));
1886 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1892 } // end UniataAhciReset()
1902 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1904 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1905 KdPrint2((" CMD %#x\n", CMD
));
1906 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1909 } // end UniataAhciStartFR()
1920 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
1922 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1923 KdPrint2((" CMD %#x\n", CMD
));
1924 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
1926 for(i
=0; i
<1000; i
++) {
1927 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1928 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
1929 KdPrint2((" final CMD %#x\n", CMD
));
1932 AtapiStallExecution(1000);
1934 KdPrint2((" CMD %#x\n", CMD
));
1935 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
1936 KdPrint2(("UniataAhciStopFR: timeout\n"));
1938 } // end UniataAhciStopFR()
1947 SATA_SERROR_REG SError
;
1949 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
1951 /* clear SATA error register */
1952 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1954 /* clear any interrupts pending on this channel */
1955 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1956 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
1958 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
1960 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1961 KdPrint2((" CMD %#x\n", CMD
));
1962 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
1965 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
1968 } // end UniataAhciStart()
1976 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1977 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1979 //SATA_SERROR_REG SError;
1982 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
1984 /* issue Command List Override if supported */
1985 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1986 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
1987 if(!(CAP
& AHCI_CAP_SCLO
)) {
1990 KdPrint2((" send CLO\n"));
1991 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1992 CMD
|= ATA_AHCI_P_CMD_CLO
;
1993 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
1995 for(i
=0; i
<1000; i
++) {
1996 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1997 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
1998 KdPrint2((" final CMD %#x\n", CMD
));
2001 AtapiStallExecution(1000);
2003 KdPrint2((" CMD %#x\n", CMD
));
2004 KdPrint2(("UniataAhciCLO: timeout\n"));
2006 } // end UniataAhciCLO()
2015 //SATA_SERROR_REG SError;
2018 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2020 /* issue Command List Override if supported */
2021 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2022 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2023 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2025 for(i
=0; i
<1000; i
++) {
2026 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2027 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2028 KdPrint2((" final CMD %#x\n", CMD
));
2031 AtapiStallExecution(1000);
2033 KdPrint2((" CMD %#x\n", CMD
));
2034 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2035 KdPrint2(("UniataAhciStop: timeout\n"));
2037 } // end UniataAhciStop()
2041 UniataAhciBeginTransaction(
2042 IN PVOID HwDeviceExtension
,
2044 IN ULONG DeviceNumber
,
2045 IN PSCSI_REQUEST_BLOCK Srb
2048 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2049 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2050 //ULONG Channel = deviceExtension->Channel + lChannel;
2054 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2055 //SATA_SSTATUS_REG SStatus;
2056 //SATA_SERROR_REG SError;
2057 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2062 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2064 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2066 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2067 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2071 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2072 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2073 AHCI_CL
->bytecount
= 0;
2074 if(AtaReq
->ahci
.ahci_base64
) {
2075 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2076 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2078 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2079 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2080 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2081 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2082 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2083 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2084 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2086 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2087 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2090 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2091 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2096 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2097 AHCI_CL
->cmd_table_phys
));
2100 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2101 KdPrint2((" CMD %#x\n", CMD
));
2102 // switch controller to ATAPI mode for ATA_PACKET commands only
2103 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2104 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2105 KdPrint2((" ATAPI\n"));
2106 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2107 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2109 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2112 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2113 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2116 /* issue command to controller */
2117 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2118 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2119 chan
->AhciPrevCI
|= 0x01 << tag
;
2121 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2122 // TODO: check if we send ATA_RESET and wait for ready of so.
2123 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2127 for(i
=0; i
<1000000; i
++) {
2128 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2129 if(!(TFD
& IDE_STATUS_BUSY
)) {
2133 if(TFD
& IDE_STATUS_BUSY
) {
2134 KdPrint2((" timeout\n"));
2136 if(TFD
& IDE_STATUS_ERROR
) {
2137 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2139 AtaReq
->ahci
.in_status
= TFD
;
2141 return IDE_STATUS_SUCCESS
;
2145 return IDE_STATUS_IDLE
;
2147 } // end UniataAhciBeginTransaction()
2151 UniataAhciEndTransaction(
2152 IN PVOID HwDeviceExtension
,
2154 IN ULONG DeviceNumber
,
2155 IN PSCSI_REQUEST_BLOCK Srb
2158 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2159 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2160 //ULONG Channel = deviceExtension->Channel + lChannel;
2163 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2165 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2168 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2169 PHW_LU_EXTENSION LunExt
;
2171 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2173 LunExt
= chan
->lun
[DeviceNumber
];
2175 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2176 KdPrint2((" TFD %#x\n", TFD
));
2178 if(TFD
& IDE_STATUS_ERROR
) {
2179 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2180 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2182 AtaReq
->ahci
.in_error
= 0;
2184 AtaReq
->ahci
.in_status
= TFD
;
2186 //if (request->flags & ATA_R_CONTROL) {
2188 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2189 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2190 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2191 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2192 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2193 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2194 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2196 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2197 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2198 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2200 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2202 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2203 KdPrint2(("RCV:\n"));
2204 KdDump(RCV_FIS, 24);
2205 KdPrint2(("PIO:\n"));
2206 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2208 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2209 if(!AHCI_CL->bytecount) {
2210 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2214 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2215 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2216 if(CI
& (1 << tag
)) {
2218 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2219 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2222 UniataDumpAhciPortRegs(chan
);
2224 if(!UniataAhciAbortOperation(chan
)) {
2225 KdPrint2((" Abort failed, need RESET\n"));
2228 UniataDumpAhciPortRegs(chan
);
2230 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2231 if(chan
->AhciPrevCI
) {
2232 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2235 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2236 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2242 } // end UniataAhciEndTransaction()
2252 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2255 //UniataDumpAhciPortRegs(chan);
2258 /* Disable port interrupts */
2259 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2261 /* setup work areas */
2262 base
= chan
->AHCI_CTL_PhAddr
;
2264 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2267 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2268 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2269 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2271 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2272 (ULONG
)(base
& 0xffffffff));
2273 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2274 (ULONG
)((base
>> 32) & 0xffffffff));
2276 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2277 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2278 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2279 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2281 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2282 (ULONG
)(base
& 0xffffffff));
2283 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2284 (ULONG
)((base
>> 32) & 0xffffffff));
2286 /* activate the channel and power/spin up device */
2287 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2288 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2289 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2290 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2294 //UniataDumpAhciPortRegs(chan);
2297 UniataAhciStartFR(chan
);
2298 UniataAhciStart(chan
);
2301 UniataDumpAhciPortRegs(chan
);
2305 } // end UniataAhciResume()
2315 SATA_SCONTROL_REG SControl
;
2317 KdPrint2(("UniataAhciSuspend:\n"));
2319 /* Disable port interrupts */
2320 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2322 /* Reset command register. */
2323 UniataAhciStop(chan
);
2324 UniataAhciStopFR(chan
);
2325 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2327 /* Allow everything including partial and slumber modes. */
2328 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2330 /* Request slumber mode transition and give some time to get there. */
2331 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2332 AtapiStallExecution(100);
2336 SControl
.DET
= SStatus_DET_Offline
;
2337 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2340 } // end UniataAhciSuspend()
2346 IN PHW_CHANNEL chan
,
2347 IN ULONG DeviceNumber
,
2352 //ULONG Channel = deviceExtension->Channel + lChannel;
2357 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2358 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2360 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2362 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2363 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2366 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2368 case IDX_SATA_SStatus
:
2370 case IDX_SATA_SError
:
2372 case IDX_SATA_SControl
:
2379 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2380 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2381 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2382 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2383 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2384 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2385 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2387 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2388 KdPrint2((" PM read failed\n"));
2392 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2394 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2397 } // end UniataAhciReadPM()
2402 IN PHW_CHANNEL chan
,
2403 IN ULONG DeviceNumber
,
2408 //ULONG Channel = deviceExtension->Channel + lChannel;
2414 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2415 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2417 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2419 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2420 UniataSataWritePort4(chan
, Reg
, value
, 0);
2423 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2425 case IDX_SATA_SStatus
:
2427 case IDX_SATA_SError
:
2429 case IDX_SATA_SControl
:
2432 return IDE_STATUS_WRONG
;
2436 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2437 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2438 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2439 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2440 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2441 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2443 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2444 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2445 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2446 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2448 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2450 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2451 KdPrint2((" PM write failed\n"));
2452 return IDE_STATUS_WRONG
;
2455 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2457 if(TFD
& IDE_STATUS_ERROR
) {
2458 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2460 return (UCHAR
)(TFD
>> 8);
2462 } // end UniataAhciWritePM()
2465 UniataAhciSetupCmdPtr(
2466 IN OUT PATA_REQ AtaReq
2471 ULONGLONG prd_base64
;
2475 ULONGLONG prd_base64_0
;
2479 prd_base64_0
= prd_base64
= 0;
2480 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2481 prd_base0
= prd_base
;
2483 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2485 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2486 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2488 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2489 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2490 } // end UniataAhciSetupCmdPtr()
2494 BuildAhciInternalSrb (
2495 IN PVOID HwDeviceExtension
,
2496 IN ULONG DeviceNumber
,
2502 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2503 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2504 PSCSI_REQUEST_BLOCK srb
;
2506 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2508 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2511 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2515 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2516 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2517 UniAtaClearAtaReq(AtaReq
);
2519 srb
= chan
->AhciInternalSrb
;
2521 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2523 srb
->PathId
= (UCHAR
)lChannel
;
2524 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2525 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2526 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2528 // Set flags to disable synchronous negociation.
2529 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2531 // Set timeout to 4 seconds.
2532 srb
->TimeOutValue
= 4;
2535 srb
->DataBuffer
= Buffer
;
2536 srb
->DataTransferLength
= Length
;
2537 srb
->SrbExtension
= AtaReq
;
2540 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2541 AtaReq
->TransferLength
= Length
;
2543 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2544 //UniataAhciSetupCmdPtr(AtaReq);
2545 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2546 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2548 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2549 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2551 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2552 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2554 /* // Set CDB operation code.
2555 cdb = (PCDB)srb->Cdb;
2556 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2557 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2560 } // end BuildAhciInternalSrb()