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