xref: /openbsd-src/sys/arch/alpha/include/intr.h (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* $OpenBSD: intr.h,v 1.46 2016/06/13 01:26:14 dlg Exp $ */
2 /* $NetBSD: intr.h,v 1.26 2000/06/03 20:47:41 thorpej Exp $ */
3 
4 /*-
5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
35  * Copyright (c) 1996 Carnegie-Mellon University.
36  * All rights reserved.
37  *
38  * Author: Chris G. Demetriou
39  *
40  * Permission to use, copy, modify and distribute this software and
41  * its documentation is hereby granted, provided that both the copyright
42  * notice and this permission notice appear in all copies of the
43  * software, derivative works or modified versions, and any portions
44  * thereof, and that both notices appear in supporting documentation.
45  *
46  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
48  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49  *
50  * Carnegie Mellon requests users of this software to return to
51  *
52  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
53  *  School of Computer Science
54  *  Carnegie Mellon University
55  *  Pittsburgh PA 15213-3890
56  *
57  * any improvements or extensions that they make and grant Carnegie the
58  * rights to redistribute these changes.
59  */
60 
61 #ifndef _MACHINE_INTR_H_
62 #define _MACHINE_INTR_H_
63 
64 #include <sys/evcount.h>
65 #include <sys/mutex.h>
66 #include <sys/queue.h>
67 #include <machine/atomic.h>
68 
69 /*
70  * The Alpha System Control Block.  This is 8k long, and you get
71  * 16 bytes per vector (i.e. the vector numbers are spaced 16
72  * apart).
73  *
74  * This is sort of a "shadow" SCB -- rather than the CPU jumping
75  * to (SCBaddr + (16 * vector)), like it does on the VAX, we get
76  * a vector number in a1.  We use the SCB to look up a routine/arg
77  * and jump to it.
78  *
79  * Since we use the SCB only for I/O interrupts, we make it shorter
80  * than normal, starting it at vector 0x800 (the start of the I/O
81  * interrupt vectors).
82  */
83 #define	SCB_IOVECBASE	0x0800
84 #define	SCB_VECSIZE	0x0010
85 #define	SCB_SIZE	0x2000
86 
87 #define	SCB_VECTOIDX(x)	((x) >> 4)
88 #define	SCB_IDXTOVEC(x)	((x) << 4)
89 
90 #define	SCB_NIOVECS	SCB_VECTOIDX(SCB_SIZE - SCB_IOVECBASE)
91 
92 struct scbvec {
93 	void	(*scb_func)(void *, u_long);
94 	void	*scb_arg;
95 };
96 
97 /*
98  * Alpha interrupts come in at one of 4 levels:
99  *
100  *	software interrupt level
101  *	i/o level 1
102  *	i/o level 2
103  *	clock level
104  *
105  * However, since we do not have any way to know which hardware
106  * level a particular i/o interrupt comes in on, we have to
107  * whittle it down to 3.
108  */
109 
110 #define	IPL_NONE	ALPHA_PSL_IPL_0
111 #define	IPL_SOFTINT	ALPHA_PSL_IPL_SOFT
112 #define	IPL_BIO		ALPHA_PSL_IPL_IO
113 #define	IPL_NET		ALPHA_PSL_IPL_IO
114 #define	IPL_TTY		ALPHA_PSL_IPL_IO
115 #define	IPL_SERIAL	ALPHA_PSL_IPL_IO
116 #define	IPL_AUDIO	ALPHA_PSL_IPL_IO
117 #define	IPL_VM		ALPHA_PSL_IPL_IO
118 #define	IPL_CLOCK	ALPHA_PSL_IPL_CLOCK
119 #define	IPL_SCHED	ALPHA_PSL_IPL_CLOCK
120 #define	IPL_IPI		ALPHA_PSL_IPL_HIGH	/* occur on _CLOCK, though */
121 #define	IPL_HIGH	ALPHA_PSL_IPL_HIGH
122 
123 #define	IPL_SOFTSERIAL	0	/* serial software interrupts */
124 #define	IPL_SOFTCLOCK	1	/* clock software interrupts */
125 #define	IPL_SOFTNET	2	/* network software interrupts */
126 #define	IPL_SOFT	3	/* other software interrupts */
127 
128 #define	IPL_MPSAFE	0	/* no "mpsafe" interrupts */
129 
130 #define	IST_UNUSABLE	-1	/* interrupt cannot be used */
131 #define	IST_NONE	0	/* none (dummy) */
132 #define	IST_PULSE	1	/* pulsed */
133 #define	IST_EDGE	2	/* edge-triggered */
134 #define	IST_LEVEL	3	/* level-triggered */
135 
136 #define SI_SOFT		0
137 #define SI_SOFTCLOCK	1
138 #define SI_SOFTNET	2
139 #define SI_SOFTSERIAL	3
140 #define	SI_NSOFT	4
141 
142 #ifdef	_KERNEL
143 
144 void intr_barrier(void *);
145 
146 /* SPL asserts */
147 #ifdef DIAGNOSTIC
148 /*
149  * Although this function is implemented in MI code, it must be in this MD
150  * header because we don't want this header to include MI includes.
151  */
152 void splassert_fail(int, int, const char *);
153 extern int splassert_ctl;
154 void splassert_check(int, const char *);
155 #define	splassert(__wantipl)						\
156 	do {								\
157 		if (splassert_ctl > 0) {				\
158 			splassert_check(__wantipl, __func__);		\
159 		}							\
160 	} while (0)
161 #define	splsoftassert(wantipl)	splassert(IPL_SOFTINT)
162 #else
163 #define	splassert(wantipl)	do { /* nothing */ } while (0)
164 #define	splsoftassert(wantipl)	do { /* nothing */ } while (0)
165 #endif
166 
167 /* IPL-lowering/restoring macros */
168 #define splx(s)								\
169     ((s) == ALPHA_PSL_IPL_0 ? spl0() : alpha_pal_swpipl(s))
170 
171 /* IPL-raising functions/macros */
172 int splraise(int);
173 
174 #define splsoft()		splraise(IPL_SOFTINT)
175 #define splsoftserial()		splsoft()
176 #define splsoftclock()		splsoft()
177 #define splsoftnet()		splsoft()
178 #define splnet()		splraise(IPL_NET)
179 #define splbio()		splraise(IPL_BIO)
180 #define spltty()		splraise(IPL_TTY)
181 #define splserial()		splraise(IPL_SERIAL)
182 #define splaudio()		splraise(IPL_AUDIO)
183 #define splvm()			splraise(IPL_VM)
184 #define splclock()		splraise(IPL_CLOCK)
185 #define splstatclock()		splraise(IPL_CLOCK)
186 #define splsched()		splraise(IPL_SCHED)
187 #define splipi()		splraise(IPL_IPI)
188 #define splhigh()		splraise(IPL_HIGH)
189 
190 #define spllock()		splhigh()
191 
192 /*
193  * Interprocessor interrupts.  In order how we want them processed.
194  */
195 #define	ALPHA_IPI_HALT			(1UL << 0)
196 #define	ALPHA_IPI_SHOOTDOWN		(1UL << 1)
197 #define	ALPHA_IPI_IMB			(1UL << 2)
198 #define	ALPHA_IPI_AST			(1UL << 3)
199 #define	ALPHA_IPI_SYNCH_FPU		(1UL << 4)
200 #define	ALPHA_IPI_DISCARD_FPU		(1UL << 5)
201 #define	ALPHA_IPI_PAUSE			(1UL << 6)
202 
203 #define	ALPHA_NIPIS		7	/* must not exceed 64 */
204 
205 struct cpu_info;
206 struct trapframe;
207 
208 void	alpha_ipi_process(struct cpu_info *, struct trapframe *);
209 #ifdef MP_LOCKDEBUG
210 void	alpha_ipi_process_with_frame(struct cpu_info *);
211 #else
212 #define	alpha_ipi_process_with_frame(ci) alpha_ipi_process((ci), NULL)
213 #endif
214 void	alpha_send_ipi(unsigned long, unsigned long);
215 void	alpha_broadcast_ipi(unsigned long);
216 void	alpha_multicast_ipi(unsigned long, unsigned long);
217 
218 /*
219  * Alpha shared-interrupt-line common code.
220  */
221 
222 struct alpha_shared_intrhand {
223 	TAILQ_ENTRY(alpha_shared_intrhand)
224 		ih_q;
225 	struct alpha_shared_intr *ih_intrhead;
226 	int	(*ih_fn)(void *);
227 	void	*ih_arg;
228 	int	ih_level;
229 	unsigned int ih_num;
230 	struct evcount ih_count;
231 };
232 
233 struct alpha_shared_intr {
234 	TAILQ_HEAD(,alpha_shared_intrhand)
235 		intr_q;
236 	void	*intr_private;
237 	int	intr_sharetype;
238 	int	intr_dfltsharetype;
239 	int	intr_nstrays;
240 	int	intr_maxstrays;
241 };
242 
243 #define	ALPHA_SHARED_INTR_DISABLE(asi, num)				\
244 	((asi)[num].intr_maxstrays != 0 &&				\
245 	 (asi)[num].intr_nstrays == (asi)[num].intr_maxstrays)
246 
247 extern int	intr_shared_edge;
248 
249 /*
250  * simulated software interrupt register
251  */
252 extern unsigned long ssir;
253 
254 #define	setsoft(x)	atomic_setbits_ulong(&ssir, 1 << (x))
255 
256 struct alpha_soft_intrhand {
257 	TAILQ_ENTRY(alpha_soft_intrhand)
258 		sih_q;
259 	struct alpha_soft_intr *sih_intrhead;
260 	void	(*sih_fn)(void *);
261 	void	*sih_arg;
262 	int	sih_pending;
263 };
264 
265 struct alpha_soft_intr {
266 	TAILQ_HEAD(, alpha_soft_intrhand)
267 		softintr_q;
268 	struct mutex softintr_mtx;
269 	unsigned long softintr_siq;
270 };
271 
272 void	 softintr_disestablish(void *);
273 void	 softintr_dispatch(void);
274 void	*softintr_establish(int, void (*)(void *), void *);
275 void	 softintr_init(void);
276 void	 softintr_schedule(void *);
277 
278 struct alpha_shared_intr *alpha_shared_intr_alloc(unsigned int);
279 int	alpha_shared_intr_dispatch(struct alpha_shared_intr *,
280 	    unsigned int);
281 void	*alpha_shared_intr_establish(struct alpha_shared_intr *,
282 	    unsigned int, int, int, int (*)(void *), void *, const char *);
283 void	alpha_shared_intr_disestablish(struct alpha_shared_intr *, void *);
284 int	alpha_shared_intr_get_sharetype(struct alpha_shared_intr *,
285 	    unsigned int);
286 int	alpha_shared_intr_isactive(struct alpha_shared_intr *,
287 	    unsigned int);
288 int	alpha_shared_intr_firstactive(struct alpha_shared_intr *,
289 	    unsigned int);
290 void	alpha_shared_intr_set_dfltsharetype(struct alpha_shared_intr *,
291 	    unsigned int, int);
292 void	alpha_shared_intr_set_maxstrays(struct alpha_shared_intr *,
293 	    unsigned int, int);
294 void	alpha_shared_intr_reset_strays(struct alpha_shared_intr *,
295 	    unsigned int);
296 void	alpha_shared_intr_stray(struct alpha_shared_intr *, unsigned int,
297 	    const char *);
298 void	alpha_shared_intr_set_private(struct alpha_shared_intr *,
299 	    unsigned int, void *);
300 void	*alpha_shared_intr_get_private(struct alpha_shared_intr *,
301 	    unsigned int);
302 
303 extern struct scbvec scb_iovectab[];
304 
305 void	scb_init(void);
306 void	scb_set(u_long, void (*)(void *, u_long), void *);
307 u_long	scb_alloc(void (*)(void *, u_long), void *);
308 void	scb_free(u_long);
309 
310 #define	SCB_ALLOC_FAILED	((u_long) -1)
311 
312 #endif /* _KERNEL */
313 #endif /* ! _MACHINE_INTR_H_ */
314