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/acpica/acpi_ged.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) 2022 Takanori Watanabe
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 #include "opt_acpi.h"
   30 
   31 #include <sys/param.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 #include <sys/module.h>
   36 #include <sys/rman.h>
   37 
   38 #include <contrib/dev/acpica/include/acpi.h>
   39 #include <contrib/dev/acpica/include/accommon.h>
   40 #include <dev/acpica/acpivar.h>
   41 
   42 /* Hooks for the ACPI CA debugging infrastructure */
   43 #define _COMPONENT ACPI_BUS
   44 ACPI_MODULE_NAME("GED")
   45 
   46 static MALLOC_DEFINE(M_ACPIGED, "acpiged", "ACPI Generic event data");
   47 
   48 struct acpi_ged_event {
   49         device_t dev;
   50         struct resource *r;
   51         int rid;
   52         void *cookie;
   53         ACPI_HANDLE ah;
   54         ACPI_OBJECT_LIST args;
   55         ACPI_OBJECT arg1;
   56 };
   57 
   58 struct acpi_ged_softc {
   59         int numevts;
   60         struct acpi_ged_event *evts;
   61 };
   62 
   63 static int acpi_ged_probe(device_t dev);
   64 static int acpi_ged_attach(device_t dev);
   65 static int acpi_ged_detach(device_t dev);
   66 
   67 static char *ged_ids[] = { "ACPI0013", NULL };
   68 
   69 static device_method_t acpi_ged_methods[] = {
   70         /* Device interface */
   71         DEVMETHOD(device_probe, acpi_ged_probe),
   72         DEVMETHOD(device_attach, acpi_ged_attach),
   73         DEVMETHOD(device_detach, acpi_ged_detach),
   74         DEVMETHOD_END
   75 };
   76 
   77 static driver_t acpi_ged_driver = {
   78         "acpi_ged",
   79         acpi_ged_methods,
   80         sizeof(struct acpi_ged_softc),
   81 };
   82 
   83 DRIVER_MODULE(acpi_ged, acpi, acpi_ged_driver, 0, 0);
   84 MODULE_DEPEND(acpi_ged, acpi, 1, 1, 1);
   85 
   86 static void
   87 acpi_ged_evt(void *arg)
   88 {
   89         struct acpi_ged_event *evt = arg;
   90 
   91         AcpiEvaluateObject(evt->ah, NULL, &evt->args, NULL);
   92 }
   93 
   94 static void
   95 acpi_ged_intr(void *arg)
   96 {
   97         AcpiOsExecute(OSL_GPE_HANDLER, acpi_ged_evt, arg);
   98 }
   99 static int
  100 acpi_ged_probe(device_t dev)
  101 {
  102         int rv;
  103 
  104         if (acpi_disabled("ged"))
  105                 return (ENXIO);
  106         rv = ACPI_ID_PROBE(device_get_parent(dev), dev, ged_ids, NULL);
  107         if (rv > 0)
  108                 return (ENXIO);
  109 
  110         device_set_desc(dev, "Generic Event Device");
  111         return (rv);
  112 }
  113 
  114 /*this should be in acpi_resource.*/
  115 static int
  116 acpi_get_trigger(ACPI_RESOURCE *res)
  117 {
  118         int trig;
  119 
  120         switch (res->Type) {
  121         case ACPI_RESOURCE_TYPE_IRQ:
  122                 KASSERT(res->Data.Irq.InterruptCount == 1,
  123                         ("%s: multiple interrupts", __func__));
  124                 trig = res->Data.Irq.Triggering;
  125                 break;
  126         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  127                 KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
  128                         ("%s: multiple interrupts", __func__));
  129                 trig = res->Data.ExtendedIrq.Triggering;
  130                 break;
  131         default:
  132                 panic("%s: bad resource type %u", __func__, res->Type);
  133         }
  134 
  135         return (trig == ACPI_EDGE_SENSITIVE)
  136                 ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL;
  137 }
  138 
  139 static int
  140 acpi_ged_attach(device_t dev)
  141 {
  142         struct acpi_ged_softc *sc = device_get_softc(dev);
  143         struct resource_list *rl;
  144         struct resource_list_entry *rle;
  145         ACPI_RESOURCE ares;
  146         ACPI_HANDLE evt_method;
  147         int i;
  148         int rawirq, trig;
  149         char name[] = "_Xnn";
  150 
  151         ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
  152 
  153         if (ACPI_FAILURE(AcpiGetHandle(acpi_get_handle(dev), "_EVT",
  154                                        &evt_method))) {
  155                 device_printf(dev, "_EVT not found\n");
  156                 evt_method = NULL;
  157         }
  158 
  159         rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
  160         STAILQ_FOREACH(rle, rl, link) {
  161                 if (rle->type == SYS_RES_IRQ) {
  162                         sc->numevts++;
  163                 }
  164         }
  165         sc->evts = mallocarray(sc->numevts, sizeof(*sc->evts), M_ACPIGED,
  166             M_WAITOK | M_ZERO);
  167         for (i = 0; i < sc->numevts; i++) {
  168                 sc->evts[i].dev = dev;
  169                 sc->evts[i].rid = i;
  170                 sc->evts[i].r = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  171                     &sc->evts[i].rid,  RF_ACTIVE | RF_SHAREABLE);
  172                 if (sc->evts[i].r == NULL) {
  173                         device_printf(dev, "Cannot alloc %dth irq\n", i);
  174                         continue;
  175                 }
  176 #ifdef INTRNG
  177                 {
  178                         struct intr_map_data_acpi *ima;
  179                         ima = rman_get_virtual(sc->evts[i].r);
  180                         if (ima == NULL) {
  181                                 device_printf(dev, "map not found"
  182                                               " non-intrng?\n");
  183                                 rawirq = rman_get_start(sc->evts[i].r);
  184                                 trig = INTR_TRIGGER_LEVEL;
  185                                 if (ACPI_SUCCESS(acpi_lookup_irq_resource
  186                                         (dev, sc->evts[i].rid,
  187                                          sc->evts[i].r, &ares))) {
  188                                         trig = acpi_get_trigger(&ares);
  189                                 }
  190                         } else if (ima->hdr.type == INTR_MAP_DATA_ACPI) {
  191                                 device_printf(dev, "Raw IRQ %d\n", ima->irq);
  192                                 rawirq = ima->irq;
  193                                 trig = ima->trig;
  194                         } else {
  195                                 device_printf(dev, "Not supported intr"
  196                                               " type%d\n", ima->hdr.type);
  197                                 continue;
  198                         }
  199                 }
  200 #else
  201                 rawirq = rman_get_start(sc->evts[i].r);
  202                 trig = INTR_TRIGGER_LEVEL;
  203                 if (ACPI_SUCCESS(acpi_lookup_irq_resource
  204                                 (dev, sc->evts[i].rid,
  205                                  sc->evts[i].r, &ares))) {
  206                         trig = acpi_get_trigger(&ares);
  207                 }
  208 #endif
  209                 if (rawirq < 0x100) {
  210                         sprintf(name, "_%c%02X",
  211                                 ((trig == INTR_TRIGGER_EDGE) ? 'E' : 'L'),
  212                                 rawirq);
  213                         if (ACPI_SUCCESS(AcpiGetHandle
  214                                         (acpi_get_handle(dev),
  215                                          name, &sc->evts[i].ah))) {
  216                                 sc->evts[i].args.Count = 0; /* ensure */
  217                         } else {
  218                                 sc->evts[i].ah = NULL; /* ensure */
  219                         }
  220                 }
  221 
  222                 if (sc->evts[i].ah == NULL) {
  223                         if (evt_method != NULL) {
  224                                 sc->evts[i].ah = evt_method;
  225                                 sc->evts[i].arg1.Type = ACPI_TYPE_INTEGER;
  226                                 sc->evts[i].arg1.Integer.Value = rawirq;
  227                                 sc->evts[i].args.Count = 1;
  228                                 sc->evts[i].args.Pointer = &sc->evts[i].arg1;
  229                         } else{
  230                                 device_printf
  231                                         (dev,
  232                                          "Cannot find handler method %d\n",
  233                                          i);
  234                                 continue;
  235                         }
  236                 }
  237 
  238                 if (bus_setup_intr(dev, sc->evts[i].r,
  239                         INTR_TYPE_MISC | INTR_MPSAFE, NULL, acpi_ged_intr,
  240                         &sc->evts[i], &sc->evts[i].cookie) != 0) {
  241                         device_printf(dev, "Failed to setup intr %d\n", i);
  242                 }
  243         }
  244 
  245         return_VALUE(0);
  246 }
  247 
  248 static int
  249 acpi_ged_detach(device_t dev)
  250 {
  251         struct acpi_ged_softc *sc = device_get_softc(dev);
  252         int i;
  253 
  254         for (i = 0; i < sc->numevts; i++) {
  255                 if (sc->evts[i].cookie) {
  256                         bus_teardown_intr(dev, sc->evts[i].r,
  257                             sc->evts[i].cookie);
  258                 }
  259                 if (sc->evts[i].r) {
  260                         bus_release_resource(dev, SYS_RES_IRQ, sc->evts[i].rid,
  261                             sc->evts[i].r);
  262                 }
  263         }
  264         free(sc->evts, M_ACPIGED);
  265 
  266         return (0);
  267 }

Cache object: de771d32bf15f045e104fa0db86c8072


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