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/mips/mips/intr_machdep.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2006 Oleksandr Tymoshenko
    3  * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions, and the following disclaimer,
   11  *    without modification, immediately at the beginning of the file.
   12  * 2. The name of the author may not be used to endorse or promote products
   13  *    derived from this software without specific prior written permission.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.4/sys/mips/mips/intr_machdep.c 215938 2010-11-27 12:26:40Z jchandra $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/interrupt.h>
   36 
   37 #include <machine/clock.h>
   38 #include <machine/cpu.h>
   39 #include <machine/cpufunc.h>
   40 #include <machine/cpuinfo.h>
   41 #include <machine/cpuregs.h>
   42 #include <machine/frame.h>
   43 #include <machine/intr_machdep.h>
   44 #include <machine/md_var.h>
   45 #include <machine/trap.h>
   46 
   47 static struct intr_event *hardintr_events[NHARD_IRQS];
   48 static struct intr_event *softintr_events[NSOFT_IRQS];
   49 static mips_intrcnt_t mips_intr_counters[NSOFT_IRQS + NHARD_IRQS];
   50 
   51 static int intrcnt_index;
   52 
   53 static cpu_intr_mask_t          hardintr_mask_func;
   54 static cpu_intr_unmask_t        hardintr_unmask_func;
   55 
   56 mips_intrcnt_t
   57 mips_intrcnt_create(const char* name)
   58 {
   59         mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
   60 
   61         mips_intrcnt_setname(counter, name);
   62         return counter;
   63 }
   64 
   65 void
   66 mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
   67 {
   68         int idx = counter - intrcnt;
   69 
   70         KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
   71 
   72         snprintf(intrnames + (MAXCOMLEN + 1) * idx,
   73             MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
   74 }
   75 
   76 static void
   77 mips_mask_hard_irq(void *source)
   78 {
   79         uintptr_t irq = (uintptr_t)source;
   80 
   81         mips_wr_status(mips_rd_status() & ~(((1 << irq) << 8) << 2));
   82 }
   83 
   84 static void
   85 mips_unmask_hard_irq(void *source)
   86 {
   87         uintptr_t irq = (uintptr_t)source;
   88 
   89         mips_wr_status(mips_rd_status() | (((1 << irq) << 8) << 2));
   90 }
   91 
   92 static void
   93 mips_mask_soft_irq(void *source)
   94 {
   95         uintptr_t irq = (uintptr_t)source;
   96 
   97         mips_wr_status(mips_rd_status() & ~((1 << irq) << 8));
   98 }
   99 
  100 static void
  101 mips_unmask_soft_irq(void *source)
  102 {
  103         uintptr_t irq = (uintptr_t)source;
  104 
  105         mips_wr_status(mips_rd_status() | ((1 << irq) << 8));
  106 }
  107 
  108 /*
  109  * Perform initialization of interrupts prior to setting 
  110  * handlings
  111  */
  112 void
  113 cpu_init_interrupts()
  114 {
  115         int i;
  116         char name[MAXCOMLEN + 1];
  117 
  118         /*
  119          * Initialize all available vectors so spare IRQ
  120          * would show up in systat output 
  121          */
  122         for (i = 0; i < NSOFT_IRQS; i++) {
  123                 snprintf(name, MAXCOMLEN + 1, "sint%d:", i);
  124                 mips_intr_counters[i] = mips_intrcnt_create(name);
  125         }
  126 
  127         for (i = 0; i < NHARD_IRQS; i++) {
  128                 snprintf(name, MAXCOMLEN + 1, "int%d:", i);
  129                 mips_intr_counters[NSOFT_IRQS + i] = mips_intrcnt_create(name);
  130         }
  131 }
  132 
  133 void
  134 cpu_set_hardintr_mask_func(cpu_intr_mask_t func)
  135 {
  136 
  137         hardintr_mask_func = func;
  138 }
  139 
  140 void
  141 cpu_set_hardintr_unmask_func(cpu_intr_unmask_t func)
  142 {
  143 
  144         hardintr_unmask_func = func;
  145 }
  146 
  147 void
  148 cpu_establish_hardintr(const char *name, driver_filter_t *filt,
  149     void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
  150 {
  151         struct intr_event *event;
  152         int error;
  153 
  154         /*
  155          * We have 6 levels, but thats 0 - 5 (not including 6)
  156          */
  157         if (irq < 0 || irq >= NHARD_IRQS)
  158                 panic("%s called for unknown hard intr %d", __func__, irq);
  159 
  160         if (hardintr_mask_func == NULL)
  161                 hardintr_mask_func = mips_mask_hard_irq;
  162 
  163         if (hardintr_unmask_func == NULL)
  164                 hardintr_unmask_func = mips_unmask_hard_irq;
  165 
  166         event = hardintr_events[irq];
  167         if (event == NULL) {
  168                 error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
  169                     irq, hardintr_mask_func, hardintr_unmask_func,
  170                     NULL, NULL, "int%d", irq);
  171                 if (error)
  172                         return;
  173                 hardintr_events[irq] = event;
  174                 mips_unmask_hard_irq((void*)(uintptr_t)irq);
  175         }
  176 
  177         intr_event_add_handler(event, name, filt, handler, arg,
  178             intr_priority(flags), flags, cookiep);
  179 
  180         mips_intrcnt_setname(mips_intr_counters[NSOFT_IRQS + irq],
  181                              event->ie_fullname);
  182 }
  183 
  184 void
  185 cpu_establish_softintr(const char *name, driver_filter_t *filt,
  186     void (*handler)(void*), void *arg, int irq, int flags,
  187     void **cookiep)
  188 {
  189         struct intr_event *event;
  190         int error;
  191 
  192 #if 0
  193         printf("Establish SOFT IRQ %d: filt %p handler %p arg %p\n",
  194             irq, filt, handler, arg);
  195 #endif
  196         if (irq < 0 || irq > NSOFT_IRQS)
  197                 panic("%s called for unknown hard intr %d", __func__, irq);
  198 
  199         event = softintr_events[irq];
  200         if (event == NULL) {
  201                 error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
  202                     irq, mips_mask_soft_irq, mips_unmask_soft_irq,
  203                     NULL, NULL, "sint%d:", irq);
  204                 if (error)
  205                         return;
  206                 softintr_events[irq] = event;
  207                 mips_unmask_soft_irq((void*)(uintptr_t)irq);
  208         }
  209 
  210         intr_event_add_handler(event, name, filt, handler, arg,
  211             intr_priority(flags), flags, cookiep);
  212 
  213         mips_intrcnt_setname(mips_intr_counters[irq], event->ie_fullname);
  214 }
  215 
  216 void
  217 cpu_intr(struct trapframe *tf)
  218 {
  219         struct intr_event *event;
  220         register_t cause, status;
  221         int hard, i, intr;
  222 
  223         critical_enter();
  224 
  225         cause = mips_rd_cause();
  226         status = mips_rd_status();
  227         intr = (cause & MIPS_INT_MASK) >> 8;
  228         /*
  229          * Do not handle masked interrupts. They were masked by 
  230          * pre_ithread function (mips_mask_XXX_intr) and will be 
  231          * unmasked once ithread is through with handler
  232          */
  233         intr &= (status & MIPS_INT_MASK) >> 8;
  234         while ((i = fls(intr)) != 0) {
  235                 intr &= ~(1 << (i - 1));
  236                 switch (i) {
  237                 case 1: case 2:
  238                         /* Software interrupt. */
  239                         i--; /* Get a 0-offset interrupt. */
  240                         hard = 0;
  241                         event = softintr_events[i];
  242                         mips_intrcnt_inc(mips_intr_counters[i]);
  243                         break;
  244                 default:
  245                         /* Hardware interrupt. */
  246                         i -= 2; /* Trim software interrupt bits. */
  247                         i--; /* Get a 0-offset interrupt. */
  248                         hard = 1;
  249                         event = hardintr_events[i];
  250                         mips_intrcnt_inc(mips_intr_counters[NSOFT_IRQS + i]);
  251                         break;
  252                 }
  253 
  254                 if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
  255                         printf("stray %s interrupt %d\n",
  256                             hard ? "hard" : "soft", i);
  257                         continue;
  258                 }
  259 
  260                 if (intr_event_handle(event, tf) != 0) {
  261                         printf("stray %s interrupt %d\n", 
  262                             hard ? "hard" : "soft", i);
  263                 }
  264         }
  265 
  266         KASSERT(i == 0, ("all interrupts handled"));
  267 
  268         critical_exit();
  269 }

Cache object: 910350d54667447adf2b9aa85d6f4ff1


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