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