| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: wmi_acpi.c,v 1.15 2010/03/05 14:00:17 jruoho Exp $ */ | | 1 | /* $NetBSD: wmi_acpi.c,v 1.16 2010/03/08 10:53:03 jruoho Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2009, 2010 Jukka Ruohonen <jruohonen@iki.fi> | | 4 | * Copyright (c) 2009, 2010 Jukka Ruohonen <jruohonen@iki.fi> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * | | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
| @@ -17,27 +17,27 @@ | | | @@ -17,27 +17,27 @@ |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 | * SUCH DAMAGE. | | 27 | * SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: wmi_acpi.c,v 1.15 2010/03/05 14:00:17 jruoho Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: wmi_acpi.c,v 1.16 2010/03/08 10:53:03 jruoho Exp $"); |
31 | | | 31 | |
32 | #include <sys/param.h> | | 32 | #include <sys/param.h> |
33 | #include <sys/device.h> | | 33 | #include <sys/device.h> |
34 | #include <sys/endian.h> | | 34 | #include <sys/endian.h> |
35 | #include <sys/kmem.h> | | 35 | #include <sys/kmem.h> |
36 | #include <sys/systm.h> | | 36 | #include <sys/systm.h> |
37 | | | 37 | |
38 | #include <dev/acpi/acpireg.h> | | 38 | #include <dev/acpi/acpireg.h> |
39 | #include <dev/acpi/acpivar.h> | | 39 | #include <dev/acpi/acpivar.h> |
40 | #include <dev/acpi/wmi_acpivar.h> | | 40 | #include <dev/acpi/wmi_acpivar.h> |
41 | | | 41 | |
42 | #define _COMPONENT ACPI_RESOURCE_COMPONENT | | 42 | #define _COMPONENT ACPI_RESOURCE_COMPONENT |
43 | ACPI_MODULE_NAME ("wmi_acpi") | | 43 | ACPI_MODULE_NAME ("wmi_acpi") |
| @@ -107,96 +107,115 @@ struct acpi_wmi_softc { | | | @@ -107,96 +107,115 @@ struct acpi_wmi_softc { |
107 | | | 107 | |
108 | #define HEXCHAR(x) (((x) >= '0' && (x) <= '9') || \ | | 108 | #define HEXCHAR(x) (((x) >= '0' && (x) <= '9') || \ |
109 | ((x) >= 'a' && (x) <= 'f') || \ | | 109 | ((x) >= 'a' && (x) <= 'f') || \ |
110 | ((x) >= 'A' && (x) <= 'F')) | | 110 | ((x) >= 'A' && (x) <= 'F')) |
111 | | | 111 | |
112 | #define GUIDCMP(a, b) \ | | 112 | #define GUIDCMP(a, b) \ |
113 | ((a)->data1 == (b)->data1 && \ | | 113 | ((a)->data1 == (b)->data1 && \ |
114 | (a)->data2 == (b)->data2 && \ | | 114 | (a)->data2 == (b)->data2 && \ |
115 | (a)->data3 == (b)->data3 && \ | | 115 | (a)->data3 == (b)->data3 && \ |
116 | UGET64((a)->data4) == UGET64((b)->data4)) | | 116 | UGET64((a)->data4) == UGET64((b)->data4)) |
117 | | | 117 | |
118 | static int acpi_wmi_match(device_t, cfdata_t, void *); | | 118 | static int acpi_wmi_match(device_t, cfdata_t, void *); |
119 | static void acpi_wmi_attach(device_t, device_t, void *); | | 119 | static void acpi_wmi_attach(device_t, device_t, void *); |
| | | 120 | static int acpi_wmi_detach(device_t, int); |
120 | static int acpi_wmi_print(void *, const char *); | | 121 | static int acpi_wmi_print(void *, const char *); |
121 | static bool acpi_wmi_init(struct acpi_wmi_softc *); | | 122 | static bool acpi_wmi_init(struct acpi_wmi_softc *); |
122 | static bool acpi_wmi_add(struct acpi_wmi_softc *, ACPI_OBJECT *); | | 123 | static bool acpi_wmi_add(struct acpi_wmi_softc *, ACPI_OBJECT *); |
123 | static void acpi_wmi_del(struct acpi_wmi_softc *); | | 124 | static void acpi_wmi_del(struct acpi_wmi_softc *); |
124 | | | 125 | |
125 | #ifdef ACPIVERBOSE | | 126 | #ifdef ACPIVERBOSE |
126 | static void acpi_wmi_dump(struct acpi_wmi_softc *); | | 127 | static void acpi_wmi_dump(struct acpi_wmi_softc *); |
127 | #endif | | 128 | #endif |
128 | | | 129 | |
129 | static ACPI_STATUS acpi_wmi_guid_get(struct acpi_wmi_softc *, | | 130 | static ACPI_STATUS acpi_wmi_guid_get(struct acpi_wmi_softc *, |
130 | const char *, struct wmi_t **); | | 131 | const char *, struct wmi_t **); |
131 | static void acpi_wmi_event_add(struct acpi_wmi_softc *); | | 132 | static ACPI_STATUS acpi_wmi_event_add(struct acpi_wmi_softc *); |
132 | static void acpi_wmi_event_del(struct acpi_wmi_softc *); | | 133 | static ACPI_STATUS acpi_wmi_event_del(struct acpi_wmi_softc *); |
133 | static void acpi_wmi_event_handler(ACPI_HANDLE, uint32_t, void *); | | 134 | static void acpi_wmi_event_handler(ACPI_HANDLE, uint32_t, void *); |
134 | static bool acpi_wmi_suspend(device_t, const pmf_qual_t *); | | 135 | static bool acpi_wmi_suspend(device_t, const pmf_qual_t *); |
135 | static bool acpi_wmi_resume(device_t, const pmf_qual_t *); | | 136 | static bool acpi_wmi_resume(device_t, const pmf_qual_t *); |
136 | static ACPI_STATUS acpi_wmi_enable(ACPI_HANDLE, const char *, bool, bool); | | 137 | static ACPI_STATUS acpi_wmi_enable(ACPI_HANDLE, const char *, bool, bool); |
137 | static bool acpi_wmi_input(struct wmi_t *, uint8_t, uint8_t); | | 138 | static bool acpi_wmi_input(struct wmi_t *, uint8_t, uint8_t); |
138 | | | 139 | |
139 | const char * const acpi_wmi_ids[] = { | | 140 | const char * const acpi_wmi_ids[] = { |
140 | "PNP0C14", | | 141 | "PNP0C14", |
141 | NULL | | 142 | NULL |
142 | }; | | 143 | }; |
143 | | | 144 | |
144 | CFATTACH_DECL_NEW(acpiwmi, sizeof(struct acpi_wmi_softc), | | 145 | CFATTACH_DECL_NEW(acpiwmi, sizeof(struct acpi_wmi_softc), |
145 | acpi_wmi_match, acpi_wmi_attach, NULL, NULL); | | 146 | acpi_wmi_match, acpi_wmi_attach, acpi_wmi_detach, NULL); |
146 | | | 147 | |
147 | static int | | 148 | static int |
148 | acpi_wmi_match(device_t parent, cfdata_t match, void *aux) | | 149 | acpi_wmi_match(device_t parent, cfdata_t match, void *aux) |
149 | { | | 150 | { |
150 | struct acpi_attach_args *aa = aux; | | 151 | struct acpi_attach_args *aa = aux; |
151 | | | 152 | |
152 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | | 153 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) |
153 | return 0; | | 154 | return 0; |
154 | | | 155 | |
155 | return acpi_match_hid(aa->aa_node->ad_devinfo, acpi_wmi_ids); | | 156 | return acpi_match_hid(aa->aa_node->ad_devinfo, acpi_wmi_ids); |
156 | } | | 157 | } |
157 | | | 158 | |
158 | static void | | 159 | static void |
159 | acpi_wmi_attach(device_t parent, device_t self, void *aux) | | 160 | acpi_wmi_attach(device_t parent, device_t self, void *aux) |
160 | { | | 161 | { |
161 | struct acpi_wmi_softc *sc = device_private(self); | | 162 | struct acpi_wmi_softc *sc = device_private(self); |
162 | struct acpi_attach_args *aa = aux; | | 163 | struct acpi_attach_args *aa = aux; |
163 | | | 164 | |
164 | sc->sc_dev = self; | | 165 | sc->sc_dev = self; |
165 | sc->sc_node = aa->aa_node; | | 166 | sc->sc_node = aa->aa_node; |
| | | 167 | |
| | | 168 | sc->sc_child = NULL; |
166 | sc->sc_handler = NULL; | | 169 | sc->sc_handler = NULL; |
167 | | | 170 | |
168 | aprint_naive("\n"); | | 171 | aprint_naive("\n"); |
169 | aprint_normal(": ACPI WMI Interface\n"); | | 172 | aprint_normal(": ACPI WMI Interface\n"); |
170 | | | 173 | |
171 | if (acpi_wmi_init(sc) != true) | | 174 | if (acpi_wmi_init(sc) != true) |
172 | return; | | 175 | return; |
173 | | | 176 | |
174 | #ifdef ACPIVERBOSE | | 177 | #ifdef ACPIVERBOSE |
175 | acpi_wmi_dump(sc); | | 178 | acpi_wmi_dump(sc); |
176 | #endif | | 179 | #endif |
177 | | | 180 | |
178 | acpi_wmi_event_add(sc); | | 181 | (void)acpi_wmi_event_add(sc); |
179 | | | 182 | (void)pmf_device_register(self, acpi_wmi_suspend, acpi_wmi_resume); |
180 | if (pmf_device_register(sc->sc_dev, | | | |
181 | acpi_wmi_suspend, acpi_wmi_resume) != true) | | | |
182 | aprint_error_dev(self, "failed to register power handler\n"); | | | |
183 | | | 183 | |
184 | /* Attach a child device to the pseudo-bus. */ | | | |
185 | sc->sc_child = config_found_ia(self, "acpiwmibus", | | 184 | sc->sc_child = config_found_ia(self, "acpiwmibus", |
186 | NULL, acpi_wmi_print); | | 185 | NULL, acpi_wmi_print); |
187 | } | | 186 | } |
188 | | | 187 | |
189 | static int | | 188 | static int |
| | | 189 | acpi_wmi_detach(device_t self, int flags) |
| | | 190 | { |
| | | 191 | struct acpi_wmi_softc *sc = device_private(self); |
| | | 192 | ACPI_STATUS rv; |
| | | 193 | |
| | | 194 | rv = acpi_wmi_event_del(sc); |
| | | 195 | |
| | | 196 | if (ACPI_FAILURE(rv)) |
| | | 197 | return EBUSY; |
| | | 198 | |
| | | 199 | if (sc->sc_child != NULL) |
| | | 200 | (void)config_detach(sc->sc_child, flags); |
| | | 201 | |
| | | 202 | acpi_wmi_del(sc); |
| | | 203 | pmf_device_deregister(self); |
| | | 204 | |
| | | 205 | return 0; |
| | | 206 | } |
| | | 207 | |
| | | 208 | static int |
190 | acpi_wmi_print(void *aux, const char *pnp) | | 209 | acpi_wmi_print(void *aux, const char *pnp) |
191 | { | | 210 | { |
192 | | | 211 | |
193 | if (pnp != NULL) | | 212 | if (pnp != NULL) |
194 | aprint_normal("acpiwmibus at %s", pnp); | | 213 | aprint_normal("acpiwmibus at %s", pnp); |
195 | | | 214 | |
196 | return UNCONF; | | 215 | return UNCONF; |
197 | } | | 216 | } |
198 | | | 217 | |
199 | static bool | | 218 | static bool |
200 | acpi_wmi_init(struct acpi_wmi_softc *sc) | | 219 | acpi_wmi_init(struct acpi_wmi_softc *sc) |
201 | { | | 220 | { |
202 | ACPI_OBJECT *obj; | | 221 | ACPI_OBJECT *obj; |
| @@ -379,98 +398,102 @@ int | | | @@ -379,98 +398,102 @@ int |
379 | acpi_wmi_guid_match(device_t self, const char *guid) | | 398 | acpi_wmi_guid_match(device_t self, const char *guid) |
380 | { | | 399 | { |
381 | struct acpi_wmi_softc *sc = device_private(self); | | 400 | struct acpi_wmi_softc *sc = device_private(self); |
382 | | | 401 | |
383 | if (ACPI_SUCCESS(acpi_wmi_guid_get(sc, guid, NULL))) | | 402 | if (ACPI_SUCCESS(acpi_wmi_guid_get(sc, guid, NULL))) |
384 | return 1; | | 403 | return 1; |
385 | | | 404 | |
386 | return 0; | | 405 | return 0; |
387 | } | | 406 | } |
388 | | | 407 | |
389 | /* | | 408 | /* |
390 | * Adds internal event handler. | | 409 | * Adds internal event handler. |
391 | */ | | 410 | */ |
392 | static void | | 411 | static ACPI_STATUS |
393 | acpi_wmi_event_add(struct acpi_wmi_softc *sc) | | 412 | acpi_wmi_event_add(struct acpi_wmi_softc *sc) |
394 | { | | 413 | { |
395 | struct wmi_t *wmi; | | 414 | struct wmi_t *wmi; |
396 | ACPI_STATUS rv; | | 415 | ACPI_STATUS rv; |
397 | | | 416 | |
398 | rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, | | 417 | rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, |
399 | ACPI_ALL_NOTIFY, acpi_wmi_event_handler, sc); | | 418 | ACPI_ALL_NOTIFY, acpi_wmi_event_handler, sc); |
400 | | | 419 | |
401 | if (ACPI_FAILURE(rv)) { | | 420 | if (ACPI_FAILURE(rv)) { |
402 | aprint_error_dev(sc->sc_dev, "failed to install notify " | | 421 | aprint_error_dev(sc->sc_dev, "failed to install notify " |
403 | "handler: %s\n", AcpiFormatException(rv)); | | 422 | "handler: %s\n", AcpiFormatException(rv)); |
404 | return; | | 423 | return rv; |
405 | } | | 424 | } |
406 | | | 425 | |
407 | /* Enable possible expensive events. */ | | 426 | /* Enable possible expensive events. */ |
408 | SIMPLEQ_FOREACH(wmi, &sc->wmi_head, wmi_link) { | | 427 | SIMPLEQ_FOREACH(wmi, &sc->wmi_head, wmi_link) { |
409 | | | 428 | |
410 | if ((wmi->guid.flags & ACPI_WMI_FLAG_EVENT) && | | 429 | if ((wmi->guid.flags & ACPI_WMI_FLAG_EVENT) && |
411 | (wmi->guid.flags & ACPI_WMI_FLAG_EXPENSIVE)) { | | 430 | (wmi->guid.flags & ACPI_WMI_FLAG_EXPENSIVE)) { |
412 | | | 431 | |
413 | rv = acpi_wmi_enable(sc->sc_node->ad_handle, | | 432 | rv = acpi_wmi_enable(sc->sc_node->ad_handle, |
414 | wmi->guid.oid, false, true); | | 433 | wmi->guid.oid, false, true); |
415 | | | 434 | |
416 | if (ACPI_SUCCESS(rv)) { | | 435 | if (ACPI_SUCCESS(rv)) { |
417 | wmi->eevent = true; | | 436 | wmi->eevent = true; |
418 | continue; | | 437 | continue; |
419 | } | | 438 | } |
420 | | | 439 | |
421 | aprint_error_dev(sc->sc_dev, "failed to enable " | | 440 | aprint_error_dev(sc->sc_dev, "failed to enable " |
422 | "expensive WExx: %s\n", AcpiFormatException(rv)); | | 441 | "expensive WExx: %s\n", AcpiFormatException(rv)); |
423 | } | | 442 | } |
424 | } | | 443 | } |
| | | 444 | |
| | | 445 | return AE_OK; |
425 | } | | 446 | } |
426 | | | 447 | |
427 | /* | | 448 | /* |
428 | * Removes the internal event handler. | | 449 | * Removes the internal event handler. |
429 | */ | | 450 | */ |
430 | static void | | 451 | static ACPI_STATUS |
431 | acpi_wmi_event_del(struct acpi_wmi_softc *sc) | | 452 | acpi_wmi_event_del(struct acpi_wmi_softc *sc) |
432 | { | | 453 | { |
433 | struct wmi_t *wmi; | | 454 | struct wmi_t *wmi; |
434 | ACPI_STATUS rv; | | 455 | ACPI_STATUS rv; |
435 | | | 456 | |
436 | rv = AcpiRemoveNotifyHandler(sc->sc_node->ad_handle, | | 457 | rv = AcpiRemoveNotifyHandler(sc->sc_node->ad_handle, |
437 | ACPI_ALL_NOTIFY, acpi_wmi_event_handler); | | 458 | ACPI_ALL_NOTIFY, acpi_wmi_event_handler); |
438 | | | 459 | |
439 | if (ACPI_FAILURE(rv)) { | | 460 | if (ACPI_FAILURE(rv)) { |
440 | aprint_debug_dev(sc->sc_dev, "failed to remove notify " | | 461 | aprint_debug_dev(sc->sc_dev, "failed to remove notify " |
441 | "handler: %s\n", AcpiFormatException(rv)); | | 462 | "handler: %s\n", AcpiFormatException(rv)); |
442 | return; | | 463 | return rv; |
443 | } | | 464 | } |
444 | | | 465 | |
445 | SIMPLEQ_FOREACH(wmi, &sc->wmi_head, wmi_link) { | | 466 | SIMPLEQ_FOREACH(wmi, &sc->wmi_head, wmi_link) { |
446 | | | 467 | |
447 | if (wmi->eevent != true) | | 468 | if (wmi->eevent != true) |
448 | continue; | | 469 | continue; |
449 | | | 470 | |
450 | KASSERT(wmi->guid.flags & ACPI_WMI_FLAG_EVENT); | | 471 | KASSERT(wmi->guid.flags & ACPI_WMI_FLAG_EVENT); |
451 | KASSERT(wmi->guid.flags & ACPI_WMI_FLAG_EXPENSIVE); | | 472 | KASSERT(wmi->guid.flags & ACPI_WMI_FLAG_EXPENSIVE); |
452 | | | 473 | |
453 | rv = acpi_wmi_enable(sc->sc_node->ad_handle, | | 474 | rv = acpi_wmi_enable(sc->sc_node->ad_handle, |
454 | wmi->guid.oid, false, false); | | 475 | wmi->guid.oid, false, false); |
455 | | | 476 | |
456 | if (ACPI_SUCCESS(rv)) { | | 477 | if (ACPI_SUCCESS(rv)) { |
457 | wmi->eevent = false; | | 478 | wmi->eevent = false; |
458 | continue; | | 479 | continue; |
459 | } | | 480 | } |
460 | | | 481 | |
461 | aprint_error_dev(sc->sc_dev, "failed to disable " | | 482 | aprint_error_dev(sc->sc_dev, "failed to disable " |
462 | "expensive WExx: %s\n", AcpiFormatException(rv)); | | 483 | "expensive WExx: %s\n", AcpiFormatException(rv)); |
463 | } | | 484 | } |
| | | 485 | |
| | | 486 | return AE_OK; |
464 | } | | 487 | } |
465 | | | 488 | |
466 | /* | | 489 | /* |
467 | * Returns extra information possibly associated with an event. | | 490 | * Returns extra information possibly associated with an event. |
468 | */ | | 491 | */ |
469 | ACPI_STATUS | | 492 | ACPI_STATUS |
470 | acpi_wmi_event_get(device_t self, uint32_t event, ACPI_BUFFER *obuf) | | 493 | acpi_wmi_event_get(device_t self, uint32_t event, ACPI_BUFFER *obuf) |
471 | { | | 494 | { |
472 | struct acpi_wmi_softc *sc = device_private(self); | | 495 | struct acpi_wmi_softc *sc = device_private(self); |
473 | struct wmi_t *wmi; | | 496 | struct wmi_t *wmi; |
474 | ACPI_OBJECT_LIST arg; | | 497 | ACPI_OBJECT_LIST arg; |
475 | ACPI_OBJECT obj; | | 498 | ACPI_OBJECT obj; |
476 | | | 499 | |
| @@ -502,26 +525,29 @@ acpi_wmi_event_get(device_t self, uint32 | | | @@ -502,26 +525,29 @@ acpi_wmi_event_get(device_t self, uint32 |
502 | } | | 525 | } |
503 | | | 526 | |
504 | return AE_NOT_FOUND; | | 527 | return AE_NOT_FOUND; |
505 | } | | 528 | } |
506 | | | 529 | |
507 | /* | | 530 | /* |
508 | * Forwards events to the external handler through the internal one. | | 531 | * Forwards events to the external handler through the internal one. |
509 | */ | | 532 | */ |
510 | static void | | 533 | static void |
511 | acpi_wmi_event_handler(ACPI_HANDLE hdl, uint32_t evt, void *aux) | | 534 | acpi_wmi_event_handler(ACPI_HANDLE hdl, uint32_t evt, void *aux) |
512 | { | | 535 | { |
513 | struct acpi_wmi_softc *sc = aux; | | 536 | struct acpi_wmi_softc *sc = aux; |
514 | | | 537 | |
| | | 538 | if (sc->sc_child == NULL) |
| | | 539 | return; |
| | | 540 | |
515 | if (sc->sc_handler == NULL) | | 541 | if (sc->sc_handler == NULL) |
516 | return; | | 542 | return; |
517 | | | 543 | |
518 | (*sc->sc_handler)(NULL, evt, sc->sc_child); | | 544 | (*sc->sc_handler)(NULL, evt, sc->sc_child); |
519 | } | | 545 | } |
520 | | | 546 | |
521 | /* | | 547 | /* |
522 | * Adds or removes (NULL) the external event handler. | | 548 | * Adds or removes (NULL) the external event handler. |
523 | */ | | 549 | */ |
524 | ACPI_STATUS | | 550 | ACPI_STATUS |
525 | acpi_wmi_event_register(device_t self, ACPI_NOTIFY_HANDLER handler) | | 551 | acpi_wmi_event_register(device_t self, ACPI_NOTIFY_HANDLER handler) |
526 | { | | 552 | { |
527 | struct acpi_wmi_softc *sc = device_private(self); | | 553 | struct acpi_wmi_softc *sc = device_private(self); |