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