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