xref: /openbsd-src/sys/arch/i386/pci/pci_machdep.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: pci_machdep.c,v 1.18 2001/01/27 04:59:40 mickey Exp $	*/
2 /*	$NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $	*/
3 
4 /*-
5  * Copyright (c) 1997 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the NetBSD
23  *	Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /*
42  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
43  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  * 1. Redistributions of source code must retain the above copyright
49  *    notice, this list of conditions and the following disclaimer.
50  * 2. Redistributions in binary form must reproduce the above copyright
51  *    notice, this list of conditions and the following disclaimer in the
52  *    documentation and/or other materials provided with the distribution.
53  * 3. All advertising materials mentioning features or use of this software
54  *    must display the following acknowledgement:
55  *	This product includes software developed by Charles Hannum.
56  * 4. The name of the author may not be used to endorse or promote products
57  *    derived from this software without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69  */
70 
71 /*
72  * Machine-specific functions for PCI autoconfiguration.
73  *
74  * On PCs, there are two methods of generating PCI configuration cycles.
75  * We try to detect the appropriate mechanism for this machine and set
76  * up a few function pointers to access the correct method directly.
77  *
78  * The configuration method can be hard-coded in the config file by
79  * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
80  * as defined section 3.6.4.1, `Generating Configuration Cycles'.
81  */
82 
83 #include <sys/types.h>
84 #include <sys/param.h>
85 #include <sys/time.h>
86 #include <sys/systm.h>
87 #include <sys/errno.h>
88 #include <sys/device.h>
89 
90 #include <vm/vm.h>
91 #include <vm/vm_kern.h>
92 
93 #define _I386_BUS_DMA_PRIVATE
94 #include <machine/bus.h>
95 #include <machine/pio.h>
96 
97 #include "bios.h"
98 #if NBIOS > 0
99 #include <machine/biosvar.h>
100 extern bios_pciinfo_t *bios_pciinfo;
101 #endif
102 
103 #include <i386/isa/icu.h>
104 #include <dev/isa/isavar.h>
105 #include <dev/pci/pcivar.h>
106 #include <dev/pci/pcireg.h>
107 
108 #include "pcibios.h"
109 #if NPCIBIOS > 0
110 #include <i386/pci/pcibiosvar.h>
111 #endif
112 
113 int pci_mode = -1;
114 
115 #define	PCI_MODE1_ENABLE	0x80000000UL
116 #define	PCI_MODE1_ADDRESS_REG	0x0cf8
117 #define	PCI_MODE1_DATA_REG	0x0cfc
118 
119 #define	PCI_MODE2_ENABLE_REG	0x0cf8
120 #define	PCI_MODE2_FORWARD_REG	0x0cfa
121 
122 /*
123  * PCI doesn't have any special needs; just use the generic versions
124  * of these functions.
125  */
126 struct i386_bus_dma_tag pci_bus_dma_tag = {
127 	NULL,			/* _cookie */
128 	_bus_dmamap_create,
129 	_bus_dmamap_destroy,
130 	_bus_dmamap_load,
131 	_bus_dmamap_load_mbuf,
132 	_bus_dmamap_load_uio,
133 	_bus_dmamap_load_raw,
134 	_bus_dmamap_unload,
135 	NULL,			/* _dmamap_sync */
136 	_bus_dmamem_alloc,
137 	_bus_dmamem_free,
138 	_bus_dmamem_map,
139 	_bus_dmamem_unmap,
140 	_bus_dmamem_mmap,
141 };
142 
143 void
144 pci_attach_hook(parent, self, pba)
145 	struct device *parent, *self;
146 	struct pcibus_attach_args *pba;
147 {
148 
149 #if NBIOS > 0
150 	if (pba->pba_bus == 0)
151 		printf(": configuration mode %d (%s)",
152 			pci_mode, (bios_pciinfo?"bios":"no bios"));
153 #else
154 	if (pba->pba_bus == 0)
155 		printf(": configuration mode %d", pci_mode);
156 #endif
157 }
158 
159 int
160 pci_bus_maxdevs(pc, busno)
161 	pci_chipset_tag_t pc;
162 	int busno;
163 {
164 
165 	/*
166 	 * Bus number is irrelevant.  If Configuration Mechanism 2 is in
167 	 * use, can only have devices 0-15 on any bus.  If Configuration
168 	 * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal'
169 	 * range).
170 	 */
171 	if (pci_mode == 2)
172 		return (16);
173 	else
174 		return (32);
175 }
176 
177 pcitag_t
178 pci_make_tag(pc, bus, device, function)
179 	pci_chipset_tag_t pc;
180 	int bus, device, function;
181 {
182 	pcitag_t tag;
183 
184 #ifndef PCI_CONF_MODE
185 	switch (pci_mode) {
186 	case 1:
187 		goto mode1;
188 	case 2:
189 		goto mode2;
190 	default:
191 		panic("pci_make_tag: mode not configured");
192 	}
193 #endif
194 
195 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
196 #ifndef PCI_CONF_MODE
197 mode1:
198 #endif
199 	if (bus >= 256 || device >= 32 || function >= 8)
200 		panic("pci_make_tag: bad request");
201 
202 	tag.mode1 = PCI_MODE1_ENABLE |
203 		    (bus << 16) | (device << 11) | (function << 8);
204 	return tag;
205 #endif
206 
207 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
208 #ifndef PCI_CONF_MODE
209 mode2:
210 #endif
211 	if (bus >= 256 || device >= 16 || function >= 8)
212 		panic("pci_make_tag: bad request");
213 
214 	tag.mode2.port = 0xc000 | (device << 8);
215 	tag.mode2.enable = 0xf0 | (function << 1);
216 	tag.mode2.forward = bus;
217 	return tag;
218 #endif
219 }
220 
221 void
222 pci_decompose_tag(pc, tag, bp, dp, fp)
223 	pci_chipset_tag_t pc;
224 	pcitag_t tag;
225 	int *bp, *dp, *fp;
226 {
227 
228 #ifndef PCI_CONF_MODE
229 	switch (pci_mode) {
230 	case 1:
231 		goto mode1;
232 	case 2:
233 		goto mode2;
234 	default:
235 		panic("pci_decompose_tag: mode not configured");
236 	}
237 #endif
238 
239 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
240 #ifndef PCI_CONF_MODE
241 mode1:
242 #endif
243 	if (bp != NULL)
244 		*bp = (tag.mode1 >> 16) & 0xff;
245 	if (dp != NULL)
246 		*dp = (tag.mode1 >> 11) & 0x1f;
247 	if (fp != NULL)
248 		*fp = (tag.mode1 >> 8) & 0x7;
249 	return;
250 #endif
251 
252 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
253 #ifndef PCI_CONF_MODE
254 mode2:
255 #endif
256 	if (bp != NULL)
257 		*bp = tag.mode2.forward & 0xff;
258 	if (dp != NULL)
259 		*dp = (tag.mode2.port >> 8) & 0xf;
260 	if (fp != NULL)
261 		*fp = (tag.mode2.enable >> 1) & 0x7;
262 #endif
263 }
264 
265 pcireg_t
266 pci_conf_read(pc, tag, reg)
267 	pci_chipset_tag_t pc;
268 	pcitag_t tag;
269 	int reg;
270 {
271 	pcireg_t data;
272 
273 #ifndef PCI_CONF_MODE
274 	switch (pci_mode) {
275 	case 1:
276 		goto mode1;
277 	case 2:
278 		goto mode2;
279 	default:
280 		panic("pci_conf_read: mode not configured");
281 	}
282 #endif
283 
284 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
285 #ifndef PCI_CONF_MODE
286 mode1:
287 #endif
288 	outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
289 	data = inl(PCI_MODE1_DATA_REG);
290 	outl(PCI_MODE1_ADDRESS_REG, 0);
291 	return data;
292 #endif
293 
294 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
295 #ifndef PCI_CONF_MODE
296 mode2:
297 #endif
298 	outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
299 	outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
300 	data = inl(tag.mode2.port | reg);
301 	outb(PCI_MODE2_ENABLE_REG, 0);
302 	return data;
303 #endif
304 }
305 
306 void
307 pci_conf_write(pc, tag, reg, data)
308 	pci_chipset_tag_t pc;
309 	pcitag_t tag;
310 	int reg;
311 	pcireg_t data;
312 {
313 
314 #ifndef PCI_CONF_MODE
315 	switch (pci_mode) {
316 	case 1:
317 		goto mode1;
318 	case 2:
319 		goto mode2;
320 	default:
321 		panic("pci_conf_write: mode not configured");
322 	}
323 #endif
324 
325 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
326 #ifndef PCI_CONF_MODE
327 mode1:
328 #endif
329 	outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
330 	outl(PCI_MODE1_DATA_REG, data);
331 	outl(PCI_MODE1_ADDRESS_REG, 0);
332 	return;
333 #endif
334 
335 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
336 #ifndef PCI_CONF_MODE
337 mode2:
338 #endif
339 	outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
340 	outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
341 	outl(tag.mode2.port | reg, data);
342 	outb(PCI_MODE2_ENABLE_REG, 0);
343 #endif
344 }
345 
346 int
347 pci_mode_detect()
348 {
349 
350 #ifdef PCI_CONF_MODE
351 #if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2)
352 	return (pci_mode = PCI_CONF_MODE);
353 #else
354 #error Invalid PCI configuration mode.
355 #endif
356 #else
357 	if (pci_mode != -1)
358 		return pci_mode;
359 
360 #if NBIOS > 0
361 	/*
362 	 * If we have PCI info passed from the BIOS, use the mode given there
363 	 * for all of this code.  If not, pass on through to the previous tests
364 	 * to try and devine the correct mode.
365 	 */
366 	if (bios_pciinfo != NULL) {
367 		if (bios_pciinfo->pci_chars & 0x2)
368 			return (pci_mode = 2);
369 
370 		if (bios_pciinfo->pci_chars & 0x1)
371 			return (pci_mode = 1);
372 
373 		/* We should never get here, but if we do, fall through... */
374 	}
375 #endif
376 
377 	/*
378 	 * We try to divine which configuration mode the host bridge wants.  We
379 	 * try mode 2 first, because our probe for mode 1 is likely to succeed
380 	 * for mode 2 also.
381 	 *
382 	 * This should really be done using the PCI BIOS.  If we get here, the
383 	 * PCI BIOS does not exist, or the boot blocks did not provide the
384 	 * information.
385 	 */
386 	outb(PCI_MODE2_ENABLE_REG, 0);
387 	outb(PCI_MODE2_FORWARD_REG, 0);
388 	if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
389 	    inb(PCI_MODE2_FORWARD_REG) != 0)
390 		goto not2;
391 	return (pci_mode = 2);
392 
393 not2:
394 	outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
395 	if (inl(PCI_MODE1_ADDRESS_REG) != PCI_MODE1_ENABLE)
396 		goto not1;
397 	outl(PCI_MODE1_ADDRESS_REG, 0);
398 	if (inl(PCI_MODE1_ADDRESS_REG) != 0)
399 		goto not1;
400 	return (pci_mode = 1);
401 
402 not1:
403 	return (pci_mode = 0);
404 #endif
405 }
406 
407 int
408 pci_intr_map(pc, intrtag, pin, line, ihp)
409 	pci_chipset_tag_t pc;
410 	pcitag_t intrtag;
411 	int pin, line;
412 	pci_intr_handle_t *ihp;
413 {
414 	if (pin == 0) {
415 		/* No IRQ used. */
416 		goto bad;
417 	}
418 
419 	if (pin > 4) {
420 		printf("pci_intr_map: bad interrupt pin %d\n", pin);
421 		goto bad;
422 	}
423 
424 	ihp->line = line;
425 	ihp->pin = pin;
426 #if NPCIBIOS > 0
427 	pci_intr_header_fixup(pc, intrtag, ihp);
428 	line = ihp->line;
429 #endif
430 
431 	/*
432 	 * Section 6.2.4, `Miscellaneous Functions', says that 255 means
433 	 * `unknown' or `no connection' on a PC.  We assume that a device with
434 	 * `no connection' either doesn't have an interrupt (in which case the
435 	 * pin number should be 0, and would have been noticed above), or
436 	 * wasn't configured by the BIOS (in which case we punt, since there's
437 	 * no real way we can know how the interrupt lines are mapped in the
438 	 * hardware).
439 	 *
440 	 * XXX
441 	 * Since IRQ 0 is only used by the clock, and we can't actually be sure
442 	 * that the BIOS did its job, we also recognize that as meaning that
443 	 * the BIOS has not configured the device.
444 	 */
445 	if (line == 0 || line == 255) {
446 		printf("pci_intr_map: no mapping for pin %c\n", '@' + pin);
447 		goto bad;
448 	} else {
449 		if (line >= ICU_LEN) {
450 			printf("pci_intr_map: bad interrupt line %d\n", line);
451 			goto bad;
452 		}
453 		if (line == 2) {
454 			printf("pci_intr_map: changed line 2 to line 9\n");
455 			line = 9;
456 		}
457 	}
458 
459 	return 0;
460 
461 bad:
462 	ihp->line = -1;
463 	return 1;
464 }
465 
466 const char *
467 pci_intr_string(pc, ih)
468 	pci_chipset_tag_t pc;
469 	pci_intr_handle_t ih;
470 {
471 	static char irqstr[8];		/* 4 + 2 + NULL + sanity */
472 
473 	if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2)
474 		panic("pci_intr_string: bogus handle 0x%x", ih.line);
475 
476 	sprintf(irqstr, "irq %d", ih.line);
477 	return (irqstr);
478 
479 }
480 
481 void *
482 pci_intr_establish(pc, ih, level, func, arg, what)
483 	pci_chipset_tag_t pc;
484 	pci_intr_handle_t ih;
485 	int level, (*func) __P((void *));
486 	void *arg;
487 	char *what;
488 {
489 	void *ret;
490 
491 	if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2)
492 		panic("pci_intr_establish: bogus handle 0x%x", ih.line);
493 
494 	ret = isa_intr_establish(NULL, ih.line,
495 	    IST_LEVEL, level, func, arg, what);
496 #if NPCIBIOS > 0
497 	if (ret)
498 		pci_intr_route_link(pc, &ih);
499 #endif
500 	return ret;
501 }
502 
503 void
504 pci_intr_disestablish(pc, cookie)
505 	pci_chipset_tag_t pc;
506 	void *cookie;
507 {
508 	/* XXX oh, unroute the pci int link? */
509 	return isa_intr_disestablish(NULL, cookie);
510 }
511