xref: /openbsd/sys/arch/i386/pci/pcibios.c (revision d485f761)
1 /*	$OpenBSD: pcibios.c,v 1.24 2001/05/12 19:12:44 mickey Exp $	*/
2 /*	$NetBSD: pcibios.c,v 1.5 2000/08/01 05:23:59 uch Exp $	*/
3 
4 /*
5  * Copyright (c) 2000 Michael Shalayeff
6  * 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 Michael Shalayeff.
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 OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 /*-
35  * Copyright (c) 1999 The NetBSD Foundation, Inc.
36  * All rights reserved.
37  *
38  * This code is derived from software contributed to The NetBSD Foundation
39  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
40  * NASA Ames Research Center.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *	This product includes software developed by the NetBSD
53  *	Foundation, Inc. and its contributors.
54  * 4. Neither the name of The NetBSD Foundation nor the names of its
55  *    contributors may be used to endorse or promote products derived
56  *    from this software without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
59  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
60  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
62  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68  * POSSIBILITY OF SUCH DAMAGE.
69  */
70 /*
71  * Copyright (c) 1999, by UCHIYAMA Yasushi
72  * All rights reserved.
73  *
74  * Redistribution and use in source and binary forms, with or without
75  * modification, are permitted provided that the following conditions
76  * are met:
77  * 1. Redistributions of source code must retain the above copyright
78  *    notice, this list of conditions and the following disclaimer.
79  * 2. The name of the developer may NOT be used to endorse or promote products
80  *    derived from this software without specific prior written permission.
81  *
82  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
83  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
86  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92  * SUCH DAMAGE.
93  */
94 
95 /*
96  * Interface to the PCI BIOS and PCI Interrupt Routing table.
97  */
98 
99 #include <sys/param.h>
100 #include <sys/systm.h>
101 #include <sys/device.h>
102 #include <sys/malloc.h>
103 
104 #include <dev/isa/isareg.h>
105 #include <i386/isa/isa_machdep.h>
106 
107 #include <dev/pci/pcireg.h>
108 #include <dev/pci/pcivar.h>
109 #include <dev/pci/pcidevs.h>
110 
111 #include <i386/pci/pcibiosvar.h>
112 
113 #include <machine/biosvar.h>
114 
115 int pcibios_present;
116 
117 struct pcibios_pir_header pcibios_pir_header;
118 struct pcibios_intr_routing *pcibios_pir_table;
119 int pcibios_pir_table_nentries;
120 int pcibios_flags = 0;
121 
122 struct bios32_entry pcibios_entry;
123 struct bios32_entry_info pcibios_entry_info;
124 
125 struct pcibios_intr_routing *pcibios_pir_init __P((struct pcibios_softc *));
126 
127 int	pcibios_get_status __P((struct pcibios_softc *,
128 	    u_int32_t *, u_int32_t *, u_int32_t *,
129 	    u_int32_t *, u_int32_t *, u_int32_t *, u_int32_t *));
130 int	pcibios_get_intr_routing __P((struct pcibios_softc *,
131 	    struct pcibios_intr_routing *, int *, u_int16_t *));
132 
133 int	pcibios_return_code __P((struct pcibios_softc *, u_int16_t, const char *));
134 
135 void	pcibios_print_exclirq __P((struct pcibios_softc *));
136 void	pcibios_print_pir_table __P((void));
137 
138 #define	PCI_IRQ_TABLE_START	0xf0000
139 #define	PCI_IRQ_TABLE_END	0xfffff
140 
141 struct cfdriver pcibios_cd = {
142 	NULL, "pcibios", DV_DULL
143 };
144 
145 int pcibiosprobe __P((struct device *, void *, void *));
146 void pcibiosattach __P((struct device *, struct device *, void *));
147 
148 struct cfattach pcibios_ca = {
149 	sizeof(struct pcibios_softc), pcibiosprobe, pcibiosattach
150 };
151 
152 int
153 pcibiosprobe(parent, match, aux)
154 	struct device *parent;
155 	void *match, *aux;
156 {
157 	struct bios_attach_args *ba = aux;
158 	u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2, maxbus;
159 	int rv;
160 
161 	if (strcmp(ba->bios_dev, "pcibios"))
162 		return 0;
163 
164 	rv = bios32_service(PCIBIOS_SIGNATURE, &pcibios_entry,
165 		&pcibios_entry_info);
166 
167 	PCIBIOS_PRINTV(("pcibiosprobe: 0x%lx:0x%lx at 0x%lx[0x%lx]\n",
168 	    pcibios_entry.segment, pcibios_entry.offset,
169 	    pcibios_entry_info.bei_base, pcibios_entry_info.bei_size));
170 
171 	return rv &&
172 	    pcibios_get_status(NULL, &rev_maj, &rev_min, &mech1, &mech2,
173 	        &scmech1, &scmech2, &maxbus) == PCIBIOS_SUCCESS;
174 }
175 
176 void
177 pcibiosattach(parent, self, aux)
178 	struct device *parent, *self;
179 	void *aux;
180 {
181 	struct pcibios_softc *sc = (struct pcibios_softc *)self;
182 	u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2;
183 
184 	pcibios_flags = sc->sc_dev.dv_cfdata->cf_flags;
185 
186 	pcibios_get_status((struct pcibios_softc *)self, &rev_maj,
187 	    &rev_min, &mech1, &mech2,
188 	    &scmech1, &scmech2, &sc->max_bus);
189 
190 	printf(": rev. %d.%d @ 0x%lx/0x%lx\n",
191 	    rev_maj, rev_min >> 4, pcibios_entry_info.bei_base,
192 	    pcibios_entry_info.bei_size);
193 
194 	PCIBIOS_PRINTV(("%s: config mechanism %s%s, special cycles %s%s, "
195 	    "last bus %d\n", sc->sc_dev.dv_xname,
196 	    mech1 ? "[1]" : "[x]", mech2 ? "[2]" : "[x]",
197 	    scmech1 ? "[1]" : "[x]", scmech2 ? "[2]" : "[x]", sc->max_bus));
198 
199 	/*
200 	 * The PCI BIOS tells us the config mechanism; fill it in now
201 	 * so that pci_mode_detect() doesn't have to look for it.
202 	 */
203 	pci_mode = mech1 ? 1 : 2;
204 
205 	pcibios_present = 1;
206 
207 	/*
208 	 * Find the PCI IRQ Routing table.
209 	 */
210 
211 	if (!(pcibios_flags & PCIBIOS_INTR_FIXUP) &&
212 	    pcibios_pir_init((struct pcibios_softc *)self) != NULL) {
213 		int rv;
214 
215 		/*
216 		 * Fixup interrupt routing.
217 		 */
218 		rv = pci_intr_fixup(sc, NULL, I386_BUS_SPACE_IO);
219 		switch (rv) {
220 		case -1:
221 			/* Non-fatal error. */
222 			printf("%s: Warning, unable to fix up PCI interrupt "
223 			    "routing\n", sc->sc_dev.dv_xname);
224 			break;
225 
226 		case 1:
227 			/* Fatal error. */
228 			printf("%s: interrupt fixup failed\n", sc->sc_dev.dv_xname);
229 			return;
230 		}
231 
232 		/*
233 		 * XXX Clear `pciirq' from the ISA interrupt allocation
234 		 * XXX mask.
235 		 */
236 	}
237 
238 	if (!(pcibios_flags & PCIBIOS_BUS_FIXUP)) {
239 		sc->max_bus = pci_bus_fixup(NULL, 0);
240 		printf("%s: PCI bus #%d is the last bus\n",
241 		    sc->sc_dev.dv_xname, sc->max_bus);
242 	}
243 
244 	if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP))
245 		pci_addr_fixup(sc, NULL, sc->max_bus);
246 }
247 
248 struct pcibios_intr_routing *
249 pcibios_pir_init(sc)
250 	struct pcibios_softc *sc;
251 {
252 	paddr_t pa;
253 
254 	pcibios_pir_table = NULL;
255 	for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) {
256 		u_int8_t *p, cksum;
257 		struct pcibios_pir_header *pirh;
258 		int i;
259 
260 		pirh = (struct pcibios_pir_header *)p = ISA_HOLE_VADDR(pa);
261 		if (pirh->signature != BIOS32_MAKESIG('$', 'P', 'I', 'R'))
262 			continue;
263 
264 		cksum = 0;
265 		for (i = 0; i < pirh->tablesize; i++)
266 			cksum += p[i];
267 
268 		printf("%s: PCI IRQ Routing Table rev. %d.%d @ 0x%lx/%d "
269 		    "(%d entries)\n", sc->sc_dev.dv_xname,
270 		    pirh->version >> 8, pirh->version & 0xff, pa,
271 		    pirh->tablesize, (pirh->tablesize - 32) / 16);
272 
273 		if (cksum != 0) {
274 			printf("%s: bad IRQ table checksum\n",
275 			    sc->sc_dev.dv_xname);
276 			continue;
277 		}
278 
279 		if (pirh->tablesize < 32 || (pirh->tablesize % 16) != 0) {
280 			printf("%s: bad IRQ table size\n", sc->sc_dev.dv_xname);
281 			continue;
282 		}
283 
284 		if (pirh->version != 0x0100) {
285 			printf("%s: unsupported IRQ table version\n",
286 			    sc->sc_dev.dv_xname);
287 			continue;
288 		}
289 
290 		/*
291 		 * We can handle this table!  Make a copy of it.
292 		 */
293 		pcibios_pir_header = *pirh;
294 		pcibios_pir_table =
295 		    malloc(pirh->tablesize - 32, M_DEVBUF, M_NOWAIT);
296 		if (pcibios_pir_table == NULL) {
297 			printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname);
298 			return NULL;
299 		}
300 		bcopy(p + 32, pcibios_pir_table, pirh->tablesize - 32);
301 		pcibios_pir_table_nentries = (pirh->tablesize - 32) / 16;
302 
303 	}
304 
305 	/*
306 	 * If there was no PIR table found, try using the PCI BIOS
307 	 * Get Interrupt Routing call.
308 	 *
309 	 * XXX The interface to this call sucks; just allocate enough
310 	 * XXX room for 32 entries.
311 	 */
312 	if (pcibios_pir_table == NULL) {
313 
314 		pcibios_pir_table_nentries = 32;
315 		pcibios_pir_table = malloc(pcibios_pir_table_nentries *
316 		    sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT);
317 		if (pcibios_pir_table == NULL) {
318 			printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname);
319 			return NULL;
320 		}
321 		if (pcibios_get_intr_routing(sc, pcibios_pir_table,
322 		    &pcibios_pir_table_nentries,
323 		    &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) {
324 			printf("%s: PCI IRQ Routing information unavailable.\n",
325 			    sc->sc_dev.dv_xname);
326 			free(pcibios_pir_table, M_DEVBUF);
327 			pcibios_pir_table = NULL;
328 			pcibios_pir_table_nentries = 0;
329 			return NULL;
330 		}
331 		printf("%s: PCI BIOS has %d Interrupt Routing table entries\n",
332 		    sc->sc_dev.dv_xname, pcibios_pir_table_nentries);
333 	}
334 
335 	pcibios_print_exclirq(sc);
336 	if (pcibios_flags & PCIBIOS_INTRDEBUG)
337 		pcibios_print_pir_table();
338 	return pcibios_pir_table;
339 }
340 
341 int
342 pcibios_get_status(sc, rev_maj, rev_min, mech1, mech2, scmech1, scmech2, maxbus)
343 	struct pcibios_softc *sc;
344 	u_int32_t *rev_maj, *rev_min, *mech1, *mech2, *scmech1, *scmech2,
345 	    *maxbus;
346 {
347 	u_int32_t ax, bx, cx, edx;
348 	int rv;
349 
350 	__asm __volatile("pushl	%%es\n\t"
351 			 "pushl	%%ds\n\t"
352 			 "movw	4(%%edi), %%ecx\n\t"
353 			 "movl	%%ecx, %%ds\n\t"
354 			 "lcall	%%cs:(%%edi)\n\t"
355 			 "pop	%%ds\n\t"
356 			 "pop	%%es\n\t"
357 			 "jc	1f\n\t"
358 			 "xor	%%ah, %%ah\n"
359 		    "1:"
360 		: "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx)
361 		: "0" (0xb101), "D" (&pcibios_entry)
362 		: "cc", "memory");
363 
364 	rv = pcibios_return_code(sc, ax, "pcibios_get_status");
365 	if (rv != PCIBIOS_SUCCESS)
366 		return (rv);
367 
368 	if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' '))
369 		return (PCIBIOS_SERVICE_NOT_PRESENT);	/* XXX */
370 
371 	/*
372 	 * Fill in the various pieces if info we're looking for.
373 	 */
374 	*mech1 = ax & 1;
375 	*mech2 = ax & (1 << 1);
376 	*scmech1 = ax & (1 << 4);
377 	*scmech2 = ax & (1 << 5);
378 	*rev_maj = (bx >> 8) & 0xff;
379 	*rev_min = bx & 0xff;
380 	*maxbus = cx & 0xff;
381 
382 	return (PCIBIOS_SUCCESS);
383 }
384 
385 int
386 pcibios_get_intr_routing(sc, table, nentries, exclirq)
387 	struct pcibios_softc *sc;
388 	struct pcibios_intr_routing *table;
389 	int *nentries;
390 	u_int16_t *exclirq;
391 {
392 	u_int32_t ax, bx;
393 	int rv;
394 	struct {
395 		u_int16_t size;
396 		u_int32_t offset;
397 		u_int16_t segment;
398 	} __attribute__((__packed__)) args;
399 
400 	args.size = *nentries * sizeof(*table);
401 	args.offset = (u_int32_t)table;
402 	args.segment = GSEL(GDATA_SEL, SEL_KPL);
403 
404 	memset(table, 0, args.size);
405 
406 	__asm __volatile("pushl	%%es\n\t"
407 			 "pushl	%%ds\n\t"
408 			 "movw	4(%%esi), %%ecx\n\t"
409 			 "movl	%%ecx, %%ds\n\t"
410 			 "lcall	%%cs:(%%esi)\n\t"
411 			 "popl	%%ds\n\t"
412 			 "popl	%%es\n\t"
413 			 "jc	1f\n\t"
414 			 "xor	%%ah, %%ah\n"
415 		    "1:\n"
416 		: "=a" (ax), "=b" (bx)
417 		: "0" (0xb10e), "1" (0), "D" (&args), "S" (&pcibios_entry)
418 		: "%ecx", "%edx", "cc", "memory");
419 
420 	rv = pcibios_return_code(sc, ax, "pcibios_get_intr_routing");
421 	if (rv != PCIBIOS_SUCCESS)
422 		return (rv);
423 
424 	*nentries = args.size / sizeof(*table);
425 	*exclirq |= bx;
426 
427 	return (PCIBIOS_SUCCESS);
428 }
429 
430 int
431 pcibios_return_code(sc, ax, func)
432 	struct pcibios_softc *sc;
433 	u_int16_t ax;
434 	const char *func;
435 {
436 	const char *errstr;
437 	int rv = ax >> 8;
438 	char *nam;
439 
440 	if (sc)
441 		nam = sc->sc_dev.dv_xname;
442 	else
443 		nam = "pcibios0";
444 
445 	switch (rv) {
446 	case PCIBIOS_SUCCESS:
447 		return (PCIBIOS_SUCCESS);
448 
449 	case PCIBIOS_SERVICE_NOT_PRESENT:
450 		errstr = "service not present";
451 		break;
452 
453 	case PCIBIOS_FUNCTION_NOT_SUPPORTED:
454 		errstr = "function not supported";
455 		break;
456 
457 	case PCIBIOS_BAD_VENDOR_ID:
458 		errstr = "bad vendor ID";
459 		break;
460 
461 	case PCIBIOS_DEVICE_NOT_FOUND:
462 		errstr = "device not found";
463 		break;
464 
465 	case PCIBIOS_BAD_REGISTER_NUMBER:
466 		errstr = "bad register number";
467 		break;
468 
469 	case PCIBIOS_SET_FAILED:
470 		errstr = "set failed";
471 		break;
472 
473 	case PCIBIOS_BUFFER_TOO_SMALL:
474 		errstr = "buffer too small";
475 		break;
476 
477 	default:
478 		printf("%s: %s - unknown return code 0x%x\n",
479 		    nam, func, rv);
480 		return (rv);
481 	}
482 
483 	printf("%s: %s - %s\n", nam, func, errstr);
484 	return (rv);
485 }
486 
487 void
488 pcibios_print_exclirq(sc)
489 	struct pcibios_softc *sc;
490 {
491 	int i;
492 
493 	if (pcibios_pir_header.exclusive_irq) {
494 		printf("%s: PCI Exclusive IRQs:", sc->sc_dev.dv_xname);
495 		for (i = 0; i < 16; i++) {
496 			if (pcibios_pir_header.exclusive_irq & (1 << i))
497 				printf(" %d", i);
498 		}
499 		printf("\n");
500 	}
501 }
502 
503 void
504 pcibios_print_pir_table()
505 {
506 	int i, j;
507 
508 	for (i = 0; i < pcibios_pir_table_nentries; i++) {
509 		printf("PIR Entry %d:\n", i);
510 		printf("\tBus: %d  Device: %d\n",
511 		    pcibios_pir_table[i].bus,
512 		    PIR_DEVFUNC_DEVICE(pcibios_pir_table[i].device));
513 		for (j = 0; j < 4; j++) {
514 			printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n",
515 			    'A' + j,
516 			    pcibios_pir_table[i].linkmap[j].link,
517 			    pcibios_pir_table[i].linkmap[j].bitmap);
518 		}
519 	}
520 }
521 
522 void
523 pci_device_foreach(sc, pc, maxbus, func)
524 	struct pcibios_softc *sc;
525 	pci_chipset_tag_t pc;
526 	int maxbus;
527 	void (*func) __P((struct pcibios_softc *, pci_chipset_tag_t, pcitag_t));
528 {
529 	const struct pci_quirkdata *qd;
530 	int bus, device, function, maxdevs, nfuncs;
531 	pcireg_t id, bhlcr;
532 	pcitag_t tag;
533 
534 	for (bus = 0; bus <= maxbus; bus++) {
535 		maxdevs = pci_bus_maxdevs(pc, bus);
536 		for (device = 0; device < maxdevs; device++) {
537 			tag = pci_make_tag(pc, bus, device, 0);
538 			id = pci_conf_read(pc, tag, PCI_ID_REG);
539 
540 			/* Invalid vendor ID value? */
541 			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
542 				continue;
543 			/* XXX Not invalid, but we've done this ~forever. */
544 			if (PCI_VENDOR(id) == 0)
545 				continue;
546 
547 			qd = pci_lookup_quirkdata(PCI_VENDOR(id),
548 			    PCI_PRODUCT(id));
549 
550 			bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
551 			if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
552 			    (qd != NULL &&
553 			     (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
554 				nfuncs = 8;
555 			else
556 				nfuncs = 1;
557 
558 			for (function = 0; function < nfuncs; function++) {
559 				tag = pci_make_tag(pc, bus, device, function);
560 				id = pci_conf_read(pc, tag, PCI_ID_REG);
561 
562 				/* Invalid vendor ID value? */
563 				if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
564 					continue;
565 				/*
566 				 * XXX Not invalid, but we've done this
567 				 * ~forever.
568 				 */
569 				if (PCI_VENDOR(id) == 0)
570 					continue;
571 				(*func)(sc, pc, tag);
572 			}
573 		}
574 	}
575 }
576