1 /* $NetBSD: ioasic.c,v 1.34 2000/07/18 06:10:06 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 42 * All rights reserved. 43 * 44 * Author: Keith Bostic, Chris G. Demetriou 45 * 46 * Permission to use, copy, modify and distribute this software and 47 * its documentation is hereby granted, provided that both the copyright 48 * notice and this permission notice appear in all copies of the 49 * software, derivative works or modified versions, and any portions 50 * thereof, and that both notices appear in supporting documentation. 51 * 52 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 53 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 54 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 55 * 56 * Carnegie Mellon requests users of this software to return to 57 * 58 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 59 * School of Computer Science 60 * Carnegie Mellon University 61 * Pittsburgh PA 15213-3890 62 * 63 * any improvements or extensions that they make and grant Carnegie the 64 * rights to redistribute these changes. 65 */ 66 67 #include "opt_dec_3000_300.h" 68 69 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 70 71 __KERNEL_RCSID(0, "$NetBSD: ioasic.c,v 1.34 2000/07/18 06:10:06 thorpej Exp $"); 72 73 #include <sys/param.h> 74 #include <sys/kernel.h> 75 #include <sys/systm.h> 76 #include <sys/device.h> 77 #include <sys/malloc.h> 78 79 #include <machine/autoconf.h> 80 #include <machine/bus.h> 81 #include <machine/pte.h> 82 #include <machine/rpb.h> 83 84 #include <dev/tc/tcvar.h> 85 #include <dev/tc/ioasicreg.h> 86 #include <dev/tc/ioasicvar.h> 87 88 /* Definition of the driver for autoconfig. */ 89 int ioasicmatch __P((struct device *, struct cfdata *, void *)); 90 void ioasicattach __P((struct device *, struct device *, void *)); 91 92 struct cfattach ioasic_ca = { 93 sizeof(struct ioasic_softc), ioasicmatch, ioasicattach, 94 }; 95 96 int ioasic_intr __P((void *)); 97 int ioasic_intrnull __P((void *)); 98 99 #define C(x) ((void *)(x)) 100 101 #define IOASIC_DEV_LANCE 0 102 #define IOASIC_DEV_SCC0 1 103 #define IOASIC_DEV_SCC1 2 104 #define IOASIC_DEV_ISDN 3 105 106 #define IOASIC_DEV_BOGUS -1 107 108 #define IOASIC_NCOOKIES 4 109 110 struct ioasic_dev ioasic_devs[] = { 111 { "PMAD-BA ", IOASIC_SLOT_3_START, C(IOASIC_DEV_LANCE), 112 IOASIC_INTR_LANCE, }, 113 { "z8530 ", IOASIC_SLOT_4_START, C(IOASIC_DEV_SCC0), 114 IOASIC_INTR_SCC_0, }, 115 { "z8530 ", IOASIC_SLOT_6_START, C(IOASIC_DEV_SCC1), 116 IOASIC_INTR_SCC_1, }, 117 { "TOY_RTC ", IOASIC_SLOT_8_START, C(IOASIC_DEV_BOGUS), 118 0, }, 119 { "AMD79c30", IOASIC_SLOT_9_START, C(IOASIC_DEV_ISDN), 120 IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD, }, 121 }; 122 int ioasic_ndevs = sizeof(ioasic_devs) / sizeof(ioasic_devs[0]); 123 124 struct ioasicintr { 125 int (*iai_func) __P((void *)); 126 void *iai_arg; 127 struct evcnt iai_evcnt; 128 } ioasicintrs[IOASIC_NCOOKIES]; 129 130 tc_addr_t ioasic_base; /* XXX XXX XXX */ 131 132 /* There can be only one. */ 133 int ioasicfound; 134 135 int 136 ioasicmatch(parent, cfdata, aux) 137 struct device *parent; 138 struct cfdata *cfdata; 139 void *aux; 140 { 141 struct tc_attach_args *ta = aux; 142 143 /* Make sure that we're looking for this type of device. */ 144 if (strncmp("FLAMG-IO", ta->ta_modname, TC_ROM_LLEN)) 145 return (0); 146 147 /* Check that it can actually exist. */ 148 if ((cputype != ST_DEC_3000_500) && (cputype != ST_DEC_3000_300)) 149 panic("ioasicmatch: how did we get here?"); 150 151 if (ioasicfound) 152 return (0); 153 154 return (1); 155 } 156 157 void 158 ioasicattach(parent, self, aux) 159 struct device *parent, *self; 160 void *aux; 161 { 162 struct ioasic_softc *sc = (struct ioasic_softc *)self; 163 struct tc_attach_args *ta = aux; 164 #ifdef DEC_3000_300 165 u_long ssr; 166 #endif 167 u_long i, imsk; 168 const struct evcnt *pevcnt; 169 char *cp; 170 171 ioasicfound = 1; 172 173 sc->sc_bst = ta->ta_memt; 174 if (bus_space_map(ta->ta_memt, ta->ta_addr, 175 0x400000, 0, &sc->sc_bsh)) { 176 printf("%s: unable to map device\n", sc->sc_dv.dv_xname); 177 return; 178 } 179 sc->sc_dmat = ta->ta_dmat; 180 181 ioasic_base = sc->sc_base = ta->ta_addr; /* XXX XXX XXX */ 182 183 #ifdef DEC_3000_300 184 if (cputype == ST_DEC_3000_300) { 185 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 186 ssr |= IOASIC_CSR_FASTMODE; 187 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 188 printf(": slow mode\n"); 189 } else 190 #endif 191 printf(": fast mode\n"); 192 193 /* 194 * Turn off all device interrupt bits. 195 * (This does _not_ include 3000/300 TC option slot bits. 196 */ 197 imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK); 198 for (i = 0; i < ioasic_ndevs; i++) 199 imsk &= ~ioasic_devs[i].iad_intrbits; 200 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk); 201 202 /* 203 * Set up interrupt handlers. 204 */ 205 pevcnt = tc_intr_evcnt(parent, ta->ta_cookie); 206 for (i = 0; i < IOASIC_NCOOKIES; i++) { 207 ioasicintrs[i].iai_func = ioasic_intrnull; 208 ioasicintrs[i].iai_arg = (void *)i; 209 210 cp = malloc(12, M_DEVBUF, M_NOWAIT); 211 if (cp == NULL) 212 panic("ioasicattach"); 213 sprintf(cp, "slot %lu", i); 214 evcnt_attach_dynamic(&ioasicintrs[i].iai_evcnt, 215 EVCNT_TYPE_INTR, pevcnt, self->dv_xname, cp); 216 } 217 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_NONE, ioasic_intr, sc); 218 219 /* 220 * Try to configure each device. 221 */ 222 ioasic_attach_devs(sc, ioasic_devs, ioasic_ndevs); 223 } 224 225 void 226 ioasic_intr_establish(ioa, cookie, level, func, arg) 227 struct device *ioa; 228 void *cookie, *arg; 229 tc_intrlevel_t level; 230 int (*func) __P((void *)); 231 { 232 struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0]; 233 u_long dev, i, imsk; 234 235 dev = (u_long)cookie; 236 #ifdef DIAGNOSTIC 237 /* XXX check cookie. */ 238 #endif 239 240 if (ioasicintrs[dev].iai_func != ioasic_intrnull) 241 panic("ioasic_intr_establish: cookie %lu twice", dev); 242 243 ioasicintrs[dev].iai_func = func; 244 ioasicintrs[dev].iai_arg = arg; 245 246 /* Enable interrupts for the device. */ 247 for (i = 0; i < ioasic_ndevs; i++) 248 if (ioasic_devs[i].iad_cookie == cookie) 249 break; 250 if (i == ioasic_ndevs) 251 panic("ioasic_intr_establish: invalid cookie."); 252 253 imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK); 254 imsk |= ioasic_devs[i].iad_intrbits; 255 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk); 256 } 257 258 void 259 ioasic_intr_disestablish(ioa, cookie) 260 struct device *ioa; 261 void *cookie; 262 { 263 struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0]; 264 u_long dev, i, imsk; 265 266 dev = (u_long)cookie; 267 #ifdef DIAGNOSTIC 268 /* XXX check cookie. */ 269 #endif 270 271 if (ioasicintrs[dev].iai_func == ioasic_intrnull) 272 panic("ioasic_intr_disestablish: cookie %lu missing intr", dev); 273 274 /* Enable interrupts for the device. */ 275 for (i = 0; i < ioasic_ndevs; i++) 276 if (ioasic_devs[i].iad_cookie == cookie) 277 break; 278 if (i == ioasic_ndevs) 279 panic("ioasic_intr_disestablish: invalid cookie."); 280 281 imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK); 282 imsk &= ~ioasic_devs[i].iad_intrbits; 283 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk); 284 285 ioasicintrs[dev].iai_func = ioasic_intrnull; 286 ioasicintrs[dev].iai_arg = (void *)dev; 287 } 288 289 int 290 ioasic_intrnull(val) 291 void *val; 292 { 293 294 panic("ioasic_intrnull: uncaught IOASIC intr for cookie %ld\n", 295 (u_long)val); 296 } 297 298 /* 299 * ASIC interrupt handler. 300 */ 301 int 302 ioasic_intr(val) 303 void *val; 304 { 305 register struct ioasic_softc *sc = val; 306 register int ifound; 307 int gifound; 308 u_int32_t sir, osir; 309 310 gifound = 0; 311 do { 312 ifound = 0; 313 tc_syncbus(); 314 315 osir = sir = 316 bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR); 317 318 #define INCRINTRCNT(slot) ioasicintrs[slot].iai_evcnt.ev_count++ 319 320 /* XXX DUPLICATION OF INTERRUPT BIT INFORMATION... */ 321 #define CHECKINTR(slot, bits, clear) \ 322 if (sir & (bits)) { \ 323 ifound = 1; \ 324 INCRINTRCNT(slot); \ 325 (*ioasicintrs[slot].iai_func) \ 326 (ioasicintrs[slot].iai_arg); \ 327 if (clear) \ 328 sir &= ~(bits); \ 329 } 330 CHECKINTR(IOASIC_DEV_SCC0, IOASIC_INTR_SCC_0, 0); 331 CHECKINTR(IOASIC_DEV_SCC1, IOASIC_INTR_SCC_1, 0); 332 CHECKINTR(IOASIC_DEV_LANCE, IOASIC_INTR_LANCE, 0); 333 CHECKINTR(IOASIC_DEV_ISDN, IOASIC_INTR_ISDN_TXLOAD | 334 IOASIC_INTR_ISDN_RXLOAD | IOASIC_INTR_ISDN_OVRUN, 1); 335 336 if (sir != osir) 337 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 338 IOASIC_INTR, sir); 339 340 gifound |= ifound; 341 } while (ifound); 342 343 return (gifound); 344 } 345