1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent, Inc. All rights reserved.
25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /*
29 * Copyright (c) 2009, Intel Corporation.
30 * All rights reserved.
31 */
32
33 /*
34 * x86 ACPI CA services
35 */
36
37 #include <sys/file.h>
38 #include <sys/errno.h>
39 #include <sys/conf.h>
40 #include <sys/modctl.h>
41 #include <sys/open.h>
42 #include <sys/stat.h>
43 #include <sys/spl.h>
44 #include <sys/ddi.h>
45 #include <sys/sunddi.h>
46 #include <sys/esunddi.h>
47 #include <sys/kstat.h>
48 #include <sys/x86_archext.h>
49
50 #include <acpica/include/acpi.h>
51 #include <sys/acpica.h>
52 #include <sys/archsystm.h>
53
54 /*
55 *
56 */
57 static struct modlmisc modlmisc = {
58 &mod_miscops,
59 "ACPI interpreter",
60 };
61
62 static struct modlinkage modlinkage = {
63 MODREV_1, /* MODREV_1 manual */
64 (void *)&modlmisc, /* module linkage */
65 NULL, /* list terminator */
66 };
67
68 /*
69 * Local prototypes
70 */
71
72 struct parsed_prw {
73 ACPI_HANDLE prw_gpeobj;
74 int prw_gpebit;
75 int prw_level;
76 };
77
78 static void acpica_init_kstats(void);
79 static ACPI_STATUS acpica_init_PRW(
80 ACPI_HANDLE hdl,
81 UINT32 lvl,
82 void *ctxp,
83 void **rvpp);
84
85 static ACPI_STATUS acpica_parse_PRW(
86 ACPI_BUFFER *prw_buf,
87 struct parsed_prw *prw);
88
89 /*
90 * Local data
91 */
92
93 static kmutex_t acpica_module_lock;
94 static kstat_t *acpica_ksp;
95
96 /*
97 * State of acpica subsystem
98 * After successful initialization, will be ACPICA_INITIALIZED
99 */
100 int acpica_init_state = ACPICA_NOT_INITIALIZED;
101
102 /*
103 * Following are set by acpica_process_user_options()
104 *
105 * acpica_enable = FALSE prevents initialization of ACPI CA
106 * completely
107 *
108 * acpi_init_level determines level of ACPI CA functionality
109 * enabled in acpica_init()
110 */
111 int acpica_enable;
112 UINT32 acpi_init_level;
113
114 /*
115 * Non-zero enables lax behavior with respect to some
116 * common ACPI BIOS issues; see ACPI CA documentation
117 * Setting this to zero causes ACPI CA to enforce strict
118 * compliance with ACPI specification
119 */
120 int acpica_enable_interpreter_slack = 1;
121
122 /*
123 * For non-DEBUG builds, set the ACPI CA debug level to 0
124 * to quiet chatty BIOS output into /var/adm/messages
125 * Field-patchable for diagnostic use.
126 */
127 #ifdef DEBUG
128 int acpica_muzzle_debug_output = 0;
129 #else
130 int acpica_muzzle_debug_output = 1;
131 #endif
132
133 /*
134 * ACPI DDI hooks
135 */
136 static int acpica_ddi_setwake(dev_info_t *dip, int level);
137
138 int
139 _init(void)
140 {
141 int error = EBUSY;
142 int status;
143 extern int (*acpi_fp_setwake)();
144 extern kmutex_t cpu_map_lock;
145
146 mutex_init(&acpica_module_lock, NULL, MUTEX_DRIVER, NULL);
147 mutex_init(&cpu_map_lock, NULL, MUTEX_SPIN,
148 (ddi_iblock_cookie_t)ipltospl(DISP_LEVEL));
149
150 if ((error = mod_install(&modlinkage)) != 0) {
151 mutex_destroy(&acpica_module_lock);
152 goto load_error;
153 }
154
155 AcpiGbl_EnableInterpreterSlack = (acpica_enable_interpreter_slack != 0);
156
157 /* global ACPI CA initialization */
158 if (ACPI_FAILURE(status = AcpiInitializeSubsystem()))
159 cmn_err(CE_WARN, "!AcpiInitializeSubsystem failed: %d", status);
160
161 /* initialize table manager */
162 if (ACPI_FAILURE(status = AcpiInitializeTables(NULL, 0, 0)))
163 cmn_err(CE_WARN, "!AcpiInitializeTables failed: %d", status);
164
165 acpi_fp_setwake = acpica_ddi_setwake;
166
167 load_error:
168 return (error);
169 }
170
171 int
172 _info(struct modinfo *modinfop)
173 {
174 return (mod_info(&modlinkage, modinfop));
175 }
176
177 int
178 _fini(void)
179 {
180 /*
181 * acpica module is never unloaded at run-time; there's always
182 * a PSM depending on it, at the very least
183 */
184 return (EBUSY);
185 }
186
187 /*
188 * Install acpica-provided (default) address-space handlers
189 * that may be needed before AcpiEnableSubsystem() runs.
190 * See the comment in AcpiInstallAddressSpaceHandler().
191 * Default handlers for remaining address spaces are
192 * installed later, in AcpiEnableSubsystem.
193 */
194 static int
195 acpica_install_handlers()
196 {
197 ACPI_STATUS rv = AE_OK;
198
199 /*
200 * Install ACPI CA default handlers
201 */
202 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
203 ACPI_ADR_SPACE_SYSTEM_MEMORY,
204 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
205 cmn_err(CE_WARN, "!acpica: no default handler for"
206 " system memory");
207 rv = AE_ERROR;
208 }
209
210 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
211 ACPI_ADR_SPACE_SYSTEM_IO,
212 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
213 cmn_err(CE_WARN, "!acpica: no default handler for"
214 " system I/O");
215 rv = AE_ERROR;
216 }
217
218 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
219 ACPI_ADR_SPACE_PCI_CONFIG,
220 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
221 cmn_err(CE_WARN, "!acpica: no default handler for"
222 " PCI Config");
223 rv = AE_ERROR;
224 }
225
226 if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
227 ACPI_ADR_SPACE_DATA_TABLE,
228 ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
229 cmn_err(CE_WARN, "!acpica: no default handler for"
230 " Data Table");
231 rv = AE_ERROR;
232 }
233
234 return (rv);
235 }
236
237 /*
238 * Find the BIOS date, and return TRUE if supplied
239 * date is same or later than the BIOS date, or FALSE
240 * if the BIOS date can't be fetched for any reason
241 */
242 static int
243 acpica_check_bios_date(int yy, int mm, int dd)
244 {
245
246 char *datep;
247 int bios_year, bios_month, bios_day;
248
249 /* If firmware has no bios, skip the check */
250 if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS,
251 "bios-free"))
252 return (TRUE);
253
254 /*
255 * PC BIOSes contain a string in the form of
256 * "mm/dd/yy" at absolute address 0xffff5,
257 * where mm, dd and yy are all ASCII digits.
258 * We map the string, pluck out the values,
259 * and accept all BIOSes from 1 Jan 1999 on
260 * as valid.
261 */
262
263 if ((datep = (char *)AcpiOsMapMemory(0xffff5, 8)) == NULL)
264 return (FALSE);
265
266 /* year */
267 bios_year = ((int)(*(datep + 6) - '0') * 10) + (*(datep + 7) - '0');
268 /* month */
269 bios_month = ((int)(*datep - '0') * 10) + (*(datep + 1) - '0');
270 /* day */
271 bios_day = ((int)(*(datep + 3) - '0') * 10) + (*(datep + 4) - '0');
272
273 AcpiOsUnmapMemory((void *) datep, 8);
274
275 if (bios_year < 0 || bios_year > 99 || bios_month < 0 ||
276 bios_month > 99 || bios_day < 0 || bios_day > 99) {
277 /* non-digit chars in BIOS date */
278 return (FALSE);
279 }
280
281 /*
282 * Adjust for 2-digit year; note to grand-children:
283 * need a new scheme before 2080 rolls around
284 */
285 bios_year += (bios_year >= 80 && bios_year <= 99) ?
286 1900 : 2000;
287
288 if (bios_year < yy)
289 return (FALSE);
290 else if (bios_year > yy)
291 return (TRUE);
292
293 if (bios_month < mm)
294 return (FALSE);
295 else if (bios_month > mm)
296 return (TRUE);
297
298 if (bios_day < dd)
299 return (FALSE);
300
301 return (TRUE);
302 }
303
304 /*
305 * Check for Metropolis systems with BIOSes older than 10/12/04
306 * return TRUE if BIOS requires legacy mode, FALSE otherwise
307 */
308 static int
309 acpica_metro_old_bios()
310 {
311 ACPI_TABLE_HEADER *fadt;
312
313 /* get the FADT */
314 if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) !=
315 AE_OK)
316 return (FALSE);
317
318 /* compare OEM Table ID to "SUNmetro" - no match, return false */
319 if (strncmp("SUNmetro", fadt->OemTableId, 8))
320 return (FALSE);
321
322 /* On a Metro - return FALSE if later than 10/12/04 */
323 return (!acpica_check_bios_date(2004, 10, 12));
324 }
325
326
327 /*
328 * Process acpi-user-options property if present
329 */
330 static void
331 acpica_process_user_options()
332 {
333 static int processed = 0;
334 int acpi_user_options;
335 char *acpi_prop;
336
337 /*
338 * return if acpi-user-options has already been processed
339 */
340 if (processed)
341 return;
342 else
343 processed = 1;
344
345 /* converts acpi-user-options from type string to int, if any */
346 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
347 DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) ==
348 DDI_PROP_SUCCESS) {
349 long data;
350 int ret;
351 ret = ddi_strtol(acpi_prop, NULL, 0, &data);
352 if (ret == 0) {
353 e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(),
354 "acpi-user-options");
355 e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(),
356 "acpi-user-options", data);
357 }
358 ddi_prop_free(acpi_prop);
359 }
360
361 /*
362 * fetch the optional options property
363 */
364 acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(),
365 DDI_PROP_DONTPASS, "acpi-user-options", 0);
366
367 /*
368 * Note that 'off' has precedence over 'on'
369 * Also note - all cases of ACPI_OUSER_MASK
370 * provided here, no default: case is present
371 */
372 switch (acpi_user_options & ACPI_OUSER_MASK) {
373 case ACPI_OUSER_DFLT:
374 acpica_enable = acpica_check_bios_date(1999, 1, 1);
375 break;
376 case ACPI_OUSER_ON:
377 acpica_enable = TRUE;
378 break;
379 case ACPI_OUSER_OFF:
380 case ACPI_OUSER_OFF | ACPI_OUSER_ON:
381 acpica_enable = FALSE;
382 break;
383 }
384
385 acpi_init_level = ACPI_FULL_INITIALIZATION;
386
387 /*
388 * special test here; may be generalized in the
389 * future - test for a machines that are known to
390 * work only in legacy mode, and set OUSER_LEGACY if
391 * we're on one
392 */
393 if (acpica_metro_old_bios())
394 acpi_user_options |= ACPI_OUSER_LEGACY;
395
396 /*
397 * If legacy mode is specified, set initialization
398 * options to avoid entering ACPI mode and hooking SCI
399 * - basically try to act like legacy acpi_intp
400 */
401 if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0)
402 acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT);
403
404 /*
405 * modify default ACPI CA debug output level for non-DEBUG builds
406 * (to avoid BIOS debug chatter in /var/adm/messages)
407 */
408 if (acpica_muzzle_debug_output) {
409 AcpiDbgLayer = 0;
410 AcpiDbgLevel = 0;
411 }
412 }
413
414 /*
415 * Initialize the CA subsystem if it hasn't been done already
416 */
417 int
418 acpica_init()
419 {
420 extern void acpica_find_ioapics(void);
421 ACPI_STATUS status;
422
423 /*
424 * Make sure user options are processed,
425 * then fail to initialize if ACPI CA has been
426 * disabled
427 */
428 acpica_process_user_options();
429 if (!acpica_enable)
430 return (AE_ERROR);
431
432 mutex_enter(&acpica_module_lock);
433 if (acpica_init_state == ACPICA_INITIALIZED) {
434 mutex_exit(&acpica_module_lock);
435 return (AE_OK);
436 }
437
438 if (ACPI_FAILURE(status = AcpiLoadTables()))
439 goto error;
440
441 if (ACPI_FAILURE(status = acpica_install_handlers()))
442 goto error;
443
444 /*
445 * Create ACPI-to-devinfo mapping now so _INI and _STA
446 * methods can access PCI config space when needed
447 */
448 scan_d2a_map();
449
450 if (ACPI_FAILURE(status = AcpiEnableSubsystem(acpi_init_level)))
451 goto error;
452
453 /* do after AcpiEnableSubsystem() so GPEs are initialized */
454 acpica_ec_init(); /* initialize EC if present */
455
456 /* This runs all device _STA and _INI methods. */
457 if (ACPI_FAILURE(status = AcpiInitializeObjects(0)))
458 goto error;
459
460 acpica_init_state = ACPICA_INITIALIZED;
461
462 /*
463 * [ACPI, sec. 4.4.1.1]
464 * As of ACPICA version 20101217 (December 2010), the _PRW methods
465 * (Power Resources for Wake) are no longer automatically executed
466 * as part of the ACPICA initialization. The OS must do this.
467 */
468 (void) AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
469 UINT32_MAX, acpica_init_PRW, NULL, NULL, NULL);
470 (void) AcpiUpdateAllGpes();
471
472 /*
473 * If we are running on the Xen hypervisor as dom0 we need to
474 * find the ioapics so we can prevent ACPI from trying to
475 * access them.
476 */
477 if (get_hwenv() == HW_XEN_PV && is_controldom())
478 acpica_find_ioapics();
479 acpica_init_kstats();
480 error:
481 if (acpica_init_state != ACPICA_INITIALIZED) {
482 cmn_err(CE_NOTE, "!failed to initialize ACPI services");
483 }
484
485 /*
486 * Set acpi-status to 13 if acpica has been initialized successfully.
487 * This indicates that acpica is up and running. This variable name
488 * and value were chosen in order to remain compatible with acpi_intp.
489 */
490 e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "acpi-status",
491 (ACPI_SUCCESS(status)) ? (ACPI_BOOT_INIT | ACPI_BOOT_ENABLE |
492 ACPI_BOOT_BOOTCONF) : 0);
493
494 /* Mark acpica subsystem as fully initialized. */
495 if (ACPI_SUCCESS(status) &&
496 acpi_init_level == ACPI_FULL_INITIALIZATION) {
497 acpica_set_core_feature(ACPI_FEATURE_FULL_INIT);
498 }
499
500 mutex_exit(&acpica_module_lock);
501 return (status);
502 }
503
504 /*
505 * SCI handling
506 */
507
508 ACPI_STATUS
509 acpica_get_sci(int *sci_irq, iflag_t *sci_flags)
510 {
511 ACPI_SUBTABLE_HEADER *ap;
512 ACPI_TABLE_MADT *mat;
513 ACPI_MADT_INTERRUPT_OVERRIDE *mio;
514 ACPI_TABLE_FADT *fadt;
515 int madt_seen, madt_size;
516
517
518 /*
519 * Make sure user options are processed,
520 * then return error if ACPI CA has been
521 * disabled or system is not running in ACPI
522 * and won't need/understand SCI
523 */
524 acpica_process_user_options();
525 if ((!acpica_enable) || (acpi_init_level & ACPI_NO_ACPI_ENABLE))
526 return (AE_ERROR);
527
528 /*
529 * according to Intel ACPI developers, SCI
530 * conforms to PCI bus conventions; level/low
531 * unless otherwise directed by overrides.
532 */
533 sci_flags->intr_el = INTR_EL_LEVEL;
534 sci_flags->intr_po = INTR_PO_ACTIVE_LOW;
535 sci_flags->bustype = BUS_PCI; /* we *do* conform to PCI */
536
537 /* get the SCI from the FADT */
538 if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) !=
539 AE_OK)
540 return (AE_ERROR);
541
542 *sci_irq = fadt->SciInterrupt;
543
544 /* search for ISOs that modify it */
545 /* if we don't find a MADT, that's OK; no ISOs then */
546 if (AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **) &mat) !=
547 AE_OK)
548 return (AE_OK);
549
550 ap = (ACPI_SUBTABLE_HEADER *) (mat + 1);
551 madt_size = mat->Header.Length;
552 madt_seen = sizeof (*mat);
553
554 while (madt_seen < madt_size) {
555 switch (ap->Type) {
556 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
557 mio = (ACPI_MADT_INTERRUPT_OVERRIDE *) ap;
558 if (mio->SourceIrq == *sci_irq) {
559 *sci_irq = mio->GlobalIrq;
560 sci_flags->intr_el = (mio->IntiFlags &
561 ACPI_MADT_TRIGGER_MASK) >> 2;
562 sci_flags->intr_po = mio->IntiFlags &
563 ACPI_MADT_POLARITY_MASK;
564 }
565 break;
566 }
567
568 /* advance to next entry */
569 madt_seen += ap->Length;
570 ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length);
571 }
572
573 /*
574 * One more check; if ISO said "conform", revert to default
575 */
576 if (sci_flags->intr_el == INTR_EL_CONFORM)
577 sci_flags->intr_el = INTR_EL_LEVEL;
578 if (sci_flags->intr_po == INTR_PO_CONFORM)
579 sci_flags->intr_po = INTR_PO_ACTIVE_LOW;
580
581 return (AE_OK);
582 }
583
584 /*
585 * Call-back function used for _PRW initialization. For every
586 * device node that has a _PRW method, evaluate, parse, and do
587 * AcpiSetupGpeForWake().
588 */
589 static ACPI_STATUS
590 acpica_init_PRW(
591 ACPI_HANDLE devhdl,
592 UINT32 depth,
593 void *ctxp,
594 void **rvpp)
595 {
596 ACPI_STATUS status;
597 ACPI_BUFFER prw_buf;
598 struct parsed_prw prw;
599
600 prw_buf.Pointer = NULL;
601 prw_buf.Length = ACPI_ALLOCATE_BUFFER;
602
603 /*
604 * Attempt to evaluate _PRW object.
605 * If no valid object is found, return quietly, since not all
606 * devices have _PRW objects.
607 */
608 status = AcpiEvaluateObject(devhdl, "_PRW", NULL, &prw_buf);
609 if (ACPI_FAILURE(status))
610 goto done;
611 status = acpica_parse_PRW(&prw_buf, &prw);
612 if (ACPI_FAILURE(status))
613 goto done;
614
615 (void) AcpiSetupGpeForWake(devhdl,
616 prw.prw_gpeobj, prw.prw_gpebit);
617
618 done:
619 if (prw_buf.Pointer != NULL)
620 AcpiOsFree(prw_buf.Pointer);
621
622 return (AE_OK);
623 }
624
625 /*
626 * Sets ACPI wake state for device referenced by dip.
627 * If level is S0 (0), disables wake event; otherwise,
628 * enables wake event which will wake system from level.
629 */
630 static int
631 acpica_ddi_setwake(dev_info_t *dip, int level)
632 {
633 ACPI_STATUS status;
634 ACPI_HANDLE devobj;
635 ACPI_BUFFER prw_buf;
636 ACPI_OBJECT_LIST arglist;
637 ACPI_OBJECT args[3];
638 struct parsed_prw prw;
639 int rv;
640
641 /*
642 * initialize these early so we can use a common
643 * exit point below
644 */
645 prw_buf.Pointer = NULL;
646 prw_buf.Length = ACPI_ALLOCATE_BUFFER;
647 rv = 0;
648
649 /*
650 * Attempt to get a handle to a corresponding ACPI object.
651 * If no object is found, return quietly, since not all
652 * devices have corresponding ACPI objects.
653 */
654 status = acpica_get_handle(dip, &devobj);
655 if (ACPI_FAILURE(status)) {
656 char pathbuf[MAXPATHLEN];
657 ddi_pathname(dip, pathbuf);
658 #ifdef DEBUG
659 cmn_err(CE_NOTE, "!acpica_ddi_setwake: could not get"
660 " handle for %s, %s:%d", pathbuf, ddi_driver_name(dip),
661 ddi_get_instance(dip));
662 #endif
663 goto done;
664 }
665
666 /*
667 * ACPI3.0 7.2.1: only use the _PSW method if OSPM does not support
668 * _DSW or if the _DSW method is not present.
669 *
670 * _DSW arguments:
671 * args[0] - Enable/Disable
672 * args[1] - Target system state
673 * args[2] - Target device state
674 */
675
676 arglist.Count = 3;
677 arglist.Pointer = args;
678 args[0].Type = ACPI_TYPE_INTEGER;
679 args[0].Integer.Value = level ? 1 : 0;
680 args[1].Type = ACPI_TYPE_INTEGER;
681 args[1].Integer.Value = level;
682 args[2].Type = ACPI_TYPE_INTEGER;
683 args[2].Integer.Value = level;
684 if (ACPI_FAILURE(status = AcpiEvaluateObject(devobj, "_DSW",
685 &arglist, NULL))) {
686
687 if (status == AE_NOT_FOUND) {
688 arglist.Count = 1;
689 args[0].Type = ACPI_TYPE_INTEGER;
690 args[0].Integer.Value = level ? 1 : 0;
691
692 if (ACPI_FAILURE(status = AcpiEvaluateObject(devobj,
693 "_PSW", &arglist, NULL))) {
694
695 if (status != AE_NOT_FOUND) {
696 cmn_err(CE_NOTE,
697 "!_PSW failure %d for device %s",
698 status, ddi_driver_name(dip));
699 }
700 }
701
702 } else {
703 cmn_err(CE_NOTE, "!_DSW failure %d for device %s",
704 status, ddi_driver_name(dip));
705 }
706 }
707
708 /*
709 * Attempt to evaluate _PRW object.
710 * If no valid object is found, return quietly, since not all
711 * devices have _PRW objects.
712 */
713 status = AcpiEvaluateObject(devobj, "_PRW", NULL, &prw_buf);
714 if (ACPI_FAILURE(status))
715 goto done;
716 status = acpica_parse_PRW(&prw_buf, &prw);
717 if (ACPI_FAILURE(status))
718 goto done;
719
720 rv = -1;
721 if (level == 0) {
722 status = AcpiDisableGpe(prw.prw_gpeobj, prw.prw_gpebit);
723 if (ACPI_FAILURE(status))
724 goto done;
725 } else if (prw.prw_level >= level) {
726 status = AcpiSetGpeWakeMask(prw.prw_gpeobj, prw.prw_gpebit,
727 ACPI_GPE_ENABLE);
728 if (ACPI_SUCCESS(status)) {
729 status = AcpiEnableGpe(prw.prw_gpeobj, prw.prw_gpebit);
730 if (ACPI_FAILURE(status))
731 goto done;
732 }
733 }
734 rv = 0;
735 done:
736 if (prw_buf.Pointer != NULL)
737 AcpiOsFree(prw_buf.Pointer);
738 return (rv);
739 }
740
741 static ACPI_STATUS
742 acpica_parse_PRW(
743 ACPI_BUFFER *prw_buf,
744 struct parsed_prw *p_prw)
745 {
746 ACPI_HANDLE gpeobj;
747 ACPI_OBJECT *prw, *gpe;
748 int gpebit, prw_level;
749
750 if (prw_buf->Length == 0 || prw_buf->Pointer == NULL)
751 return (AE_NULL_OBJECT);
752
753 prw = prw_buf->Pointer;
754 if (prw->Type != ACPI_TYPE_PACKAGE || prw->Package.Count < 2 ||
755 prw->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
756 return (AE_TYPE);
757
758 /* fetch the lowest wake level from the _PRW */
759 prw_level = prw->Package.Elements[1].Integer.Value;
760
761 /*
762 * process the GPE description
763 */
764 switch (prw->Package.Elements[0].Type) {
765 case ACPI_TYPE_INTEGER:
766 gpeobj = NULL;
767 gpebit = prw->Package.Elements[0].Integer.Value;
768 break;
769 case ACPI_TYPE_PACKAGE:
770 gpe = &prw->Package.Elements[0];
771 if (gpe->Package.Count != 2 ||
772 gpe->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
773 return (AE_TYPE);
774 gpeobj = gpe->Package.Elements[0].Reference.Handle;
775 gpebit = gpe->Package.Elements[1].Integer.Value;
776 if (gpeobj == NULL)
777 return (AE_NULL_OBJECT);
778 break;
779 default:
780 return (AE_TYPE);
781 }
782
783 p_prw->prw_gpeobj = gpeobj;
784 p_prw->prw_gpebit = gpebit;
785 p_prw->prw_level = prw_level;
786
787 return (AE_OK);
788 }
789
790 /*
791 * kstat access to a limited set of ACPI propertis
792 */
793 static void
794 acpica_init_kstats()
795 {
796 ACPI_HANDLE s3handle;
797 ACPI_STATUS status;
798 ACPI_TABLE_FADT *fadt;
799 kstat_named_t *knp;
800
801 /*
802 * Create a small set of named kstats; just return in the rare
803 * case of a failure, * in which case, the kstats won't be present.
804 */
805 if ((acpica_ksp = kstat_create("acpi", 0, "acpi", "misc",
806 KSTAT_TYPE_NAMED, 2, 0)) == NULL)
807 return;
808
809 /*
810 * initialize kstat 'S3' to reflect the presence of \_S3 in
811 * the ACPI namespace (1 = present, 0 = not present)
812 */
813 knp = acpica_ksp->ks_data;
814 knp->value.l = (AcpiGetHandle(NULL, "\\_S3", &s3handle) == AE_OK);
815 kstat_named_init(knp, "S3", KSTAT_DATA_LONG);
816 knp++; /* advance to next named kstat */
817
818 /*
819 * initialize kstat 'preferred_pm_profile' to the value
820 * contained in the (always present) FADT
821 */
822 status = AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt);
823 knp->value.l = (status == AE_OK) ? fadt->PreferredProfile : -1;
824 kstat_named_init(knp, "preferred_pm_profile", KSTAT_DATA_LONG);
825
826 /*
827 * install the named kstats
828 */
829 kstat_install(acpica_ksp);
830 }
831
832 /*
833 * Attempt to save the current ACPI settings (_CRS) for the device
834 * which corresponds to the supplied devinfo node. The settings are
835 * saved as a property on the dip. If no ACPI object is found to be
836 * associated with the devinfo node, no action is taken and no error
837 * is reported.
838 */
839 void
840 acpica_ddi_save_resources(dev_info_t *dip)
841 {
842 ACPI_HANDLE devobj;
843 ACPI_BUFFER resbuf;
844 int ret;
845
846 resbuf.Length = ACPI_ALLOCATE_BUFFER;
847 if (ACPI_FAILURE(acpica_get_handle(dip, &devobj)) ||
848 ACPI_FAILURE(AcpiGetCurrentResources(devobj, &resbuf)))
849 return;
850
851 ret = ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
852 "acpi-crs", resbuf.Pointer, resbuf.Length);
853
854 ASSERT(ret == DDI_PROP_SUCCESS);
855
856 AcpiOsFree(resbuf.Pointer);
857 }
858
859 /*
860 * If the supplied devinfo node has an ACPI settings property attached,
861 * restore them to the associated ACPI device using _SRS. The property
862 * is deleted from the devinfo node afterward.
863 */
864 void
865 acpica_ddi_restore_resources(dev_info_t *dip)
866 {
867 ACPI_HANDLE devobj;
868 ACPI_BUFFER resbuf;
869 uchar_t *propdata;
870 uint_t proplen;
871
872 if (ACPI_FAILURE(acpica_get_handle(dip, &devobj)))
873 return;
874
875 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
876 "acpi-crs", &propdata, &proplen) != DDI_PROP_SUCCESS)
877 return;
878
879 resbuf.Pointer = propdata;
880 resbuf.Length = proplen;
881 (void) AcpiSetCurrentResources(devobj, &resbuf);
882 ddi_prop_free(propdata);
883 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "acpi-crs");
884 }
885
886 void
887 acpi_reset_system(void)
888 {
889 ACPI_STATUS status;
890 int ten;
891
892 status = AcpiReset();
893 if (status == AE_OK) {
894 /*
895 * Wait up to 500 milliseconds for AcpiReset() to make its
896 * way.
897 */
898 ten = 50000;
899 while (ten-- > 0)
900 tenmicrosec();
901 }
902 }