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