1 1.57 thorpej /* $NetBSD: sio.c,v 1.57 2021/08/07 16:18:41 thorpej Exp $ */ 2 1.30 thorpej 3 1.30 thorpej /*- 4 1.30 thorpej * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 1.30 thorpej * All rights reserved. 6 1.30 thorpej * 7 1.30 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.30 thorpej * by Jason R. Thorpe. 9 1.30 thorpej * 10 1.30 thorpej * Redistribution and use in source and binary forms, with or without 11 1.30 thorpej * modification, are permitted provided that the following conditions 12 1.30 thorpej * are met: 13 1.30 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.30 thorpej * notice, this list of conditions and the following disclaimer. 15 1.30 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.30 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.30 thorpej * documentation and/or other materials provided with the distribution. 18 1.30 thorpej * 19 1.30 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.30 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.30 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.30 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.30 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.30 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.30 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.30 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.30 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.30 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.30 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.30 thorpej */ 31 1.1 cgd 32 1.1 cgd /* 33 1.7 cgd * Copyright (c) 1995, 1996 Carnegie-Mellon University. 34 1.1 cgd * All rights reserved. 35 1.1 cgd * 36 1.1 cgd * Author: Chris G. Demetriou 37 1.52 matt * 38 1.1 cgd * Permission to use, copy, modify and distribute this software and 39 1.1 cgd * its documentation is hereby granted, provided that both the copyright 40 1.1 cgd * notice and this permission notice appear in all copies of the 41 1.1 cgd * software, derivative works or modified versions, and any portions 42 1.1 cgd * thereof, and that both notices appear in supporting documentation. 43 1.52 matt * 44 1.52 matt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 45 1.52 matt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 46 1.1 cgd * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 47 1.52 matt * 48 1.1 cgd * Carnegie Mellon requests users of this software to return to 49 1.1 cgd * 50 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 51 1.1 cgd * School of Computer Science 52 1.1 cgd * Carnegie Mellon University 53 1.1 cgd * Pittsburgh PA 15213-3890 54 1.1 cgd * 55 1.1 cgd * any improvements or extensions that they make and grant Carnegie the 56 1.1 cgd * rights to redistribute these changes. 57 1.1 cgd */ 58 1.17 cgd 59 1.30 thorpej #include "opt_dec_2100_a500.h" 60 1.31 thorpej #include "opt_dec_2100a_a500.h" 61 1.33 thorpej #include "eisa.h" 62 1.39 drochner #include "sio.h" 63 1.30 thorpej 64 1.18 cgd #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 65 1.18 cgd 66 1.57 thorpej __KERNEL_RCSID(0, "$NetBSD: sio.c,v 1.57 2021/08/07 16:18:41 thorpej Exp $"); 67 1.1 cgd 68 1.1 cgd #include <sys/param.h> 69 1.1 cgd #include <sys/systm.h> 70 1.1 cgd #include <sys/kernel.h> 71 1.1 cgd #include <sys/device.h> 72 1.54 thorpej #include <sys/kmem.h> 73 1.1 cgd 74 1.5 cgd #include <machine/intr.h> 75 1.51 dyoung #include <sys/bus.h> 76 1.30 thorpej #include <machine/rpb.h> 77 1.5 cgd 78 1.3 cgd #include <dev/isa/isavar.h> 79 1.3 cgd #include <dev/eisa/eisavar.h> 80 1.3 cgd 81 1.1 cgd #include <dev/pci/pcireg.h> 82 1.1 cgd #include <dev/pci/pcivar.h> 83 1.1 cgd #include <dev/pci/pcidevs.h> 84 1.1 cgd 85 1.3 cgd #include <alpha/pci/siovar.h> 86 1.1 cgd 87 1.31 thorpej #if defined(DEC_2100_A500) || defined(DEC_2100A_A500) 88 1.30 thorpej #include <alpha/pci/pci_2100_a500.h> 89 1.31 thorpej #include <alpha/sableio/sableiovar.h> 90 1.30 thorpej #endif 91 1.30 thorpej 92 1.14 cgd struct sio_softc { 93 1.50 matt device_t sc_dev; 94 1.14 cgd 95 1.30 thorpej pci_chipset_tag_t sc_pc; 96 1.30 thorpej 97 1.14 cgd bus_space_tag_t sc_iot, sc_memt; 98 1.19 thorpej bus_dma_tag_t sc_parent_dmat; 99 1.39 drochner #if NPCEB > 0 100 1.14 cgd int sc_haseisa; 101 1.39 drochner #endif 102 1.22 thorpej int sc_is82c693; 103 1.25 thorpej 104 1.25 thorpej /* ISA chipset must persist; it's used after autoconfig. */ 105 1.31 thorpej isa_chipset_tag_t sc_ic; 106 1.14 cgd }; 107 1.14 cgd 108 1.56 thorpej static int siomatch(device_t, cfdata_t, void *); 109 1.56 thorpej static void sioattach(device_t, device_t, void *); 110 1.1 cgd 111 1.50 matt CFATTACH_DECL_NEW(sio, sizeof(struct sio_softc), 112 1.35 thorpej siomatch, sioattach, NULL, NULL); 113 1.4 thorpej 114 1.39 drochner #if NPCEB > 0 115 1.56 thorpej static int pcebmatch(device_t, cfdata_t, void *); 116 1.3 cgd 117 1.50 matt CFATTACH_DECL_NEW(pceb, sizeof(struct sio_softc), 118 1.35 thorpej pcebmatch, sioattach, NULL, NULL); 119 1.39 drochner #endif 120 1.5 cgd 121 1.5 cgd union sio_attach_args { 122 1.5 cgd struct isabus_attach_args sa_iba; 123 1.5 cgd struct eisabus_attach_args sa_eba; 124 1.3 cgd }; 125 1.3 cgd 126 1.56 thorpej static void sio_isa_attach_hook(device_t, device_t, 127 1.56 thorpej struct isabus_attach_args *); 128 1.56 thorpej static void sio_isa_detach_hook(isa_chipset_tag_t, device_t); 129 1.39 drochner #if NPCEB > 0 130 1.56 thorpej static void sio_eisa_attach_hook(device_t, device_t, 131 1.56 thorpej struct eisabus_attach_args *); 132 1.56 thorpej static int sio_eisa_maxslots(void *); 133 1.56 thorpej static int sio_eisa_intr_map(void *, u_int, eisa_intr_handle_t *); 134 1.39 drochner #endif 135 1.1 cgd 136 1.56 thorpej static void sio_bridge_callback(device_t); 137 1.14 cgd 138 1.56 thorpej static int 139 1.50 matt siomatch(device_t parent, cfdata_t match, void *aux) 140 1.1 cgd { 141 1.5 cgd struct pci_attach_args *pa = aux; 142 1.3 cgd 143 1.22 thorpej /* 144 1.22 thorpej * The Cypress 82C693 is more-or-less an SIO, but with 145 1.22 thorpej * indirect register access. (XXX for everything, or 146 1.22 thorpej * just the ELCR?) 147 1.22 thorpej */ 148 1.22 thorpej if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CONTAQ && 149 1.22 thorpej PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONTAQ_82C693 && 150 1.22 thorpej pa->pa_function == 0) 151 1.22 thorpej return (1); 152 1.22 thorpej 153 1.22 thorpej if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 154 1.22 thorpej PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_SIO) 155 1.27 lukem return (1); 156 1.27 lukem 157 1.27 lukem if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI && 158 1.49 mhitch PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M1533) 159 1.22 thorpej return (1); 160 1.3 cgd 161 1.22 thorpej return (0); 162 1.3 cgd } 163 1.3 cgd 164 1.39 drochner #if NPCEB > 0 165 1.56 thorpej static int 166 1.50 matt pcebmatch(device_t parent, cfdata_t match, void *aux) 167 1.3 cgd { 168 1.5 cgd struct pci_attach_args *pa = aux; 169 1.1 cgd 170 1.22 thorpej if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 171 1.22 thorpej PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB) 172 1.22 thorpej return (1); 173 1.1 cgd 174 1.22 thorpej return (0); 175 1.1 cgd } 176 1.39 drochner #endif 177 1.1 cgd 178 1.56 thorpej static void 179 1.50 matt sioattach(device_t parent, device_t self, void *aux) 180 1.1 cgd { 181 1.50 matt struct sio_softc *sc = device_private(self); 182 1.5 cgd struct pci_attach_args *pa = aux; 183 1.3 cgd char devinfo[256]; 184 1.3 cgd 185 1.37 itojun pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 186 1.50 matt aprint_normal(": %s (rev. 0x%02x)\n", devinfo, 187 1.5 cgd PCI_REVISION(pa->pa_class)); 188 1.3 cgd 189 1.50 matt sc->sc_dev = self; 190 1.30 thorpej sc->sc_pc = pa->pa_pc; 191 1.14 cgd sc->sc_iot = pa->pa_iot; 192 1.14 cgd sc->sc_memt = pa->pa_memt; 193 1.19 thorpej sc->sc_parent_dmat = pa->pa_dmat; 194 1.39 drochner #if NPCEB > 0 195 1.22 thorpej sc->sc_haseisa = (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 196 1.22 thorpej PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 197 1.39 drochner #endif 198 1.22 thorpej sc->sc_is82c693 = (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CONTAQ && 199 1.22 thorpej PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONTAQ_82C693); 200 1.3 cgd 201 1.26 thorpej config_defer(self, sio_bridge_callback); 202 1.14 cgd } 203 1.14 cgd 204 1.56 thorpej static void 205 1.50 matt sio_bridge_callback(device_t self) 206 1.14 cgd { 207 1.50 matt struct sio_softc *sc = device_private(self); 208 1.39 drochner union sio_attach_args sa; 209 1.39 drochner #if NPCEB > 0 210 1.14 cgd struct alpha_eisa_chipset ec; 211 1.14 cgd 212 1.14 cgd if (sc->sc_haseisa) { 213 1.8 cgd ec.ec_v = NULL; 214 1.8 cgd ec.ec_attach_hook = sio_eisa_attach_hook; 215 1.8 cgd ec.ec_maxslots = sio_eisa_maxslots; 216 1.30 thorpej 217 1.30 thorpej /* 218 1.30 thorpej * Deal with platforms that hook EISA interrupts 219 1.30 thorpej * up differently. 220 1.30 thorpej */ 221 1.30 thorpej switch (cputype) { 222 1.31 thorpej #if defined(DEC_2100_A500) || defined(DEC_2100A_A500) 223 1.30 thorpej case ST_DEC_2100_A500: 224 1.31 thorpej case ST_DEC_2100A_A500: 225 1.30 thorpej pci_2100_a500_eisa_pickintr(sc->sc_pc, &ec); 226 1.30 thorpej break; 227 1.30 thorpej #endif 228 1.30 thorpej default: 229 1.30 thorpej ec.ec_intr_map = sio_eisa_intr_map; 230 1.30 thorpej ec.ec_intr_string = sio_intr_string; 231 1.30 thorpej ec.ec_intr_evcnt = sio_intr_evcnt; 232 1.53 thorpej ec.ec_intr_establish = sio_isa_intr_establish; 233 1.30 thorpej ec.ec_intr_disestablish = sio_intr_disestablish; 234 1.30 thorpej } 235 1.8 cgd 236 1.14 cgd sa.sa_eba.eba_iot = sc->sc_iot; 237 1.14 cgd sa.sa_eba.eba_memt = sc->sc_memt; 238 1.19 thorpej sa.sa_eba.eba_dmat = 239 1.19 thorpej alphabus_dma_get_tag(sc->sc_parent_dmat, ALPHA_BUS_EISA); 240 1.6 cgd sa.sa_eba.eba_ec = &ec; 241 1.55 thorpej config_found(sc->sc_dev, &sa.sa_eba, eisabusprint, 242 1.57 thorpej CFARGS(.iattr = "eisabus")); 243 1.1 cgd } 244 1.39 drochner #endif /* NPCEB */ 245 1.5 cgd 246 1.31 thorpej /* 247 1.31 thorpej * Deal with platforms which have Odd ISA DMA needs. 248 1.31 thorpej */ 249 1.31 thorpej switch (cputype) { 250 1.32 thorpej #if defined(DEC_2100_A500) || defined(DEC_2100A_A500) 251 1.31 thorpej case ST_DEC_2100_A500: 252 1.32 thorpej case ST_DEC_2100A_A500: 253 1.31 thorpej sc->sc_ic = sableio_pickisa(); 254 1.31 thorpej break; 255 1.31 thorpej #endif 256 1.31 thorpej default: 257 1.54 thorpej sc->sc_ic = kmem_zalloc(sizeof(*sc->sc_ic), KM_SLEEP); 258 1.31 thorpej } 259 1.31 thorpej 260 1.31 thorpej sc->sc_ic->ic_v = NULL; 261 1.31 thorpej sc->sc_ic->ic_attach_hook = sio_isa_attach_hook; 262 1.47 dyoung sc->sc_ic->ic_detach_hook = sio_isa_detach_hook; 263 1.30 thorpej 264 1.30 thorpej /* 265 1.30 thorpej * Deal with platforms that hook up ISA interrupts differently. 266 1.30 thorpej */ 267 1.30 thorpej switch (cputype) { 268 1.32 thorpej #if defined(DEC_2100_A500) || defined(DEC_2100A_A500) 269 1.30 thorpej case ST_DEC_2100_A500: 270 1.32 thorpej case ST_DEC_2100A_A500: 271 1.31 thorpej pci_2100_a500_isa_pickintr(sc->sc_pc, sc->sc_ic); 272 1.30 thorpej break; 273 1.30 thorpej #endif 274 1.30 thorpej default: 275 1.31 thorpej sc->sc_ic->ic_intr_evcnt = sio_intr_evcnt; 276 1.53 thorpej sc->sc_ic->ic_intr_establish = sio_isa_intr_establish; 277 1.31 thorpej sc->sc_ic->ic_intr_disestablish = sio_intr_disestablish; 278 1.31 thorpej sc->sc_ic->ic_intr_alloc = sio_intr_alloc; 279 1.30 thorpej } 280 1.6 cgd 281 1.14 cgd sa.sa_iba.iba_iot = sc->sc_iot; 282 1.14 cgd sa.sa_iba.iba_memt = sc->sc_memt; 283 1.19 thorpej sa.sa_iba.iba_dmat = 284 1.19 thorpej alphabus_dma_get_tag(sc->sc_parent_dmat, ALPHA_BUS_ISA); 285 1.31 thorpej sa.sa_iba.iba_ic = sc->sc_ic; 286 1.55 thorpej config_found(sc->sc_dev, &sa.sa_iba, isabusprint, 287 1.57 thorpej CFARGS(.iattr = "isabus")); 288 1.6 cgd } 289 1.6 cgd 290 1.56 thorpej static void 291 1.50 matt sio_isa_attach_hook(device_t parent, device_t self, struct isabus_attach_args *iba) 292 1.6 cgd { 293 1.6 cgd 294 1.6 cgd /* Nothing to do. */ 295 1.8 cgd } 296 1.8 cgd 297 1.56 thorpej static void 298 1.48 dyoung sio_isa_detach_hook(isa_chipset_tag_t ic, device_t self) 299 1.47 dyoung { 300 1.47 dyoung 301 1.47 dyoung /* Nothing to do. */ 302 1.47 dyoung } 303 1.47 dyoung 304 1.39 drochner #if NPCEB > 0 305 1.39 drochner 306 1.56 thorpej static void 307 1.50 matt sio_eisa_attach_hook(device_t parent, device_t self, struct eisabus_attach_args *eba) 308 1.8 cgd { 309 1.8 cgd 310 1.33 thorpej #if NEISA > 0 311 1.41 tsutsui eisa_init(eba->eba_ec); 312 1.33 thorpej #endif 313 1.8 cgd } 314 1.8 cgd 315 1.56 thorpej static int 316 1.45 dsl sio_eisa_maxslots(void *v) 317 1.8 cgd { 318 1.8 cgd 319 1.8 cgd return 16; /* as good a number as any. only 8, maybe? */ 320 1.8 cgd } 321 1.8 cgd 322 1.56 thorpej static int 323 1.45 dsl sio_eisa_intr_map(void *v, u_int irq, eisa_intr_handle_t *ihp) 324 1.8 cgd { 325 1.8 cgd 326 1.8 cgd #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 327 1.8 cgd 328 1.8 cgd if (irq >= ICU_LEN) { 329 1.11 christos printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 330 1.8 cgd *ihp = -1; 331 1.8 cgd return 1; 332 1.8 cgd } 333 1.8 cgd if (irq == 2) { 334 1.11 christos printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 335 1.8 cgd irq = 9; 336 1.8 cgd } 337 1.8 cgd 338 1.8 cgd *ihp = irq; 339 1.8 cgd return 0; 340 1.1 cgd } 341 1.39 drochner 342 1.39 drochner #endif /* NPCEB */ 343