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