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