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