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