1 /* $NetBSD: isabus.c,v 1.54 2023/12/07 03:46:10 thorpej Exp $ */
2 /* $OpenBSD: isabus.c,v 1.15 1998/03/16 09:38:46 pefo Exp $ */
3 /* NetBSD: isa.c,v 1.33 1995/06/28 04:30:51 cgd Exp */
4
5 /*-
6 * Copyright (c) 1990 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * William Jolitz and Don Ahn.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)isa.c 7.2 (Berkeley) 5/12/91
37 */
38 /*-
39 * Copyright (c) 1995 Per Fogelstrom
40 * Copyright (c) 1993, 1994 Charles M. Hannum.
41 *
42 * This code is derived from software contributed to Berkeley by
43 * William Jolitz and Don Ahn.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 *
73 * @(#)isa.c 7.2 (Berkeley) 5/12/91
74 */
75 /*
76 * Mach Operating System
77 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
78 * All Rights Reserved.
79 *
80 * Permission to use, copy, modify and distribute this software and its
81 * documentation is hereby granted, provided that both the copyright
82 * notice and this permission notice appear in all copies of the
83 * software, derivative works or modified versions, and any portions
84 * thereof, and that both notices appear in supporting documentation.
85 *
86 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
87 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
88 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
89 *
90 * Carnegie Mellon requests users of this software to return to
91 *
92 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
93 * School of Computer Science
94 * Carnegie Mellon University
95 * Pittsburgh PA 15213-3890
96 *
97 * any improvements or extensions that they make and grant Carnegie Mellon
98 * the rights to redistribute these changes.
99 */
100 /*
101 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
102
103 All Rights Reserved
104
105 Permission to use, copy, modify, and distribute this software and
106 its documentation for any purpose and without fee is hereby
107 granted, provided that the above copyright notice appears in all
108 copies and that both the copyright notice and this permission notice
109 appear in supporting documentation, and that the name of Intel
110 not be used in advertising or publicity pertaining to distribution
111 of the software without specific, written prior permission.
112
113 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
114 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
115 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
116 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
117 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
118 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
119 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
120 */
121
122 #include <sys/cdefs.h>
123 __KERNEL_RCSID(0, "$NetBSD: isabus.c,v 1.54 2023/12/07 03:46:10 thorpej Exp $");
124
125 #include <sys/param.h>
126 #include <sys/proc.h>
127 #include <sys/systm.h>
128 #include <sys/callout.h>
129 #include <sys/time.h>
130 #include <sys/kernel.h>
131 #include <sys/device.h>
132 #include <sys/kmem.h>
133 #include <sys/vmem_impl.h>
134
135 #include <uvm/uvm_extern.h>
136
137 #include <machine/cpu.h>
138 #include <machine/pio.h>
139 #include <machine/autoconf.h>
140 #include <machine/intr.h>
141
142 #include <mips/locore.h>
143
144 #include <dev/ic/i8253reg.h>
145 #include <dev/ic/i8259reg.h>
146 #include <dev/isa/isareg.h>
147 #include <dev/isa/isavar.h>
148 #include <arc/isa/isabrvar.h>
149 #include <arc/isa/spkrreg.h>
150
151 #include <arc/arc/timervar.h>
152
153 static int beeping;
154 static callout_t sysbeep_ch;
155
156 #define ISA_MEM_BTAG_COUNT VMEM_EST_BTCOUNT(1, 16)
157 #define ISA_IO_BTAG_COUNT VMEM_EST_BTCOUNT(1, 16)
158
159 static struct vmem isa_mem_arena_store;
160 static struct vmem isa_io_arena_store;
161 static struct vmem_btag isa_mem_btag_store[ISA_MEM_BTAG_COUNT];
162 static struct vmem_btag isa_io_btag_store[ISA_IO_BTAG_COUNT];
163
164 #define IRQ_SLAVE 2
165
166 /* Definition of the driver for autoconfig. */
167 static int isabrprint(void *, const char *);
168
169 extern struct arc_bus_space arc_bus_io, arc_bus_mem;
170
171 static void isabr_attach_hook(device_t , device_t,
172 struct isabus_attach_args *);
173 static void isabr_detach_hook(isa_chipset_tag_t, device_t);
174 static const struct evcnt *isabr_intr_evcnt(isa_chipset_tag_t, int);
175 static void *isabr_intr_establish(isa_chipset_tag_t, int, int, int,
176 int (*)(void *), void *);
177 static void isabr_intr_disestablish(isa_chipset_tag_t, void*);
178 static void isabr_initicu(void);
179 static void intr_calculatemasks(void);
180 static int fakeintr(void *a);
181
182 struct isabr_config *isabr_conf = NULL;
183 uint32_t imask[_IPL_N]; /* XXX */
184
185 void
isabrattach(struct isabr_softc * sc)186 isabrattach(struct isabr_softc *sc)
187 {
188 struct isabus_attach_args iba;
189
190 callout_init(&sysbeep_ch, 0);
191
192 if (isabr_conf == NULL)
193 panic("isabr_conf isn't initialized");
194
195 aprint_normal("\n");
196
197 /* Initialize interrupt controller */
198 isabr_initicu();
199
200 sc->arc_isa_cs.ic_attach_hook = isabr_attach_hook;
201 sc->arc_isa_cs.ic_detach_hook = isabr_detach_hook;
202 sc->arc_isa_cs.ic_intr_evcnt = isabr_intr_evcnt;
203 sc->arc_isa_cs.ic_intr_establish = isabr_intr_establish;
204 sc->arc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
205
206 arc_bus_space_init_arena(&arc_bus_mem, &isa_mem_arena_store,
207 isa_mem_btag_store, ISA_MEM_BTAG_COUNT);
208 arc_bus_space_init_arena(&arc_bus_io, &isa_io_arena_store,
209 isa_io_btag_store, ISA_IO_BTAG_COUNT);
210
211 iba.iba_iot = &arc_bus_io;
212 iba.iba_memt = &arc_bus_mem;
213 iba.iba_dmat = &sc->sc_dmat;
214 iba.iba_ic = &sc->arc_isa_cs;
215 config_found(sc->sc_dev, &iba, isabrprint,
216 CFARGS(.iattr = "isabus"));
217 }
218
219 static int
isabrprint(void * aux,const char * pnp)220 isabrprint(void *aux, const char *pnp)
221 {
222
223 if (pnp)
224 aprint_normal("isa at %s", pnp);
225 aprint_verbose(" isa_io_base 0x%"PRIxVADDR" isa_mem_base 0x%"PRIxVADDR,
226 arc_bus_io.bs_vbase, arc_bus_mem.bs_vbase);
227 return UNCONF;
228 }
229
230
231 /*
232 * Interrupt system driver code
233 * ============================
234 */
235 #define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
236
237 int imen;
238 int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
239 struct isa_intrhand *isa_intrhand[ICU_LEN];
240
241 static int
fakeintr(void * a)242 fakeintr(void *a)
243 {
244
245 return 0;
246 }
247
248 /*
249 * Recalculate the interrupt masks from scratch.
250 * We could code special registry and deregistry versions of this function that
251 * would be faster, but the code would be nastier, and we don't expect this to
252 * happen very much anyway.
253 */
254 static void
intr_calculatemasks(void)255 intr_calculatemasks(void)
256 {
257 int irq, level;
258 struct isa_intrhand *q;
259
260 /* First, figure out which levels each IRQ uses. */
261 for (irq = 0; irq < ICU_LEN; irq++) {
262 int levels = 0;
263 for (q = isa_intrhand[irq]; q; q = q->ih_next)
264 levels |= 1 << q->ih_level;
265 intrlevel[irq] = levels;
266 }
267
268 /* Then figure out which IRQs use each level. */
269 for (level = 0; level < _IPL_N; level++) {
270 int irqs = 0;
271 for (irq = 0; irq < ICU_LEN; irq++)
272 if (intrlevel[irq] & (1 << level))
273 irqs |= 1 << irq;
274 imask[level] = irqs;
275 }
276
277 imask[IPL_NONE] = 0;
278
279 imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
280 imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
281
282 /*
283 * Enforce a hierarchy that gives slow devices a better chance at not
284 * dropping data.
285 */
286 imask[IPL_VM] |= imask[IPL_SOFTNET];
287
288 /*
289 * Since run queues may be manipulated by both the statclock and tty,
290 * network, and diskdrivers, clock > tty.
291 */
292 imask[IPL_SCHED] |= imask[IPL_VM];
293
294 /* And eventually calculate the complete masks. */
295 for (irq = 0; irq < ICU_LEN; irq++) {
296 int irqs = 1 << irq;
297 for (q = isa_intrhand[irq]; q; q = q->ih_next)
298 irqs |= imask[q->ih_level];
299 intrmask[irq] = irqs;
300 }
301
302 /* Lastly, determine which IRQs are actually in use. */
303 {
304 int irqs = 0;
305 for (irq = 0; irq < ICU_LEN; irq++)
306 if (isa_intrhand[irq])
307 irqs |= 1 << irq;
308 if (irqs >= 0x100) /* any IRQs >= 8 in use */
309 irqs |= 1 << IRQ_SLAVE;
310 imen = ~irqs;
311 isa_outb(IO_ICU1 + PIC_OCW1, imen);
312 isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
313 }
314 }
315
316 static void
isabr_attach_hook(device_t parent,device_t self,struct isabus_attach_args * iba)317 isabr_attach_hook(device_t parent, device_t self,
318 struct isabus_attach_args *iba)
319 {
320
321 /* Nothing to do. */
322 }
323
324 static void
isabr_detach_hook(isa_chipset_tag_t ic,device_t self)325 isabr_detach_hook(isa_chipset_tag_t ic, device_t self)
326 {
327
328 /* Nothing to do. */
329 }
330
331 static const struct evcnt *
isabr_intr_evcnt(isa_chipset_tag_t ic,int irq)332 isabr_intr_evcnt(isa_chipset_tag_t ic, int irq)
333 {
334
335 /* XXX for now, no evcnt parent reported */
336 return NULL;
337 }
338
339 /*
340 * Establish a ISA bus interrupt.
341 */
342 static void *
isabr_intr_establish(isa_chipset_tag_t ic,int irq,int type,int level,int (* ih_fun)(void *),void * ih_arg)343 isabr_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
344 int (*ih_fun)(void *), void *ih_arg)
345 {
346 struct isa_intrhand **p, *q, *ih;
347 static struct isa_intrhand fakehand = {NULL, fakeintr};
348
349 ih = kmem_alloc(sizeof *ih, KM_SLEEP);
350
351 if (!LEGAL_IRQ(irq) || type == IST_NONE)
352 panic("intr_establish: bogus irq or type");
353
354 switch (intrtype[irq]) {
355 case IST_NONE:
356 intrtype[irq] = type;
357 break;
358 case IST_EDGE:
359 case IST_LEVEL:
360 if (type == intrtype[irq])
361 break;
362 case IST_PULSE:
363 if (type != IST_NONE)
364 panic("intr_establish: can't share %s with %s",
365 isa_intr_typename(intrtype[irq]),
366 isa_intr_typename(type));
367 break;
368 }
369
370 /*
371 * Figure out where to put the handler.
372 * This is O(N^2), but we want to preserve the order, and N is
373 * generally small.
374 */
375 for (p = &isa_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
376 ;
377
378 /*
379 * Actually install a fake handler momentarily, since we might be doing
380 * this with interrupts enabled and don't want the real routine called
381 * until masking is set up.
382 */
383 fakehand.ih_level = level;
384 *p = &fakehand;
385
386 intr_calculatemasks();
387
388 /*
389 * Poke the real handler in now.
390 */
391 ih->ih_fun = ih_fun;
392 ih->ih_arg = ih_arg;
393 ih->ih_count = 0;
394 ih->ih_next = NULL;
395 ih->ih_level = level;
396 ih->ih_irq = irq;
397 snprintf(ih->ih_evname, sizeof(ih->ih_evname), "irq %d", irq);
398 evcnt_attach_dynamic(&ih->ih_evcnt, EVCNT_TYPE_INTR, NULL, "isa",
399 ih->ih_evname);
400 *p = ih;
401
402 return ih;
403 }
404
405 static void
isabr_intr_disestablish(isa_chipset_tag_t ic,void * arg)406 isabr_intr_disestablish(isa_chipset_tag_t ic, void *arg)
407 {
408
409 }
410
411 /*
412 * Process an interrupt from the ISA bus.
413 */
414 uint32_t
isabr_iointr(uint32_t mask,struct clockframe * cf)415 isabr_iointr(uint32_t mask, struct clockframe *cf)
416 {
417 struct isa_intrhand *ih;
418 int isa_vector;
419 int o_imen;
420
421 isa_vector = (*isabr_conf->ic_intr_status)();
422 if (isa_vector < 0)
423 return 0;
424
425 o_imen = imen;
426 imen |= 1 << (isa_vector & (ICU_LEN - 1));
427 if (isa_vector & 0x08) {
428 isa_inb(IO_ICU2 + PIC_OCW1);
429 isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
430 isa_outb(IO_ICU2 + PIC_OCW2,
431 OCW2_SELECT | OCW2_EOI | OCW2_SL |
432 OCW2_ILS((isa_vector & 7)));
433 isa_outb(IO_ICU1,
434 OCW2_SELECT | OCW2_EOI | OCW2_SL | IRQ_SLAVE);
435 } else {
436 isa_inb(IO_ICU1 + PIC_OCW1);
437 isa_outb(IO_ICU1 + PIC_OCW1, imen);
438 isa_outb(IO_ICU1 + PIC_OCW2,
439 OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(isa_vector));
440 }
441 ih = isa_intrhand[isa_vector];
442 if (isa_vector == 0 && ih) { /* Clock */ /*XXX*/
443 last_cp0_count = mips3_cp0_count_read();
444 /* XXX: spllowerclock() not allowed */
445 cf->sr &= ~MIPS_SR_INT_IE;
446 if ((*ih->ih_fun)(cf))
447 ih->ih_evcnt.ev_count++;
448 ih = ih->ih_next;
449 }
450 while (ih) {
451 if ((*ih->ih_fun)(ih->ih_arg))
452 ih->ih_evcnt.ev_count++;
453 ih = ih->ih_next;
454 }
455 imen = o_imen;
456 isa_inb(IO_ICU1 + PIC_OCW1);
457 isa_inb(IO_ICU2 + PIC_OCW1);
458 isa_outb(IO_ICU1 + PIC_OCW1, imen);
459 isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
460
461 return MIPS_INT_MASK_2;
462 }
463
464
465 /*
466 * Initialize the Interrupt controller logic.
467 */
468 static void
isabr_initicu(void)469 isabr_initicu(void)
470 {
471
472 int i;
473
474 for (i = 0; i < ICU_LEN; i++) {
475 switch (i) {
476 case 2:
477 case 8:
478 intrtype[i] = IST_EDGE;
479 break;
480 default:
481 intrtype[i] = IST_NONE;
482 break;
483 }
484 }
485
486 /* reset; program device, four bytes */
487 isa_outb(IO_ICU1 + PIC_ICW1, ICW1_SELECT | ICW1_IC4);
488 /* starting at this vector index */
489 isa_outb(IO_ICU1 + PIC_ICW2, 0);
490 /* slave on line 2 */
491 isa_outb(IO_ICU1 + PIC_ICW3, ICW3_CASCADE(IRQ_SLAVE));
492 /* 8086 mode */
493 isa_outb(IO_ICU1 + PIC_ICW4, ICW4_8086);
494
495 /* leave interrupts masked */
496 isa_outb(IO_ICU1 + PIC_OCW1, 0xff);
497
498 /* special mask mode (if available) */
499 isa_outb(IO_ICU1 + PIC_OCW3, OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
500 /* Read IRR by default. */
501 isa_outb(IO_ICU1 + PIC_OCW3, OCW3_SELECT | OCW3_RR);
502 #ifdef REORDER_IRQ
503 /* pri order 3-7, 0-2 (com2 first) */
504 isa_outb(IO_ICU1 + PIC_OCW2,
505 OCW2_SELECT | OCW2_R | OCW2_SL OCW2_ILS(3 - 1));
506 #endif
507
508 /* reset; program device, four bytes */
509 isa_outb(IO_ICU2 + PIC_ICW1, ICW1_SELECT | ICW1_IC4);
510 /* staring at this vector index */
511 isa_outb(IO_ICU2 + PIC_ICW2, 8);
512 /* slave connected to line 2 of master */
513 isa_outb(IO_ICU2 + PIC_ICW3, ICW3_SIC(IRQ_SLAVE));
514 /* 8086 mode */
515 isa_outb(IO_ICU2 + PIC_ICW4, ICW4_8086);
516
517 /* leave interrupts masked */
518 isa_outb(IO_ICU2 + PIC_OCW1, 0xff);
519
520 /* special mask mode (if available) */
521 isa_outb(IO_ICU2 + PIC_OCW3, OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
522 /* Read IRR by default. */
523 isa_outb(IO_ICU2 + PIC_OCW3, OCW3_SELECT | OCW3_RR);
524 }
525
526
527 /*
528 * SPEAKER BEEPER...
529 */
530 void
sysbeepstop(void * arg)531 sysbeepstop(void *arg)
532 {
533 int s;
534
535 /* disable counter 2 */
536 s = splhigh();
537 isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) & ~PIT_SPKR);
538 splx(s);
539 beeping = 0;
540 }
541
542 void
sysbeep(int pitch,int period)543 sysbeep(int pitch, int period)
544 {
545 static int last_pitch, last_period;
546 int s;
547
548 if (cold)
549 return; /* Can't beep yet. */
550
551 if (beeping)
552 callout_stop(&sysbeep_ch);
553 if (!beeping || last_pitch != pitch) {
554 s = splhigh();
555 isa_outb(IO_TIMER1 + TIMER_MODE,
556 TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
557 isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) % 256);
558 isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) / 256);
559 isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) | PIT_SPKR);
560 splx(s);
561 }
562 last_pitch = pitch;
563 beeping = last_period = period;
564 callout_reset(&sysbeep_ch, period, sysbeepstop, NULL);
565 }
566
567 int
isa_intr_alloc(isa_chipset_tag_t c,int mask,int type,int * irq_p)568 isa_intr_alloc(isa_chipset_tag_t c, int mask, int type, int *irq_p)
569 {
570 int irq;
571 int maybe_irq = -1;
572 int shared_depth = 0;
573 mask &= 0x8b28; /* choose from 3, 5, 8, 9, 11, 15 XXX */
574 for (irq = 0; mask != 0; mask >>= 1, irq++) {
575 if ((mask & 1) == 0)
576 continue;
577 if (intrtype[irq] == IST_NONE) {
578 *irq_p = irq;
579 return 0;
580 }
581 /* Level interrupts can be shared */
582 if (type == IST_LEVEL && intrtype[irq] == IST_LEVEL) {
583 struct isa_intrhand *ih = isa_intrhand[irq];
584 int depth;
585 if (maybe_irq == -1) {
586 maybe_irq = irq;
587 continue;
588 }
589 for (depth = 0; ih != NULL; ih = ih->ih_next)
590 depth++;
591 if (depth < shared_depth) {
592 maybe_irq = irq;
593 shared_depth = depth;
594 }
595 }
596 }
597 if (maybe_irq != -1) {
598 *irq_p = maybe_irq;
599 return 0;
600 }
601 return 1;
602 }
603