xref: /netbsd-src/sys/arch/sun3/sun3/intreg.c (revision 81b108b45f75f89f1e3ffad9fb6f074e771c0935)
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