Home | History | Annotate | Line # | Download | only in pic
intr.c revision 1.15
      1 /*	$NetBSD: intr.c,v 1.15 2011/06/17 23:36:18 matt Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2007 Michael Lorenz
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.15 2011/06/17 23:36:18 matt Exp $");
     31 
     32 #include "opt_multiprocessor.h"
     33 
     34 #define __INTR_PRIVATE
     35 
     36 #include <sys/param.h>
     37 #include <sys/malloc.h>
     38 #include <sys/kernel.h>
     39 #include <sys/cpu.h>
     40 
     41 #include <arch/powerpc/pic/picvar.h>
     42 #include "opt_pic.h"
     43 #include "opt_interrupt.h"
     44 #if defined(PIC_I8259) || defined (PIC_PREPIVR)
     45 #include <machine/isa_machdep.h>
     46 #endif
     47 
     48 #ifdef MULTIPROCESSOR
     49 #include <arch/powerpc/pic/ipivar.h>
     50 #endif
     51 
     52 #ifdef __HAVE_FAST_SOFTINTS
     53 #include <powerpc/softint.h>
     54 #endif
     55 
     56 #define MAX_PICS	8	/* 8 PICs ought to be enough for everyone */
     57 
     58 #define	PIC_VIRQ_LEGAL_P(x)	((u_int)(x) < NVIRQ)
     59 
     60 struct pic_ops *pics[MAX_PICS];
     61 int num_pics = 0;
     62 int max_base = 0;
     63 uint8_t	virq_map[NIRQ];
     64 imask_t virq_mask = HWIRQ_MASK;
     65 imask_t	imask[NIPL];
     66 int	primary_pic = 0;
     67 
     68 static int	fakeintr(void *);
     69 static int	mapirq(int);
     70 static void	intr_calculatemasks(void);
     71 static struct pic_ops *find_pic_by_hwirq(int);
     72 
     73 static struct intr_source intrsources[NVIRQ];
     74 
     75 void
     76 pic_init(void)
     77 {
     78 	/* everything is in bss, no reason to zero it. */
     79 }
     80 
     81 int
     82 pic_add(struct pic_ops *pic)
     83 {
     84 
     85 	if (num_pics >= MAX_PICS)
     86 		return -1;
     87 
     88 	pics[num_pics] = pic;
     89 	pic->pic_intrbase = max_base;
     90 	max_base += pic->pic_numintrs;
     91 	num_pics++;
     92 
     93 	return pic->pic_intrbase;
     94 }
     95 
     96 void
     97 pic_finish_setup(void)
     98 {
     99 	for (size_t i = 0; i < num_pics; i++) {
    100 		struct pic_ops * const pic = pics[i];
    101 		if (pic->pic_finish_setup != NULL)
    102 			pic->pic_finish_setup(pic);
    103 	}
    104 }
    105 
    106 static struct pic_ops *
    107 find_pic_by_hwirq(int hwirq)
    108 {
    109 	for (u_int base = 0; base < num_pics; base++) {
    110 		struct pic_ops * const pic = pics[base];
    111 		if (pic->pic_intrbase <= hwirq
    112 		    && hwirq < pic->pic_intrbase + pic->pic_numintrs) {
    113 			return pic;
    114 		}
    115 	}
    116 	return NULL;
    117 }
    118 
    119 static int
    120 fakeintr(void *arg)
    121 {
    122 
    123 	return 0;
    124 }
    125 
    126 /*
    127  * Register an interrupt handler.
    128  */
    129 void *
    130 intr_establish(int hwirq, int type, int ipl, int (*ih_fun)(void *),
    131     void *ih_arg)
    132 {
    133 	struct intrhand **p, *q, *ih;
    134 	struct pic_ops *pic;
    135 	static struct intrhand fakehand;
    136 	int maxipl = ipl;
    137 
    138 	if (maxipl == IPL_NONE)
    139 		maxipl = IPL_HIGH;
    140 
    141 	if (hwirq >= max_base) {
    142 		panic("%s: bogus IRQ %d, max is %d", __func__, hwirq,
    143 		    max_base - 1);
    144 	}
    145 
    146 	pic = find_pic_by_hwirq(hwirq);
    147 	if (pic == NULL) {
    148 
    149 		panic("%s: cannot find a pic for IRQ %d", __func__, hwirq);
    150 	}
    151 
    152 	const int virq = mapirq(hwirq);
    153 
    154 	/* no point in sleeping unless someone can free memory. */
    155 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    156 	if (ih == NULL)
    157 		panic("intr_establish: can't malloc handler info");
    158 
    159 	if (!PIC_VIRQ_LEGAL_P(virq) || type == IST_NONE)
    160 		panic("intr_establish: bogus irq (%d) or type (%d)",
    161 		    hwirq, type);
    162 
    163 	struct intr_source * const is = &intrsources[virq];
    164 
    165 	switch (is->is_type) {
    166 	case IST_NONE:
    167 		is->is_type = type;
    168 		break;
    169 	case IST_EDGE:
    170 	case IST_LEVEL:
    171 		if (type == is->is_type)
    172 			break;
    173 		/* FALLTHROUGH */
    174 	case IST_PULSE:
    175 		if (type != IST_NONE)
    176 			panic("intr_establish: can't share %s with %s",
    177 			    intr_typename(is->is_type),
    178 			    intr_typename(type));
    179 		break;
    180 	}
    181 	if (is->is_hand == NULL) {
    182 		snprintf(is->is_source, sizeof(is->is_source), "irq %d",
    183 		    is->is_hwirq);
    184 		evcnt_attach_dynamic(&is->is_ev, EVCNT_TYPE_INTR, NULL,
    185 		    pic->pic_name, is->is_source);
    186 	}
    187 
    188 	/*
    189 	 * Figure out where to put the handler.
    190 	 * This is O(N^2), but we want to preserve the order, and N is
    191 	 * generally small.
    192 	 */
    193 	for (p = &is->is_hand; (q = *p) != NULL; p = &q->ih_next) {
    194 		maxipl = max(maxipl, q->ih_ipl);
    195 	}
    196 
    197 	/*
    198 	 * Actually install a fake handler momentarily, since we might be doing
    199 	 * this with interrupts enabled and don't want the real routine called
    200 	 * until masking is set up.
    201 	 */
    202 	fakehand.ih_ipl = ipl;
    203 	fakehand.ih_fun = fakeintr;
    204 	*p = &fakehand;
    205 
    206 	/*
    207 	 * Poke the real handler in now.
    208 	 */
    209 	ih->ih_fun = ih_fun;
    210 	ih->ih_arg = ih_arg;
    211 	ih->ih_next = NULL;
    212 	ih->ih_ipl = ipl;
    213 	ih->ih_virq = virq;
    214 	*p = ih;
    215 
    216 	if (pic->pic_establish_irq != NULL)
    217 		pic->pic_establish_irq(pic, hwirq - pic->pic_intrbase,
    218 		    is->is_type, maxipl);
    219 
    220 	/*
    221 	 * Remember the highest IPL used by this handler.
    222 	 */
    223 	is->is_ipl = maxipl;
    224 
    225 	/*
    226 	 * now that the handler is established we're actually ready to
    227 	 * calculate the masks
    228 	 */
    229 	intr_calculatemasks();
    230 
    231 
    232 	return ih;
    233 }
    234 
    235 void
    236 dummy_pic_establish_intr(struct pic_ops *pic, int irq, int type, int pri)
    237 {
    238 }
    239 
    240 /*
    241  * Deregister an interrupt handler.
    242  */
    243 void
    244 intr_disestablish(void *arg)
    245 {
    246 	struct intrhand * const ih = arg;
    247 	const int virq = ih->ih_virq;
    248 	struct intr_source * const is = &intrsources[virq];
    249 	struct intrhand **p, **q;
    250 	int maxipl = IPL_NONE;
    251 
    252 	if (!PIC_VIRQ_LEGAL_P(virq))
    253 		panic("intr_disestablish: bogus virq %d", virq);
    254 
    255 	/*
    256 	 * Remove the handler from the chain.
    257 	 * This is O(n^2), too.
    258 	 */
    259 	for (p = &is->is_hand, q = NULL; (*p) != NULL; p = &(*p)->ih_next) {
    260 		struct intrhand * const tmp_ih = *p;
    261 		if (tmp_ih == ih) {
    262 			q = p;
    263 		} else {
    264 			maxipl = max(maxipl, tmp_ih->ih_ipl);
    265 		}
    266 	}
    267 	if (q)
    268 		*q = ih->ih_next;
    269 	else
    270 		panic("intr_disestablish: handler not registered");
    271 	free((void *)ih, M_DEVBUF);
    272 
    273 	/*
    274 	 * Reset the IPL for this source now that we've removed a handler.
    275 	 */
    276 	is->is_ipl = maxipl;
    277 
    278 	intr_calculatemasks();
    279 
    280 	if (is->is_hand == NULL) {
    281 		is->is_type = IST_NONE;
    282 		evcnt_detach(&is->is_ev);
    283 		/*
    284 		 * Make the virutal IRQ available again.
    285 		 */
    286 		virq_map[virq] = 0;
    287 		virq_mask |= PIC_VIRQ_TO_MASK(virq);
    288 	}
    289 }
    290 
    291 /*
    292  * Map max_base irqs into 32 (bits).
    293  */
    294 static int
    295 mapirq(int hwirq)
    296 {
    297 	struct pic_ops *pic;
    298 
    299 	if (hwirq >= max_base)
    300 		panic("invalid irq %d", hwirq);
    301 
    302 	if ((pic = find_pic_by_hwirq(hwirq)) == NULL)
    303 		panic("%s: cannot find PIC for HWIRQ %d", __func__, hwirq);
    304 
    305 	if (virq_map[hwirq])
    306 		return virq_map[hwirq];
    307 
    308 	if (virq_mask == 0)
    309 		panic("virq overflow");
    310 
    311 	const int virq = PIC_VIRQ_MS_PENDING(virq_mask);
    312 	struct intr_source * const is = intrsources + virq;
    313 
    314 	virq_mask &= ~PIC_VIRQ_TO_MASK(virq);
    315 
    316 	is->is_hwirq = hwirq;
    317 	is->is_pic = pic;
    318 	virq_map[hwirq] = virq;
    319 #ifdef PIC_DEBUG
    320 	printf("mapping hwirq %d to virq %d\n", irq, virq);
    321 #endif
    322 	return virq;
    323 }
    324 
    325 static const char * const intr_typenames[] = {
    326    [IST_NONE]  = "none",
    327    [IST_PULSE] = "pulsed",
    328    [IST_EDGE]  = "edge-triggered",
    329    [IST_LEVEL] = "level-triggered",
    330 };
    331 
    332 const char *
    333 intr_typename(int type)
    334 {
    335 	KASSERT((unsigned int) type < __arraycount(intr_typenames));
    336 	KASSERT(intr_typenames[type] != NULL);
    337 	return intr_typenames[type];
    338 }
    339 
    340 /*
    341  * Recalculate the interrupt masks from scratch.
    342  * We could code special registry and deregistry versions of this function that
    343  * would be faster, but the code would be nastier, and we don't expect this to
    344  * happen very much anyway.
    345  */
    346 static void
    347 intr_calculatemasks(void)
    348 {
    349 	imask_t newmask[NIPL] = { [IPL_NONE...IPL_HIGH] = 0 };
    350 	struct intr_source *is;
    351 	int irq;
    352 
    353 	for (u_int ipl = IPL_NONE; ipl < NIPL; ipl++) {
    354 		newmask[ipl] = 0;
    355 	}
    356 
    357 	/* First, figure out which ipl each IRQ uses. */
    358 	for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) {
    359 		newmask[is->is_ipl] |= PIC_VIRQ_TO_MASK(irq);
    360 	}
    361 
    362 	/*
    363 	 * IPL_NONE is used for hardware interrupts that are never blocked,
    364 	 * and do not block anything else.
    365 	 */
    366 	newmask[IPL_NONE] = 0;
    367 
    368 	/*
    369 	 * strict hierarchy - all IPLs block everything blocked by any lower
    370 	 * IPL
    371 	 */
    372 	for (u_int ipl = 1; ipl < NIPL; ipl++) {
    373 		newmask[ipl] |= newmask[ipl - 1];
    374 	}
    375 
    376 #ifdef DEBUG_IPL
    377 	for (u_int ipl = 0; ipl < NIPL; ipl++) {
    378 		printf("%u: %08x -> %08x\n", ipl, imask[ipl], newmask[ipl]);
    379 	}
    380 #endif
    381 
    382 	/*
    383 	 * Disable all interrupts.
    384 	 */
    385 	for (u_int base = 0; base < num_pics; base++) {
    386 		struct pic_ops * const pic = pics[base];
    387 		for (u_int i = 0; i < pic->pic_numintrs; i++) {
    388 			pic->pic_disable_irq(pic, i);
    389 		}
    390 	}
    391 
    392 	/*
    393 	 * Now that all interrupts are disabled, update the ipl masks.
    394 	 */
    395 	for (u_int ipl = 0; ipl < NIPL; ipl++) {
    396 		imask[ipl] = newmask[ipl];
    397 	}
    398 
    399 	/*
    400 	 * Lastly, enable IRQs actually in use.
    401 	 */
    402 	for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) {
    403 		if (is->is_hand)
    404 			pic_enable_irq(is->is_hwirq);
    405 	}
    406 }
    407 
    408 void
    409 pic_enable_irq(int hwirq)
    410 {
    411 	struct pic_ops * const pic = find_pic_by_hwirq(hwirq);
    412 	if (pic == NULL)
    413 		panic("%s: bogus IRQ %d", __func__, hwirq);
    414 	const int type = intrsources[virq_map[hwirq]].is_type;
    415 	(*pic->pic_enable_irq)(pic, hwirq - pic->pic_intrbase, type);
    416 }
    417 
    418 void
    419 pic_mark_pending(int hwirq)
    420 {
    421 	struct cpu_info * const ci = curcpu();
    422 
    423 	const int virq = virq_map[hwirq];
    424 	if (virq == 0)
    425 		printf("IRQ %d maps to 0\n", hwirq);
    426 
    427 	const register_t msr = mfmsr();
    428 	mtmsr(msr & ~PSL_EE);
    429 	ci->ci_ipending |= PIC_VIRQ_TO_MASK(virq);
    430 	mtmsr(msr);
    431 }
    432 
    433 static void
    434 intr_deliver(struct intr_source *is, int virq)
    435 {
    436 	bool locked = false;
    437 	for (struct intrhand *ih = is->is_hand; ih != NULL; ih = ih->ih_next) {
    438 		KASSERTMSG(ih->ih_fun != NULL,
    439 		    ("%s: irq %d, hwirq %d, is %p ih %p: "
    440 		     "NULL interrupt handler!\n", __func__,
    441 		     virq, is->is_hwirq, is, ih));
    442 		if (ih->ih_ipl == IPL_VM) {
    443 			if (!locked) {
    444 				KERNEL_LOCK(1, NULL);
    445 				locked = true;
    446 			}
    447 		} else if (locked) {
    448 			KERNEL_UNLOCK_ONE(NULL);
    449 			locked = false;
    450 		}
    451 		(*ih->ih_fun)(ih->ih_arg);
    452 	}
    453 	if (locked) {
    454 		KERNEL_UNLOCK_ONE(NULL);
    455 	}
    456 	is->is_ev.ev_count++;
    457 }
    458 
    459 void
    460 pic_do_pending_int(void)
    461 {
    462 	struct cpu_info * const ci = curcpu();
    463 	imask_t vpend;
    464 
    465 	if (ci->ci_iactive)
    466 		return;
    467 
    468 	ci->ci_iactive = 1;
    469 
    470 	const register_t emsr = mfmsr();
    471 	const register_t dmsr = emsr & ~PSL_EE;
    472 
    473 	KASSERT(emsr & PSL_EE);
    474 	mtmsr(dmsr);
    475 
    476 	const int pcpl = ci->ci_cpl;
    477 #ifdef __HAVE_FAST_SOFTINTS
    478 again:
    479 #endif
    480 
    481 	/* Do now unmasked pendings */
    482 	while ((vpend = (ci->ci_ipending & ~imask[pcpl])) != 0) {
    483 		ci->ci_idepth++;
    484 		KASSERT((PIC_VIRQ_TO_MASK(0) & ci->ci_ipending) == 0);
    485 
    486 		/* Get most significant pending bit */
    487 		const int virq = PIC_VIRQ_MS_PENDING(vpend);
    488 		ci->ci_ipending &= ~PIC_VIRQ_TO_MASK(virq);
    489 
    490 		struct intr_source * const is = &intrsources[virq];
    491 		struct pic_ops * const pic = is->is_pic;
    492 
    493 		splraise(is->is_ipl);
    494 		mtmsr(emsr);
    495 		intr_deliver(is, virq);
    496 		mtmsr(dmsr);
    497 		ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */
    498 
    499 		pic->pic_reenable_irq(pic, is->is_hwirq - pic->pic_intrbase,
    500 		    is->is_type);
    501 		ci->ci_idepth--;
    502 	}
    503 
    504 #ifdef __HAVE_FAST_SOFTINTS
    505 	const u_int softints = (ci->ci_data.cpu_softints << pcpl) & IPL_SOFTMASK;
    506 
    507 	if (__predict_false(softints != 0)) {
    508 		ci->ci_cpl = IPL_HIGH;
    509 		mtmsr(emsr);
    510 		powerpc_softint(ci, pcpl,
    511 		    (vaddr_t)__builtin_return_address(0));
    512 		mtmsr(dmsr);
    513 		ci->ci_cpl = pcpl;
    514 		if (__predict_false(ci->ci_ipending & ~imask[pcpl]))
    515 			goto again;
    516 	}
    517 #endif
    518 
    519 	ci->ci_iactive = 0;
    520 	mtmsr(emsr);
    521 }
    522 
    523 int
    524 pic_handle_intr(void *cookie)
    525 {
    526 	struct pic_ops *pic = cookie;
    527 	struct cpu_info *ci = curcpu();
    528 	int picirq;
    529 
    530 	picirq = pic->pic_get_irq(pic, PIC_GET_IRQ);
    531 	if (picirq == 255)
    532 		return 0;
    533 
    534 	const register_t msr = mfmsr();
    535 	const int pcpl = ci->ci_cpl;
    536 
    537 	do {
    538 #ifdef MULTIPROCESSOR
    539 		/* THIS IS WRONG XXX */
    540 		if (picirq == ipiops.ppc_ipi_vector) {
    541 			ci->ci_cpl = IPL_HIGH;
    542 			ipi_intr(NULL);
    543 			ci->ci_cpl = pcpl;
    544 			pic->pic_ack_irq(pic, picirq);
    545 			continue;
    546 		}
    547 #endif
    548 
    549 		const int virq = virq_map[picirq + pic->pic_intrbase];
    550 		KASSERT(virq != 0);
    551 		KASSERT(picirq < pic->pic_numintrs);
    552 		imask_t v_imen = PIC_VIRQ_TO_MASK(virq);
    553 		struct intr_source * const is = &intrsources[virq];
    554 
    555 		if ((imask[pcpl] & v_imen) != 0) {
    556 			ci->ci_ipending |= v_imen; /* Masked! Mark this as pending */
    557 			pic->pic_disable_irq(pic, picirq);
    558 		} else {
    559 			/* this interrupt is no longer pending */
    560 			ci->ci_ipending &= ~v_imen;
    561 			ci->ci_idepth++;
    562 
    563 			splraise(is->is_ipl);
    564 			mtmsr(msr | PSL_EE);
    565 			intr_deliver(is, virq);
    566 			mtmsr(msr);
    567 			ci->ci_cpl = pcpl;
    568 
    569 			ci->ci_data.cpu_nintr++;
    570 			ci->ci_idepth--;
    571 		}
    572 		pic->pic_ack_irq(pic, picirq);
    573 	} while ((picirq = pic->pic_get_irq(pic, PIC_GET_RECHECK)) != 255);
    574 
    575 	mtmsr(msr | PSL_EE);
    576 	splx(pcpl);	/* Process pendings. */
    577 	mtmsr(msr);
    578 
    579 	return 0;
    580 }
    581 
    582 void
    583 pic_ext_intr(void)
    584 {
    585 
    586 	KASSERT(pics[primary_pic] != NULL);
    587 	pic_handle_intr(pics[primary_pic]);
    588 
    589 	return;
    590 
    591 }
    592 
    593 int
    594 splraise(int ncpl)
    595 {
    596 	struct cpu_info *ci = curcpu();
    597 	int ocpl;
    598 
    599 	if (ncpl == ci->ci_cpl) return ncpl;
    600 	__asm volatile("sync; eieio");	/* don't reorder.... */
    601 	ocpl = ci->ci_cpl;
    602 	KASSERT(ncpl < NIPL);
    603 	ci->ci_cpl = max(ncpl, ocpl);
    604 	__asm volatile("sync; eieio");	/* reorder protect */
    605 	__insn_barrier();
    606 	return ocpl;
    607 }
    608 
    609 static inline bool
    610 have_pending_intr_p(struct cpu_info *ci, int ncpl)
    611 {
    612 	if (ci->ci_ipending & ~imask[ncpl])
    613 		return true;
    614 #ifdef __HAVE_FAST_SOFTINTS
    615 	if ((ci->ci_data.cpu_softints << ncpl) & IPL_SOFTMASK)
    616 		return true;
    617 #endif
    618 	return false;
    619 }
    620 
    621 void
    622 splx(int ncpl)
    623 {
    624 	struct cpu_info *ci = curcpu();
    625 
    626 	__insn_barrier();
    627 	__asm volatile("sync; eieio");	/* reorder protect */
    628 	ci->ci_cpl = ncpl;
    629 	if (have_pending_intr_p(ci, ncpl))
    630 		pic_do_pending_int();
    631 
    632 	__asm volatile("sync; eieio");	/* reorder protect */
    633 }
    634 
    635 int
    636 spllower(int ncpl)
    637 {
    638 	struct cpu_info *ci = curcpu();
    639 	int ocpl;
    640 
    641 	__insn_barrier();
    642 	__asm volatile("sync; eieio");	/* reorder protect */
    643 	ocpl = ci->ci_cpl;
    644 	ci->ci_cpl = ncpl;
    645 	if (have_pending_intr_p(ci, ncpl))
    646 		pic_do_pending_int();
    647 	__asm volatile("sync; eieio");	/* reorder protect */
    648 	return ocpl;
    649 }
    650 
    651 void
    652 genppc_cpu_configure(void)
    653 {
    654 	aprint_normal("biomask %x netmask %x ttymask %x\n",
    655 	    (u_int)imask[IPL_BIO] & 0x1fffffff,
    656 	    (u_int)imask[IPL_NET] & 0x1fffffff,
    657 	    (u_int)imask[IPL_TTY] & 0x1fffffff);
    658 
    659 	spl0();
    660 }
    661 
    662 #if defined(PIC_PREPIVR) || defined(PIC_I8259)
    663 /*
    664  * isa_intr_alloc needs to be done here, because it needs direct access to
    665  * the various interrupt handler structures.
    666  */
    667 
    668 int
    669 genppc_isa_intr_alloc(isa_chipset_tag_t ic, struct pic_ops *pic,
    670     int mask, int type, int *irq_p)
    671 {
    672 	int irq, vi;
    673 	int maybe_irq = -1;
    674 	int shared_depth = 0;
    675 	struct intr_source *is;
    676 
    677 	if (pic == NULL)
    678 		return 1;
    679 
    680 	for (irq = 0; (mask != 0 && irq < pic->pic_numintrs);
    681 	     mask >>= 1, irq++) {
    682 		if ((mask & 1) == 0)
    683 			continue;
    684 		vi = virq_map[irq + pic->pic_intrbase];
    685 		if (!vi) {
    686 			*irq_p = irq;
    687 			return 0;
    688 		}
    689 		is = &intrsources[vi];
    690 		if (is->is_type == IST_NONE) {
    691 			*irq_p = irq;
    692 			return 0;
    693 		}
    694 		/* Level interrupts can be shared */
    695 		if (type == IST_LEVEL && is->is_type == IST_LEVEL) {
    696 			struct intrhand *ih = is->is_hand;
    697 			int depth;
    698 
    699 			if (maybe_irq == -1) {
    700 				maybe_irq = irq;
    701 				continue;
    702 			}
    703 			for (depth = 0; ih != NULL; ih = ih->ih_next)
    704 				depth++;
    705 			if (depth < shared_depth) {
    706 				maybe_irq = irq;
    707 				shared_depth = depth;
    708 			}
    709 		}
    710 	}
    711 	if (maybe_irq != -1) {
    712 		*irq_p = maybe_irq;
    713 		return 0;
    714 	}
    715 	return 1;
    716 }
    717 #endif
    718