Line data Source code
1 : /* $OpenBSD: ahci_pci.c,v 1.15 2018/08/03 22:18:13 kettenis Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
5 : * Copyright (c) 2010 Conformal Systems LLC <info@conformal.com>
6 : * Copyright (c) 2010 Jonathan Matthew <jonathan@d14n.org>
7 : *
8 : * Permission to use, copy, modify, and distribute this software for any
9 : * purpose with or without fee is hereby granted, provided that the above
10 : * copyright notice and this permission notice appear in all copies.
11 : *
12 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 : */
20 :
21 : #include <sys/param.h>
22 : #include <sys/systm.h>
23 : #include <sys/buf.h>
24 : #include <sys/kernel.h>
25 : #include <sys/malloc.h>
26 : #include <sys/device.h>
27 : #include <sys/timeout.h>
28 : #include <sys/queue.h>
29 : #include <sys/mutex.h>
30 : #include <sys/pool.h>
31 :
32 : #include <machine/bus.h>
33 :
34 : #include <dev/pci/pcireg.h>
35 : #include <dev/pci/pcivar.h>
36 : #include <dev/pci/pcidevs.h>
37 :
38 : #include <dev/ata/pmreg.h>
39 :
40 : #include <dev/ic/ahcireg.h>
41 : #include <dev/ic/ahcivar.h>
42 :
43 : #define AHCI_PCI_BAR 0x24
44 : #define AHCI_PCI_ATI_SB600_MAGIC 0x40
45 : #define AHCI_PCI_ATI_SB600_LOCKED 0x01
46 :
47 : struct ahci_pci_softc {
48 : struct ahci_softc psc_ahci;
49 :
50 : pci_chipset_tag_t psc_pc;
51 : pcitag_t psc_tag;
52 :
53 : int psc_flags;
54 : };
55 :
56 : struct ahci_device {
57 : pci_vendor_id_t ad_vendor;
58 : pci_product_id_t ad_product;
59 : int (*ad_match)(struct pci_attach_args *);
60 : int (*ad_attach)(struct ahci_softc *,
61 : struct pci_attach_args *);
62 : };
63 :
64 : const struct ahci_device *ahci_lookup_device(struct pci_attach_args *);
65 :
66 : int ahci_no_match(struct pci_attach_args *);
67 : int ahci_vt8251_attach(struct ahci_softc *,
68 : struct pci_attach_args *);
69 : void ahci_ati_sb_idetoahci(struct ahci_softc *,
70 : struct pci_attach_args *pa);
71 : int ahci_ati_sb600_attach(struct ahci_softc *,
72 : struct pci_attach_args *);
73 : int ahci_ati_sb700_attach(struct ahci_softc *,
74 : struct pci_attach_args *);
75 : int ahci_amd_hudson2_attach(struct ahci_softc *,
76 : struct pci_attach_args *);
77 : int ahci_intel_attach(struct ahci_softc *,
78 : struct pci_attach_args *);
79 : int ahci_samsung_attach(struct ahci_softc *,
80 : struct pci_attach_args *);
81 :
82 : static const struct ahci_device ahci_devices[] = {
83 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON2_SATA_1,
84 : NULL, ahci_amd_hudson2_attach },
85 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON2_SATA_2,
86 : NULL, ahci_amd_hudson2_attach },
87 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON2_SATA_3,
88 : NULL, ahci_amd_hudson2_attach },
89 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON2_SATA_4,
90 : NULL, ahci_amd_hudson2_attach },
91 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON2_SATA_5,
92 : NULL, ahci_amd_hudson2_attach },
93 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON2_SATA_6,
94 : NULL, ahci_amd_hudson2_attach },
95 :
96 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_SATA,
97 : NULL, ahci_ati_sb600_attach },
98 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SBX00_SATA_1,
99 : NULL, ahci_ati_sb700_attach },
100 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SBX00_SATA_2,
101 : NULL, ahci_ati_sb700_attach },
102 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SBX00_SATA_3,
103 : NULL, ahci_ati_sb700_attach },
104 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SBX00_SATA_4,
105 : NULL, ahci_ati_sb700_attach },
106 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SBX00_SATA_5,
107 : NULL, ahci_ati_sb700_attach },
108 : { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SBX00_SATA_6,
109 : NULL, ahci_ati_sb700_attach },
110 :
111 : { PCI_VENDOR_ASMEDIA, PCI_PRODUCT_ASMEDIA_ASM1061_SATA },
112 :
113 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6SERIES_AHCI_1,
114 : NULL, ahci_intel_attach },
115 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6SERIES_AHCI_2,
116 : NULL, ahci_intel_attach },
117 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6321ESB_AHCI,
118 : NULL, ahci_intel_attach },
119 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GR_AHCI,
120 : NULL, ahci_intel_attach },
121 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GBM_AHCI,
122 : NULL, ahci_intel_attach },
123 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_AHCI_6P,
124 : NULL, ahci_intel_attach },
125 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_AHCI_4P,
126 : NULL, ahci_intel_attach },
127 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HBM_AHCI,
128 : NULL, ahci_intel_attach },
129 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_AHCI_1,
130 : NULL, ahci_intel_attach },
131 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_AHCI_2,
132 : NULL, ahci_intel_attach },
133 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_AHCI_3,
134 : NULL, ahci_intel_attach },
135 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JD_AHCI,
136 : NULL, ahci_intel_attach },
137 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JI_AHCI,
138 : NULL, ahci_intel_attach },
139 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_AHCI_1,
140 : NULL, ahci_intel_attach },
141 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_AHCI_2,
142 : NULL, ahci_intel_attach },
143 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_AHCI_3,
144 : NULL, ahci_intel_attach },
145 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_AHCI_4,
146 : NULL, ahci_intel_attach },
147 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_EP80579_AHCI,
148 : NULL, ahci_intel_attach },
149 :
150 : { PCI_VENDOR_SAMSUNG2, PCI_PRODUCT_SAMSUNG2_S4LN053X01,
151 : NULL, ahci_samsung_attach },
152 : { PCI_VENDOR_SAMSUNG2, PCI_PRODUCT_SAMSUNG2_XP941,
153 : NULL, ahci_samsung_attach },
154 : { PCI_VENDOR_SAMSUNG2, PCI_PRODUCT_SAMSUNG2_SM951_AHCI,
155 : NULL, ahci_samsung_attach },
156 :
157 : { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8251_SATA,
158 : ahci_no_match, ahci_vt8251_attach }
159 : };
160 :
161 : int ahci_pci_match(struct device *, void *, void *);
162 : void ahci_pci_attach(struct device *, struct device *,
163 : void *);
164 : int ahci_pci_detach(struct device *, int);
165 : int ahci_pci_activate(struct device *, int);
166 :
167 : struct cfattach ahci_pci_ca = {
168 : sizeof(struct ahci_pci_softc),
169 : ahci_pci_match,
170 : ahci_pci_attach,
171 : ahci_pci_detach,
172 : ahci_pci_activate
173 : };
174 :
175 : struct cfattach ahci_jmb_ca = {
176 : sizeof(struct ahci_pci_softc),
177 : ahci_pci_match,
178 : ahci_pci_attach,
179 : ahci_pci_detach
180 : };
181 :
182 : int ahci_map_regs(struct ahci_pci_softc *,
183 : struct pci_attach_args *);
184 : void ahci_unmap_regs(struct ahci_pci_softc *);
185 : int ahci_map_intr(struct ahci_pci_softc *,
186 : struct pci_attach_args *, pci_intr_handle_t);
187 : void ahci_unmap_intr(struct ahci_pci_softc *);
188 :
189 : const struct ahci_device *
190 0 : ahci_lookup_device(struct pci_attach_args *pa)
191 : {
192 : int i;
193 : const struct ahci_device *ad;
194 :
195 0 : for (i = 0; i < (sizeof(ahci_devices) / sizeof(ahci_devices[0])); i++) {
196 0 : ad = &ahci_devices[i];
197 0 : if (ad->ad_vendor == PCI_VENDOR(pa->pa_id) &&
198 0 : ad->ad_product == PCI_PRODUCT(pa->pa_id))
199 0 : return (ad);
200 : }
201 :
202 0 : return (NULL);
203 0 : }
204 :
205 : int
206 0 : ahci_no_match(struct pci_attach_args *pa)
207 : {
208 0 : return (0);
209 : }
210 :
211 : int
212 0 : ahci_vt8251_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
213 : {
214 0 : sc->sc_flags |= AHCI_F_NO_NCQ;
215 :
216 0 : return (0);
217 : }
218 :
219 : void
220 0 : ahci_ati_sb_idetoahci(struct ahci_softc *sc, struct pci_attach_args *pa)
221 : {
222 : pcireg_t magic;
223 :
224 0 : if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
225 0 : magic = pci_conf_read(pa->pa_pc, pa->pa_tag,
226 : AHCI_PCI_ATI_SB600_MAGIC);
227 0 : pci_conf_write(pa->pa_pc, pa->pa_tag,
228 : AHCI_PCI_ATI_SB600_MAGIC,
229 0 : magic | AHCI_PCI_ATI_SB600_LOCKED);
230 :
231 0 : pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG,
232 : PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT |
233 : PCI_SUBCLASS_MASS_STORAGE_SATA << PCI_SUBCLASS_SHIFT |
234 0 : PCI_INTERFACE_SATA_AHCI10 << PCI_INTERFACE_SHIFT |
235 0 : PCI_REVISION(pa->pa_class) << PCI_REVISION_SHIFT);
236 :
237 0 : pci_conf_write(pa->pa_pc, pa->pa_tag,
238 : AHCI_PCI_ATI_SB600_MAGIC, magic);
239 0 : }
240 0 : }
241 :
242 : int
243 0 : ahci_ati_sb600_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
244 : {
245 0 : ahci_ati_sb_idetoahci(sc, pa);
246 :
247 0 : sc->sc_flags |= AHCI_F_IPMS_PROBE;
248 :
249 0 : return (0);
250 : }
251 :
252 : int
253 0 : ahci_ati_sb700_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
254 : {
255 0 : ahci_ati_sb_idetoahci(sc, pa);
256 :
257 0 : sc->sc_flags |= AHCI_F_IPMS_PROBE;
258 :
259 0 : return (0);
260 : }
261 :
262 : int
263 0 : ahci_amd_hudson2_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
264 : {
265 0 : ahci_ati_sb_idetoahci(sc, pa);
266 :
267 0 : sc->sc_flags |= AHCI_F_IPMS_PROBE;
268 :
269 0 : return (0);
270 : }
271 :
272 : int
273 0 : ahci_intel_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
274 : {
275 0 : sc->sc_flags |= AHCI_F_NO_PMP;
276 :
277 0 : return (0);
278 : }
279 :
280 : int
281 0 : ahci_samsung_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
282 : {
283 : /*
284 : * Disable MSI with the Samsung S4LN053X01 SSD controller as found
285 : * in some Apple MacBook Air models such as the 6,1 and 6,2, as well
286 : * as the XP941 SSD controller.
287 : * https://bugzilla.kernel.org/show_bug.cgi?id=60731
288 : * https://bugzilla.kernel.org/show_bug.cgi?id=89171
289 : */
290 0 : sc->sc_flags |= AHCI_F_NO_MSI;
291 :
292 0 : return (0);
293 : }
294 :
295 : int
296 0 : ahci_pci_match(struct device *parent, void *match, void *aux)
297 : {
298 0 : struct pci_attach_args *pa = aux;
299 : const struct ahci_device *ad;
300 :
301 0 : ad = ahci_lookup_device(pa);
302 0 : if (ad != NULL) {
303 : /* the device may need special checks to see if it matches */
304 0 : if (ad->ad_match != NULL)
305 0 : return (ad->ad_match(pa));
306 :
307 0 : return (2); /* match higher than pciide */
308 : }
309 :
310 0 : if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
311 0 : PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_SATA &&
312 0 : PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_SATA_AHCI10)
313 0 : return (2);
314 :
315 0 : return (0);
316 0 : }
317 :
318 : void
319 0 : ahci_pci_attach(struct device *parent, struct device *self, void *aux)
320 : {
321 0 : struct ahci_pci_softc *psc = (struct ahci_pci_softc *)self;
322 0 : struct ahci_softc *sc = &psc->psc_ahci;
323 0 : struct pci_attach_args *pa = aux;
324 : const struct ahci_device *ad;
325 0 : pci_intr_handle_t ih;
326 :
327 0 : psc->psc_pc = pa->pa_pc;
328 0 : psc->psc_tag = pa->pa_tag;
329 0 : sc->sc_dmat = pa->pa_dmat;
330 :
331 0 : ad = ahci_lookup_device(pa);
332 0 : if (ad != NULL && ad->ad_attach != NULL) {
333 0 : if (ad->ad_attach(sc, pa) != 0) {
334 : /* error should be printed by ad_attach */
335 0 : return;
336 : }
337 : }
338 :
339 0 : if (sc->sc_flags & AHCI_F_NO_MSI)
340 0 : pa->pa_flags &= ~PCI_FLAGS_MSI_ENABLED;
341 :
342 0 : if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
343 0 : printf(": unable to map interrupt\n");
344 0 : return;
345 : }
346 0 : printf(": %s,", pci_intr_string(pa->pa_pc, ih));
347 :
348 0 : if (ahci_map_regs(psc, pa) != 0) {
349 : /* error already printed by ahci_map_regs */
350 0 : return;
351 : }
352 :
353 0 : if (ahci_map_intr(psc, pa, ih) != 0) {
354 : /* error already printed by ahci_map_intr */
355 : goto unmap;
356 : }
357 :
358 0 : if (ahci_attach(sc) != 0) {
359 : /* error printed by ahci_attach */
360 : goto unmap;
361 : }
362 :
363 0 : return;
364 :
365 : unmap:
366 0 : ahci_unmap_regs(psc);
367 0 : return;
368 0 : }
369 :
370 : int
371 0 : ahci_pci_detach(struct device *self, int flags)
372 : {
373 0 : struct ahci_pci_softc *psc = (struct ahci_pci_softc *)self;
374 0 : struct ahci_softc *sc = &psc->psc_ahci;
375 :
376 0 : ahci_detach(sc, flags);
377 :
378 0 : ahci_unmap_intr(psc);
379 0 : ahci_unmap_regs(psc);
380 :
381 0 : return (0);
382 : }
383 :
384 : int
385 0 : ahci_map_regs(struct ahci_pci_softc *psc, struct pci_attach_args *pa)
386 : {
387 : pcireg_t maptype;
388 0 : struct ahci_softc *sc = &psc->psc_ahci;
389 :
390 0 : maptype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHCI_PCI_BAR);
391 0 : if (pci_mapreg_map(pa, AHCI_PCI_BAR, maptype, 0, &sc->sc_iot,
392 0 : &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
393 0 : printf(" unable to map registers\n");
394 0 : return (1);
395 : }
396 :
397 0 : return (0);
398 0 : }
399 :
400 : void
401 0 : ahci_unmap_regs(struct ahci_pci_softc *psc)
402 : {
403 0 : struct ahci_softc *sc = &psc->psc_ahci;
404 :
405 0 : bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
406 0 : sc->sc_ios = 0;
407 0 : }
408 :
409 : int
410 0 : ahci_map_intr(struct ahci_pci_softc *psc, struct pci_attach_args *pa,
411 : pci_intr_handle_t ih)
412 : {
413 0 : struct ahci_softc *sc = &psc->psc_ahci;
414 0 : sc->sc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO,
415 0 : ahci_intr, sc, DEVNAME(sc));
416 0 : if (sc->sc_ih == NULL) {
417 0 : printf("%s: unable to map interrupt\n", DEVNAME(sc));
418 0 : return (1);
419 : }
420 :
421 0 : return (0);
422 0 : }
423 :
424 : void
425 0 : ahci_unmap_intr(struct ahci_pci_softc *psc)
426 : {
427 0 : struct ahci_softc *sc = &psc->psc_ahci;
428 0 : pci_intr_disestablish(psc->psc_pc, sc->sc_ih);
429 0 : }
430 :
431 : int
432 0 : ahci_pci_activate(struct device *self, int act)
433 : {
434 0 : struct ahci_pci_softc *psc = (struct ahci_pci_softc *)self;
435 0 : struct ahci_softc *sc = &psc->psc_ahci;
436 0 : return ahci_activate((struct device *)sc, act);
437 : }
|