xref: /openbsd-src/sys/dev/pci/pci.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: pci.c,v 1.33 2003/04/27 11:22:53 ho Exp $	*/
2 /*	$NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $	*/
3 
4 /*
5  * Copyright (c) 1995, 1996 Christopher G. Demetriou.  All rights reserved.
6  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by Charles Hannum.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * PCI bus autoconfiguration.
36  */
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcivar.h>
44 #include <dev/pci/pcidevs.h>
45 
46 int pcimatch(struct device *, void *, void *);
47 void pciattach(struct device *, struct device *, void *);
48 
49 #ifdef USER_PCICONF
50 struct pci_softc {
51 	struct device sc_dev;
52 	pci_chipset_tag_t sc_pc;
53 	int sc_bus;		/* PCI configuration space bus # */
54 };
55 #endif
56 
57 #ifdef APERTURE
58 extern int allowaperture;
59 #endif
60 
61 struct cfattach pci_ca = {
62 #ifndef USER_PCICONF
63 	sizeof(struct device), pcimatch, pciattach
64 #else
65 	sizeof(struct pci_softc), pcimatch, pciattach
66 #endif
67 };
68 
69 struct cfdriver pci_cd = {
70 	NULL, "pci", DV_DULL
71 };
72 
73 int	pciprint(void *, const char *);
74 int	pcisubmatch(struct device *, void *, void *);
75 
76 /*
77  * Callback so that ISA/EISA bridges can attach their child busses
78  * after PCI configuration is done.
79  *
80  * This works because:
81  *	(1) there can be at most one ISA/EISA bridge per PCI bus, and
82  *	(2) any ISA/EISA bridges must be attached to primary PCI
83  *	    busses (i.e. bus zero).
84  *
85  * That boils down to: there can only be one of these outstanding
86  * at a time, it is cleared when configuring PCI bus 0 before any
87  * subdevices have been found, and it is run after all subdevices
88  * of PCI bus 0 have been found.
89  *
90  * This is needed because there are some (legacy) PCI devices which
91  * can show up as ISA/EISA devices as well (the prime example of which
92  * are VGA controllers).  If you attach ISA from a PCI-ISA/EISA bridge,
93  * and the bridge is seen before the video board is, the board can show
94  * up as an ISA device, and that can (bogusly) complicate the PCI device's
95  * attach code, or make the PCI device not be properly attached at all.
96  */
97 static void	(*pci_isa_bridge_callback)(void *);
98 static void	*pci_isa_bridge_callback_arg;
99 
100 int
101 pcimatch(parent, match, aux)
102 	struct device *parent;
103 	void *match, *aux;
104 {
105 	struct cfdata *cf = match;
106 	struct pcibus_attach_args *pba = aux;
107 
108 	if (strcmp(pba->pba_busname, cf->cf_driver->cd_name))
109 		return (0);
110 
111 	/* Check the locators */
112 	if (cf->pcibuscf_bus != PCIBUS_UNK_BUS &&
113 	    cf->pcibuscf_bus != pba->pba_bus)
114 		return (0);
115 
116 	/* sanity */
117 	if (pba->pba_bus < 0 || pba->pba_bus > 255)
118 		return (0);
119 
120 	/*
121 	 * XXX check other (hardware?) indicators
122 	 */
123 
124 	return 1;
125 }
126 
127 void
128 pciattach(parent, self, aux)
129 	struct device *parent, *self;
130 	void *aux;
131 {
132 	struct pcibus_attach_args *pba = aux;
133 	bus_space_tag_t iot, memt;
134 	pci_chipset_tag_t pc;
135 	int bus, device, maxndevs, function, nfunctions;
136 #ifdef USER_PCICONF
137 	struct pci_softc *sc = (struct pci_softc *)self;
138 #endif
139 #ifdef __PCI_BUS_DEVORDER
140 	char devs[32];
141 	int i;
142 #endif
143 #ifdef __PCI_DEV_FUNCORDER
144 	char funcs[8];
145 	int j;
146 #endif
147 
148 	pci_attach_hook(parent, self, pba);
149 	printf("\n");
150 
151 	iot = pba->pba_iot;
152 	memt = pba->pba_memt;
153 	pc = pba->pba_pc;
154 	bus = pba->pba_bus;
155 	maxndevs = pci_bus_maxdevs(pc, bus);
156 
157 #ifdef USER_PCICONF
158 	sc->sc_pc = pba->pba_pc;
159 	sc->sc_bus = bus;
160 #endif
161 
162 	if (bus == 0)
163 		pci_isa_bridge_callback = NULL;
164 
165 #ifdef __PCI_BUS_DEVORDER
166 	pci_bus_devorder(pc, bus, devs);
167 	for (i = 0; (device = devs[i]) < 32 && device >= 0; i++) {
168 #else
169 	for (device = 0; device < maxndevs; device++) {
170 #endif
171 		pcitag_t tag;
172 		pcireg_t id, class, intr;
173 #ifndef __sparc64__
174 		pcireg_t bhlcr;
175 #endif
176 		struct pci_attach_args pa;
177 		int pin;
178 
179 		tag = pci_make_tag(pc, bus, device, 0);
180 		id = pci_conf_read(pc, tag, PCI_ID_REG);
181 
182 #ifdef __sparc64__
183 		pci_dev_funcorder(pc, bus, device, funcs);
184 		nfunctions = 8;
185 
186 		/* Invalid vendor ID value or 0 (see below for zero)
187 		 * ... of course, if the pci_dev_funcorder found
188 		 *     functions other than zero, we probably want
189 		 *     to attach them.
190 		 */
191 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0)
192 			if (funcs[0] < 0)
193 				continue;
194 
195 		for (j = 0; (function = funcs[j]) < nfunctions &&
196 		    function >= 0; j++) {
197 #else
198 
199 		/* Invalid vendor ID value? */
200 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
201 			continue;
202 		/* XXX Not invalid, but we've done this ~forever. */
203 		if (PCI_VENDOR(id) == 0)
204 			continue;
205 
206 		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
207 		nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
208 
209 #ifdef __PCI_DEV_FUNCORDER
210 		pci_dev_funcorder(pc, bus, device, funcs);
211 		for (j = 0; (function = funcs[j]) < nfunctions &&
212 		    function >= 0; j++) {
213 #else
214 		for (function = 0; function < nfunctions; function++) {
215 #endif
216 #endif
217 			tag = pci_make_tag(pc, bus, device, function);
218 			id = pci_conf_read(pc, tag, PCI_ID_REG);
219 
220 			/* Invalid vendor ID value? */
221 			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
222 				continue;
223 			/* XXX Not invalid, but we've done this ~forever. */
224 			if (PCI_VENDOR(id) == 0)
225 				continue;
226 
227 			class = pci_conf_read(pc, tag, PCI_CLASS_REG);
228 			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
229 
230 			pa.pa_iot = iot;
231 			pa.pa_memt = memt;
232 			pa.pa_dmat = pba->pba_dmat;
233 			pa.pa_pc = pc;
234 			pa.pa_device = device;
235 			pa.pa_function = function;
236 			pa.pa_bus = bus;
237 			pa.pa_tag = tag;
238 			pa.pa_id = id;
239 			pa.pa_class = class;
240 
241 			/* This is a simplification of the NetBSD code.
242 			   We don't support turning off I/O or memory
243 			   on broken hardware. <csapuntz@stanford.edu> */
244 			pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
245 #ifdef __i386__
246 			/*
247 			 * on i386 we really need to know the device tag
248 			 * and not the pci bridge tag, in intr_map
249 			 * to be able to program the device and the
250 			 * pci interrupt router.
251 			 */
252 			pa.pa_intrtag = tag;
253 			pa.pa_intrswiz = 0;
254 #else
255 			if (bus == 0) {
256 				pa.pa_intrswiz = 0;
257 				pa.pa_intrtag = tag;
258 			} else {
259 				pa.pa_intrswiz = pba->pba_intrswiz + device;
260 				pa.pa_intrtag = pba->pba_intrtag;
261 			}
262 #endif
263 			pin = PCI_INTERRUPT_PIN(intr);
264 			if (pin == PCI_INTERRUPT_PIN_NONE) {
265 				/* no interrupt */
266 				pa.pa_intrpin = 0;
267 			} else {
268 				/*
269 				 * swizzle it based on the number of
270 				 * busses we're behind and our device
271 				 * number.
272 				 */
273 				pa.pa_intrpin =			/* XXX */
274 				    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
275 			}
276 			pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
277 
278 			config_found_sm(self, &pa, pciprint, pcisubmatch);
279 		}
280 	}
281 
282 	if (bus == 0 && pci_isa_bridge_callback != NULL)
283 		(*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg);
284 }
285 
286 int
287 pciprint(aux, pnp)
288 	void *aux;
289 	const char *pnp;
290 {
291 	register struct pci_attach_args *pa = aux;
292 	char devinfo[256];
293 
294 	if (pnp) {
295 		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo,
296 		    sizeof devinfo);
297 		printf("%s at %s", devinfo, pnp);
298 	}
299 	printf(" dev %d function %d", pa->pa_device, pa->pa_function);
300 	if (!pnp) {
301 		pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo,
302 		    sizeof devinfo);
303 		printf(" %s", devinfo);
304 	}
305 
306 	return (UNCONF);
307 }
308 
309 int
310 pcisubmatch(parent, match, aux)
311 	struct device *parent;
312 	void *match, *aux;
313 {
314 	struct cfdata *cf = match;
315 	struct pci_attach_args *pa = aux;
316 	int success;
317 
318 	if (cf->pcicf_dev != PCI_UNK_DEV &&
319 	    cf->pcicf_dev != pa->pa_device)
320 		return 0;
321 	if (cf->pcicf_function != PCI_UNK_FUNCTION &&
322 	    cf->pcicf_function != pa->pa_function)
323 		return 0;
324 
325 	success = (*cf->cf_attach->ca_match)(parent, match, aux);
326 
327 	/* My Dell BIOS does not enable certain non-critical PCI devices
328 	   for IO and memory cycles (e.g. network card). This is
329 	   the generic approach to fixing this problem. Basically, if
330 	   we support the card, then we enable its IO cycles.
331 	*/
332 	if (success) {
333 		u_int32_t csr = pci_conf_read(pa->pa_pc, pa->pa_tag,
334 					      PCI_COMMAND_STATUS_REG);
335 
336 		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
337 			       csr | PCI_COMMAND_MASTER_ENABLE |
338 			       PCI_COMMAND_IO_ENABLE |
339 			       PCI_COMMAND_MEM_ENABLE);
340 	}
341 
342 	return (success);
343 }
344 
345 void
346 set_pci_isa_bridge_callback(fn, arg)
347 	void (*fn)(void *);
348 	void *arg;
349 {
350 
351 	if (pci_isa_bridge_callback != NULL)
352 		panic("set_pci_isa_bridge_callback");
353 	pci_isa_bridge_callback = fn;
354 	pci_isa_bridge_callback_arg = arg;
355 }
356 
357 int
358 pci_get_capability(pc, tag, capid, offset, value)
359 	pci_chipset_tag_t pc;
360 	pcitag_t tag;
361 	int capid;
362 	int *offset;
363 	pcireg_t *value;
364 {
365 	pcireg_t reg;
366 	unsigned int ofs;
367 
368 	reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
369 	if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
370 		return (0);
371 
372 	ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, PCI_CAPLISTPTR_REG));
373 	while (ofs != 0) {
374 #ifdef DIAGNOSTIC
375 		if ((ofs & 3) || (ofs < 0x40))
376 			panic("pci_get_capability");
377 #endif
378 		reg = pci_conf_read(pc, tag, ofs);
379 		if (PCI_CAPLIST_CAP(reg) == capid) {
380 			if (offset)
381 				*offset = ofs;
382 			if (value)
383 				*value = reg;
384 			return (1);
385 		}
386 		ofs = PCI_CAPLIST_NEXT(reg);
387 	}
388 
389 	return (0);
390 }
391 
392 int
393 pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids,
394     int nent)
395 {
396 	const struct pci_matchid *pm;
397 	int i;
398 
399 	for (i = 0, pm = ids; i < nent; i++, pm++)
400 		if (PCI_VENDOR(pa->pa_id) == pm->pm_vid &&
401 		    PCI_PRODUCT(pa->pa_id) == pm->pm_pid)
402 			return (1);
403 	return (0);
404 }
405 
406 #ifdef USER_PCICONF
407 /*
408  * This is the user interface to PCI configuration space.
409  */
410 
411 #include <sys/pciio.h>
412 #include <sys/fcntl.h>
413 
414 #ifdef DEBUG
415 #define PCIDEBUG(x) printf x
416 #else
417 #define PCIDEBUG(x)
418 #endif
419 
420 
421 int pciopen(dev_t dev, int oflags, int devtype, struct proc *p);
422 int pciclose(dev_t dev, int flag, int devtype, struct proc *p);
423 int pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
424 
425 int
426 pciopen(dev_t dev, int oflags, int devtype, struct proc *p)
427 {
428 	PCIDEBUG(("pciopen ndevs: %d\n" , pci_cd.cd_ndevs));
429 
430 #ifndef APERTURE
431 	if ((oflags & FWRITE) && securelevel > 0) {
432 		return EPERM;
433 	}
434 #else
435 	if ((oflags & FWRITE) && securelevel > 0 && allowaperture == 0) {
436 		return EPERM;
437 	}
438 #endif
439 	return 0;
440 }
441 
442 int
443 pciclose(dev_t dev, int flag, int devtype, struct proc *p)
444 {
445 	PCIDEBUG(("pciclose\n"));
446 	return 0;
447 }
448 
449 int
450 pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
451 {
452 	struct pci_io *io;
453 	int error;
454 	pcitag_t tag;
455 	struct pci_softc *pci;
456 	pci_chipset_tag_t pc;
457 
458 	io = (struct pci_io *)data;
459 
460 	PCIDEBUG(("pciioctl cmd %s", cmd == PCIOCREAD ? "pciocread"
461 		  : cmd == PCIOCWRITE ? "pciocwrite" : "unknown"));
462 	PCIDEBUG(("  bus %d dev %d func %d reg %x\n", io->pi_sel.pc_bus,
463 		  io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg));
464 
465 	if (io->pi_sel.pc_bus >= pci_cd.cd_ndevs) {
466 		error = ENXIO;
467 		goto done;
468 	}
469 	pci = pci_cd.cd_devs[io->pi_sel.pc_bus];
470 	if (pci != NULL) {
471 		pc = pci->sc_pc;
472 	} else {
473 		error = ENXIO;
474 		goto done;
475 	}
476 	/* Check bounds */
477 	if (pci->sc_bus >= 256 ||
478 	    io->pi_sel.pc_dev >= pci_bus_maxdevs(pc, pci->sc_bus) ||
479 	    io->pi_sel.pc_func >= 8) {
480 		error = EINVAL;
481 		goto done;
482 	}
483 
484 	tag = pci_make_tag(pc, pci->sc_bus, io->pi_sel.pc_dev,
485 			   io->pi_sel.pc_func);
486 
487 	switch(cmd) {
488 	case PCIOCGETCONF:
489 		error = ENODEV;
490 		break;
491 
492 	case PCIOCREAD:
493 		switch(io->pi_width) {
494 		case 4:
495 			/* Make sure the register is properly aligned */
496 			if (io->pi_reg & 0x3)
497 				return EINVAL;
498 			io->pi_data = pci_conf_read(pc, tag, io->pi_reg);
499 			error = 0;
500 			break;
501 		default:
502 			error = ENODEV;
503 			break;
504 		}
505 		break;
506 
507 	case PCIOCWRITE:
508 		if (!(flag & FWRITE))
509 			return EPERM;
510 
511 		switch(io->pi_width) {
512 		case 4:
513 			/* Make sure the register is properly aligned */
514 			if (io->pi_reg & 0x3)
515 				return EINVAL;
516 			pci_conf_write(pc, tag, io->pi_reg, io->pi_data);
517 			error = 0;
518 			break;
519 		default:
520 			error = ENODEV;
521 			break;
522 		}
523 		break;
524 
525 	default:
526 		error = ENOTTY;
527 		break;
528 	}
529  done:
530 	return (error);
531 }
532 
533 #endif
534