xref: /openbsd/sys/arch/alpha/include/intr.h (revision 1684d4b8)
1 /* $OpenBSD: intr.h,v 1.50 2024/05/17 20:07:33 miod 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_MPFLOOR	IPL_AUDIO
129 
130 #define	IPL_MPSAFE	0	/* no "mpsafe" interrupts */
131 
132 #define	IST_UNUSABLE	-1	/* interrupt cannot be used */
133 #define	IST_NONE	0	/* none (dummy) */
134 #define	IST_PULSE	1	/* pulsed */
135 #define	IST_EDGE	2	/* edge-triggered */
136 #define	IST_LEVEL	3	/* level-triggered */
137 
138 #define SI_SOFT		0
139 #define SI_SOFTCLOCK	1
140 #define SI_SOFTNET	2
141 #define SI_SOFTSERIAL	3
142 #define	SI_NSOFT	4
143 
144 #ifdef	_KERNEL
145 
146 void intr_barrier(void *);
147 
148 /* SPL asserts */
149 #ifdef DIAGNOSTIC
150 /*
151  * Although this function is implemented in MI code, it must be in this MD
152  * header because we don't want this header to include MI includes.
153  */
154 void splassert_fail(int, int, const char *);
155 extern int splassert_ctl;
156 void splassert_check(int, const char *);
157 #define	splassert(__wantipl)						\
158 	do {								\
159 		if (splassert_ctl > 0) {				\
160 			splassert_check(__wantipl, __func__);		\
161 		}							\
162 	} while (0)
163 #define	splsoftassert(wantipl)	splassert(IPL_SOFTINT)
164 #else
165 #define	splassert(wantipl)	do { /* nothing */ } while (0)
166 #define	splsoftassert(wantipl)	do { /* nothing */ } while (0)
167 #endif
168 
169 /* IPL-lowering/restoring macros */
170 #define splx(s)								\
171     ((s) == ALPHA_PSL_IPL_0 ? spl0() : (int)alpha_pal_swpipl(s))
172 
173 /* IPL-raising functions/macros */
174 int splraise(int);
175 int spl0(void);
176 
177 #define splsoft()		splraise(IPL_SOFTINT)
178 #define splsoftserial()		splsoft()
179 #define splsoftclock()		splsoft()
180 #define splsoftnet()		splsoft()
181 #define splnet()		splraise(IPL_NET)
182 #define splbio()		splraise(IPL_BIO)
183 #define spltty()		splraise(IPL_TTY)
184 #define splserial()		splraise(IPL_SERIAL)
185 #define splaudio()		splraise(IPL_AUDIO)
186 #define splvm()			splraise(IPL_VM)
187 #define splclock()		splraise(IPL_CLOCK)
188 #define splstatclock()		splraise(IPL_CLOCK)
189 #define splsched()		splraise(IPL_SCHED)
190 #define splipi()		splraise(IPL_IPI)
191 #define splhigh()		splraise(IPL_HIGH)
192 
193 /*
194  * Interprocessor interrupts.  In order how we want them processed.
195  */
196 #define	ALPHA_IPI_HALT			(1UL << 0)
197 #define	ALPHA_IPI_SHOOTDOWN		(1UL << 1)
198 #define	ALPHA_IPI_IMB			(1UL << 2)
199 #define	ALPHA_IPI_AST			(1UL << 3)
200 #define	ALPHA_IPI_SYNCH_FPU		(1UL << 4)
201 #define	ALPHA_IPI_DISCARD_FPU		(1UL << 5)
202 #define	ALPHA_IPI_PAUSE			(1UL << 6)
203 
204 #define	ALPHA_NIPIS		7	/* must not exceed 64 */
205 
206 struct cpu_info;
207 struct trapframe;
208 
209 void	alpha_ipi_process(struct cpu_info *, struct trapframe *);
210 #ifdef MP_LOCKDEBUG
211 void	alpha_ipi_process_with_frame(struct cpu_info *);
212 #else
213 #define	alpha_ipi_process_with_frame(ci) alpha_ipi_process((ci), NULL)
214 #endif
215 void	alpha_send_ipi(unsigned long, unsigned long);
216 void	alpha_broadcast_ipi(unsigned long);
217 void	alpha_multicast_ipi(unsigned long, unsigned long);
218 
219 /*
220  * Alpha shared-interrupt-line common code.
221  */
222 
223 struct alpha_shared_intrhand {
224 	TAILQ_ENTRY(alpha_shared_intrhand)
225 		ih_q;
226 	struct alpha_shared_intr *ih_intrhead;
227 	int	(*ih_fn)(void *);
228 	void	*ih_arg;
229 	int	ih_level;
230 	unsigned int ih_num;
231 	struct evcount ih_count;
232 };
233 
234 struct alpha_shared_intr {
235 	TAILQ_HEAD(,alpha_shared_intrhand)
236 		intr_q;
237 	void	*intr_private;
238 	int	intr_sharetype;
239 	int	intr_dfltsharetype;
240 	int	intr_nstrays;
241 	int	intr_maxstrays;
242 };
243 
244 #define	ALPHA_SHARED_INTR_DISABLE(asi, num)				\
245 	((asi)[num].intr_maxstrays != 0 &&				\
246 	 (asi)[num].intr_nstrays == (asi)[num].intr_maxstrays)
247 
248 extern int	intr_shared_edge;
249 
250 /*
251  * simulated software interrupt register
252  */
253 extern unsigned long ssir;
254 
255 #define	setsoft(x)	atomic_setbits_ulong(&ssir, 1 << (x))
256 
257 struct alpha_soft_intrhand {
258 	TAILQ_ENTRY(alpha_soft_intrhand)
259 		sih_q;
260 	struct alpha_soft_intr *sih_intrhead;
261 	void	(*sih_fn)(void *);
262 	void	*sih_arg;
263 	int	sih_pending;
264 };
265 
266 struct alpha_soft_intr {
267 	TAILQ_HEAD(, alpha_soft_intrhand)
268 		softintr_q;
269 	struct mutex softintr_mtx;
270 	unsigned long softintr_siq;
271 };
272 
273 void	 softintr_disestablish(void *);
274 void	 softintr_dispatch(void);
275 void	*softintr_establish(int, void (*)(void *), void *);
276 void	 softintr_init(void);
277 void	 softintr_schedule(void *);
278 
279 struct alpha_shared_intr *alpha_shared_intr_alloc(unsigned int);
280 int	alpha_shared_intr_dispatch(struct alpha_shared_intr *,
281 	    unsigned int);
282 void	*alpha_shared_intr_establish(struct alpha_shared_intr *,
283 	    unsigned int, int, int, int (*)(void *), void *, const char *);
284 void	alpha_shared_intr_disestablish(struct alpha_shared_intr *, void *);
285 int	alpha_shared_intr_get_sharetype(struct alpha_shared_intr *,
286 	    unsigned int);
287 int	alpha_shared_intr_isactive(struct alpha_shared_intr *,
288 	    unsigned int);
289 int	alpha_shared_intr_firstactive(struct alpha_shared_intr *,
290 	    unsigned int);
291 void	alpha_shared_intr_set_dfltsharetype(struct alpha_shared_intr *,
292 	    unsigned int, int);
293 void	alpha_shared_intr_set_maxstrays(struct alpha_shared_intr *,
294 	    unsigned int, int);
295 void	alpha_shared_intr_reset_strays(struct alpha_shared_intr *,
296 	    unsigned int);
297 void	alpha_shared_intr_stray(struct alpha_shared_intr *, unsigned int,
298 	    const char *);
299 void	alpha_shared_intr_set_private(struct alpha_shared_intr *,
300 	    unsigned int, void *);
301 void	*alpha_shared_intr_get_private(struct alpha_shared_intr *,
302 	    unsigned int);
303 
304 extern struct scbvec scb_iovectab[];
305 
306 void	scb_init(void);
307 void	scb_set(u_long, void (*)(void *, u_long), void *);
308 u_long	scb_alloc(void (*)(void *, u_long), void *);
309 void	scb_free(u_long);
310 
311 #define	SCB_ALLOC_FAILED	((u_long) -1)
312 
313 #endif /* _KERNEL */
314 #endif /* ! _MACHINE_INTR_H_ */
315