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