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