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/ps3/ps3pic.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 2010 Nathan Whitehorn
    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  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * 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  * $FreeBSD$
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/module.h>
   33 #include <sys/bus.h>
   34 #include <sys/conf.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 
   38 #include <vm/vm.h>
   39 #include <vm/pmap.h>
   40 
   41 #include <machine/bus.h>
   42 #include <machine/intr_machdep.h>
   43 #include <machine/md_var.h>
   44 #include <machine/platform.h>
   45 
   46 #include "ps3-hvcall.h"
   47 #include "pic_if.h"
   48 
   49 static void     ps3pic_identify(driver_t *driver, device_t parent);
   50 static int      ps3pic_probe(device_t);
   51 static int      ps3pic_attach(device_t);
   52 
   53 static void     ps3pic_dispatch(device_t, struct trapframe *);
   54 static void     ps3pic_enable(device_t, u_int, u_int, void **);
   55 static void     ps3pic_eoi(device_t, u_int, void *);
   56 static void     ps3pic_ipi(device_t, u_int);
   57 static void     ps3pic_mask(device_t, u_int, void *);
   58 static void     ps3pic_unmask(device_t, u_int, void *);
   59 
   60 struct ps3pic_softc {
   61         volatile uint64_t *bitmap_thread0;
   62         volatile uint64_t *mask_thread0;
   63         volatile uint64_t *bitmap_thread1;
   64         volatile uint64_t *mask_thread1;
   65 
   66         uint64_t        sc_ipi_outlet[2];
   67         uint64_t        sc_ipi_virq;
   68         int             sc_vector[64];
   69 };
   70 
   71 static device_method_t  ps3pic_methods[] = {
   72         /* Device interface */
   73         DEVMETHOD(device_identify,      ps3pic_identify),
   74         DEVMETHOD(device_probe,         ps3pic_probe),
   75         DEVMETHOD(device_attach,        ps3pic_attach),
   76 
   77         /* PIC interface */
   78         DEVMETHOD(pic_dispatch,         ps3pic_dispatch),
   79         DEVMETHOD(pic_enable,           ps3pic_enable),
   80         DEVMETHOD(pic_eoi,              ps3pic_eoi),
   81         DEVMETHOD(pic_ipi,              ps3pic_ipi),
   82         DEVMETHOD(pic_mask,             ps3pic_mask),
   83         DEVMETHOD(pic_unmask,           ps3pic_unmask),
   84 
   85         { 0, 0 },
   86 };
   87 
   88 static driver_t ps3pic_driver = {
   89         "ps3pic",
   90         ps3pic_methods,
   91         sizeof(struct ps3pic_softc)
   92 };
   93 
   94 DRIVER_MODULE(ps3pic, nexus, ps3pic_driver, 0, 0);
   95 
   96 static MALLOC_DEFINE(M_PS3PIC, "ps3pic", "PS3 PIC");
   97 
   98 static void
   99 ps3pic_identify(driver_t *driver, device_t parent)
  100 {
  101         if (strcmp(installed_platform(), "ps3") != 0)
  102                 return;
  103 
  104         if (device_find_child(parent, "ps3pic", -1) == NULL)
  105                 BUS_ADD_CHILD(parent, 0, "ps3pic", 0);
  106 }
  107 
  108 static int
  109 ps3pic_probe(device_t dev)
  110 {
  111         device_set_desc(dev, "Playstation 3 interrupt controller");
  112         return (BUS_PROBE_NOWILDCARD);
  113 }
  114 
  115 static int
  116 ps3pic_attach(device_t dev)
  117 {
  118         struct ps3pic_softc *sc;
  119         uint64_t ppe;
  120         int thread;
  121 
  122         sc = device_get_softc(dev);
  123 
  124         sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC,
  125             M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */,
  126             PAGE_SIZE /* boundary */);
  127         sc->mask_thread0 = sc->bitmap_thread0 + 4;
  128         sc->bitmap_thread1 = sc->bitmap_thread0 + 8;
  129         sc->mask_thread1 = sc->bitmap_thread0 + 12;
  130 
  131         lv1_get_logical_ppe_id(&ppe);
  132         thread = 32 - fls(mfctrl());
  133         lv1_configure_irq_state_bitmap(ppe, thread,
  134             vtophys(sc->bitmap_thread0));
  135 
  136         sc->sc_ipi_virq = 63;
  137 
  138 #ifdef SMP
  139         lv1_configure_irq_state_bitmap(ppe, !thread,
  140             vtophys(sc->bitmap_thread1));
  141 
  142         /* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */
  143         lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]);
  144         lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_virq,
  145             sc->sc_ipi_outlet[0], 0);
  146         lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]);
  147         lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_virq,
  148             sc->sc_ipi_outlet[1], 0);
  149 #endif
  150 
  151         powerpc_register_pic(dev, 0, sc->sc_ipi_virq, 1, FALSE);
  152         return (0);
  153 }
  154 
  155 /*
  156  * PIC I/F methods.
  157  */
  158 
  159 static void
  160 ps3pic_dispatch(device_t dev, struct trapframe *tf)
  161 {
  162         uint64_t bitmap, mask;
  163         int irq;
  164         struct ps3pic_softc *sc;
  165 
  166         sc = device_get_softc(dev);
  167 
  168         if (PCPU_GET(cpuid) == 0) {
  169                 bitmap = atomic_readandclear_64(&sc->bitmap_thread0[0]);
  170                 mask = sc->mask_thread0[0];
  171         } else {
  172                 bitmap = atomic_readandclear_64(&sc->bitmap_thread1[0]);
  173                 mask = sc->mask_thread1[0];
  174         }
  175         powerpc_sync();
  176 
  177         while ((irq = ffsl(bitmap & mask) - 1) != -1) {
  178                 bitmap &= ~(1UL << irq);
  179                 powerpc_dispatch_intr(sc->sc_vector[63 - irq], tf);
  180         }
  181 }
  182 
  183 static void
  184 ps3pic_enable(device_t dev, u_int irq, u_int vector, void **priv)
  185 {
  186         struct ps3pic_softc *sc;
  187 
  188         sc = device_get_softc(dev);
  189         sc->sc_vector[irq] = vector;
  190 
  191         ps3pic_unmask(dev, irq, priv);
  192 }
  193 
  194 static void
  195 ps3pic_eoi(device_t dev, u_int irq, void *priv)
  196 {
  197         uint64_t ppe;
  198         int thread;
  199 
  200         lv1_get_logical_ppe_id(&ppe);
  201         thread = 32 - fls(mfctrl());
  202 
  203         lv1_end_of_interrupt_ext(ppe, thread, irq);
  204 }
  205 
  206 static void
  207 ps3pic_ipi(device_t dev, u_int cpu)
  208 {
  209         struct ps3pic_softc *sc;
  210         sc = device_get_softc(dev);
  211 
  212         lv1_send_event_locally(sc->sc_ipi_outlet[cpu]);
  213 }
  214 
  215 static void
  216 ps3pic_mask(device_t dev, u_int irq, void *priv)
  217 {
  218         struct ps3pic_softc *sc;
  219         uint64_t ppe;
  220 
  221         sc = device_get_softc(dev);
  222 
  223         /* Do not mask IPIs! */
  224         if (irq == sc->sc_ipi_virq)
  225                 return;
  226 
  227         atomic_clear_64(&sc->mask_thread0[0], 1UL << (63 - irq));
  228         atomic_clear_64(&sc->mask_thread1[0], 1UL << (63 - irq));
  229 
  230         lv1_get_logical_ppe_id(&ppe);
  231         lv1_did_update_interrupt_mask(ppe, 0);
  232         lv1_did_update_interrupt_mask(ppe, 1);
  233 }
  234 
  235 static void
  236 ps3pic_unmask(device_t dev, u_int irq, void *priv)
  237 {
  238         struct ps3pic_softc *sc;
  239         uint64_t ppe;
  240 
  241         sc = device_get_softc(dev);
  242         atomic_set_64(&sc->mask_thread0[0], 1UL << (63 - irq));
  243         atomic_set_64(&sc->mask_thread1[0], 1UL << (63 - irq));
  244 
  245         lv1_get_logical_ppe_id(&ppe);
  246         lv1_did_update_interrupt_mask(ppe, 0);
  247         lv1_did_update_interrupt_mask(ppe, 1);
  248 }

Cache object: 65a223bfa89401d0c9cbca6cfc71602f


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