shared_intr.c revision 1.1 1 /* $NetBSD: shared_intr.c,v 1.1 1996/11/17 02:03:08 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1996 Carnegie-Mellon University.
5 * All rights reserved.
6 *
7 * Authors: Chris G. Demetriou
8 *
9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
14 *
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 *
19 * Carnegie Mellon requests users of this software to return to
20 *
21 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
25 *
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
28 */
29
30 /*
31 * Common shared-interrupt-line functionality.
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/syslog.h>
38 #include <sys/queue.h>
39
40 #include <machine/intr.h>
41
42 extern int cold;
43
44 static const char *intr_typename __P((int));
45
46 static const char *
47 intr_typename(type)
48 int type;
49 {
50
51 switch (type) {
52 case IST_UNUSABLE:
53 return ("disabled");
54 case IST_NONE:
55 return ("none");
56 case IST_PULSE:
57 return ("pulsed");
58 case IST_EDGE:
59 return ("edge-triggered");
60 case IST_LEVEL:
61 return ("level-triggered");
62 }
63 panic("intr_typename: unknown type %d", type);
64 }
65
66 struct alpha_shared_intr *
67 alpha_shared_intr_alloc(n)
68 unsigned int n;
69 {
70 struct alpha_shared_intr *intr;
71 unsigned int i;
72
73 intr = malloc(n * sizeof (struct alpha_shared_intr), M_DEVBUF,
74 cold ? M_NOWAIT : M_WAITOK);
75 if (intr == NULL)
76 panic("alpha_shared_intr_alloc: couldn't malloc intr");
77
78 for (i = 0; i < n; i++) {
79 TAILQ_INIT(&intr[i].intr_q);
80 intr[i].intr_sharetype = IST_NONE;
81 intr[i].intr_dfltsharetype = IST_NONE;
82 intr[i].intr_nstrays = 0;
83 intr[i].intr_maxstrays = 5;
84 }
85
86 return (intr);
87 }
88
89 int
90 alpha_shared_intr_dispatch(intr, num)
91 struct alpha_shared_intr *intr;
92 unsigned int num;
93 {
94 struct alpha_shared_intrhand *ih;
95 int rv, handled;
96
97 ih = intr[num].intr_q.tqh_first;
98 handled = 0;
99 while (ih != NULL) {
100
101 /*
102 * The handler returns one of three values:
103 * 0: This interrupt wasn't for me.
104 * 1: This interrupt was for me.
105 * -1: This interrupt might have been for me, but I can't say
106 * for sure.
107 */
108 rv = (*ih->ih_fn)(ih->ih_arg);
109
110 handled = handled || (rv != 0);
111 ih = ih->ih_q.tqe_next;
112 }
113
114 return (handled);
115 }
116
117 void *
118 alpha_shared_intr_establish(intr, num, type, level, fn, arg, basename)
119 struct alpha_shared_intr *intr;
120 unsigned int num;
121 int type, level;
122 int (*fn) __P((void *));
123 void *arg;
124 const char *basename;
125 {
126 struct alpha_shared_intrhand *ih;
127
128 if (intr[num].intr_sharetype == IST_UNUSABLE) {
129 printf("alpha_shared_intr_establish: %s %d: unusable\n",
130 basename, num);
131 return NULL;
132 }
133
134 /* no point in sleeping unless someone can free memory. */
135 ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
136 if (ih == NULL)
137 panic("alpha_shared_intr_establish: can't malloc intrhand");
138
139 #ifdef DIAGNOSTIC
140 if (type == IST_NONE)
141 panic("alpha_shared_intr_establish: bogus type");
142 #endif
143
144 switch (intr[num].intr_sharetype) {
145 case IST_EDGE:
146 case IST_LEVEL:
147 if (type == intr[num].intr_sharetype)
148 break;
149 case IST_PULSE:
150 if (type != IST_NONE) {
151 if (intr[num].intr_q.tqh_first == NULL) {
152 printf("alpha_shared_intr_establish: %s %d: warning: using %s on %s\n",
153 basename, num, intr_typename(type),
154 intr_typename(intr[num].intr_sharetype));
155 type = intr[num].intr_sharetype;
156 } else {
157 panic("alpha_shared_intr_establish: %s %d: can't share %s with %s",
158 basename, num, intr_typename(type),
159 intr_typename(intr[num].intr_sharetype));
160 }
161 }
162 break;
163
164 case IST_NONE:
165 /* not currently used; safe */
166 break;
167 }
168
169 ih->ih_fn = fn;
170 ih->ih_arg = arg;
171 ih->ih_level = level;
172
173 intr[num].intr_sharetype = type;
174 TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q);
175
176 return (ih);
177 }
178
179 int
180 alpha_shared_intr_get_sharetype(intr, num)
181 struct alpha_shared_intr *intr;
182 unsigned int num;
183 {
184
185 return (intr[num].intr_sharetype);
186 }
187
188 int
189 alpha_shared_intr_isactive(intr, num)
190 struct alpha_shared_intr *intr;
191 unsigned int num;
192 {
193
194 return (intr[num].intr_q.tqh_first != NULL);
195 }
196
197 void
198 alpha_shared_intr_set_dfltsharetype(intr, num, newdfltsharetype)
199 struct alpha_shared_intr *intr;
200 unsigned int num;
201 int newdfltsharetype;
202 {
203
204 #ifdef DIAGNOSTIC
205 if (alpha_shared_intr_isactive(intr, num))
206 panic("alpha_shared_intr_set_dfltsharetype on active intr");
207 #endif
208
209 intr[num].intr_dfltsharetype = newdfltsharetype;
210 intr[num].intr_sharetype = intr[num].intr_dfltsharetype;
211 }
212
213 void
214 alpha_shared_intr_set_maxstrays(intr, num, newmaxstrays)
215 struct alpha_shared_intr *intr;
216 unsigned int num;
217 int newmaxstrays;
218 {
219
220 #ifdef DIAGNOSTIC
221 if (alpha_shared_intr_isactive(intr, num))
222 panic("alpha_shared_intr_set_maxstrays on active intr");
223 #endif
224
225 intr[num].intr_maxstrays = newmaxstrays;
226 intr[num].intr_nstrays = 0;
227 }
228
229 void
230 alpha_shared_intr_stray(intr, num, basename)
231 struct alpha_shared_intr *intr;
232 unsigned int num;
233 const char *basename;
234 {
235
236 intr[num].intr_nstrays++;
237 if (intr[num].intr_nstrays <= intr[num].intr_maxstrays)
238 log(LOG_ERR, "stray %s %d%s\n", basename, num,
239 intr[num].intr_nstrays >= intr[num].intr_maxstrays ?
240 "; stopped logging" : "");
241 }
242