xref: /netbsd-src/sys/arch/x86/pci/pcib.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: pcib.c,v 1.21 2021/08/07 16:19:08 thorpej Exp $	*/
27e8be191Sxtraeme 
37e8be191Sxtraeme /*-
47e8be191Sxtraeme  * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc.
57e8be191Sxtraeme  * All rights reserved.
67e8be191Sxtraeme  *
77e8be191Sxtraeme  * This code is derived from software contributed to The NetBSD Foundation
87e8be191Sxtraeme  * by Jason R. Thorpe.
97e8be191Sxtraeme  *
107e8be191Sxtraeme  * Redistribution and use in source and binary forms, with or without
117e8be191Sxtraeme  * modification, are permitted provided that the following conditions
127e8be191Sxtraeme  * are met:
137e8be191Sxtraeme  * 1. Redistributions of source code must retain the above copyright
147e8be191Sxtraeme  *    notice, this list of conditions and the following disclaimer.
157e8be191Sxtraeme  * 2. Redistributions in binary form must reproduce the above copyright
167e8be191Sxtraeme  *    notice, this list of conditions and the following disclaimer in the
177e8be191Sxtraeme  *    documentation and/or other materials provided with the distribution.
187e8be191Sxtraeme  *
197e8be191Sxtraeme  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
207e8be191Sxtraeme  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
217e8be191Sxtraeme  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
227e8be191Sxtraeme  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
237e8be191Sxtraeme  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
247e8be191Sxtraeme  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
257e8be191Sxtraeme  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
267e8be191Sxtraeme  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
277e8be191Sxtraeme  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
287e8be191Sxtraeme  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
297e8be191Sxtraeme  * POSSIBILITY OF SUCH DAMAGE.
307e8be191Sxtraeme  */
317e8be191Sxtraeme 
327e8be191Sxtraeme #include <sys/cdefs.h>
33*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.21 2021/08/07 16:19:08 thorpej Exp $");
347e8be191Sxtraeme 
357e8be191Sxtraeme #include <sys/types.h>
367e8be191Sxtraeme #include <sys/param.h>
377e8be191Sxtraeme #include <sys/systm.h>
387e8be191Sxtraeme #include <sys/device.h>
397e8be191Sxtraeme 
40391925c7Sdyoung #include <sys/bus.h>
417e8be191Sxtraeme 
427e8be191Sxtraeme #include <dev/isa/isavar.h>
437e8be191Sxtraeme 
447e8be191Sxtraeme #include <dev/pci/pcivar.h>
457e8be191Sxtraeme #include <dev/pci/pcireg.h>
467e8be191Sxtraeme 
477e8be191Sxtraeme #include <dev/pci/pcidevs.h>
487e8be191Sxtraeme 
497e8be191Sxtraeme #include "isa.h"
50e394f32aSmartin #include "pcibvar.h"
514c1d81b2Sjmcneill 
52e61fddb8Scegger int	pcibmatch(device_t, cfdata_t, void *);
537e8be191Sxtraeme 
540d1ba3e8Sdyoung CFATTACH_DECL3_NEW(pcib, sizeof(struct pcib_softc),
559b779d6eSdyoung     pcibmatch, pcibattach, pcibdetach, NULL, pcibrescan, pcibchilddet,
560d1ba3e8Sdyoung     DVF_DETACH_SHUTDOWN);
577e8be191Sxtraeme 
58d2cef052Sdyoung void	pcib_callback(device_t);
597e8be191Sxtraeme 
607e8be191Sxtraeme int
pcibmatch(device_t parent,cfdata_t match,void * aux)61e61fddb8Scegger pcibmatch(device_t parent, cfdata_t match, void *aux)
627e8be191Sxtraeme {
637e8be191Sxtraeme 	struct pci_attach_args *pa = aux;
647e8be191Sxtraeme 
657e8be191Sxtraeme #if 0
667e8be191Sxtraeme 	/*
677e8be191Sxtraeme 	 * PCI-ISA bridges are matched on class/subclass.
687e8be191Sxtraeme 	 * This list contains only the bridges where correct
697e8be191Sxtraeme 	 * (or incorrect) behaviour is not yet confirmed.
707e8be191Sxtraeme 	 */
717e8be191Sxtraeme 	switch (PCI_VENDOR(pa->pa_id)) {
727e8be191Sxtraeme 	case PCI_VENDOR_INTEL:
737e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
747e8be191Sxtraeme 		case PCI_PRODUCT_INTEL_82426EX:
757e8be191Sxtraeme 		case PCI_PRODUCT_INTEL_82380AB:
767e8be191Sxtraeme 			return (1);
777e8be191Sxtraeme 		}
787e8be191Sxtraeme 		break;
797e8be191Sxtraeme 
807e8be191Sxtraeme 	case PCI_VENDOR_UMC:
817e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
827e8be191Sxtraeme 		case PCI_PRODUCT_UMC_UM8886F:
837e8be191Sxtraeme 		case PCI_PRODUCT_UMC_UM82C886:
847e8be191Sxtraeme 			return (1);
857e8be191Sxtraeme 		}
867e8be191Sxtraeme 		break;
877e8be191Sxtraeme 	case PCI_VENDOR_ALI:
887e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
897e8be191Sxtraeme 		case PCI_PRODUCT_ALI_M1449:
907e8be191Sxtraeme 		case PCI_PRODUCT_ALI_M1543:
917e8be191Sxtraeme 			return (1);
927e8be191Sxtraeme 		}
937e8be191Sxtraeme 		break;
947e8be191Sxtraeme 	case PCI_VENDOR_COMPAQ:
957e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
967e8be191Sxtraeme 		case PCI_PRODUCT_COMPAQ_PCI_ISA_BRIDGE:
977e8be191Sxtraeme 			return (1);
987e8be191Sxtraeme 		}
997e8be191Sxtraeme 		break;
1007e8be191Sxtraeme 	case PCI_VENDOR_VIATECH:
1017e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
1027e8be191Sxtraeme 		case PCI_PRODUCT_VIATECH_VT82C570MV:
1037e8be191Sxtraeme 		case PCI_PRODUCT_VIATECH_VT82C586_ISA:
1047e8be191Sxtraeme 			return (1);
1057e8be191Sxtraeme 		}
1067e8be191Sxtraeme 		break;
1077e8be191Sxtraeme 	}
1087e8be191Sxtraeme #endif
1097e8be191Sxtraeme 
1107e8be191Sxtraeme 	/*
1117e8be191Sxtraeme 	 * some special cases:
1127e8be191Sxtraeme 	 */
1137e8be191Sxtraeme 	switch (PCI_VENDOR(pa->pa_id)) {
1147e8be191Sxtraeme 	case PCI_VENDOR_INTEL:
1157e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
1167e8be191Sxtraeme 		case PCI_PRODUCT_INTEL_SIO:
1177e8be191Sxtraeme 			/*
1187e8be191Sxtraeme 			 * The Intel SIO identifies itself as a
1197e8be191Sxtraeme 			 * miscellaneous prehistoric.
1207e8be191Sxtraeme 			 */
1217e8be191Sxtraeme 		case PCI_PRODUCT_INTEL_82371MX:
1227e8be191Sxtraeme 			/*
1237e8be191Sxtraeme 			 * The Intel 82371MX identifies itself erroneously as a
1247e8be191Sxtraeme 			 * miscellaneous bridge.
1257e8be191Sxtraeme 			 */
1267e8be191Sxtraeme 		case PCI_PRODUCT_INTEL_82371AB_ISA:
1277e8be191Sxtraeme 			/*
1287e8be191Sxtraeme 			 * Some Intel 82371AB PCI-ISA bridge identifies
1297e8be191Sxtraeme 			 * itself as miscellaneous bridge.
1307e8be191Sxtraeme 			 */
1317e8be191Sxtraeme 			return (1);
1327e8be191Sxtraeme 		}
1337e8be191Sxtraeme 		break;
1347e8be191Sxtraeme 	case PCI_VENDOR_SIS:
1357e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
1367e8be191Sxtraeme 		case PCI_PRODUCT_SIS_85C503:
1377e8be191Sxtraeme 			/*
1387e8be191Sxtraeme 			 * The SIS 85C503 identifies itself as a
1397e8be191Sxtraeme 			 * miscellaneous prehistoric.
1407e8be191Sxtraeme 			 */
1417e8be191Sxtraeme 			return (1);
1427e8be191Sxtraeme 		}
1437e8be191Sxtraeme 		break;
1447e8be191Sxtraeme 	case PCI_VENDOR_VIATECH:
1457e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
14697619249Sjdolecek 		case PCI_PRODUCT_VIATECH_VT82C686A_PWR:
1477e8be191Sxtraeme 			/*
14897619249Sjdolecek 			 * The VIA VT82C686A Power Management Controller
14997619249Sjdolecek 			 * identifies itself as ISA bridge, but it's wrong !
1507e8be191Sxtraeme 			 */
1517e8be191Sxtraeme 			return (0);
1527e8be191Sxtraeme 		}
153027eb8b5Smrg 		break;
1547e8be191Sxtraeme 	/*
1557e8be191Sxtraeme 	 * The Cyrix cs5530 PCI host bridge does not have a broken
1567e8be191Sxtraeme 	 * latch on the i8254 clock core, unlike its predecessors
1577e8be191Sxtraeme 	 * the cs5510 and cs5520. This reverses the setting from
1587e8be191Sxtraeme 	 * i386/i386/identcpu.c where it arguably should not have
1597e8be191Sxtraeme 	 * been set in the first place. XXX
1607e8be191Sxtraeme 	 */
1617e8be191Sxtraeme 	case PCI_VENDOR_CYRIX:
1627e8be191Sxtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
1637e8be191Sxtraeme 		case PCI_PRODUCT_CYRIX_CX5530_PCIB:
164427af037Scherry #if !defined(XENPV)
1657e8be191Sxtraeme 			{
1667e8be191Sxtraeme 				extern int clock_broken_latch;
1677e8be191Sxtraeme 
1687e8be191Sxtraeme 				clock_broken_latch = 0;
1697e8be191Sxtraeme 			}
1709ae46516Sjoerg #endif
1717e8be191Sxtraeme 			return (1);
1727e8be191Sxtraeme 		}
1737e8be191Sxtraeme 		break;
1747e8be191Sxtraeme 	}
1757e8be191Sxtraeme 
1767e8be191Sxtraeme 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
1777e8be191Sxtraeme 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) {
1787e8be191Sxtraeme 		return (1);
1797e8be191Sxtraeme 	}
1807e8be191Sxtraeme 
1817e8be191Sxtraeme 	return (0);
1827e8be191Sxtraeme }
1837e8be191Sxtraeme 
1847e8be191Sxtraeme void
pcibattach(device_t parent,device_t self,void * aux)185d2cef052Sdyoung pcibattach(device_t parent, device_t self, void *aux)
1867e8be191Sxtraeme {
1874c1d81b2Sjmcneill 	struct pcib_softc *sc = device_private(self);
1887e8be191Sxtraeme 	struct pci_attach_args *pa = aux;
1897e8be191Sxtraeme 
1907e8be191Sxtraeme 	/*
1917e8be191Sxtraeme 	 * Just print out a description and defer configuration
1927e8be191Sxtraeme 	 * until all PCI devices have been attached.
1937e8be191Sxtraeme 	 */
194d8e1a7b6Sdrochner 	pci_aprint_devinfo(pa, NULL);
1957e8be191Sxtraeme 
1964c1d81b2Sjmcneill 	sc->sc_pc = pa->pa_pc;
1974c1d81b2Sjmcneill 	sc->sc_tag = pa->pa_tag;
1984c1d81b2Sjmcneill 
1994c1d81b2Sjmcneill 	if (!pmf_device_register(self, NULL, NULL))
2004c1d81b2Sjmcneill 		aprint_error_dev(self, "couldn't establish power handler\n");
2014c1d81b2Sjmcneill 
2027e8be191Sxtraeme 	config_defer(self, pcib_callback);
2037e8be191Sxtraeme }
2047e8be191Sxtraeme 
205d2cef052Sdyoung int
pcibdetach(device_t self,int flags)206d2cef052Sdyoung pcibdetach(device_t self, int flags)
207d2cef052Sdyoung {
208d2cef052Sdyoung 	int rc;
209d2cef052Sdyoung 
210d2cef052Sdyoung 	if ((rc = config_detach_children(self, flags)) != 0)
211d2cef052Sdyoung 		return rc;
212d2cef052Sdyoung 	pmf_device_deregister(self);
213d2cef052Sdyoung 	return 0;
214d2cef052Sdyoung }
215d2cef052Sdyoung 
2167e8be191Sxtraeme void
pcibchilddet(device_t self,device_t child)217d2cef052Sdyoung pcibchilddet(device_t self, device_t child)
218d2cef052Sdyoung {
2199b779d6eSdyoung 	struct pcib_softc *sc = device_private(self);
2209b779d6eSdyoung 
2219b779d6eSdyoung 	if (sc->sc_isabus == child)
2229b779d6eSdyoung 		sc->sc_isabus = NULL;
223d2cef052Sdyoung }
224d2cef052Sdyoung 
2259b779d6eSdyoung int
pcibrescan(device_t self,const char * ifattr,const int * loc)2269b779d6eSdyoung pcibrescan(device_t self, const char *ifattr, const int *loc)
2279b779d6eSdyoung {
2289b779d6eSdyoung 	struct pcib_softc *sc = device_private(self);
2297e8be191Sxtraeme 	struct isabus_attach_args iba;
2307e8be191Sxtraeme 
2312685996bSthorpej 	/*
2322685996bSthorpej 	 * Even though pcib only has a single "isabus" interface
2332685996bSthorpej 	 * attribute, this function is referenced by other drivers
2342685996bSthorpej 	 * that carry more, so we go ahead and filter.
2352685996bSthorpej 	 */
2369b779d6eSdyoung 	if (ifattr_match(ifattr, "isabus") && sc->sc_isabus == NULL) {
2377e8be191Sxtraeme 		/*
2387e8be191Sxtraeme 		 * Attach the ISA bus behind this bridge.
2397e8be191Sxtraeme 		 */
2407e8be191Sxtraeme 		memset(&iba, 0, sizeof(iba));
24130b2d68dSdyoung 		iba.iba_iot = x86_bus_space_io;
24230b2d68dSdyoung 		iba.iba_memt = x86_bus_space_mem;
2437e8be191Sxtraeme #if NISA > 0
2447e8be191Sxtraeme 		iba.iba_dmat = &isa_bus_dma_tag;
2457e8be191Sxtraeme #endif
2469b779d6eSdyoung 		sc->sc_isabus =
2472685996bSthorpej 		    config_found(self, &iba, isabusprint,
248*c7fb772bSthorpej 			CFARGS(.iattr = "isabus"));
2497e8be191Sxtraeme 	}
2509b779d6eSdyoung 	return 0;
2519b779d6eSdyoung }
2529b779d6eSdyoung 
2539b779d6eSdyoung void
pcib_callback(device_t self)2549b779d6eSdyoung pcib_callback(device_t self)
2559b779d6eSdyoung {
2569b779d6eSdyoung 	pcibrescan(self, "isabus", NULL);
2579b779d6eSdyoung }
258