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