xref: /openbsd-src/sys/dev/pci/pci.c (revision 62a742911104f98b9185b2c6b6007d9b1c36396c)
1 /*	$OpenBSD: pci.c,v 1.14 1998/10/29 18:11:53 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 struct cfattach pci_ca = {
50 	sizeof(struct device), pcimatch, pciattach
51 };
52 
53 struct cfdriver pci_cd = {
54 	NULL, "pci", DV_DULL
55 };
56 
57 int	pciprint __P((void *, const char *));
58 int	pcisubmatch __P((struct device *, void *, void *));
59 
60 /*
61  * Callback so that ISA/EISA bridges can attach their child busses
62  * after PCI configuration is done.
63  *
64  * This works because:
65  *	(1) there can be at most one ISA/EISA bridge per PCI bus, and
66  *	(2) any ISA/EISA bridges must be attached to primary PCI
67  *	    busses (i.e. bus zero).
68  *
69  * That boils down to: there can only be one of these outstanding
70  * at a time, it is cleared when configuring PCI bus 0 before any
71  * subdevices have been found, and it is run after all subdevices
72  * of PCI bus 0 have been found.
73  *
74  * This is needed because there are some (legacy) PCI devices which
75  * can show up as ISA/EISA devices as well (the prime example of which
76  * are VGA controllers).  If you attach ISA from a PCI-ISA/EISA bridge,
77  * and the bridge is seen before the video board is, the board can show
78  * up as an ISA device, and that can (bogusly) complicate the PCI device's
79  * attach code, or make the PCI device not be properly attached at all.
80  */
81 static void	(*pci_isa_bridge_callback) __P((void *));
82 static void	*pci_isa_bridge_callback_arg;
83 
84 int
85 pcimatch(parent, match, aux)
86 	struct device *parent;
87 	void *match, *aux;
88 {
89 	struct cfdata *cf = match;
90 	struct pcibus_attach_args *pba = aux;
91 
92 	if (strcmp(pba->pba_busname, cf->cf_driver->cd_name))
93 		return (0);
94 
95 	/* Check the locators */
96 	if (cf->pcibuscf_bus != PCIBUS_UNK_BUS &&
97 	    cf->pcibuscf_bus != pba->pba_bus)
98 		return (0);
99 
100 	/* sanity */
101 	if (pba->pba_bus < 0 || pba->pba_bus > 255)
102 		return (0);
103 
104 	/*
105 	 * XXX check other (hardware?) indicators
106 	 */
107 
108 	return 1;
109 }
110 
111 void
112 pciattach(parent, self, aux)
113 	struct device *parent, *self;
114 	void *aux;
115 {
116 	struct pcibus_attach_args *pba = aux;
117 	bus_space_tag_t iot, memt;
118 	pci_chipset_tag_t pc;
119 	int bus, device, maxndevs, function, nfunctions;
120 
121 	pci_attach_hook(parent, self, pba);
122 	printf("\n");
123 
124 	iot = pba->pba_iot;
125 	memt = pba->pba_memt;
126 	pc = pba->pba_pc;
127 	bus = pba->pba_bus;
128 	maxndevs = pci_bus_maxdevs(pc, bus);
129 
130 	if (bus == 0)
131 		pci_isa_bridge_callback = NULL;
132 
133 	for (device = 0; device < maxndevs; device++) {
134 		pcitag_t tag;
135 		pcireg_t id, class, intr, bhlcr;
136 		struct pci_attach_args pa;
137 		int pin;
138 
139 		tag = pci_make_tag(pc, bus, device, 0);
140 		id = pci_conf_read(pc, tag, PCI_ID_REG);
141 
142 		/* Invalid vendor ID value? */
143 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
144 			continue;
145 		/* XXX Not invalid, but we've done this ~forever. */
146 		if (PCI_VENDOR(id) == 0)
147 			continue;
148 
149 		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
150 		nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
151 
152 		for (function = 0; function < nfunctions; function++) {
153 			tag = pci_make_tag(pc, bus, device, function);
154 			id = pci_conf_read(pc, tag, PCI_ID_REG);
155 
156 			/* Invalid vendor ID value? */
157 			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
158 				continue;
159 			/* XXX Not invalid, but we've done this ~forever. */
160 			if (PCI_VENDOR(id) == 0)
161 				continue;
162 
163 			class = pci_conf_read(pc, tag, PCI_CLASS_REG);
164 			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
165 
166 			pa.pa_iot = iot;
167 			pa.pa_memt = memt;
168 			pa.pa_dmat = pba->pba_dmat;
169 			pa.pa_pc = pc;
170 			pa.pa_device = device;
171 			pa.pa_function = function;
172 			pa.pa_tag = tag;
173 			pa.pa_id = id;
174 			pa.pa_class = class;
175 
176 			if (bus == 0) {
177 				pa.pa_intrswiz = 0;
178 				pa.pa_intrtag = tag;
179 			} else {
180 				pa.pa_intrswiz = pba->pba_intrswiz + device;
181 				pa.pa_intrtag = pba->pba_intrtag;
182 			}
183 			pin = PCI_INTERRUPT_PIN(intr);
184 			if (pin == PCI_INTERRUPT_PIN_NONE) {
185 				/* no interrupt */
186 				pa.pa_intrpin = 0;
187 			} else {
188 				/*
189 				 * swizzle it based on the number of
190 				 * busses we're behind and our device
191 				 * number.
192 				 */
193 				pa.pa_intrpin =			/* XXX */
194 				    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
195 			}
196 			pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
197 
198 			config_found_sm(self, &pa, pciprint, pcisubmatch);
199 		}
200 	}
201 
202 	if (bus == 0 && pci_isa_bridge_callback != NULL)
203 		(*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg);
204 }
205 
206 int
207 pciprint(aux, pnp)
208 	void *aux;
209 	const char *pnp;
210 {
211 	register struct pci_attach_args *pa = aux;
212 	char devinfo[256];
213 
214 	if (pnp) {
215 		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo);
216 		printf("%s at %s", devinfo, pnp);
217 	}
218 	printf(" dev %d function %d", pa->pa_device, pa->pa_function);
219 	if (!pnp) {
220 		pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
221 		printf(" %s", devinfo);
222 	}
223 
224 	return (UNCONF);
225 }
226 
227 int
228 pcisubmatch(parent, match, aux)
229 	struct device *parent;
230 	void *match, *aux;
231 {
232 	struct cfdata *cf = match;
233 	struct pci_attach_args *pa = aux;
234 	int success;
235 
236 	if (cf->pcicf_dev != PCI_UNK_DEV &&
237 	    cf->pcicf_dev != pa->pa_device)
238 		return 0;
239 	if (cf->pcicf_function != PCI_UNK_FUNCTION &&
240 	    cf->pcicf_function != pa->pa_function)
241 		return 0;
242 
243 	success = (*cf->cf_attach->ca_match)(parent, match, aux);
244 
245 	/* My Dell BIOS does not enable certain non-critical PCI devices
246 	   for IO and memory cycles (e.g. network card). This is
247 	   the generic approach to fixing this problem. Basically, if
248 	   we support the card, then we enable its IO cycles.
249 	*/
250 	if (success) {
251 		u_int32_t csr = pci_conf_read(pa->pa_pc, pa->pa_tag,
252 					      PCI_COMMAND_STATUS_REG);
253 
254 		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
255 			       csr | PCI_COMMAND_MASTER_ENABLE |
256 			       PCI_COMMAND_IO_ENABLE |
257 			       PCI_COMMAND_MEM_ENABLE);
258 	}
259 
260 	return (success);
261 }
262 
263 int
264 pci_io_find(pc, pcitag, reg, iobasep, iosizep)
265 	pci_chipset_tag_t pc;
266 	pcitag_t pcitag;
267 	int reg;
268 	bus_addr_t *iobasep;
269 	bus_size_t *iosizep;
270 {
271 	pcireg_t addrdata, sizedata;
272 	int s;
273 
274 	if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
275 		panic("pci_io_find: bad request");
276 
277 	/* XXX?
278 	 * Section 6.2.5.1, `Address Maps', tells us that:
279 	 *
280 	 * 1) The builtin software should have already mapped the device in a
281 	 * reasonable way.
282 	 *
283 	 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
284 	 * n bits of the address to 0.  As recommended, we write all 1s and see
285 	 * what we get back.
286 	 */
287 	addrdata = pci_conf_read(pc, pcitag, reg);
288 
289 	s = splhigh();
290 	pci_conf_write(pc, pcitag, reg, 0xffffffff);
291 	sizedata = pci_conf_read(pc, pcitag, reg);
292 	pci_conf_write(pc, pcitag, reg, addrdata);
293 	splx(s);
294 
295 	if (PCI_MAPREG_TYPE(addrdata) != PCI_MAPREG_TYPE_IO)
296 		panic("pci_io_find: not an I/O region");
297 
298 	if (iobasep != NULL)
299 		*iobasep = PCI_MAPREG_IO_ADDR(addrdata);
300 	if (iosizep != NULL)
301 		*iosizep = PCI_MAPREG_IO_SIZE(sizedata);
302 
303 #ifdef powerpc
304 	/*
305 	 * Open Firmware (yuck) shuts down devices before entering a
306 	 * program so we need to bring them back 'online' to respond
307          * to bus accesses... so far this is true on the power.4e.
308          */
309 	s = splhigh();
310 	sizedata = pci_conf_read(pc, pcitag, PCI_COMMAND_STATUS_REG);
311 	sizedata |= (PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE |
312 		     PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE);
313 	pci_conf_write(pc, pcitag, PCI_COMMAND_STATUS_REG, sizedata);
314 	splx(s);
315 #endif
316 
317 	return (0);
318 }
319 
320 int
321 pci_mem_find(pc, pcitag, reg, membasep, memsizep, cacheablep)
322 	pci_chipset_tag_t pc;
323 	pcitag_t pcitag;
324 	int reg;
325 	bus_addr_t *membasep;
326 	bus_size_t *memsizep;
327 	int *cacheablep;
328 {
329 	pcireg_t addrdata, sizedata;
330 	int s;
331 
332 	if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
333 		panic("pci_find_mem: bad request");
334 
335 	/*
336 	 * Section 6.2.5.1, `Address Maps', tells us that:
337 	 *
338 	 * 1) The builtin software should have already mapped the device in a
339 	 * reasonable way.
340 	 *
341 	 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
342 	 * n bits of the address to 0.  As recommended, we write all 1s and see
343 	 * what we get back.
344 	 */
345 	addrdata = pci_conf_read(pc, pcitag, reg);
346 
347 	s = splhigh();
348 	pci_conf_write(pc, pcitag, reg, 0xffffffff);
349 	sizedata = pci_conf_read(pc, pcitag, reg);
350 	pci_conf_write(pc, pcitag, reg, addrdata);
351 	splx(s);
352 
353 	if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_IO)
354 		panic("pci_find_mem: I/O region");
355 
356 	switch (PCI_MAPREG_MEM_TYPE(addrdata)) {
357 	case PCI_MAPREG_MEM_TYPE_32BIT:
358 	case PCI_MAPREG_MEM_TYPE_32BIT_1M:
359 		break;
360 	case PCI_MAPREG_MEM_TYPE_64BIT:
361 /* XXX */	printf("pci_find_mem: 64-bit region\n");
362 /* XXX */	return (1);
363 	default:
364 		printf("pci_find_mem: reserved region type\n");
365 		return (1);
366 	}
367 
368 	if (membasep != NULL)
369 		*membasep = PCI_MAPREG_MEM_ADDR(addrdata);	/* PCI addr */
370 	if (memsizep != NULL)
371 		*memsizep = PCI_MAPREG_MEM_SIZE(sizedata);
372 	if (cacheablep != NULL)
373 		*cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata);
374 
375 #ifdef powerpc
376 	/*
377 	 * Open Firmware (yuck) shuts down devices before entering a
378 	 * program so we need to bring them back 'online' to respond
379          * to bus accesses... so far this is true on the power.4e.
380          */
381 	s = splhigh();
382 	sizedata = pci_conf_read(pc, pcitag, PCI_COMMAND_STATUS_REG);
383 	sizedata |= (PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE |
384 		     PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE);
385 	pci_conf_write(pc, pcitag, PCI_COMMAND_STATUS_REG, sizedata);
386 	splx(s);
387 #endif
388 
389 	return 0;
390 }
391 
392 void
393 set_pci_isa_bridge_callback(fn, arg)
394 	void (*fn) __P((void *));
395 	void *arg;
396 {
397 
398 	if (pci_isa_bridge_callback != NULL)
399 		panic("set_pci_isa_bridge_callback");
400 	pci_isa_bridge_callback = fn;
401 	pci_isa_bridge_callback_arg = arg;
402 }
403