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);
   55 static void     ps3pic_eoi(device_t, u_int);
   56 static void     ps3pic_ipi(device_t, u_int);
   57 static void     ps3pic_mask(device_t, u_int);
   58 static void     ps3pic_unmask(device_t, u_int);
   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 static devclass_t ps3pic_devclass;
   95 
   96 DRIVER_MODULE(ps3pic, nexus, ps3pic_driver, ps3pic_devclass, 0, 0);
   97 
   98 static MALLOC_DEFINE(M_PS3PIC, "ps3pic", "PS3 PIC");
   99 
  100 static void
  101 ps3pic_identify(driver_t *driver, device_t parent)
  102 {
  103         if (strcmp(installed_platform(), "ps3") != 0)
  104                 return;
  105 
  106         if (device_find_child(parent, "ps3pic", -1) == NULL)
  107                 BUS_ADD_CHILD(parent, 0, "ps3pic", 0);
  108 }
  109 
  110 static int
  111 ps3pic_probe(device_t dev)
  112 {
  113         device_set_desc(dev, "Playstation 3 interrupt controller");
  114         return (BUS_PROBE_NOWILDCARD);
  115 }
  116 
  117 static int
  118 ps3pic_attach(device_t dev)
  119 {
  120         struct ps3pic_softc *sc;
  121         uint64_t ppe;
  122         int thread;
  123 
  124         sc = device_get_softc(dev);
  125 
  126         sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC,
  127             M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */,
  128             PAGE_SIZE /* boundary */);
  129         sc->mask_thread0 = sc->bitmap_thread0 + 4;
  130         sc->bitmap_thread1 = sc->bitmap_thread0 + 8;
  131         sc->mask_thread1 = sc->bitmap_thread0 + 12;
  132 
  133         lv1_get_logical_ppe_id(&ppe);
  134         thread = 32 - fls(mfctrl());
  135         lv1_configure_irq_state_bitmap(ppe, thread,
  136             vtophys(sc->bitmap_thread0));
  137 
  138         sc->sc_ipi_virq = 63;
  139 
  140 #ifdef SMP
  141         lv1_configure_irq_state_bitmap(ppe, !thread,
  142             vtophys(sc->bitmap_thread1));
  143 
  144         /* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */
  145         lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]);
  146         lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_virq,
  147             sc->sc_ipi_outlet[0], 0);
  148         lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]);
  149         lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_virq,
  150             sc->sc_ipi_outlet[1], 0);
  151 #endif
  152 
  153         powerpc_register_pic(dev, 0, sc->sc_ipi_virq, 1, FALSE);
  154         return (0);
  155 }
  156 
  157 /*
  158  * PIC I/F methods.
  159  */
  160 
  161 static void
  162 ps3pic_dispatch(device_t dev, struct trapframe *tf)
  163 {
  164         uint64_t bitmap, mask;
  165         int irq;
  166         struct ps3pic_softc *sc;
  167 
  168         sc = device_get_softc(dev);
  169 
  170         if (PCPU_GET(cpuid) == 0) {
  171                 bitmap = atomic_readandclear_64(&sc->bitmap_thread0[0]);
  172                 mask = sc->mask_thread0[0];
  173         } else {
  174                 bitmap = atomic_readandclear_64(&sc->bitmap_thread1[0]);
  175                 mask = sc->mask_thread1[0];
  176         }
  177         powerpc_sync();
  178 
  179         while ((irq = ffsl(bitmap & mask) - 1) != -1) {
  180                 bitmap &= ~(1UL << irq);
  181                 powerpc_dispatch_intr(sc->sc_vector[63 - irq], tf);
  182         }
  183 }
  184 
  185 static void
  186 ps3pic_enable(device_t dev, u_int irq, u_int vector)
  187 {
  188         struct ps3pic_softc *sc;
  189 
  190         sc = device_get_softc(dev);
  191         sc->sc_vector[irq] = vector;
  192 
  193         ps3pic_unmask(dev, irq);
  194 }
  195 
  196 static void
  197 ps3pic_eoi(device_t dev, u_int irq)
  198 {
  199         uint64_t ppe;
  200         int thread;
  201 
  202         lv1_get_logical_ppe_id(&ppe);
  203         thread = 32 - fls(mfctrl());
  204 
  205         lv1_end_of_interrupt_ext(ppe, thread, irq);
  206 }
  207 
  208 static void
  209 ps3pic_ipi(device_t dev, u_int cpu)
  210 {
  211         struct ps3pic_softc *sc;
  212         sc = device_get_softc(dev);
  213 
  214         lv1_send_event_locally(sc->sc_ipi_outlet[cpu]);
  215 }
  216 
  217 static void
  218 ps3pic_mask(device_t dev, u_int irq)
  219 {
  220         struct ps3pic_softc *sc;
  221         uint64_t ppe;
  222 
  223         sc = device_get_softc(dev);
  224 
  225         /* Do not mask IPIs! */
  226         if (irq == sc->sc_ipi_virq)
  227                 return;
  228 
  229         atomic_clear_64(&sc->mask_thread0[0], 1UL << (63 - irq));
  230         atomic_clear_64(&sc->mask_thread1[0], 1UL << (63 - irq));
  231 
  232         lv1_get_logical_ppe_id(&ppe);
  233         lv1_did_update_interrupt_mask(ppe, 0);
  234         lv1_did_update_interrupt_mask(ppe, 1);
  235 }
  236 
  237 static void
  238 ps3pic_unmask(device_t dev, u_int irq)
  239 {
  240         struct ps3pic_softc *sc;
  241         uint64_t ppe;
  242 
  243         sc = device_get_softc(dev);
  244         atomic_set_64(&sc->mask_thread0[0], 1UL << (63 - irq));
  245         atomic_set_64(&sc->mask_thread1[0], 1UL << (63 - irq));
  246 
  247         lv1_get_logical_ppe_id(&ppe);
  248         lv1_did_update_interrupt_mask(ppe, 0);
  249         lv1_did_update_interrupt_mask(ppe, 1);
  250 }

Cache object: 9b7d23b8b9191a1b4ccdc3ce7cc3d025


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