Annotation of src/sys/dev/acpi/acpi.c, Revision 1.10
1.10 ! tshiozak 1: /* $NetBSD: acpi.c,v 1.9 2002/06/17 08:18:51 kanaoka Exp $ */
1.1 thorpej 2:
3: /*
4: * Copyright 2001 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: */
1.5 lukem 42:
43: #include <sys/cdefs.h>
1.10 ! tshiozak 44: __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.9 2002/06/17 08:18:51 kanaoka Exp $");
1.1 thorpej 45:
46: #include <sys/param.h>
47: #include <sys/systm.h>
48: #include <sys/device.h>
49: #include <sys/malloc.h>
50:
51: #include <dev/acpi/acpica.h>
52: #include <dev/acpi/acpireg.h>
53: #include <dev/acpi/acpivar.h>
54: #include <dev/acpi/acpi_osd.h>
55:
1.10 ! tshiozak 56: #include <machine/acpi_machdep.h>
! 57:
1.1 thorpej 58: #ifdef ENABLE_DEBUGGER
59: #define ACPI_DBGR_INIT 0x01
60: #define ACPI_DBGR_TABLES 0x02
61: #define ACPI_DBGR_ENABLE 0x04
62: #define ACPI_DBGR_PROBE 0x08
63: #define ACPI_DBGR_RUNNING 0x10
64:
65: int acpi_dbgr = 0x00;
66: #endif
67:
68: int acpi_match(struct device *, struct cfdata *, void *);
69: void acpi_attach(struct device *, struct device *, void *);
70:
71: int acpi_print(void *aux, const char *);
72:
73: extern struct cfdriver acpi_cd;
74:
75: struct cfattach acpi_ca = {
76: sizeof(struct acpi_softc), acpi_match, acpi_attach,
77: };
78:
79: /*
80: * This is a flag we set when the ACPI subsystem is active. Machine
81: * dependent code may wish to skip other steps (such as attaching
82: * subsystems that ACPI supercedes) when ACPI is active.
83: */
84: int acpi_active;
85:
86: /*
87: * Pointer to the ACPI subsystem's state. There can be only
88: * one ACPI instance.
89: */
90: struct acpi_softc *acpi_softc;
91:
92: void acpi_shutdown(void *);
93: ACPI_STATUS acpi_disable(struct acpi_softc *sc);
94: void acpi_build_tree(struct acpi_softc *);
95: ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
96:
97: void acpi_enable_fixed_events(struct acpi_softc *);
98:
99: /*
100: * acpi_probe:
101: *
102: * Probe for ACPI support. This is called by the
103: * machine-dependent ACPI front-end. All of the
104: * actual work is done by ACPICA.
105: *
106: * NOTE: This is not an autoconfiguration interface function.
107: */
108: int
109: acpi_probe(void)
110: {
111: static int beenhere;
112: ACPI_STATUS rv;
113:
114: if (beenhere != 0)
115: panic("acpi_probe: ACPI has already been probed");
116: beenhere = 1;
117:
118: /*
119: * Start up ACPICA.
120: */
121: #ifdef ENABLE_DEBUGGER
122: if (acpi_dbgr & ACPI_DBGR_INIT)
123: acpi_osd_debugger();
124: #endif
125:
126: rv = AcpiInitializeSubsystem();
127: if (rv != AE_OK) {
128: printf("ACPI: unable to initialize ACPICA: %d\n", rv);
129: return (0);
130: }
131:
132: #ifdef ENABLE_DEBUGGER
133: if (acpi_dbgr & ACPI_DBGR_TABLES)
134: acpi_osd_debugger();
135: #endif
136:
137: rv = AcpiLoadTables();
138: if (rv != AE_OK) {
139: printf("ACPI: unable to load tables: %d\n", rv);
140: return (0);
141: }
142:
143: /*
144: * Looks like we have ACPI!
145: */
146:
147: return (1);
148: }
149:
150: /*
151: * acpi_match:
152: *
153: * Autoconfiguration `match' routine.
154: */
155: int
156: acpi_match(struct device *parent, struct cfdata *match, void *aux)
157: {
158: struct acpibus_attach_args *aa = aux;
159:
160: if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0)
161: return (0);
162:
163: /*
164: * XXX Check other locators? Hard to know -- machine
165: * dependent code has already checked for the presence
166: * of ACPI by calling acpi_probe(), so I suppose we
167: * don't really have to do anything else.
168: */
169: return (1);
170: }
171:
172: /*
173: * acpi_attach:
174: *
175: * Autoconfiguration `attach' routine. Finish initializing
176: * ACPICA (some initialization was done in acpi_probe(),
177: * which was required to check for the presence of ACPI),
178: * and enable the ACPI subsystem.
179: */
180: void
181: acpi_attach(struct device *parent, struct device *self, void *aux)
182: {
183: struct acpi_softc *sc = (void *) self;
184: struct acpibus_attach_args *aa = aux;
185: ACPI_STATUS rv;
186:
187: printf("\n");
188:
189: if (acpi_softc != NULL)
190: panic("acpi_attach: ACPI has already been attached");
191:
192: sc->sc_iot = aa->aa_iot;
193: sc->sc_memt = aa->aa_memt;
194: sc->sc_pc = aa->aa_pc;
195: sc->sc_pciflags = aa->aa_pciflags;
196:
197: acpi_softc = sc;
198:
199: /*
200: * Install the default address space handlers.
201: */
202:
203: rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
204: ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
205: if (rv != AE_OK) {
206: printf("%s: unable to install SYSTEM MEMORY handler: %d\n",
207: sc->sc_dev.dv_xname, rv);
208: return;
209: }
210:
211: rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
212: ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
213: if (rv != AE_OK) {
214: printf("%s: unable to install SYSTEM IO handler: %d\n",
215: sc->sc_dev.dv_xname, rv);
216: return;
217: }
218:
219: rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
220: ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
221: if (rv != AE_OK) {
222: printf("%s: unable to install PCI CONFIG handler: %d\n",
223: sc->sc_dev.dv_xname, rv);
224: return;
225: }
226:
227: /*
228: * Bring ACPI on-line.
229: *
230: * Note that we request that _STA (device init) and _INI (object init)
231: * methods not be run.
232: *
233: * XXX We need to arrange for the object init pass after we have
234: * XXX attached all of our children.
235: */
236: #ifdef ENABLE_DEBUGGER
237: if (acpi_dbgr & ACPI_DBGR_ENABLE)
238: acpi_osd_debugger();
239: #endif
240: rv = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
241: if (rv != AE_OK) {
242: printf("%s: unable to enable ACPI: %d\n",
243: sc->sc_dev.dv_xname, rv);
244: return;
245: }
246: acpi_active = 1;
247:
248: /*
249: * Set up the default sleep state to enter when various
250: * switches are activated.
251: */
252: sc->sc_switch_sleep[ACPI_SWITCH_POWERBUTTON] = ACPI_STATE_S5;
253: sc->sc_switch_sleep[ACPI_SWITCH_SLEEPBUTTON] = ACPI_STATE_S1;
254: sc->sc_switch_sleep[ACPI_SWITCH_LID] = ACPI_STATE_S1;
255:
256: /* Our current state is "awake". */
257: sc->sc_sleepstate = ACPI_STATE_S0;
258:
1.9 kanaoka 259: /* Show SCI interrupt. */
260: if (AcpiGbl_FADT != NULL)
261: printf("%s: SCI interrupting at irq %d\n",
262: sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt);
1.1 thorpej 263: /*
264: * Check for fixed-hardware features.
265: */
266: acpi_enable_fixed_events(sc);
267:
268: /*
269: * Scan the namespace and build our device tree.
270: */
271: #ifdef ENABLE_DEBUGGER
272: if (acpi_dbgr & ACPI_DBGR_PROBE)
273: acpi_osd_debugger();
274: #endif
275: acpi_build_tree(sc);
276:
277: /*
278: * Register a shutdown hook that disables certain ACPI
279: * events that might happen and confuse us while we're
280: * trying to shut down.
281: */
282: sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
283: if (sc->sc_sdhook == NULL)
284: printf("%s: WARNING: unable to register shutdown hook\n",
285: sc->sc_dev.dv_xname);
286:
287: #ifdef ENABLE_DEBUGGER
288: if (acpi_dbgr & ACPI_DBGR_RUNNING)
289: acpi_osd_debugger();
290: #endif
291: }
292:
293: /*
294: * acpi_shutdown:
295: *
296: * Shutdown hook for ACPI -- disable some events that
297: * might confuse us.
298: */
299: void
300: acpi_shutdown(void *arg)
301: {
302: struct acpi_softc *sc = arg;
303:
304: if (acpi_disable(sc) != AE_OK)
305: printf("%s: WARNING: unable to disable ACPI\n",
306: sc->sc_dev.dv_xname);
307: }
308:
309: /*
310: * acpi_disable:
311: *
312: * Disable ACPI.
313: */
314: ACPI_STATUS
315: acpi_disable(struct acpi_softc *sc)
316: {
317: ACPI_STATUS rv = AE_OK;
318:
319: if (acpi_active) {
320: rv = AcpiDisable();
321: if (rv == AE_OK)
322: acpi_active = 0;
323: }
324: return (rv);
325: }
326:
327: struct acpi_make_devnode_state {
328: struct acpi_softc *softc;
329: struct acpi_scope *scope;
330: };
331:
332: /*
333: * acpi_build_tree:
334: *
335: * Scan relevant portions of the ACPI namespace and attach
336: * child devices.
337: */
338: void
339: acpi_build_tree(struct acpi_softc *sc)
340: {
341: static const char *scopes[] = {
342: "\\_PR_", /* ACPI 1.0 processor namespace */
343: "\\_SB_", /* system bus namespace */
344: "\\_SI_", /* system idicator namespace */
345: "\\_TZ_", /* ACPI 1.0 thermal zone namespace */
346: NULL,
347: };
348: struct acpi_attach_args aa;
349: struct acpi_make_devnode_state state;
350: struct acpi_scope *as;
351: struct acpi_devnode *ad;
352: ACPI_HANDLE parent;
353: int i;
354:
355: TAILQ_INIT(&sc->sc_scopes);
356:
357: state.softc = sc;
358:
359: /*
360: * Scan the namespace and build our tree.
361: */
362: for (i = 0; scopes[i] != NULL; i++) {
363: as = malloc(sizeof(*as), M_DEVBUF, M_WAITOK);
364: as->as_name = scopes[i];
365: TAILQ_INIT(&as->as_devnodes);
366:
367: TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
368:
369: state.scope = as;
370:
371: if (AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i],
372: &parent) == AE_OK) {
373: AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
374: acpi_make_devnode, &state, NULL);
375: }
376:
377: /* Now, for this namespace, try and attach the devices. */
378: TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
379: aa.aa_node = ad;
380: aa.aa_iot = sc->sc_iot;
381: aa.aa_memt = sc->sc_memt;
382: aa.aa_pc = sc->sc_pc;
383: aa.aa_pciflags = sc->sc_pciflags;
384:
385: /*
386: * XXX We only attach devices which are:
387: *
388: * - present
389: * - enabled
390: * - functioning properly
391: *
392: * However, if enabled, it's decoding resources,
393: * so we should claim them, if possible. Requires
394: * changes to bus_space(9).
395: */
396: if ((ad->ad_devinfo.CurrentStatus &
397: (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
1.9 kanaoka 398: ACPI_STA_DEV_OK)) !=
1.1 thorpej 399: (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
1.9 kanaoka 400: ACPI_STA_DEV_OK))
1.1 thorpej 401: continue;
402:
403: /*
404: * XXX Same problem as above...
405: */
406: if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
407: continue;
408:
409: ad->ad_device = config_found(&sc->sc_dev,
410: &aa, acpi_print);
411: }
412: }
413: }
414:
415: /*
416: * acpi_make_devnode:
417: *
418: * Make an ACPI devnode.
419: */
420: ACPI_STATUS
421: acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
422: void **status)
423: {
424: struct acpi_make_devnode_state *state = context;
1.4 thorpej 425: #ifdef ACPI_DEBUG
1.1 thorpej 426: struct acpi_softc *sc = state->softc;
1.4 thorpej 427: #endif
1.1 thorpej 428: struct acpi_scope *as = state->scope;
429: struct acpi_devnode *ad;
430: ACPI_OBJECT_TYPE type;
431: ACPI_STATUS rv;
432:
433: if (AcpiGetType(handle, &type) == AE_OK) {
434: switch (type) {
435: case ACPI_TYPE_DEVICE:
436: case ACPI_TYPE_PROCESSOR:
437: case ACPI_TYPE_THERMAL:
438: case ACPI_TYPE_POWER:
1.6 tsutsui 439: ad = malloc(sizeof(*ad), M_DEVBUF, M_NOWAIT|M_ZERO);
1.1 thorpej 440: if (ad == NULL)
441: return (AE_NO_MEMORY);
442:
443: ad->ad_handle = handle;
444: ad->ad_level = level;
445: ad->ad_scope = as;
446: ad->ad_type = type;
447:
448: TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
449:
450: rv = AcpiGetObjectInfo(handle, &ad->ad_devinfo);
451: if (rv != AE_OK)
452: goto out;
453:
454: if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
455: goto out;
456:
457: #ifdef ACPI_DEBUG
458: printf("%s: HID %s found in scope %s level %d\n",
459: sc->sc_dev.dv_xname, ad->ad_devinfo.HardwareId,
460: as->as_name, ad->ad_level);
461: if (ad->ad_devinfo.Valid & ACPI_VALID_UID)
462: printf(" UID %s\n",
463: ad->ad_devinfo.UniqueId);
464: if (ad->ad_devinfo.Valid & ACPI_VALID_ADR)
465: printf(" ADR 0x%016qx\n",
466: ad->ad_devinfo.Address);
467: if (ad->ad_devinfo.Valid & ACPI_VALID_STA)
468: printf(" STA 0x%08x\n",
469: ad->ad_devinfo.CurrentStatus);
470: #endif
471: }
472: }
473: out:
474: return (AE_OK);
475: }
476:
477: /*
478: * acpi_print:
479: *
480: * Autoconfiguration print routine.
481: */
482: int
483: acpi_print(void *aux, const char *pnp)
484: {
485: struct acpi_attach_args *aa = aux;
1.7 sommerfe 486: #if 0
1.4 thorpej 487: char *str;
1.7 sommerfe 488: #endif
1.1 thorpej 489:
1.4 thorpej 490: if (pnp) {
491: printf("%s ", aa->aa_node->ad_devinfo.HardwareId);
1.7 sommerfe 492: #if 0 /* Not until we fix acpi_eval_string */
1.4 thorpej 493: if (acpi_eval_string(aa->aa_node->ad_handle,
494: "_STR", &str) == AE_OK) {
495: printf("[%s] ", str);
496: AcpiOsFree(str);
497: }
1.7 sommerfe 498: #endif
1.4 thorpej 499: printf("at %s", pnp);
500: }
1.1 thorpej 501:
502: return (UNCONF);
503: }
504:
505: /*****************************************************************************
506: * ACPI fixed-hardware feature handlers
507: *****************************************************************************/
508:
509: UINT32 acpi_fixed_power_button_handler(void *);
510: UINT32 acpi_fixed_sleep_button_handler(void *);
511:
512: /*
513: * acpi_enable_fixed_events:
514: *
515: * Enable any fixed-hardware feature handlers.
516: */
517: void
518: acpi_enable_fixed_events(struct acpi_softc *sc)
519: {
520: static int beenhere;
521: ACPI_STATUS rv;
522:
523: /*
524: * Check for fixed-hardware buttons.
525: */
526:
527: if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
528: if (beenhere == 0)
529: printf("%s: fixed-feature power button present\n",
530: sc->sc_dev.dv_xname);
531: rv = AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
532: acpi_fixed_power_button_handler, sc);
533: if (rv != AE_OK)
534: printf("%s: unable to install handler for fixed "
535: "power button: %d\n", sc->sc_dev.dv_xname, rv);
536: }
537:
538: if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
539: if (beenhere == 0)
540: printf("%s: fixed-feature sleep button present\n",
541: sc->sc_dev.dv_xname);
542: rv = AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
543: acpi_fixed_sleep_button_handler, sc);
544: if (rv != AE_OK)
545: printf("%s: unable to install handler for fixed "
546: "power button: %d\n", sc->sc_dev.dv_xname, rv);
547: }
548:
549: beenhere = 1;
550: }
551:
552: /*
553: * acpi_fixed_power_button_handler:
554: *
555: * Fixed event handler for the power button.
556: */
557: UINT32
558: acpi_fixed_power_button_handler(void *context)
559: {
560: struct acpi_softc *sc = context;
561:
562: /* XXX XXX XXX */
563:
564: printf("%s: fixed power button pressed\n", sc->sc_dev.dv_xname);
565:
1.8 thorpej 566: return (ACPI_INTERRUPT_HANDLED);
1.1 thorpej 567: }
568:
569: /*
570: * acpi_fixed_sleep_button_handler:
571: *
572: * Fixed event handler for the sleep button.
573: */
574: UINT32
575: acpi_fixed_sleep_button_handler(void *context)
576: {
577: struct acpi_softc *sc = context;
578:
579: /* XXX XXX XXX */
580:
581: printf("%s: fixed sleep button pressed\n", sc->sc_dev.dv_xname);
582:
1.8 thorpej 583: return (ACPI_INTERRUPT_HANDLED);
1.1 thorpej 584: }
585:
586: /*****************************************************************************
587: * ACPI utility routines.
588: *****************************************************************************/
589:
1.2 thorpej 590: /*
591: * acpi_eval_integer:
592: *
593: * Evaluate an integer object.
594: */
1.1 thorpej 595: ACPI_STATUS
596: acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp)
597: {
598: ACPI_STATUS rv;
599: ACPI_BUFFER buf;
600: ACPI_OBJECT param;
601:
602: if (handle == NULL)
603: handle = ACPI_ROOT_OBJECT;
604:
605: buf.Pointer = ¶m;
606: buf.Length = sizeof(param);
607:
608: rv = AcpiEvaluateObject(handle, path, NULL, &buf);
609: if (rv == AE_OK) {
610: if (param.Type == ACPI_TYPE_INTEGER)
611: *valp = param.Integer.Value;
612: else
613: rv = AE_TYPE;
614: }
615:
1.4 thorpej 616: return (rv);
617: }
618:
1.7 sommerfe 619: #if 0
1.4 thorpej 620: /*
621: * acpi_eval_string:
622: *
1.7 sommerfe 623: * Evaluate a (Unicode) string object.
624: * XXX current API may leak memory, so don't use this.
1.4 thorpej 625: */
626: ACPI_STATUS
627: acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
628: {
629: ACPI_STATUS rv;
630: ACPI_BUFFER buf;
1.7 sommerfe 631: ACPI_OBJECT *param;
1.4 thorpej 632:
633: if (handle == NULL)
634: handle = ACPI_ROOT_OBJECT;
635:
636: buf.Pointer = NULL;
637: buf.Length = 0;
638:
639: rv = AcpiEvaluateObject(handle, path, NULL, &buf);
640: if (rv != AE_BUFFER_OVERFLOW)
641: return (rv);
642:
643: buf.Pointer = AcpiOsAllocate(buf.Length);
644: if (buf.Pointer == NULL)
645: return (AE_NO_MEMORY);
646:
647: rv = AcpiEvaluateObject(handle, path, NULL, &buf);
1.7 sommerfe 648: param = (ACPI_OBJECT *)buf.Pointer;
1.4 thorpej 649: if (rv == AE_OK) {
1.7 sommerfe 650: if (param->Type == ACPI_TYPE_STRING) {
651: /* XXX may leak buf.Pointer!! */
652: *stringp = param->String.Pointer;
1.4 thorpej 653: return (AE_OK);
654: }
655: rv = AE_TYPE;
656: }
657:
658: AcpiOsFree(buf.Pointer);
1.7 sommerfe 659: return (rv);
660: }
661: #endif
662:
663:
664: /*
665: * acpi_eval_struct:
666: *
667: * Evaluate a more complex structure. Caller must free buf.Pointer.
668: */
669: ACPI_STATUS
670: acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp)
671: {
672: ACPI_STATUS rv;
673:
674: if (handle == NULL)
675: handle = ACPI_ROOT_OBJECT;
676:
677: bufp->Pointer = NULL;
678: bufp->Length = 0;
679:
680: rv = AcpiEvaluateObject(handle, path, NULL, bufp);
681: if (rv != AE_BUFFER_OVERFLOW)
682: return (rv);
683:
684: bufp->Pointer = AcpiOsAllocate(bufp->Length);
685: if (bufp->Pointer == NULL)
686: return (AE_NO_MEMORY);
687:
688: rv = AcpiEvaluateObject(handle, path, NULL, bufp);
689:
1.1 thorpej 690: return (rv);
1.2 thorpej 691: }
692:
693: /*
694: * acpi_get:
695: *
696: * Fetch data info the specified (empty) ACPI buffer.
697: */
698: ACPI_STATUS
699: acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
700: ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
701: {
702: ACPI_STATUS rv;
703:
704: buf->Pointer = NULL;
705: buf->Length = 0;
706:
707: rv = (*getit)(handle, buf);
708: if (rv != AE_BUFFER_OVERFLOW)
709: return (rv);
710:
1.8 thorpej 711: buf->Pointer = AcpiOsAllocate(buf->Length);
1.2 thorpej 712: if (buf->Pointer == NULL)
713: return (AE_NO_MEMORY);
1.8 thorpej 714: memset(buf->Pointer, 0, buf->Length);
1.2 thorpej 715:
716: return ((*getit)(handle, buf));
1.10 ! tshiozak 717: }
! 718:
! 719:
! 720: /*****************************************************************************
! 721: * ACPI sleep support.
! 722: *****************************************************************************/
! 723:
! 724: static int
! 725: is_available_state(struct acpi_softc *sc, int state)
! 726: {
! 727: UINT8 type_a, type_b;
! 728:
! 729: return (ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
! 730: &type_a, &type_b)));
! 731: }
! 732:
! 733: /*
! 734: * acpi_enter_sleep_state:
! 735: *
! 736: * enter to the specified sleep state.
! 737: */
! 738:
! 739: ACPI_STATUS
! 740: acpi_enter_sleep_state(struct acpi_softc *sc, int state)
! 741: {
! 742: int s;
! 743: ACPI_STATUS ret = AE_OK;
! 744:
! 745: switch (state) {
! 746: case ACPI_STATE_S0:
! 747: break;
! 748: case ACPI_STATE_S1:
! 749: case ACPI_STATE_S2:
! 750: case ACPI_STATE_S3:
! 751: case ACPI_STATE_S4:
! 752: if (!is_available_state(sc, state)) {
! 753: printf("acpi: cannot enter the sleep state (%d).\n",
! 754: state);
! 755: break;
! 756: }
! 757: ret = AcpiEnterSleepStatePrep(state);
! 758: if (ACPI_FAILURE(ret)) {
! 759: printf("acpi: failed preparing to sleep (%s)\n",
! 760: AcpiFormatException(ret));
! 761: break;
! 762: }
! 763: if (state==ACPI_STATE_S1) {
! 764: /* just enter the state */
! 765: AcpiEnterSleepState((UINT8)state);
! 766: AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
! 767: } else {
! 768: /* XXX: powerhooks(9) framework is too poor to
! 769: * support ACPI sleep state...
! 770: */
! 771: dopowerhooks(PWR_SOFTSUSPEND);
! 772: s = splhigh();
! 773: dopowerhooks(PWR_SUSPEND);
! 774: acpi_md_sleep(state);
! 775: dopowerhooks(PWR_RESUME);
! 776: splx(s);
! 777: dopowerhooks(PWR_SOFTRESUME);
! 778: if (state==ACPI_STATE_S4)
! 779: AcpiEnable();
! 780: }
! 781: AcpiLeaveSleepState((UINT8)state);
! 782: break;
! 783: case ACPI_STATE_S5:
! 784: AcpiEnterSleepStatePrep(ACPI_STATE_S5);
! 785: AcpiEnterSleepState(ACPI_STATE_S5);
! 786: printf("WARNING: powerdown failed!\n");
! 787: break;
! 788: }
! 789:
! 790: return_ACPI_STATUS(ret);
1.1 thorpej 791: }
CVSweb <webmaster@jp.NetBSD.org>