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
;
653 BOOLEAN MemIo
= FALSE
;
655 KdPrint2((PRINT_PREFIX
" UniataAhciInit:\n"));
658 UniataDumpAhciRegs(deviceExtension
);
661 /* disable AHCI interrupts, for MSI compatibility issue
662 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
663 26. AHCI Reset and MSI Request
666 KdPrint2((PRINT_PREFIX
" get GHC\n"));
667 /* enable AHCI mode */
668 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
669 if(!(GHC
& AHCI_GHC_AE
)) {
670 KdPrint2((PRINT_PREFIX
" enable AHCI mode, disable intr, GHC %#x\n", GHC
));
671 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
672 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
674 KdPrint2((PRINT_PREFIX
" disable intr, GHC %#x\n", GHC
));
675 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
678 AtapiStallExecution(100);
680 /* read GHC again and reset AHCI controller */
681 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
682 KdPrint2((PRINT_PREFIX
" reset AHCI controller, GHC %#x\n", GHC
));
683 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
686 for(i
=0; i
<1000; i
++) {
687 AtapiStallExecution(1000);
688 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
689 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
690 if(!(GHC
& AHCI_GHC_HR
)) {
694 if(GHC
& AHCI_GHC_HR
) {
695 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
699 /* re-enable AHCI mode */
700 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
701 if(!(GHC
& AHCI_GHC_AE
)) {
702 KdPrint2((PRINT_PREFIX
" re-enable AHCI mode, GHC %#x\n", GHC
));
703 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
705 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
707 KdPrint2((PRINT_PREFIX
" AHCI GHC %#x\n", GHC
));
708 if(!(GHC
& AHCI_GHC_AE
)) {
709 KdPrint2((PRINT_PREFIX
" Can't enable AHCI mode\n"));
713 deviceExtension
->AHCI_CAP
=
714 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
715 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x\n", CAP
));
716 if(CAP
& AHCI_CAP_S64A
) {
717 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
718 deviceExtension
->Host64
= TRUE
;
720 KdPrint2((PRINT_PREFIX
" AHCI %d CMD slots\n", (CAP
& AHCI_CAP_NCS_MASK
) >> 8 ));
721 if(CAP
& AHCI_CAP_PMD
) {
722 KdPrint2((PRINT_PREFIX
" AHCI multi-block PIO\n"));
724 if(CAP
& AHCI_CAP_SAM
) {
725 KdPrint2((PRINT_PREFIX
" AHCI legasy SATA\n"));
728 /* get the number of HW channels */
729 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
730 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
733 /* clear interrupts */
734 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
,
735 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
));
737 /* enable AHCI interrupts */
738 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
739 UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
741 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
742 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
744 deviceExtension
->MaxTransferMode
= ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1);
745 KdPrint2((PRINT_PREFIX
" SATA Gen %d\n", ((CAP
& AHCI_CAP_ISS_MASK
) >> 20) ));
747 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
748 chan
= &deviceExtension
->chan
[c
];
749 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
751 KdPrint2((PRINT_PREFIX
" chan %d, offs %#x\n", c
, offs
));
753 chan
->MaxTransferMode
= deviceExtension
->MaxTransferMode
;
755 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
757 chan
->BaseIoAHCI_Port
= deviceExtension
->BaseIoAHCI_0
;
758 chan
->BaseIoAHCI_Port
.Addr
= BaseMemAddress
+ offs
;
760 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
761 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
762 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
763 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
764 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
765 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
766 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
767 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
768 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
769 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
770 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
772 UniataInitSyncBaseIO(chan
);
774 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
775 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
776 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
777 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
778 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
779 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
780 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
781 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
783 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
785 if(!UniataAhciChanImplemented(deviceExtension
, c
)) {
786 KdPrint2((PRINT_PREFIX
" chan %d not implemented\n", c
));
790 UniataAhciResume(chan
);
792 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
796 } // end UniataAhciInit()
800 UniAtaAhciValidateVersion(
801 IN PHW_DEVICE_EXTENSION deviceExtension
,
809 KdPrint((" wrong AHCI revision %#x\n", version
));
818 KdPrint2((PRINT_PREFIX
" Unknown AHCI revision\n"));
819 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"CheckAhciRevision", Strict
)) {
820 KdPrint((" AHCI revision excluded\n"));
825 } // end UniAtaAhciValidateVersion()
830 IN PVOID HwDeviceExtension
,
831 IN PPCI_COMMON_CONFIG pciData
, // optional
832 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
835 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
836 //ULONG slotNumber = deviceExtension->slotNumber;
837 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
848 ULONG NumberChannels
;
849 ULONG BaseMemAddress
;
850 BOOLEAN MemIo
= FALSE
;
851 BOOLEAN found
= FALSE
;
853 KdPrint2((PRINT_PREFIX
" UniataAhciDetect:\n"));
855 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhci", 0)) {
856 KdPrint((" AHCI excluded\n"));
859 BaseMemAddress
= AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, pciData
, SystemIoBusNumber
,
861 if(!BaseMemAddress
) {
862 KdPrint2((PRINT_PREFIX
" AHCI init failed - no IoRange\n"));
865 if((*ConfigInfo
->AccessRanges
)[5].RangeInMemory
) {
866 KdPrint2((PRINT_PREFIX
"MemIo\n"));
869 deviceExtension
->BaseIoAHCI_0
.Addr
= BaseMemAddress
;
870 deviceExtension
->BaseIoAHCI_0
.MemIo
= MemIo
;
873 UniataDumpAhciRegs(deviceExtension
);
876 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
877 if(GHC
& AHCI_GHC_HR
) {
878 KdPrint2((PRINT_PREFIX
" AHCI in reset state\n"));
882 /* check AHCI mode. Save state and try enable */
884 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
885 KdPrint2((PRINT_PREFIX
" check AHCI mode, GHC %#x\n", GHC
));
887 version
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_VS
);
889 if(!(GHC
& AHCI_GHC_AE
)) {
890 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE), check revision %#x\n", version
));
891 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, FALSE
)) {
892 KdPrint2((PRINT_PREFIX
" Non-AHCI\n"));
895 KdPrint2((PRINT_PREFIX
" try enable\n"));
896 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
,
897 (GHC
| AHCI_GHC_AE
) & ~AHCI_GHC_IE
);
898 GHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_GHC
);
900 KdPrint2((PRINT_PREFIX
" re-check AHCI mode, GHC %#x\n", GHC
));
901 if(!(GHC
& AHCI_GHC_AE
)) {
902 KdPrint2((PRINT_PREFIX
" Non-AHCI GHC (!AE)\n"));
907 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
908 CAP2
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP2
);
909 KdPrint2((PRINT_PREFIX
" AHCI CAP %#x, CAP2 %#x\n", CAP
, CAP2
));
910 if(CAP
& AHCI_CAP_S64A
) {
911 KdPrint2((PRINT_PREFIX
" 64bit"));
912 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
915 if(CAP2
& AHCI_CAP2_BOH
) {
916 BOHC
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_BOHC
);
917 KdPrint2((PRINT_PREFIX
" BOHC %#x", BOHC
));
920 if(CAP
& AHCI_CAP_NCQ
) {
921 KdPrint2((PRINT_PREFIX
" NCQ"));
923 if(CAP
& AHCI_CAP_SNTF
) {
924 KdPrint2((PRINT_PREFIX
" SNTF"));
926 if(CAP
& AHCI_CAP_CCC
) {
927 KdPrint2((PRINT_PREFIX
" CCC"));
929 KdPrint2((PRINT_PREFIX
"\n"));
931 /* get the number of HW channels */
932 PI
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_PI
);
933 deviceExtension
->AHCI_PI
= PI
;
934 KdPrint2((PRINT_PREFIX
" AHCI PI %#x\n", PI
));
935 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
937 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
939 KdPrint2((PRINT_PREFIX
" CommandSlots %d\n", (CAP
& AHCI_CAP_NCS_MASK
)>>8 ));
940 KdPrint2((PRINT_PREFIX
" Channels %d\n", n
));
942 switch(deviceExtension
->DevID
) {
955 if(!NumberChannels
) {
956 KdPrint2((PRINT_PREFIX
" Non-AHCI - NumberChannels=0\n"));
962 v_Mj
= ((version
>> 20) & 0xf0) + ((version
>> 16) & 0x0f);
963 v_Mn
= ((version
>> 4) & 0xf0) + (version
& 0x0f);
965 KdPrint2((PRINT_PREFIX
" AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
967 NumberChannels
, PI
));
968 KdPrint((" AHCI SATA Gen %d\n", (((CAP
& AHCI_CAP_ISS_MASK
) >> 20)) ));
971 if(CAP
& AHCI_CAP_SPM
) {
972 KdPrint2((PRINT_PREFIX
" PM supported\n"));
973 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreAhciPM", 1 /* DEBUG */)) {
974 KdPrint2((PRINT_PREFIX
"SATA/AHCI w/o PM, max luns 1\n"));
975 deviceExtension
->NumberLuns
= 1;
976 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
978 KdPrint2((PRINT_PREFIX
"SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS
));
979 deviceExtension
->NumberLuns
= SATA_MAX_PM_UNITS
;
980 //deviceExtension->NumberLuns = 1;
983 KdPrint2((PRINT_PREFIX
" PM not supported -> 1 lun/chan\n"));
984 deviceExtension
->NumberLuns
= 1;
987 if(!UniAtaAhciValidateVersion(deviceExtension
, version
, TRUE
)) {
991 deviceExtension
->HwFlags
|= UNIATA_SATA
| UNIATA_AHCI
;
992 if(deviceExtension
->NumberChannels
< NumberChannels
) {
993 deviceExtension
->NumberChannels
= NumberChannels
;
995 deviceExtension
->DmaSegmentLength
= 0x3fffff+1; // 4MB
996 deviceExtension
->DmaSegmentAlignmentMask
= -1; // no restrictions
998 deviceExtension
->BusMaster
= DMA_MODE_AHCI
;
999 deviceExtension
->MaxTransferMode
= max(deviceExtension
->MaxTransferMode
, ATA_SA150
+(((CAP
& AHCI_CAP_ISS_MASK
) >> 20)-1) );
1004 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_GHC
, GHC0
);
1005 KdPrint((" AHCI detect status %d\n", found
));
1008 } // end UniataAhciDetect()
1013 IN PVOID HwDeviceExtension
,
1015 IN ULONG DeviceNumber
1018 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1019 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1020 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
1024 SATA_SSTATUS_REG SStatus
;
1025 SATA_SERROR_REG SError
;
1026 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1029 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel
, Channel
));
1031 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
1032 KdPrint((" hIS %#x\n", hIS
));
1033 hIS
&= (1 << Channel
);
1035 return INTERRUPT_REASON_IGNORE
;
1037 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1038 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1039 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
1040 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
1041 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1043 /* clear interrupt(s) */
1044 UniataAhciWriteHostPort4(deviceExtension
, IDX_AHCI_IS
, hIS
);
1045 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1046 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
1048 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1049 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
, ACT
));
1051 /* do we have cold connect surprise */
1055 /* check for and handle connect events */
1057 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
1060 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
1062 chan
->AhciCompleteCI
= (chan
->AhciPrevCI
^ CI
) & chan
->AhciPrevCI
; // only 1->0 states
1063 chan
->AhciPrevCI
= CI
;
1064 KdPrint((" AHCI: complete mask %#x\n", chan
->AhciCompleteCI
));
1065 chan
->AhciLastIS
= IS
.Reg
;
1066 if(CI
& (1 << tag
)) {
1068 UniataDumpAhciPortRegs(chan
);
1070 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1072 (ATA_AHCI_P_IX_OF
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
|
1073 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_HBF
| ATA_AHCI_P_IX_TFE
)) {
1074 KdPrint((" AHCI: unexpected, error\n"));
1076 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1080 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1081 KdPrint2((" TFD %#x\n", TFD));
1082 if(TFD & IDE_STATUS_BUSY) {
1083 KdPrint2((" Seems to be interrupt on error\n"));
1084 return INTERRUPT_REASON_OUR;
1087 return INTERRUPT_REASON_UNEXPECTED
;
1090 return INTERRUPT_REASON_OUR
;
1092 } // end UniataAhciStatus()
1096 UniataAhciSnapAtaRegs(
1097 IN PHW_CHANNEL chan
,
1098 IN ULONG DeviceNumber
,
1099 IN OUT PIDEREGS_EX regs
1104 regs
->bDriveHeadReg
= IDE_DRIVE_SELECT_1
;
1105 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1106 regs
->bCommandReg
= (UCHAR
)(TFD
& 0xff);
1107 regs
->bFeaturesReg
= (UCHAR
)((TFD
>> 8) & 0xff);
1109 SIG
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1110 regs
->bSectorCountReg
= (UCHAR
)(SIG
& 0xff);
1111 regs
->bSectorNumberReg
= (UCHAR
)((SIG
>> 8) & 0xff);
1112 regs
->bCylLowReg
= (UCHAR
)((SIG
>> 16) & 0xff);
1113 regs
->bCylHighReg
= (UCHAR
)((SIG
>> 24) & 0xff);
1117 } // end UniataAhciSnapAtaRegs()
1121 UniataAhciSetupFIS_H2D(
1122 IN PHW_DEVICE_EXTENSION deviceExtension
,
1123 IN ULONG DeviceNumber
,
1135 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1137 KdPrint2((PRINT_PREFIX
" AHCI setup FIS %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1139 plba
= (PUCHAR
)&lba
;
1141 RtlZeroMemory(fis
, 20);
1143 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1144 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1145 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1146 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1147 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1149 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1150 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1151 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1153 command
== IDE_COMMAND_ATAPI_PACKET
) {
1154 fis
[IDX_AHCI_o_Command
] = IDE_COMMAND_ATAPI_PACKET
;
1155 if(feature
& ATA_F_DMA
) {
1156 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)(feature
& 0xff);
1158 fis
[IDX_AHCI_o_CylinderLow
] = (UCHAR
)(count
& 0xff);
1159 fis
[IDX_AHCI_o_CylinderHigh
] = (UCHAR
)(count
>>8) & 0xff;
1161 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1164 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
1165 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
1166 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
1167 //return IDE_STATUS_ERROR;
1168 //return SRB_STATUS_ERROR;
1172 need48
= UniAta_need_lba48(command
, lba
, count
,
1173 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
);
1175 /* translate command into 48bit version */
1177 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1178 command
= AtaCommands48
[command
];
1180 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1185 fis
[IDX_AHCI_o_Command
] = command
;
1186 fis
[IDX_AHCI_o_Feature
] = (UCHAR
)feature
;
1188 fis
[IDX_AHCI_o_BlockNumber
] = plba
[0];
1189 fis
[IDX_AHCI_o_CylinderLow
] = plba
[1];
1190 fis
[IDX_AHCI_o_CylinderHigh
] = plba
[2];
1192 fis
[IDX_AHCI_o_BlockCount
] = (UCHAR
)count
& 0xff;
1196 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1198 fis
[IDX_AHCI_o_BlockNumberExp
] = plba
[3];
1199 fis
[IDX_AHCI_o_CylinderLowExp
] = plba
[4];
1200 fis
[IDX_AHCI_o_CylinderHighExp
] = plba
[5];
1202 fis
[IDX_AHCI_o_BlockCountExp
] = (UCHAR
)(count
>>8) & 0xff;
1204 fis
[IDX_AHCI_o_FeatureExp
] = (UCHAR
)(feature
>>8) & 0xff;
1206 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1209 //#pragma warning(push)
1210 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1212 fis
[IDX_AHCI_o_DriveSelect
] |= /*IDE_DRIVE_1 |*/ (plba
[3] & 0x0f);
1213 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1215 //#pragma warning(pop)
1226 } // end UniataAhciSetupFIS_H2D()
1230 UniataAhciSetupFIS_H2D_Direct(
1231 IN PHW_DEVICE_EXTENSION deviceExtension
,
1232 IN ULONG DeviceNumber
,
1241 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1244 command
= regs
->bCommandReg
;
1246 KdPrint2((PRINT_PREFIX
" AHCI setup FIS Direct %x, ch %d, dev %d\n", fis
, lChannel
, DeviceNumber
));
1248 //plba = (PUCHAR)&lba;
1250 RtlZeroMemory(fis
, 20);
1252 fis
[0] = AHCI_FIS_TYPE_ATA_H2D
; /* host to device */
1253 fis
[1] = 0x80 | ((UCHAR
)DeviceNumber
& 0x0f); /* command FIS (note PM goes here) */
1254 fis
[IDX_AHCI_o_DriveSelect
] = IDE_DRIVE_SELECT_1
|
1255 ((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_48
)) ? IDE_USE_LBA
: 0);
1256 fis
[IDX_AHCI_o_Control
] = IDE_DC_A_4BIT
;
1258 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1259 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1260 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1262 command
== IDE_COMMAND_ATAPI_PACKET
) {
1263 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1264 if(feature & ATA_F_DMA) {
1265 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1267 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1268 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1271 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1274 need48
= (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) &&
1275 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
;
1277 /* translate command into 48bit version */
1279 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
1280 command
= AtaCommands48
[command
];
1282 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
1287 fis
[IDX_AHCI_o_Command
] = command
;
1288 fis
[IDX_AHCI_o_Feature
] = regs
->bFeaturesReg
;
1290 fis
[IDX_AHCI_o_BlockNumber
] = regs
->bSectorNumberReg
;
1291 fis
[IDX_AHCI_o_CylinderLow
] = regs
->bCylLowReg
;
1292 fis
[IDX_AHCI_o_CylinderHigh
] = regs
->bCylHighReg
;
1294 fis
[IDX_AHCI_o_BlockCount
] = regs
->bSectorCountReg
;
1298 fis
[IDX_AHCI_o_Control
] |= IDE_DC_USE_HOB
;
1300 fis
[IDX_AHCI_o_BlockNumberExp
] = regs
->bSectorNumberRegH
;
1301 fis
[IDX_AHCI_o_CylinderLowExp
] = regs
->bCylLowRegH
;
1302 fis
[IDX_AHCI_o_CylinderHighExp
] = regs
->bCylHighRegH
;
1304 fis
[IDX_AHCI_o_BlockCountExp
] = regs
->bSectorCountRegH
;
1306 fis
[IDX_AHCI_o_FeatureExp
] = regs
->bFeaturesRegH
;
1308 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
1310 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1311 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
1313 fis
[IDX_AHCI_o_DriveSelect
] |= regs
->bDriveHeadReg
& 0x0f;
1319 } // end UniataAhciSetupFIS_H2D_Direct()
1323 UniataAhciWaitCommandReady(
1324 IN PHW_CHANNEL chan
,
1337 for (i
=0; i
<timeout
; i
++) {
1338 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
1339 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1340 if (!(( CI
>> tag
) & 0x01)) {
1343 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1344 //KdPrint((" IS %#x\n", IS.Reg));
1348 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1350 KdPrint((" AHCI: error %#x\n", SError
));
1354 AtapiStallExecution(200);
1356 KdPrint((" CI %#x\n", CI
));
1358 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1359 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1361 /* clear interrupt(s) */
1362 IS
.Reg
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1363 KdPrint((" IS %#x\n", IS
.Reg
));
1364 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
.Reg
);
1366 if (timeout
&& (i
>= timeout
)) {
1370 SError
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1371 KdPrint((" AHCI: timeout, SError %#x\n", SError
));
1373 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1374 KdPrint2((" TFD %#x\n", TFD
));
1377 return IDE_STATUS_WRONG
;
1380 return IDE_STATUS_IDLE
;
1381 } // end UniataAhciWaitCommandReady()
1385 UniataAhciSendCommand(
1386 IN PVOID HwDeviceExtension
,
1388 IN ULONG DeviceNumber
,
1389 IN USHORT ahci_flags
,
1393 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1394 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1395 //ULONG Channel = deviceExtension->Channel + lChannel;
1398 //SATA_SSTATUS_REG SStatus;
1399 //SATA_SERROR_REG SError;
1400 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1404 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
1406 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan
->lChannel
));
1408 AHCI_CL
->prd_length
= 0;
1409 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1410 AHCI_CL
->cmd_flags
= UniAtaAhciAdjustIoFlags(0, ahci_flags
, 20, DeviceNumber
);
1412 AHCI_CL
->bytecount
= 0;
1413 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
1414 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
1415 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
1418 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1419 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 1 << tag
);
1421 return UniataAhciWaitCommandReady(chan
, timeout
);
1423 } // end UniataAhciSendCommand()
1427 UniataAhciSendPIOCommand(
1428 IN PVOID HwDeviceExtension
,
1430 IN ULONG DeviceNumber
,
1431 IN PSCSI_REQUEST_BLOCK Srb
,
1433 IN ULONG length
, /* bytes */
1436 IN USHORT bcount
, /* block count, just ATA register */
1438 IN USHORT ahci_flags
,
1439 IN ULONG wait_flags
,
1443 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1444 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1449 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1450 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1452 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1454 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1455 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, command
, lba
, bcount
, feature
, data
, length
, wait_flags
));
1457 if(length
/DEV_BSIZE
!= bcount
) {
1458 KdPrint((" length/DEV_BSIZE != bcount\n"));
1462 //UniataDumpAhciPortRegs(chan);
1466 Srb
= BuildAhciInternalSrb(HwDeviceExtension
, DeviceNumber
, lChannel
, data
, length
);
1468 KdPrint((" !Srb\n"));
1469 return IDE_STATUS_WRONG
;
1471 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1472 //should be already called on init
1474 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1475 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1477 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1479 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
1480 &(AHCI_CMD
->cfis
[0]),
1488 KdPrint2(("!fis_size\n"));
1489 return IDE_STATUS_WRONG
;
1492 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1493 ahci_flags
= UniAtaAhciAdjustIoFlags(command
, ahci_flags
, fis_size
, DeviceNumber
);
1494 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1497 if(ahci_flags
& ATA_AHCI_CMD_WRITE
) {
1498 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1499 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
1500 KdPrint((" assume OUT\n"));
1502 AtaReq
->Flags
|= REQ_FLAG_READ
;
1503 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
1504 KdPrint((" assume IN\n"));
1506 if(!AtapiDmaSetup(HwDeviceExtension
,
1508 lChannel
, // logical channel,
1512 KdPrint2((" can't setup buffer\n"));
1513 return IDE_STATUS_WRONG
;
1517 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1520 //UniataDumpAhciPortRegs(chan);
1523 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1526 //UniataDumpAhciPortRegs(chan);
1529 if(wait_flags
== ATA_IMMEDIATE
) {
1531 KdPrint2((" return imemdiately\n"));
1533 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1534 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1535 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1540 } // end UniataAhciSendPIOCommand()
1544 UniataAhciSendPIOCommandDirect(
1545 IN PVOID HwDeviceExtension
,
1547 IN ULONG DeviceNumber
,
1548 IN PSCSI_REQUEST_BLOCK Srb
,
1549 IN PIDEREGS_EX regs
,
1550 IN ULONG wait_flags
,
1554 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1555 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1560 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1561 PIDE_AHCI_CMD AHCI_CMD
= NULL
;
1562 USHORT ahci_flags
=0;
1565 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1567 KdPrint2((PRINT_PREFIX
"UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1568 deviceExtension
->DevIndex
, lChannel
, DeviceNumber
, Srb
->DataBuffer
, Srb
->DataTransferLength
, wait_flags
));
1570 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1571 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1575 //UniataDumpAhciPortRegs(chan);
1579 KdPrint((" !Srb\n"));
1580 return IDE_STATUS_WRONG
;
1581 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1582 //should be already called on init
1584 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
1585 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1587 AHCI_CMD
= AtaReq
->ahci
.ahci_cmd_ptr
;
1589 KdPrint((" !AHCI_CMD\n"));
1590 return IDE_STATUS_WRONG
;
1593 if(Srb
->DataTransferLength
) {
1594 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
1595 ahci_flags
|= ATA_AHCI_CMD_WRITE
;
1596 AtaReq
->Flags
&= ~REQ_FLAG_READ
;
1598 AtaReq
->Flags
|= REQ_FLAG_READ
;
1602 fis_size
= UniataAhciSetupFIS_H2D_Direct(deviceExtension
, DeviceNumber
, lChannel
,
1603 &(AHCI_CMD
->cfis
[0]),
1607 KdPrint2(("!fis_size\n"));
1608 return IDE_STATUS_WRONG
;
1611 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1612 ahci_flags
= UniAtaAhciAdjustIoFlags(regs
->bCommandReg
, ahci_flags
, fis_size
, DeviceNumber
);
1613 KdPrint2(("ahci_flags %#x\n", ahci_flags
));
1615 if(Srb
->DataTransferLength
) {
1616 if(!AtapiDmaSetup(HwDeviceExtension
,
1618 lChannel
, // logical channel,
1620 (PUCHAR
)(Srb
->DataBuffer
),
1621 Srb
->DataTransferLength
)) {
1622 KdPrint2((" can't setup buffer\n"));
1623 return IDE_STATUS_WRONG
;
1627 AtaReq
->ahci
.io_cmd_flags
= ahci_flags
;
1630 //UniataDumpAhciPortRegs(chan);
1633 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1636 //UniataDumpAhciPortRegs(chan);
1639 if(wait_flags
== ATA_IMMEDIATE
) {
1641 KdPrint2((" return imemdiately\n"));
1643 statusByte
= UniataAhciWaitCommandReady(chan
, timeout
);
1644 UniataAhciStatus(HwDeviceExtension
, lChannel
, DeviceNumber
);
1645 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
1650 } // end UniataAhciSendPIOCommandDirect()
1654 UniataAhciAbortOperation(
1658 /* kick controller into sane state */
1659 if(!UniataAhciStop(chan
)) {
1662 if(!UniataAhciStopFR(chan
)) {
1665 if(!UniataAhciCLO(chan
)) {
1668 UniataAhciStartFR(chan
);
1669 UniataAhciStart(chan
);
1672 } // end UniataAhciAbortOperation()
1676 UniataAhciSoftReset(
1677 IN PVOID HwDeviceExtension
,
1679 IN ULONG DeviceNumber
1682 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1683 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1684 //ULONG Channel = deviceExtension->Channel + lChannel;
1690 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan
->lChannel
));
1692 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
1693 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
1695 /* kick controller into sane state */
1696 if(!UniataAhciAbortOperation(chan
)) {
1697 KdPrint2((" abort failed\n"));
1701 /* pull reset active */
1702 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1703 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1704 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1705 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1706 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
| IDE_DC_RESET_CONTROLLER
);
1708 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, ATA_AHCI_CMD_RESET
| ATA_AHCI_CMD_CLR_BUSY
, 100) == IDE_STATUS_WRONG
) {
1709 KdPrint2((" timeout\n"));
1712 AtapiStallExecution(50);
1714 /* pull reset inactive */
1715 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
1716 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
1717 AHCI_CMD
->cfis
[1] = (UCHAR
)DeviceNumber
& 0x0f;
1718 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1719 AHCI_CMD
->cfis
[15] = (IDE_DC_A_4BIT
);
1720 if(UniataAhciSendCommand(HwDeviceExtension
, lChannel
, DeviceNumber
, 0, 3000) == IDE_STATUS_WRONG
) {
1721 KdPrint2((" timeout (2)\n"));
1725 UniataAhciWaitReady(chan
, 1);
1727 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
1729 return UniataAhciUlongFromRFIS(RCV_FIS
);
1731 } // end UniataAhciSoftReset()
1735 UniataAhciWaitReady(
1736 IN PHW_CHANNEL chan
,
1743 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan
->lChannel
));
1745 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1747 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1748 for(i
=0; i
<timeout
&& (TFD
&
1749 (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)); i
++) {
1750 AtapiStallExecution(1000);
1751 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
1754 KdPrint2((" TFD %#x\n", TFD
));
1758 } // end UniataAhciWaitReady()
1762 UniataAhciHardReset(
1763 IN PVOID HwDeviceExtension
,
1765 OUT PULONG signature
1768 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1769 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1770 //ULONG Channel = deviceExtension->Channel + lChannel;
1774 KdPrint(("UniataAhciHardReset: lChan %d\n", chan
->lChannel
));
1776 (*signature
) = 0xffffffff;
1778 UniataAhciStop(chan
);
1779 if(UniataSataPhyEnable(HwDeviceExtension
, lChannel
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
) == IDE_STATUS_WRONG
) {
1780 KdPrint((" no PHY\n"));
1781 return IDE_STATUS_WRONG
;
1784 /* Wait for clearing busy status. */
1785 TFD
= UniataAhciWaitReady(chan
, 15000);
1786 if(TFD
& (IDE_STATUS_DRQ
| IDE_STATUS_BUSY
)) {
1787 KdPrint((" busy: TFD %#x\n", TFD
));
1790 KdPrint((" TFD %#x\n", TFD
));
1793 UniataDumpAhciPortRegs(chan
);
1796 (*signature
) = UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_SIG
);
1797 KdPrint((" sig: %#x\n", *signature
));
1799 UniataAhciStart(chan
);
1803 } // end UniataAhciHardReset()
1808 IN PVOID HwDeviceExtension
,
1812 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1813 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1814 //ULONG Channel = deviceExtension->Channel + lChannel;
1815 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1820 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1822 KdPrint(("UniataAhciReset: lChan %d\n", chan
->lChannel
));
1824 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1826 /* Disable port interrupts */
1827 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
1829 if(UniataAhciHardReset(HwDeviceExtension
, lChannel
, &signature
)) {
1831 KdPrint((" No devices in all LUNs\n"));
1832 for (i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
1833 // Zero device fields to ensure that if earlier devices were found,
1834 // but not claimed, the fields are cleared.
1835 UniataForgetDevice(chan
->lun
[i
]);
1838 /* enable wanted port interrupts */
1839 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1840 ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
);
1844 /* enable wanted port interrupts */
1845 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
1846 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
1847 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
1848 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
) : 0) |
1849 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
1850 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
) );
1853 * Only probe for PortMultiplier if HW has support.
1854 * Ignore Marvell, which is not working,
1856 CAP
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_CAP
);
1857 if ((CAP
& AHCI_CAP_SPM
) &&
1858 (VendorID
!= ATA_MARVELL_ID
)) {
1859 KdPrint((" check PM\n"));
1860 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, AHCI_DEV_SEL_PM
);
1861 /* Workaround for some ATI chips, failing to soft-reset
1862 * when port multiplicator supported, but absent.
1863 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1864 if (signature
== 0xffffffff) {
1865 KdPrint((" re-check PM\n"));
1866 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1869 signature
= UniataAhciSoftReset(HwDeviceExtension
, lChannel
, 0);
1872 KdPrint((" signature %#x\n", signature
));
1873 chan
->lun
[0]->DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| CTRFLAGS_AHCI_PM
);
1874 switch (signature
>> 16) {
1876 KdPrint((" ATA dev\n"));
1877 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1882 if(deviceExtension
->NumberLuns
> 1) {
1883 chan
->ChannelCtrlFlags
|= CTRFLAGS_AHCI_PM
;
1884 UniataSataIdentifyPM(chan
);
1886 KdPrint((" no PM supported (1 lun/chan)\n"));
1890 KdPrint((" ATAPI dev\n"));
1891 chan
->lun
[0]->DeviceFlags
|= (DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
);
1894 default: /* SOS XXX */
1895 KdPrint((" default to ATA ???\n"));
1896 chan
->lun
[0]->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
1902 } // end UniataAhciReset()
1912 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan
->lChannel
));
1914 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1915 KdPrint2((" CMD %#x\n", CMD
));
1916 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
| ATA_AHCI_P_CMD_FRE
);
1919 } // end UniataAhciStartFR()
1930 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan
->lChannel
));
1932 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1933 KdPrint2((" CMD %#x\n", CMD
));
1934 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
& ~ATA_AHCI_P_CMD_FRE
);
1936 for(i
=0; i
<1000; i
++) {
1937 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1938 if(!(CMD
& ATA_AHCI_P_CMD_FR
)) {
1939 KdPrint2((" final CMD %#x\n", CMD
));
1942 AtapiStallExecution(1000);
1944 KdPrint2((" CMD %#x\n", CMD
));
1945 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
1946 KdPrint2(("UniataAhciStopFR: timeout\n"));
1948 } // end UniataAhciStopFR()
1957 SATA_SERROR_REG SError
;
1959 KdPrint2(("UniataAhciStart: lChan %d\n", chan
->lChannel
));
1961 /* clear SATA error register */
1962 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
1964 /* clear any interrupts pending on this channel */
1965 IS
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_IS
);
1966 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IS
, IS
);
1968 KdPrint2((" SError %#x, IS %#x\n", SError
.Reg
, IS
));
1970 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
1971 KdPrint2((" CMD %#x\n", CMD
));
1972 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
1975 ((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) ? ATA_AHCI_P_CMD_PMA
: 0));
1978 } // end UniataAhciStart()
1986 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1987 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1989 //SATA_SERROR_REG SError;
1992 KdPrint2(("UniataAhciCLO: lChan %d\n", chan
->lChannel
));
1994 /* issue Command List Override if supported */
1995 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1996 CAP
= chan
->DeviceExtension
->AHCI_CAP
;
1997 if(!(CAP
& AHCI_CAP_SCLO
)) {
2000 KdPrint2((" send CLO\n"));
2001 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2002 CMD
|= ATA_AHCI_P_CMD_CLO
;
2003 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2005 for(i
=0; i
<1000; i
++) {
2006 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2007 if(!(CMD
& ATA_AHCI_P_CMD_CLO
)) {
2008 KdPrint2((" final CMD %#x\n", CMD
));
2011 AtapiStallExecution(1000);
2013 KdPrint2((" CMD %#x\n", CMD
));
2014 KdPrint2(("UniataAhciCLO: timeout\n"));
2016 } // end UniataAhciCLO()
2025 //SATA_SERROR_REG SError;
2028 KdPrint2(("UniataAhciStop: lChan %d\n", chan
->lChannel
));
2030 /* issue Command List Override if supported */
2031 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2032 CMD
&= ~ATA_AHCI_P_CMD_ST
;
2033 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2035 for(i
=0; i
<1000; i
++) {
2036 CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2037 if(!(CMD
& ATA_AHCI_P_CMD_CR
)) {
2038 KdPrint2((" final CMD %#x\n", CMD
));
2041 AtapiStallExecution(1000);
2043 KdPrint2((" CMD %#x\n", CMD
));
2044 KdPrint((" SError %#x\n", AtapiReadPort4(chan
, IDX_SATA_SError
)));
2045 KdPrint2(("UniataAhciStop: timeout\n"));
2047 } // end UniataAhciStop()
2051 UniataAhciBeginTransaction(
2052 IN PVOID HwDeviceExtension
,
2054 IN ULONG DeviceNumber
,
2055 IN PSCSI_REQUEST_BLOCK Srb
2058 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2059 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2060 //ULONG Channel = deviceExtension->Channel + lChannel;
2064 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2065 //SATA_SSTATUS_REG SStatus;
2066 //SATA_SERROR_REG SError;
2067 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2072 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2074 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan
->lChannel
, AtaReq
));
2076 if(Srb
->DataTransferLength
&& (!AtaReq
->dma_entries
|| AtaReq
->dma_entries
>= (USHORT
)0xffff)) {
2077 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq
->dma_entries
));
2081 AHCI_CL
->prd_length
= (USHORT
)(AtaReq
->dma_entries
);
2082 AHCI_CL
->cmd_flags
= AtaReq
->ahci
.io_cmd_flags
;
2083 AHCI_CL
->bytecount
= 0;
2084 if(AtaReq
->ahci
.ahci_base64
) {
2085 KdPrint2((PRINT_PREFIX
" AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
)));
2086 AHCI_CL
->cmd_table_phys
= AtaReq
->ahci
.ahci_base64
;
2088 if(AtaReq
->ahci
.ahci_cmd_ptr
) {
2089 KdPrint2((PRINT_PREFIX
" AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2090 AtaReq
->ahci
.ahci_cmd_ptr
, (ULONG
)(AtaReq
->ahci
.ahci_base64
),
2091 &(chan
->AhciCtlBlock
->cmd
), chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
) ));
2092 RtlCopyMemory(&(chan
->AhciCtlBlock
->cmd
), AtaReq
->ahci
.ahci_cmd_ptr
,
2093 FIELD_OFFSET(IDE_AHCI_CMD
, prd_tab
)+AHCI_CL
->prd_length
*sizeof(IDE_AHCI_PRD_ENTRY
));
2094 AHCI_CL
->cmd_table_phys
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, cmd
);
2096 KdPrint2((PRINT_PREFIX
" no AHCI CMD\n"));
2097 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2100 if(AHCI_CL
->cmd_table_phys
& AHCI_CMD_ALIGNEMENT_MASK
) {
2101 KdPrint2((PRINT_PREFIX
" AHCI CMD address is not aligned (mask %#x)\n", (ULONG
)AHCI_CMD_ALIGNEMENT_MASK
));
2106 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL
->prd_length
, AHCI_CL
->cmd_flags
,
2107 AHCI_CL
->cmd_table_phys
));
2110 CMD0
= CMD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CMD
);
2111 KdPrint2((" CMD %#x\n", CMD
));
2112 // switch controller to ATAPI mode for ATA_PACKET commands only
2113 if(ATAPI_DEVICE(chan
, DeviceNumber
) &&
2114 AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_PACKET
) {
2115 KdPrint2((" ATAPI\n"));
2116 CMD
|= ATA_AHCI_P_CMD_ATAPI
;
2117 KdDump(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), 16);
2119 CMD
&= ~ATA_AHCI_P_CMD_ATAPI
;
2122 KdPrint2((" send CMD %#x, entries %#x\n", CMD
, AHCI_CL
->prd_length
));
2123 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, CMD
);
2126 /* issue command to controller */
2127 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2128 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CI
, 0x01 << tag
);
2129 chan
->AhciPrevCI
|= 0x01 << tag
;
2131 if(!ATAPI_DEVICE(chan
, DeviceNumber
)) {
2132 // TODO: check if we send ATA_RESET and wait for ready of so.
2133 if(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[2] == IDE_COMMAND_ATAPI_RESET
) {
2137 for(i
=0; i
<1000000; i
++) {
2138 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2139 if(!(TFD
& IDE_STATUS_BUSY
)) {
2143 if(TFD
& IDE_STATUS_BUSY
) {
2144 KdPrint2((" timeout\n"));
2146 if(TFD
& IDE_STATUS_ERROR
) {
2147 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2149 AtaReq
->ahci
.in_status
= TFD
;
2151 return IDE_STATUS_SUCCESS
;
2155 return IDE_STATUS_IDLE
;
2157 } // end UniataAhciBeginTransaction()
2161 UniataAhciEndTransaction(
2162 IN PVOID HwDeviceExtension
,
2164 IN ULONG DeviceNumber
,
2165 IN PSCSI_REQUEST_BLOCK Srb
2168 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2169 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2170 //ULONG Channel = deviceExtension->Channel + lChannel;
2173 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2175 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2178 PIDE_AHCI_CMD_LIST AHCI_CL
= &(chan
->AhciCtlBlock
->cmd_list
[tag
]);
2179 //PHW_LU_EXTENSION LunExt;
2181 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan
->lChannel
));
2183 //LunExt = chan->lun[DeviceNumber];
2185 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2186 KdPrint2((" TFD %#x\n", TFD
));
2188 if(TFD
& IDE_STATUS_ERROR
) {
2189 AtaReq
->ahci
.in_error
= (UCHAR
)(TFD
>> 8);
2190 KdPrint2((" ERROR %#x\n", AtaReq
->ahci
.in_error
));
2192 AtaReq
->ahci
.in_error
= 0;
2194 AtaReq
->ahci
.in_status
= TFD
;
2196 //if (request->flags & ATA_R_CONTROL) {
2198 AtaReq
->ahci
.in_bcount
= (ULONG
)(RCV_FIS
[12]) | ((ULONG
)(RCV_FIS
[13]) << 8);
2199 AtaReq
->ahci
.in_lba
= (ULONG
)(RCV_FIS
[4]) | ((ULONGLONG
)(RCV_FIS
[5]) << 8) |
2200 ((ULONGLONG
)(RCV_FIS
[6]) << 16);
2201 if(chan
->ChannelCtrlFlags
& CTRFLAGS_LBA48
) {
2202 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2203 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2204 ((ULONGLONG
)(RCV_FIS
[10]) << 40);
2206 AtaReq
->ahci
.in_lba
|= ((ULONGLONG
)(RCV_FIS
[8]) << 24) |
2207 ((ULONGLONG
)(RCV_FIS
[9]) << 32) |
2208 ((ULONGLONG
)(RCV_FIS
[7] & 0x0f) << 24);
2210 AtaReq
->WordsTransfered
= AHCI_CL
->bytecount
/2;
2212 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2213 KdPrint2(("RCV:\n"));
2214 KdDump(RCV_FIS, 24);
2215 KdPrint2(("PIO:\n"));
2216 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2218 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2219 if(!AHCI_CL->bytecount) {
2220 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2224 ACT
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_ACT
);
2225 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
2226 if(CI
& (1 << tag
)) {
2228 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI
, ACT
));
2229 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS
[2], RCV_FIS
[3]));
2232 UniataDumpAhciPortRegs(chan
);
2234 if(!UniataAhciAbortOperation(chan
)) {
2235 KdPrint2((" Abort failed, need RESET\n"));
2238 UniataDumpAhciPortRegs(chan
);
2240 chan
->AhciPrevCI
= CI
& ~((ULONG
)1 << tag
);
2241 if(chan
->AhciPrevCI
) {
2242 KdPrint2((" Need command list restart, CI %#x\n", chan
->AhciPrevCI
));
2245 chan
->AhciPrevCI
&= ~((ULONG
)1 << tag
);
2246 RtlZeroMemory(AHCI_CL
, sizeof(IDE_AHCI_CMD_LIST
));
2252 } // end UniataAhciEndTransaction()
2262 KdPrint2(("UniataAhciResume: lChan %d\n", chan
->lChannel
));
2265 //UniataDumpAhciPortRegs(chan);
2268 /* Disable port interrupts */
2269 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2271 /* setup work areas */
2272 base
= chan
->AHCI_CTL_PhAddr
;
2274 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
2277 KdPrint2((PRINT_PREFIX
" AHCI CLB setup\n"));
2278 if(base
& AHCI_CLB_ALIGNEMENT_MASK
) {
2279 KdPrint2((PRINT_PREFIX
" AHCI CLB address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2281 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
,
2282 (ULONG
)(base
& 0xffffffff));
2283 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CLB
+ 4,
2284 (ULONG
)((base
>> 32) & 0xffffffff));
2286 KdPrint2((PRINT_PREFIX
" AHCI RCV FIS setup\n"));
2287 base
= chan
->AHCI_CTL_PhAddr
+ FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK
, rcv_fis
);
2288 if(base
& AHCI_FIS_ALIGNEMENT_MASK
) {
2289 KdPrint2((PRINT_PREFIX
" AHCI FIS address is not aligned (mask %#x)\n", (ULONG
)AHCI_FIS_ALIGNEMENT_MASK
));
2291 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
,
2292 (ULONG
)(base
& 0xffffffff));
2293 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_FB
+ 4,
2294 (ULONG
)((base
>> 32) & 0xffffffff));
2296 /* activate the channel and power/spin up device */
2297 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
,
2298 (ATA_AHCI_P_CMD_ACTIVE
| ATA_AHCI_P_CMD_POD
| ATA_AHCI_P_CMD_SUD
|
2299 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
)) ? ATA_AHCI_P_CMD_ALPE
: 0) |
2300 (((chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM2
)) ? ATA_AHCI_P_CMD_ASP
: 0 ))
2304 //UniataDumpAhciPortRegs(chan);
2307 UniataAhciStartFR(chan
);
2308 UniataAhciStart(chan
);
2311 UniataDumpAhciPortRegs(chan
);
2315 } // end UniataAhciResume()
2325 SATA_SCONTROL_REG SControl
;
2327 KdPrint2(("UniataAhciSuspend:\n"));
2329 /* Disable port interrupts */
2330 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
2332 /* Reset command register. */
2333 UniataAhciStop(chan
);
2334 UniataAhciStopFR(chan
);
2335 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, 0);
2337 /* Allow everything including partial and slumber modes. */
2338 UniataSataWritePort4(chan
, IDX_SATA_SControl
, 0, 0);
2340 /* Request slumber mode transition and give some time to get there. */
2341 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_CMD
, ATA_AHCI_P_CMD_SLUMBER
);
2342 AtapiStallExecution(100);
2346 SControl
.DET
= SStatus_DET_Offline
;
2347 UniataSataWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
, 0);
2350 } // end UniataAhciSuspend()
2356 IN PHW_CHANNEL chan
,
2357 IN ULONG DeviceNumber
,
2362 //ULONG Channel = deviceExtension->Channel + lChannel;
2367 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2368 PUCHAR RCV_FIS
= &(chan
->AhciCtlBlock
->rcv_fis
.rfis
[0]);
2370 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan
->lChannel
, DeviceNumber
));
2372 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2373 (*result
) = UniataSataReadPort4(chan
, Reg
, 0);
2376 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2378 case IDX_SATA_SStatus
:
2380 case IDX_SATA_SError
:
2382 case IDX_SATA_SControl
:
2389 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2390 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2391 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2392 AHCI_CMD
->cfis
[2] = IDE_COMMAND_READ_PM
;
2393 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2394 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2395 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2397 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 10) == IDE_STATUS_WRONG
) {
2398 KdPrint2((" PM read failed\n"));
2402 KdDump(RCV_FIS
, sizeof(chan
->AhciCtlBlock
->rcv_fis
.rfis
));
2404 (*result
) = UniataAhciUlongFromRFIS(RCV_FIS
);
2407 } // end UniataAhciReadPM()
2412 IN PHW_CHANNEL chan
,
2413 IN ULONG DeviceNumber
,
2418 //ULONG Channel = deviceExtension->Channel + lChannel;
2424 PIDE_AHCI_CMD AHCI_CMD
= &(chan
->AhciCtlBlock
->cmd
);
2425 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2427 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan
->lChannel
, DeviceNumber
, value
));
2429 if(DeviceNumber
== DEVNUM_NOT_SPECIFIED
) {
2430 UniataSataWritePort4(chan
, Reg
, value
, 0);
2433 if(DeviceNumber
< AHCI_DEV_SEL_PM
) {
2435 case IDX_SATA_SStatus
:
2437 case IDX_SATA_SError
:
2439 case IDX_SATA_SControl
:
2442 return IDE_STATUS_WRONG
;
2446 RtlZeroMemory(AHCI_CMD
->cfis
, sizeof(AHCI_CMD
->cfis
));
2447 AHCI_CMD
->cfis
[0] = AHCI_FIS_TYPE_ATA_H2D
;
2448 AHCI_CMD
->cfis
[1] = AHCI_FIS_COMM_PM
;
2449 AHCI_CMD
->cfis
[2] = IDE_COMMAND_WRITE_PM
;
2450 AHCI_CMD
->cfis
[3] = (UCHAR
)Reg
;
2451 AHCI_CMD
->cfis
[7] = (UCHAR
)(IDE_USE_LBA
| DeviceNumber
);
2453 AHCI_CMD
->cfis
[12] = (UCHAR
)(value
& 0xff);
2454 AHCI_CMD
->cfis
[4] = (UCHAR
)((value
>> 8) & 0xff);
2455 AHCI_CMD
->cfis
[5] = (UCHAR
)((value
>> 16) & 0xff);
2456 AHCI_CMD
->cfis
[6] = (UCHAR
)((value
>> 24) & 0xff);
2458 AHCI_CMD
->cfis
[15] = IDE_DC_A_4BIT
;
2460 if(UniataAhciSendCommand(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
, 0, 100) == IDE_STATUS_WRONG
) {
2461 KdPrint2((" PM write failed\n"));
2462 return IDE_STATUS_WRONG
;
2465 TFD
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_TFD
);
2467 if(TFD
& IDE_STATUS_ERROR
) {
2468 KdPrint2((" ERROR %#x\n", (UCHAR
)(TFD
>> 8)));
2470 return (UCHAR
)(TFD
>> 8);
2472 } // end UniataAhciWritePM()
2475 UniataAhciSetupCmdPtr(
2476 IN OUT PATA_REQ AtaReq
2481 ULONGLONG prd_base64
;
2485 ULONGLONG prd_base64_0
;
2491 prd_base64_0
= prd_base64
= 0;
2492 prd_base
= (PUCHAR
)(&AtaReq
->ahci_cmd0
);
2493 prd_base0
= prd_base
;
2495 prd_base64
= (prd_base64
+ max(FIELD_OFFSET(ATA_REQ
, ahci_cmd0
), AHCI_CMD_ALIGNEMENT_MASK
+1)) & ~AHCI_CMD_ALIGNEMENT_MASK
;
2498 d
= (ULONG
)(prd_base64
- prd_base64_0
);
2499 KdPrint2((PRINT_PREFIX
" AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq
, prd_base64
, d
));
2502 AtaReq
->ahci
.ahci_cmd_ptr
= (PIDE_AHCI_CMD
)prd_base64
;
2503 KdPrint2((PRINT_PREFIX
" ahci_cmd_ptr %#x\n", AtaReq
->ahci
.ahci_cmd_ptr
));
2504 } // end UniataAhciSetupCmdPtr()
2508 BuildAhciInternalSrb (
2509 IN PVOID HwDeviceExtension
,
2510 IN ULONG DeviceNumber
,
2516 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2517 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
2518 PSCSI_REQUEST_BLOCK srb
;
2520 PATA_REQ AtaReq
= chan
->AhciInternalAtaReq
;
2522 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel
, DeviceNumber
));
2525 KdPrint2((PRINT_PREFIX
" !chan->AhciInternalAtaReq\n"));
2529 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2530 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2531 UniAtaClearAtaReq(AtaReq
);
2533 srb
= chan
->AhciInternalSrb
;
2535 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
2537 srb
->PathId
= (UCHAR
)lChannel
;
2538 srb
->TargetId
= (UCHAR
)DeviceNumber
;
2539 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2540 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2542 // Set flags to disable synchronous negociation.
2543 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2545 // Set timeout to 4 seconds.
2546 srb
->TimeOutValue
= 4;
2549 srb
->DataBuffer
= Buffer
;
2550 srb
->DataTransferLength
= Length
;
2551 srb
->SrbExtension
= AtaReq
;
2554 AtaReq
->DataBuffer
= (PUSHORT
)Buffer
;
2555 AtaReq
->TransferLength
= Length
;
2557 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2558 //UniataAhciSetupCmdPtr(AtaReq);
2559 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2560 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2562 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2563 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2565 KdPrint2((PRINT_PREFIX
" Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb
, AtaReq
,
2566 AtaReq
->ahci
.ahci_cmd_ptr
, AtaReq
->ahci
.ahci_base64
));
2568 /* // Set CDB operation code.
2569 cdb = (PCDB)srb->Cdb;
2570 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2571 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2574 } // end BuildAhciInternalSrb()