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