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