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

Cache object: aae573a2e32bb2cb6fb732f6b7941466


[ 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.