kern_intr.c revision 65822
1/*
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/kern/kern_intr.c 65822 2000-09-13 18:33:25Z jhb $
27 *
28 */
29
30
31#include <sys/param.h>
32#include <sys/bus.h>
33#include <sys/rtprio.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36
37#include <machine/ipl.h>
38
39#include <sys/interrupt.h>
40
41struct swilist {
42	swihand_t	*sl_handler;
43	struct swilist	*sl_next;
44};
45
46static struct swilist swilists[NSWI];
47
48void
49register_swi(intr, handler)
50	int intr;
51	swihand_t *handler;
52{
53	struct swilist *slp, *slq;
54	int s;
55
56	if (intr < NHWI || intr >= NHWI + NSWI)
57		panic("register_swi: bad intr %d", intr);
58	if (handler == swi_generic || handler == swi_null)
59		panic("register_swi: bad handler %p", (void *)handler);
60	slp = &swilists[intr - NHWI];
61	s = splhigh();
62	if (ihandlers[intr] == swi_null)
63		ihandlers[intr] = handler;
64	else {
65		if (slp->sl_next == NULL) {
66			slp->sl_handler = ihandlers[intr];
67			ihandlers[intr] = swi_generic;
68		}
69		slq = malloc(sizeof(*slq), M_DEVBUF, M_NOWAIT);
70		if (slq == NULL)
71			panic("register_swi: malloc failed");
72		slq->sl_handler = handler;
73		slq->sl_next = NULL;
74		while (slp->sl_next != NULL)
75			slp = slp->sl_next;
76		slp->sl_next = slq;
77	}
78	splx(s);
79}
80
81void
82swi_dispatcher(intr)
83	int intr;
84{
85	struct swilist *slp;
86
87	slp = &swilists[intr - NHWI];
88	do {
89		(*slp->sl_handler)();
90		slp = slp->sl_next;
91	} while (slp != NULL);
92}
93
94void
95unregister_swi(intr, handler)
96	int intr;
97	swihand_t *handler;
98{
99	struct swilist *slfoundpred, *slp, *slq;
100	int s;
101
102	if (intr < NHWI || intr >= NHWI + NSWI)
103		panic("unregister_swi: bad intr %d", intr);
104	if (handler == swi_generic || handler == swi_null)
105		panic("unregister_swi: bad handler %p", (void *)handler);
106	slp = &swilists[intr - NHWI];
107	s = splhigh();
108	if (ihandlers[intr] == handler)
109		ihandlers[intr] = swi_null;
110	else if (slp->sl_next != NULL) {
111		slfoundpred = NULL;
112		for (slq = slp->sl_next; slq != NULL;
113		    slp = slq, slq = slp->sl_next)
114			if (slq->sl_handler == handler)
115				slfoundpred = slp;
116		slp = &swilists[intr - NHWI];
117		if (slfoundpred != NULL) {
118			slq = slfoundpred->sl_next;
119			slfoundpred->sl_next = slq->sl_next;
120			free(slq, M_DEVBUF);
121		} else if (slp->sl_handler == handler) {
122			slq = slp->sl_next;
123			slp->sl_next = slq->sl_next;
124			slp->sl_handler = slq->sl_handler;
125			free(slq, M_DEVBUF);
126		}
127		if (slp->sl_next == NULL)
128			ihandlers[intr] = slp->sl_handler;
129	}
130	splx(s);
131}
132
133int
134ithread_priority(flags)
135	int flags;
136{
137	int pri;
138
139	switch (flags) {
140	case INTR_TYPE_TTY:             /* keyboard or parallel port */
141		pri = PI_TTYLOW;
142		break;
143	case (INTR_TYPE_TTY | INTR_FAST): /* sio */
144		pri = PI_TTYHIGH;
145		break;
146	case INTR_TYPE_BIO:
147		/*
148		 * XXX We need to refine this.  BSD/OS distinguishes
149		 * between tape and disk priorities.
150		 */
151		pri = PI_DISK;
152		break;
153	case INTR_TYPE_NET:
154		pri = PI_NET;
155		break;
156	case INTR_TYPE_CAM:
157		pri = PI_DISK;          /* XXX or PI_CAM? */
158		break;
159	case INTR_TYPE_MISC:
160		pri = PI_DULL;          /* don't care */
161		break;
162	/* We didn't specify an interrupt level. */
163	default:
164		panic("ithread_priority: no interrupt type in flags");
165	}
166
167	return pri;
168}
169
170