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/dev/mvme/vme_two_isr.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 /*      $NetBSD: vme_two_isr.c,v 1.4 2003/07/14 15:47:21 lukem Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Steve C. Woodford.
    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 NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Split off from vme_two.c specifically to deal with hardware assisted
   41  * soft interrupts when the user hasn't specified `vmetwo0' in the
   42  * kernel config file (mvme1[67]2 only).
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __KERNEL_RCSID(0, "$NetBSD: vme_two_isr.c,v 1.4 2003/07/14 15:47:21 lukem Exp $");
   47 
   48 #include "vmetwo.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/kernel.h>
   52 #include <sys/systm.h>
   53 #include <sys/device.h>
   54 #include <sys/malloc.h>
   55 #include <sys/lock.h>
   56 
   57 #include <machine/cpu.h>
   58 #include <machine/bus.h>
   59 
   60 #include <dev/vme/vmereg.h>
   61 #include <dev/vme/vmevar.h>
   62 
   63 #include <dev/mvme/mvmebus.h>
   64 #include <dev/mvme/vme_tworeg.h>
   65 #include <dev/mvme/vme_twovar.h>
   66 
   67 /*
   68  * Non-zero if there is no VMEChip2 on this board.
   69  */
   70 int vmetwo_not_present;
   71 
   72 /*
   73  * Array of interrupt handlers registered with us for the non-VMEbus
   74  * vectored interrupts. Eg. ABORT Switch, SYSFAIL etc.
   75  *
   76  * We can't just install a caller's handler directly, since these
   77  * interrupts have to be manually cleared, so we have a trampoline
   78  * which does the clearing automatically.
   79  */
   80 static struct vme_two_handler {
   81         int (*isr_hand) __P((void *));
   82         void *isr_arg;
   83 } vme_two_handlers[(VME2_VECTOR_LOCAL_MAX - VME2_VECTOR_LOCAL_MIN) + 1];
   84 
   85 #define VMETWO_HANDLERS_SZ      (sizeof(vme_two_handlers) /     \
   86                                  sizeof(struct vme_two_handler))
   87 
   88 static  int  vmetwo_local_isr_trampoline(void *);
   89 static  void vmetwo_softintr_assert(void);
   90 
   91 static  struct vmetwo_softc *vmetwo_sc;
   92 
   93 int
   94 vmetwo_probe(bus_space_tag_t bt, bus_addr_t offset)
   95 {
   96         bus_space_handle_t bh;
   97 
   98         bus_space_map(bt, offset + VME2REG_LCSR_OFFSET, VME2LCSR_SIZE, 0, &bh);
   99 
  100         if (bus_space_peek_4(bt, bh, VME2LCSR_MISC_STATUS, NULL) != 0) {
  101 #if defined(MVME162) || defined(MVME172)
  102 #if defined(MVME167) || defined(MVME177)
  103                 if (machineid == MVME_162 || machineid == MVME_172)
  104 #endif
  105                 {
  106                         /*
  107                          * No VMEChip2 on mvme162/172 is not too big a
  108                          * deal; we can fall back on timer4 in the
  109                          * mcchip for h/w assisted soft interrupts...
  110                          */
  111                         extern void pcctwosoftintrinit(void);
  112                         bus_space_unmap(bt, bh, VME2LCSR_SIZE);
  113                         vmetwo_not_present = 1;
  114                         pcctwosoftintrinit();
  115                         return (0);
  116                 }
  117 #endif
  118 #if defined(MVME167) || defined(MVME177) || defined(MVME88K)
  119                 /*
  120                  * No VMEChip2 on mvme167/177, however, is a Big Deal.
  121                  * In fact, it means the hardware's shot since the
  122                  * VMEChip2 is not a `build-option' on those boards.
  123                  */
  124                 panic("VMEChip2 not responding! Faulty board?");
  125                 /* NOTREACHED */
  126 #endif
  127 #if defined(MVMEPPC)
  128                 /*
  129                  * No VMEChip2 on mvmeppc is no big deal.
  130                  */
  131                 bus_space_unmap(bt, bh, VME2LCSR_SIZE);
  132                 vmetwo_not_present = 1;
  133                 return (0);
  134 #endif
  135         }
  136 #if NVMETWO == 0
  137         else {
  138                 /*
  139                  * The kernel config file has no `vmetwo0' device, but
  140                  * there is a VMEChip2 on the board. Fix up things
  141                  * just enough to hook VMEChip2 local interrupts.
  142                  */
  143                 struct vmetwo_softc *sc;
  144 
  145                 /* XXX Should check sc != NULL here... */
  146                 MALLOC(sc, struct vmetwo_softc *, sizeof(*sc), M_DEVBUF,
  147                     M_NOWAIT);
  148 
  149                 sc->sc_mvmebus.sc_bust = bt;
  150                 sc->sc_lcrh = bh;
  151                 vmetwo_intr_init(sc);
  152                 return 0;
  153         }
  154 #else
  155         bus_space_unmap(bt, bh, VME2LCSR_SIZE);
  156         return (1);
  157 #endif
  158 }
  159 
  160 void
  161 vmetwo_intr_init(struct vmetwo_softc *sc)
  162 {
  163         u_int32_t reg;
  164         int i;
  165 
  166         vmetwo_sc = sc;
  167 
  168         /* Clear out the ISR handler array */
  169         for (i = 0; i < VMETWO_HANDLERS_SZ; i++)
  170                 vme_two_handlers[i].isr_hand = NULL;
  171 
  172         /*
  173          * Initialize the chip.
  174          * Firstly, disable all VMEChip2 Interrupts
  175          */
  176         reg = vme2_lcsr_read(sc, VME2LCSR_MISC_STATUS) & ~VME2_MISC_STATUS_MIEN;
  177         vme2_lcsr_write(sc, VME2LCSR_MISC_STATUS, reg);
  178         vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, 0);
  179         vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
  180             VME2_LOCAL_INTERRUPT_CLEAR_ALL);
  181 
  182         /* Zap all the IRQ level registers */
  183         for (i = 0; i < VME2_NUM_IL_REGS; i++)
  184                 vme2_lcsr_write(sc, VME2LCSR_INTERRUPT_LEVEL_BASE + (i * 4), 0);
  185 
  186         /* Disable the tick timers */
  187         reg = vme2_lcsr_read(sc, VME2LCSR_TIMER_CONTROL);
  188         reg &= ~VME2_TIMER_CONTROL_EN(0);
  189         reg &= ~VME2_TIMER_CONTROL_EN(1);
  190         vme2_lcsr_write(sc, VME2LCSR_TIMER_CONTROL, reg);
  191 
  192         /* Set the VMEChip2's vector base register to the required value */
  193         reg = vme2_lcsr_read(sc, VME2LCSR_VECTOR_BASE);
  194         reg &= ~VME2_VECTOR_BASE_MASK;
  195         reg |= VME2_VECTOR_BASE_REG_VALUE;
  196         vme2_lcsr_write(sc, VME2LCSR_VECTOR_BASE, reg);
  197 
  198         /* Set the Master Interrupt Enable bit now */
  199         reg = vme2_lcsr_read(sc, VME2LCSR_MISC_STATUS) | VME2_MISC_STATUS_MIEN;
  200         vme2_lcsr_write(sc, VME2LCSR_MISC_STATUS, reg);
  201 
  202         /* Allow the MD code the chance to do some initialising */
  203         vmetwo_md_intr_init(sc);
  204 
  205 #if defined(MVME167) || defined(MVME177)
  206 #if defined(MVME162) || defined(MVME172)
  207         if (machineid != MVME_162 && machineid != MVME_172)
  208 #endif
  209         {
  210                 /*
  211                  * Let the NMI handler deal with level 7 ABORT switch
  212                  * interrupts
  213                  */
  214                 vmetwo_intr_establish(sc, 7, 7, VME2_VEC_ABORT, 1,
  215                     nmihand, NULL, NULL);
  216         }
  217 #endif
  218 
  219         /* Setup hardware assisted soft interrupts */
  220         vmetwo_intr_establish(sc, 1, 1, VME2_VEC_SOFT0, 1,
  221             (int (*)(void *))softintr_dispatch, NULL, NULL);
  222         _softintr_chipset_assert = vmetwo_softintr_assert;
  223 }
  224 
  225 static int
  226 vmetwo_local_isr_trampoline(arg)
  227         void *arg;
  228 {
  229         struct vme_two_handler *isr;
  230         int vec;
  231 
  232         vec = (int) arg;        /* 0x08 <= vec <= 0x1f */
  233 
  234         /* Clear the interrupt source */
  235         vme2_lcsr_write(vmetwo_sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
  236             VME2_LOCAL_INTERRUPT(vec));
  237 
  238         isr = &vme_two_handlers[vec - VME2_VECTOR_LOCAL_OFFSET];
  239         if (isr->isr_hand)
  240                 (void) (*isr->isr_hand) (isr->isr_arg);
  241         else
  242                 printf("vmetwo: Spurious local interrupt, vector 0x%x\n", vec);
  243 
  244         return (1);
  245 }
  246 
  247 void
  248 vmetwo_local_intr_establish(pri, vec, hand, arg, evcnt)
  249         int pri, vec;
  250         int (*hand)(void *);
  251         void *arg;
  252         struct evcnt *evcnt;
  253 {
  254 
  255         vmetwo_intr_establish(vmetwo_sc, pri, pri, vec, 1, hand, arg, evcnt);
  256 }
  257 
  258 /* ARGSUSED */
  259 void
  260 vmetwo_intr_establish(csc, prior, lvl, vec, first, hand, arg, evcnt)
  261         void *csc;
  262         int prior, lvl, vec, first;
  263         int (*hand)(void *);
  264         void *arg;
  265         struct evcnt *evcnt;
  266 {
  267         struct vmetwo_softc *sc = csc;
  268         u_int32_t reg;
  269         int bitoff;
  270         int iloffset, ilshift;
  271         int s;
  272 
  273         s = splhigh();
  274 
  275 #if NVMETWO > 0
  276         /*
  277          * Sort out interrupts generated locally by the VMEChip2 from
  278          * those generated by VMEbus devices...
  279          */
  280         if (vec >= VME2_VECTOR_LOCAL_MIN && vec <= VME2_VECTOR_LOCAL_MAX) {
  281 #endif
  282                 /*
  283                  * Local interrupts need to be bounced through some
  284                  * trampoline code which acknowledges/clears them.
  285                  */
  286                 vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_hand = hand;
  287                 vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_arg = arg;
  288                 hand = vmetwo_local_isr_trampoline;
  289                 arg = (void *) (vec - VME2_VECTOR_BASE);
  290 
  291                 /*
  292                  * Interrupt enable/clear bit offset is 0x08 - 0x1f
  293                  */
  294                 bitoff = vec - VME2_VECTOR_BASE;
  295 #if NVMETWO > 0
  296                 first = 1;      /* Force the interrupt to be enabled */
  297         } else {
  298                 /*
  299                  * Interrupts originating from the VMEbus are
  300                  * controlled by an offset of 0x00 - 0x07
  301                  */
  302                 bitoff = lvl - 1;
  303         }
  304 #endif
  305 
  306         /* Hook the interrupt */
  307         (*sc->sc_isrlink)(sc->sc_isrcookie, hand, arg, prior, vec, evcnt);
  308 
  309         /*
  310          * Do we need to tell the VMEChip2 to let the interrupt through?
  311          * (This is always true for locally-generated interrupts, but only
  312          * needs doing once for each VMEbus interrupt level which is hooked)
  313          */
  314 #if NVMETWO > 0
  315         if (first) {
  316                 if (evcnt)
  317                         evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
  318                             (*sc->sc_isrevcnt)(sc->sc_isrcookie, prior),
  319                             sc->sc_mvmebus.sc_dev.dv_xname,
  320                             mvmebus_irq_name[lvl]);
  321 #endif
  322                 iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
  323                     VME2LCSR_INTERRUPT_LEVEL_BASE;
  324                 ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
  325 
  326                 /* Program the specified interrupt to signal at 'prior' */
  327                 reg = vme2_lcsr_read(sc, iloffset);
  328                 reg &= ~(VME2_INTERRUPT_LEVEL_MASK << ilshift);
  329                 reg |= (prior << ilshift);
  330                 vme2_lcsr_write(sc, iloffset, reg);
  331 
  332                 /* Clear it */
  333                 vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
  334                     VME2_LOCAL_INTERRUPT(bitoff));
  335 
  336                 /* Enable it. */
  337                 reg = vme2_lcsr_read(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE);
  338                 reg |= VME2_LOCAL_INTERRUPT(bitoff);
  339                 vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, reg);
  340 #if NVMETWO > 0
  341         }
  342 #ifdef DIAGNOSTIC
  343         else {
  344                 /* Verify the interrupt priority is the same */
  345                 iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
  346                     VME2LCSR_INTERRUPT_LEVEL_BASE;
  347                 ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
  348 
  349                 reg = vme2_lcsr_read(sc, iloffset);
  350                 reg &= (VME2_INTERRUPT_LEVEL_MASK << ilshift);
  351 
  352                 if ((prior << ilshift) != reg)
  353                         panic("vmetwo_intr_establish: priority mismatch!");
  354         }
  355 #endif
  356 #endif
  357         splx(s);
  358 }
  359 
  360 void
  361 vmetwo_intr_disestablish(csc, lvl, vec, last, evcnt)
  362         void *csc;
  363         int lvl, vec, last;
  364         struct evcnt *evcnt;
  365 {
  366         struct vmetwo_softc *sc = csc;
  367         u_int32_t reg;
  368         int iloffset, ilshift;
  369         int bitoff;
  370         int s;
  371 
  372         s = splhigh();
  373 
  374 #if NVMETWO > 0
  375         /*
  376          * Sort out interrupts generated locally by the VMEChip2 from
  377          * those generated by VMEbus devices...
  378          */
  379         if (vec >= VME2_VECTOR_LOCAL_MIN && vec <= VME2_VECTOR_LOCAL_MAX) {
  380 #endif
  381                 /*
  382                  * Interrupt enable/clear bit offset is 0x08 - 0x1f
  383                  */
  384                 bitoff = vec - VME2_VECTOR_BASE;
  385                 vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_hand = NULL;
  386                 last = 1; /* Force the interrupt to be cleared */
  387 #if NVMETWO > 0
  388         } else {
  389                 /*
  390                  * Interrupts originating from the VMEbus are
  391                  * controlled by an offset of 0x00 - 0x07
  392                  */
  393                 bitoff = lvl - 1;
  394         }
  395 #endif
  396 
  397         /*
  398          * Do we need to tell the VMEChip2 to block the interrupt?
  399          * (This is always true for locally-generated interrupts, but only
  400          * needs doing once when the last VMEbus handler for any given level
  401          * has been unhooked.)
  402          */
  403         if (last) {
  404                 iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
  405                     VME2LCSR_INTERRUPT_LEVEL_BASE;
  406                 ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
  407 
  408                 /* Disable it. */
  409                 reg = vme2_lcsr_read(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE);
  410                 reg &= ~VME2_LOCAL_INTERRUPT(bitoff);
  411                 vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, reg);
  412 
  413                 /* Set the interrupt's level to zero */
  414                 reg = vme2_lcsr_read(sc, iloffset);
  415                 reg &= ~(VME2_INTERRUPT_LEVEL_MASK << ilshift);
  416                 vme2_lcsr_write(sc, iloffset, reg);
  417 
  418                 /* Clear it */
  419                 vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
  420                     VME2_LOCAL_INTERRUPT(vec));
  421 
  422                 if (evcnt)
  423                         evcnt_detach(evcnt);
  424         }
  425         /* Un-hook it */
  426         (*sc->sc_isrunlink)(sc->sc_isrcookie, vec);
  427 
  428         splx(s);
  429 }
  430 
  431 static void
  432 vmetwo_softintr_assert(void)
  433 {
  434 
  435         vme2_lcsr_write(vmetwo_sc, VME2LCSR_SOFTINT_SET, VME2_SOFTINT_SET(0));
  436 }

Cache object: 414f3441c7eb0cb851ede6375c4f505b


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