3 * Copyright (C) 2012 secunet Security Networks AG
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 //#define DEBUG_STATUS
34 #include <libpayload.h>
37 #include <storage/ata.h>
38 #include <storage/ahci.h>
40 #include "ahci_private.h"
43 static inline u32
_ahci_clear_status(volatile u32
*const reg
,
47 const u32 bits
= *reg
;
50 printf("ahci: %s: %s == 0x%08x\n", f
, r
, bits
);
54 #define ahci_clear_status(p, r) _ahci_clear_status(&(p)->r, #r, __func__)
56 static inline u32
_ahci_clear_status(volatile u32
*const reg
)
58 const u32 bits
= *reg
;
63 #define ahci_clear_status(p, r) _ahci_clear_status(&(p)->r)
66 static inline int ahci_port_is_active(const hba_port_t
*const port
)
68 return (port
->sata_status
& (HBA_PxSSTS_IPM_MASK
| HBA_PxSSTS_DET_MASK
))
69 == (HBA_PxSSTS_IPM_ACTIVE
| HBA_PxSSTS_DET_ESTABLISHED
);
72 /** Do minimal error recovery. */
73 int ahci_error_recovery(ahci_dev_t
*const dev
, const u32 intr_status
)
75 /* Command engine has to be restarted.
76 We don't call ahci_cmdengine_stop() here as it also checks
77 HBA_PxCMD_FR which won't clear on fatal errors. */
78 dev
->port
->cmd_stat
&= ~HBA_PxCMD_ST
;
80 /* Always clear sata_error. */
81 ahci_clear_status(dev
->port
, sata_error
);
83 /* Perform COMRESET if appropriate. */
84 const u32 tfd
= dev
->port
->taskfile_data
;
85 if ((tfd
& (HBA_PxTFD_BSY
| HBA_PxTFD_DRQ
)) |
86 (intr_status
& HBA_PxIS_PCS
)) {
87 const u32 sctl
= dev
->port
->sata_control
& ~HBA_PxSCTL_DET_MASK
;
88 dev
->port
->sata_control
= sctl
| HBA_PxSCTL_DET_COMRESET
;
90 dev
->port
->sata_control
= sctl
;
93 if (ahci_port_is_active(dev
->port
))
94 /* Start command engine. */
95 return ahci_cmdengine_start(dev
->port
);
100 static int ahci_dev_init(hba_ctrl_t
*const ctrl
,
101 hba_port_t
*const port
,
106 const int ncs
= HBA_CAPS_DECODE_NCS(ctrl
->caps
);
108 if (ahci_cmdengine_stop(port
))
111 /* Allocate command list, one command table and received FIS. */
112 cmd_t
*const cmdlist
= memalign(1024, ncs
* sizeof(cmd_t
));
113 cmdtable_t
*const cmdtable
= memalign(128, sizeof(cmdtable_t
));
114 rcvd_fis_t
*const rcvd_fis
= memalign(256, sizeof(rcvd_fis_t
));
115 /* Allocate our device structure. */
116 ahci_dev_t
*const dev
= calloc(1, sizeof(ahci_dev_t
));
117 if (!cmdlist
|| !cmdtable
|| !rcvd_fis
|| !dev
)
119 memset((void *)cmdlist
, '\0', ncs
* sizeof(cmd_t
));
120 memset((void *)cmdtable
, '\0', sizeof(*cmdtable
));
121 memset((void *)rcvd_fis
, '\0', sizeof(*rcvd_fis
));
123 /* Set command list base and received FIS base. */
124 port
->cmdlist_base
= virt_to_phys(cmdlist
);
125 port
->frameinfo_base
= virt_to_phys(rcvd_fis
);
126 if (ahci_cmdengine_start(port
))
128 /* Put port into active state. */
129 port
->cmd_stat
|= HBA_PxCMD_ICC_ACTIVE
;
133 dev
->cmdlist
= cmdlist
;
134 dev
->cmdtable
= cmdtable
;
135 dev
->rcvd_fis
= rcvd_fis
;
138 * Wait for D2H Register FIS with device' signature.
139 * The drive has to spin up here, so wait up to 30s.
141 const int timeout_s
= 30; /* Time out after 30s. */
142 int timeout
= timeout_s
* 100;
143 while ((port
->taskfile_data
& HBA_PxTFD_BSY
) && timeout
--)
146 if (port
->taskfile_data
& HBA_PxTFD_BSY
)
147 printf("ahci: Timed out after %d seconds "
148 "of waiting for device to spin up.\n", timeout_s
);
150 /* Initialize device or fall through to clean up. */
151 switch (port
->signature
) {
153 printf("ahci: ATA drive on port #%d.\n", portnum
);
154 #if CONFIG(LP_STORAGE_ATA)
155 dev
->ata_dev
.identify
= ahci_identify_device
;
156 dev
->ata_dev
.read_sectors
= ahci_ata_read_sectors
;
157 return ata_attach_device(&dev
->ata_dev
, PORT_TYPE_SATA
);
160 case HBA_PxSIG_ATAPI
:
161 printf("ahci: ATAPI drive on port #%d.\n", portnum
);
162 #if CONFIG(LP_STORAGE_ATAPI)
163 dev
->atapi_dev
.identify
= ahci_identify_device
;
164 dev
->atapi_dev
.packet_read_cmd
= ahci_packet_read_cmd
;
165 return atapi_attach_device(&dev
->atapi_dev
, PORT_TYPE_SATA
);
169 printf("ahci: Unsupported device (signature == 0x%08x) "
170 "on port #%d.\n", port
->signature
, portnum
);
176 /* Clean up (not reached for initialized devices). */
179 /* Only free if stopping succeeds, since otherwise the controller may
180 still use the resources for DMA. */
181 if (!ahci_cmdengine_stop(port
)) {
182 port
->cmdlist_base
= 0;
183 port
->frameinfo_base
= 0;
185 free((void *)rcvd_fis
);
187 free((void *)cmdtable
);
189 free((void *)cmdlist
);
194 static void ahci_port_probe(hba_ctrl_t
*const ctrl
,
195 hba_port_t
*const port
,
198 /* If staggered spin-up is supported, spin-up device. */
199 if (ctrl
->caps
& HBA_CAPS_SSS
) {
200 port
->cmd_stat
|= HBA_PxCMD_SUD
;
203 /* Wait 1s if we just told the device to spin up or
204 if it's the first port. */
205 if ((ctrl
->caps
& HBA_CAPS_SSS
) ||
206 !(ctrl
->ports_impl
& ((1 << (portnum
- 1)) - 1))) {
207 /* Wait for port to become active. */
208 int timeout
= 100; /* Time out after 100 * 100us == 10ms. */
209 while (!ahci_port_is_active(port
) && timeout
--)
212 if (!ahci_port_is_active(port
))
215 ahci_clear_status(port
, sata_error
);
216 ahci_clear_status(port
, intr_status
);
218 ahci_dev_init(ctrl
, port
, portnum
);
221 #if CONFIG(LP_STORAGE_AHCI_ONLY_TESTED)
222 static u32 working_controllers
[] = {
223 0x8086 | 0x2929 << 16, /* Mobile ICH9 */
224 0x8086 | 0x1c03 << 16, /* Mobile Cougar Point PCH */
225 0x8086 | 0x1e03 << 16, /* Mobile Panther Point PCH */
226 0x8086 | 0xa102 << 16, /* Desktop / Mobile-Wks Sunrise Point PCH */
227 0x8086 | 0xa353 << 16, /* Mobile 300 series Cannon Point PCH */
228 0x8086 | 0x5ae3 << 16, /* Apollo Lake */
232 void ahci_initialize(struct pci_dev
*dev
)
236 #if CONFIG(LP_STORAGE_AHCI_ONLY_TESTED)
237 const u32 vendor_device
= dev
->vendor_id
| dev
->device_id
<< 16;
238 for (i
= 0; i
< ARRAY_SIZE(working_controllers
); ++i
)
239 if (vendor_device
== working_controllers
[i
])
241 if (i
== ARRAY_SIZE(working_controllers
)) {
242 printf("ahci: Not using untested SATA controller "
243 "%02x:%02x.%02x (%04x:%04x).\n", dev
->bus
,
244 dev
->dev
, dev
->func
, dev
->vendor_id
, dev
->device_id
);
249 printf("ahci: Found SATA controller %02x:%02x.%02x (%04x:%04x).\n",
250 dev
->bus
, dev
->dev
, dev
->func
, dev
->vendor_id
, dev
->device_id
);
252 hba_ctrl_t
*const ctrl
= phys_to_virt(pci_read_long(dev
, 0x24) & ~0x3ff);
253 hba_port_t
*const ports
= ctrl
->ports
;
255 /* Reset host controller. */
256 ctrl
->global_ctrl
|= HBA_CTRL_RESET
;
257 /* Reset has to be finished after 1s. */
258 int timeout
= 10 * 1000; /* Time out after 10,000 * 100us == 1s. */
259 while (ctrl
->global_ctrl
& HBA_CTRL_RESET
&& timeout
--)
261 if (ctrl
->global_ctrl
& HBA_CTRL_RESET
) {
262 printf("ahci: ERROR: "
263 "Controller reset didn't finish within 1s.\n");
267 /* Set AHCI access mode. */
268 ctrl
->global_ctrl
|= HBA_CTRL_AHCI_EN
;
270 /* Enable bus mastering. */
271 const u16 command
= pci_read_word(dev
, PCI_COMMAND
);
272 pci_write_word(dev
, PCI_COMMAND
, command
| PCI_COMMAND_MASTER
);
274 /* Probe for devices. */
275 for (i
= 0; i
< 32; ++i
) {
276 if (ctrl
->ports_impl
& (1 << i
))
277 ahci_port_probe(ctrl
, &ports
[i
], i
+ 1);