int.c revision 1.9.2.2 1 1.9.2.2 skrll /* $NetBSD: int.c,v 1.9.2.2 2004/08/03 10:40:00 skrll Exp $ */
2 1.9.2.2 skrll
3 1.9.2.2 skrll /*
4 1.9.2.2 skrll * Copyright (c) 2004 Christopher SEKIYA
5 1.9.2.2 skrll * All rights reserved.
6 1.9.2.2 skrll *
7 1.9.2.2 skrll * Redistribution and use in source and binary forms, with or without
8 1.9.2.2 skrll * modification, are permitted provided that the following conditions
9 1.9.2.2 skrll * are met:
10 1.9.2.2 skrll * 1. Redistributions of source code must retain the above copyright
11 1.9.2.2 skrll * notice, this list of conditions and the following disclaimer.
12 1.9.2.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
13 1.9.2.2 skrll * notice, this list of conditions and the following disclaimer in the
14 1.9.2.2 skrll * documentation and/or other materials provided with the distribution.
15 1.9.2.2 skrll * 3. The name of the author may not be used to endorse or promote products
16 1.9.2.2 skrll * derived from this software without specific prior written permission.
17 1.9.2.2 skrll *
18 1.9.2.2 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.9.2.2 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.9.2.2 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.9.2.2 skrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.9.2.2 skrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.9.2.2 skrll * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.9.2.2 skrll * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.9.2.2 skrll * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.9.2.2 skrll * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.9.2.2 skrll * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.9.2.2 skrll */
29 1.9.2.2 skrll
30 1.9.2.2 skrll /*
31 1.9.2.2 skrll * INT/INT2/INT3 interrupt controller (used in Indy's, Indigo's, etc..)
32 1.9.2.2 skrll */
33 1.9.2.2 skrll
34 1.9.2.2 skrll #include <sys/cdefs.h>
35 1.9.2.2 skrll __KERNEL_RCSID(0, "$NetBSD: int.c,v 1.9.2.2 2004/08/03 10:40:00 skrll Exp $");
36 1.9.2.2 skrll
37 1.9.2.2 skrll #include "opt_cputype.h"
38 1.9.2.2 skrll
39 1.9.2.2 skrll #include <sys/param.h>
40 1.9.2.2 skrll #include <sys/proc.h>
41 1.9.2.2 skrll #include <sys/systm.h>
42 1.9.2.2 skrll #include <sys/kernel.h>
43 1.9.2.2 skrll #include <sys/device.h>
44 1.9.2.2 skrll #include <sys/malloc.h>
45 1.9.2.2 skrll
46 1.9.2.2 skrll #include <dev/ic/i8253reg.h>
47 1.9.2.2 skrll #include <machine/sysconf.h>
48 1.9.2.2 skrll #include <machine/machtype.h>
49 1.9.2.2 skrll #include <machine/bus.h>
50 1.9.2.2 skrll #include <mips/locore.h>
51 1.9.2.2 skrll
52 1.9.2.2 skrll #include <mips/cache.h>
53 1.9.2.2 skrll
54 1.9.2.2 skrll #include <sgimips/dev/int2reg.h>
55 1.9.2.2 skrll #include <sgimips/dev/int2var.h>
56 1.9.2.2 skrll
57 1.9.2.2 skrll static bus_space_handle_t ioh;
58 1.9.2.2 skrll static bus_space_tag_t iot;
59 1.9.2.2 skrll
60 1.9.2.2 skrll struct int_softc {
61 1.9.2.2 skrll struct device sc_dev;
62 1.9.2.2 skrll };
63 1.9.2.2 skrll
64 1.9.2.2 skrll
65 1.9.2.2 skrll static int int_match(struct device *, struct cfdata *, void *);
66 1.9.2.2 skrll static void int_attach(struct device *, struct device *, void *);
67 1.9.2.2 skrll void int_local0_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
68 1.9.2.2 skrll void int_local1_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
69 1.9.2.2 skrll int int_mappable_intr(void *);
70 1.9.2.2 skrll void *int_intr_establish(int, int, int (*)(void *), void *);
71 1.9.2.2 skrll unsigned long int_cal_timer(void);
72 1.9.2.2 skrll void int_8254_cal(void);
73 1.9.2.2 skrll
74 1.9.2.2 skrll CFATTACH_DECL(int, sizeof(struct int_softc),
75 1.9.2.2 skrll int_match, int_attach, NULL, NULL);
76 1.9.2.2 skrll
77 1.9.2.2 skrll static int
78 1.9.2.2 skrll int_match(struct device *parent, struct cfdata *match, void *aux)
79 1.9.2.2 skrll {
80 1.9.2.2 skrll
81 1.9.2.2 skrll if ((mach_type == MACH_SGI_IP12) || (mach_type == MACH_SGI_IP20) ||
82 1.9.2.2 skrll (mach_type == MACH_SGI_IP22) )
83 1.9.2.2 skrll return 1;
84 1.9.2.2 skrll
85 1.9.2.2 skrll return 0;
86 1.9.2.2 skrll }
87 1.9.2.2 skrll
88 1.9.2.2 skrll static void
89 1.9.2.2 skrll int_attach(struct device *parent, struct device *self, void *aux)
90 1.9.2.2 skrll {
91 1.9.2.2 skrll u_int32_t address;
92 1.9.2.2 skrll
93 1.9.2.2 skrll if (mach_type == MACH_SGI_IP12)
94 1.9.2.2 skrll address = INT_IP12;
95 1.9.2.2 skrll else if (mach_type == MACH_SGI_IP20)
96 1.9.2.2 skrll address = INT_IP20;
97 1.9.2.2 skrll else if (mach_type == MACH_SGI_IP22) {
98 1.9.2.2 skrll if (mach_subtype == MACH_SGI_IP22_FULLHOUSE)
99 1.9.2.2 skrll address = INT_IP22;
100 1.9.2.2 skrll else
101 1.9.2.2 skrll address = INT_IP24;
102 1.9.2.2 skrll } else
103 1.9.2.2 skrll panic("\nint0: passed match, but failed attach?");
104 1.9.2.2 skrll
105 1.9.2.2 skrll printf(" addr 0x%x", address);
106 1.9.2.2 skrll
107 1.9.2.2 skrll bus_space_map(iot, address, 0, 0, &ioh);
108 1.9.2.2 skrll iot = SGIMIPS_BUS_SPACE_NORMAL;
109 1.9.2.2 skrll
110 1.9.2.2 skrll /* Clean out interrupt masks */
111 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, 0);
112 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, 0);
113 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_MAP_MASK0, 0);
114 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_MAP_MASK1, 0);
115 1.9.2.2 skrll
116 1.9.2.2 skrll /* Reset timer interrupts */
117 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_TIMER_CLEAR, 0x03);
118 1.9.2.2 skrll
119 1.9.2.2 skrll switch (mach_type) {
120 1.9.2.2 skrll case MACH_SGI_IP12:
121 1.9.2.2 skrll platform.intr1 = int_local0_intr;
122 1.9.2.2 skrll platform.intr2 = int_local1_intr;
123 1.9.2.2 skrll int_8254_cal();
124 1.9.2.2 skrll break;
125 1.9.2.2 skrll #ifdef MIPS3
126 1.9.2.2 skrll case MACH_SGI_IP20:
127 1.9.2.2 skrll case MACH_SGI_IP22:
128 1.9.2.2 skrll {
129 1.9.2.2 skrll int i;
130 1.9.2.2 skrll unsigned long cps;
131 1.9.2.2 skrll unsigned long ctrdiff[3];
132 1.9.2.2 skrll
133 1.9.2.2 skrll platform.intr0 = int_local0_intr;
134 1.9.2.2 skrll platform.intr1 = int_local1_intr;
135 1.9.2.2 skrll
136 1.9.2.2 skrll /* calibrate timer */
137 1.9.2.2 skrll int_cal_timer();
138 1.9.2.2 skrll
139 1.9.2.2 skrll cps = 0;
140 1.9.2.2 skrll for (i = 0;
141 1.9.2.2 skrll i < sizeof(ctrdiff) / sizeof(ctrdiff[0]); i++) {
142 1.9.2.2 skrll do {
143 1.9.2.2 skrll ctrdiff[i] = int_cal_timer();
144 1.9.2.2 skrll } while (ctrdiff[i] == 0);
145 1.9.2.2 skrll
146 1.9.2.2 skrll cps += ctrdiff[i];
147 1.9.2.2 skrll }
148 1.9.2.2 skrll
149 1.9.2.2 skrll cps = cps / (sizeof(ctrdiff) / sizeof(ctrdiff[0]));
150 1.9.2.2 skrll
151 1.9.2.2 skrll printf(": bus %luMHz, CPU %luMHz",
152 1.9.2.2 skrll cps / 10000, cps / 5000);
153 1.9.2.2 skrll
154 1.9.2.2 skrll /* R4k/R4400/R4600/R5k count at half CPU frequency */
155 1.9.2.2 skrll curcpu()->ci_cpu_freq = 2 * cps * hz;
156 1.9.2.2 skrll }
157 1.9.2.2 skrll #endif /* MIPS3 */
158 1.9.2.2 skrll
159 1.9.2.2 skrll break;
160 1.9.2.2 skrll default:
161 1.9.2.2 skrll panic("int0: unsupported machine type %i\n", mach_type);
162 1.9.2.2 skrll break;
163 1.9.2.2 skrll }
164 1.9.2.2 skrll
165 1.9.2.2 skrll printf("\n");
166 1.9.2.2 skrll
167 1.9.2.2 skrll curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / (2 * hz);
168 1.9.2.2 skrll curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / (2 * 1000000);
169 1.9.2.2 skrll MIPS_SET_CI_RECIPRICAL(curcpu());
170 1.9.2.2 skrll
171 1.9.2.2 skrll if (mach_type == MACH_SGI_IP22) {
172 1.9.2.2 skrll /* Wire interrupts 7, 11 to mappable interrupt 0,1 handlers */
173 1.9.2.2 skrll intrtab[7].ih_fun = int_mappable_intr;
174 1.9.2.2 skrll intrtab[7].ih_arg = (void*) 0;
175 1.9.2.2 skrll
176 1.9.2.2 skrll intrtab[11].ih_fun = int_mappable_intr;
177 1.9.2.2 skrll intrtab[11].ih_arg = (void*) 1;
178 1.9.2.2 skrll }
179 1.9.2.2 skrll
180 1.9.2.2 skrll platform.intr_establish = int_intr_establish;
181 1.9.2.2 skrll }
182 1.9.2.2 skrll
183 1.9.2.2 skrll int
184 1.9.2.2 skrll int_mappable_intr(void *arg)
185 1.9.2.2 skrll {
186 1.9.2.2 skrll int i;
187 1.9.2.2 skrll int ret;
188 1.9.2.2 skrll int intnum;
189 1.9.2.2 skrll u_int32_t mstat;
190 1.9.2.2 skrll u_int32_t mmask;
191 1.9.2.2 skrll int which = (int)arg;
192 1.9.2.2 skrll struct sgimips_intrhand *ih;
193 1.9.2.2 skrll
194 1.9.2.2 skrll ret = 0;
195 1.9.2.2 skrll mstat = bus_space_read_4(iot, ioh, INT2_MAP_STATUS);
196 1.9.2.2 skrll mmask = bus_space_read_4(iot, ioh, INT2_MAP_MASK0 + (which << 2));
197 1.9.2.2 skrll
198 1.9.2.2 skrll mstat &= mmask;
199 1.9.2.2 skrll
200 1.9.2.2 skrll for (i = 0; i < 8; i++) {
201 1.9.2.2 skrll intnum = i + 16 + (which << 3);
202 1.9.2.2 skrll if (mstat & (1 << i)) {
203 1.9.2.2 skrll for (ih = &intrtab[intnum]; ih != NULL;
204 1.9.2.2 skrll ih = ih->ih_next) {
205 1.9.2.2 skrll if (ih->ih_fun != NULL)
206 1.9.2.2 skrll ret |= (ih->ih_fun)(ih->ih_arg);
207 1.9.2.2 skrll else
208 1.9.2.2 skrll printf("int0: unexpected mapped "
209 1.9.2.2 skrll "interrupt %d\n", intnum);
210 1.9.2.2 skrll }
211 1.9.2.2 skrll }
212 1.9.2.2 skrll }
213 1.9.2.2 skrll
214 1.9.2.2 skrll return ret;
215 1.9.2.2 skrll }
216 1.9.2.2 skrll
217 1.9.2.2 skrll void
218 1.9.2.2 skrll int_local0_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
219 1.9.2.2 skrll u_int32_t ipending)
220 1.9.2.2 skrll {
221 1.9.2.2 skrll int i;
222 1.9.2.2 skrll u_int32_t l0stat;
223 1.9.2.2 skrll u_int32_t l0mask;
224 1.9.2.2 skrll struct sgimips_intrhand *ih;
225 1.9.2.2 skrll
226 1.9.2.2 skrll l0stat = bus_space_read_4(iot, ioh, INT2_LOCAL0_STATUS);
227 1.9.2.2 skrll l0mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK);
228 1.9.2.2 skrll
229 1.9.2.2 skrll /* The "FIFO full" bit is apparently not latched in the ISR, which
230 1.9.2.2 skrll means that it won't be present in l0stat unless we're very lucky.
231 1.9.2.2 skrll If no interrupts are pending, assume that it was caused by a full
232 1.9.2.2 skrll FIFO and dispatch.
233 1.9.2.2 skrll */
234 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, l0mask & (0xfe));
235 1.9.2.2 skrll if ( (l0mask & 0x01) && ((l0stat & l0mask) == 0) )
236 1.9.2.2 skrll l0stat = 0x01;
237 1.9.2.2 skrll
238 1.9.2.2 skrll for (i = 0; i < 8; i++) {
239 1.9.2.2 skrll if ( (l0stat & l0mask) & (1 << i)) {
240 1.9.2.2 skrll for (ih = &intrtab[i]; ih != NULL; ih = ih->ih_next) {
241 1.9.2.2 skrll if (ih->ih_fun != NULL)
242 1.9.2.2 skrll (ih->ih_fun)(ih->ih_arg);
243 1.9.2.2 skrll else
244 1.9.2.2 skrll printf("int0: unexpected local0 "
245 1.9.2.2 skrll "interrupt %d\n", i);
246 1.9.2.2 skrll }
247 1.9.2.2 skrll }
248 1.9.2.2 skrll }
249 1.9.2.2 skrll
250 1.9.2.2 skrll /* Unmask FIFO */
251 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, l0mask | 0x01);
252 1.9.2.2 skrll }
253 1.9.2.2 skrll
254 1.9.2.2 skrll void
255 1.9.2.2 skrll int_local1_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
256 1.9.2.2 skrll u_int32_t ipending)
257 1.9.2.2 skrll {
258 1.9.2.2 skrll int i;
259 1.9.2.2 skrll u_int32_t l1stat;
260 1.9.2.2 skrll u_int32_t l1mask;
261 1.9.2.2 skrll struct sgimips_intrhand *ih;
262 1.9.2.2 skrll
263 1.9.2.2 skrll l1stat = bus_space_read_4(iot, ioh, INT2_LOCAL1_STATUS);
264 1.9.2.2 skrll l1mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK);
265 1.9.2.2 skrll
266 1.9.2.2 skrll l1stat &= l1mask;
267 1.9.2.2 skrll
268 1.9.2.2 skrll for (i = 0; i < 8; i++) {
269 1.9.2.2 skrll if (l1stat & (1 << i)) {
270 1.9.2.2 skrll for (ih = &intrtab[8+i]; ih != NULL; ih = ih->ih_next) {
271 1.9.2.2 skrll if (ih->ih_fun != NULL)
272 1.9.2.2 skrll (ih->ih_fun)(ih->ih_arg);
273 1.9.2.2 skrll else
274 1.9.2.2 skrll printf("int0: unexpected local1 "
275 1.9.2.2 skrll " interrupt %x\n", 8 + i);
276 1.9.2.2 skrll }
277 1.9.2.2 skrll }
278 1.9.2.2 skrll }
279 1.9.2.2 skrll }
280 1.9.2.2 skrll
281 1.9.2.2 skrll void *
282 1.9.2.2 skrll int_intr_establish(int level, int ipl, int (*handler) (void *), void *arg)
283 1.9.2.2 skrll {
284 1.9.2.2 skrll u_int32_t mask;
285 1.9.2.2 skrll
286 1.9.2.2 skrll if (level < 0 || level >= NINTR)
287 1.9.2.2 skrll panic("invalid interrupt level");
288 1.9.2.2 skrll
289 1.9.2.2 skrll if (intrtab[level].ih_fun == NULL) {
290 1.9.2.2 skrll intrtab[level].ih_fun = handler;
291 1.9.2.2 skrll intrtab[level].ih_arg = arg;
292 1.9.2.2 skrll intrtab[level].ih_next = NULL;
293 1.9.2.2 skrll } else {
294 1.9.2.2 skrll struct sgimips_intrhand *n, *ih = malloc(sizeof *ih,
295 1.9.2.2 skrll M_DEVBUF, M_NOWAIT);
296 1.9.2.2 skrll
297 1.9.2.2 skrll if (ih == NULL) {
298 1.9.2.2 skrll printf("int_intr_establish: can't allocate handler\n");
299 1.9.2.2 skrll return (void *)NULL;
300 1.9.2.2 skrll }
301 1.9.2.2 skrll
302 1.9.2.2 skrll ih->ih_fun = handler;
303 1.9.2.2 skrll ih->ih_arg = arg;
304 1.9.2.2 skrll ih->ih_next = NULL;
305 1.9.2.2 skrll
306 1.9.2.2 skrll for (n = &intrtab[level]; n->ih_next != NULL; n = n->ih_next)
307 1.9.2.2 skrll ;
308 1.9.2.2 skrll
309 1.9.2.2 skrll n->ih_next = ih;
310 1.9.2.2 skrll
311 1.9.2.2 skrll return (void *)NULL; /* vector already set */
312 1.9.2.2 skrll }
313 1.9.2.2 skrll
314 1.9.2.2 skrll
315 1.9.2.2 skrll if (level < 8) {
316 1.9.2.2 skrll mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK);
317 1.9.2.2 skrll mask |= (1 << level);
318 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, mask);
319 1.9.2.2 skrll } else if (level < 16) {
320 1.9.2.2 skrll mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK);
321 1.9.2.2 skrll mask |= (1 << (level - 8));
322 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, mask);
323 1.9.2.2 skrll } else if (level < 24) {
324 1.9.2.2 skrll /* Map0 interrupt maps to l0 bit 7, so turn that on too */
325 1.9.2.2 skrll mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK);
326 1.9.2.2 skrll mask |= (1 << 7);
327 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, mask);
328 1.9.2.2 skrll
329 1.9.2.2 skrll mask = bus_space_read_4(iot, ioh, INT2_MAP_MASK0);
330 1.9.2.2 skrll mask |= (1 << (level - 16));
331 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_MAP_MASK0, mask);
332 1.9.2.2 skrll } else {
333 1.9.2.2 skrll /* Map1 interrupt maps to l1 bit 3, so turn that on too */
334 1.9.2.2 skrll mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK);
335 1.9.2.2 skrll mask |= (1 << 3);
336 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, mask);
337 1.9.2.2 skrll
338 1.9.2.2 skrll mask = bus_space_read_4(iot, ioh, INT2_MAP_MASK1);
339 1.9.2.2 skrll mask |= (1 << (level - 24));
340 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_MAP_MASK1, mask);
341 1.9.2.2 skrll }
342 1.9.2.2 skrll
343 1.9.2.2 skrll return (void *)NULL;
344 1.9.2.2 skrll }
345 1.9.2.2 skrll
346 1.9.2.2 skrll #ifdef MIPS3
347 1.9.2.2 skrll unsigned long
348 1.9.2.2 skrll int_cal_timer(void)
349 1.9.2.2 skrll {
350 1.9.2.2 skrll int s;
351 1.9.2.2 skrll int roundtime;
352 1.9.2.2 skrll int sampletime;
353 1.9.2.2 skrll int startmsb, lsb, msb;
354 1.9.2.2 skrll unsigned long startctr, endctr;
355 1.9.2.2 skrll
356 1.9.2.2 skrll /*
357 1.9.2.2 skrll * NOTE: HZ must be greater than 15 for this to work, as otherwise
358 1.9.2.2 skrll * we'll overflow the counter. We round the answer to hearest 1
359 1.9.2.2 skrll * MHz of the master (2x) clock.
360 1.9.2.2 skrll */
361 1.9.2.2 skrll roundtime = (1000000 / hz) / 2;
362 1.9.2.2 skrll sampletime = (1000000 / hz) + 0xff;
363 1.9.2.2 skrll startmsb = (sampletime >> 8);
364 1.9.2.2 skrll
365 1.9.2.2 skrll s = splhigh();
366 1.9.2.2 skrll
367 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL,
368 1.9.2.2 skrll ( TIMER_SEL2 | TIMER_16BIT | TIMER_RATEGEN) );
369 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_TIMER_2, (sampletime & 0xff));
370 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_TIMER_2, (sampletime >> 8));
371 1.9.2.2 skrll
372 1.9.2.2 skrll startctr = mips3_cp0_count_read();
373 1.9.2.2 skrll
374 1.9.2.2 skrll /* Wait for the MSB to count down to zero */
375 1.9.2.2 skrll do {
376 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL, TIMER_SEL2 );
377 1.9.2.2 skrll lsb = bus_space_read_4(iot, ioh, INT2_TIMER_2) & 0xff;
378 1.9.2.2 skrll msb = bus_space_read_4(iot, ioh, INT2_TIMER_2) & 0xff;
379 1.9.2.2 skrll
380 1.9.2.2 skrll endctr = mips3_cp0_count_read();
381 1.9.2.2 skrll } while (msb);
382 1.9.2.2 skrll
383 1.9.2.2 skrll /* Turn off timer */
384 1.9.2.2 skrll bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL,
385 1.9.2.2 skrll ( TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE) );
386 1.9.2.2 skrll
387 1.9.2.2 skrll splx(s);
388 1.9.2.2 skrll
389 1.9.2.2 skrll return (endctr - startctr) / roundtime * roundtime;
390 1.9.2.2 skrll }
391 1.9.2.2 skrll #endif /* MIPS3 */
392 1.9.2.2 skrll
393 1.9.2.2 skrll void
394 1.9.2.2 skrll int_8254_cal(void)
395 1.9.2.2 skrll {
396 1.9.2.2 skrll int s;
397 1.9.2.2 skrll
398 1.9.2.2 skrll s = splhigh();
399 1.9.2.2 skrll
400 1.9.2.2 skrll bus_space_write_1(iot, ioh, INT2_TIMER_0 + 15,
401 1.9.2.2 skrll TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
402 1.9.2.2 skrll bus_space_write_1(iot, ioh, INT2_TIMER_0 + 3, (20000 / hz) % 256);
403 1.9.2.2 skrll wbflush();
404 1.9.2.2 skrll delay(4);
405 1.9.2.2 skrll bus_space_write_1(iot, ioh, INT2_TIMER_0 + 3, (20000 / hz) / 256);
406 1.9.2.2 skrll
407 1.9.2.2 skrll bus_space_write_1(iot, ioh, INT2_TIMER_0 + 15,
408 1.9.2.2 skrll TIMER_SEL2|TIMER_RATEGEN|TIMER_16BIT);
409 1.9.2.2 skrll bus_space_write_1(iot, ioh, INT2_TIMER_0 + 11, 50);
410 1.9.2.2 skrll wbflush();
411 1.9.2.2 skrll delay(4);
412 1.9.2.2 skrll bus_space_write_1(iot, ioh, INT2_TIMER_0 + 11, 0);
413 1.9.2.2 skrll splx(s);
414 1.9.2.2 skrll }
415 1.9.2.2 skrll
416 1.9.2.2 skrll void
417 1.9.2.2 skrll int2_wait_fifo(u_int32_t flag)
418 1.9.2.2 skrll {
419 1.9.2.2 skrll if (ioh == 0)
420 1.9.2.2 skrll delay(5000);
421 1.9.2.2 skrll else
422 1.9.2.2 skrll while (bus_space_read_4(iot, ioh, INT2_LOCAL0_STATUS) & flag)
423 1.9.2.2 skrll ;
424 1.9.2.2 skrll }
425