xref: /netbsd/sys/arch/mipsco/mipsco/interrupt.c (revision bf9ec67e)
1 /*	$NetBSD: interrupt.c,v 1.1 2001/03/30 23:21:30 wdk Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wayne Knowles
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/malloc.h>
41 
42 #include <uvm/uvm_extern.h>
43 
44 #include <net/netisr.h>			/* Legacy softnet support */
45 
46 #include <machine/intr.h>
47 #include <machine/sysconf.h>
48 
49 struct mipsco_intr softintr_tab[IPL_NSOFT];
50 
51 /* XXX For legacy software interrupts. */
52 struct mipsco_intrhand *softnet_intrhand;
53 
54 u_int32_t ssir;
55 
56 /*
57  * softintr_init:
58  *
59  *	Initialize the software interrupt system.
60  */
61 void
62 softintr_init()
63 {
64 	static const char *softintr_names[] = IPL_SOFTNAMES;
65 	struct mipsco_intr *sip;
66 	int i;
67 
68 	for (i = 0; i < IPL_NSOFT; i++) {
69 		sip = &softintr_tab[i];
70 		sip->intr_ipl = i;
71 		LIST_INIT(&sip->intr_q);
72 		evcnt_attach_dynamic(&sip->ih_evcnt, EVCNT_TYPE_INTR,
73 		    NULL, "soft", softintr_names[i]);
74 	}
75 
76 	/* XXX Establish legacy software interrupt handlers. */
77 	softnet_intrhand = softintr_establish(IPL_SOFTNET,
78 	    (void (*)(void *))netintr, NULL);
79 
80 	KASSERT(softnet_intrhand != NULL);
81 }
82 
83 /*
84  * softintr_dispatch:
85  *
86  *	Process pending software interrupts.
87  *
88  *      Called at splsoft()
89  */
90 void
91 softintr_dispatch()
92 {
93 	struct mipsco_intr *sip;
94 	struct mipsco_intrhand *sih;
95 	u_int32_t n, i, s;
96 
97 	s = splhigh();
98 	n = ssir; ssir = 0;
99 	splx(s);
100 	sip = softintr_tab;
101   	for (i = 0; i < IPL_NSOFT; sip++, i++) {
102 	    if ((n & (1 << i)) == 0)
103 		continue;
104 	    sip->ih_evcnt.ev_count++;
105 
106 	    LIST_FOREACH(sih, &sip->intr_q, ih_q) {
107 		if (sih->ih_pending) {
108 		    uvmexp.softs++;
109 		    sih->ih_pending = 0;
110 		    (*sih->ih_fun)(sih->ih_arg);
111 		}
112 	    }
113 	}
114 }
115 
116 /*
117  * softintr_establish:		[interface]
118  *
119  *	Register a software interrupt handler.
120  */
121 void *
122 softintr_establish(int ipl, void (*func)(void *), void *arg)
123 {
124 	struct mipsco_intr *sip;
125 	struct mipsco_intrhand *sih;
126 	int s;
127 
128 	if (__predict_false(ipl >= IPL_NSOFT || ipl < 0))
129 		panic("softintr_establish");
130 
131 	sip = &softintr_tab[ipl];
132 
133 	sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT);
134 	if (__predict_true(sih != NULL)) {
135 		sih->ih_fun = (void *)func;
136 		sih->ih_arg = arg;
137 		sih->ih_intrhead = sip;
138 		sih->ih_pending = 0;
139 
140 		s = splsoft();
141 		LIST_INSERT_HEAD(&sip->intr_q, sih, ih_q);
142 		splx(s);
143 	}
144 	return (sih);
145 }
146 
147 /*
148  * softintr_disestablish:	[interface]
149  *
150  *	Unregister a software interrupt handler.
151  */
152 void
153 softintr_disestablish(void *arg)
154 {
155 	struct mipsco_intrhand *ih = arg;
156 	int s;
157 
158 	s = splsoft();
159 	LIST_REMOVE(ih, ih_q);
160 	splx(s);
161 	free(ih, M_DEVBUF);
162 }
163 
164 void
165 cpu_intr(status, cause, pc, ipending)
166 	u_int32_t status;
167 	u_int32_t cause;
168 	u_int32_t pc;
169 	u_int32_t ipending;
170 {
171 	uvmexp.intrs++;
172 
173 	/* device interrupts */
174 	(*platform.iointr)(status, cause, pc, ipending);
175 
176 	/* software simulated interrupt */
177 	if ((ipending & MIPS_SOFT_INT_MASK_1)
178 		    || (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
179 	    _clrsoftintr(MIPS_SOFT_INT_MASK_1);
180 	    softintr_dispatch();
181 	}
182 }
183