xref: /freebsd/sys/i386/pci/pci_cfgreg.c (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
1 /*
2  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 
36 #include <pci/pcivar.h>
37 #include <pci/pcireg.h>
38 #include <i386/isa/pcibus.h>
39 #include <isa/isavar.h>
40 
41 #include <machine/segments.h>
42 #include <machine/pc/bios.h>
43 
44 static int cfgmech;
45 static int devmax;
46 static int usebios;
47 
48 static int	pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
49 static void	pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
50 static int	pcibios_cfgopen(void);
51 static int	pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
52 static void	pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
53 static int	pcireg_cfgopen(void);
54 
55 /* read configuration space register */
56 
57 int
58 pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
59 {
60 	return(usebios ?
61 	       pcibios_cfgread(cfg, reg, bytes) :
62 	       pcireg_cfgread(cfg, reg, bytes));
63 }
64 
65 /* write configuration space register */
66 
67 void
68 pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
69 {
70 	return(usebios ?
71 	       pcibios_cfgwrite(cfg, reg, data, bytes) :
72 	       pcireg_cfgwrite(cfg, reg, data, bytes));
73 }
74 
75 /* initialise access to PCI configuration space */
76 static int
77 pci_cfgopen(void)
78 {
79 	if (pcibios_cfgopen() != 0) {
80 		usebios = 1;
81 	} else if (pcireg_cfgopen() != 0) {
82 		usebios = 0;
83 	} else {
84 		return(0);
85 	}
86 	return(1);
87 }
88 
89 /* config space access using BIOS functions */
90 
91 static int
92 pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
93 {
94 	struct bios_regs args;
95 	u_int mask;
96 
97 	switch(bytes) {
98 	case 1:
99 		args.eax = PCIBIOS_READ_CONFIG_BYTE;
100 		mask = 0xff;
101 		break;
102 	case 2:
103 		args.eax = PCIBIOS_READ_CONFIG_WORD;
104 		mask = 0xffff;
105 		break;
106 	case 4:
107 		args.eax = PCIBIOS_READ_CONFIG_DWORD;
108 		mask = 0xffffffff;
109 		break;
110 	default:
111 		return(-1);
112 	}
113 	args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
114 	args.edi = reg;
115 	bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
116 	/* check call results? */
117 	return(args.ecx & mask);
118 }
119 
120 static void
121 pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
122 {
123 	struct bios_regs args;
124 
125 	switch(bytes) {
126 	case 1:
127 		args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
128 		break;
129 	case 2:
130 		args.eax = PCIBIOS_WRITE_CONFIG_WORD;
131 		break;
132 	case 4:
133 		args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
134 		break;
135 	default:
136 		return;
137 	}
138 	args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
139 	args.ecx = data;
140 	args.edi = reg;
141 	bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
142 }
143 
144 /* determine whether there is a PCI BIOS present */
145 
146 static int
147 pcibios_cfgopen(void)
148 {
149 	/* check for a found entrypoint */
150 	return(PCIbios.entry != 0);
151 }
152 
153 /* configuration space access using direct register operations */
154 
155 /* enable configuration space accesses and return data port address */
156 
157 static int
158 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
159 {
160 	int dataport = 0;
161 
162 	if (bus <= PCI_BUSMAX
163 	    && slot < devmax
164 	    && func <= PCI_FUNCMAX
165 	    && reg <= PCI_REGMAX
166 	    && bytes != 3
167 	    && (unsigned) bytes <= 4
168 	    && (reg & (bytes -1)) == 0) {
169 		switch (cfgmech) {
170 		case 1:
171 			outl(CONF1_ADDR_PORT, (1 << 31)
172 			     | (bus << 16) | (slot << 11)
173 			     | (func << 8) | (reg & ~0x03));
174 			dataport = CONF1_DATA_PORT + (reg & 0x03);
175 			break;
176 		case 2:
177 			outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
178 			outb(CONF2_FORWARD_PORT, bus);
179 			dataport = 0xc000 | (slot << 8) | reg;
180 			break;
181 		}
182 	}
183 	return (dataport);
184 }
185 
186 /* disable configuration space accesses */
187 
188 static void
189 pci_cfgdisable(void)
190 {
191 	switch (cfgmech) {
192 	case 1:
193 		outl(CONF1_ADDR_PORT, 0);
194 		break;
195 	case 2:
196 		outb(CONF2_ENABLE_PORT, 0);
197 		outb(CONF2_FORWARD_PORT, 0);
198 		break;
199 	}
200 }
201 
202 static int
203 pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
204 {
205 	int data = -1;
206 	int port;
207 
208 	port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
209 
210 	if (port != 0) {
211 		switch (bytes) {
212 		case 1:
213 			data = inb(port);
214 			break;
215 		case 2:
216 			data = inw(port);
217 			break;
218 		case 4:
219 			data = inl(port);
220 			break;
221 		}
222 		pci_cfgdisable();
223 	}
224 	return (data);
225 }
226 
227 static void
228 pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
229 {
230 	int port;
231 
232 	port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
233 	if (port != 0) {
234 		switch (bytes) {
235 		case 1:
236 			outb(port, data);
237 			break;
238 		case 2:
239 			outw(port, data);
240 			break;
241 		case 4:
242 			outl(port, data);
243 			break;
244 		}
245 		pci_cfgdisable();
246 	}
247 }
248 
249 /* check whether the configuration mechanism has been correct identified */
250 
251 static int
252 pci_cfgcheck(int maxdev)
253 {
254 	u_char device;
255 
256 	if (bootverbose)
257 		printf("pci_cfgcheck:\tdevice ");
258 
259 	for (device = 0; device < maxdev; device++) {
260 		unsigned id, class, header;
261 		if (bootverbose)
262 			printf("%d ", device);
263 
264 		id = inl(pci_cfgenable(0, device, 0, 0, 4));
265 		if (id == 0 || id == -1)
266 			continue;
267 
268 		class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
269 		if (bootverbose)
270 			printf("[class=%06x] ", class);
271 		if (class == 0 || (class & 0xf870ff) != 0)
272 			continue;
273 
274 		header = inb(pci_cfgenable(0, device, 0, 14, 1));
275 		if (bootverbose)
276 			printf("[hdr=%02x] ", header);
277 		if ((header & 0x7e) != 0)
278 			continue;
279 
280 		if (bootverbose)
281 			printf("is there (id=%08x)\n", id);
282 
283 		pci_cfgdisable();
284 		return (1);
285 	}
286 	if (bootverbose)
287 		printf("-- nothing found\n");
288 
289 	pci_cfgdisable();
290 	return (0);
291 }
292 
293 static int
294 pcireg_cfgopen(void)
295 {
296 	unsigned long mode1res,oldval1;
297 	unsigned char mode2res,oldval2;
298 
299 	oldval1 = inl(CONF1_ADDR_PORT);
300 
301 	if (bootverbose) {
302 		printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
303 		       oldval1);
304 	}
305 
306 	if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
307 
308 		cfgmech = 1;
309 		devmax = 32;
310 
311 		outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
312 		outb(CONF1_ADDR_PORT +3, 0);
313 		mode1res = inl(CONF1_ADDR_PORT);
314 		outl(CONF1_ADDR_PORT, oldval1);
315 
316 		if (bootverbose)
317 			printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
318 			       mode1res, CONF1_ENABLE_CHK);
319 
320 		if (mode1res) {
321 			if (pci_cfgcheck(32))
322 				return (cfgmech);
323 		}
324 
325 		outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
326 		mode1res = inl(CONF1_ADDR_PORT);
327 		outl(CONF1_ADDR_PORT, oldval1);
328 
329 		if (bootverbose)
330 			printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
331 			       mode1res, CONF1_ENABLE_CHK1);
332 
333 		if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
334 			if (pci_cfgcheck(32))
335 				return (cfgmech);
336 		}
337 	}
338 
339 	oldval2 = inb(CONF2_ENABLE_PORT);
340 
341 	if (bootverbose) {
342 		printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
343 		       oldval2);
344 	}
345 
346 	if ((oldval2 & 0xf0) == 0) {
347 
348 		cfgmech = 2;
349 		devmax = 16;
350 
351 		outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
352 		mode2res = inb(CONF2_ENABLE_PORT);
353 		outb(CONF2_ENABLE_PORT, oldval2);
354 
355 		if (bootverbose)
356 			printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
357 			       mode2res, CONF2_ENABLE_CHK);
358 
359 		if (mode2res == CONF2_ENABLE_RES) {
360 			if (bootverbose)
361 				printf("pci_open(2a):\tnow trying mechanism 2\n");
362 
363 			if (pci_cfgcheck(16))
364 				return (cfgmech);
365 		}
366 	}
367 
368 	cfgmech = 0;
369 	devmax = 0;
370 	return (cfgmech);
371 }
372 
373 static devclass_t	pcib_devclass;
374 
375 static const char *
376 nexus_pcib_is_host_bridge(pcicfgregs *cfg,
377 			  u_int32_t id, u_int8_t class, u_int8_t subclass,
378 			  u_int8_t *busnum)
379 {
380 	const char *s = NULL;
381 	static u_int8_t pxb[4];	/* hack for 450nx */
382 
383 	*busnum = 0;
384 
385 	switch (id) {
386 	case 0x12258086:
387 		s = "Intel 824?? host to PCI bridge";
388 		/* XXX This is a guess */
389 		/* *busnum = pci_cfgread(cfg, 0x41, 1); */
390 		*busnum = cfg->bus;
391 		break;
392 	case 0x71208086:
393 		s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
394 		break;
395 	case 0x71228086:
396 		s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge";
397 		break;
398 	case 0x71248086:
399 		s = "Intel 82810E (i810E GMCH) Host To Hub bridge";
400 		break;
401 	case 0x71808086:
402 		s = "Intel 82443LX (440 LX) host to PCI bridge";
403 		break;
404 	case 0x71908086:
405 		s = "Intel 82443BX (440 BX) host to PCI bridge";
406 		break;
407 	case 0x71928086:
408 		s = "Intel 82443BX host to PCI bridge (AGP disabled)";
409 		break;
410 	case 0x71948086:
411 		s = "Intel 82443MX host to PCI bridge";
412 		break;
413 	case 0x71a08086:
414 		s = "Intel 82443GX host to PCI bridge";
415 		break;
416 	case 0x71a18086:
417 		s = "Intel 82443GX host to AGP bridge";
418 		break;
419 	case 0x71a28086:
420 		s = "Intel 82443GX host to PCI bridge (AGP disabled)";
421 		break;
422 	case 0x84c48086:
423 		s = "Intel 82454KX/GX (Orion) host to PCI bridge";
424 		*busnum = pci_cfgread(cfg, 0x4a, 1);
425 		break;
426 	case 0x84ca8086:
427 		/*
428 		 * For the 450nx chipset, there is a whole bundle of
429 		 * things pretending to be host bridges. The MIOC will
430 		 * be seen first and isn't really a pci bridge (the
431 		 * actual busses are attached to the PXB's). We need to
432 		 * read the registers of the MIOC to figure out the
433 		 * bus numbers for the PXB channels.
434 		 *
435 		 * Since the MIOC doesn't have a pci bus attached, we
436 		 * pretend it wasn't there.
437 		 */
438 		pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
439 		pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1;	/* SUBA[0]+1 */
440 		pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
441 		pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1;	/* SUBA[1]+1 */
442 		return NULL;
443 	case 0x84cb8086:
444 		switch (cfg->slot) {
445 		case 0x12:
446 			s = "Intel 82454NX PXB#0, Bus#A";
447 			*busnum = pxb[0];
448 			break;
449 		case 0x13:
450 			s = "Intel 82454NX PXB#0, Bus#B";
451 			*busnum = pxb[1];
452 			break;
453 		case 0x14:
454 			s = "Intel 82454NX PXB#1, Bus#A";
455 			*busnum = pxb[2];
456 			break;
457 		case 0x15:
458 			s = "Intel 82454NX PXB#1, Bus#B";
459 			*busnum = pxb[3];
460 			break;
461 		}
462 		break;
463 
464 		/* AMD -- vendor 0x1022 */
465 	case 0x70061022:
466 		s = "AMD-751 host to PCI bridge";
467 		break;
468 
469 		/* SiS -- vendor 0x1039 */
470 	case 0x04961039:
471 		s = "SiS 85c496";
472 		break;
473 	case 0x04061039:
474 		s = "SiS 85c501";
475 		break;
476 	case 0x06011039:
477 		s = "SiS 85c601";
478 		break;
479 	case 0x55911039:
480 		s = "SiS 5591 host to PCI bridge";
481 		break;
482 	case 0x00011039:
483 		s = "SiS 5591 host to AGP bridge";
484 		break;
485 
486 		/* VLSI -- vendor 0x1004 */
487 	case 0x00051004:
488 		s = "VLSI 82C592 Host to PCI bridge";
489 		break;
490 
491 		/* XXX Here is MVP3, I got the datasheet but NO M/B to test it  */
492 		/* totally. Please let me know if anything wrong.            -F */
493 		/* XXX need info on the MVP3 -- any takers? */
494 	case 0x05981106:
495 		s = "VIA 82C598MVP (Apollo MVP3) host bridge";
496 		break;
497 
498 		/* AcerLabs -- vendor 0x10b9 */
499 		/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
500 		/* id is '10b9" but the register always shows "10b9". -Foxfair  */
501 	case 0x154110b9:
502 		s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
503 		break;
504 
505 		/* OPTi -- vendor 0x1045 */
506 	case 0xc7011045:
507 		s = "OPTi 82C700 host to PCI bridge";
508 		break;
509 	case 0xc8221045:
510 		s = "OPTi 82C822 host to PCI Bridge";
511 		break;
512 
513 		/* RCC -- vendor 0x1166 */
514 	case 0x00051166:
515 		s = "RCC HE host to PCI bridge";
516 		*busnum = pci_cfgread(cfg, 0x44, 1);
517 		break;
518 
519 	case 0x00061166:
520 		/* FALLTHROUGH */
521 	case 0x00081166:
522 		s = "RCC host to PCI bridge";
523 		*busnum = pci_cfgread(cfg, 0x44, 1);
524 		break;
525 
526 	case 0x00091166:
527 		s = "RCC LE host to PCI bridge";
528 		*busnum = pci_cfgread(cfg, 0x44, 1);
529 		break;
530 
531 		/* Integrated Micro Solutions -- vendor 0x10e0 */
532 	case 0x884910e0:
533 		s = "Integrated Micro Solutions VL Bridge";
534 		break;
535 
536 	default:
537 		if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
538 			s = "Host to PCI bridge";
539 		break;
540 	}
541 
542 	return s;
543 }
544 
545 /*
546  * Scan the first pci bus for host-pci bridges and add pcib instances
547  * to the nexus for each bridge.
548  */
549 static void
550 nexus_pcib_identify(driver_t *driver, device_t parent)
551 {
552 	pcicfgregs probe;
553 	u_int8_t  hdrtype;
554 	int found = 0;
555 	int pcifunchigh;
556 	int found824xx = 0;
557 
558 	if (pci_cfgopen() == 0)
559 		return;
560 	probe.hose = 0;
561 	probe.bus = 0;
562  retry:
563 	for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
564 		probe.func = 0;
565 		hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
566 		if (hdrtype & PCIM_MFDEV)
567 			pcifunchigh = 7;
568 		else
569 			pcifunchigh = 0;
570 		for (probe.func = 0;
571 		     probe.func <= pcifunchigh;
572 		     probe.func++) {
573 			/*
574 			 * Read the IDs and class from the device.
575 			 */
576 			u_int32_t id;
577 			u_int8_t class, subclass, busnum;
578 			device_t child;
579 			const char *s;
580 
581 			id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
582 			if (id == -1)
583 				continue;
584 			class = pci_cfgread(&probe, PCIR_CLASS, 1);
585 			subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
586 
587 			s = nexus_pcib_is_host_bridge(&probe, id,
588 						      class, subclass,
589 						      &busnum);
590 			if (s) {
591 				/*
592 				 * Add at priority 100 to make sure we
593 				 * go after any motherboard resources
594 				 */
595 				child = BUS_ADD_CHILD(parent, 100,
596 						      "pcib", busnum);
597 				device_set_desc(child, s);
598 				found = 1;
599 				if (id == 0x12258086)
600 					found824xx = 1;
601 			}
602 		}
603 	}
604 	if (found824xx && probe.bus == 0) {
605 		probe.bus++;
606 		goto retry;
607 	}
608 
609 	/*
610 	 * Make sure we add at least one bridge since some old
611 	 * hardware doesn't actually have a host-pci bridge device.
612 	 * Note that pci_cfgopen() thinks we have PCI devices..
613 	 */
614 	if (!found) {
615 		if (bootverbose)
616 			printf(
617 	"nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
618 		BUS_ADD_CHILD(parent, 100, "pcib", 0);
619 	}
620 }
621 
622 static int
623 nexus_pcib_probe(device_t dev)
624 {
625 	if (pci_cfgopen() != 0) {
626 		device_add_child(dev, "pci", device_get_unit(dev));
627 		return 0;
628 	}
629 	return ENXIO;
630 }
631 
632 static device_method_t nexus_pcib_methods[] = {
633 	/* Device interface */
634 	DEVMETHOD(device_identify,	nexus_pcib_identify),
635 	DEVMETHOD(device_probe,		nexus_pcib_probe),
636 	DEVMETHOD(device_attach,	bus_generic_attach),
637 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
638 	DEVMETHOD(device_suspend,	bus_generic_suspend),
639 	DEVMETHOD(device_resume,	bus_generic_resume),
640 
641 	/* Bus interface */
642 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
643 	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
644 	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
645 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
646 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
647 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
648 	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
649 
650 	{ 0, 0 }
651 };
652 
653 static driver_t nexus_pcib_driver = {
654 	"pcib",
655 	nexus_pcib_methods,
656 	1,
657 };
658 
659 DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);
660 
661 /*
662  * Install placeholder to claim the resources owned by the
663  * PCI bus interface.  This could be used to extract the
664  * config space registers in the extreme case where the PnP
665  * ID is available and the PCI BIOS isn't, but for now we just
666  * eat the PnP ID and do nothing else.
667  *
668  * XXX we should silence this probe, as it will generally confuse
669  * people.
670  */
671 static struct isa_pnp_id pcibus_pnp_ids[] = {
672 	{ 0x030ad041 /* PNP030A */, "PCI Bus" },
673 	{ 0 }
674 };
675 
676 static int
677 pcibus_pnp_probe(device_t dev)
678 {
679 	int result;
680 
681 	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0)
682 		device_quiet(dev);
683 	return(result);
684 }
685 
686 static int
687 pcibus_pnp_attach(device_t dev)
688 {
689 	return(0);
690 }
691 
692 static device_method_t pcibus_pnp_methods[] = {
693 	/* Device interface */
694 	DEVMETHOD(device_probe,		pcibus_pnp_probe),
695 	DEVMETHOD(device_attach,	pcibus_pnp_attach),
696 	DEVMETHOD(device_detach,	bus_generic_detach),
697 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
698 	DEVMETHOD(device_suspend,	bus_generic_suspend),
699 	DEVMETHOD(device_resume,	bus_generic_resume),
700 	{ 0, 0 }
701 };
702 
703 static driver_t pcibus_pnp_driver = {
704 	"pcibus_pnp",
705 	pcibus_pnp_methods,
706 	1,		/* no softc */
707 };
708 
709 static devclass_t pcibus_pnp_devclass;
710 
711 DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
712