1 /* $NetBSD: intreg.c,v 1.4 1996/10/30 00:24:43 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 /* Validate the given address. */ 97 if (ca->ca_paddr != OBIO_INTERREG) 98 return (0); 99 100 return (1); 101 } 102 103 104 static void 105 intreg_attach(parent, self, args) 106 struct device *parent; 107 struct device *self; 108 void *args; 109 { 110 struct intreg_softc *sc = (void *)self; 111 struct cfdata *cf = self->dv_cfdata; 112 113 printf("\n"); 114 115 sc->sc_reg = interrupt_reg; 116 117 /* Install handler for our "soft" interrupt. */ 118 isr_add_autovect(soft1intr, (void *)sc, 1); 119 } 120 121 122 /* 123 * Level 1 software interrupt. 124 * Possible reasons: 125 * Network software interrupt 126 * Soft clock interrupt 127 */ 128 int soft1intr(arg) 129 void *arg; 130 { 131 union sun3sir sir; 132 int n, s; 133 134 s = splhigh(); 135 sir.sir_any = sun3sir.sir_any; 136 sun3sir.sir_any = 0; 137 isr_soft_clear(1); 138 splx(s); 139 140 if (sir.sir_any) { 141 cnt.v_soft++; 142 if (sir.sir_which[SIR_NET]) { 143 sir.sir_which[SIR_NET] = 0; 144 netintr(); 145 } 146 if (sir.sir_which[SIR_CLOCK]) { 147 sir.sir_which[SIR_CLOCK] = 0; 148 softclock(); 149 } 150 if (sir.sir_which[SIR_SPARE2]) { 151 sir.sir_which[SIR_SPARE2] = 0; 152 /* spare2intr(); */ 153 } 154 if (sir.sir_which[SIR_SPARE3]) { 155 sir.sir_which[SIR_SPARE3] = 0; 156 /* spare3intr(); */ 157 } 158 return (1); 159 } 160 return(0); 161 } 162 163 164 static int isr_soft_pending; 165 void isr_soft_request(level) 166 int level; 167 { 168 u_char bit, reg_val; 169 int s; 170 171 if ((level < 1) || (level > 3)) 172 panic("isr_soft_request"); 173 174 bit = 1 << level; 175 176 /* XXX - Should do this in the callers... */ 177 if (isr_soft_pending & bit) 178 return; 179 180 s = splhigh(); 181 isr_soft_pending |= bit; 182 reg_val = *interrupt_reg; 183 *interrupt_reg &= ~IREG_ALL_ENAB; 184 185 *interrupt_reg |= bit; 186 *interrupt_reg |= IREG_ALL_ENAB; 187 splx(s); 188 } 189 190 void isr_soft_clear(level) 191 int level; 192 { 193 u_char bit, reg_val; 194 int s; 195 196 if ((level < 1) || (level > 3)) 197 panic("isr_soft_clear"); 198 199 bit = 1 << level; 200 201 s = splhigh(); 202 isr_soft_pending &= ~bit; 203 reg_val = *interrupt_reg; 204 *interrupt_reg &= ~IREG_ALL_ENAB; 205 206 *interrupt_reg &= ~bit; 207 *interrupt_reg |= IREG_ALL_ENAB; 208 splx(s); 209 } 210 211