Deleted Added
full compact
acpi.c (84500) acpi.c (85556)
1/*-
2 * Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4 * Copyright (c) 2000, 2001 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
1/*-
2 * Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4 * Copyright (c) 2000, 2001 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/dev/acpica/acpi.c 84500 2001-10-04 23:21:09Z msmith $
29 * $FreeBSD: head/sys/dev/acpica/acpi.c 85556 2001-10-26 17:43:05Z iwasaki $
30 */
31
32#include "opt_acpi.h"
33#include <sys/param.h>
34#include <sys/kernel.h>
35#include <sys/proc.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
41#include <sys/ioccom.h>
42#include <sys/reboot.h>
43#include <sys/sysctl.h>
44#include <sys/ctype.h>
45
46#include <machine/clock.h>
47#include <machine/resource.h>
48
49#include <isa/isavar.h>
50
51#include "acpi.h"
52
53#include <dev/acpica/acpivar.h>
54#include <dev/acpica/acpiio.h>
55
56MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
57
58/*
59 * Hooks for the ACPI CA debugging infrastructure
60 */
61#define _COMPONENT ACPI_BUS
62MODULE_NAME("ACPI")
63
64/*
65 * Character device
66 */
67
68static d_open_t acpiopen;
69static d_close_t acpiclose;
70static d_ioctl_t acpiioctl;
71
72#define CDEV_MAJOR 152
73static struct cdevsw acpi_cdevsw = {
74 acpiopen,
75 acpiclose,
76 noread,
77 nowrite,
78 acpiioctl,
79 nopoll,
80 nommap,
81 nostrategy,
82 "acpi",
83 CDEV_MAJOR,
84 nodump,
85 nopsize,
86 0
87};
88
89static const char* sleep_state_names[] = {
90 "S0", "S1", "S2", "S3", "S4", "S5", "S4B" };
91
92/* this has to be static, as the softc is gone when we need it */
93static int acpi_off_state = ACPI_STATE_S5;
94
95struct mtx acpi_mutex;
96
97static int acpi_modevent(struct module *mod, int event, void *junk);
98static void acpi_identify(driver_t *driver, device_t parent);
99static int acpi_probe(device_t dev);
100static int acpi_attach(device_t dev);
101static device_t acpi_add_child(device_t bus, int order, const char *name, int unit);
102static int acpi_print_resources(struct resource_list *rl, const char *name, int type,
103 const char *format);
104static int acpi_print_child(device_t bus, device_t child);
105static int acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result);
106static int acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value);
107static int acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start,
108 u_long count);
109static int acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp,
110 u_long *countp);
111static struct resource *acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
112 u_long start, u_long end, u_long count, u_int flags);
113static int acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r);
114static u_int32_t acpi_isa_get_logicalid(device_t dev);
115static int acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids);
116
117static void acpi_probe_children(device_t bus);
118static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status);
119
120static void acpi_shutdown_pre_sync(void *arg, int howto);
121static void acpi_shutdown_final(void *arg, int howto);
122
123static void acpi_enable_fixed_events(struct acpi_softc *sc);
124
125static void acpi_system_eventhandler_sleep(void *arg, int state);
126static void acpi_system_eventhandler_wakeup(void *arg, int state);
127static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
128
129static device_method_t acpi_methods[] = {
130 /* Device interface */
131 DEVMETHOD(device_identify, acpi_identify),
132 DEVMETHOD(device_probe, acpi_probe),
133 DEVMETHOD(device_attach, acpi_attach),
134 DEVMETHOD(device_shutdown, bus_generic_shutdown),
135 DEVMETHOD(device_suspend, bus_generic_suspend),
136 DEVMETHOD(device_resume, bus_generic_resume),
137
138 /* Bus interface */
139 DEVMETHOD(bus_add_child, acpi_add_child),
140 DEVMETHOD(bus_print_child, acpi_print_child),
141 DEVMETHOD(bus_read_ivar, acpi_read_ivar),
142 DEVMETHOD(bus_write_ivar, acpi_write_ivar),
143 DEVMETHOD(bus_set_resource, acpi_set_resource),
144 DEVMETHOD(bus_get_resource, acpi_get_resource),
145 DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
146 DEVMETHOD(bus_release_resource, acpi_release_resource),
147 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
148 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
149 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
150 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
151 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
152
153 /* ISA emulation */
154 DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
155
156 {0, 0}
157};
158
159static driver_t acpi_driver = {
160 "acpi",
161 acpi_methods,
162 sizeof(struct acpi_softc),
163};
164
165devclass_t acpi_devclass;
166DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, acpi_modevent, 0);
167MODULE_VERSION(acpi, 100);
168
169SYSCTL_INT(_debug, OID_AUTO, acpi_debug_layer, CTLFLAG_RW, &AcpiDbgLayer, 0, "");
170SYSCTL_INT(_debug, OID_AUTO, acpi_debug_level, CTLFLAG_RW, &AcpiDbgLevel, 0, "");
171static int acpi_ca_version = ACPI_CA_VERSION;
172SYSCTL_INT(_debug, OID_AUTO, acpi_ca_version, CTLFLAG_RD, &acpi_ca_version, 0, "");
173
174/*
175 * ACPI can only be loaded as a module by the loader; activating it after
176 * system bootstrap time is not useful, and can be fatal to the system.
177 * It also cannot be unloaded, since the entire system bus heirarchy hangs off it.
178 */
179static int
180acpi_modevent(struct module *mod, int event, void *junk)
181{
182 switch(event) {
183 case MOD_LOAD:
184 if (!cold)
185 return(EPERM);
186 break;
187 case MOD_UNLOAD:
188 return(EBUSY);
189 default:
190 break;
191 }
192 return(0);
193}
194
195/*
196 * Detect ACPI, perform early initialisation
197 */
198static void
199acpi_identify(driver_t *driver, device_t parent)
200{
201 device_t child;
202 int error;
203#ifdef ENABLE_DEBUGGER
204 char *debugpoint = getenv("debug.acpi.debugger");
205#endif
206
207 FUNCTION_TRACE(__func__);
208
209 if(!cold){
210 printf("Don't load this driver from userland!!\n");
211 return ;
212 }
213
214 /*
215 * Check that we haven't been disabled with a hint.
216 */
217 if (!resource_int_value("acpi", 0, "disabled", &error) &&
218 (error != 0))
219 return_VOID;
220
221 /*
222 * Make sure we're not being doubly invoked.
223 */
224 if (device_find_child(parent, "acpi", 0) != NULL)
225 return_VOID;
226
227 /* initialise the ACPI mutex */
228 mtx_init(&acpi_mutex, "ACPI global lock", MTX_DEF);
229
230 /*
231 * Start up the ACPI CA subsystem.
232 */
233#ifdef ENABLE_DEBUGGER
234 if (debugpoint && !strcmp(debugpoint, "init"))
235 acpi_EnterDebugger();
236#endif
237 if ((error = AcpiInitializeSubsystem()) != AE_OK) {
238 printf("ACPI: initialisation failed: %s\n", AcpiFormatException(error));
239 return_VOID;
240 }
241#ifdef ENABLE_DEBUGGER
242 if (debugpoint && !strcmp(debugpoint, "tables"))
243 acpi_EnterDebugger();
244#endif
245 if ((error = AcpiLoadTables()) != AE_OK) {
246 printf("ACPI: table load failed: %s\n", AcpiFormatException(error));
247 return_VOID;
248 }
249
250 /*
251 * Attach the actual ACPI device.
252 */
253 if ((child = BUS_ADD_CHILD(parent, 0, "acpi", 0)) == NULL) {
254 device_printf(parent, "ACPI: could not attach\n");
255 return_VOID;
256 }
257}
258
259/*
260 * Fetch some descriptive data from ACPI to put in our attach message
261 */
262static int
263acpi_probe(device_t dev)
264{
265 ACPI_TABLE_HEADER th;
266 char buf[20];
267 ACPI_STATUS status;
268 int error;
269
270 FUNCTION_TRACE(__func__);
271 ACPI_LOCK;
272
273 if ((status = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) {
274 device_printf(dev, "couldn't get XSDT header: %s\n", AcpiFormatException(status));
275 error = ENXIO;
276 } else {
277 sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId);
278 device_set_desc_copy(dev, buf);
279 error = 0;
280 }
281 ACPI_UNLOCK;
282 return_VALUE(error);
283}
284
285static int
286acpi_attach(device_t dev)
287{
288 struct acpi_softc *sc;
289 ACPI_STATUS status;
290 int error;
291 UINT32 flags;
292
293#ifdef ENABLE_DEBUGGER
294 char *debugpoint = getenv("debug.acpi.debugger");
295#endif
296
297 FUNCTION_TRACE(__func__);
298 ACPI_LOCK;
299 sc = device_get_softc(dev);
300 bzero(sc, sizeof(*sc));
301 sc->acpi_dev = dev;
302
30 */
31
32#include "opt_acpi.h"
33#include <sys/param.h>
34#include <sys/kernel.h>
35#include <sys/proc.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
41#include <sys/ioccom.h>
42#include <sys/reboot.h>
43#include <sys/sysctl.h>
44#include <sys/ctype.h>
45
46#include <machine/clock.h>
47#include <machine/resource.h>
48
49#include <isa/isavar.h>
50
51#include "acpi.h"
52
53#include <dev/acpica/acpivar.h>
54#include <dev/acpica/acpiio.h>
55
56MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
57
58/*
59 * Hooks for the ACPI CA debugging infrastructure
60 */
61#define _COMPONENT ACPI_BUS
62MODULE_NAME("ACPI")
63
64/*
65 * Character device
66 */
67
68static d_open_t acpiopen;
69static d_close_t acpiclose;
70static d_ioctl_t acpiioctl;
71
72#define CDEV_MAJOR 152
73static struct cdevsw acpi_cdevsw = {
74 acpiopen,
75 acpiclose,
76 noread,
77 nowrite,
78 acpiioctl,
79 nopoll,
80 nommap,
81 nostrategy,
82 "acpi",
83 CDEV_MAJOR,
84 nodump,
85 nopsize,
86 0
87};
88
89static const char* sleep_state_names[] = {
90 "S0", "S1", "S2", "S3", "S4", "S5", "S4B" };
91
92/* this has to be static, as the softc is gone when we need it */
93static int acpi_off_state = ACPI_STATE_S5;
94
95struct mtx acpi_mutex;
96
97static int acpi_modevent(struct module *mod, int event, void *junk);
98static void acpi_identify(driver_t *driver, device_t parent);
99static int acpi_probe(device_t dev);
100static int acpi_attach(device_t dev);
101static device_t acpi_add_child(device_t bus, int order, const char *name, int unit);
102static int acpi_print_resources(struct resource_list *rl, const char *name, int type,
103 const char *format);
104static int acpi_print_child(device_t bus, device_t child);
105static int acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result);
106static int acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value);
107static int acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start,
108 u_long count);
109static int acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp,
110 u_long *countp);
111static struct resource *acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
112 u_long start, u_long end, u_long count, u_int flags);
113static int acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r);
114static u_int32_t acpi_isa_get_logicalid(device_t dev);
115static int acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids);
116
117static void acpi_probe_children(device_t bus);
118static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status);
119
120static void acpi_shutdown_pre_sync(void *arg, int howto);
121static void acpi_shutdown_final(void *arg, int howto);
122
123static void acpi_enable_fixed_events(struct acpi_softc *sc);
124
125static void acpi_system_eventhandler_sleep(void *arg, int state);
126static void acpi_system_eventhandler_wakeup(void *arg, int state);
127static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
128
129static device_method_t acpi_methods[] = {
130 /* Device interface */
131 DEVMETHOD(device_identify, acpi_identify),
132 DEVMETHOD(device_probe, acpi_probe),
133 DEVMETHOD(device_attach, acpi_attach),
134 DEVMETHOD(device_shutdown, bus_generic_shutdown),
135 DEVMETHOD(device_suspend, bus_generic_suspend),
136 DEVMETHOD(device_resume, bus_generic_resume),
137
138 /* Bus interface */
139 DEVMETHOD(bus_add_child, acpi_add_child),
140 DEVMETHOD(bus_print_child, acpi_print_child),
141 DEVMETHOD(bus_read_ivar, acpi_read_ivar),
142 DEVMETHOD(bus_write_ivar, acpi_write_ivar),
143 DEVMETHOD(bus_set_resource, acpi_set_resource),
144 DEVMETHOD(bus_get_resource, acpi_get_resource),
145 DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
146 DEVMETHOD(bus_release_resource, acpi_release_resource),
147 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
148 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
149 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
150 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
151 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
152
153 /* ISA emulation */
154 DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
155
156 {0, 0}
157};
158
159static driver_t acpi_driver = {
160 "acpi",
161 acpi_methods,
162 sizeof(struct acpi_softc),
163};
164
165devclass_t acpi_devclass;
166DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, acpi_modevent, 0);
167MODULE_VERSION(acpi, 100);
168
169SYSCTL_INT(_debug, OID_AUTO, acpi_debug_layer, CTLFLAG_RW, &AcpiDbgLayer, 0, "");
170SYSCTL_INT(_debug, OID_AUTO, acpi_debug_level, CTLFLAG_RW, &AcpiDbgLevel, 0, "");
171static int acpi_ca_version = ACPI_CA_VERSION;
172SYSCTL_INT(_debug, OID_AUTO, acpi_ca_version, CTLFLAG_RD, &acpi_ca_version, 0, "");
173
174/*
175 * ACPI can only be loaded as a module by the loader; activating it after
176 * system bootstrap time is not useful, and can be fatal to the system.
177 * It also cannot be unloaded, since the entire system bus heirarchy hangs off it.
178 */
179static int
180acpi_modevent(struct module *mod, int event, void *junk)
181{
182 switch(event) {
183 case MOD_LOAD:
184 if (!cold)
185 return(EPERM);
186 break;
187 case MOD_UNLOAD:
188 return(EBUSY);
189 default:
190 break;
191 }
192 return(0);
193}
194
195/*
196 * Detect ACPI, perform early initialisation
197 */
198static void
199acpi_identify(driver_t *driver, device_t parent)
200{
201 device_t child;
202 int error;
203#ifdef ENABLE_DEBUGGER
204 char *debugpoint = getenv("debug.acpi.debugger");
205#endif
206
207 FUNCTION_TRACE(__func__);
208
209 if(!cold){
210 printf("Don't load this driver from userland!!\n");
211 return ;
212 }
213
214 /*
215 * Check that we haven't been disabled with a hint.
216 */
217 if (!resource_int_value("acpi", 0, "disabled", &error) &&
218 (error != 0))
219 return_VOID;
220
221 /*
222 * Make sure we're not being doubly invoked.
223 */
224 if (device_find_child(parent, "acpi", 0) != NULL)
225 return_VOID;
226
227 /* initialise the ACPI mutex */
228 mtx_init(&acpi_mutex, "ACPI global lock", MTX_DEF);
229
230 /*
231 * Start up the ACPI CA subsystem.
232 */
233#ifdef ENABLE_DEBUGGER
234 if (debugpoint && !strcmp(debugpoint, "init"))
235 acpi_EnterDebugger();
236#endif
237 if ((error = AcpiInitializeSubsystem()) != AE_OK) {
238 printf("ACPI: initialisation failed: %s\n", AcpiFormatException(error));
239 return_VOID;
240 }
241#ifdef ENABLE_DEBUGGER
242 if (debugpoint && !strcmp(debugpoint, "tables"))
243 acpi_EnterDebugger();
244#endif
245 if ((error = AcpiLoadTables()) != AE_OK) {
246 printf("ACPI: table load failed: %s\n", AcpiFormatException(error));
247 return_VOID;
248 }
249
250 /*
251 * Attach the actual ACPI device.
252 */
253 if ((child = BUS_ADD_CHILD(parent, 0, "acpi", 0)) == NULL) {
254 device_printf(parent, "ACPI: could not attach\n");
255 return_VOID;
256 }
257}
258
259/*
260 * Fetch some descriptive data from ACPI to put in our attach message
261 */
262static int
263acpi_probe(device_t dev)
264{
265 ACPI_TABLE_HEADER th;
266 char buf[20];
267 ACPI_STATUS status;
268 int error;
269
270 FUNCTION_TRACE(__func__);
271 ACPI_LOCK;
272
273 if ((status = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) {
274 device_printf(dev, "couldn't get XSDT header: %s\n", AcpiFormatException(status));
275 error = ENXIO;
276 } else {
277 sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId);
278 device_set_desc_copy(dev, buf);
279 error = 0;
280 }
281 ACPI_UNLOCK;
282 return_VALUE(error);
283}
284
285static int
286acpi_attach(device_t dev)
287{
288 struct acpi_softc *sc;
289 ACPI_STATUS status;
290 int error;
291 UINT32 flags;
292
293#ifdef ENABLE_DEBUGGER
294 char *debugpoint = getenv("debug.acpi.debugger");
295#endif
296
297 FUNCTION_TRACE(__func__);
298 ACPI_LOCK;
299 sc = device_get_softc(dev);
300 bzero(sc, sizeof(*sc));
301 sc->acpi_dev = dev;
302
303 acpi_install_wakeup_handler(sc);
304
305#ifdef ENABLE_DEBUGGER
306 if (debugpoint && !strcmp(debugpoint, "spaces"))
307 acpi_EnterDebugger();
308#endif
309
310 /*
311 * Install the default address space handlers.
312 */
313 error = ENXIO;
314 if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
315 ACPI_ADR_SPACE_SYSTEM_MEMORY,
316 ACPI_DEFAULT_HANDLER,
317 NULL, NULL)) != AE_OK) {
318 device_printf(dev, "could not initialise SystemMemory handler: %s\n", AcpiFormatException(status));
319 goto out;
320 }
321 if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
322 ACPI_ADR_SPACE_SYSTEM_IO,
323 ACPI_DEFAULT_HANDLER,
324 NULL, NULL)) != AE_OK) {
325 device_printf(dev, "could not initialise SystemIO handler: %s\n", AcpiFormatException(status));
326 goto out;
327 }
328 if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
329 ACPI_ADR_SPACE_PCI_CONFIG,
330 ACPI_DEFAULT_HANDLER,
331 NULL, NULL)) != AE_OK) {
332 device_printf(dev, "could not initialise PciConfig handler: %s\n", AcpiFormatException(status));
333 goto out;
334 }
335
336 /*
337 * Bring ACPI fully online.
338 *
339 * Note that some systems (specifically, those with namespace evaluation issues
340 * that require the avoidance of parts of the namespace) must avoid running _INI
341 * and _STA on everything, as well as dodging the final object init pass.
342 *
343 * For these devices, we set ACPI_NO_DEVICE_INIT and ACPI_NO_OBJECT_INIT).
344 *
345 * XXX We should arrange for the object init pass after we have attached all our
346 * child devices, but on many systems it works here.
347 */
348#ifdef ENABLE_DEBUGGER
349 if (debugpoint && !strcmp(debugpoint, "enable"))
350 acpi_EnterDebugger();
351#endif
352 flags = 0;
353 if (getenv("debug.acpi.avoid") != NULL)
354 flags = ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
355 if ((status = AcpiEnableSubsystem(flags)) != AE_OK) {
356 device_printf(dev, "could not enable ACPI: %s\n", AcpiFormatException(status));
357 goto out;
358 }
359
360 /*
361 * Setup our sysctl tree.
362 *
363 * XXX: This doesn't check to make sure that none of these fail.
364 */
365 sysctl_ctx_init(&sc->acpi_sysctl_ctx);
366 sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx,
367 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
368 device_get_name(dev), CTLFLAG_RD, 0, "");
369 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
370 OID_AUTO, "power_button_state", CTLTYPE_STRING | CTLFLAG_RW,
371 &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
372 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
373 OID_AUTO, "sleep_button_state", CTLTYPE_STRING | CTLFLAG_RW,
374 &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
375 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
376 OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW,
377 &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", "");
303#ifdef ENABLE_DEBUGGER
304 if (debugpoint && !strcmp(debugpoint, "spaces"))
305 acpi_EnterDebugger();
306#endif
307
308 /*
309 * Install the default address space handlers.
310 */
311 error = ENXIO;
312 if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
313 ACPI_ADR_SPACE_SYSTEM_MEMORY,
314 ACPI_DEFAULT_HANDLER,
315 NULL, NULL)) != AE_OK) {
316 device_printf(dev, "could not initialise SystemMemory handler: %s\n", AcpiFormatException(status));
317 goto out;
318 }
319 if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
320 ACPI_ADR_SPACE_SYSTEM_IO,
321 ACPI_DEFAULT_HANDLER,
322 NULL, NULL)) != AE_OK) {
323 device_printf(dev, "could not initialise SystemIO handler: %s\n", AcpiFormatException(status));
324 goto out;
325 }
326 if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
327 ACPI_ADR_SPACE_PCI_CONFIG,
328 ACPI_DEFAULT_HANDLER,
329 NULL, NULL)) != AE_OK) {
330 device_printf(dev, "could not initialise PciConfig handler: %s\n", AcpiFormatException(status));
331 goto out;
332 }
333
334 /*
335 * Bring ACPI fully online.
336 *
337 * Note that some systems (specifically, those with namespace evaluation issues
338 * that require the avoidance of parts of the namespace) must avoid running _INI
339 * and _STA on everything, as well as dodging the final object init pass.
340 *
341 * For these devices, we set ACPI_NO_DEVICE_INIT and ACPI_NO_OBJECT_INIT).
342 *
343 * XXX We should arrange for the object init pass after we have attached all our
344 * child devices, but on many systems it works here.
345 */
346#ifdef ENABLE_DEBUGGER
347 if (debugpoint && !strcmp(debugpoint, "enable"))
348 acpi_EnterDebugger();
349#endif
350 flags = 0;
351 if (getenv("debug.acpi.avoid") != NULL)
352 flags = ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
353 if ((status = AcpiEnableSubsystem(flags)) != AE_OK) {
354 device_printf(dev, "could not enable ACPI: %s\n", AcpiFormatException(status));
355 goto out;
356 }
357
358 /*
359 * Setup our sysctl tree.
360 *
361 * XXX: This doesn't check to make sure that none of these fail.
362 */
363 sysctl_ctx_init(&sc->acpi_sysctl_ctx);
364 sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx,
365 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
366 device_get_name(dev), CTLFLAG_RD, 0, "");
367 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
368 OID_AUTO, "power_button_state", CTLTYPE_STRING | CTLFLAG_RW,
369 &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
370 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
371 OID_AUTO, "sleep_button_state", CTLTYPE_STRING | CTLFLAG_RW,
372 &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
373 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
374 OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW,
375 &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", "");
376 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
377 OID_AUTO, "standby_state", CTLTYPE_STRING | CTLFLAG_RW,
378 &sc->acpi_standby_sx, 0, acpi_sleep_state_sysctl, "A", "");
379 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
380 OID_AUTO, "suspend_state", CTLTYPE_STRING | CTLFLAG_RW,
381 &sc->acpi_suspend_sx, 0, acpi_sleep_state_sysctl, "A", "");
378
379 /*
380 * Dispatch the default sleep state to devices.
381 * TBD: should be configured from userland policy manager.
382 */
383 sc->acpi_power_button_sx = ACPI_POWER_BUTTON_DEFAULT_SX;
384 sc->acpi_sleep_button_sx = ACPI_SLEEP_BUTTON_DEFAULT_SX;
385 sc->acpi_lid_switch_sx = ACPI_LID_SWITCH_DEFAULT_SX;
382
383 /*
384 * Dispatch the default sleep state to devices.
385 * TBD: should be configured from userland policy manager.
386 */
387 sc->acpi_power_button_sx = ACPI_POWER_BUTTON_DEFAULT_SX;
388 sc->acpi_sleep_button_sx = ACPI_SLEEP_BUTTON_DEFAULT_SX;
389 sc->acpi_lid_switch_sx = ACPI_LID_SWITCH_DEFAULT_SX;
390 sc->acpi_standby_sx = ACPI_STATE_S1;
391 sc->acpi_suspend_sx = ACPI_STATE_S3;
386
387 acpi_enable_fixed_events(sc);
388
389 /*
390 * Scan the namespace and attach/initialise children.
391 */
392#ifdef ENABLE_DEBUGGER
393 if (debugpoint && !strcmp(debugpoint, "probe"))
394 acpi_EnterDebugger();
395#endif
396 if (!acpi_disabled("bus"))
397 acpi_probe_children(dev);
398
399 /*
400 * Register our shutdown handlers
401 */
402 EVENTHANDLER_REGISTER(shutdown_pre_sync, acpi_shutdown_pre_sync, sc, SHUTDOWN_PRI_LAST);
403 EVENTHANDLER_REGISTER(shutdown_final, acpi_shutdown_final, sc, SHUTDOWN_PRI_LAST);
404
405 /*
406 * Register our acpi event handlers.
407 * XXX should be configurable eg. via userland policy manager.
408 */
409 EVENTHANDLER_REGISTER(acpi_sleep_event, acpi_system_eventhandler_sleep, sc, ACPI_EVENT_PRI_LAST);
410 EVENTHANDLER_REGISTER(acpi_wakeup_event, acpi_system_eventhandler_wakeup, sc, ACPI_EVENT_PRI_LAST);
411
412 /*
413 * Flag our initial states.
414 */
415 sc->acpi_enabled = 1;
416 sc->acpi_sstate = ACPI_STATE_S0;
417
418 /*
419 * Create the control device
420 */
421 sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, 0, 5, 0660, "acpi");
422 sc->acpi_dev_t->si_drv1 = sc;
423
424#ifdef ENABLE_DEBUGGER
425 if (debugpoint && !strcmp(debugpoint, "running"))
426 acpi_EnterDebugger();
427#endif
392
393 acpi_enable_fixed_events(sc);
394
395 /*
396 * Scan the namespace and attach/initialise children.
397 */
398#ifdef ENABLE_DEBUGGER
399 if (debugpoint && !strcmp(debugpoint, "probe"))
400 acpi_EnterDebugger();
401#endif
402 if (!acpi_disabled("bus"))
403 acpi_probe_children(dev);
404
405 /*
406 * Register our shutdown handlers
407 */
408 EVENTHANDLER_REGISTER(shutdown_pre_sync, acpi_shutdown_pre_sync, sc, SHUTDOWN_PRI_LAST);
409 EVENTHANDLER_REGISTER(shutdown_final, acpi_shutdown_final, sc, SHUTDOWN_PRI_LAST);
410
411 /*
412 * Register our acpi event handlers.
413 * XXX should be configurable eg. via userland policy manager.
414 */
415 EVENTHANDLER_REGISTER(acpi_sleep_event, acpi_system_eventhandler_sleep, sc, ACPI_EVENT_PRI_LAST);
416 EVENTHANDLER_REGISTER(acpi_wakeup_event, acpi_system_eventhandler_wakeup, sc, ACPI_EVENT_PRI_LAST);
417
418 /*
419 * Flag our initial states.
420 */
421 sc->acpi_enabled = 1;
422 sc->acpi_sstate = ACPI_STATE_S0;
423
424 /*
425 * Create the control device
426 */
427 sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, 0, 5, 0660, "acpi");
428 sc->acpi_dev_t->si_drv1 = sc;
429
430#ifdef ENABLE_DEBUGGER
431 if (debugpoint && !strcmp(debugpoint, "running"))
432 acpi_EnterDebugger();
433#endif
434
435 if ((error = acpi_machdep_init(dev))) {
436 goto out;
437 }
438
428 error = 0;
429
430 out:
431 ACPI_UNLOCK;
432 return_VALUE(error);
433}
434
435/*
436 * Handle a new device being added
437 */
438static device_t
439acpi_add_child(device_t bus, int order, const char *name, int unit)
440{
441 struct acpi_device *ad;
442 device_t child;
443
444 if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT)) == NULL)
445 return(NULL);
446 bzero(ad, sizeof(*ad));
447
448 resource_list_init(&ad->ad_rl);
449
450 child = device_add_child_ordered(bus, order, name, unit);
451 if (child != NULL)
452 device_set_ivars(child, ad);
453 return(child);
454}
455
456/*
457 * Print child device resource usage
458 */
459static int
460acpi_print_resources(struct resource_list *rl, const char *name, int type, const char *format)
461{
462 struct resource_list_entry *rle;
463 int printed, retval;
464
465 printed = 0;
466 retval = 0;
467
468 if (!SLIST_FIRST(rl))
469 return(0);
470
471 /* Yes, this is kinda cheating */
472 SLIST_FOREACH(rle, rl, link) {
473 if (rle->type == type) {
474 if (printed == 0)
475 retval += printf(" %s ", name);
476 else if (printed > 0)
477 retval += printf(",");
478 printed++;
479 retval += printf(format, rle->start);
480 if (rle->count > 1) {
481 retval += printf("-");
482 retval += printf(format, rle->start +
483 rle->count - 1);
484 }
485 }
486 }
487 return(retval);
488}
489
490static int
491acpi_print_child(device_t bus, device_t child)
492{
493 struct acpi_device *adev = device_get_ivars(child);
494 struct resource_list *rl = &adev->ad_rl;
495 int retval = 0;
496
497 retval += bus_print_child_header(bus, child);
498 retval += acpi_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx");
499 retval += acpi_print_resources(rl, "iomem", SYS_RES_MEMORY, "%#lx");
500 retval += acpi_print_resources(rl, "irq", SYS_RES_IRQ, "%ld");
501 retval += bus_print_child_footer(bus, child);
502
503 return(retval);
504}
505
506
507/*
508 * Handle per-device ivars
509 */
510static int
511acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
512{
513 struct acpi_device *ad;
514
515 if ((ad = device_get_ivars(child)) == NULL) {
516 printf("device has no ivars\n");
517 return(ENOENT);
518 }
519
520 switch(index) {
521 /* ACPI ivars */
522 case ACPI_IVAR_HANDLE:
523 *(ACPI_HANDLE *)result = ad->ad_handle;
524 break;
525 case ACPI_IVAR_MAGIC:
526 *(int *)result = ad->ad_magic;
527 break;
528 case ACPI_IVAR_PRIVATE:
529 *(void **)result = ad->ad_private;
530 break;
531
532 /* ISA compatibility */
533 case ISA_IVAR_VENDORID:
534 case ISA_IVAR_SERIAL:
535 case ISA_IVAR_COMPATID:
536 *(int *)result = -1;
537 break;
538
539 case ISA_IVAR_LOGICALID:
540 *(int *)result = acpi_isa_get_logicalid(child);
541 break;
542
543 default:
544 panic("bad ivar read request (%d)\n", index);
545 return(ENOENT);
546 }
547 return(0);
548}
549
550static int
551acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
552{
553 struct acpi_device *ad;
554
555 if ((ad = device_get_ivars(child)) == NULL) {
556 printf("device has no ivars\n");
557 return(ENOENT);
558 }
559
560 switch(index) {
561 /* ACPI ivars */
562 case ACPI_IVAR_HANDLE:
563 ad->ad_handle = (ACPI_HANDLE)value;
564 break;
565 case ACPI_IVAR_MAGIC:
566 ad->ad_magic = (int )value;
567 break;
568 case ACPI_IVAR_PRIVATE:
569 ad->ad_private = (void *)value;
570 break;
571
572 default:
573 panic("bad ivar write request (%d)\n", index);
574 return(ENOENT);
575 }
576 return(0);
577}
578
579/*
580 * Handle child resource allocation/removal
581 */
582static int
583acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
584{
585 struct acpi_device *ad = device_get_ivars(child);
586 struct resource_list *rl = &ad->ad_rl;
587
588 resource_list_add(rl, type, rid, start, start + count -1, count);
589
590 return(0);
591}
592
593static int
594acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp)
595{
596 struct acpi_device *ad = device_get_ivars(child);
597 struct resource_list *rl = &ad->ad_rl;
598 struct resource_list_entry *rle;
599
600 rle = resource_list_find(rl, type, rid);
601 if (!rle)
602 return(ENOENT);
603
604 if (startp)
605 *startp = rle->start;
606 if (countp)
607 *countp = rle->count;
608
609 return(0);
610}
611
612static struct resource *
613acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
614 u_long start, u_long end, u_long count, u_int flags)
615{
616 struct acpi_device *ad = device_get_ivars(child);
617 struct resource_list *rl = &ad->ad_rl;
618
619 return(resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags));
620}
621
622static int
623acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
624{
625 struct acpi_device *ad = device_get_ivars(child);
626 struct resource_list *rl = &ad->ad_rl;
627
628 return(resource_list_release(rl, bus, child, type, rid, r));
629}
630
631/*
632 * Handle ISA-like devices probing for a PnP ID to match.
633 */
634#define PNP_EISAID(s) \
635 ((((s[0] - '@') & 0x1f) << 2) \
636 | (((s[1] - '@') & 0x18) >> 3) \
637 | (((s[1] - '@') & 0x07) << 13) \
638 | (((s[2] - '@') & 0x1f) << 8) \
639 | (PNP_HEXTONUM(s[4]) << 16) \
640 | (PNP_HEXTONUM(s[3]) << 20) \
641 | (PNP_HEXTONUM(s[6]) << 24) \
642 | (PNP_HEXTONUM(s[5]) << 28))
643
644static u_int32_t
645acpi_isa_get_logicalid(device_t dev)
646{
647 ACPI_HANDLE h;
648 ACPI_DEVICE_INFO devinfo;
649 ACPI_STATUS error;
650 u_int32_t pnpid;
651
652 FUNCTION_TRACE(__func__);
653
654 pnpid = 0;
655 ACPI_LOCK;
656
657 /* fetch and validate the HID */
658 if ((h = acpi_get_handle(dev)) == NULL)
659 goto out;
660 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
661 goto out;
662 if (!(devinfo.Valid & ACPI_VALID_HID))
663 goto out;
664
665 pnpid = PNP_EISAID(devinfo.HardwareId);
666out:
667 ACPI_UNLOCK;
668 return_VALUE(pnpid);
669}
670
671static int
672acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids)
673{
674 int result;
675 u_int32_t pnpid;
676
677 FUNCTION_TRACE(__func__);
678
679 /*
680 * ISA-style drivers attached to ACPI may persist and
681 * probe manually if we return ENOENT. We never want
682 * that to happen, so don't ever return it.
683 */
684 result = ENXIO;
685
686 /* scan the supplied IDs for a match */
687 pnpid = acpi_isa_get_logicalid(child);
688 while (ids && ids->ip_id) {
689 if (pnpid == ids->ip_id) {
690 result = 0;
691 goto out;
692 }
693 ids++;
694 }
695 out:
696 return_VALUE(result);
697}
698
699/*
700 * Scan relevant portions of the ACPI namespace and attach child devices.
701 *
702 * Note that we only expect to find devices in the \_PR_, \_TZ_, \_SI_ and \_SB_ scopes,
703 * and \_PR_ and \_TZ_ become obsolete in the ACPI 2.0 spec.
704 */
705static void
706acpi_probe_children(device_t bus)
707{
708 ACPI_HANDLE parent;
709 static char *scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI", "\\_SB_", NULL};
710 int i;
711
712 FUNCTION_TRACE(__func__);
713 ACPI_ASSERTLOCK;
714
715 /*
716 * Create any static children by calling device identify methods.
717 */
718 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "device identify routines\n"));
719 bus_generic_probe(bus);
720
721 /*
722 * Scan the namespace and insert placeholders for all the devices that
723 * we find.
724 *
725 * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because
726 * we want to create nodes for all devices, not just those that are currently
727 * present. (This assumes that we don't want to create/remove devices as they
728 * appear, which might be smarter.)
729 */
730 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "namespace scan\n"));
731 for (i = 0; scopes[i] != NULL; i++)
732 if ((AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent)) == AE_OK)
733 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child, bus, NULL);
734
735 /*
736 * Scan all of the child devices we have created and let them probe/attach.
737 */
738 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "first bus_generic_attach\n"));
739 bus_generic_attach(bus);
740
741 /*
742 * Some of these children may have attached others as part of their attach
743 * process (eg. the root PCI bus driver), so rescan.
744 */
745 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "second bus_generic_attach\n"));
746 bus_generic_attach(bus);
747
748 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "done attaching children\n"));
749 return_VOID;
750}
751
752/*
753 * Evaluate a child device and determine whether we might attach a device to
754 * it.
755 */
756static ACPI_STATUS
757acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
758{
759 ACPI_OBJECT_TYPE type;
760 device_t child, bus = (device_t)context;
761
762 FUNCTION_TRACE(__func__);
763
764 /*
765 * Skip this device if we think we'll have trouble with it.
766 */
767 if (acpi_avoid(handle))
768 return_ACPI_STATUS(AE_OK);
769
770 if (AcpiGetType(handle, &type) == AE_OK) {
771 switch(type) {
772 case ACPI_TYPE_DEVICE:
773 case ACPI_TYPE_PROCESSOR:
774 case ACPI_TYPE_THERMAL:
775 case ACPI_TYPE_POWER:
776 if (acpi_disabled("children"))
777 break;
778 /*
779 * Create a placeholder device for this node. Sort the placeholder
780 * so that the probe/attach passes will run breadth-first.
781 */
782 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n", acpi_name(handle)));
783 child = BUS_ADD_CHILD(bus, level * 10, NULL, -1);
784 if (child == NULL)
785 break;
786 acpi_set_handle(child, handle);
787
788 /*
789 * Check that the device is present. If it's not present,
790 * leave it disabled (so that we have a device_t attached to
791 * the handle, but we don't probe it).
792 */
793 if ((type == ACPI_TYPE_DEVICE) && (!acpi_DeviceIsPresent(child))) {
794 device_disable(child);
795 break;
796 }
797
798 /*
799 * Get the device's resource settings and attach them.
800 * Note that if the device has _PRS but no _CRS, we need
801 * to decide when it's appropriate to try to configure the
802 * device. Ignore the return value here; it's OK for the
803 * device not to have any resources.
804 */
805 acpi_parse_resources(child, handle, &acpi_res_parse_set);
806
807 /* if we're debugging, probe/attach now rather than later */
808 DEBUG_EXEC(device_probe_and_attach(child));
809 break;
810 }
811 }
812 return_ACPI_STATUS(AE_OK);
813}
814
815static void
816acpi_shutdown_pre_sync(void *arg, int howto)
817{
818
819 ACPI_ASSERTLOCK;
820
821 /*
822 * Disable all ACPI events before soft off, otherwise the system
823 * will be turned on again on some laptops.
824 *
825 * XXX this should probably be restricted to masking some events just
826 * before powering down, since we may still need ACPI during the
827 * shutdown process.
828 */
829 acpi_Disable((struct acpi_softc *)arg);
830}
831
832static void
833acpi_shutdown_final(void *arg, int howto)
834{
835 ACPI_STATUS status;
836
837 ACPI_ASSERTLOCK;
838
839 if (howto & RB_POWEROFF) {
840 printf("Power system off using ACPI...\n");
841 if ((status = AcpiEnterSleepState(acpi_off_state)) != AE_OK) {
842 printf("ACPI power-off failed - %s\n", AcpiFormatException(status));
843 } else {
844 DELAY(1000000);
845 printf("ACPI power-off failed - timeout\n");
846 }
847 }
848}
849
850static void
851acpi_enable_fixed_events(struct acpi_softc *sc)
852{
853 static int first_time = 1;
854#define MSGFORMAT "%s button is handled as a fixed feature programming model.\n"
855
856 ACPI_ASSERTLOCK;
857
858 /* Enable and clear fixed events and install handlers. */
859 if ((AcpiGbl_FADT != NULL) && (AcpiGbl_FADT->PwrButton == 0)) {
860 AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED, 0);
861 AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
862 AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
863 acpi_eventhandler_power_button_for_sleep, sc);
864 if (first_time) {
865 device_printf(sc->acpi_dev, MSGFORMAT, "power");
866 }
867 }
868 if ((AcpiGbl_FADT != NULL) && (AcpiGbl_FADT->SleepButton == 0)) {
869 AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED, 0);
870 AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
871 AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
872 acpi_eventhandler_sleep_button_for_sleep, sc);
873 if (first_time) {
874 device_printf(sc->acpi_dev, MSGFORMAT, "sleep");
875 }
876 }
877
878 first_time = 0;
879}
880
881/*
882 * Returns true if the device is actually present and should
883 * be attached to. This requires the present, enabled, UI-visible
884 * and diagnostics-passed bits to be set.
885 */
886BOOLEAN
887acpi_DeviceIsPresent(device_t dev)
888{
889 ACPI_HANDLE h;
890 ACPI_DEVICE_INFO devinfo;
891 ACPI_STATUS error;
892
893 ACPI_ASSERTLOCK;
894
895 if ((h = acpi_get_handle(dev)) == NULL)
896 return(FALSE);
897 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
898 return(FALSE);
899 /* if no _STA method, must be present */
900 if (!(devinfo.Valid & ACPI_VALID_STA))
901 return(TRUE);
902 /* return true for 'present' and 'functioning' */
903 if ((devinfo.CurrentStatus & 0x9) == 0x9)
904 return(TRUE);
905 return(FALSE);
906}
907
908/*
909 * Match a HID string against a device
910 */
911BOOLEAN
912acpi_MatchHid(device_t dev, char *hid)
913{
914 ACPI_HANDLE h;
915 ACPI_DEVICE_INFO devinfo;
916 ACPI_STATUS error;
917 int cid;
918
919 ACPI_ASSERTLOCK;
920
921 if (hid == NULL)
922 return(FALSE);
923 if ((h = acpi_get_handle(dev)) == NULL)
924 return(FALSE);
925 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
926 return(FALSE);
927 if ((devinfo.Valid & ACPI_VALID_HID) && !strcmp(hid, devinfo.HardwareId))
928 return(TRUE);
929 if ((error = acpi_EvaluateInteger(h, "_CID", &cid)) != AE_OK)
930 return(FALSE);
931 if (cid == PNP_EISAID(hid))
932 return(TRUE);
933 return(FALSE);
934}
935
936/*
937 * Return the handle of a named object within our scope, ie. that of (parent)
938 * or one if its parents.
939 */
940ACPI_STATUS
941acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
942{
943 ACPI_HANDLE r;
944 ACPI_STATUS status;
945
946 ACPI_ASSERTLOCK;
947
948 /* walk back up the tree to the root */
949 for (;;) {
950 status = AcpiGetHandle(parent, path, &r);
951 if (status == AE_OK) {
952 *result = r;
953 return(AE_OK);
954 }
955 if (status != AE_NOT_FOUND)
956 return(AE_OK);
957 if (AcpiGetParent(parent, &r) != AE_OK)
958 return(AE_NOT_FOUND);
959 parent = r;
960 }
961}
962
963/*
964 * Allocate a buffer with a preset data size.
965 */
966ACPI_BUFFER *
967acpi_AllocBuffer(int size)
968{
969 ACPI_BUFFER *buf;
970
971 if ((buf = malloc(size + sizeof(*buf), M_ACPIDEV, M_NOWAIT)) == NULL)
972 return(NULL);
973 buf->Length = size;
974 buf->Pointer = (void *)(buf + 1);
975 return(buf);
976}
977
978/*
979 * Perform the tedious double-get procedure required for fetching something into
980 * an ACPI_BUFFER that has not been initialised.
981 */
982ACPI_STATUS
983acpi_GetIntoBuffer(ACPI_HANDLE handle, ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUFFER *), ACPI_BUFFER *buf)
984{
985 ACPI_STATUS status;
986
987 ACPI_ASSERTLOCK;
988
989 buf->Length = 0;
990 buf->Pointer = NULL;
991
992 if ((status = func(handle, buf)) != AE_BUFFER_OVERFLOW)
993 return(status);
994 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
995 return(AE_NO_MEMORY);
996 return(func(handle, buf));
997}
998
999/*
1000 * Perform the tedious double-get procedure required for fetching a table into
1001 * an ACPI_BUFFER that has not been initialised.
1002 */
1003ACPI_STATUS
1004acpi_GetTableIntoBuffer(ACPI_TABLE_TYPE table, UINT32 instance, ACPI_BUFFER *buf)
1005{
1006 ACPI_STATUS status;
1007
1008 ACPI_ASSERTLOCK;
1009
1010 buf->Length = 0;
1011 buf->Pointer = NULL;
1012
1013 if ((status = AcpiGetTable(table, instance, buf)) != AE_BUFFER_OVERFLOW)
1014 return(status);
1015 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
1016 return(AE_NO_MEMORY);
1017 return(AcpiGetTable(table, instance, buf));
1018}
1019
1020/*
1021 * Perform the tedious double-evaluate procedure for evaluating something into
1022 * an ACPI_BUFFER that has not been initialised. Note that this evaluates
1023 * twice, so avoid applying this to things that may have side-effects.
1024 *
1025 * This is like AcpiEvaluateObject with automatic buffer allocation.
1026 */
1027ACPI_STATUS
1028acpi_EvaluateIntoBuffer(ACPI_HANDLE object, ACPI_STRING pathname, ACPI_OBJECT_LIST *params,
1029 ACPI_BUFFER *buf)
1030{
1031 ACPI_STATUS status;
1032
1033 ACPI_ASSERTLOCK;
1034
1035 buf->Length = 0;
1036 buf->Pointer = NULL;
1037
1038 if ((status = AcpiEvaluateObject(object, pathname, params, buf)) != AE_BUFFER_OVERFLOW)
1039 return(status);
1040 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
1041 return(AE_NO_MEMORY);
1042 return(AcpiEvaluateObject(object, pathname, params, buf));
1043}
1044
1045/*
1046 * Evaluate a path that should return an integer.
1047 */
1048ACPI_STATUS
1049acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number)
1050{
1051 ACPI_STATUS error;
1052 ACPI_BUFFER buf;
1053 ACPI_OBJECT param, *p;
1054 int i;
1055
1056 ACPI_ASSERTLOCK;
1057
1058 if (handle == NULL)
1059 handle = ACPI_ROOT_OBJECT;
1060
1061 /*
1062 * Assume that what we've been pointed at is an Integer object, or
1063 * a method that will return an Integer.
1064 */
1065 buf.Pointer = &param;
1066 buf.Length = sizeof(param);
1067 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) {
1068 if (param.Type == ACPI_TYPE_INTEGER) {
1069 *number = param.Integer.Value;
1070 } else {
1071 error = AE_TYPE;
1072 }
1073 }
1074
1075 /*
1076 * In some applications, a method that's expected to return an Integer
1077 * may instead return a Buffer (probably to simplify some internal
1078 * arithmetic). We'll try to fetch whatever it is, and if it's a Buffer,
1079 * convert it into an Integer as best we can.
1080 *
1081 * This is a hack.
1082 */
1083 if (error == AE_BUFFER_OVERFLOW) {
1084 if ((buf.Pointer = AcpiOsCallocate(buf.Length)) == NULL) {
1085 error = AE_NO_MEMORY;
1086 } else {
1087 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) {
1088 p = (ACPI_OBJECT *)buf.Pointer;
1089 if (p->Type != ACPI_TYPE_BUFFER) {
1090 error = AE_TYPE;
1091 } else {
1092 if (p->Buffer.Length > sizeof(int)) {
1093 error = AE_BAD_DATA;
1094 } else {
1095 *number = 0;
1096 for (i = 0; i < p->Buffer.Length; i++)
1097 *number += (*(p->Buffer.Pointer + i) << (i * 8));
1098 }
1099 }
1100 }
1101 }
1102 AcpiOsFree(buf.Pointer);
1103 }
1104 return(error);
1105}
1106
1107/*
1108 * Iterate over the elements of an a package object, calling the supplied
1109 * function for each element.
1110 *
1111 * XXX possible enhancement might be to abort traversal on error.
1112 */
1113ACPI_STATUS
1114acpi_ForeachPackageObject(ACPI_OBJECT *pkg, void (* func)(ACPI_OBJECT *comp, void *arg), void *arg)
1115{
1116 ACPI_OBJECT *comp;
1117 int i;
1118
1119 if ((pkg == NULL) || (pkg->Type != ACPI_TYPE_PACKAGE))
1120 return(AE_BAD_PARAMETER);
1121
1122 /* iterate over components */
1123 for (i = 0, comp = pkg->Package.Elements; i < pkg->Package.Count; i++, comp++)
1124 func(comp, arg);
1125
1126 return(AE_OK);
1127}
1128
1129/*
1130 * Find the (index)th resource object in a set.
1131 */
1132ACPI_STATUS
1133acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp)
1134{
1135 ACPI_RESOURCE *rp;
1136 int i;
1137
1138 rp = (ACPI_RESOURCE *)buf->Pointer;
1139 i = index;
1140 while (i-- > 0) {
1141 /* range check */
1142 if (rp > (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
1143 return(AE_BAD_PARAMETER);
1144 /* check for terminator */
1145 if ((rp->Id == ACPI_RSTYPE_END_TAG) ||
1146 (rp->Length == 0))
1147 return(AE_NOT_FOUND);
1148 rp = ACPI_RESOURCE_NEXT(rp);
1149 }
1150 if (resp != NULL)
1151 *resp = rp;
1152 return(AE_OK);
1153}
1154
1155/*
1156 * Append an ACPI_RESOURCE to an ACPI_BUFFER.
1157 *
1158 * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
1159 * provided to contain it. If the ACPI_BUFFER is empty, allocate a sensible
1160 * backing block. If the ACPI_RESOURCE is NULL, return an empty set of
1161 * resources.
1162 */
1163#define ACPI_INITIAL_RESOURCE_BUFFER_SIZE 512
1164
1165ACPI_STATUS
1166acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
1167{
1168 ACPI_RESOURCE *rp;
1169 void *newp;
1170
1171 /*
1172 * Initialise the buffer if necessary.
1173 */
1174 if (buf->Pointer == NULL) {
1175 buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
1176 if ((buf->Pointer = AcpiOsAllocate(buf->Length)) == NULL)
1177 return(AE_NO_MEMORY);
1178 rp = (ACPI_RESOURCE *)buf->Pointer;
1179 rp->Id = ACPI_RSTYPE_END_TAG;
1180 rp->Length = 0;
1181 }
1182 if (res == NULL)
1183 return(AE_OK);
1184
1185 /*
1186 * Scan the current buffer looking for the terminator.
1187 * This will either find the terminator or hit the end
1188 * of the buffer and return an error.
1189 */
1190 rp = (ACPI_RESOURCE *)buf->Pointer;
1191 for (;;) {
1192 /* range check, don't go outside the buffer */
1193 if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
1194 return(AE_BAD_PARAMETER);
1195 if ((rp->Id == ACPI_RSTYPE_END_TAG) ||
1196 (rp->Length == 0)) {
1197 break;
1198 }
1199 rp = ACPI_RESOURCE_NEXT(rp);
1200 }
1201
1202 /*
1203 * Check the size of the buffer and expand if required.
1204 *
1205 * Required size is:
1206 * size of existing resources before terminator +
1207 * size of new resource and header +
1208 * size of terminator.
1209 *
1210 * Note that this loop should really only run once, unless
1211 * for some reason we are stuffing a *really* huge resource.
1212 */
1213 while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +
1214 res->Length + ACPI_RESOURCE_LENGTH_NO_DATA +
1215 ACPI_RESOURCE_LENGTH) >= buf->Length) {
1216 if ((newp = AcpiOsAllocate(buf->Length * 2)) == NULL)
1217 return(AE_NO_MEMORY);
1218 bcopy(buf->Pointer, newp, buf->Length);
1219 rp = (ACPI_RESOURCE *)((u_int8_t *)newp +
1220 ((u_int8_t *)rp - (u_int8_t *)buf->Pointer));
1221 AcpiOsFree(buf->Pointer);
1222 buf->Pointer = newp;
1223 buf->Length += buf->Length;
1224 }
1225
1226 /*
1227 * Insert the new resource.
1228 */
1229 bcopy(res, rp, res->Length + ACPI_RESOURCE_LENGTH_NO_DATA);
1230
1231 /*
1232 * And add the terminator.
1233 */
1234 rp = ACPI_RESOURCE_NEXT(rp);
1235 rp->Id = ACPI_RSTYPE_END_TAG;
1236 rp->Length = 0;
1237
1238 return(AE_OK);
1239}
1240
1241
1242/*
1243 * Set the system sleep state
1244 *
1245 * Currently we only support S1 and S5
1246 */
1247ACPI_STATUS
1248acpi_SetSleepState(struct acpi_softc *sc, int state)
1249{
1250 ACPI_STATUS status = AE_OK;
1251 UINT16 Count;
1252 UINT8 TypeA;
1253 UINT8 TypeB;
1254
1255 FUNCTION_TRACE_U32(__func__, state);
1256 ACPI_ASSERTLOCK;
1257
1258 switch (state) {
1259 case ACPI_STATE_S0: /* XXX only for testing */
1260 status = AcpiEnterSleepState((UINT8)state);
1261 if (status != AE_OK) {
1262 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status));
1263 }
1264 break;
1265
1266 case ACPI_STATE_S1:
1267 case ACPI_STATE_S2:
1268 case ACPI_STATE_S3:
1269 case ACPI_STATE_S4:
1270 status = AcpiHwObtainSleepTypeRegisterData((UINT8)state, &TypeA, &TypeB);
1271 if (status != AE_OK) {
1272 device_printf(sc->acpi_dev, "AcpiHwObtainSleepTypeRegisterData failed - %s\n", AcpiFormatException(status));
1273 break;
1274 }
1275
1276 /*
1277 * Inform all devices that we are going to sleep.
1278 */
1279 if (DEVICE_SUSPEND(root_bus) != 0) {
1280 /*
1281 * Re-wake the system.
1282 *
1283 * XXX note that a better two-pass approach with a 'veto' pass
1284 * followed by a "real thing" pass would be better, but the
1285 * current bus interface does not provide for this.
1286 */
1287 DEVICE_RESUME(root_bus);
1288 return_ACPI_STATUS(AE_ERROR);
1289 }
1290 sc->acpi_sstate = state;
1291
1292 if (state != ACPI_STATE_S1) {
1293 acpi_sleep_machdep(sc, state);
1294
1295 /* AcpiEnterSleepState() maybe incompleted, unlock here. */
1296 AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
1297
1298 /* Re-enable ACPI hardware on wakeup from sleep state 4. */
1299 if (state >= ACPI_STATE_S4) {
1300 acpi_Disable(sc);
1301 acpi_Enable(sc);
1302 }
1303 } else {
1304 status = AcpiEnterSleepState((UINT8)state);
1305 if (status != AE_OK) {
1306 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status));
1307 break;
1308 }
1309 /* wait for the WAK_STS bit */
1310 Count = 0;
1311 while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
1312 AcpiOsSleep(0, 1);
1313 /*
1314 * Some BIOSes don't set WAK_STS at all,
1315 * give up waiting for wakeup if we time out.
1316 */
1317 if (Count > 1000) {
1318 break; /* giving up */
1319 }
1320 Count++;
1321 }
1322 }
1323 AcpiLeaveSleepState((UINT8)state);
1324 DEVICE_RESUME(root_bus);
1325 sc->acpi_sstate = ACPI_STATE_S0;
1326 acpi_enable_fixed_events(sc);
1327 break;
1328
1329 case ACPI_STATE_S5:
1330 /*
1331 * Shut down cleanly and power off. This will call us back through the
1332 * shutdown handlers.
1333 */
1334 shutdown_nice(RB_POWEROFF);
1335 break;
1336
1337 default:
1338 status = AE_BAD_PARAMETER;
1339 break;
1340 }
1341 return_ACPI_STATUS(status);
1342}
1343
1344/*
1345 * Enable/Disable ACPI
1346 */
1347ACPI_STATUS
1348acpi_Enable(struct acpi_softc *sc)
1349{
1350 ACPI_STATUS status;
1351 u_int32_t flags;
1352
1353 FUNCTION_TRACE(__func__);
1354 ACPI_ASSERTLOCK;
1355
1356 flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
1357 ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
1358 if (!sc->acpi_enabled) {
1359 status = AcpiEnableSubsystem(flags);
1360 } else {
1361 status = AE_OK;
1362 }
1363 if (status == AE_OK)
1364 sc->acpi_enabled = 1;
1365 return_ACPI_STATUS(status);
1366}
1367
1368ACPI_STATUS
1369acpi_Disable(struct acpi_softc *sc)
1370{
1371 ACPI_STATUS status;
1372
1373 FUNCTION_TRACE(__func__);
1374 ACPI_ASSERTLOCK;
1375
1376 if (sc->acpi_enabled) {
1377 status = AcpiDisable();
1378 } else {
1379 status = AE_OK;
1380 }
1381 if (status == AE_OK)
1382 sc->acpi_enabled = 0;
1383 return_ACPI_STATUS(status);
1384}
1385
1386/*
1387 * ACPI Event Handlers
1388 */
1389
1390/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
1391
1392static void
1393acpi_system_eventhandler_sleep(void *arg, int state)
1394{
1395 FUNCTION_TRACE_U32(__func__, state);
1396
1397 ACPI_LOCK;
1398 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
1399 acpi_SetSleepState((struct acpi_softc *)arg, state);
1400 ACPI_UNLOCK;
1401 return_VOID;
1402}
1403
1404static void
1405acpi_system_eventhandler_wakeup(void *arg, int state)
1406{
1407 FUNCTION_TRACE_U32(__func__, state);
1408
1409 /* Well, what to do? :-) */
1410
1411 ACPI_LOCK;
1412 ACPI_UNLOCK;
1413
1414 return_VOID;
1415}
1416
1417/*
1418 * ACPICA Event Handlers (FixedEvent, also called from button notify handler)
1419 */
1420UINT32
1421acpi_eventhandler_power_button_for_sleep(void *context)
1422{
1423 struct acpi_softc *sc = (struct acpi_softc *)context;
1424
1425 FUNCTION_TRACE(__func__);
1426
1427 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
1428
1429 return_VALUE(INTERRUPT_HANDLED);
1430}
1431
1432UINT32
1433acpi_eventhandler_power_button_for_wakeup(void *context)
1434{
1435 struct acpi_softc *sc = (struct acpi_softc *)context;
1436
1437 FUNCTION_TRACE(__func__);
1438
1439 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx);
1440
1441 return_VALUE(INTERRUPT_HANDLED);
1442}
1443
1444UINT32
1445acpi_eventhandler_sleep_button_for_sleep(void *context)
1446{
1447 struct acpi_softc *sc = (struct acpi_softc *)context;
1448
1449 FUNCTION_TRACE(__func__);
1450
1451 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
1452
1453 return_VALUE(INTERRUPT_HANDLED);
1454}
1455
1456UINT32
1457acpi_eventhandler_sleep_button_for_wakeup(void *context)
1458{
1459 struct acpi_softc *sc = (struct acpi_softc *)context;
1460
1461 FUNCTION_TRACE(__func__);
1462
1463 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx);
1464
1465 return_VALUE(INTERRUPT_HANDLED);
1466}
1467
1468/*
1469 * XXX This is kinda ugly, and should not be here.
1470 */
1471struct acpi_staticbuf {
1472 ACPI_BUFFER buffer;
1473 char data[512];
1474};
1475
1476char *
1477acpi_name(ACPI_HANDLE handle)
1478{
1479 static struct acpi_staticbuf buf;
1480
1481 ACPI_ASSERTLOCK;
1482
1483 buf.buffer.Length = 512;
1484 buf.buffer.Pointer = &buf.data[0];
1485
1486 if (AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer) == AE_OK)
1487 return(buf.buffer.Pointer);
1488 return("(unknown path)");
1489}
1490
1491/*
1492 * Debugging/bug-avoidance. Avoid trying to fetch info on various
1493 * parts of the namespace.
1494 */
1495int
1496acpi_avoid(ACPI_HANDLE handle)
1497{
1498 char *cp, *np;
1499 int len;
1500
1501 np = acpi_name(handle);
1502 if (*np == '\\')
1503 np++;
1504 if ((cp = getenv("debug.acpi.avoid")) == NULL)
1505 return(0);
1506
1507 /* scan the avoid list checking for a match */
1508 for (;;) {
1509 while ((*cp != 0) && isspace(*cp))
1510 cp++;
1511 if (*cp == 0)
1512 break;
1513 len = 0;
1514 while ((cp[len] != 0) && !isspace(cp[len]))
1515 len++;
1516 if (!strncmp(cp, np, len))
1517 return(1);
1518 cp += len;
1519 }
1520 return(0);
1521}
1522
1523/*
1524 * Debugging/bug-avoidance. Disable ACPI subsystem components.
1525 */
1526int
1527acpi_disabled(char *subsys)
1528{
1529 char *cp;
1530 int len;
1531
1532 if ((cp = getenv("debug.acpi.disable")) == NULL)
1533 return(0);
1534 if (!strcmp(cp, "all"))
1535 return(1);
1536
1537 /* scan the disable list checking for a match */
1538 for (;;) {
1539 while ((*cp != 0) && isspace(*cp))
1540 cp++;
1541 if (*cp == 0)
1542 break;
1543 len = 0;
1544 while ((cp[len] != 0) && !isspace(cp[len]))
1545 len++;
1546 if (!strncmp(cp, subsys, len))
1547 return(1);
1548 cp += len;
1549 }
1550 return(0);
1551}
1552
1553/*
1554 * Control interface.
1555 *
1556 * We multiplex ioctls for all participating ACPI devices here. Individual
1557 * drivers wanting to be accessible via /dev/acpi should use the register/deregister
1558 * interface to make their handlers visible.
1559 */
1560struct acpi_ioctl_hook
1561{
1562 TAILQ_ENTRY(acpi_ioctl_hook) link;
1563 u_long cmd;
1564 int (* fn)(u_long cmd, caddr_t addr, void *arg);
1565 void *arg;
1566};
1567
1568static TAILQ_HEAD(,acpi_ioctl_hook) acpi_ioctl_hooks;
1569static int acpi_ioctl_hooks_initted;
1570
1571/*
1572 * Register an ioctl handler.
1573 */
1574int
1575acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg)
1576{
1577 struct acpi_ioctl_hook *hp;
1578
1579 if ((hp = malloc(sizeof(*hp), M_ACPIDEV, M_NOWAIT)) == NULL)
1580 return(ENOMEM);
1581 hp->cmd = cmd;
1582 hp->fn = fn;
1583 hp->arg = arg;
1584 if (acpi_ioctl_hooks_initted == 0) {
1585 TAILQ_INIT(&acpi_ioctl_hooks);
1586 acpi_ioctl_hooks_initted = 1;
1587 }
1588 TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link);
1589 return(0);
1590}
1591
1592/*
1593 * Deregister an ioctl handler.
1594 */
1595void
1596acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg))
1597{
1598 struct acpi_ioctl_hook *hp;
1599
1600 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link)
1601 if ((hp->cmd == cmd) && (hp->fn == fn))
1602 break;
1603
1604 if (hp != NULL) {
1605 TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link);
1606 free(hp, M_ACPIDEV);
1607 }
1608}
1609
1610static int
1611acpiopen(dev_t dev, int flag, int fmt, struct thread *td)
1612{
1613 return(0);
1614}
1615
1616static int
1617acpiclose(dev_t dev, int flag, int fmt, struct thread *td)
1618{
1619 return(0);
1620}
1621
1622static int
1623acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
1624{
1625 struct acpi_softc *sc;
1626 struct acpi_ioctl_hook *hp;
1627 int error, xerror, state;
1628
1629 ACPI_LOCK;
1630
1631 error = state = 0;
1632 sc = dev->si_drv1;
1633
1634 /*
1635 * Scan the list of registered ioctls, looking for handlers.
1636 */
1637 if (acpi_ioctl_hooks_initted) {
1638 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) {
1639 if (hp->cmd == cmd) {
1640 xerror = hp->fn(cmd, addr, hp->arg);
1641 if (xerror != 0)
1642 error = xerror;
1643 goto out;
1644 }
1645 }
1646 }
1647
1648 /*
1649 * Core system ioctls.
1650 */
1651 switch (cmd) {
1652 case ACPIIO_ENABLE:
1653 if (ACPI_FAILURE(acpi_Enable(sc)))
1654 error = ENXIO;
1655 break;
1656
1657 case ACPIIO_DISABLE:
1658 if (ACPI_FAILURE(acpi_Disable(sc)))
1659 error = ENXIO;
1660 break;
1661
1662 case ACPIIO_SETSLPSTATE:
1663 if (!sc->acpi_enabled) {
1664 error = ENXIO;
1665 break;
1666 }
1667 state = *(int *)addr;
1668 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX) {
1669 acpi_SetSleepState(sc, state);
1670 } else {
1671 error = EINVAL;
1672 }
1673 break;
1674
1675 default:
1676 if (error == 0)
1677 error = EINVAL;
1678 break;
1679 }
1680
1681out:
1682 ACPI_UNLOCK;
1683 return(error);
1684}
1685
1686static int
1687acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
1688{
1689 char sleep_state[10];
1690 int error;
1691 u_int new_state, old_state;
1692
1693 old_state = *(u_int *)oidp->oid_arg1;
1694 if (old_state > ACPI_S_STATES_MAX) {
1695 strcpy(sleep_state, "unknown");
1696 } else {
1697 strncpy(sleep_state, sleep_state_names[old_state],
1698 sizeof(sleep_state_names[old_state]));
1699 }
1700 error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
1701 if (error == 0 && req->newptr != NULL) {
1702 for (new_state = ACPI_STATE_S0; new_state <= ACPI_S_STATES_MAX; new_state++) {
1703 if (strncmp(sleep_state, sleep_state_names[new_state],
1704 sizeof(sleep_state)) == 0)
1705 break;
1706 }
1707 if ((new_state != old_state) && (new_state <= ACPI_S_STATES_MAX)) {
1708 *(u_int *)oidp->oid_arg1 = new_state;
1709 } else {
1710 error = EINVAL;
1711 }
1712 }
1713 return(error);
1714}
1715
1716#ifdef ACPI_DEBUG
1717/*
1718 * Support for parsing debug options from the kernel environment.
1719 *
1720 * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers
1721 * by specifying the names of the bits in the debug.acpi.layer and
1722 * debug.acpi.level environment variables. Bits may be unset by
1723 * prefixing the bit name with !.
1724 */
1725struct debugtag
1726{
1727 char *name;
1728 UINT32 value;
1729};
1730
1731static struct debugtag dbg_layer[] = {
1732 {"ACPI_UTILITIES", ACPI_UTILITIES},
1733 {"ACPI_HARDWARE", ACPI_HARDWARE},
1734 {"ACPI_EVENTS", ACPI_EVENTS},
1735 {"ACPI_TABLES", ACPI_TABLES},
1736 {"ACPI_NAMESPACE", ACPI_NAMESPACE},
1737 {"ACPI_PARSER", ACPI_PARSER},
1738 {"ACPI_DISPATCHER", ACPI_DISPATCHER},
1739 {"ACPI_EXECUTER", ACPI_EXECUTER},
1740 {"ACPI_RESOURCES", ACPI_RESOURCES},
1741 {"ACPI_DEBUGGER", ACPI_DEBUGGER},
1742 {"ACPI_OS_SERVICES", ACPI_OS_SERVICES},
1743
1744 {"ACPI_BUS", ACPI_BUS},
1745 {"ACPI_SYSTEM", ACPI_SYSTEM},
1746 {"ACPI_POWER", ACPI_POWER},
1747 {"ACPI_EC", ACPI_EC},
1748 {"ACPI_AC_ADAPTER", ACPI_AC_ADAPTER},
1749 {"ACPI_BATTERY", ACPI_BATTERY},
1750 {"ACPI_BUTTON", ACPI_BUTTON},
1751 {"ACPI_PROCESSOR", ACPI_PROCESSOR},
1752 {"ACPI_THERMAL", ACPI_THERMAL},
1753 {"ACPI_FAN", ACPI_FAN},
1754
1755 {"ACPI_ALL_COMPONENTS", ACPI_ALL_COMPONENTS},
1756 {NULL, 0}
1757};
1758
1759static struct debugtag dbg_level[] = {
1760 {"ACPI_LV_OK", ACPI_LV_OK},
1761 {"ACPI_LV_INFO", ACPI_LV_INFO},
1762 {"ACPI_LV_WARN", ACPI_LV_WARN},
1763 {"ACPI_LV_ERROR", ACPI_LV_ERROR},
1764 {"ACPI_LV_FATAL", ACPI_LV_FATAL},
1765 {"ACPI_LV_DEBUG_OBJECT", ACPI_LV_DEBUG_OBJECT},
1766 {"ACPI_LV_ALL_EXCEPTIONS", ACPI_LV_ALL_EXCEPTIONS},
1767 {"ACPI_LV_THREADS", ACPI_LV_THREADS},
1768 {"ACPI_LV_PARSE", ACPI_LV_PARSE},
1769 {"ACPI_LV_DISPATCH", ACPI_LV_DISPATCH},
1770 {"ACPI_LV_LOAD", ACPI_LV_LOAD},
1771 {"ACPI_LV_EXEC", ACPI_LV_EXEC},
1772 {"ACPI_LV_NAMES", ACPI_LV_NAMES},
1773 {"ACPI_LV_OPREGION", ACPI_LV_OPREGION},
1774 {"ACPI_LV_BFIELD", ACPI_LV_BFIELD},
1775 {"ACPI_LV_TABLES", ACPI_LV_TABLES},
1776 {"ACPI_LV_FUNCTIONS", ACPI_LV_FUNCTIONS},
1777 {"ACPI_LV_VALUES", ACPI_LV_VALUES},
1778 {"ACPI_LV_OBJECTS", ACPI_LV_OBJECTS},
1779 {"ACPI_LV_ALLOCATIONS", ACPI_LV_ALLOCATIONS},
1780 {"ACPI_LV_RESOURCES", ACPI_LV_RESOURCES},
1781 {"ACPI_LV_IO", ACPI_LV_IO},
1782 {"ACPI_LV_INTERRUPTS", ACPI_LV_INTERRUPTS},
1783 {"ACPI_LV_USER_REQUESTS", ACPI_LV_USER_REQUESTS},
1784 {"ACPI_LV_PACKAGE", ACPI_LV_PACKAGE},
1785 {"ACPI_LV_MUTEX", ACPI_LV_MUTEX},
1786 {"ACPI_LV_INIT", ACPI_LV_INIT},
1787 {"ACPI_LV_ALL", ACPI_LV_ALL},
1788 {"ACPI_DB_AML_DISASSEMBLE", ACPI_DB_AML_DISASSEMBLE},
1789 {"ACPI_DB_VERBOSE_INFO", ACPI_DB_VERBOSE_INFO},
1790 {"ACPI_DB_FULL_TABLES", ACPI_DB_FULL_TABLES},
1791 {"ACPI_DB_EVENTS", ACPI_DB_EVENTS},
1792 {"ACPI_DB_VERBOSE", ACPI_DB_VERBOSE},
1793 {NULL, 0}
1794};
1795
1796static void
1797acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag)
1798{
1799 char *ep;
1800 int i, l;
1801 int set;
1802
1803 while (*cp) {
1804 if (isspace(*cp)) {
1805 cp++;
1806 continue;
1807 }
1808 ep = cp;
1809 while (*ep && !isspace(*ep))
1810 ep++;
1811 if (*cp == '!') {
1812 set = 0;
1813 cp++;
1814 if (cp == ep)
1815 continue;
1816 } else {
1817 set = 1;
1818 }
1819 l = ep - cp;
1820 for (i = 0; tag[i].name != NULL; i++) {
1821 if (!strncmp(cp, tag[i].name, l)) {
1822 if (set) {
1823 *flag |= tag[i].value;
1824 } else {
1825 *flag &= ~tag[i].value;
1826 }
1827 printf("ACPI_DEBUG: set '%s'\n", tag[i].name);
1828 }
1829 }
1830 cp = ep;
1831 }
1832}
1833
1834static void
1835acpi_set_debugging(void *junk)
1836{
1837 char *cp;
1838
1839 AcpiDbgLayer = 0;
1840 AcpiDbgLevel = 0;
1841 if ((cp = getenv("debug.acpi.layer")) != NULL)
1842 acpi_parse_debug(cp, &dbg_layer[0], &AcpiDbgLayer);
1843 if ((cp = getenv("debug.acpi.level")) != NULL)
1844 acpi_parse_debug(cp, &dbg_level[0], &AcpiDbgLevel);
1845
1846 printf("ACPI debug layer 0x%x debug level 0x%x\n", AcpiDbgLayer, AcpiDbgLevel);
1847}
1848SYSINIT(acpi_debugging, SI_SUB_TUNABLES, SI_ORDER_ANY, acpi_set_debugging, NULL);
1849#endif
439 error = 0;
440
441 out:
442 ACPI_UNLOCK;
443 return_VALUE(error);
444}
445
446/*
447 * Handle a new device being added
448 */
449static device_t
450acpi_add_child(device_t bus, int order, const char *name, int unit)
451{
452 struct acpi_device *ad;
453 device_t child;
454
455 if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT)) == NULL)
456 return(NULL);
457 bzero(ad, sizeof(*ad));
458
459 resource_list_init(&ad->ad_rl);
460
461 child = device_add_child_ordered(bus, order, name, unit);
462 if (child != NULL)
463 device_set_ivars(child, ad);
464 return(child);
465}
466
467/*
468 * Print child device resource usage
469 */
470static int
471acpi_print_resources(struct resource_list *rl, const char *name, int type, const char *format)
472{
473 struct resource_list_entry *rle;
474 int printed, retval;
475
476 printed = 0;
477 retval = 0;
478
479 if (!SLIST_FIRST(rl))
480 return(0);
481
482 /* Yes, this is kinda cheating */
483 SLIST_FOREACH(rle, rl, link) {
484 if (rle->type == type) {
485 if (printed == 0)
486 retval += printf(" %s ", name);
487 else if (printed > 0)
488 retval += printf(",");
489 printed++;
490 retval += printf(format, rle->start);
491 if (rle->count > 1) {
492 retval += printf("-");
493 retval += printf(format, rle->start +
494 rle->count - 1);
495 }
496 }
497 }
498 return(retval);
499}
500
501static int
502acpi_print_child(device_t bus, device_t child)
503{
504 struct acpi_device *adev = device_get_ivars(child);
505 struct resource_list *rl = &adev->ad_rl;
506 int retval = 0;
507
508 retval += bus_print_child_header(bus, child);
509 retval += acpi_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx");
510 retval += acpi_print_resources(rl, "iomem", SYS_RES_MEMORY, "%#lx");
511 retval += acpi_print_resources(rl, "irq", SYS_RES_IRQ, "%ld");
512 retval += bus_print_child_footer(bus, child);
513
514 return(retval);
515}
516
517
518/*
519 * Handle per-device ivars
520 */
521static int
522acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
523{
524 struct acpi_device *ad;
525
526 if ((ad = device_get_ivars(child)) == NULL) {
527 printf("device has no ivars\n");
528 return(ENOENT);
529 }
530
531 switch(index) {
532 /* ACPI ivars */
533 case ACPI_IVAR_HANDLE:
534 *(ACPI_HANDLE *)result = ad->ad_handle;
535 break;
536 case ACPI_IVAR_MAGIC:
537 *(int *)result = ad->ad_magic;
538 break;
539 case ACPI_IVAR_PRIVATE:
540 *(void **)result = ad->ad_private;
541 break;
542
543 /* ISA compatibility */
544 case ISA_IVAR_VENDORID:
545 case ISA_IVAR_SERIAL:
546 case ISA_IVAR_COMPATID:
547 *(int *)result = -1;
548 break;
549
550 case ISA_IVAR_LOGICALID:
551 *(int *)result = acpi_isa_get_logicalid(child);
552 break;
553
554 default:
555 panic("bad ivar read request (%d)\n", index);
556 return(ENOENT);
557 }
558 return(0);
559}
560
561static int
562acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
563{
564 struct acpi_device *ad;
565
566 if ((ad = device_get_ivars(child)) == NULL) {
567 printf("device has no ivars\n");
568 return(ENOENT);
569 }
570
571 switch(index) {
572 /* ACPI ivars */
573 case ACPI_IVAR_HANDLE:
574 ad->ad_handle = (ACPI_HANDLE)value;
575 break;
576 case ACPI_IVAR_MAGIC:
577 ad->ad_magic = (int )value;
578 break;
579 case ACPI_IVAR_PRIVATE:
580 ad->ad_private = (void *)value;
581 break;
582
583 default:
584 panic("bad ivar write request (%d)\n", index);
585 return(ENOENT);
586 }
587 return(0);
588}
589
590/*
591 * Handle child resource allocation/removal
592 */
593static int
594acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
595{
596 struct acpi_device *ad = device_get_ivars(child);
597 struct resource_list *rl = &ad->ad_rl;
598
599 resource_list_add(rl, type, rid, start, start + count -1, count);
600
601 return(0);
602}
603
604static int
605acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp)
606{
607 struct acpi_device *ad = device_get_ivars(child);
608 struct resource_list *rl = &ad->ad_rl;
609 struct resource_list_entry *rle;
610
611 rle = resource_list_find(rl, type, rid);
612 if (!rle)
613 return(ENOENT);
614
615 if (startp)
616 *startp = rle->start;
617 if (countp)
618 *countp = rle->count;
619
620 return(0);
621}
622
623static struct resource *
624acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
625 u_long start, u_long end, u_long count, u_int flags)
626{
627 struct acpi_device *ad = device_get_ivars(child);
628 struct resource_list *rl = &ad->ad_rl;
629
630 return(resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags));
631}
632
633static int
634acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
635{
636 struct acpi_device *ad = device_get_ivars(child);
637 struct resource_list *rl = &ad->ad_rl;
638
639 return(resource_list_release(rl, bus, child, type, rid, r));
640}
641
642/*
643 * Handle ISA-like devices probing for a PnP ID to match.
644 */
645#define PNP_EISAID(s) \
646 ((((s[0] - '@') & 0x1f) << 2) \
647 | (((s[1] - '@') & 0x18) >> 3) \
648 | (((s[1] - '@') & 0x07) << 13) \
649 | (((s[2] - '@') & 0x1f) << 8) \
650 | (PNP_HEXTONUM(s[4]) << 16) \
651 | (PNP_HEXTONUM(s[3]) << 20) \
652 | (PNP_HEXTONUM(s[6]) << 24) \
653 | (PNP_HEXTONUM(s[5]) << 28))
654
655static u_int32_t
656acpi_isa_get_logicalid(device_t dev)
657{
658 ACPI_HANDLE h;
659 ACPI_DEVICE_INFO devinfo;
660 ACPI_STATUS error;
661 u_int32_t pnpid;
662
663 FUNCTION_TRACE(__func__);
664
665 pnpid = 0;
666 ACPI_LOCK;
667
668 /* fetch and validate the HID */
669 if ((h = acpi_get_handle(dev)) == NULL)
670 goto out;
671 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
672 goto out;
673 if (!(devinfo.Valid & ACPI_VALID_HID))
674 goto out;
675
676 pnpid = PNP_EISAID(devinfo.HardwareId);
677out:
678 ACPI_UNLOCK;
679 return_VALUE(pnpid);
680}
681
682static int
683acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids)
684{
685 int result;
686 u_int32_t pnpid;
687
688 FUNCTION_TRACE(__func__);
689
690 /*
691 * ISA-style drivers attached to ACPI may persist and
692 * probe manually if we return ENOENT. We never want
693 * that to happen, so don't ever return it.
694 */
695 result = ENXIO;
696
697 /* scan the supplied IDs for a match */
698 pnpid = acpi_isa_get_logicalid(child);
699 while (ids && ids->ip_id) {
700 if (pnpid == ids->ip_id) {
701 result = 0;
702 goto out;
703 }
704 ids++;
705 }
706 out:
707 return_VALUE(result);
708}
709
710/*
711 * Scan relevant portions of the ACPI namespace and attach child devices.
712 *
713 * Note that we only expect to find devices in the \_PR_, \_TZ_, \_SI_ and \_SB_ scopes,
714 * and \_PR_ and \_TZ_ become obsolete in the ACPI 2.0 spec.
715 */
716static void
717acpi_probe_children(device_t bus)
718{
719 ACPI_HANDLE parent;
720 static char *scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI", "\\_SB_", NULL};
721 int i;
722
723 FUNCTION_TRACE(__func__);
724 ACPI_ASSERTLOCK;
725
726 /*
727 * Create any static children by calling device identify methods.
728 */
729 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "device identify routines\n"));
730 bus_generic_probe(bus);
731
732 /*
733 * Scan the namespace and insert placeholders for all the devices that
734 * we find.
735 *
736 * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because
737 * we want to create nodes for all devices, not just those that are currently
738 * present. (This assumes that we don't want to create/remove devices as they
739 * appear, which might be smarter.)
740 */
741 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "namespace scan\n"));
742 for (i = 0; scopes[i] != NULL; i++)
743 if ((AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent)) == AE_OK)
744 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child, bus, NULL);
745
746 /*
747 * Scan all of the child devices we have created and let them probe/attach.
748 */
749 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "first bus_generic_attach\n"));
750 bus_generic_attach(bus);
751
752 /*
753 * Some of these children may have attached others as part of their attach
754 * process (eg. the root PCI bus driver), so rescan.
755 */
756 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "second bus_generic_attach\n"));
757 bus_generic_attach(bus);
758
759 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "done attaching children\n"));
760 return_VOID;
761}
762
763/*
764 * Evaluate a child device and determine whether we might attach a device to
765 * it.
766 */
767static ACPI_STATUS
768acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
769{
770 ACPI_OBJECT_TYPE type;
771 device_t child, bus = (device_t)context;
772
773 FUNCTION_TRACE(__func__);
774
775 /*
776 * Skip this device if we think we'll have trouble with it.
777 */
778 if (acpi_avoid(handle))
779 return_ACPI_STATUS(AE_OK);
780
781 if (AcpiGetType(handle, &type) == AE_OK) {
782 switch(type) {
783 case ACPI_TYPE_DEVICE:
784 case ACPI_TYPE_PROCESSOR:
785 case ACPI_TYPE_THERMAL:
786 case ACPI_TYPE_POWER:
787 if (acpi_disabled("children"))
788 break;
789 /*
790 * Create a placeholder device for this node. Sort the placeholder
791 * so that the probe/attach passes will run breadth-first.
792 */
793 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n", acpi_name(handle)));
794 child = BUS_ADD_CHILD(bus, level * 10, NULL, -1);
795 if (child == NULL)
796 break;
797 acpi_set_handle(child, handle);
798
799 /*
800 * Check that the device is present. If it's not present,
801 * leave it disabled (so that we have a device_t attached to
802 * the handle, but we don't probe it).
803 */
804 if ((type == ACPI_TYPE_DEVICE) && (!acpi_DeviceIsPresent(child))) {
805 device_disable(child);
806 break;
807 }
808
809 /*
810 * Get the device's resource settings and attach them.
811 * Note that if the device has _PRS but no _CRS, we need
812 * to decide when it's appropriate to try to configure the
813 * device. Ignore the return value here; it's OK for the
814 * device not to have any resources.
815 */
816 acpi_parse_resources(child, handle, &acpi_res_parse_set);
817
818 /* if we're debugging, probe/attach now rather than later */
819 DEBUG_EXEC(device_probe_and_attach(child));
820 break;
821 }
822 }
823 return_ACPI_STATUS(AE_OK);
824}
825
826static void
827acpi_shutdown_pre_sync(void *arg, int howto)
828{
829
830 ACPI_ASSERTLOCK;
831
832 /*
833 * Disable all ACPI events before soft off, otherwise the system
834 * will be turned on again on some laptops.
835 *
836 * XXX this should probably be restricted to masking some events just
837 * before powering down, since we may still need ACPI during the
838 * shutdown process.
839 */
840 acpi_Disable((struct acpi_softc *)arg);
841}
842
843static void
844acpi_shutdown_final(void *arg, int howto)
845{
846 ACPI_STATUS status;
847
848 ACPI_ASSERTLOCK;
849
850 if (howto & RB_POWEROFF) {
851 printf("Power system off using ACPI...\n");
852 if ((status = AcpiEnterSleepState(acpi_off_state)) != AE_OK) {
853 printf("ACPI power-off failed - %s\n", AcpiFormatException(status));
854 } else {
855 DELAY(1000000);
856 printf("ACPI power-off failed - timeout\n");
857 }
858 }
859}
860
861static void
862acpi_enable_fixed_events(struct acpi_softc *sc)
863{
864 static int first_time = 1;
865#define MSGFORMAT "%s button is handled as a fixed feature programming model.\n"
866
867 ACPI_ASSERTLOCK;
868
869 /* Enable and clear fixed events and install handlers. */
870 if ((AcpiGbl_FADT != NULL) && (AcpiGbl_FADT->PwrButton == 0)) {
871 AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED, 0);
872 AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
873 AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
874 acpi_eventhandler_power_button_for_sleep, sc);
875 if (first_time) {
876 device_printf(sc->acpi_dev, MSGFORMAT, "power");
877 }
878 }
879 if ((AcpiGbl_FADT != NULL) && (AcpiGbl_FADT->SleepButton == 0)) {
880 AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED, 0);
881 AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
882 AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
883 acpi_eventhandler_sleep_button_for_sleep, sc);
884 if (first_time) {
885 device_printf(sc->acpi_dev, MSGFORMAT, "sleep");
886 }
887 }
888
889 first_time = 0;
890}
891
892/*
893 * Returns true if the device is actually present and should
894 * be attached to. This requires the present, enabled, UI-visible
895 * and diagnostics-passed bits to be set.
896 */
897BOOLEAN
898acpi_DeviceIsPresent(device_t dev)
899{
900 ACPI_HANDLE h;
901 ACPI_DEVICE_INFO devinfo;
902 ACPI_STATUS error;
903
904 ACPI_ASSERTLOCK;
905
906 if ((h = acpi_get_handle(dev)) == NULL)
907 return(FALSE);
908 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
909 return(FALSE);
910 /* if no _STA method, must be present */
911 if (!(devinfo.Valid & ACPI_VALID_STA))
912 return(TRUE);
913 /* return true for 'present' and 'functioning' */
914 if ((devinfo.CurrentStatus & 0x9) == 0x9)
915 return(TRUE);
916 return(FALSE);
917}
918
919/*
920 * Match a HID string against a device
921 */
922BOOLEAN
923acpi_MatchHid(device_t dev, char *hid)
924{
925 ACPI_HANDLE h;
926 ACPI_DEVICE_INFO devinfo;
927 ACPI_STATUS error;
928 int cid;
929
930 ACPI_ASSERTLOCK;
931
932 if (hid == NULL)
933 return(FALSE);
934 if ((h = acpi_get_handle(dev)) == NULL)
935 return(FALSE);
936 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
937 return(FALSE);
938 if ((devinfo.Valid & ACPI_VALID_HID) && !strcmp(hid, devinfo.HardwareId))
939 return(TRUE);
940 if ((error = acpi_EvaluateInteger(h, "_CID", &cid)) != AE_OK)
941 return(FALSE);
942 if (cid == PNP_EISAID(hid))
943 return(TRUE);
944 return(FALSE);
945}
946
947/*
948 * Return the handle of a named object within our scope, ie. that of (parent)
949 * or one if its parents.
950 */
951ACPI_STATUS
952acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
953{
954 ACPI_HANDLE r;
955 ACPI_STATUS status;
956
957 ACPI_ASSERTLOCK;
958
959 /* walk back up the tree to the root */
960 for (;;) {
961 status = AcpiGetHandle(parent, path, &r);
962 if (status == AE_OK) {
963 *result = r;
964 return(AE_OK);
965 }
966 if (status != AE_NOT_FOUND)
967 return(AE_OK);
968 if (AcpiGetParent(parent, &r) != AE_OK)
969 return(AE_NOT_FOUND);
970 parent = r;
971 }
972}
973
974/*
975 * Allocate a buffer with a preset data size.
976 */
977ACPI_BUFFER *
978acpi_AllocBuffer(int size)
979{
980 ACPI_BUFFER *buf;
981
982 if ((buf = malloc(size + sizeof(*buf), M_ACPIDEV, M_NOWAIT)) == NULL)
983 return(NULL);
984 buf->Length = size;
985 buf->Pointer = (void *)(buf + 1);
986 return(buf);
987}
988
989/*
990 * Perform the tedious double-get procedure required for fetching something into
991 * an ACPI_BUFFER that has not been initialised.
992 */
993ACPI_STATUS
994acpi_GetIntoBuffer(ACPI_HANDLE handle, ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUFFER *), ACPI_BUFFER *buf)
995{
996 ACPI_STATUS status;
997
998 ACPI_ASSERTLOCK;
999
1000 buf->Length = 0;
1001 buf->Pointer = NULL;
1002
1003 if ((status = func(handle, buf)) != AE_BUFFER_OVERFLOW)
1004 return(status);
1005 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
1006 return(AE_NO_MEMORY);
1007 return(func(handle, buf));
1008}
1009
1010/*
1011 * Perform the tedious double-get procedure required for fetching a table into
1012 * an ACPI_BUFFER that has not been initialised.
1013 */
1014ACPI_STATUS
1015acpi_GetTableIntoBuffer(ACPI_TABLE_TYPE table, UINT32 instance, ACPI_BUFFER *buf)
1016{
1017 ACPI_STATUS status;
1018
1019 ACPI_ASSERTLOCK;
1020
1021 buf->Length = 0;
1022 buf->Pointer = NULL;
1023
1024 if ((status = AcpiGetTable(table, instance, buf)) != AE_BUFFER_OVERFLOW)
1025 return(status);
1026 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
1027 return(AE_NO_MEMORY);
1028 return(AcpiGetTable(table, instance, buf));
1029}
1030
1031/*
1032 * Perform the tedious double-evaluate procedure for evaluating something into
1033 * an ACPI_BUFFER that has not been initialised. Note that this evaluates
1034 * twice, so avoid applying this to things that may have side-effects.
1035 *
1036 * This is like AcpiEvaluateObject with automatic buffer allocation.
1037 */
1038ACPI_STATUS
1039acpi_EvaluateIntoBuffer(ACPI_HANDLE object, ACPI_STRING pathname, ACPI_OBJECT_LIST *params,
1040 ACPI_BUFFER *buf)
1041{
1042 ACPI_STATUS status;
1043
1044 ACPI_ASSERTLOCK;
1045
1046 buf->Length = 0;
1047 buf->Pointer = NULL;
1048
1049 if ((status = AcpiEvaluateObject(object, pathname, params, buf)) != AE_BUFFER_OVERFLOW)
1050 return(status);
1051 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
1052 return(AE_NO_MEMORY);
1053 return(AcpiEvaluateObject(object, pathname, params, buf));
1054}
1055
1056/*
1057 * Evaluate a path that should return an integer.
1058 */
1059ACPI_STATUS
1060acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number)
1061{
1062 ACPI_STATUS error;
1063 ACPI_BUFFER buf;
1064 ACPI_OBJECT param, *p;
1065 int i;
1066
1067 ACPI_ASSERTLOCK;
1068
1069 if (handle == NULL)
1070 handle = ACPI_ROOT_OBJECT;
1071
1072 /*
1073 * Assume that what we've been pointed at is an Integer object, or
1074 * a method that will return an Integer.
1075 */
1076 buf.Pointer = &param;
1077 buf.Length = sizeof(param);
1078 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) {
1079 if (param.Type == ACPI_TYPE_INTEGER) {
1080 *number = param.Integer.Value;
1081 } else {
1082 error = AE_TYPE;
1083 }
1084 }
1085
1086 /*
1087 * In some applications, a method that's expected to return an Integer
1088 * may instead return a Buffer (probably to simplify some internal
1089 * arithmetic). We'll try to fetch whatever it is, and if it's a Buffer,
1090 * convert it into an Integer as best we can.
1091 *
1092 * This is a hack.
1093 */
1094 if (error == AE_BUFFER_OVERFLOW) {
1095 if ((buf.Pointer = AcpiOsCallocate(buf.Length)) == NULL) {
1096 error = AE_NO_MEMORY;
1097 } else {
1098 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) {
1099 p = (ACPI_OBJECT *)buf.Pointer;
1100 if (p->Type != ACPI_TYPE_BUFFER) {
1101 error = AE_TYPE;
1102 } else {
1103 if (p->Buffer.Length > sizeof(int)) {
1104 error = AE_BAD_DATA;
1105 } else {
1106 *number = 0;
1107 for (i = 0; i < p->Buffer.Length; i++)
1108 *number += (*(p->Buffer.Pointer + i) << (i * 8));
1109 }
1110 }
1111 }
1112 }
1113 AcpiOsFree(buf.Pointer);
1114 }
1115 return(error);
1116}
1117
1118/*
1119 * Iterate over the elements of an a package object, calling the supplied
1120 * function for each element.
1121 *
1122 * XXX possible enhancement might be to abort traversal on error.
1123 */
1124ACPI_STATUS
1125acpi_ForeachPackageObject(ACPI_OBJECT *pkg, void (* func)(ACPI_OBJECT *comp, void *arg), void *arg)
1126{
1127 ACPI_OBJECT *comp;
1128 int i;
1129
1130 if ((pkg == NULL) || (pkg->Type != ACPI_TYPE_PACKAGE))
1131 return(AE_BAD_PARAMETER);
1132
1133 /* iterate over components */
1134 for (i = 0, comp = pkg->Package.Elements; i < pkg->Package.Count; i++, comp++)
1135 func(comp, arg);
1136
1137 return(AE_OK);
1138}
1139
1140/*
1141 * Find the (index)th resource object in a set.
1142 */
1143ACPI_STATUS
1144acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp)
1145{
1146 ACPI_RESOURCE *rp;
1147 int i;
1148
1149 rp = (ACPI_RESOURCE *)buf->Pointer;
1150 i = index;
1151 while (i-- > 0) {
1152 /* range check */
1153 if (rp > (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
1154 return(AE_BAD_PARAMETER);
1155 /* check for terminator */
1156 if ((rp->Id == ACPI_RSTYPE_END_TAG) ||
1157 (rp->Length == 0))
1158 return(AE_NOT_FOUND);
1159 rp = ACPI_RESOURCE_NEXT(rp);
1160 }
1161 if (resp != NULL)
1162 *resp = rp;
1163 return(AE_OK);
1164}
1165
1166/*
1167 * Append an ACPI_RESOURCE to an ACPI_BUFFER.
1168 *
1169 * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
1170 * provided to contain it. If the ACPI_BUFFER is empty, allocate a sensible
1171 * backing block. If the ACPI_RESOURCE is NULL, return an empty set of
1172 * resources.
1173 */
1174#define ACPI_INITIAL_RESOURCE_BUFFER_SIZE 512
1175
1176ACPI_STATUS
1177acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
1178{
1179 ACPI_RESOURCE *rp;
1180 void *newp;
1181
1182 /*
1183 * Initialise the buffer if necessary.
1184 */
1185 if (buf->Pointer == NULL) {
1186 buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
1187 if ((buf->Pointer = AcpiOsAllocate(buf->Length)) == NULL)
1188 return(AE_NO_MEMORY);
1189 rp = (ACPI_RESOURCE *)buf->Pointer;
1190 rp->Id = ACPI_RSTYPE_END_TAG;
1191 rp->Length = 0;
1192 }
1193 if (res == NULL)
1194 return(AE_OK);
1195
1196 /*
1197 * Scan the current buffer looking for the terminator.
1198 * This will either find the terminator or hit the end
1199 * of the buffer and return an error.
1200 */
1201 rp = (ACPI_RESOURCE *)buf->Pointer;
1202 for (;;) {
1203 /* range check, don't go outside the buffer */
1204 if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
1205 return(AE_BAD_PARAMETER);
1206 if ((rp->Id == ACPI_RSTYPE_END_TAG) ||
1207 (rp->Length == 0)) {
1208 break;
1209 }
1210 rp = ACPI_RESOURCE_NEXT(rp);
1211 }
1212
1213 /*
1214 * Check the size of the buffer and expand if required.
1215 *
1216 * Required size is:
1217 * size of existing resources before terminator +
1218 * size of new resource and header +
1219 * size of terminator.
1220 *
1221 * Note that this loop should really only run once, unless
1222 * for some reason we are stuffing a *really* huge resource.
1223 */
1224 while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +
1225 res->Length + ACPI_RESOURCE_LENGTH_NO_DATA +
1226 ACPI_RESOURCE_LENGTH) >= buf->Length) {
1227 if ((newp = AcpiOsAllocate(buf->Length * 2)) == NULL)
1228 return(AE_NO_MEMORY);
1229 bcopy(buf->Pointer, newp, buf->Length);
1230 rp = (ACPI_RESOURCE *)((u_int8_t *)newp +
1231 ((u_int8_t *)rp - (u_int8_t *)buf->Pointer));
1232 AcpiOsFree(buf->Pointer);
1233 buf->Pointer = newp;
1234 buf->Length += buf->Length;
1235 }
1236
1237 /*
1238 * Insert the new resource.
1239 */
1240 bcopy(res, rp, res->Length + ACPI_RESOURCE_LENGTH_NO_DATA);
1241
1242 /*
1243 * And add the terminator.
1244 */
1245 rp = ACPI_RESOURCE_NEXT(rp);
1246 rp->Id = ACPI_RSTYPE_END_TAG;
1247 rp->Length = 0;
1248
1249 return(AE_OK);
1250}
1251
1252
1253/*
1254 * Set the system sleep state
1255 *
1256 * Currently we only support S1 and S5
1257 */
1258ACPI_STATUS
1259acpi_SetSleepState(struct acpi_softc *sc, int state)
1260{
1261 ACPI_STATUS status = AE_OK;
1262 UINT16 Count;
1263 UINT8 TypeA;
1264 UINT8 TypeB;
1265
1266 FUNCTION_TRACE_U32(__func__, state);
1267 ACPI_ASSERTLOCK;
1268
1269 switch (state) {
1270 case ACPI_STATE_S0: /* XXX only for testing */
1271 status = AcpiEnterSleepState((UINT8)state);
1272 if (status != AE_OK) {
1273 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status));
1274 }
1275 break;
1276
1277 case ACPI_STATE_S1:
1278 case ACPI_STATE_S2:
1279 case ACPI_STATE_S3:
1280 case ACPI_STATE_S4:
1281 status = AcpiHwObtainSleepTypeRegisterData((UINT8)state, &TypeA, &TypeB);
1282 if (status != AE_OK) {
1283 device_printf(sc->acpi_dev, "AcpiHwObtainSleepTypeRegisterData failed - %s\n", AcpiFormatException(status));
1284 break;
1285 }
1286
1287 /*
1288 * Inform all devices that we are going to sleep.
1289 */
1290 if (DEVICE_SUSPEND(root_bus) != 0) {
1291 /*
1292 * Re-wake the system.
1293 *
1294 * XXX note that a better two-pass approach with a 'veto' pass
1295 * followed by a "real thing" pass would be better, but the
1296 * current bus interface does not provide for this.
1297 */
1298 DEVICE_RESUME(root_bus);
1299 return_ACPI_STATUS(AE_ERROR);
1300 }
1301 sc->acpi_sstate = state;
1302
1303 if (state != ACPI_STATE_S1) {
1304 acpi_sleep_machdep(sc, state);
1305
1306 /* AcpiEnterSleepState() maybe incompleted, unlock here. */
1307 AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
1308
1309 /* Re-enable ACPI hardware on wakeup from sleep state 4. */
1310 if (state >= ACPI_STATE_S4) {
1311 acpi_Disable(sc);
1312 acpi_Enable(sc);
1313 }
1314 } else {
1315 status = AcpiEnterSleepState((UINT8)state);
1316 if (status != AE_OK) {
1317 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status));
1318 break;
1319 }
1320 /* wait for the WAK_STS bit */
1321 Count = 0;
1322 while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
1323 AcpiOsSleep(0, 1);
1324 /*
1325 * Some BIOSes don't set WAK_STS at all,
1326 * give up waiting for wakeup if we time out.
1327 */
1328 if (Count > 1000) {
1329 break; /* giving up */
1330 }
1331 Count++;
1332 }
1333 }
1334 AcpiLeaveSleepState((UINT8)state);
1335 DEVICE_RESUME(root_bus);
1336 sc->acpi_sstate = ACPI_STATE_S0;
1337 acpi_enable_fixed_events(sc);
1338 break;
1339
1340 case ACPI_STATE_S5:
1341 /*
1342 * Shut down cleanly and power off. This will call us back through the
1343 * shutdown handlers.
1344 */
1345 shutdown_nice(RB_POWEROFF);
1346 break;
1347
1348 default:
1349 status = AE_BAD_PARAMETER;
1350 break;
1351 }
1352 return_ACPI_STATUS(status);
1353}
1354
1355/*
1356 * Enable/Disable ACPI
1357 */
1358ACPI_STATUS
1359acpi_Enable(struct acpi_softc *sc)
1360{
1361 ACPI_STATUS status;
1362 u_int32_t flags;
1363
1364 FUNCTION_TRACE(__func__);
1365 ACPI_ASSERTLOCK;
1366
1367 flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
1368 ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
1369 if (!sc->acpi_enabled) {
1370 status = AcpiEnableSubsystem(flags);
1371 } else {
1372 status = AE_OK;
1373 }
1374 if (status == AE_OK)
1375 sc->acpi_enabled = 1;
1376 return_ACPI_STATUS(status);
1377}
1378
1379ACPI_STATUS
1380acpi_Disable(struct acpi_softc *sc)
1381{
1382 ACPI_STATUS status;
1383
1384 FUNCTION_TRACE(__func__);
1385 ACPI_ASSERTLOCK;
1386
1387 if (sc->acpi_enabled) {
1388 status = AcpiDisable();
1389 } else {
1390 status = AE_OK;
1391 }
1392 if (status == AE_OK)
1393 sc->acpi_enabled = 0;
1394 return_ACPI_STATUS(status);
1395}
1396
1397/*
1398 * ACPI Event Handlers
1399 */
1400
1401/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
1402
1403static void
1404acpi_system_eventhandler_sleep(void *arg, int state)
1405{
1406 FUNCTION_TRACE_U32(__func__, state);
1407
1408 ACPI_LOCK;
1409 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
1410 acpi_SetSleepState((struct acpi_softc *)arg, state);
1411 ACPI_UNLOCK;
1412 return_VOID;
1413}
1414
1415static void
1416acpi_system_eventhandler_wakeup(void *arg, int state)
1417{
1418 FUNCTION_TRACE_U32(__func__, state);
1419
1420 /* Well, what to do? :-) */
1421
1422 ACPI_LOCK;
1423 ACPI_UNLOCK;
1424
1425 return_VOID;
1426}
1427
1428/*
1429 * ACPICA Event Handlers (FixedEvent, also called from button notify handler)
1430 */
1431UINT32
1432acpi_eventhandler_power_button_for_sleep(void *context)
1433{
1434 struct acpi_softc *sc = (struct acpi_softc *)context;
1435
1436 FUNCTION_TRACE(__func__);
1437
1438 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
1439
1440 return_VALUE(INTERRUPT_HANDLED);
1441}
1442
1443UINT32
1444acpi_eventhandler_power_button_for_wakeup(void *context)
1445{
1446 struct acpi_softc *sc = (struct acpi_softc *)context;
1447
1448 FUNCTION_TRACE(__func__);
1449
1450 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx);
1451
1452 return_VALUE(INTERRUPT_HANDLED);
1453}
1454
1455UINT32
1456acpi_eventhandler_sleep_button_for_sleep(void *context)
1457{
1458 struct acpi_softc *sc = (struct acpi_softc *)context;
1459
1460 FUNCTION_TRACE(__func__);
1461
1462 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
1463
1464 return_VALUE(INTERRUPT_HANDLED);
1465}
1466
1467UINT32
1468acpi_eventhandler_sleep_button_for_wakeup(void *context)
1469{
1470 struct acpi_softc *sc = (struct acpi_softc *)context;
1471
1472 FUNCTION_TRACE(__func__);
1473
1474 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx);
1475
1476 return_VALUE(INTERRUPT_HANDLED);
1477}
1478
1479/*
1480 * XXX This is kinda ugly, and should not be here.
1481 */
1482struct acpi_staticbuf {
1483 ACPI_BUFFER buffer;
1484 char data[512];
1485};
1486
1487char *
1488acpi_name(ACPI_HANDLE handle)
1489{
1490 static struct acpi_staticbuf buf;
1491
1492 ACPI_ASSERTLOCK;
1493
1494 buf.buffer.Length = 512;
1495 buf.buffer.Pointer = &buf.data[0];
1496
1497 if (AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer) == AE_OK)
1498 return(buf.buffer.Pointer);
1499 return("(unknown path)");
1500}
1501
1502/*
1503 * Debugging/bug-avoidance. Avoid trying to fetch info on various
1504 * parts of the namespace.
1505 */
1506int
1507acpi_avoid(ACPI_HANDLE handle)
1508{
1509 char *cp, *np;
1510 int len;
1511
1512 np = acpi_name(handle);
1513 if (*np == '\\')
1514 np++;
1515 if ((cp = getenv("debug.acpi.avoid")) == NULL)
1516 return(0);
1517
1518 /* scan the avoid list checking for a match */
1519 for (;;) {
1520 while ((*cp != 0) && isspace(*cp))
1521 cp++;
1522 if (*cp == 0)
1523 break;
1524 len = 0;
1525 while ((cp[len] != 0) && !isspace(cp[len]))
1526 len++;
1527 if (!strncmp(cp, np, len))
1528 return(1);
1529 cp += len;
1530 }
1531 return(0);
1532}
1533
1534/*
1535 * Debugging/bug-avoidance. Disable ACPI subsystem components.
1536 */
1537int
1538acpi_disabled(char *subsys)
1539{
1540 char *cp;
1541 int len;
1542
1543 if ((cp = getenv("debug.acpi.disable")) == NULL)
1544 return(0);
1545 if (!strcmp(cp, "all"))
1546 return(1);
1547
1548 /* scan the disable list checking for a match */
1549 for (;;) {
1550 while ((*cp != 0) && isspace(*cp))
1551 cp++;
1552 if (*cp == 0)
1553 break;
1554 len = 0;
1555 while ((cp[len] != 0) && !isspace(cp[len]))
1556 len++;
1557 if (!strncmp(cp, subsys, len))
1558 return(1);
1559 cp += len;
1560 }
1561 return(0);
1562}
1563
1564/*
1565 * Control interface.
1566 *
1567 * We multiplex ioctls for all participating ACPI devices here. Individual
1568 * drivers wanting to be accessible via /dev/acpi should use the register/deregister
1569 * interface to make their handlers visible.
1570 */
1571struct acpi_ioctl_hook
1572{
1573 TAILQ_ENTRY(acpi_ioctl_hook) link;
1574 u_long cmd;
1575 int (* fn)(u_long cmd, caddr_t addr, void *arg);
1576 void *arg;
1577};
1578
1579static TAILQ_HEAD(,acpi_ioctl_hook) acpi_ioctl_hooks;
1580static int acpi_ioctl_hooks_initted;
1581
1582/*
1583 * Register an ioctl handler.
1584 */
1585int
1586acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg)
1587{
1588 struct acpi_ioctl_hook *hp;
1589
1590 if ((hp = malloc(sizeof(*hp), M_ACPIDEV, M_NOWAIT)) == NULL)
1591 return(ENOMEM);
1592 hp->cmd = cmd;
1593 hp->fn = fn;
1594 hp->arg = arg;
1595 if (acpi_ioctl_hooks_initted == 0) {
1596 TAILQ_INIT(&acpi_ioctl_hooks);
1597 acpi_ioctl_hooks_initted = 1;
1598 }
1599 TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link);
1600 return(0);
1601}
1602
1603/*
1604 * Deregister an ioctl handler.
1605 */
1606void
1607acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg))
1608{
1609 struct acpi_ioctl_hook *hp;
1610
1611 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link)
1612 if ((hp->cmd == cmd) && (hp->fn == fn))
1613 break;
1614
1615 if (hp != NULL) {
1616 TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link);
1617 free(hp, M_ACPIDEV);
1618 }
1619}
1620
1621static int
1622acpiopen(dev_t dev, int flag, int fmt, struct thread *td)
1623{
1624 return(0);
1625}
1626
1627static int
1628acpiclose(dev_t dev, int flag, int fmt, struct thread *td)
1629{
1630 return(0);
1631}
1632
1633static int
1634acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
1635{
1636 struct acpi_softc *sc;
1637 struct acpi_ioctl_hook *hp;
1638 int error, xerror, state;
1639
1640 ACPI_LOCK;
1641
1642 error = state = 0;
1643 sc = dev->si_drv1;
1644
1645 /*
1646 * Scan the list of registered ioctls, looking for handlers.
1647 */
1648 if (acpi_ioctl_hooks_initted) {
1649 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) {
1650 if (hp->cmd == cmd) {
1651 xerror = hp->fn(cmd, addr, hp->arg);
1652 if (xerror != 0)
1653 error = xerror;
1654 goto out;
1655 }
1656 }
1657 }
1658
1659 /*
1660 * Core system ioctls.
1661 */
1662 switch (cmd) {
1663 case ACPIIO_ENABLE:
1664 if (ACPI_FAILURE(acpi_Enable(sc)))
1665 error = ENXIO;
1666 break;
1667
1668 case ACPIIO_DISABLE:
1669 if (ACPI_FAILURE(acpi_Disable(sc)))
1670 error = ENXIO;
1671 break;
1672
1673 case ACPIIO_SETSLPSTATE:
1674 if (!sc->acpi_enabled) {
1675 error = ENXIO;
1676 break;
1677 }
1678 state = *(int *)addr;
1679 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX) {
1680 acpi_SetSleepState(sc, state);
1681 } else {
1682 error = EINVAL;
1683 }
1684 break;
1685
1686 default:
1687 if (error == 0)
1688 error = EINVAL;
1689 break;
1690 }
1691
1692out:
1693 ACPI_UNLOCK;
1694 return(error);
1695}
1696
1697static int
1698acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
1699{
1700 char sleep_state[10];
1701 int error;
1702 u_int new_state, old_state;
1703
1704 old_state = *(u_int *)oidp->oid_arg1;
1705 if (old_state > ACPI_S_STATES_MAX) {
1706 strcpy(sleep_state, "unknown");
1707 } else {
1708 strncpy(sleep_state, sleep_state_names[old_state],
1709 sizeof(sleep_state_names[old_state]));
1710 }
1711 error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
1712 if (error == 0 && req->newptr != NULL) {
1713 for (new_state = ACPI_STATE_S0; new_state <= ACPI_S_STATES_MAX; new_state++) {
1714 if (strncmp(sleep_state, sleep_state_names[new_state],
1715 sizeof(sleep_state)) == 0)
1716 break;
1717 }
1718 if ((new_state != old_state) && (new_state <= ACPI_S_STATES_MAX)) {
1719 *(u_int *)oidp->oid_arg1 = new_state;
1720 } else {
1721 error = EINVAL;
1722 }
1723 }
1724 return(error);
1725}
1726
1727#ifdef ACPI_DEBUG
1728/*
1729 * Support for parsing debug options from the kernel environment.
1730 *
1731 * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers
1732 * by specifying the names of the bits in the debug.acpi.layer and
1733 * debug.acpi.level environment variables. Bits may be unset by
1734 * prefixing the bit name with !.
1735 */
1736struct debugtag
1737{
1738 char *name;
1739 UINT32 value;
1740};
1741
1742static struct debugtag dbg_layer[] = {
1743 {"ACPI_UTILITIES", ACPI_UTILITIES},
1744 {"ACPI_HARDWARE", ACPI_HARDWARE},
1745 {"ACPI_EVENTS", ACPI_EVENTS},
1746 {"ACPI_TABLES", ACPI_TABLES},
1747 {"ACPI_NAMESPACE", ACPI_NAMESPACE},
1748 {"ACPI_PARSER", ACPI_PARSER},
1749 {"ACPI_DISPATCHER", ACPI_DISPATCHER},
1750 {"ACPI_EXECUTER", ACPI_EXECUTER},
1751 {"ACPI_RESOURCES", ACPI_RESOURCES},
1752 {"ACPI_DEBUGGER", ACPI_DEBUGGER},
1753 {"ACPI_OS_SERVICES", ACPI_OS_SERVICES},
1754
1755 {"ACPI_BUS", ACPI_BUS},
1756 {"ACPI_SYSTEM", ACPI_SYSTEM},
1757 {"ACPI_POWER", ACPI_POWER},
1758 {"ACPI_EC", ACPI_EC},
1759 {"ACPI_AC_ADAPTER", ACPI_AC_ADAPTER},
1760 {"ACPI_BATTERY", ACPI_BATTERY},
1761 {"ACPI_BUTTON", ACPI_BUTTON},
1762 {"ACPI_PROCESSOR", ACPI_PROCESSOR},
1763 {"ACPI_THERMAL", ACPI_THERMAL},
1764 {"ACPI_FAN", ACPI_FAN},
1765
1766 {"ACPI_ALL_COMPONENTS", ACPI_ALL_COMPONENTS},
1767 {NULL, 0}
1768};
1769
1770static struct debugtag dbg_level[] = {
1771 {"ACPI_LV_OK", ACPI_LV_OK},
1772 {"ACPI_LV_INFO", ACPI_LV_INFO},
1773 {"ACPI_LV_WARN", ACPI_LV_WARN},
1774 {"ACPI_LV_ERROR", ACPI_LV_ERROR},
1775 {"ACPI_LV_FATAL", ACPI_LV_FATAL},
1776 {"ACPI_LV_DEBUG_OBJECT", ACPI_LV_DEBUG_OBJECT},
1777 {"ACPI_LV_ALL_EXCEPTIONS", ACPI_LV_ALL_EXCEPTIONS},
1778 {"ACPI_LV_THREADS", ACPI_LV_THREADS},
1779 {"ACPI_LV_PARSE", ACPI_LV_PARSE},
1780 {"ACPI_LV_DISPATCH", ACPI_LV_DISPATCH},
1781 {"ACPI_LV_LOAD", ACPI_LV_LOAD},
1782 {"ACPI_LV_EXEC", ACPI_LV_EXEC},
1783 {"ACPI_LV_NAMES", ACPI_LV_NAMES},
1784 {"ACPI_LV_OPREGION", ACPI_LV_OPREGION},
1785 {"ACPI_LV_BFIELD", ACPI_LV_BFIELD},
1786 {"ACPI_LV_TABLES", ACPI_LV_TABLES},
1787 {"ACPI_LV_FUNCTIONS", ACPI_LV_FUNCTIONS},
1788 {"ACPI_LV_VALUES", ACPI_LV_VALUES},
1789 {"ACPI_LV_OBJECTS", ACPI_LV_OBJECTS},
1790 {"ACPI_LV_ALLOCATIONS", ACPI_LV_ALLOCATIONS},
1791 {"ACPI_LV_RESOURCES", ACPI_LV_RESOURCES},
1792 {"ACPI_LV_IO", ACPI_LV_IO},
1793 {"ACPI_LV_INTERRUPTS", ACPI_LV_INTERRUPTS},
1794 {"ACPI_LV_USER_REQUESTS", ACPI_LV_USER_REQUESTS},
1795 {"ACPI_LV_PACKAGE", ACPI_LV_PACKAGE},
1796 {"ACPI_LV_MUTEX", ACPI_LV_MUTEX},
1797 {"ACPI_LV_INIT", ACPI_LV_INIT},
1798 {"ACPI_LV_ALL", ACPI_LV_ALL},
1799 {"ACPI_DB_AML_DISASSEMBLE", ACPI_DB_AML_DISASSEMBLE},
1800 {"ACPI_DB_VERBOSE_INFO", ACPI_DB_VERBOSE_INFO},
1801 {"ACPI_DB_FULL_TABLES", ACPI_DB_FULL_TABLES},
1802 {"ACPI_DB_EVENTS", ACPI_DB_EVENTS},
1803 {"ACPI_DB_VERBOSE", ACPI_DB_VERBOSE},
1804 {NULL, 0}
1805};
1806
1807static void
1808acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag)
1809{
1810 char *ep;
1811 int i, l;
1812 int set;
1813
1814 while (*cp) {
1815 if (isspace(*cp)) {
1816 cp++;
1817 continue;
1818 }
1819 ep = cp;
1820 while (*ep && !isspace(*ep))
1821 ep++;
1822 if (*cp == '!') {
1823 set = 0;
1824 cp++;
1825 if (cp == ep)
1826 continue;
1827 } else {
1828 set = 1;
1829 }
1830 l = ep - cp;
1831 for (i = 0; tag[i].name != NULL; i++) {
1832 if (!strncmp(cp, tag[i].name, l)) {
1833 if (set) {
1834 *flag |= tag[i].value;
1835 } else {
1836 *flag &= ~tag[i].value;
1837 }
1838 printf("ACPI_DEBUG: set '%s'\n", tag[i].name);
1839 }
1840 }
1841 cp = ep;
1842 }
1843}
1844
1845static void
1846acpi_set_debugging(void *junk)
1847{
1848 char *cp;
1849
1850 AcpiDbgLayer = 0;
1851 AcpiDbgLevel = 0;
1852 if ((cp = getenv("debug.acpi.layer")) != NULL)
1853 acpi_parse_debug(cp, &dbg_layer[0], &AcpiDbgLayer);
1854 if ((cp = getenv("debug.acpi.level")) != NULL)
1855 acpi_parse_debug(cp, &dbg_level[0], &AcpiDbgLevel);
1856
1857 printf("ACPI debug layer 0x%x debug level 0x%x\n", AcpiDbgLayer, AcpiDbgLevel);
1858}
1859SYSINIT(acpi_debugging, SI_SUB_TUNABLES, SI_ORDER_ANY, acpi_set_debugging, NULL);
1860#endif