1 /* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 JF Hay. All rights reserved. 5 * Copyright (c) 2000 M. Warner Losh. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c) 1996, 1998, 1999 31 * Christopher G. Demetriou. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by Christopher G. Demetriou 44 * for the NetBSD Project. 45 * 4. The name of the author may not be used to endorse or promote products 46 * derived from this software without specific prior written permission 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 50 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 51 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 52 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 57 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60 #include <sys/cdefs.h> 61 __FBSDID("$FreeBSD$"); 62 63 #include <sys/param.h> 64 #include <sys/systm.h> 65 #include <sys/kernel.h> 66 #include <sys/module.h> 67 #include <sys/bus.h> 68 #include <sys/conf.h> 69 #include <sys/malloc.h> 70 #include <sys/sysctl.h> 71 72 #include <machine/bus.h> 73 #include <machine/resource.h> 74 #include <sys/rman.h> 75 76 #include <dev/pci/pcireg.h> 77 #include <dev/pci/pcivar.h> 78 79 #include <dev/puc/puc_cfg.h> 80 #include <dev/puc/puc_bfe.h> 81 82 static int puc_msi_disable; 83 TUNABLE_INT("hw.puc.msi_disable", &puc_msi_disable); 84 SYSCTL_INT(_hw_puc, OID_AUTO, msi_disable, CTLFLAG_RD | CTLFLAG_TUN, 85 &puc_msi_disable, 0, "Disable use of MSI interrupts by puc(9)"); 86 87 static const struct puc_cfg * 88 puc_pci_match(device_t dev, const struct puc_cfg *desc) 89 { 90 uint16_t vendor, device; 91 uint16_t subvendor, subdevice; 92 93 vendor = pci_get_vendor(dev); 94 device = pci_get_device(dev); 95 subvendor = pci_get_subvendor(dev); 96 subdevice = pci_get_subdevice(dev); 97 98 while (desc->vendor != 0xffff) { 99 if (desc->vendor == vendor && desc->device == device) { 100 /* exact match */ 101 if (desc->subvendor == subvendor && 102 desc->subdevice == subdevice) 103 return (desc); 104 /* wildcard match */ 105 if (desc->subvendor == 0xffff) 106 return (desc); 107 } 108 desc++; 109 } 110 111 /* no match */ 112 return (NULL); 113 } 114 115 static int 116 puc_pci_probe(device_t dev) 117 { 118 const struct puc_cfg *desc; 119 120 if ((pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) != 0) 121 return (ENXIO); 122 123 desc = puc_pci_match(dev, puc_pci_devices); 124 if (desc == NULL) 125 return (ENXIO); 126 return (puc_bfe_probe(dev, desc)); 127 } 128 129 static int 130 puc_pci_attach(device_t dev) 131 { 132 struct puc_softc *sc; 133 int error, count; 134 135 sc = device_get_softc(dev); 136 137 if (!puc_msi_disable) { 138 count = 1; 139 140 if (pci_alloc_msi(dev, &count) == 0) { 141 sc->sc_msi = 1; 142 sc->sc_irid = 1; 143 } 144 } 145 146 error = puc_bfe_attach(dev); 147 148 if (error != 0 && sc->sc_msi) 149 pci_release_msi(dev); 150 151 return (error); 152 } 153 154 static int 155 puc_pci_detach(device_t dev) 156 { 157 struct puc_softc *sc; 158 int error; 159 160 sc = device_get_softc(dev); 161 162 error = puc_bfe_detach(dev); 163 164 if (error != 0) 165 return (error); 166 167 if (sc->sc_msi) 168 error = pci_release_msi(dev); 169 170 return (error); 171 } 172 173 174 static device_method_t puc_pci_methods[] = { 175 /* Device interface */ 176 DEVMETHOD(device_probe, puc_pci_probe), 177 DEVMETHOD(device_attach, puc_pci_attach), 178 DEVMETHOD(device_detach, puc_pci_detach), 179 180 DEVMETHOD(bus_alloc_resource, puc_bus_alloc_resource), 181 DEVMETHOD(bus_release_resource, puc_bus_release_resource), 182 DEVMETHOD(bus_get_resource, puc_bus_get_resource), 183 DEVMETHOD(bus_read_ivar, puc_bus_read_ivar), 184 DEVMETHOD(bus_setup_intr, puc_bus_setup_intr), 185 DEVMETHOD(bus_teardown_intr, puc_bus_teardown_intr), 186 DEVMETHOD(bus_print_child, puc_bus_print_child), 187 DEVMETHOD(bus_child_pnpinfo_str, puc_bus_child_pnpinfo_str), 188 DEVMETHOD(bus_child_location_str, puc_bus_child_location_str), 189 190 DEVMETHOD_END 191 }; 192 193 static driver_t puc_pci_driver = { 194 puc_driver_name, 195 puc_pci_methods, 196 sizeof(struct puc_softc), 197 }; 198 199 DRIVER_MODULE(puc, pci, puc_pci_driver, puc_devclass, 0, 0); 200