xref: /freebsd/sys/x86/pci/pci_bus.c (revision 18250ec6c089c0c50cbd9fd87d78e03ff89916df)
11368987aSJohn Baldwin /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3ebf5747bSPedro F. Giffuni  *
41368987aSJohn Baldwin  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
51368987aSJohn Baldwin  * All rights reserved.
61368987aSJohn Baldwin  *
71368987aSJohn Baldwin  * Redistribution and use in source and binary forms, with or without
81368987aSJohn Baldwin  * modification, are permitted provided that the following conditions
91368987aSJohn Baldwin  * are met:
101368987aSJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
111368987aSJohn Baldwin  *    notice unmodified, this list of conditions, and the following
121368987aSJohn Baldwin  *    disclaimer.
131368987aSJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
141368987aSJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
151368987aSJohn Baldwin  *    documentation and/or other materials provided with the distribution.
161368987aSJohn Baldwin  *
171368987aSJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
181368987aSJohn Baldwin  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
191368987aSJohn Baldwin  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
201368987aSJohn Baldwin  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
211368987aSJohn Baldwin  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
221368987aSJohn Baldwin  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231368987aSJohn Baldwin  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241368987aSJohn Baldwin  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251368987aSJohn Baldwin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
261368987aSJohn Baldwin  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271368987aSJohn Baldwin  */
281368987aSJohn Baldwin 
291368987aSJohn Baldwin #include <sys/cdefs.h>
301368987aSJohn Baldwin #include "opt_cpu.h"
311368987aSJohn Baldwin 
321368987aSJohn Baldwin #include <sys/param.h>
331368987aSJohn Baldwin #include <sys/systm.h>
341368987aSJohn Baldwin #include <sys/bus.h>
351368987aSJohn Baldwin #include <sys/kernel.h>
361368987aSJohn Baldwin #include <sys/malloc.h>
371368987aSJohn Baldwin #include <sys/module.h>
381368987aSJohn Baldwin #include <sys/rman.h>
391368987aSJohn Baldwin #include <sys/sysctl.h>
401368987aSJohn Baldwin 
411368987aSJohn Baldwin #include <dev/pci/pcivar.h>
421368987aSJohn Baldwin #include <dev/pci/pcireg.h>
431368987aSJohn Baldwin #include <dev/pci/pcib_private.h>
441368987aSJohn Baldwin #include <isa/isavar.h>
451368987aSJohn Baldwin #ifdef CPU_ELAN
461368987aSJohn Baldwin #include <machine/md_var.h>
471368987aSJohn Baldwin #endif
48435803f3SJohn Baldwin #include <x86/legacyvar.h>
491368987aSJohn Baldwin #include <machine/pci_cfgreg.h>
501368987aSJohn Baldwin #include <machine/resource.h>
511368987aSJohn Baldwin 
521368987aSJohn Baldwin #include "pcib_if.h"
531368987aSJohn Baldwin 
541368987aSJohn Baldwin int
legacy_pcib_maxslots(device_t dev)551368987aSJohn Baldwin legacy_pcib_maxslots(device_t dev)
561368987aSJohn Baldwin {
571368987aSJohn Baldwin 	return 31;
581368987aSJohn Baldwin }
591368987aSJohn Baldwin 
601368987aSJohn Baldwin /* read configuration space register */
611368987aSJohn Baldwin 
621368987aSJohn Baldwin uint32_t
legacy_pcib_read_config(device_t dev,u_int bus,u_int slot,u_int func,u_int reg,int bytes)631368987aSJohn Baldwin legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
641368987aSJohn Baldwin 			u_int reg, int bytes)
651368987aSJohn Baldwin {
661587a9dbSJohn Baldwin 	return(pci_cfgregread(0, bus, slot, func, reg, bytes));
671368987aSJohn Baldwin }
681368987aSJohn Baldwin 
691368987aSJohn Baldwin /* write configuration space register */
701368987aSJohn Baldwin 
711368987aSJohn Baldwin void
legacy_pcib_write_config(device_t dev,u_int bus,u_int slot,u_int func,u_int reg,uint32_t data,int bytes)721368987aSJohn Baldwin legacy_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
731368987aSJohn Baldwin 			 u_int reg, uint32_t data, int bytes)
741368987aSJohn Baldwin {
751587a9dbSJohn Baldwin 	pci_cfgregwrite(0, bus, slot, func, reg, data, bytes);
761368987aSJohn Baldwin }
771368987aSJohn Baldwin 
781368987aSJohn Baldwin /* route interrupt */
791368987aSJohn Baldwin 
801368987aSJohn Baldwin static int
legacy_pcib_route_interrupt(device_t pcib,device_t dev,int pin)811368987aSJohn Baldwin legacy_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
821368987aSJohn Baldwin {
831368987aSJohn Baldwin 
841368987aSJohn Baldwin #ifdef __HAVE_PIR
851368987aSJohn Baldwin 	return (pci_pir_route_interrupt(pci_get_bus(dev), pci_get_slot(dev),
861368987aSJohn Baldwin 	    pci_get_function(dev), pin));
871368987aSJohn Baldwin #else
881368987aSJohn Baldwin 	/* No routing possible */
891368987aSJohn Baldwin 	return (PCI_INVALID_IRQ);
901368987aSJohn Baldwin #endif
911368987aSJohn Baldwin }
921368987aSJohn Baldwin 
931368987aSJohn Baldwin /* Pass MSI requests up to the nexus. */
941368987aSJohn Baldwin 
9584ca9aadSJohn Baldwin int
legacy_pcib_alloc_msi(device_t pcib,device_t dev,int count,int maxcount,int * irqs)961368987aSJohn Baldwin legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount,
971368987aSJohn Baldwin     int *irqs)
981368987aSJohn Baldwin {
991368987aSJohn Baldwin 	device_t bus;
1001368987aSJohn Baldwin 
1011368987aSJohn Baldwin 	bus = device_get_parent(pcib);
1021368987aSJohn Baldwin 	return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
1031368987aSJohn Baldwin 	    irqs));
1041368987aSJohn Baldwin }
1051368987aSJohn Baldwin 
10684ca9aadSJohn Baldwin int
legacy_pcib_alloc_msix(device_t pcib,device_t dev,int * irq)1071368987aSJohn Baldwin legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
1081368987aSJohn Baldwin {
1091368987aSJohn Baldwin 	device_t bus;
1101368987aSJohn Baldwin 
1111368987aSJohn Baldwin 	bus = device_get_parent(pcib);
1121368987aSJohn Baldwin 	return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
1131368987aSJohn Baldwin }
1141368987aSJohn Baldwin 
1150d95597cSJohn Baldwin int
legacy_pcib_map_msi(device_t pcib,device_t dev,int irq,uint64_t * addr,uint32_t * data)1161368987aSJohn Baldwin legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
1171368987aSJohn Baldwin     uint32_t *data)
1181368987aSJohn Baldwin {
1190d95597cSJohn Baldwin 	device_t bus, hostb;
1200d95597cSJohn Baldwin 	int error, func, slot;
1211368987aSJohn Baldwin 
1221368987aSJohn Baldwin 	bus = device_get_parent(pcib);
1230d95597cSJohn Baldwin 	error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
1240d95597cSJohn Baldwin 	if (error)
1250d95597cSJohn Baldwin 		return (error);
1260d95597cSJohn Baldwin 
1270d95597cSJohn Baldwin 	slot = legacy_get_pcislot(pcib);
1280d95597cSJohn Baldwin 	func = legacy_get_pcifunc(pcib);
1290d95597cSJohn Baldwin 	if (slot == -1 || func == -1)
1300d95597cSJohn Baldwin 		return (0);
1310d95597cSJohn Baldwin 	hostb = pci_find_bsf(0, slot, func);
1320d95597cSJohn Baldwin 	KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
1330d95597cSJohn Baldwin 	    slot, func));
1340d95597cSJohn Baldwin 	pci_ht_map_msi(hostb, *addr);
1350d95597cSJohn Baldwin 	return (0);
1361368987aSJohn Baldwin }
1371368987aSJohn Baldwin 
1381368987aSJohn Baldwin static const char *
legacy_pcib_is_host_bridge(int bus,int slot,int func,uint32_t id,uint8_t class,uint8_t subclass,uint8_t * busnum)1391368987aSJohn Baldwin legacy_pcib_is_host_bridge(int bus, int slot, int func,
1401368987aSJohn Baldwin 			  uint32_t id, uint8_t class, uint8_t subclass,
1411368987aSJohn Baldwin 			  uint8_t *busnum)
1421368987aSJohn Baldwin {
1431368987aSJohn Baldwin #ifdef __i386__
1441368987aSJohn Baldwin 	const char *s = NULL;
1451368987aSJohn Baldwin 	static uint8_t pxb[4];	/* hack for 450nx */
1461368987aSJohn Baldwin 
1471368987aSJohn Baldwin 	*busnum = 0;
1481368987aSJohn Baldwin 
1491368987aSJohn Baldwin 	switch (id) {
1501368987aSJohn Baldwin 	case 0x12258086:
1511368987aSJohn Baldwin 		s = "Intel 824?? host to PCI bridge";
1521368987aSJohn Baldwin 		/* XXX This is a guess */
1531368987aSJohn Baldwin 		/* *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x41, 1); */
1541368987aSJohn Baldwin 		*busnum = bus;
1551368987aSJohn Baldwin 		break;
1561368987aSJohn Baldwin 	case 0x71208086:
1571368987aSJohn Baldwin 		s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
1581368987aSJohn Baldwin 		break;
1591368987aSJohn Baldwin 	case 0x71228086:
1601368987aSJohn Baldwin 		s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge";
1611368987aSJohn Baldwin 		break;
1621368987aSJohn Baldwin 	case 0x71248086:
1631368987aSJohn Baldwin 		s = "Intel 82810E (i810E GMCH) Host To Hub bridge";
1641368987aSJohn Baldwin 		break;
1651368987aSJohn Baldwin 	case 0x11308086:
1661368987aSJohn Baldwin 		s = "Intel 82815 (i815 GMCH) Host To Hub bridge";
1671368987aSJohn Baldwin 		break;
1681368987aSJohn Baldwin 	case 0x71808086:
1691368987aSJohn Baldwin 		s = "Intel 82443LX (440 LX) host to PCI bridge";
1701368987aSJohn Baldwin 		break;
1711368987aSJohn Baldwin 	case 0x71908086:
1721368987aSJohn Baldwin 		s = "Intel 82443BX (440 BX) host to PCI bridge";
1731368987aSJohn Baldwin 		break;
1741368987aSJohn Baldwin 	case 0x71928086:
1751368987aSJohn Baldwin 		s = "Intel 82443BX host to PCI bridge (AGP disabled)";
1761368987aSJohn Baldwin 		break;
1771368987aSJohn Baldwin 	case 0x71948086:
1781368987aSJohn Baldwin 		s = "Intel 82443MX host to PCI bridge";
1791368987aSJohn Baldwin 		break;
1801368987aSJohn Baldwin 	case 0x71a08086:
1811368987aSJohn Baldwin 		s = "Intel 82443GX host to PCI bridge";
1821368987aSJohn Baldwin 		break;
1831368987aSJohn Baldwin 	case 0x71a18086:
1841368987aSJohn Baldwin 		s = "Intel 82443GX host to AGP bridge";
1851368987aSJohn Baldwin 		break;
1861368987aSJohn Baldwin 	case 0x71a28086:
1871368987aSJohn Baldwin 		s = "Intel 82443GX host to PCI bridge (AGP disabled)";
1881368987aSJohn Baldwin 		break;
1891368987aSJohn Baldwin 	case 0x84c48086:
1901368987aSJohn Baldwin 		s = "Intel 82454KX/GX (Orion) host to PCI bridge";
1911368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x4a, 1);
1921368987aSJohn Baldwin 		break;
1931368987aSJohn Baldwin 	case 0x84ca8086:
1941368987aSJohn Baldwin 		/*
1951368987aSJohn Baldwin 		 * For the 450nx chipset, there is a whole bundle of
1961368987aSJohn Baldwin 		 * things pretending to be host bridges. The MIOC will
1971368987aSJohn Baldwin 		 * be seen first and isn't really a pci bridge (the
198db4fcadfSConrad Meyer 		 * actual buses are attached to the PXB's). We need to
1991368987aSJohn Baldwin 		 * read the registers of the MIOC to figure out the
2001368987aSJohn Baldwin 		 * bus numbers for the PXB channels.
2011368987aSJohn Baldwin 		 *
2021368987aSJohn Baldwin 		 * Since the MIOC doesn't have a pci bus attached, we
2031368987aSJohn Baldwin 		 * pretend it wasn't there.
2041368987aSJohn Baldwin 		 */
2051368987aSJohn Baldwin 		pxb[0] = legacy_pcib_read_config(0, bus, slot, func,
2061368987aSJohn Baldwin 						0xd0, 1); /* BUSNO[0] */
2071368987aSJohn Baldwin 		pxb[1] = legacy_pcib_read_config(0, bus, slot, func,
2081368987aSJohn Baldwin 						0xd1, 1) + 1;	/* SUBA[0]+1 */
2091368987aSJohn Baldwin 		pxb[2] = legacy_pcib_read_config(0, bus, slot, func,
2101368987aSJohn Baldwin 						0xd3, 1); /* BUSNO[1] */
2111368987aSJohn Baldwin 		pxb[3] = legacy_pcib_read_config(0, bus, slot, func,
2121368987aSJohn Baldwin 						0xd4, 1) + 1;	/* SUBA[1]+1 */
2131368987aSJohn Baldwin 		return NULL;
2141368987aSJohn Baldwin 	case 0x84cb8086:
2151368987aSJohn Baldwin 		switch (slot) {
2161368987aSJohn Baldwin 		case 0x12:
2171368987aSJohn Baldwin 			s = "Intel 82454NX PXB#0, Bus#A";
2181368987aSJohn Baldwin 			*busnum = pxb[0];
2191368987aSJohn Baldwin 			break;
2201368987aSJohn Baldwin 		case 0x13:
2211368987aSJohn Baldwin 			s = "Intel 82454NX PXB#0, Bus#B";
2221368987aSJohn Baldwin 			*busnum = pxb[1];
2231368987aSJohn Baldwin 			break;
2241368987aSJohn Baldwin 		case 0x14:
2251368987aSJohn Baldwin 			s = "Intel 82454NX PXB#1, Bus#A";
2261368987aSJohn Baldwin 			*busnum = pxb[2];
2271368987aSJohn Baldwin 			break;
2281368987aSJohn Baldwin 		case 0x15:
2291368987aSJohn Baldwin 			s = "Intel 82454NX PXB#1, Bus#B";
2301368987aSJohn Baldwin 			*busnum = pxb[3];
2311368987aSJohn Baldwin 			break;
2321368987aSJohn Baldwin 		}
2331368987aSJohn Baldwin 		break;
2341368987aSJohn Baldwin 	case 0x1A308086:
2351368987aSJohn Baldwin 		s = "Intel 82845 Host to PCI bridge";
2361368987aSJohn Baldwin 		break;
2371368987aSJohn Baldwin 
2381368987aSJohn Baldwin 		/* AMD -- vendor 0x1022 */
2391368987aSJohn Baldwin 	case 0x30001022:
2401368987aSJohn Baldwin 		s = "AMD Elan SC520 host to PCI bridge";
2411368987aSJohn Baldwin #ifdef CPU_ELAN
2421368987aSJohn Baldwin 		init_AMD_Elan_sc520();
2431368987aSJohn Baldwin #else
2441368987aSJohn Baldwin 		printf(
2451368987aSJohn Baldwin "*** WARNING: missing CPU_ELAN -- timekeeping may be wrong\n");
2461368987aSJohn Baldwin #endif
2471368987aSJohn Baldwin 		break;
2481368987aSJohn Baldwin 	case 0x70061022:
2491368987aSJohn Baldwin 		s = "AMD-751 host to PCI bridge";
2501368987aSJohn Baldwin 		break;
2511368987aSJohn Baldwin 	case 0x700e1022:
2521368987aSJohn Baldwin 		s = "AMD-761 host to PCI bridge";
2531368987aSJohn Baldwin 		break;
2541368987aSJohn Baldwin 
2551368987aSJohn Baldwin 		/* SiS -- vendor 0x1039 */
2561368987aSJohn Baldwin 	case 0x04961039:
2571368987aSJohn Baldwin 		s = "SiS 85c496";
2581368987aSJohn Baldwin 		break;
2591368987aSJohn Baldwin 	case 0x04061039:
2601368987aSJohn Baldwin 		s = "SiS 85c501";
2611368987aSJohn Baldwin 		break;
2621368987aSJohn Baldwin 	case 0x06011039:
2631368987aSJohn Baldwin 		s = "SiS 85c601";
2641368987aSJohn Baldwin 		break;
2651368987aSJohn Baldwin 	case 0x55911039:
2661368987aSJohn Baldwin 		s = "SiS 5591 host to PCI bridge";
2671368987aSJohn Baldwin 		break;
2681368987aSJohn Baldwin 	case 0x00011039:
2691368987aSJohn Baldwin 		s = "SiS 5591 host to AGP bridge";
2701368987aSJohn Baldwin 		break;
2711368987aSJohn Baldwin 
2721368987aSJohn Baldwin 		/* VLSI -- vendor 0x1004 */
2731368987aSJohn Baldwin 	case 0x00051004:
2741368987aSJohn Baldwin 		s = "VLSI 82C592 Host to PCI bridge";
2751368987aSJohn Baldwin 		break;
2761368987aSJohn Baldwin 
2771368987aSJohn Baldwin 		/* XXX Here is MVP3, I got the datasheet but NO M/B to test it  */
2781368987aSJohn Baldwin 		/* totally. Please let me know if anything wrong.            -F */
2791368987aSJohn Baldwin 		/* XXX need info on the MVP3 -- any takers? */
2801368987aSJohn Baldwin 	case 0x05981106:
2811368987aSJohn Baldwin 		s = "VIA 82C598MVP (Apollo MVP3) host bridge";
2821368987aSJohn Baldwin 		break;
2831368987aSJohn Baldwin 
2841368987aSJohn Baldwin 		/* AcerLabs -- vendor 0x10b9 */
2851368987aSJohn Baldwin 		/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
2861368987aSJohn Baldwin 		/* id is '10b9" but the register always shows "10b9". -Foxfair  */
2871368987aSJohn Baldwin 	case 0x154110b9:
2881368987aSJohn Baldwin 		s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
2891368987aSJohn Baldwin 		break;
2901368987aSJohn Baldwin 
2911368987aSJohn Baldwin 		/* OPTi -- vendor 0x1045 */
2921368987aSJohn Baldwin 	case 0xc7011045:
2931368987aSJohn Baldwin 		s = "OPTi 82C700 host to PCI bridge";
2941368987aSJohn Baldwin 		break;
2951368987aSJohn Baldwin 	case 0xc8221045:
2961368987aSJohn Baldwin 		s = "OPTi 82C822 host to PCI Bridge";
2971368987aSJohn Baldwin 		break;
2981368987aSJohn Baldwin 
2991368987aSJohn Baldwin 		/* ServerWorks -- vendor 0x1166 */
3001368987aSJohn Baldwin 	case 0x00051166:
3011368987aSJohn Baldwin 		s = "ServerWorks NB6536 2.0HE host to PCI bridge";
3021368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1);
3031368987aSJohn Baldwin 		break;
3041368987aSJohn Baldwin 
3051368987aSJohn Baldwin 	case 0x00061166:
3061368987aSJohn Baldwin 		/* FALLTHROUGH */
3071368987aSJohn Baldwin 	case 0x00081166:
3081368987aSJohn Baldwin 		/* FALLTHROUGH */
3091368987aSJohn Baldwin 	case 0x02011166:
3101368987aSJohn Baldwin 		/* FALLTHROUGH */
3111368987aSJohn Baldwin 	case 0x010f1014: /* IBM re-badged ServerWorks chipset */
3121368987aSJohn Baldwin 		s = "ServerWorks host to PCI bridge";
3131368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1);
3141368987aSJohn Baldwin 		break;
3151368987aSJohn Baldwin 
3161368987aSJohn Baldwin 	case 0x00091166:
3171368987aSJohn Baldwin 		s = "ServerWorks NB6635 3.0LE host to PCI bridge";
3181368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1);
3191368987aSJohn Baldwin 		break;
3201368987aSJohn Baldwin 
3211368987aSJohn Baldwin 	case 0x00101166:
3221368987aSJohn Baldwin 		s = "ServerWorks CIOB30 host to PCI bridge";
3231368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1);
3241368987aSJohn Baldwin 		break;
3251368987aSJohn Baldwin 
3261368987aSJohn Baldwin 	case 0x00111166:
3271368987aSJohn Baldwin 		/* FALLTHROUGH */
3281368987aSJohn Baldwin 	case 0x03021014: /* IBM re-badged ServerWorks chipset */
3291368987aSJohn Baldwin 		s = "ServerWorks CMIC-HE host to PCI-X bridge";
3301368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1);
3311368987aSJohn Baldwin 		break;
3321368987aSJohn Baldwin 
3331368987aSJohn Baldwin 		/* XXX unknown chipset, but working */
3341368987aSJohn Baldwin 	case 0x00171166:
3351368987aSJohn Baldwin 		/* FALLTHROUGH */
3361368987aSJohn Baldwin 	case 0x01011166:
3371368987aSJohn Baldwin 	case 0x01101166:
3381368987aSJohn Baldwin 	case 0x02251166:
3391368987aSJohn Baldwin 		s = "ServerWorks host to PCI bridge(unknown chipset)";
3401368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1);
3411368987aSJohn Baldwin 		break;
3421368987aSJohn Baldwin 
3431368987aSJohn Baldwin 		/* Compaq/HP -- vendor 0x0e11 */
3441368987aSJohn Baldwin 	case 0x60100e11:
3451368987aSJohn Baldwin 		s = "Compaq/HP Model 6010 HotPlug PCI Bridge";
3461368987aSJohn Baldwin 		*busnum = legacy_pcib_read_config(0, bus, slot, func, 0xc8, 1);
3471368987aSJohn Baldwin 		break;
3481368987aSJohn Baldwin 
3491368987aSJohn Baldwin 		/* Integrated Micro Solutions -- vendor 0x10e0 */
3501368987aSJohn Baldwin 	case 0x884910e0:
3511368987aSJohn Baldwin 		s = "Integrated Micro Solutions VL Bridge";
3521368987aSJohn Baldwin 		break;
3531368987aSJohn Baldwin 
3541368987aSJohn Baldwin 	default:
3551368987aSJohn Baldwin 		if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
3561368987aSJohn Baldwin 			s = "Host to PCI bridge";
3571368987aSJohn Baldwin 		break;
3581368987aSJohn Baldwin 	}
3591368987aSJohn Baldwin 
3601368987aSJohn Baldwin 	return s;
3611368987aSJohn Baldwin #else
3621368987aSJohn Baldwin 	const char *s = NULL;
3631368987aSJohn Baldwin 
3641368987aSJohn Baldwin 	*busnum = 0;
3651368987aSJohn Baldwin 	if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
3661368987aSJohn Baldwin 		s = "Host to PCI bridge";
3671368987aSJohn Baldwin 	return s;
3681368987aSJohn Baldwin #endif
3691368987aSJohn Baldwin }
3701368987aSJohn Baldwin 
3711368987aSJohn Baldwin /*
3721368987aSJohn Baldwin  * Scan the first pci bus for host-pci bridges and add pcib instances
3731368987aSJohn Baldwin  * to the nexus for each bridge.
3741368987aSJohn Baldwin  */
3751368987aSJohn Baldwin static void
legacy_pcib_identify(driver_t * driver,device_t parent)3761368987aSJohn Baldwin legacy_pcib_identify(driver_t *driver, device_t parent)
3771368987aSJohn Baldwin {
3781368987aSJohn Baldwin 	int bus, slot, func;
3791368987aSJohn Baldwin 	uint8_t  hdrtype;
3801368987aSJohn Baldwin 	int found = 0;
3811368987aSJohn Baldwin 	int pcifunchigh;
3821368987aSJohn Baldwin 	int found824xx = 0;
3831368987aSJohn Baldwin 	int found_orion = 0;
3841368987aSJohn Baldwin 	device_t child;
3851368987aSJohn Baldwin 	devclass_t pci_devclass;
3861368987aSJohn Baldwin 
3871368987aSJohn Baldwin 	if (pci_cfgregopen() == 0)
3881368987aSJohn Baldwin 		return;
3891368987aSJohn Baldwin 	/*
3901368987aSJohn Baldwin 	 * Check to see if we haven't already had a PCI bus added
3911368987aSJohn Baldwin 	 * via some other means.  If we have, bail since otherwise
3921368987aSJohn Baldwin 	 * we're going to end up duplicating it.
3931368987aSJohn Baldwin 	 */
3941368987aSJohn Baldwin 	if ((pci_devclass = devclass_find("pci")) &&
3951368987aSJohn Baldwin 		devclass_get_device(pci_devclass, 0))
3961368987aSJohn Baldwin 		return;
3971368987aSJohn Baldwin 
3981368987aSJohn Baldwin 	bus = 0;
3991368987aSJohn Baldwin  retry:
4001368987aSJohn Baldwin 	for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
4011368987aSJohn Baldwin 		func = 0;
4021368987aSJohn Baldwin 		hdrtype = legacy_pcib_read_config(0, bus, slot, func,
4031368987aSJohn Baldwin 						 PCIR_HDRTYPE, 1);
4041368987aSJohn Baldwin 		/*
4051368987aSJohn Baldwin 		 * When enumerating bus devices, the standard says that
4061368987aSJohn Baldwin 		 * one should check the header type and ignore the slots whose
4071368987aSJohn Baldwin 		 * header types that the software doesn't know about.  We use
4081368987aSJohn Baldwin 		 * this to filter out devices.
4091368987aSJohn Baldwin 		 */
4101368987aSJohn Baldwin 		if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
4111368987aSJohn Baldwin 			continue;
4121368987aSJohn Baldwin 		if ((hdrtype & PCIM_MFDEV) &&
4131368987aSJohn Baldwin 		    (!found_orion || hdrtype != 0xff))
4141368987aSJohn Baldwin 			pcifunchigh = PCI_FUNCMAX;
4151368987aSJohn Baldwin 		else
4161368987aSJohn Baldwin 			pcifunchigh = 0;
4171368987aSJohn Baldwin 		for (func = 0; func <= pcifunchigh; func++) {
4181368987aSJohn Baldwin 			/*
4191368987aSJohn Baldwin 			 * Read the IDs and class from the device.
4201368987aSJohn Baldwin 			 */
4211368987aSJohn Baldwin 			uint32_t id;
4221368987aSJohn Baldwin 			uint8_t class, subclass, busnum;
4231368987aSJohn Baldwin 			const char *s;
4241368987aSJohn Baldwin 			device_t *devs;
4251368987aSJohn Baldwin 			int ndevs, i;
4261368987aSJohn Baldwin 
4271368987aSJohn Baldwin 			id = legacy_pcib_read_config(0, bus, slot, func,
4281368987aSJohn Baldwin 						    PCIR_DEVVENDOR, 4);
4291368987aSJohn Baldwin 			if (id == -1)
4301368987aSJohn Baldwin 				continue;
4311368987aSJohn Baldwin 			class = legacy_pcib_read_config(0, bus, slot, func,
4321368987aSJohn Baldwin 						       PCIR_CLASS, 1);
4331368987aSJohn Baldwin 			subclass = legacy_pcib_read_config(0, bus, slot, func,
4341368987aSJohn Baldwin 							  PCIR_SUBCLASS, 1);
4351368987aSJohn Baldwin 
4361368987aSJohn Baldwin 			s = legacy_pcib_is_host_bridge(bus, slot, func,
4371368987aSJohn Baldwin 						      id, class, subclass,
4381368987aSJohn Baldwin 						      &busnum);
4391368987aSJohn Baldwin 			if (s == NULL)
4401368987aSJohn Baldwin 				continue;
4411368987aSJohn Baldwin 
4421368987aSJohn Baldwin 			/*
4431368987aSJohn Baldwin 			 * Check to see if the physical bus has already
4441368987aSJohn Baldwin 			 * been seen.  Eg: hybrid 32 and 64 bit host
4451368987aSJohn Baldwin 			 * bridges to the same logical bus.
4461368987aSJohn Baldwin 			 */
4471368987aSJohn Baldwin 			if (device_get_children(parent, &devs, &ndevs) == 0) {
4481368987aSJohn Baldwin 				for (i = 0; s != NULL && i < ndevs; i++) {
4491368987aSJohn Baldwin 					if (strcmp(device_get_name(devs[i]),
4501368987aSJohn Baldwin 					    "pcib") != 0)
4511368987aSJohn Baldwin 						continue;
4521368987aSJohn Baldwin 					if (legacy_get_pcibus(devs[i]) == busnum)
4531368987aSJohn Baldwin 						s = NULL;
4541368987aSJohn Baldwin 				}
4551368987aSJohn Baldwin 				free(devs, M_TEMP);
4561368987aSJohn Baldwin 			}
4571368987aSJohn Baldwin 
4581368987aSJohn Baldwin 			if (s == NULL)
4591368987aSJohn Baldwin 				continue;
4601368987aSJohn Baldwin 			/*
4611368987aSJohn Baldwin 			 * Add at priority 100 to make sure we
4621368987aSJohn Baldwin 			 * go after any motherboard resources
4631368987aSJohn Baldwin 			 */
4641368987aSJohn Baldwin 			child = BUS_ADD_CHILD(parent, 100,
4651368987aSJohn Baldwin 					      "pcib", busnum);
4661368987aSJohn Baldwin 			device_set_desc(child, s);
4671368987aSJohn Baldwin 			legacy_set_pcibus(child, busnum);
4680d95597cSJohn Baldwin 			legacy_set_pcislot(child, slot);
4690d95597cSJohn Baldwin 			legacy_set_pcifunc(child, func);
4701368987aSJohn Baldwin 
4711368987aSJohn Baldwin 			found = 1;
4721368987aSJohn Baldwin 			if (id == 0x12258086)
4731368987aSJohn Baldwin 				found824xx = 1;
4741368987aSJohn Baldwin 			if (id == 0x84c48086)
4751368987aSJohn Baldwin 				found_orion = 1;
4761368987aSJohn Baldwin 		}
4771368987aSJohn Baldwin 	}
4781368987aSJohn Baldwin 	if (found824xx && bus == 0) {
4791368987aSJohn Baldwin 		bus++;
4801368987aSJohn Baldwin 		goto retry;
4811368987aSJohn Baldwin 	}
4821368987aSJohn Baldwin 
4831368987aSJohn Baldwin 	/*
4841368987aSJohn Baldwin 	 * Make sure we add at least one bridge since some old
4851368987aSJohn Baldwin 	 * hardware doesn't actually have a host-pci bridge device.
4861368987aSJohn Baldwin 	 * Note that pci_cfgregopen() thinks we have PCI devices..
4871368987aSJohn Baldwin 	 */
4881368987aSJohn Baldwin 	if (!found) {
4892297a163SColin Percival #ifndef NO_LEGACY_PCIB
4901368987aSJohn Baldwin 		if (bootverbose)
4911368987aSJohn Baldwin 			printf(
4921368987aSJohn Baldwin 	"legacy_pcib_identify: no bridge found, adding pcib0 anyway\n");
4931368987aSJohn Baldwin 		child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
4941368987aSJohn Baldwin 		legacy_set_pcibus(child, 0);
4952297a163SColin Percival #endif
4961368987aSJohn Baldwin 	}
4971368987aSJohn Baldwin }
4981368987aSJohn Baldwin 
4991368987aSJohn Baldwin static int
legacy_pcib_probe(device_t dev)5001368987aSJohn Baldwin legacy_pcib_probe(device_t dev)
5011368987aSJohn Baldwin {
5021368987aSJohn Baldwin 
5031368987aSJohn Baldwin 	if (pci_cfgregopen() == 0)
5041368987aSJohn Baldwin 		return ENXIO;
5051368987aSJohn Baldwin 	return -100;
5061368987aSJohn Baldwin }
5071368987aSJohn Baldwin 
5081368987aSJohn Baldwin static int
legacy_pcib_attach(device_t dev)5091368987aSJohn Baldwin legacy_pcib_attach(device_t dev)
5101368987aSJohn Baldwin {
5111368987aSJohn Baldwin #ifdef __HAVE_PIR
5121368987aSJohn Baldwin 	device_t pir;
5131368987aSJohn Baldwin 	int bus;
5141368987aSJohn Baldwin 
5151368987aSJohn Baldwin 	bus = pcib_get_bus(dev);
5161368987aSJohn Baldwin 	/*
5171368987aSJohn Baldwin 	 * Look for a PCI BIOS interrupt routing table as that will be
5181368987aSJohn Baldwin 	 * our method of routing interrupts if we have one.
5191368987aSJohn Baldwin 	 */
5201368987aSJohn Baldwin 	if (pci_pir_probe(bus, 0)) {
5211368987aSJohn Baldwin 		pir = BUS_ADD_CHILD(device_get_parent(dev), 0, "pir", 0);
5221368987aSJohn Baldwin 		if (pir != NULL)
5231368987aSJohn Baldwin 			device_probe_and_attach(pir);
5241368987aSJohn Baldwin 	}
5251368987aSJohn Baldwin #endif
5265b56413dSWarner Losh 	device_add_child(dev, "pci", DEVICE_UNIT_ANY);
527*18250ec6SJohn Baldwin 	bus_attach_children(dev);
528*18250ec6SJohn Baldwin 	return (0);
5291368987aSJohn Baldwin }
5301368987aSJohn Baldwin 
5311368987aSJohn Baldwin int
legacy_pcib_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)5321368987aSJohn Baldwin legacy_pcib_read_ivar(device_t dev, device_t child, int which,
5331368987aSJohn Baldwin     uintptr_t *result)
5341368987aSJohn Baldwin {
5351368987aSJohn Baldwin 
5361368987aSJohn Baldwin 	switch (which) {
5371368987aSJohn Baldwin 	case  PCIB_IVAR_DOMAIN:
5381368987aSJohn Baldwin 		*result = 0;
5391368987aSJohn Baldwin 		return 0;
5401368987aSJohn Baldwin 	case  PCIB_IVAR_BUS:
5411368987aSJohn Baldwin 		*result = legacy_get_pcibus(dev);
5421368987aSJohn Baldwin 		return 0;
5431368987aSJohn Baldwin 	}
5441368987aSJohn Baldwin 	return ENOENT;
5451368987aSJohn Baldwin }
5461368987aSJohn Baldwin 
5471368987aSJohn Baldwin int
legacy_pcib_write_ivar(device_t dev,device_t child,int which,uintptr_t value)5481368987aSJohn Baldwin legacy_pcib_write_ivar(device_t dev, device_t child, int which,
5491368987aSJohn Baldwin     uintptr_t value)
5501368987aSJohn Baldwin {
5511368987aSJohn Baldwin 
5521368987aSJohn Baldwin 	switch (which) {
5531368987aSJohn Baldwin 	case  PCIB_IVAR_DOMAIN:
5541368987aSJohn Baldwin 		return EINVAL;
5551368987aSJohn Baldwin 	case  PCIB_IVAR_BUS:
5561368987aSJohn Baldwin 		legacy_set_pcibus(dev, value);
5571368987aSJohn Baldwin 		return 0;
5581368987aSJohn Baldwin 	}
5591368987aSJohn Baldwin 	return ENOENT;
5601368987aSJohn Baldwin }
5611368987aSJohn Baldwin 
5621368987aSJohn Baldwin /*
5631368987aSJohn Baldwin  * Helper routine for x86 Host-PCI bridge driver resource allocation.
5641368987aSJohn Baldwin  * This is used to adjust the start address of wildcard allocation
5651368987aSJohn Baldwin  * requests to avoid low addresses that are known to be problematic.
5661368987aSJohn Baldwin  *
5671368987aSJohn Baldwin  * If no memory preference is given, use upper 32MB slot most BIOSes
5681368987aSJohn Baldwin  * use for their memory window.  This is typically only used on older
569db4fcadfSConrad Meyer  * laptops that don't have PCI buses behind a PCI bridge, so assuming
5701368987aSJohn Baldwin  * > 32MB is likely OK.
5711368987aSJohn Baldwin  *
5721368987aSJohn Baldwin  * However, this can cause problems for other chipsets, so we make
5731368987aSJohn Baldwin  * this tunable by hw.pci.host_mem_start.
5741368987aSJohn Baldwin  */
5751368987aSJohn Baldwin SYSCTL_DECL(_hw_pci);
5761368987aSJohn Baldwin 
5771368987aSJohn Baldwin static unsigned long host_mem_start = 0x80000000;
5781368987aSJohn Baldwin SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start,
5791368987aSJohn Baldwin     0, "Limit the host bridge memory to being above this address.");
5801368987aSJohn Baldwin 
5812dd1bdf1SJustin Hibbits rman_res_t
hostb_alloc_start(int type,rman_res_t start,rman_res_t end,rman_res_t count)5822dd1bdf1SJustin Hibbits hostb_alloc_start(int type, rman_res_t start, rman_res_t end, rman_res_t count)
5831368987aSJohn Baldwin {
5841368987aSJohn Baldwin 
5851368987aSJohn Baldwin 	if (start + count - 1 != end) {
5861368987aSJohn Baldwin 		if (type == SYS_RES_MEMORY && start < host_mem_start)
5871368987aSJohn Baldwin 			start = host_mem_start;
5881368987aSJohn Baldwin 		if (type == SYS_RES_IOPORT && start < 0x1000)
5891368987aSJohn Baldwin 			start = 0x1000;
5901368987aSJohn Baldwin 	}
5911368987aSJohn Baldwin 	return (start);
5921368987aSJohn Baldwin }
5931368987aSJohn Baldwin 
5941368987aSJohn Baldwin struct resource *
legacy_pcib_alloc_resource(device_t dev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)5951368987aSJohn Baldwin legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
5962dd1bdf1SJustin Hibbits     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
5971368987aSJohn Baldwin {
5981368987aSJohn Baldwin 
5994edef187SJohn Baldwin 	if (type == PCI_RES_BUS)
6004edef187SJohn Baldwin 		return (pci_domain_alloc_bus(0, child, rid, start, end, count,
6014edef187SJohn Baldwin 		    flags));
6021368987aSJohn Baldwin 	start = hostb_alloc_start(type, start, end, count);
6031368987aSJohn Baldwin 	return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
6041368987aSJohn Baldwin 	    count, flags));
6051368987aSJohn Baldwin }
6061368987aSJohn Baldwin 
6074edef187SJohn Baldwin int
legacy_pcib_adjust_resource(device_t dev,device_t child,struct resource * r,rman_res_t start,rman_res_t end)608fef01f04SJohn Baldwin legacy_pcib_adjust_resource(device_t dev, device_t child,
6092dd1bdf1SJustin Hibbits     struct resource *r, rman_res_t start, rman_res_t end)
6104edef187SJohn Baldwin {
6114edef187SJohn Baldwin 
612fef01f04SJohn Baldwin 	if (rman_get_type(r) == PCI_RES_BUS)
6134edef187SJohn Baldwin 		return (pci_domain_adjust_bus(0, child, r, start, end));
614fef01f04SJohn Baldwin 	return (bus_generic_adjust_resource(dev, child, r, start, end));
6154edef187SJohn Baldwin }
6164edef187SJohn Baldwin 
6174edef187SJohn Baldwin int
legacy_pcib_release_resource(device_t dev,device_t child,struct resource * r)6189dbf5b0eSJohn Baldwin legacy_pcib_release_resource(device_t dev, device_t child, struct resource *r)
6194edef187SJohn Baldwin {
6204edef187SJohn Baldwin 
6219dbf5b0eSJohn Baldwin 	if (rman_get_type(r) == PCI_RES_BUS)
6229dbf5b0eSJohn Baldwin 		return (pci_domain_release_bus(0, child, r));
6239dbf5b0eSJohn Baldwin 	return (bus_generic_release_resource(dev, child, r));
6244edef187SJohn Baldwin }
62531e15e53SJohn Baldwin 
62631e15e53SJohn Baldwin int
legacy_pcib_activate_resource(device_t dev,device_t child,struct resource * r)6272baed46eSJohn Baldwin legacy_pcib_activate_resource(device_t dev, device_t child, struct resource *r)
62831e15e53SJohn Baldwin {
6292baed46eSJohn Baldwin 	if (rman_get_type(r) == PCI_RES_BUS)
6302baed46eSJohn Baldwin 		return (pci_domain_activate_bus(0, child, r));
6312baed46eSJohn Baldwin 	return (bus_generic_activate_resource(dev, child, r));
63231e15e53SJohn Baldwin }
63331e15e53SJohn Baldwin 
63431e15e53SJohn Baldwin int
legacy_pcib_deactivate_resource(device_t dev,device_t child,struct resource * r)6352baed46eSJohn Baldwin legacy_pcib_deactivate_resource(device_t dev, device_t child,
63631e15e53SJohn Baldwin     struct resource *r)
63731e15e53SJohn Baldwin {
6382baed46eSJohn Baldwin 	if (rman_get_type(r) == PCI_RES_BUS)
6392baed46eSJohn Baldwin 		return (pci_domain_deactivate_bus(0, child, r));
6402baed46eSJohn Baldwin 	return (bus_generic_deactivate_resource(dev, child, r));
64131e15e53SJohn Baldwin }
6424edef187SJohn Baldwin 
6431368987aSJohn Baldwin static device_method_t legacy_pcib_methods[] = {
6441368987aSJohn Baldwin 	/* Device interface */
6451368987aSJohn Baldwin 	DEVMETHOD(device_identify,	legacy_pcib_identify),
6461368987aSJohn Baldwin 	DEVMETHOD(device_probe,		legacy_pcib_probe),
6471368987aSJohn Baldwin 	DEVMETHOD(device_attach,	legacy_pcib_attach),
6481368987aSJohn Baldwin 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
6491368987aSJohn Baldwin 	DEVMETHOD(device_suspend,	bus_generic_suspend),
6501368987aSJohn Baldwin 	DEVMETHOD(device_resume,	bus_generic_resume),
6511368987aSJohn Baldwin 
6521368987aSJohn Baldwin 	/* Bus interface */
6531368987aSJohn Baldwin 	DEVMETHOD(bus_read_ivar,	legacy_pcib_read_ivar),
6541368987aSJohn Baldwin 	DEVMETHOD(bus_write_ivar,	legacy_pcib_write_ivar),
6551368987aSJohn Baldwin 	DEVMETHOD(bus_alloc_resource,	legacy_pcib_alloc_resource),
6564edef187SJohn Baldwin 	DEVMETHOD(bus_adjust_resource,	legacy_pcib_adjust_resource),
6574edef187SJohn Baldwin 	DEVMETHOD(bus_release_resource,	legacy_pcib_release_resource),
65831e15e53SJohn Baldwin 	DEVMETHOD(bus_activate_resource, legacy_pcib_activate_resource),
65931e15e53SJohn Baldwin 	DEVMETHOD(bus_deactivate_resource, legacy_pcib_deactivate_resource),
6601368987aSJohn Baldwin 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
6611368987aSJohn Baldwin 	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
6621368987aSJohn Baldwin 
6631368987aSJohn Baldwin 	/* pcib interface */
6641368987aSJohn Baldwin 	DEVMETHOD(pcib_maxslots,	legacy_pcib_maxslots),
6651368987aSJohn Baldwin 	DEVMETHOD(pcib_read_config,	legacy_pcib_read_config),
6661368987aSJohn Baldwin 	DEVMETHOD(pcib_write_config,	legacy_pcib_write_config),
6671368987aSJohn Baldwin 	DEVMETHOD(pcib_route_interrupt,	legacy_pcib_route_interrupt),
6681368987aSJohn Baldwin 	DEVMETHOD(pcib_alloc_msi,	legacy_pcib_alloc_msi),
6691368987aSJohn Baldwin 	DEVMETHOD(pcib_release_msi,	pcib_release_msi),
6701368987aSJohn Baldwin 	DEVMETHOD(pcib_alloc_msix,	legacy_pcib_alloc_msix),
6711368987aSJohn Baldwin 	DEVMETHOD(pcib_release_msix,	pcib_release_msix),
6721368987aSJohn Baldwin 	DEVMETHOD(pcib_map_msi,		legacy_pcib_map_msi),
67328586889SWarner Losh 	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
6741368987aSJohn Baldwin 
6754b7ec270SMarius Strobl 	DEVMETHOD_END
6761368987aSJohn Baldwin };
6771368987aSJohn Baldwin 
6781368987aSJohn Baldwin DEFINE_CLASS_0(pcib, legacy_pcib_driver, legacy_pcib_methods, 1);
67980d2b3deSJohn Baldwin DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, 0, 0);
6801368987aSJohn Baldwin 
6811368987aSJohn Baldwin /*
6821368987aSJohn Baldwin  * Install placeholder to claim the resources owned by the
6831368987aSJohn Baldwin  * PCI bus interface.  This could be used to extract the
6841368987aSJohn Baldwin  * config space registers in the extreme case where the PnP
6851368987aSJohn Baldwin  * ID is available and the PCI BIOS isn't, but for now we just
6861368987aSJohn Baldwin  * eat the PnP ID and do nothing else.
6871368987aSJohn Baldwin  *
688d6b66397SWarner Losh  * we silence this probe, as it will generally confuse people.
6891368987aSJohn Baldwin  */
6901368987aSJohn Baldwin static struct isa_pnp_id pcibus_pnp_ids[] = {
6911368987aSJohn Baldwin 	{ 0x030ad041 /* PNP0A03 */, "PCI Bus" },
6921368987aSJohn Baldwin 	{ 0x080ad041 /* PNP0A08 */, "PCIe Bus" },
6931368987aSJohn Baldwin 	{ 0 }
6941368987aSJohn Baldwin };
6951368987aSJohn Baldwin 
6961368987aSJohn Baldwin static int
pcibus_pnp_probe(device_t dev)6971368987aSJohn Baldwin pcibus_pnp_probe(device_t dev)
6981368987aSJohn Baldwin {
6991368987aSJohn Baldwin 	int result;
7001368987aSJohn Baldwin 
7011368987aSJohn Baldwin 	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0)
7021368987aSJohn Baldwin 		device_quiet(dev);
7031368987aSJohn Baldwin 	return(result);
7041368987aSJohn Baldwin }
7051368987aSJohn Baldwin 
7061368987aSJohn Baldwin static int
pcibus_pnp_attach(device_t dev)7071368987aSJohn Baldwin pcibus_pnp_attach(device_t dev)
7081368987aSJohn Baldwin {
7091368987aSJohn Baldwin 	return(0);
7101368987aSJohn Baldwin }
7111368987aSJohn Baldwin 
7121368987aSJohn Baldwin static device_method_t pcibus_pnp_methods[] = {
7131368987aSJohn Baldwin 	/* Device interface */
7141368987aSJohn Baldwin 	DEVMETHOD(device_probe,		pcibus_pnp_probe),
7151368987aSJohn Baldwin 	DEVMETHOD(device_attach,	pcibus_pnp_attach),
7161368987aSJohn Baldwin 	{ 0, 0 }
7171368987aSJohn Baldwin };
7181368987aSJohn Baldwin 
7191368987aSJohn Baldwin DEFINE_CLASS_0(pcibus_pnp, pcibus_pnp_driver, pcibus_pnp_methods, 1);
72080d2b3deSJohn Baldwin DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, 0, 0);
7211368987aSJohn Baldwin 
7221368987aSJohn Baldwin #ifdef __HAVE_PIR
7231368987aSJohn Baldwin /*
724db4fcadfSConrad Meyer  * Provide a PCI-PCI bridge driver for PCI buses behind PCI-PCI bridges
7251368987aSJohn Baldwin  * that appear in the PCIBIOS Interrupt Routing Table to use the routing
7261368987aSJohn Baldwin  * table for interrupt routing when possible.
7271368987aSJohn Baldwin  */
7281368987aSJohn Baldwin static int	pcibios_pcib_probe(device_t bus);
7291368987aSJohn Baldwin 
7301368987aSJohn Baldwin static device_method_t pcibios_pcib_pci_methods[] = {
7311368987aSJohn Baldwin 	/* Device interface */
7321368987aSJohn Baldwin 	DEVMETHOD(device_probe,		pcibios_pcib_probe),
7331368987aSJohn Baldwin 
7341368987aSJohn Baldwin 	/* pcib interface */
7351368987aSJohn Baldwin 	DEVMETHOD(pcib_route_interrupt,	legacy_pcib_route_interrupt),
7361368987aSJohn Baldwin 	{0, 0}
7371368987aSJohn Baldwin };
7381368987aSJohn Baldwin 
7391368987aSJohn Baldwin DEFINE_CLASS_1(pcib, pcibios_pcib_driver, pcibios_pcib_pci_methods,
7401368987aSJohn Baldwin     sizeof(struct pcib_softc), pcib_driver);
74180d2b3deSJohn Baldwin DRIVER_MODULE(pcibios_pcib, pci, pcibios_pcib_driver, 0, 0);
742d6b66397SWarner Losh ISA_PNP_INFO(pcibus_pnp_ids);
7431368987aSJohn Baldwin 
7441368987aSJohn Baldwin static int
pcibios_pcib_probe(device_t dev)7451368987aSJohn Baldwin pcibios_pcib_probe(device_t dev)
7461368987aSJohn Baldwin {
7471368987aSJohn Baldwin 	int bus;
7481368987aSJohn Baldwin 
7491368987aSJohn Baldwin 	if ((pci_get_class(dev) != PCIC_BRIDGE) ||
7501368987aSJohn Baldwin 	    (pci_get_subclass(dev) != PCIS_BRIDGE_PCI))
7511368987aSJohn Baldwin 		return (ENXIO);
7521368987aSJohn Baldwin 	bus = pci_read_config(dev, PCIR_SECBUS_1, 1);
7531368987aSJohn Baldwin 	if (bus == 0)
7541368987aSJohn Baldwin 		return (ENXIO);
7551368987aSJohn Baldwin 	if (!pci_pir_probe(bus, 1))
7561368987aSJohn Baldwin 		return (ENXIO);
7571368987aSJohn Baldwin 	device_set_desc(dev, "PCIBIOS PCI-PCI bridge");
7581368987aSJohn Baldwin 	return (-2000);
7591368987aSJohn Baldwin }
7601368987aSJohn Baldwin #endif
761