xref: /openbsd-src/sys/dev/pci/pci.c (revision 8445c53715e7030056b779e8ab40efb7820981f2)
1 /*	$OpenBSD: pci.c,v 1.22 2001/08/25 12:48:35 art 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 __P((struct device *, void *, void *));
47 void pciattach __P((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 };
54 #endif
55 
56 struct cfattach pci_ca = {
57 #ifndef USER_PCICONF
58 	sizeof(struct device), pcimatch, pciattach
59 #else
60 	sizeof(struct pci_softc), pcimatch, pciattach
61 #endif
62 };
63 
64 struct cfdriver pci_cd = {
65 	NULL, "pci", DV_DULL
66 };
67 
68 int	pciprint __P((void *, const char *));
69 int	pcisubmatch __P((struct device *, void *, void *));
70 
71 /*
72  * Callback so that ISA/EISA bridges can attach their child busses
73  * after PCI configuration is done.
74  *
75  * This works because:
76  *	(1) there can be at most one ISA/EISA bridge per PCI bus, and
77  *	(2) any ISA/EISA bridges must be attached to primary PCI
78  *	    busses (i.e. bus zero).
79  *
80  * That boils down to: there can only be one of these outstanding
81  * at a time, it is cleared when configuring PCI bus 0 before any
82  * subdevices have been found, and it is run after all subdevices
83  * of PCI bus 0 have been found.
84  *
85  * This is needed because there are some (legacy) PCI devices which
86  * can show up as ISA/EISA devices as well (the prime example of which
87  * are VGA controllers).  If you attach ISA from a PCI-ISA/EISA bridge,
88  * and the bridge is seen before the video board is, the board can show
89  * up as an ISA device, and that can (bogusly) complicate the PCI device's
90  * attach code, or make the PCI device not be properly attached at all.
91  */
92 static void	(*pci_isa_bridge_callback) __P((void *));
93 static void	*pci_isa_bridge_callback_arg;
94 
95 int
96 pcimatch(parent, match, aux)
97 	struct device *parent;
98 	void *match, *aux;
99 {
100 	struct cfdata *cf = match;
101 	struct pcibus_attach_args *pba = aux;
102 
103 	if (strcmp(pba->pba_busname, cf->cf_driver->cd_name))
104 		return (0);
105 
106 	/* Check the locators */
107 	if (cf->pcibuscf_bus != PCIBUS_UNK_BUS &&
108 	    cf->pcibuscf_bus != pba->pba_bus)
109 		return (0);
110 
111 	/* sanity */
112 	if (pba->pba_bus < 0 || pba->pba_bus > 255)
113 		return (0);
114 
115 	/*
116 	 * XXX check other (hardware?) indicators
117 	 */
118 
119 	return 1;
120 }
121 
122 void
123 pciattach(parent, self, aux)
124 	struct device *parent, *self;
125 	void *aux;
126 {
127 	struct pcibus_attach_args *pba = aux;
128 	bus_space_tag_t iot, memt;
129 	pci_chipset_tag_t pc;
130 	int bus, device, maxndevs, function, nfunctions;
131 #ifdef USER_PCICONF
132 	struct pci_softc *sc = (struct pci_softc *)self;
133 #endif
134 #ifdef __PCI_BUS_DEVORDER
135 	char devs[32];
136 	int i;
137 #endif
138 #ifdef __PCI_DEV_FUNCORDER
139 	char funcs[8];
140 	int j;
141 #endif
142 
143 	pci_attach_hook(parent, self, pba);
144 	printf("\n");
145 
146 	iot = pba->pba_iot;
147 	memt = pba->pba_memt;
148 	pc = pba->pba_pc;
149 	bus = pba->pba_bus;
150 	maxndevs = pci_bus_maxdevs(pc, bus);
151 
152 #ifdef USER_PCICONF
153 	sc->sc_pc = pba->pba_pc;
154 #endif
155 
156 	if (bus == 0)
157 		pci_isa_bridge_callback = NULL;
158 
159 #ifdef __PCI_BUS_DEVORDER
160 	pci_bus_devorder(pc, bus, devs);
161 	for (i = 0; (device = devs[i]) < 32 && device >= 0; i++) {
162 #else
163 	for (device = 0; device < maxndevs; device++) {
164 #endif
165 		pcitag_t tag;
166 		pcireg_t id, class, intr, bhlcr;
167 		struct pci_attach_args pa;
168 		int pin;
169 
170 		tag = pci_make_tag(pc, bus, device, 0);
171 		id = pci_conf_read(pc, tag, PCI_ID_REG);
172 
173 		/* Invalid vendor ID value? */
174 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
175 			continue;
176 		/* XXX Not invalid, but we've done this ~forever. */
177 		if (PCI_VENDOR(id) == 0)
178 			continue;
179 
180 		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
181 		nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
182 
183 #ifdef __PCI_DEV_FUNCORDER
184 		pci_dev_funcorder(pc, bus, device, funcs);
185 		for (j = 0; (function = funcs[j]) < nfunctions &&
186 		    function >= 0; j++) {
187 #else
188 		for (function = 0; function < nfunctions; function++) {
189 #endif
190 			tag = pci_make_tag(pc, bus, device, function);
191 			id = pci_conf_read(pc, tag, PCI_ID_REG);
192 
193 			/* Invalid vendor ID value? */
194 			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
195 				continue;
196 			/* XXX Not invalid, but we've done this ~forever. */
197 			if (PCI_VENDOR(id) == 0)
198 				continue;
199 
200 			class = pci_conf_read(pc, tag, PCI_CLASS_REG);
201 			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
202 
203 			pa.pa_iot = iot;
204 			pa.pa_memt = memt;
205 			pa.pa_dmat = pba->pba_dmat;
206 			pa.pa_pc = pc;
207 			pa.pa_device = device;
208 			pa.pa_function = function;
209 			pa.pa_bus = bus;
210 			pa.pa_tag = tag;
211 			pa.pa_id = id;
212 			pa.pa_class = class;
213 
214 			/* This is a simplification of the NetBSD code.
215 			   We don't support turning off I/O or memory
216 			   on broken hardware. <csapuntz@stanford.edu> */
217 			pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
218 #ifdef __i386__
219 			/*
220 			 * on i386 we really need to know the device tag
221 			 * and not the pci bridge tag, in intr_map
222 			 * to be able to program the device and the
223 			 * pci interrupt router.
224 			 */
225 			pa.pa_intrtag = tag;
226 			pa.pa_intrswiz = 0;
227 #else
228 			if (bus == 0) {
229 				pa.pa_intrswiz = 0;
230 				pa.pa_intrtag = tag;
231 			} else {
232 				pa.pa_intrswiz = pba->pba_intrswiz + device;
233 				pa.pa_intrtag = pba->pba_intrtag;
234 			}
235 #endif
236 			pin = PCI_INTERRUPT_PIN(intr);
237 			if (pin == PCI_INTERRUPT_PIN_NONE) {
238 				/* no interrupt */
239 				pa.pa_intrpin = 0;
240 			} else {
241 				/*
242 				 * swizzle it based on the number of
243 				 * busses we're behind and our device
244 				 * number.
245 				 */
246 				pa.pa_intrpin =			/* XXX */
247 				    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
248 			}
249 			pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
250 
251 			config_found_sm(self, &pa, pciprint, pcisubmatch);
252 		}
253 	}
254 
255 	if (bus == 0 && pci_isa_bridge_callback != NULL)
256 		(*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg);
257 }
258 
259 int
260 pciprint(aux, pnp)
261 	void *aux;
262 	const char *pnp;
263 {
264 	register struct pci_attach_args *pa = aux;
265 	char devinfo[256];
266 
267 	if (pnp) {
268 		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo);
269 		printf("%s at %s", devinfo, pnp);
270 	}
271 	printf(" dev %d function %d", pa->pa_device, pa->pa_function);
272 	if (!pnp) {
273 		pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
274 		printf(" %s", devinfo);
275 	}
276 
277 	return (UNCONF);
278 }
279 
280 int
281 pcisubmatch(parent, match, aux)
282 	struct device *parent;
283 	void *match, *aux;
284 {
285 	struct cfdata *cf = match;
286 	struct pci_attach_args *pa = aux;
287 	int success;
288 
289 	if (cf->pcicf_dev != PCI_UNK_DEV &&
290 	    cf->pcicf_dev != pa->pa_device)
291 		return 0;
292 	if (cf->pcicf_function != PCI_UNK_FUNCTION &&
293 	    cf->pcicf_function != pa->pa_function)
294 		return 0;
295 
296 	success = (*cf->cf_attach->ca_match)(parent, match, aux);
297 
298 	/* My Dell BIOS does not enable certain non-critical PCI devices
299 	   for IO and memory cycles (e.g. network card). This is
300 	   the generic approach to fixing this problem. Basically, if
301 	   we support the card, then we enable its IO cycles.
302 	*/
303 	if (success) {
304 		u_int32_t csr = pci_conf_read(pa->pa_pc, pa->pa_tag,
305 					      PCI_COMMAND_STATUS_REG);
306 
307 		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
308 			       csr | PCI_COMMAND_MASTER_ENABLE |
309 			       PCI_COMMAND_IO_ENABLE |
310 			       PCI_COMMAND_MEM_ENABLE);
311 	}
312 
313 	return (success);
314 }
315 
316 void
317 set_pci_isa_bridge_callback(fn, arg)
318 	void (*fn) __P((void *));
319 	void *arg;
320 {
321 
322 	if (pci_isa_bridge_callback != NULL)
323 		panic("set_pci_isa_bridge_callback");
324 	pci_isa_bridge_callback = fn;
325 	pci_isa_bridge_callback_arg = arg;
326 }
327 
328 int
329 pci_get_capability(pc, tag, capid, offset, value)
330 	pci_chipset_tag_t pc;
331 	pcitag_t tag;
332 	int capid;
333 	int *offset;
334 	pcireg_t *value;
335 {
336 	pcireg_t reg;
337 	unsigned int ofs;
338 
339 	reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
340 	if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
341 		return (0);
342 
343 	ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, PCI_CAPLISTPTR_REG));
344 	while (ofs != 0) {
345 #ifdef DIAGNOSTIC
346 		if ((ofs & 3) || (ofs < 0x40))
347 			panic("pci_get_capability");
348 #endif
349 		reg = pci_conf_read(pc, tag, ofs);
350 		if (PCI_CAPLIST_CAP(reg) == capid) {
351 			if (offset)
352 				*offset = ofs;
353 			if (value)
354 				*value = reg;
355 			return (1);
356 		}
357 		ofs = PCI_CAPLIST_NEXT(reg);
358 	}
359 
360 	return (0);
361 }
362 
363 #ifdef USER_PCICONF
364 /*
365  * This is the user interface to PCI configuration space.
366  */
367 
368 #include <sys/pciio.h>
369 #include <sys/fcntl.h>
370 
371 #ifdef DEBUG
372 #define PCIDEBUG(x) printf x
373 #else
374 #define PCIDEBUG(x)
375 #endif
376 
377 
378 int pciopen __P((dev_t dev, int oflags, int devtype, struct proc *p));
379 int pciclose __P((dev_t dev, int flag, int devtype, struct proc *p));
380 int pciioctl __P((dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p));
381 
382 int
383 pciopen(dev_t dev, int oflags, int devtype, struct proc *p)
384 {
385 	PCIDEBUG(("pciopen ndevs: %d\n" , pci_cd.cd_ndevs));
386 
387 	if ((oflags & FWRITE) && securelevel > 0) {
388 		return EPERM;
389 	}
390 	return 0;
391 }
392 
393 int
394 pciclose(dev_t dev, int flag, int devtype, struct proc *p)
395 {
396 	PCIDEBUG(("pciclose\n"));
397 	return 0;
398 }
399 
400 int
401 pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
402 {
403 	struct pci_io *io;
404 	int error;
405 	pcitag_t tag;
406 	struct pci_softc *pci;
407 	pci_chipset_tag_t pc;
408 
409 	io = (struct pci_io *)data;
410 
411 	PCIDEBUG(("pciioctl cmd %s", cmd == PCIOCREAD ? "pciocread"
412 		  : cmd == PCIOCWRITE ? "pciocwrite" : "unknown"));
413 	PCIDEBUG(("  bus %d dev %d func %d reg %x\n", io->pi_sel.pc_bus,
414 		  io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg));
415 
416 	if (io->pi_sel.pc_bus >= pci_cd.cd_ndevs) {
417 		error = ENXIO;
418 		goto done;
419 	}
420 	pci = pci_cd.cd_devs[io->pi_sel.pc_bus];
421 	if (pci != NULL) {
422 		pc = pci->sc_pc;
423 	} else {
424 		error = ENXIO;
425 		goto done;
426 	}
427 #ifdef __i386__
428 	/* The i386 pci_make_tag function can panic if called with wrong
429 	   args, try to avoid that */
430 	if (io->pi_sel.pc_bus >= 256 ||
431 	    io->pi_sel.pc_dev >= pci_bus_maxdevs(pc, io->pi_sel.pc_bus) ||
432 	    io->pi_sel.pc_func >= 8) {
433 		error = EINVAL;
434 		goto done;
435 	}
436 #endif
437 
438 	tag = pci_make_tag(pc, io->pi_sel.pc_bus, io->pi_sel.pc_dev,
439 			   io->pi_sel.pc_func);
440 
441 	switch(cmd) {
442 	case PCIOCGETCONF:
443 		error = ENODEV;
444 		break;
445 
446 	case PCIOCREAD:
447 		switch(io->pi_width) {
448 		case 4:
449 			/* Make sure the register is properly aligned */
450 			if (io->pi_reg & 0x3)
451 				return EINVAL;
452 			io->pi_data = pci_conf_read(pc, tag, io->pi_reg);
453 			error = 0;
454 			break;
455 		default:
456 			error = ENODEV;
457 			break;
458 		}
459 		break;
460 
461 	case PCIOCWRITE:
462 		if (!(flag & FWRITE))
463 			return EPERM;
464 
465 		switch(io->pi_width) {
466 		case 4:
467 			/* Make sure the register is properly aligned */
468 			if (io->pi_reg & 0x3)
469 				return EINVAL;
470 			pci_conf_write(pc, tag, io->pi_reg, io->pi_data);
471 			break;
472 		default:
473 			error = ENODEV;
474 			break;
475 		}
476 		break;
477 
478 	default:
479 		error = ENOTTY;
480 		break;
481 	}
482  done:
483 	return (error);
484 }
485 
486 #endif
487