xref: /openbsd-src/sys/dev/pci/pci.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: pci.c,v 1.21 2001/07/20 05:56:25 csapuntz 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 
135 	pci_attach_hook(parent, self, pba);
136 	printf("\n");
137 
138 	iot = pba->pba_iot;
139 	memt = pba->pba_memt;
140 	pc = pba->pba_pc;
141 	bus = pba->pba_bus;
142 	maxndevs = pci_bus_maxdevs(pc, bus);
143 
144 #ifdef USER_PCICONF
145 	sc->sc_pc = pba->pba_pc;
146 #endif
147 
148 	if (bus == 0)
149 		pci_isa_bridge_callback = NULL;
150 
151 	for (device = 0; device < maxndevs; device++) {
152 		pcitag_t tag;
153 		pcireg_t id, class, intr, bhlcr;
154 		struct pci_attach_args pa;
155 		int pin;
156 
157 		tag = pci_make_tag(pc, bus, device, 0);
158 		id = pci_conf_read(pc, tag, PCI_ID_REG);
159 
160 		/* Invalid vendor ID value? */
161 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
162 			continue;
163 		/* XXX Not invalid, but we've done this ~forever. */
164 		if (PCI_VENDOR(id) == 0)
165 			continue;
166 
167 		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
168 		nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
169 
170 		for (function = 0; function < nfunctions; function++) {
171 			tag = pci_make_tag(pc, bus, device, function);
172 			id = pci_conf_read(pc, tag, PCI_ID_REG);
173 
174 			/* Invalid vendor ID value? */
175 			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
176 				continue;
177 			/* XXX Not invalid, but we've done this ~forever. */
178 			if (PCI_VENDOR(id) == 0)
179 				continue;
180 
181 			class = pci_conf_read(pc, tag, PCI_CLASS_REG);
182 			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
183 
184 			pa.pa_iot = iot;
185 			pa.pa_memt = memt;
186 			pa.pa_dmat = pba->pba_dmat;
187 			pa.pa_pc = pc;
188 			pa.pa_device = device;
189 			pa.pa_function = function;
190 			pa.pa_bus = bus;
191 			pa.pa_tag = tag;
192 			pa.pa_id = id;
193 			pa.pa_class = class;
194 
195 			/* This is a simplification of the NetBSD code.
196 			   We don't support turning off I/O or memory
197 			   on broken hardware. <csapuntz@stanford.edu> */
198 			pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
199 #ifdef __i386__
200 			/*
201 			 * on i386 we really need to know the device tag
202 			 * and not the pci bridge tag, in intr_map
203 			 * to be able to program the device and the
204 			 * pci interrupt router.
205 			 */
206 			pa.pa_intrtag = tag;
207 			pa.pa_intrswiz = 0;
208 #else
209 			if (bus == 0) {
210 				pa.pa_intrswiz = 0;
211 				pa.pa_intrtag = tag;
212 			} else {
213 				pa.pa_intrswiz = pba->pba_intrswiz + device;
214 				pa.pa_intrtag = pba->pba_intrtag;
215 			}
216 #endif
217 			pin = PCI_INTERRUPT_PIN(intr);
218 			if (pin == PCI_INTERRUPT_PIN_NONE) {
219 				/* no interrupt */
220 				pa.pa_intrpin = 0;
221 			} else {
222 				/*
223 				 * swizzle it based on the number of
224 				 * busses we're behind and our device
225 				 * number.
226 				 */
227 				pa.pa_intrpin =			/* XXX */
228 				    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
229 			}
230 			pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
231 
232 			config_found_sm(self, &pa, pciprint, pcisubmatch);
233 		}
234 	}
235 
236 	if (bus == 0 && pci_isa_bridge_callback != NULL)
237 		(*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg);
238 }
239 
240 int
241 pciprint(aux, pnp)
242 	void *aux;
243 	const char *pnp;
244 {
245 	register struct pci_attach_args *pa = aux;
246 	char devinfo[256];
247 
248 	if (pnp) {
249 		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo);
250 		printf("%s at %s", devinfo, pnp);
251 	}
252 	printf(" dev %d function %d", pa->pa_device, pa->pa_function);
253 	if (!pnp) {
254 		pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
255 		printf(" %s", devinfo);
256 	}
257 
258 	return (UNCONF);
259 }
260 
261 int
262 pcisubmatch(parent, match, aux)
263 	struct device *parent;
264 	void *match, *aux;
265 {
266 	struct cfdata *cf = match;
267 	struct pci_attach_args *pa = aux;
268 	int success;
269 
270 	if (cf->pcicf_dev != PCI_UNK_DEV &&
271 	    cf->pcicf_dev != pa->pa_device)
272 		return 0;
273 	if (cf->pcicf_function != PCI_UNK_FUNCTION &&
274 	    cf->pcicf_function != pa->pa_function)
275 		return 0;
276 
277 	success = (*cf->cf_attach->ca_match)(parent, match, aux);
278 
279 	/* My Dell BIOS does not enable certain non-critical PCI devices
280 	   for IO and memory cycles (e.g. network card). This is
281 	   the generic approach to fixing this problem. Basically, if
282 	   we support the card, then we enable its IO cycles.
283 	*/
284 	if (success) {
285 		u_int32_t csr = pci_conf_read(pa->pa_pc, pa->pa_tag,
286 					      PCI_COMMAND_STATUS_REG);
287 
288 		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
289 			       csr | PCI_COMMAND_MASTER_ENABLE |
290 			       PCI_COMMAND_IO_ENABLE |
291 			       PCI_COMMAND_MEM_ENABLE);
292 	}
293 
294 	return (success);
295 }
296 
297 void
298 set_pci_isa_bridge_callback(fn, arg)
299 	void (*fn) __P((void *));
300 	void *arg;
301 {
302 
303 	if (pci_isa_bridge_callback != NULL)
304 		panic("set_pci_isa_bridge_callback");
305 	pci_isa_bridge_callback = fn;
306 	pci_isa_bridge_callback_arg = arg;
307 }
308 
309 int
310 pci_get_capability(pc, tag, capid, offset, value)
311 	pci_chipset_tag_t pc;
312 	pcitag_t tag;
313 	int capid;
314 	int *offset;
315 	pcireg_t *value;
316 {
317 	pcireg_t reg;
318 	unsigned int ofs;
319 
320 	reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
321 	if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
322 		return (0);
323 
324 	ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, PCI_CAPLISTPTR_REG));
325 	while (ofs != 0) {
326 #ifdef DIAGNOSTIC
327 		if ((ofs & 3) || (ofs < 0x40))
328 			panic("pci_get_capability");
329 #endif
330 		reg = pci_conf_read(pc, tag, ofs);
331 		if (PCI_CAPLIST_CAP(reg) == capid) {
332 			if (offset)
333 				*offset = ofs;
334 			if (value)
335 				*value = reg;
336 			return (1);
337 		}
338 		ofs = PCI_CAPLIST_NEXT(reg);
339 	}
340 
341 	return (0);
342 }
343 
344 #ifdef USER_PCICONF
345 /*
346  * This is the user interface to PCI configuration space.
347  */
348 
349 #include <sys/pciio.h>
350 #include <sys/fcntl.h>
351 
352 #ifdef DEBUG
353 #define PCIDEBUG(x) printf x
354 #else
355 #define PCIDEBUG(x)
356 #endif
357 
358 
359 int pciopen __P((dev_t dev, int oflags, int devtype, struct proc *p));
360 int pciclose __P((dev_t dev, int flag, int devtype, struct proc *p));
361 int pciioctl __P((dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p));
362 
363 int
364 pciopen(dev_t dev, int oflags, int devtype, struct proc *p)
365 {
366 	PCIDEBUG(("pciopen ndevs: %d\n" , pci_cd.cd_ndevs));
367 
368 	if ((oflags & FWRITE) && securelevel > 0) {
369 		return EPERM;
370 	}
371 	return 0;
372 }
373 
374 int
375 pciclose(dev_t dev, int flag, int devtype, struct proc *p)
376 {
377 	PCIDEBUG(("pciclose\n"));
378 	return 0;
379 }
380 
381 int
382 pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
383 {
384 	struct pci_io *io;
385 	int error;
386 	pcitag_t tag;
387 	struct pci_softc *pci;
388 	pci_chipset_tag_t pc;
389 
390 	io = (struct pci_io *)data;
391 
392 	PCIDEBUG(("pciioctl cmd %s", cmd == PCIOCREAD ? "pciocread"
393 		  : cmd == PCIOCWRITE ? "pciocwrite" : "unknown"));
394 	PCIDEBUG(("  bus %d dev %d func %d reg %x\n", io->pi_sel.pc_bus,
395 		  io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg));
396 
397 	if (io->pi_sel.pc_bus >= pci_cd.cd_ndevs) {
398 		error = ENXIO;
399 		goto done;
400 	}
401 	pci = pci_cd.cd_devs[io->pi_sel.pc_bus];
402 	if (pci != NULL) {
403 		pc = pci->sc_pc;
404 	} else {
405 		error = ENXIO;
406 		goto done;
407 	}
408 #ifdef __i386__
409 	/* The i386 pci_make_tag function can panic if called with wrong
410 	   args, try to avoid that */
411 	if (io->pi_sel.pc_bus >= 256 ||
412 	    io->pi_sel.pc_dev >= pci_bus_maxdevs(pc, io->pi_sel.pc_bus) ||
413 	    io->pi_sel.pc_func >= 8) {
414 		error = EINVAL;
415 		goto done;
416 	}
417 #endif
418 
419 	tag = pci_make_tag(pc, io->pi_sel.pc_bus, io->pi_sel.pc_dev,
420 			   io->pi_sel.pc_func);
421 
422 	switch(cmd) {
423 	case PCIOCGETCONF:
424 		error = ENODEV;
425 		break;
426 
427 	case PCIOCREAD:
428 		switch(io->pi_width) {
429 		case 4:
430 			/* Make sure the register is properly aligned */
431 			if (io->pi_reg & 0x3)
432 				return EINVAL;
433 			io->pi_data = pci_conf_read(pc, tag, io->pi_reg);
434 			error = 0;
435 			break;
436 		default:
437 			error = ENODEV;
438 			break;
439 		}
440 		break;
441 
442 	case PCIOCWRITE:
443 		if (!(flag & FWRITE))
444 			return EPERM;
445 
446 		switch(io->pi_width) {
447 		case 4:
448 			/* Make sure the register is properly aligned */
449 			if (io->pi_reg & 0x3)
450 				return EINVAL;
451 			pci_conf_write(pc, tag, io->pi_reg, io->pi_data);
452 			break;
453 		default:
454 			error = ENODEV;
455 			break;
456 		}
457 		break;
458 
459 	default:
460 		error = ENOTTY;
461 		break;
462 	}
463  done:
464 	return (error);
465 }
466 
467 #endif
468