acpi.c revision 1.43 1 /* $NetBSD: acpi.c,v 1.43 2003/10/30 18:13:38 mycroft Exp $ */
2
3 /*
4 * Copyright 2001, 2003 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * Autoconfiguration support for the Intel ACPI Component Architecture
40 * ACPI reference implementation.
41 */
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.43 2003/10/30 18:13:38 mycroft Exp $");
45
46 #include "opt_acpi.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/device.h>
51 #include <sys/malloc.h>
52 #include <sys/kernel.h>
53 #include <sys/proc.h>
54
55 #include <dev/acpi/acpica.h>
56 #include <dev/acpi/acpireg.h>
57 #include <dev/acpi/acpivar.h>
58 #include <dev/acpi/acpi_osd.h>
59 #ifdef ACPIVERBOSE
60 #include <dev/acpi/acpidevs_data.h>
61 #endif
62
63 #ifdef ACPI_PCI_FIXUP
64 #include <dev/acpi/acpica/Subsystem/acnamesp.h> /* AcpiNsGetNodeByPath() */
65 #include <dev/pci/pcidevs.h>
66 #endif
67
68 MALLOC_DECLARE(M_ACPI);
69
70 #include <machine/acpi_machdep.h>
71
72 #ifdef ACPI_DEBUGGER
73 #define ACPI_DBGR_INIT 0x01
74 #define ACPI_DBGR_TABLES 0x02
75 #define ACPI_DBGR_ENABLE 0x04
76 #define ACPI_DBGR_PROBE 0x08
77 #define ACPI_DBGR_RUNNING 0x10
78
79 int acpi_dbgr = 0x00;
80 #endif
81
82 int acpi_match(struct device *, struct cfdata *, void *);
83 void acpi_attach(struct device *, struct device *, void *);
84
85 int acpi_print(void *aux, const char *);
86
87 extern struct cfdriver acpi_cd;
88
89 CFATTACH_DECL(acpi, sizeof(struct acpi_softc),
90 acpi_match, acpi_attach, NULL, NULL);
91
92 /*
93 * This is a flag we set when the ACPI subsystem is active. Machine
94 * dependent code may wish to skip other steps (such as attaching
95 * subsystems that ACPI supercedes) when ACPI is active.
96 */
97 int acpi_active;
98
99 /*
100 * Pointer to the ACPI subsystem's state. There can be only
101 * one ACPI instance.
102 */
103 struct acpi_softc *acpi_softc;
104
105 /*
106 * Locking stuff.
107 */
108 static struct simplelock acpi_slock;
109 static int acpi_locked;
110
111 /*
112 * Prototypes.
113 */
114 void acpi_shutdown(void *);
115 ACPI_STATUS acpi_disable(struct acpi_softc *sc);
116 void acpi_build_tree(struct acpi_softc *);
117 ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
118
119 void acpi_enable_fixed_events(struct acpi_softc *);
120 #ifdef ACPI_PCI_FIXUP
121 void acpi_pci_fixup(struct acpi_softc *);
122 #endif
123 #if defined(ACPI_PCI_FIXUP) || defined(ACPI_ACTIVATE_DEV)
124 ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE handle);
125 #endif
126
127 /*
128 * acpi_probe:
129 *
130 * Probe for ACPI support. This is called by the
131 * machine-dependent ACPI front-end. All of the
132 * actual work is done by ACPICA.
133 *
134 * NOTE: This is not an autoconfiguration interface function.
135 */
136 int
137 acpi_probe(void)
138 {
139 static int beenhere;
140 ACPI_STATUS rv;
141
142 if (beenhere != 0)
143 panic("acpi_probe: ACPI has already been probed");
144 beenhere = 1;
145
146 simple_lock_init(&acpi_slock);
147 acpi_locked = 0;
148
149 /*
150 * Start up ACPICA.
151 */
152 #ifdef ACPI_DEBUGGER
153 if (acpi_dbgr & ACPI_DBGR_INIT)
154 acpi_osd_debugger();
155 #endif
156
157 rv = AcpiInitializeSubsystem();
158 if (rv != AE_OK) {
159 printf("ACPI: unable to initialize ACPICA: %d\n", rv);
160 return (0);
161 }
162
163 #ifdef ACPI_DEBUGGER
164 if (acpi_dbgr & ACPI_DBGR_TABLES)
165 acpi_osd_debugger();
166 #endif
167
168 rv = AcpiLoadTables();
169 if (rv != AE_OK) {
170 printf("ACPI: unable to load tables: %d\n", rv);
171 return (0);
172 }
173
174 /*
175 * Looks like we have ACPI!
176 */
177
178 return (1);
179 }
180
181 /*
182 * acpi_match:
183 *
184 * Autoconfiguration `match' routine.
185 */
186 int
187 acpi_match(struct device *parent, struct cfdata *match, void *aux)
188 {
189 struct acpibus_attach_args *aa = aux;
190
191 if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0)
192 return (0);
193
194 /*
195 * XXX Check other locators? Hard to know -- machine
196 * dependent code has already checked for the presence
197 * of ACPI by calling acpi_probe(), so I suppose we
198 * don't really have to do anything else.
199 */
200 return (1);
201 }
202
203 /*
204 * acpi_attach:
205 *
206 * Autoconfiguration `attach' routine. Finish initializing
207 * ACPICA (some initialization was done in acpi_probe(),
208 * which was required to check for the presence of ACPI),
209 * and enable the ACPI subsystem.
210 */
211 void
212 acpi_attach(struct device *parent, struct device *self, void *aux)
213 {
214 struct acpi_softc *sc = (void *) self;
215 struct acpibus_attach_args *aa = aux;
216 ACPI_TABLE_HEADER *ap = &AcpiGbl_XSDT->Header;
217 ACPI_STATUS rv;
218
219 printf("\n");
220
221 if (acpi_softc != NULL)
222 panic("acpi_attach: ACPI has already been attached");
223
224 sysmon_power_settype("acpi");
225
226 printf("%s: using Intel ACPI CA subsystem version %08x\n",
227 sc->sc_dev.dv_xname, ACPI_CA_VERSION);
228
229 printf("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
230 sc->sc_dev.dv_xname,
231 ap->OemId, ap->OemTableId, ap->OemRevision,
232 ap->AslCompilerId, ap->AslCompilerRevision);
233
234 sc->sc_quirks = acpi_find_quirks();
235
236 sc->sc_iot = aa->aa_iot;
237 sc->sc_memt = aa->aa_memt;
238 sc->sc_pc = aa->aa_pc;
239 sc->sc_pciflags = aa->aa_pciflags;
240 sc->sc_ic = aa->aa_ic;
241
242 acpi_softc = sc;
243
244 /*
245 * Install the default address space handlers.
246 */
247
248 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
249 ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
250 if (rv != AE_OK) {
251 printf("%s: unable to install SYSTEM MEMORY handler: %d\n",
252 sc->sc_dev.dv_xname, rv);
253 return;
254 }
255
256 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
257 ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
258 if (rv != AE_OK) {
259 printf("%s: unable to install SYSTEM IO handler: %d\n",
260 sc->sc_dev.dv_xname, rv);
261 return;
262 }
263
264 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
265 ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
266 if (rv != AE_OK) {
267 printf("%s: unable to install PCI CONFIG handler: %d\n",
268 sc->sc_dev.dv_xname, rv);
269 return;
270 }
271
272 /*
273 * Bring ACPI on-line.
274 *
275 * Note that we request that _STA (device init) and _INI (object init)
276 * methods not be run.
277 *
278 * XXX We need to arrange for the object init pass after we have
279 * XXX attached all of our children.
280 */
281 #ifdef ACPI_DEBUGGER
282 if (acpi_dbgr & ACPI_DBGR_ENABLE)
283 acpi_osd_debugger();
284 #endif
285 rv = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
286 if (rv != AE_OK) {
287 printf("%s: unable to enable ACPI: %d\n",
288 sc->sc_dev.dv_xname, rv);
289 return;
290 }
291 acpi_active = 1;
292
293 /* Our current state is "awake". */
294 sc->sc_sleepstate = ACPI_STATE_S0;
295
296 /* Show SCI interrupt. */
297 if (AcpiGbl_FADT != NULL)
298 printf("%s: SCI interrupting at int %d\n",
299 sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt);
300 /*
301 * Check for fixed-hardware features.
302 */
303 acpi_enable_fixed_events(sc);
304
305 /*
306 * Fix up PCI devices.
307 */
308 #ifdef ACPI_PCI_FIXUP
309 if ((sc->sc_quirks & (ACPI_QUIRK_BADPCI | ACPI_QUIRK_BADIRQ)) == 0)
310 acpi_pci_fixup(sc);
311 #endif
312
313 /*
314 * Scan the namespace and build our device tree.
315 */
316 #ifdef ACPI_DEBUGGER
317 if (acpi_dbgr & ACPI_DBGR_PROBE)
318 acpi_osd_debugger();
319 #endif
320 acpi_md_callback((struct device *)sc);
321 acpi_build_tree(sc);
322
323 /*
324 * Register a shutdown hook that disables certain ACPI
325 * events that might happen and confuse us while we're
326 * trying to shut down.
327 */
328 sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
329 if (sc->sc_sdhook == NULL)
330 printf("%s: WARNING: unable to register shutdown hook\n",
331 sc->sc_dev.dv_xname);
332
333 #ifdef ACPI_DEBUGGER
334 if (acpi_dbgr & ACPI_DBGR_RUNNING)
335 acpi_osd_debugger();
336 #endif
337 }
338
339 /*
340 * acpi_shutdown:
341 *
342 * Shutdown hook for ACPI -- disable some events that
343 * might confuse us.
344 */
345 void
346 acpi_shutdown(void *arg)
347 {
348 struct acpi_softc *sc = arg;
349
350 if (acpi_disable(sc) != AE_OK)
351 printf("%s: WARNING: unable to disable ACPI\n",
352 sc->sc_dev.dv_xname);
353 }
354
355 /*
356 * acpi_disable:
357 *
358 * Disable ACPI.
359 */
360 ACPI_STATUS
361 acpi_disable(struct acpi_softc *sc)
362 {
363 ACPI_STATUS rv = AE_OK;
364
365 if (acpi_active) {
366 rv = AcpiDisable();
367 if (rv == AE_OK)
368 acpi_active = 0;
369 }
370 return (rv);
371 }
372
373 struct acpi_make_devnode_state {
374 struct acpi_softc *softc;
375 struct acpi_scope *scope;
376 };
377
378 /*
379 * acpi_build_tree:
380 *
381 * Scan relevant portions of the ACPI namespace and attach
382 * child devices.
383 */
384 void
385 acpi_build_tree(struct acpi_softc *sc)
386 {
387 static const char *scopes[] = {
388 "\\_PR_", /* ACPI 1.0 processor namespace */
389 "\\_SB_", /* system bus namespace */
390 "\\_SI_", /* system idicator namespace */
391 "\\_TZ_", /* ACPI 1.0 thermal zone namespace */
392 NULL,
393 };
394 struct acpi_attach_args aa;
395 struct acpi_make_devnode_state state;
396 struct acpi_scope *as;
397 struct acpi_devnode *ad;
398 ACPI_HANDLE parent;
399 int i;
400
401 TAILQ_INIT(&sc->sc_scopes);
402
403 state.softc = sc;
404
405 /*
406 * Scan the namespace and build our tree.
407 */
408 for (i = 0; scopes[i] != NULL; i++) {
409 as = malloc(sizeof(*as), M_ACPI, M_WAITOK);
410 as->as_name = scopes[i];
411 TAILQ_INIT(&as->as_devnodes);
412
413 TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
414
415 state.scope = as;
416
417 if (AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i],
418 &parent) == AE_OK) {
419 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
420 acpi_make_devnode, &state, NULL);
421 }
422
423 /* Now, for this namespace, try and attach the devices. */
424 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
425 aa.aa_node = ad;
426 aa.aa_iot = sc->sc_iot;
427 aa.aa_memt = sc->sc_memt;
428 aa.aa_pc = sc->sc_pc;
429 aa.aa_pciflags = sc->sc_pciflags;
430 aa.aa_ic = sc->sc_ic;
431
432 if (ad->ad_devinfo.Type == ACPI_TYPE_DEVICE) {
433 /*
434 * XXX We only attach devices which are:
435 *
436 * - present
437 * - enabled
438 * - functioning properly
439 *
440 * However, if enabled, it's decoding resources,
441 * so we should claim them, if possible.
442 * Requires changes to bus_space(9).
443 */
444 if ((ad->ad_devinfo.CurrentStatus &
445 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
446 ACPI_STA_DEV_OK)) !=
447 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
448 ACPI_STA_DEV_OK))
449 continue;
450
451 /*
452 * XXX Same problem as above...
453 */
454 if ((ad->ad_devinfo.Valid & ACPI_VALID_HID)
455 == 0)
456 continue;
457 }
458
459 ad->ad_device = config_found(&sc->sc_dev,
460 &aa, acpi_print);
461 }
462 }
463 }
464
465 #ifdef ACPI_ACTIVATE_DEV
466 static void
467 acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO *di)
468 {
469 ACPI_STATUS rv;
470
471 #ifdef ACPI_DEBUG
472 printf("acpi_activate_device: %s, old status=%x\n",
473 di->HardwareId, di->CurrentStatus);
474 #endif
475
476 rv = acpi_allocate_resources(handle);
477 if (ACPI_FAILURE(rv)) {
478 printf("acpi: activate failed for %s\n", di->HardwareId);
479 } else {
480 printf("acpi: activated %s\n", di->HardwareId);
481 }
482
483 (void)AcpiGetObjectInfo(handle, di);
484 #ifdef ACPI_DEBUG
485 printf("acpi_activate_device: %s, new status=%x\n",
486 di->HardwareId, di->CurrentStatus);
487 #endif
488 }
489 #endif /* ACPI_ACTIVATE_DEV */
490
491 /*
492 * acpi_make_devnode:
493 *
494 * Make an ACPI devnode.
495 */
496 ACPI_STATUS
497 acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
498 void **status)
499 {
500 struct acpi_make_devnode_state *state = context;
501 #if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG)
502 struct acpi_softc *sc = state->softc;
503 #endif
504 struct acpi_scope *as = state->scope;
505 struct acpi_devnode *ad;
506 ACPI_DEVICE_INFO devinfo;
507 ACPI_OBJECT_TYPE type;
508 ACPI_STATUS rv;
509
510 if (AcpiGetType(handle, &type) == AE_OK) {
511 rv = AcpiGetObjectInfo(handle, &devinfo);
512 if (rv != AE_OK) {
513 #ifdef ACPI_DEBUG
514 printf("%s: AcpiGetObjectInfo failed\n",
515 sc->sc_dev.dv_xname);
516 #endif
517 goto out; /* XXX why return OK */
518 }
519
520 switch (type) {
521 case ACPI_TYPE_DEVICE:
522 #ifdef ACPI_ACTIVATE_DEV
523 if ((devinfo.Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) ==
524 (ACPI_VALID_STA|ACPI_VALID_HID) &&
525 (devinfo.CurrentStatus &
526 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
527 ACPI_STA_DEV_PRESENT) {
528 acpi_activate_device(handle, &devinfo);
529
530 /* Update devinfo. */
531 rv = AcpiGetObjectInfo(handle, &devinfo);
532 if (rv != AE_OK)
533 goto out;
534 }
535
536 /* FALLTHROUGH */
537 #endif
538
539 case ACPI_TYPE_PROCESSOR:
540 case ACPI_TYPE_THERMAL:
541 case ACPI_TYPE_POWER:
542 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO);
543 if (ad == NULL)
544 return (AE_NO_MEMORY);
545
546 ad->ad_devinfo = devinfo;
547 ad->ad_handle = handle;
548 ad->ad_level = level;
549 ad->ad_scope = as;
550 ad->ad_type = type;
551
552 TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
553
554 if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
555 goto out;
556
557 #ifdef ACPI_EXTRA_DEBUG
558 printf("%s: HID %s found in scope %s level %d\n",
559 sc->sc_dev.dv_xname, ad->ad_devinfo.HardwareId,
560 as->as_name, ad->ad_level);
561 if (ad->ad_devinfo.Valid & ACPI_VALID_UID)
562 printf(" UID %s\n",
563 ad->ad_devinfo.UniqueId);
564 if (ad->ad_devinfo.Valid & ACPI_VALID_ADR)
565 printf(" ADR 0x%016qx\n",
566 ad->ad_devinfo.Address);
567 if (ad->ad_devinfo.Valid & ACPI_VALID_STA)
568 printf(" STA 0x%08x\n",
569 ad->ad_devinfo.CurrentStatus);
570 #endif
571 }
572 }
573 out:
574 return (AE_OK);
575 }
576
577 /*
578 * acpi_print:
579 *
580 * Autoconfiguration print routine.
581 */
582 int
583 acpi_print(void *aux, const char *pnp)
584 {
585 struct acpi_attach_args *aa = aux;
586
587 if (pnp) {
588 if (aa->aa_node->ad_devinfo.Valid & ACPI_VALID_HID) {
589 char *pnpstr = aa->aa_node->ad_devinfo.HardwareId;
590 char *str;
591
592 aprint_normal("%s ", pnpstr);
593 if (acpi_eval_string(aa->aa_node->ad_handle,
594 "_STR", &str) == AE_OK) {
595 aprint_normal("[%s] ", str);
596 AcpiOsFree(str);
597 }
598 #ifdef ACPIVERBOSE
599 else {
600 int i;
601
602 for (i = 0; i < sizeof(acpi_knowndevs) /
603 sizeof(acpi_knowndevs[0]); i++) {
604 if (strcmp(acpi_knowndevs[i].pnp,
605 pnpstr) == 0) {
606 printf("[%s] ",
607 acpi_knowndevs[i].str);
608 }
609 }
610 }
611
612 #endif
613 } else {
614 aprint_normal("ACPI Object Type '%s' (0x%02x) ",
615 AcpiUtGetTypeName(aa->aa_node->ad_devinfo.Type),
616 aa->aa_node->ad_devinfo.Type);
617 }
618 aprint_normal("at %s", pnp);
619 } else {
620 if (aa->aa_node->ad_devinfo.Valid & ACPI_VALID_HID) {
621 aprint_normal(" (%s", aa->aa_node->ad_devinfo.HardwareId);
622 if (aa->aa_node->ad_devinfo.Valid & ACPI_VALID_UID) {
623 char *uid;
624
625 if (aa->aa_node->ad_devinfo.UniqueId[0] == '\0')
626 uid = "<null>";
627 else
628 uid = aa->aa_node->ad_devinfo.UniqueId;
629 aprint_normal("-%s", uid);
630 }
631 aprint_normal(")");
632 }
633 }
634
635 return (UNCONF);
636 }
637
638 /*****************************************************************************
639 * ACPI fixed-hardware feature handlers
640 *****************************************************************************/
641
642 UINT32 acpi_fixed_button_handler(void *);
643 void acpi_fixed_button_pressed(void *);
644
645 /*
646 * acpi_enable_fixed_events:
647 *
648 * Enable any fixed-hardware feature handlers.
649 */
650 void
651 acpi_enable_fixed_events(struct acpi_softc *sc)
652 {
653 static int beenhere;
654 ACPI_STATUS rv;
655
656 KASSERT(beenhere == 0);
657 beenhere = 1;
658
659 /*
660 * Check for fixed-hardware buttons.
661 */
662
663 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
664 printf("%s: fixed-feature power button present\n",
665 sc->sc_dev.dv_xname);
666 sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname;
667 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
668 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
669 printf("%s: unable to register fixed power button "
670 "with sysmon\n", sc->sc_dev.dv_xname);
671 } else {
672 rv = AcpiInstallFixedEventHandler(
673 ACPI_EVENT_POWER_BUTTON,
674 acpi_fixed_button_handler, &sc->sc_smpsw_power);
675 if (rv != AE_OK) {
676 printf("%s: unable to install handler for "
677 "fixed power button: %d\n",
678 sc->sc_dev.dv_xname, rv);
679 }
680 }
681 }
682
683 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
684 printf("%s: fixed-feature sleep button present\n",
685 sc->sc_dev.dv_xname);
686 sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname;
687 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
688 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
689 printf("%s: unable to register fixed sleep button "
690 "with sysmon\n", sc->sc_dev.dv_xname);
691 } else {
692 rv = AcpiInstallFixedEventHandler(
693 ACPI_EVENT_SLEEP_BUTTON,
694 acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
695 if (rv != AE_OK) {
696 printf("%s: unable to install handler for "
697 "fixed sleep button: %d\n",
698 sc->sc_dev.dv_xname, rv);
699 }
700 }
701 }
702 }
703
704 /*
705 * acpi_fixed_button_handler:
706 *
707 * Event handler for the fixed buttons.
708 */
709 UINT32
710 acpi_fixed_button_handler(void *context)
711 {
712 struct sysmon_pswitch *smpsw = context;
713 int rv;
714
715 #ifdef ACPI_BUT_DEBUG
716 printf("%s: fixed button handler\n", smpsw->smpsw_name);
717 #endif
718
719 rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO,
720 acpi_fixed_button_pressed, smpsw);
721 if (rv != AE_OK)
722 printf("%s: WARNING: unable to queue fixed button pressed "
723 "callback: %d\n", smpsw->smpsw_name, rv);
724
725 return (ACPI_INTERRUPT_HANDLED);
726 }
727
728 /*
729 * acpi_fixed_button_pressed:
730 *
731 * Deal with a fixed button being pressed.
732 */
733 void
734 acpi_fixed_button_pressed(void *context)
735 {
736 struct sysmon_pswitch *smpsw = context;
737
738 #ifdef ACPI_BUT_DEBUG
739 printf("%s: fixed button pressed, calling sysmon\n",
740 smpsw->smpsw_name);
741 #endif
742
743 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
744 }
745
746 /*****************************************************************************
747 * ACPI utility routines.
748 *****************************************************************************/
749
750 /*
751 * acpi_eval_integer:
752 *
753 * Evaluate an integer object.
754 */
755 ACPI_STATUS
756 acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp)
757 {
758 ACPI_STATUS rv;
759 ACPI_BUFFER buf;
760 ACPI_OBJECT param;
761
762 if (handle == NULL)
763 handle = ACPI_ROOT_OBJECT;
764
765 buf.Pointer = ¶m;
766 buf.Length = sizeof(param);
767
768 rv = AcpiEvaluateObject(handle, path, NULL, &buf);
769 if (rv == AE_OK) {
770 if (param.Type == ACPI_TYPE_INTEGER)
771 *valp = param.Integer.Value;
772 else
773 rv = AE_TYPE;
774 }
775
776 return (rv);
777 }
778
779 /*
780 * acpi_eval_string:
781 *
782 * Evaluate a (Unicode) string object.
783 */
784 ACPI_STATUS
785 acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
786 {
787 ACPI_STATUS rv;
788 ACPI_BUFFER buf;
789 ACPI_OBJECT *param;
790
791 if (handle == NULL)
792 handle = ACPI_ROOT_OBJECT;
793
794 buf.Pointer = NULL;
795 buf.Length = ACPI_ALLOCATE_BUFFER;
796
797 rv = AcpiEvaluateObject(handle, path, NULL, &buf);
798 param = (ACPI_OBJECT *)buf.Pointer;
799 if (rv == AE_OK && param) {
800 if (param->Type == ACPI_TYPE_STRING) {
801 char *ptr = param->String.Pointer;
802 size_t len;
803 while (*ptr++)
804 continue;
805 len = ptr - param->String.Pointer;
806 if ((*stringp = AcpiOsAllocate(len)) == NULL) {
807 rv = AE_NO_MEMORY;
808 goto done;
809 }
810 (void)memcpy(*stringp, param->String.Pointer, len);
811 goto done;
812 }
813 rv = AE_TYPE;
814 }
815 done:
816 if (buf.Pointer)
817 AcpiOsFree(buf.Pointer);
818 return (rv);
819 }
820
821
822 /*
823 * acpi_eval_struct:
824 *
825 * Evaluate a more complex structure.
826 * Caller must free buf.Pointer by AcpiOsFree().
827 */
828 ACPI_STATUS
829 acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp)
830 {
831 ACPI_STATUS rv;
832
833 if (handle == NULL)
834 handle = ACPI_ROOT_OBJECT;
835
836 bufp->Pointer = NULL;
837 bufp->Length = ACPI_ALLOCATE_BUFFER;
838
839 rv = AcpiEvaluateObject(handle, path, NULL, bufp);
840
841 return (rv);
842 }
843
844 /*
845 * acpi_get:
846 *
847 * Fetch data info the specified (empty) ACPI buffer.
848 * Caller must free buf.Pointer by AcpiOsFree().
849 */
850 ACPI_STATUS
851 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
852 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
853 {
854 buf->Pointer = NULL;
855 buf->Length = ACPI_ALLOCATE_BUFFER;
856
857 return ((*getit)(handle, buf));
858 }
859
860
861 /*
862 * acpi_acquire_global_lock:
863 *
864 * Acquire global lock, with sleeping appropriately.
865 */
866 #define ACQUIRE_WAIT 1000
867
868 ACPI_STATUS
869 acpi_acquire_global_lock(UINT32 *handle)
870 {
871 ACPI_STATUS status;
872 UINT32 h;
873 int s;
874
875 s = splhigh();
876 simple_lock(&acpi_slock);
877 while (acpi_locked)
878 ltsleep(&acpi_slock, PVM, "acpi_lock", 0, &acpi_slock);
879 acpi_locked = 1;
880 simple_unlock(&acpi_slock);
881 splx(s);
882 status = AcpiAcquireGlobalLock(ACQUIRE_WAIT, &h);
883 if (ACPI_SUCCESS(status))
884 *handle = h;
885 else {
886 printf("acpi: cannot acquire lock. status=0x%X\n", status);
887 s = splhigh();
888 simple_lock(&acpi_slock);
889 acpi_locked = 0;
890 simple_unlock(&acpi_slock);
891 splx(s);
892 }
893
894 return (status);
895 }
896
897 void
898 acpi_release_global_lock(UINT32 handle)
899 {
900 ACPI_STATUS status;
901 int s;
902
903 if (!acpi_locked) {
904 printf("acpi: not locked.\n");
905 return;
906 }
907
908 status = AcpiReleaseGlobalLock(handle);
909 if (ACPI_FAILURE(status)) {
910 printf("acpi: AcpiReleaseGlobalLock failed. status=0x%X\n",
911 status);
912 return;
913 }
914
915 s = splhigh();
916 simple_lock(&acpi_slock);
917 acpi_locked = 0;
918 simple_unlock(&acpi_slock);
919 splx(s);
920 wakeup(&acpi_slock);
921 }
922
923 int
924 acpi_is_global_locked(void)
925 {
926 return (acpi_locked);
927 }
928
929
930
931 /*****************************************************************************
932 * ACPI sleep support.
933 *****************************************************************************/
934
935 static int
936 is_available_state(struct acpi_softc *sc, int state)
937 {
938 UINT8 type_a, type_b;
939
940 return (ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
941 &type_a, &type_b)));
942 }
943
944 /*
945 * acpi_enter_sleep_state:
946 *
947 * enter to the specified sleep state.
948 */
949
950 ACPI_STATUS
951 acpi_enter_sleep_state(struct acpi_softc *sc, int state)
952 {
953 int s;
954 ACPI_STATUS ret = AE_OK;
955
956 switch (state) {
957 case ACPI_STATE_S0:
958 break;
959 case ACPI_STATE_S1:
960 case ACPI_STATE_S2:
961 case ACPI_STATE_S3:
962 case ACPI_STATE_S4:
963 if (!is_available_state(sc, state)) {
964 printf("acpi: cannot enter the sleep state (%d).\n",
965 state);
966 break;
967 }
968 ret = AcpiEnterSleepStatePrep(state);
969 if (ACPI_FAILURE(ret)) {
970 printf("acpi: failed preparing to sleep (%s)\n",
971 AcpiFormatException(ret));
972 break;
973 }
974 if (state==ACPI_STATE_S1) {
975 /* just enter the state */
976 acpi_md_OsDisableInterrupt();
977 AcpiEnterSleepState((UINT8)state);
978 AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
979 } else {
980 /* XXX: powerhooks(9) framework is too poor to
981 * support ACPI sleep state...
982 */
983 dopowerhooks(PWR_SOFTSUSPEND);
984 s = splhigh();
985 dopowerhooks(PWR_SUSPEND);
986 acpi_md_sleep(state);
987 dopowerhooks(PWR_RESUME);
988 splx(s);
989 dopowerhooks(PWR_SOFTRESUME);
990 if (state==ACPI_STATE_S4)
991 AcpiEnable();
992 }
993 AcpiLeaveSleepState((UINT8)state);
994 break;
995 case ACPI_STATE_S5:
996 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
997 if (ACPI_FAILURE(ret)) {
998 printf("acpi: failed preparing to sleep (%s)\n",
999 AcpiFormatException(ret));
1000 break;
1001 }
1002 acpi_md_OsDisableInterrupt();
1003 AcpiEnterSleepState(ACPI_STATE_S5);
1004 printf("WARNING: powerdown failed!\n");
1005 break;
1006 }
1007
1008 return (ret);
1009 }
1010
1011 #ifdef ACPI_PCI_FIXUP
1012 ACPI_STATUS acpi_pci_fixup_bus(ACPI_HANDLE, UINT32, void *, void **);
1013 /*
1014 * acpi_pci_fixup:
1015 *
1016 * Set up PCI devices that BIOS didn't handle right.
1017 * Iterate through all devices and try to get the _PTR
1018 * (PCI Routing Table). If it exists then make sure all
1019 * interrupt links that it uses are working.
1020 */
1021 void
1022 acpi_pci_fixup(struct acpi_softc *sc)
1023 {
1024 ACPI_HANDLE parent;
1025
1026 #ifdef ACPI_DEBUG
1027 printf("acpi_pci_fixup starts:\n");
1028 #endif
1029 if (AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent) != AE_OK)
1030 return;
1031 sc->sc_pci_bus = 0;
1032 AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
1033 acpi_pci_fixup_bus, sc, NULL);
1034 }
1035
1036 static ACPI_HANDLE
1037 acpi_get_node(char *name)
1038 {
1039 ACPI_NAMESPACE_NODE *ObjDesc;
1040 ACPI_STATUS Status;
1041
1042 Status = AcpiNsGetNodeByPath(name, NULL, 0, &ObjDesc);
1043 if (ACPI_FAILURE (Status)) {
1044 printf("acpi_get_node: could not find: %s\n",
1045 AcpiFormatException (Status));
1046 return NULL;
1047 }
1048 return ObjDesc;
1049 }
1050
1051 static uint
1052 acpi_get_intr(ACPI_HANDLE handle)
1053 {
1054 ACPI_BUFFER ret;
1055 ACPI_STATUS rv;
1056 ACPI_RESOURCE *res;
1057 ACPI_RESOURCE_IRQ *irq;
1058 uint intr;
1059
1060 intr = -1;
1061 rv = acpi_get(handle, &ret, AcpiGetCurrentResources);
1062 if (ACPI_FAILURE(rv))
1063 return (intr);
1064 for (res = ret.Pointer; res->Id != ACPI_RSTYPE_END_TAG;
1065 res = ACPI_NEXT_RESOURCE(res)) {
1066 if (res->Id == ACPI_RSTYPE_IRQ) {
1067 irq = (ACPI_RESOURCE_IRQ *)&res->Data;
1068 if (irq->NumberOfInterrupts == 1)
1069 intr = irq->Interrupts[0];
1070 break;
1071 }
1072 }
1073 AcpiOsFree(ret.Pointer);
1074 return (intr);
1075 }
1076
1077 static void
1078 acpi_pci_set_line(int bus, int dev, int pin, int line)
1079 {
1080 ACPI_STATUS err;
1081 ACPI_PCI_ID pid;
1082 UINT32 intr, id, bhlc;
1083 int func, nfunc;
1084
1085 pid.Bus = bus;
1086 pid.Device = dev;
1087 pid.Function = 0;
1088
1089 err = AcpiOsReadPciConfiguration(&pid, PCI_BHLC_REG, &bhlc, 32);
1090 if (err)
1091 return;
1092 if (PCI_HDRTYPE_MULTIFN(bhlc))
1093 nfunc = 8;
1094 else
1095 nfunc = 1;
1096
1097 for (func = 0; func < nfunc; func++) {
1098 pid.Function = func;
1099
1100 err = AcpiOsReadPciConfiguration(&pid, PCI_ID_REG, &id, 32);
1101 if (err || PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
1102 PCI_VENDOR(id) == 0)
1103 continue;
1104
1105 err = AcpiOsReadPciConfiguration(&pid, PCI_INTERRUPT_REG,
1106 &intr, 32);
1107 if (err) {
1108 printf("AcpiOsReadPciConfiguration failed %d\n", err);
1109 return;
1110 }
1111 if (pin == PCI_INTERRUPT_PIN(intr) &&
1112 line != PCI_INTERRUPT_LINE(intr)) {
1113 #ifdef ACPI_DEBUG
1114 printf("acpi fixup pci intr: %d:%d:%d %c: %d -> %d\n",
1115 bus, dev, func,
1116 pin + '@', PCI_INTERRUPT_LINE(intr),
1117 line);
1118 #endif
1119 intr &= ~(PCI_INTERRUPT_LINE_MASK <<
1120 PCI_INTERRUPT_LINE_SHIFT);
1121 intr |= line << PCI_INTERRUPT_LINE_SHIFT;
1122 err = AcpiOsWritePciConfiguration(&pid,
1123 PCI_INTERRUPT_REG, intr, 32);
1124 if (err) {
1125 printf("AcpiOsWritePciConfiguration failed"
1126 " %d\n", err);
1127 return;
1128 }
1129 }
1130 }
1131 }
1132
1133 ACPI_STATUS
1134 acpi_pci_fixup_bus(ACPI_HANDLE handle, UINT32 level, void *context,
1135 void **status)
1136 {
1137 struct acpi_softc *sc = context;
1138 ACPI_STATUS rv;
1139 ACPI_BUFFER buf;
1140 UINT8 *Buffer;
1141 ACPI_PCI_ROUTING_TABLE *PrtElement;
1142 ACPI_HANDLE link;
1143 uint line;
1144 ACPI_NAMESPACE_NODE *node;
1145 ACPI_INTEGER val;
1146
1147 rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable);
1148 if (ACPI_FAILURE(rv))
1149 return (AE_OK);
1150
1151 /*
1152 * If at level 1, this is a PCI root bus. Try the _BBN method
1153 * to get the right PCI bus numbering for the following
1154 * busses (this is a depth-first walk). It may fail,
1155 * for example if there's only one root bus, but that
1156 * case should be ok, so we'll ignore that.
1157 */
1158 if (level == 1) {
1159 node = AcpiNsMapHandleToNode(handle);
1160 rv = AcpiUtEvaluateNumericObject(METHOD_NAME__BBN, node, &val);
1161 if (!ACPI_FAILURE(rv)) {
1162 #ifdef ACPI_DEBUG
1163 printf("%s: fixup: _BBN success, bus # was %d now %d\n",
1164 sc->sc_dev.dv_xname, sc->sc_pci_bus,
1165 ACPI_LOWORD(val));
1166 #endif
1167 sc->sc_pci_bus = ACPI_LOWORD(val);
1168 }
1169 }
1170
1171
1172 #ifdef ACPI_DEBUG
1173 printf("%s: fixing up PCI bus %d at level %u\n", sc->sc_dev.dv_xname,
1174 sc->sc_pci_bus, level);
1175 #endif
1176
1177 for (Buffer = buf.Pointer; ; Buffer += PrtElement->Length) {
1178 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
1179 if (PrtElement->Length == 0)
1180 break;
1181 if (PrtElement->Source[0] == 0)
1182 continue;
1183
1184 link = acpi_get_node(PrtElement->Source);
1185 if (link == NULL)
1186 continue;
1187 line = acpi_get_intr(link);
1188 if (line == -1) {
1189 #ifdef ACPI_DEBUG
1190 printf("%s: fixing up intr link %s\n",
1191 sc->sc_dev.dv_xname, PrtElement->Source);
1192 #endif
1193 rv = acpi_allocate_resources(link);
1194 if (ACPI_FAILURE(rv)) {
1195 printf("%s: interrupt allocation failed %s\n",
1196 sc->sc_dev.dv_xname, PrtElement->Source);
1197 continue;
1198 }
1199 line = acpi_get_intr(link);
1200 if (line == -1) {
1201 printf("%s: get intr failed %s\n",
1202 sc->sc_dev.dv_xname, PrtElement->Source);
1203 continue;
1204 }
1205 }
1206
1207 acpi_pci_set_line(sc->sc_pci_bus, PrtElement->Address >> 16,
1208 PrtElement->Pin + 1, line);
1209 }
1210
1211 sc->sc_pci_bus++;
1212
1213 AcpiOsFree(buf.Pointer);
1214 return (AE_OK);
1215 }
1216 #endif /* ACPI_PCI_FIXUP */
1217
1218 #if defined(ACPI_PCI_FIXUP) || defined(ACPI_ACTIVATE_DEV)
1219 /* XXX This very incomplete */
1220 ACPI_STATUS
1221 acpi_allocate_resources(ACPI_HANDLE handle)
1222 {
1223 ACPI_BUFFER bufp, bufc, bufn;
1224 ACPI_RESOURCE *resp, *resc, *resn;
1225 ACPI_RESOURCE_IRQ *irq;
1226 ACPI_STATUS rv;
1227 uint delta;
1228
1229 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1230 if (ACPI_FAILURE(rv))
1231 goto out;
1232 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1233 if (ACPI_FAILURE(rv)) {
1234 goto out1;
1235 }
1236
1237 bufn.Length = 1000;
1238 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1239 resp = bufp.Pointer;
1240 resc = bufc.Pointer;
1241 while (resc->Id != ACPI_RSTYPE_END_TAG &&
1242 resp->Id != ACPI_RSTYPE_END_TAG) {
1243 while (resc->Id != resp->Id && resp->Id != ACPI_RSTYPE_END_TAG)
1244 resp = ACPI_NEXT_RESOURCE(resp);
1245 if (resp->Id == ACPI_RSTYPE_END_TAG)
1246 break;
1247 /* Found identical Id */
1248 resn->Id = resc->Id;
1249 switch (resc->Id) {
1250 case ACPI_RSTYPE_IRQ:
1251 memcpy(&resn->Data, &resp->Data,
1252 sizeof(ACPI_RESOURCE_IRQ));
1253 irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1254 irq->Interrupts[0] =
1255 ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1256 Interrupts[irq->NumberOfInterrupts-1];
1257 irq->NumberOfInterrupts = 1;
1258 resn->Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ);
1259 break;
1260 case ACPI_RSTYPE_IO:
1261 memcpy(&resn->Data, &resp->Data,
1262 sizeof(ACPI_RESOURCE_IO));
1263 resn->Length = resp->Length;
1264 break;
1265 default:
1266 printf("acpi_allocate_resources: res=%d\n", resc->Id);
1267 rv = AE_BAD_DATA;
1268 goto out2;
1269 }
1270 resc = ACPI_NEXT_RESOURCE(resc);
1271 resn = ACPI_NEXT_RESOURCE(resn);
1272 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1273 if (delta >=
1274 bufn.Length-ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_DATA)) {
1275 bufn.Length *= 2;
1276 bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1277 M_ACPI, M_WAITOK);
1278 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1279 }
1280 }
1281 if (resc->Id != ACPI_RSTYPE_END_TAG) {
1282 printf("acpi_allocate_resources: resc not exhausted\n");
1283 rv = AE_BAD_DATA;
1284 goto out3;
1285 }
1286
1287 resn->Id = ACPI_RSTYPE_END_TAG;
1288 rv = AcpiSetCurrentResources(handle, &bufn);
1289 if (ACPI_FAILURE(rv)) {
1290 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
1291 AcpiFormatException(rv));
1292 }
1293
1294 out3:
1295 free(bufn.Pointer, M_ACPI);
1296 out2:
1297 AcpiOsFree(bufc.Pointer);
1298 out1:
1299 AcpiOsFree(bufp.Pointer);
1300 out:
1301 return rv;
1302 }
1303 #endif /* ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV */
1304