The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/extintr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1995 Per Fogelstrom
    3  * Copyright (c) 1993, 1994 Charles M. Hannum.
    4  * Copyright (c) 1990 The Regents of the University of California.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * William Jolitz and Don Ahn.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      $NetBSD: extintr.c,v 1.12 2000/02/14 12:45:52 tsubai Exp $
   39  *      @(#)isa.c       7.2 (Berkeley) 5/12/91
   40  */
   41 
   42 #ifndef lint
   43 static const char rcsid[] =
   44   "$FreeBSD: releng/5.0/sys/powerpc/powerpc/extintr.c 92842 2002-03-20 23:17:50Z alfred $";
   45 #endif /* not lint */
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/bus.h>
   50 #include <sys/lock.h>
   51 #include <sys/mutex.h>
   52 #include <sys/interrupt.h>
   53 #include <sys/malloc.h>
   54 #include <sys/kernel.h>
   55 
   56 #include <vm/vm.h>
   57 #include <vm/vm_kern.h>
   58 
   59 #if 0 /* XXX: Not used yet and may never be. */
   60 #include <machine/autoconf.h>
   61 #endif
   62 
   63 #include <machine/intr.h>
   64 #include <machine/psl.h>
   65 #include <machine/pio.h>
   66 
   67 #include <machine/openpicreg.h>
   68 
   69 #include <dev/ofw/openfirm.h>
   70 
   71 #define NIRQ            32
   72 #define HWIRQ_MAX       (NIRQ - 4 - 1)
   73 #define HWIRQ_MASK      0x0fffffff
   74 
   75 void    intr_calculatemasks(void);
   76 char    *intr_typename(int);
   77 int     fakeintr(void *);
   78 
   79 static __inline int     cntlzw(int);
   80 static __inline int     read_irq(void);
   81 static __inline int     mapirq(int);
   82 static void             enable_irq(int);
   83 
   84 static __inline u_int   openpic_read(int);
   85 static __inline void    openpic_write(int, u_int);
   86 void                    openpic_enable_irq(int);
   87 void                    openpic_disable_irq(int);
   88 void                    openpic_set_priority(int, int);
   89 static __inline int     openpic_read_irq(int);
   90 static __inline void    openpic_eoi(int);
   91 
   92 unsigned int    imen = 0xffffffff;
   93 u_int           cpl, ipending, tickspending;
   94 int             imask[NIPL];
   95 
   96 int             intrtype[NIRQ], intrmask[NIRQ], intrlevel[NIRQ];
   97 struct intrhand *intrhand[NIRQ];
   98 
   99 static u_char   hwirq[NIRQ], virq[ICU_LEN];
  100 static int      virq_max = 0;
  101 
  102 static u_char   *obio_base, *openpic_base;
  103 
  104 #if 0 /* XXX */
  105 extern u_int    *heathrow_FCR;
  106 #endif
  107 
  108 extern void     install_extint(void (*)(void));
  109 
  110 #define interrupt_reg   (obio_base + 0x10)
  111 
  112 #define INT_STATE_REG_H         (interrupt_reg + 0x00)
  113 #define INT_ENABLE_REG_H        (interrupt_reg + 0x04)
  114 #define INT_CLEAR_REG_H         (interrupt_reg + 0x08)
  115 #define INT_LEVEL_REG_H         (interrupt_reg + 0x0c)
  116 #define INT_STATE_REG_L         (interrupt_reg + 0x10)
  117 #define INT_ENABLE_REG_L        (interrupt_reg + 0x14)
  118 #define INT_CLEAR_REG_L         (interrupt_reg + 0x18)
  119 #define INT_LEVEL_REG_L         (interrupt_reg + 0x1c)
  120 
  121 #define have_openpic    (openpic_base != NULL)
  122 
  123 /*
  124  * Map 64 irqs into 32 (bits).
  125  */
  126 int
  127 mapirq(irq)
  128         int     irq;
  129 {
  130         int     v;
  131 
  132         if (irq < 0 || irq >= ICU_LEN)
  133                 panic("invalid irq");
  134         if (virq[irq])
  135                 return virq[irq];
  136 
  137         virq_max++;
  138         v = virq_max;
  139         if (v > HWIRQ_MAX)
  140                 panic("virq overflow");
  141 
  142         hwirq[v] = irq;
  143         virq[irq] = v;
  144 
  145         return v;
  146 }
  147 
  148 /*
  149  * Count leading zeros.
  150  */
  151 static __inline int
  152 cntlzw(x)
  153         int     x;
  154 {
  155         int     a;
  156 
  157         __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
  158 
  159         return a;
  160 }
  161 
  162 int
  163 read_irq()
  164 {
  165         int     rv, lo, hi, p;
  166 
  167         rv = 0;
  168         lo = in32rb(INT_STATE_REG_L);
  169         if (lo)
  170                 out32rb(INT_CLEAR_REG_L, lo);
  171         while (lo) {
  172                 p = 31 - cntlzw(lo);
  173                 rv |= 1 << virq[p];
  174                 lo &= ~(1 << p);
  175         }
  176 
  177 #if 0 /* XXX */
  178         if (heathrow_FCR)                       /* has heathrow? */
  179                 hi = in32rb(INT_STATE_REG_H);
  180         else
  181 #endif
  182                 hi = 0;
  183 
  184         if (hi)
  185                 out32rb(INT_CLEAR_REG_H, hi);
  186         while (hi) {
  187                 p = 31 - cntlzw(hi);
  188                 rv |= 1 << virq[p + 32];
  189                 hi &= ~(1 << p);
  190         }
  191 
  192         /* 1 << 0 is invalid. */
  193         return rv & ~1;
  194 }
  195 
  196 void
  197 enable_irq(x)
  198         int     x;
  199 {
  200         int     lo, hi, v, irq;
  201 
  202         x &= HWIRQ_MASK;        /* XXX Higher bits are software interrupts. */
  203 
  204         lo = hi = 0;
  205         while (x) {
  206                 v = 31 - cntlzw(x);
  207                 irq = hwirq[v];
  208                 if (irq < 32)
  209                         lo |= 1 << irq;
  210                 else
  211                         hi |= 1 << (irq - 32);
  212                 x &= ~(1 << v);
  213         }
  214 
  215         out32rb(INT_ENABLE_REG_L, lo);
  216 #if 0 /* XXX */
  217         if (heathrow_FCR)
  218                 out32rb(INT_ENABLE_REG_H, hi);
  219 #endif
  220 }
  221 
  222 u_int
  223 openpic_read(reg)
  224         int     reg;
  225 {
  226         char    *addr;
  227 
  228         addr = openpic_base + reg;
  229 
  230         return in32rb(addr);
  231 }
  232 
  233 void
  234 openpic_write(reg, val)
  235         int     reg;
  236         u_int   val;
  237 {
  238         char    *addr;
  239 
  240         addr = openpic_base + reg;
  241 
  242         out32rb(addr, val);
  243 }
  244 
  245 void
  246 openpic_enable_irq(irq)
  247         int     irq;
  248 {
  249         u_int   x;
  250 
  251         x = openpic_read(OPENPIC_SRC_VECTOR(irq));
  252         x &= ~OPENPIC_IMASK;
  253         openpic_write(OPENPIC_SRC_VECTOR(irq), x);
  254 }
  255 
  256 void
  257 openpic_disable_irq(irq)
  258         int     irq;
  259 {
  260         u_int   x;
  261 
  262         x = openpic_read(OPENPIC_SRC_VECTOR(irq));
  263         x |= OPENPIC_IMASK;
  264         openpic_write(OPENPIC_SRC_VECTOR(irq), x);
  265 }
  266 
  267 void
  268 openpic_set_priority(cpu, pri)
  269         int     cpu, pri;
  270 {
  271         u_int   x;
  272 
  273         x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
  274         x &= ~OPENPIC_CPU_PRIORITY_MASK;
  275         x |= pri;
  276         openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
  277 }
  278 
  279 int
  280 openpic_read_irq(cpu)
  281         int     cpu;
  282 {
  283         return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
  284 }
  285 
  286 void
  287 openpic_eoi(cpu)
  288         int     cpu;
  289 {
  290         openpic_write(OPENPIC_EOI(cpu), 0);
  291         openpic_read(OPENPIC_EOI(cpu));
  292 }
  293 
  294 /*
  295  * Recalculate the interrupt masks from scratch.
  296  * We could code special registry and deregistry versions of this function that
  297  * would be faster, but the code would be nastier, and we don't expect this to
  298  * happen very much anyway.
  299  */
  300 void
  301 intr_calculatemasks()
  302 {
  303         int     irq, level, irqs;
  304         struct intrhand *q;
  305 
  306         irqs = 0;
  307 
  308         /* First, figure out which levels each IRQ uses. */
  309 #if 0 /* XXX */
  310         for (irq = 0; irq < NIRQ; irq++) {
  311                 register int levels = 0;
  312                 for (q = intrhand[irq]; q; q = q->ih_next)
  313                         levels |= 1 << q->ih_level;
  314                 intrlevel[irq] = levels;
  315         }
  316 #endif
  317 
  318         /* Then figure out which IRQs use each level. */
  319         for (level = 0; level < NIPL; level++) {
  320                 register int irqs = 0;
  321                 for (irq = 0; irq < NIRQ; irq++)
  322                         if (intrlevel[irq] & (1 << level))
  323                                 irqs |= 1 << irq;
  324                 imask[level] = irqs;
  325         }
  326 
  327         /*
  328          * IPL_CLOCK should mask clock interrupt even if interrupt handler
  329          * is not registered.
  330          */
  331         imask[IPL_CLOCK] |= 1 << SPL_CLOCK;
  332 
  333         /*
  334          * Initialize soft interrupt masks to block themselves.
  335          */
  336         imask[IPL_SOFTCLOCK] = 1 << SIR_CLOCK;
  337         imask[IPL_SOFTNET] = 1 << SIR_NET;
  338         imask[IPL_SOFTSERIAL] = 1 << SIR_SERIAL;
  339 
  340         /*
  341          * IPL_NONE is used for hardware interrupts that are never blocked,
  342          * and do not block anything else.
  343          */
  344         imask[IPL_NONE] = 0;
  345 
  346         /*
  347          * Enforce a hierarchy that gives slow devices a better chance at not
  348          * dropping data.
  349          */
  350         imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
  351         imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
  352         imask[IPL_BIO] |= imask[IPL_SOFTNET];
  353         imask[IPL_NET] |= imask[IPL_BIO];
  354         imask[IPL_SOFTSERIAL] |= imask[IPL_NET];
  355         imask[IPL_TTY] |= imask[IPL_SOFTSERIAL];
  356 
  357         /*
  358          * There are tty, network and disk drivers that use free() at interrupt
  359          * time, so imp > (tty | net | bio).
  360          */
  361         imask[IPL_IMP] |= imask[IPL_TTY];
  362 
  363         imask[IPL_AUDIO] |= imask[IPL_IMP];
  364 
  365         /*
  366          * Since run queues may be manipulated by both the statclock and tty,
  367          * network, and disk drivers, clock > imp.
  368          */
  369         imask[IPL_CLOCK] |= imask[IPL_AUDIO];
  370 
  371         /*
  372          * IPL_HIGH must block everything that can manipulate a run queue.
  373          */
  374         imask[IPL_HIGH] |= imask[IPL_CLOCK];
  375 
  376         /*
  377          * We need serial drivers to run at the absolute highest priority to
  378          * avoid overruns, so serial > high.
  379          */
  380         imask[IPL_SERIAL] |= imask[IPL_HIGH];
  381 
  382         /* And eventually calculate the complete masks. */
  383 #if 0 /* XXX */
  384         for (irq = 0; irq < NIRQ; irq++) {
  385                 register int irqs = 1 << irq;
  386                 for (q = intrhand[irq]; q; q = q->ih_next)
  387                         irqs |= imask[q->ih_level];
  388                 intrmask[irq] = irqs;
  389         }
  390 #endif
  391 
  392         /* Lastly, determine which IRQs are actually in use. */
  393         for (irq = 0; irq < NIRQ; irq++)
  394                 if (intrhand[irq])
  395                         irqs |= 1 << irq;
  396 
  397         if (have_openpic) {
  398                 for (irq = 0; irq < NIRQ; irq++) {
  399                         if (irqs & (1 << irq))
  400                                 openpic_enable_irq(hwirq[irq]);
  401                         else
  402                                 openpic_disable_irq(hwirq[irq]);
  403                 }
  404         } else {
  405                 imen = ~irqs;
  406                 enable_irq(~imen);
  407         }
  408 }
  409 
  410 int
  411 fakeintr(arg)
  412         void *arg;
  413 {
  414 
  415         return 0;
  416 }
  417 
  418 #define LEGAL_IRQ(x)    ((x) >= 0 && (x) < NIRQ)
  419 
  420 char *
  421 intr_typename(type)
  422         int     type;
  423 {
  424 
  425         switch (type) {
  426         case IST_NONE :
  427                 return ("none");
  428         case IST_PULSE:
  429                 return ("pulsed");
  430         case IST_EDGE:
  431                 return ("edge-triggered");
  432         case IST_LEVEL:
  433                 return ("level-triggered");
  434         default:
  435                 panic("intr_typename: invalid type %d", type);
  436 #if 1 /* XXX */
  437                 return ("unknown");
  438 #endif
  439         }
  440 }
  441 
  442 /*
  443  * Register an interrupt handler.
  444  */
  445 void *
  446 intr_establish(int irq, int type, int level, int (*ih_fun)(void *),
  447     void *ih_arg)
  448 {
  449         struct intrhand         **p, *q, *ih;
  450         static struct intrhand  fakehand = {fakeintr};
  451 
  452         irq = mapirq(irq);
  453 
  454         /* no point in sleeping unless someone can free memory. */
  455         ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
  456         if (ih == NULL)
  457                 panic("intr_establish: can't malloc handler info");
  458 
  459         if (!LEGAL_IRQ(irq) || type == IST_NONE)
  460                 panic("intr_establish: bogus irq or type");
  461 
  462         switch (intrtype[irq]) {
  463         case IST_NONE:
  464                 intrtype[irq] = type;
  465                 break;
  466         case IST_EDGE:
  467         case IST_LEVEL:
  468                 if (type == intrtype[irq])
  469                         break;
  470         case IST_PULSE:
  471                 if (type != IST_NONE)
  472                         panic("intr_establish: can't share %s with %s",
  473                             intr_typename(intrtype[irq]),
  474                             intr_typename(type));
  475                 break;
  476         }
  477 
  478         /*
  479          * Figure out where to put the handler.
  480          * This is O(N^2), but we want to preserve the order, and N is
  481          * generally small.
  482          */
  483 #if 0 /* XXX */
  484         for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
  485                 ;
  486 #endif
  487 
  488         /*
  489          * Actually install a fake handler momentarily, since we might be doing
  490          * this with interrupts enabled and don't want the real routine called
  491          * until masking is set up.
  492          */
  493 #if 0 /* XXX */
  494         fakehand.ih_level = level;
  495 #endif
  496         *p = &fakehand;
  497 
  498         intr_calculatemasks();
  499 
  500         /*
  501          * Poke the real handler in now.
  502          */
  503 #if 0
  504         ih->ih_fun = ih_fun;
  505         ih->ih_arg = ih_arg;
  506         ih->ih_count = 0;
  507         ih->ih_next = NULL;
  508         ih->ih_level = level;
  509         ih->ih_irq = irq;
  510 #endif
  511         *p = ih;
  512 
  513         return (ih);
  514 }
  515 
  516 /*
  517  * Deregister an interrupt handler.
  518  */
  519 void
  520 intr_disestablish(void *arg)
  521 {
  522         struct intrhand *ih, **p, *q;
  523         int             irq;
  524 
  525 #if 0 /* XXX */
  526         irq = ih->ih_irq;
  527 #endif
  528 
  529         ih = arg;
  530 
  531         if (!LEGAL_IRQ(irq))
  532                 panic("intr_disestablish: bogus irq");
  533 
  534         /*
  535          * Remove the handler from the chain.
  536          * This is O(n^2), too.
  537          */
  538         for (p = &intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
  539                 ;
  540         if (q)
  541 #if 0 /* XXX */
  542                 *p = q->ih_next;
  543 #else
  544                 p = p;
  545 #endif
  546         else
  547                 panic("intr_disestablish: handler not registered");
  548         free((void *)ih, M_DEVBUF);
  549 
  550         intr_calculatemasks();
  551 
  552         if (intrhand[irq] == NULL)
  553                 intrtype[irq] = IST_NONE;
  554 }
  555 
  556 /*
  557  * external interrupt handler
  558  */
  559 void
  560 ext_intr(void)
  561 {
  562         int             irq;
  563         int             o_imen, r_imen;
  564         int             pcpl;
  565         struct intrhand *ih;
  566         volatile unsigned long  int_state;
  567 
  568         pcpl = splhigh();       /* Turn off all */
  569 
  570         int_state = read_irq();
  571         if (int_state == 0)
  572                 goto out;
  573 
  574 start:
  575         irq = 31 - cntlzw(int_state);
  576 
  577         o_imen = imen;
  578         r_imen = 1 << irq;
  579 
  580         if ((pcpl & r_imen) != 0) {
  581                 ipending |= r_imen;     /* Masked! Mark this as pending */
  582                 imen |= r_imen;
  583                 enable_irq(~imen);
  584         } else {
  585                 ih = intrhand[irq];
  586                 while (ih) {
  587 #if 0 /* XXX */
  588                         (*ih->ih_fun)(ih->ih_arg);
  589                         ih = ih->ih_next;
  590 #endif
  591                 }
  592 
  593                 intrcnt[hwirq[irq]]++;
  594         }
  595 
  596         int_state &= ~r_imen;
  597         if (int_state)
  598                 goto start;
  599 
  600 out:
  601         splx(pcpl);     /* Process pendings. */
  602 }
  603 
  604 void
  605 ext_intr_openpic()
  606 {
  607         int             irq, realirq;
  608         int             r_imen;
  609         int             pcpl;
  610         struct intrhand *ih;
  611 
  612         pcpl = splhigh();       /* Turn off all */
  613 
  614         realirq = openpic_read_irq(0);
  615         if (realirq == 255) {
  616                 printf("sprious interrupt\n");
  617                 goto out;
  618         }
  619 
  620 start:
  621         irq = virq[realirq];
  622 
  623         /* XXX check range */
  624 
  625         r_imen = 1 << irq;
  626 
  627         if ((pcpl & r_imen) != 0) {
  628                 ipending |= r_imen;     /* Masked! Mark this as pending */
  629                 openpic_disable_irq(realirq);
  630         } else {
  631                 ih = intrhand[irq];
  632                 while (ih) {
  633 #if 0 /* XXX */
  634                         (*ih->ih_fun)(ih->ih_arg);
  635                         ih = ih->ih_next;
  636 #endif
  637                 }
  638 
  639                 intrcnt[hwirq[irq]]++;
  640         }
  641 
  642         openpic_eoi(0);
  643 
  644         realirq = openpic_read_irq(0);
  645         if (realirq != 255)
  646                 goto start;
  647 
  648 out:
  649         splx(pcpl);     /* Process pendings. */
  650 }
  651 
  652 void
  653 do_pending_int()
  654 {
  655         struct intrhand *ih;
  656         int             irq;
  657         int             pcpl;
  658         int             hwpend;
  659         int             emsr, dmsr;
  660         static int      processing;
  661 
  662         return; /* XXX */
  663 
  664         if (processing)
  665                 return;
  666 
  667         processing = 1;
  668         emsr = mfmsr();
  669         dmsr = emsr & ~PSL_EE;
  670         mtmsr(dmsr);
  671 
  672         pcpl = splhigh();               /* Turn off all */
  673         hwpend = ipending & ~pcpl;      /* Do now unmasked pendings */
  674         if (!have_openpic) {
  675                 imen &= ~hwpend;
  676                 enable_irq(~imen);
  677         }
  678         hwpend &= HWIRQ_MASK;
  679         while (hwpend) {
  680                 irq = 31 - cntlzw(hwpend);
  681                 hwpend &= ~(1L << irq);
  682                 ih = intrhand[irq];
  683                 while(ih) {
  684 #if 0 /* XXX */
  685                         (*ih->ih_fun)(ih->ih_arg);
  686                         ih = ih->ih_next;
  687 #endif
  688                 }
  689 
  690                 intrcnt[hwirq[irq]]++;
  691                 if (have_openpic)
  692                         openpic_enable_irq(hwirq[irq]);
  693         }
  694 
  695         /*out32rb(INT_ENABLE_REG, ~imen);*/
  696 
  697         if ((ipending & ~pcpl) & (1 << SIR_CLOCK)) {
  698                 ipending &= ~(1 << SIR_CLOCK);
  699                 softclock(NULL);
  700                 intrcnt[CNT_SOFTCLOCK]++;
  701         }
  702 #if 0 /* XXX */
  703         if ((ipending & ~pcpl) & (1 << SIR_NET)) {
  704                 ipending &= ~(1 << SIR_NET);
  705                 softnet();
  706                 intrcnt[CNT_SOFTNET]++;
  707         }
  708         if ((ipending & ~pcpl) & (1 << SIR_SERIAL)) {
  709                 ipending &= ~(1 << SIR_SERIAL);
  710                 softserial();
  711                 intrcnt[CNT_SOFTSERIAL]++;
  712         }
  713 #endif
  714         ipending &= pcpl;
  715         cpl = pcpl;     /* Don't use splx... we are here already! */
  716         mtmsr(emsr);
  717         processing = 0;
  718 }
  719 
  720 void
  721 openpic_init(void)
  722 {
  723         int     irq;
  724         u_int   x;
  725 
  726         /* disable all interrupts */
  727         for (irq = 0; irq < 256; irq++)
  728                 openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
  729 
  730         openpic_set_priority(0, 15);
  731 
  732         /* we don't need 8259 pass through mode */
  733         x = openpic_read(OPENPIC_CONFIG);
  734         x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
  735         openpic_write(OPENPIC_CONFIG, x);
  736 
  737         /* send all interrupts to cpu 0 */
  738         for (irq = 0; irq < ICU_LEN; irq++)
  739                 openpic_write(OPENPIC_IDEST(irq), 1 << 0);
  740 
  741         for (irq = 0; irq < ICU_LEN; irq++) {
  742                 x = irq;
  743                 x |= OPENPIC_IMASK;
  744                 x |= OPENPIC_POLARITY_POSITIVE;
  745                 x |= OPENPIC_SENSE_LEVEL;
  746                 x |= 8 << OPENPIC_PRIORITY_SHIFT;
  747                 openpic_write(OPENPIC_SRC_VECTOR(irq), x);
  748         }
  749 
  750         /* XXX set spurious intr vector */
  751 
  752         openpic_set_priority(0, 0);
  753 
  754         /* clear all pending interrunts */
  755         for (irq = 0; irq < 256; irq++) {
  756                 openpic_read_irq(0);
  757                 openpic_eoi(0);
  758         }
  759 
  760         for (irq = 0; irq < ICU_LEN; irq++)
  761                 openpic_disable_irq(irq);
  762 
  763         install_extint(ext_intr_openpic);
  764 }
  765 
  766 void
  767 legacy_int_init(void)
  768 {
  769         out32rb(INT_ENABLE_REG_L, 0);           /* disable all intr. */
  770         out32rb(INT_CLEAR_REG_L, 0xffffffff);   /* clear pending intr. */
  771 
  772         install_extint(ext_intr);
  773 }
  774 
  775 #define HEATHROW_FCR_OFFSET     0x38            /* XXX should not here */
  776 #define GC_OBIO_BASE            0xf3000000
  777 
  778 void
  779 init_interrupt(void)
  780 {
  781         int     chosen;
  782         int     mac_io, reg[5];
  783         int32_t ictlr;
  784         char    type[32];
  785 
  786         openpic_base = NULL;
  787 
  788         mac_io = OF_finddevice("mac-io");
  789         if (mac_io == -1)
  790                 mac_io = OF_finddevice("/pci/mac-io");
  791 
  792         if (mac_io == -1) {
  793                 /*
  794                  * No mac-io.  Assume Grand-Central or OHare.
  795                  */
  796                 obio_base = (void *)GC_OBIO_BASE;
  797                 legacy_int_init();
  798                 return;
  799         }
  800 
  801         if (OF_getprop(mac_io, "assigned-addresses", reg, sizeof(reg)) < 20)
  802                 goto failed;
  803 
  804         obio_base = (void *)reg[2];
  805 #if 0 /* XXX */
  806         heathrow_FCR = (void *)(obio_base + HEATHROW_FCR_OFFSET);
  807 #endif
  808 
  809         bzero(type, sizeof(type));
  810         chosen = OF_finddevice("/chosen");
  811         if (OF_getprop(chosen, "interrupt-controller", &ictlr, 4) == 4)
  812                 OF_getprop(ictlr, "device_type", type, sizeof(type));
  813 
  814         if (strcmp(type, "open-pic") != 0) {
  815                 /*
  816                  * Not an open-pic.  Must be a Heathrow (compatible).
  817                  */
  818                 legacy_int_init();
  819                 return;
  820         } else {
  821                 /*
  822                  * We have an Open PIC.
  823                  */
  824                 if (OF_getprop(ictlr, "reg", reg, sizeof(reg)) < 8)
  825                         goto failed;
  826 
  827                 openpic_base = (void *)(obio_base + reg[0]);
  828                 openpic_init();
  829                 return;
  830         }
  831 
  832         printf("unknown interrupt controller\n");
  833 failed:
  834         panic("init_interrupt: failed to initialize interrupt controller");
  835 }

Cache object: 96ba1e3473ad8d936d9a61c0c6ca6247


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.