]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/intr_machdep.c
This commit was generated by cvs2svn to compensate for changes in r178866,
[FreeBSD/FreeBSD.git] / sys / mips / mips / intr_machdep.c
1 /*-
2  * Copyright (c) 2006 Fill this file and put your name here
3  * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions, and the following disclaimer,
11  *    without modification, immediately at the beginning of the file.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/interrupt.h>
36
37 #include <machine/clock.h>
38 #include <machine/cpu.h>
39 #include <machine/cpufunc.h>
40 #include <machine/cpuinfo.h>
41 #include <machine/cpuregs.h>
42 #include <machine/frame.h>
43 #include <machine/intr_machdep.h>
44 #include <machine/md_var.h>
45 #include <machine/trap.h>
46
47 static struct intr_event *hardintr_events[NHARD_IRQS];
48 static struct intr_event *softintr_events[NSOFT_IRQS];
49
50 #ifdef notyet
51 static int intrcnt_tab[NHARD_IRQS + NSOFT_IRQS];
52 static int intrcnt_index = 0;
53 static int last_printed = 0;
54 #endif
55
56 void 
57 mips_mask_irq(void)
58 {
59
60         printf("Unimplemented: %s\n", __func__);
61 }
62
63 void 
64 mips_unmask_irq(void)
65 {
66
67         printf("Unimplemented: %s\n", __func__);
68 }
69
70 void
71 cpu_establish_hardintr(const char *name, driver_filter_t *filt, 
72     void (*handler)(void*), void *arg, int irq, int flags, 
73     void **cookiep)
74 {
75         struct intr_event *event;
76         int error;
77
78         printf("Establish HARD IRQ %d: filt %p handler %p arg %p\n", irq, filt, handler, arg);
79         /*
80          * We have 6 levels, but thats 0 - 5 (not including 6)
81          */
82         if (irq < 0 || irq >= NHARD_IRQS)
83                 panic("%s called for unknown hard intr %d", __func__, irq);
84
85         event = hardintr_events[irq];
86         if (event == NULL) {
87                 error = intr_event_create(&event, (void *)irq, 0,
88                     (mask_fn)mips_mask_irq, (mask_fn)mips_unmask_irq,
89                     (mask_fn)mips_unmask_irq, NULL, "hard intr%d:", irq);
90                 if (error)
91                         return;
92                 hardintr_events[irq] = event;
93 #ifdef notyet
94                 last_printed += 
95                     snprintf(intrnames + last_printed,
96                     MAXCOMLEN + 1,
97                     "hard irq%d: %s", irq, name);
98                 last_printed++;
99                 intrcnt_tab[irq] = intrcnt_index;
100                 intrcnt_index++;
101 #endif
102                 
103         }
104
105         intr_event_add_handler(event, name, filt, handler, arg,
106             intr_priority(flags), flags, cookiep);
107
108         mips_wr_status(mips_rd_status() | (((1<< irq) << 8) << 2));
109 }
110
111 void
112 cpu_establish_softintr(const char *name, driver_filter_t *filt, 
113     void (*handler)(void*), void *arg, int irq, int flags, 
114     void **cookiep)
115 {
116         struct intr_event *event;
117         int error;
118
119         printf("Establish SOFT IRQ %d: filt %p handler %p arg %p\n", irq, filt, handler, arg);
120         if (irq < 0 || irq > NSOFT_IRQS)
121                 panic("%s called for unknown hard intr %d", __func__, irq);
122
123         event = softintr_events[irq];
124         if (event == NULL) {
125                 error = intr_event_create(&event, (void *)irq, 0,
126                     (mask_fn)mips_mask_irq, (mask_fn)mips_unmask_irq,
127                     (mask_fn)mips_unmask_irq, NULL, "intr%d:", irq);
128                 if (error)
129                         return;
130                 softintr_events[irq] = event;
131         }
132
133         intr_event_add_handler(event, name, filt, handler, arg,
134             intr_priority(flags), flags, cookiep);
135
136         mips_wr_status(mips_rd_status() | (((1<< irq) << 8)));
137 }
138
139 void
140 cpu_intr(struct trapframe *tf)
141 {
142         struct intr_handler *ih;
143         struct intr_event *event;
144         register_t cause;
145         int hard;
146         int intr;
147         int i;
148         int thread;
149
150         critical_enter();
151
152         cause = mips_rd_cause();
153         intr = (cause & MIPS_INT_MASK) >> 8;
154         cause &= ~MIPS_INT_MASK;
155         mips_wr_cause(cause);
156         while ((i = fls(intr)) != 0) {
157                 intr &= ~(1 << (i - 1));
158                 switch (i) {
159                 case 1: case 2:
160                         /* Software interrupt. */
161                         i--; /* Get a 0-offset interrupt. */
162                         hard = 0;
163                         event = softintr_events[i];
164                         break;
165                 default:
166                         /* Hardware interrupt. */
167                         i -= 2; /* Trim software interrupt bits. */
168                         i--; /* Get a 0-offset interrupt. */
169                         hard = 1;
170                         event = hardintr_events[i];
171                         break;
172                 }
173
174                 if (!event || TAILQ_EMPTY(&event->ie_handlers))
175                 {
176                   printf("stray %s interrupt %d\n",
177                          hard ? "hard" : "soft", i);
178                   continue;
179                 }
180
181                 /* Execute fast handlers. */
182                 thread = 0;
183                 TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) {
184                         if (ih->ih_filter == NULL)
185                                 thread = 1;
186                         else
187                                 ih->ih_filter(ih->ih_argument ?
188                                     ih->ih_argument : tf);
189                 }
190
191                 /* Schedule thread if needed. */
192                 if (thread)
193                         intr_event_schedule_thread(event);
194         }
195
196         KASSERT(i == 0, ("all interrupts handled"));
197
198         critical_exit();
199 }