1 /* $NetBSD: intreg.c,v 1.1 1996/03/26 15:03:11 gwr Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Gordon W. Ross 5 * Copyright (c) 1993 Adam Glass 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Adam Glass. 19 * 4. The name of the authors may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * This handles multiple attach of autovectored interrupts, 36 * and the handy software interrupt request register. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/vmmeter.h> 43 44 #include <machine/autoconf.h> 45 #include <machine/cpu.h> 46 #include <machine/mon.h> 47 #include <machine/obio.h> 48 #include <machine/isr.h> 49 50 #include "interreg.h" 51 52 struct intreg_softc { 53 struct device sc_dev; 54 volatile u_char *sc_reg; 55 }; 56 57 static int intreg_match __P((struct device *, void *vcf, void *args)); 58 static void intreg_attach __P((struct device *, struct device *, void *)); 59 static int soft1intr(); 60 61 struct cfattach intreg_ca = { 62 sizeof(struct intreg_softc), intreg_match, intreg_attach 63 }; 64 65 struct cfdriver intreg_cd = { 66 NULL, "intreg", DV_DULL 67 }; 68 69 volatile u_char *interrupt_reg; 70 71 72 /* called early (by internal_configure) */ 73 void intreg_init() 74 { 75 interrupt_reg = obio_find_mapping(OBIO_INTERREG, 1); 76 if (!interrupt_reg) 77 mon_panic("interrupt reg VA not found\n"); 78 /* Turn off all interrupts until clock_attach */ 79 *interrupt_reg = 0; 80 } 81 82 83 static int 84 intreg_match(parent, vcf, args) 85 struct device *parent; 86 void *vcf, *args; 87 { 88 struct cfdata *cf = vcf; 89 struct confargs *ca = args; 90 int pa; 91 92 /* This driver only supports one unit. */ 93 if (cf->cf_unit != 0) 94 return (0); 95 96 if ((pa = cf->cf_paddr) == -1) { 97 /* Use our default PA. */ 98 pa = OBIO_INTERREG; 99 } else { 100 /* Validate the given PA. */ 101 if (pa != OBIO_INTERREG) 102 panic("clock: wrong address"); 103 } 104 if (pa != ca->ca_paddr) 105 return (0); 106 107 return (1); 108 } 109 110 111 static void 112 intreg_attach(parent, self, args) 113 struct device *parent; 114 struct device *self; 115 void *args; 116 { 117 struct intreg_softc *sc = (void *)self; 118 struct cfdata *cf = self->dv_cfdata; 119 120 printf("\n"); 121 122 sc->sc_reg = interrupt_reg; 123 124 /* Install handler for our "soft" interrupt. */ 125 isr_add_autovect(soft1intr, (void *)sc, 1); 126 } 127 128 129 /* 130 * Level 1 software interrupt. 131 * Possible reasons: 132 * Network software interrupt 133 * Soft clock interrupt 134 */ 135 int soft1intr(arg) 136 void *arg; 137 { 138 union sun3sir sir; 139 int n, s; 140 141 s = splhigh(); 142 sir.sir_any = sun3sir.sir_any; 143 sun3sir.sir_any = 0; 144 isr_soft_clear(1); 145 splx(s); 146 147 if (sir.sir_any) { 148 cnt.v_soft++; 149 if (sir.sir_which[SIR_NET]) { 150 sir.sir_which[SIR_NET] = 0; 151 netintr(); 152 } 153 if (sir.sir_which[SIR_CLOCK]) { 154 sir.sir_which[SIR_CLOCK] = 0; 155 softclock(); 156 } 157 if (sir.sir_which[SIR_SPARE2]) { 158 sir.sir_which[SIR_SPARE2] = 0; 159 /* spare2intr(); */ 160 } 161 if (sir.sir_which[SIR_SPARE3]) { 162 sir.sir_which[SIR_SPARE3] = 0; 163 /* spare3intr(); */ 164 } 165 return (1); 166 } 167 return(0); 168 } 169 170 171 static int isr_soft_pending; 172 void isr_soft_request(level) 173 int level; 174 { 175 u_char bit, reg_val; 176 int s; 177 178 if ((level < 1) || (level > 3)) 179 panic("isr_soft_request"); 180 181 bit = 1 << level; 182 183 /* XXX - Should do this in the callers... */ 184 if (isr_soft_pending & bit) 185 return; 186 187 s = splhigh(); 188 isr_soft_pending |= bit; 189 reg_val = *interrupt_reg; 190 *interrupt_reg &= ~IREG_ALL_ENAB; 191 192 *interrupt_reg |= bit; 193 *interrupt_reg |= IREG_ALL_ENAB; 194 splx(s); 195 } 196 197 void isr_soft_clear(level) 198 int level; 199 { 200 u_char bit, reg_val; 201 int s; 202 203 if ((level < 1) || (level > 3)) 204 panic("isr_soft_clear"); 205 206 bit = 1 << level; 207 208 s = splhigh(); 209 isr_soft_pending &= ~bit; 210 reg_val = *interrupt_reg; 211 *interrupt_reg &= ~IREG_ALL_ENAB; 212 213 *interrupt_reg &= ~bit; 214 *interrupt_reg |= IREG_ALL_ENAB; 215 splx(s); 216 } 217 218