2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, 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
27 * $FreeBSD: src/sys/dev/acpica/Osd/OsdInterrupt.c,v 1.17 2004/04/14 03:41:06 njl Exp $
28 * $DragonFly: src/sys/dev/acpica5/Osd/OsdInterrupt.c,v 1.7 2006/10/25 20:55:52 dillon Exp $
32 * 6.5 : Interrupt handling
35 #include <sys/param.h>
36 #include <sys/kernel.h>
39 #include <sys/thread2.h>
43 #include <dev/acpica5/acpivar.h>
45 #define _COMPONENT ACPI_OS_SERVICES
46 ACPI_MODULE_NAME("INTERRUPT")
48 static void InterruptWrapper(void *arg
);
50 static ACPI_OSD_HANDLER InterruptHandler
;
51 static UINT32 InterruptOverride
= 0;
54 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber
,
55 ACPI_OSD_HANDLER ServiceRoutine
, void *Context
)
57 struct acpi_softc
*sc
;
59 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__
);
61 if ((sc
= devclass_get_softc(devclass_find("acpi"), 0)) == NULL
)
62 panic("can't find ACPI device to register interrupt");
63 if (sc
->acpi_dev
== NULL
)
64 panic("acpi softc has invalid device");
66 if (InterruptNumber
< 0 || InterruptNumber
> 255)
67 return_ACPI_STATUS (AE_BAD_PARAMETER
);
68 if (ServiceRoutine
== NULL
)
69 return_ACPI_STATUS (AE_BAD_PARAMETER
);
70 if (InterruptHandler
!= NULL
) {
71 device_printf(sc
->acpi_dev
, "interrupt handler already installed\n");
72 return_ACPI_STATUS (AE_ALREADY_EXISTS
);
74 InterruptHandler
= ServiceRoutine
;
77 * If the MADT contained an interrupt override directive for the SCI,
78 * we use that value instead of the one from the FADT.
80 if (InterruptOverride
!= 0) {
81 device_printf(sc
->acpi_dev
,
82 "Overriding SCI Interrupt from IRQ %u to IRQ %u\n",
83 InterruptNumber
, InterruptOverride
);
84 InterruptNumber
= InterruptOverride
;
87 /* Set up the interrupt resource. */
89 bus_set_resource(sc
->acpi_dev
, SYS_RES_IRQ
, 0, InterruptNumber
, 1);
90 sc
->acpi_irq
= bus_alloc_resource_any(sc
->acpi_dev
, SYS_RES_IRQ
,
91 &sc
->acpi_irq_rid
, RF_SHAREABLE
| RF_ACTIVE
);
92 if (sc
->acpi_irq
== NULL
) {
93 device_printf(sc
->acpi_dev
, "could not allocate interrupt\n");
96 if (bus_setup_intr(sc
->acpi_dev
, sc
->acpi_irq
, 0,
97 InterruptWrapper
, Context
, &sc
->acpi_irq_handle
, NULL
)) {
98 device_printf(sc
->acpi_dev
, "could not set up interrupt\n");
102 return_ACPI_STATUS (AE_OK
);
105 if (sc
->acpi_irq_handle
)
106 bus_teardown_intr(sc
->acpi_dev
, sc
->acpi_irq
, sc
->acpi_irq_handle
);
107 sc
->acpi_irq_handle
= NULL
;
109 bus_release_resource(sc
->acpi_dev
, SYS_RES_IRQ
, 0, sc
->acpi_irq
);
111 bus_delete_resource(sc
->acpi_dev
, SYS_RES_IRQ
, 0);
112 InterruptHandler
= NULL
;
114 return_ACPI_STATUS (AE_ALREADY_EXISTS
);
118 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber
, ACPI_OSD_HANDLER ServiceRoutine
)
120 struct acpi_softc
*sc
;
122 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__
);
124 if (InterruptNumber
< 0 || InterruptNumber
> 255)
125 return_ACPI_STATUS (AE_BAD_PARAMETER
);
126 if (ServiceRoutine
== NULL
)
127 return_ACPI_STATUS (AE_BAD_PARAMETER
);
129 if ((sc
= devclass_get_softc(devclass_find("acpi"), 0)) == NULL
)
130 panic("can't find ACPI device to deregister interrupt");
132 if (sc
->acpi_irq
== NULL
)
133 return_ACPI_STATUS (AE_NOT_EXIST
);
135 bus_teardown_intr(sc
->acpi_dev
, sc
->acpi_irq
, sc
->acpi_irq_handle
);
136 bus_release_resource(sc
->acpi_dev
, SYS_RES_IRQ
, 0, sc
->acpi_irq
);
137 bus_delete_resource(sc
->acpi_dev
, SYS_RES_IRQ
, 0);
140 InterruptHandler
= NULL
;
142 return_ACPI_STATUS (AE_OK
);
146 acpi_OverrideInterruptLevel(UINT32 InterruptNumber
)
149 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__
);
151 if (InterruptOverride
!= 0)
152 return_ACPI_STATUS (AE_ALREADY_EXISTS
);
153 InterruptOverride
= InterruptNumber
;
154 return_ACPI_STATUS (AE_OK
);
158 InterruptWrapper(void *arg
)
161 InterruptHandler(arg
);