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/Osd/OsdInterrupt.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) 2000 Michael Smith
    3  * Copyright (c) 2000 BSDi
    4  * Copyright (c) 2011 Jung-uk Kim <jkim@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * 6.5 : Interrupt handling
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: releng/10.4/sys/dev/acpica/Osd/OsdInterrupt.c 227293 2011-11-07 06:44:47Z ed $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/bus.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mutex.h>
   42 #include <machine/bus.h>
   43 #include <machine/resource.h>
   44 #include <sys/rman.h>
   45 
   46 #include <contrib/dev/acpica/include/acpi.h>
   47 #include <contrib/dev/acpica/include/accommon.h>
   48 
   49 #include <dev/acpica/acpivar.h>
   50 
   51 #define _COMPONENT      ACPI_OS_SERVICES
   52 ACPI_MODULE_NAME("INTERRUPT")
   53 
   54 static MALLOC_DEFINE(M_ACPIINTR, "acpiintr", "ACPI interrupt");
   55 
   56 struct acpi_intr {
   57         SLIST_ENTRY(acpi_intr)  ai_link;
   58         struct resource         *ai_irq;
   59         int                     ai_rid;
   60         void                    *ai_handle;
   61         int                     ai_number;
   62         ACPI_OSD_HANDLER        ai_handler;
   63         void                    *ai_context;
   64 };
   65 static SLIST_HEAD(, acpi_intr) acpi_intr_list =
   66     SLIST_HEAD_INITIALIZER(acpi_intr_list);
   67 static struct mtx       acpi_intr_lock;
   68 
   69 static UINT32           InterruptOverride;
   70 
   71 static void
   72 acpi_intr_init(struct mtx *lock)
   73 {
   74 
   75         mtx_init(lock, "ACPI interrupt lock", NULL, MTX_DEF);
   76 }
   77 
   78 SYSINIT(acpi_intr, SI_SUB_DRIVERS, SI_ORDER_FIRST, acpi_intr_init,
   79     &acpi_intr_lock);
   80 
   81 static int
   82 acpi_intr_handler(void *arg)
   83 {
   84         struct acpi_intr *ai;
   85 
   86         ai = arg;
   87         KASSERT(ai != NULL && ai->ai_handler != NULL,
   88             ("invalid ACPI interrupt handler"));
   89         if (ai->ai_handler(ai->ai_context) == ACPI_INTERRUPT_HANDLED)
   90                 return (FILTER_HANDLED);
   91         return (FILTER_STRAY);
   92 }
   93 
   94 static void
   95 acpi_intr_destroy(device_t dev, struct acpi_intr *ai)
   96 {
   97 
   98         if (ai->ai_handle != NULL)
   99                 bus_teardown_intr(dev, ai->ai_irq, ai->ai_handle);
  100         if (ai->ai_irq != NULL)
  101                 bus_release_resource(dev, SYS_RES_IRQ, ai->ai_rid, ai->ai_irq);
  102         bus_delete_resource(dev, SYS_RES_IRQ, ai->ai_rid);
  103         free(ai, M_ACPIINTR);
  104 }
  105 
  106 ACPI_STATUS
  107 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
  108     ACPI_OSD_HANDLER ServiceRoutine, void *Context)
  109 {
  110         struct acpi_softc *sc;
  111         struct acpi_intr *ai, *ap;
  112 
  113         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  114 
  115         sc = devclass_get_softc(devclass_find("acpi"), 0);
  116         KASSERT(sc != NULL && sc->acpi_dev != NULL,
  117             ("can't find ACPI device to register interrupt"));
  118 
  119         if (InterruptNumber > 255 || ServiceRoutine == NULL)
  120                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  121 
  122         ai = malloc(sizeof(*ai), M_ACPIINTR, M_WAITOK | M_ZERO);
  123         mtx_lock(&acpi_intr_lock);
  124         SLIST_FOREACH(ap, &acpi_intr_list, ai_link) {
  125                 if (InterruptNumber == ap->ai_number ||
  126                     (InterruptNumber == InterruptOverride &&
  127                     InterruptNumber != AcpiGbl_FADT.SciInterrupt)) {
  128                         mtx_unlock(&acpi_intr_lock);
  129                         free(ai, M_ACPIINTR);
  130                         return_ACPI_STATUS (AE_ALREADY_EXISTS);
  131                 }
  132                 if (ai->ai_rid <= ap->ai_rid)
  133                         ai->ai_rid = ap->ai_rid + 1;
  134         }
  135         ai->ai_number = InterruptNumber;
  136         ai->ai_handler = ServiceRoutine;
  137         ai->ai_context = Context;
  138         SLIST_INSERT_HEAD(&acpi_intr_list, ai, ai_link);
  139         mtx_unlock(&acpi_intr_lock);
  140 
  141         /*
  142          * If the MADT contained an interrupt override directive for the SCI,
  143          * we use that value instead of the one from the FADT.
  144          */
  145         if (InterruptOverride != 0 &&
  146             InterruptNumber == AcpiGbl_FADT.SciInterrupt) {
  147                 device_printf(sc->acpi_dev,
  148                     "Overriding SCI from IRQ %u to IRQ %u\n",
  149                     InterruptNumber, InterruptOverride);
  150                 InterruptNumber = InterruptOverride;
  151         }
  152 
  153         /* Set up the interrupt resource. */
  154         bus_set_resource(sc->acpi_dev, SYS_RES_IRQ, ai->ai_rid,
  155             InterruptNumber, 1);
  156         ai->ai_irq = bus_alloc_resource_any(sc->acpi_dev, SYS_RES_IRQ,
  157             &ai->ai_rid, RF_SHAREABLE | RF_ACTIVE);
  158         if (ai->ai_irq == NULL) {
  159                 device_printf(sc->acpi_dev, "could not allocate interrupt\n");
  160                 goto error;
  161         }
  162         if (bus_setup_intr(sc->acpi_dev, ai->ai_irq,
  163             INTR_TYPE_MISC | INTR_MPSAFE, acpi_intr_handler, NULL, ai,
  164             &ai->ai_handle) != 0) {
  165                 device_printf(sc->acpi_dev, "could not set up interrupt\n");
  166                 goto error;
  167         }
  168         return_ACPI_STATUS (AE_OK);
  169 
  170 error:
  171         mtx_lock(&acpi_intr_lock);
  172         SLIST_REMOVE(&acpi_intr_list, ai, acpi_intr, ai_link);
  173         mtx_unlock(&acpi_intr_lock);
  174         acpi_intr_destroy(sc->acpi_dev, ai);
  175         return_ACPI_STATUS (AE_ALREADY_EXISTS);
  176 }
  177 
  178 ACPI_STATUS
  179 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
  180     ACPI_OSD_HANDLER ServiceRoutine)
  181 {
  182         struct acpi_softc *sc;
  183         struct acpi_intr *ai;
  184 
  185         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  186 
  187         sc = devclass_get_softc(devclass_find("acpi"), 0);
  188         KASSERT(sc != NULL && sc->acpi_dev != NULL,
  189             ("can't find ACPI device to deregister interrupt"));
  190 
  191         if (InterruptNumber > 255 || ServiceRoutine == NULL)
  192                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  193         mtx_lock(&acpi_intr_lock);
  194         SLIST_FOREACH(ai, &acpi_intr_list, ai_link)
  195                 if (InterruptNumber == ai->ai_number) {
  196                         if (ServiceRoutine != ai->ai_handler) {
  197                                 mtx_unlock(&acpi_intr_lock);
  198                                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  199                         }
  200                         SLIST_REMOVE(&acpi_intr_list, ai, acpi_intr, ai_link);
  201                         break;
  202                 }
  203         mtx_unlock(&acpi_intr_lock);
  204         if (ai == NULL)
  205                 return_ACPI_STATUS (AE_NOT_EXIST);
  206         acpi_intr_destroy(sc->acpi_dev, ai);
  207         return_ACPI_STATUS (AE_OK);
  208 }
  209 
  210 ACPI_STATUS
  211 acpi_OverrideInterruptLevel(UINT32 InterruptNumber)
  212 {
  213 
  214         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  215 
  216         if (InterruptOverride != 0)
  217                 return_ACPI_STATUS (AE_ALREADY_EXISTS);
  218         InterruptOverride = InterruptNumber;
  219         return_ACPI_STATUS (AE_OK);
  220 }

Cache object: fa7e74e6fabe8237daade0834c9c3675


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