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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * ACPI CA OSL for Solaris x86 28 */ 29 30 #include <sys/types.h> 31 #include <sys/kmem.h> 32 #include <sys/psm.h> 33 #include <sys/pci_cfgspace.h> 34 #include <sys/ddi.h> 35 #include <sys/sunndi.h> 36 #include <sys/pci.h> 37 #include <sys/kobj.h> 38 #include <sys/taskq.h> 39 #include <sys/strlog.h> 40 #include <sys/note.h> 41 42 #include <sys/acpi/acpi.h> 43 #include <sys/acpica.h> 44 #include <sys/acpi/acinterp.h> 45 46 #define MAX_DAT_FILE_SIZE (64*1024) 47 48 /* local functions */ 49 static int CompressEisaID(char *np); 50 51 static void scan_d2a_map(void); 52 static void scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus); 53 static void acpica_tag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj); 54 55 static int acpica_query_bbn_problem(void); 56 static int acpica_find_pcibus(int busno, ACPI_HANDLE *rh); 57 static int acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint); 58 static ACPI_STATUS acpica_set_devinfo(ACPI_HANDLE, dev_info_t *); 59 static void acpica_devinfo_handler(ACPI_HANDLE, UINT32, void *); 60 61 /* 62 * Event queue vars 63 */ 64 int acpica_eventq_init = 0; 65 ddi_taskq_t *osl_eventq[OSL_EC_BURST_HANDLER+1]; 66 67 /* 68 * Priorities relative to minclsyspri that each taskq 69 * run at; OSL_NOTIFY_HANDLER needs to run at a higher 70 * priority than OSL_GPE_HANDLER. There's an implicit 71 * assumption that no priority here results in exceeding 72 * maxclsyspri. 73 * Note: these initializations need to match the order of 74 * ACPI_EXECUTE_TYPE. 75 */ 76 int osl_eventq_pri_delta[OSL_EC_BURST_HANDLER+1] = { 77 0, /* OSL_GLOBAL_LOCK_HANDLER */ 78 2, /* OSL_NOTIFY_HANDLER */ 79 0, /* OSL_GPE_HANDLER */ 80 0, /* OSL_DEBUGGER_THREAD */ 81 0, /* OSL_EC_POLL_HANDLER */ 82 0 /* OSL_EC_BURST_HANDLER */ 83 }; 84 85 /* 86 * Note, if you change this path, you need to update 87 * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386 88 */ 89 static char *acpi_table_path = "/boot/acpi/tables/"; 90 91 /* non-zero while scan_d2a_map() is working */ 92 static int scanning_d2a_map = 0; 93 static int d2a_done = 0; 94 95 /* set by acpi_poweroff() in PSMs and appm_ioctl() in acpippm for S3 */ 96 int acpica_use_safe_delay = 0; 97 98 /* CPU mapping data */ 99 struct cpu_map_item { 100 UINT32 proc_id; 101 ACPI_HANDLE obj; 102 }; 103 104 static struct cpu_map_item **cpu_map = NULL; 105 static int cpu_map_count = 0; 106 static int cpu_map_built = 0; 107 108 static int acpi_has_broken_bbn = -1; 109 110 /* buffer for AcpiOsVprintf() */ 111 #define ACPI_OSL_PR_BUFLEN 1024 112 static char *acpi_osl_pr_buffer = NULL; 113 static int acpi_osl_pr_buflen; 114 115 #define D2A_DEBUG 116 117 /* 118 * 119 */ 120 static void 121 discard_event_queues() 122 { 123 int i; 124 125 /* 126 * destroy event queues 127 */ 128 for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) { 129 if (osl_eventq[i]) 130 ddi_taskq_destroy(osl_eventq[i]); 131 } 132 } 133 134 135 /* 136 * 137 */ 138 static ACPI_STATUS 139 init_event_queues() 140 { 141 char namebuf[32]; 142 int i, error = 0; 143 144 /* 145 * Initialize event queues 146 */ 147 148 /* Always allocate only 1 thread per queue to force FIFO execution */ 149 for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) { 150 snprintf(namebuf, 32, "ACPI%d", i); 151 osl_eventq[i] = ddi_taskq_create(NULL, namebuf, 1, 152 osl_eventq_pri_delta[i] + minclsyspri, 0); 153 if (osl_eventq[i] == NULL) 154 error++; 155 } 156 157 if (error != 0) { 158 discard_event_queues(); 159 #ifdef DEBUG 160 cmn_err(CE_WARN, "!acpica: could not initialize event queues"); 161 #endif 162 return (AE_ERROR); 163 } 164 165 acpica_eventq_init = 1; 166 return (AE_OK); 167 } 168 169 /* 170 * One-time initialization of OSL layer 171 */ 172 ACPI_STATUS 173 AcpiOsInitialize(void) 174 { 175 /* 176 * Allocate buffer for AcpiOsVprintf() here to avoid 177 * kmem_alloc()/kmem_free() at high PIL 178 */ 179 acpi_osl_pr_buffer = kmem_alloc(ACPI_OSL_PR_BUFLEN, KM_SLEEP); 180 if (acpi_osl_pr_buffer != NULL) 181 acpi_osl_pr_buflen = ACPI_OSL_PR_BUFLEN; 182 183 return (AE_OK); 184 } 185 186 /* 187 * One-time shut-down of OSL layer 188 */ 189 ACPI_STATUS 190 AcpiOsTerminate(void) 191 { 192 193 if (acpi_osl_pr_buffer != NULL) 194 kmem_free(acpi_osl_pr_buffer, acpi_osl_pr_buflen); 195 196 discard_event_queues(); 197 return (AE_OK); 198 } 199 200 201 ACPI_PHYSICAL_ADDRESS 202 AcpiOsGetRootPointer() 203 { 204 ACPI_PHYSICAL_ADDRESS Address; 205 206 /* 207 * For EFI firmware, the root pointer is defined in EFI systab. 208 * The boot code process the table and put the physical address 209 * in the acpi-root-tab property. 210 */ 211 Address = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0, 212 "acpi-root-tab", NULL); 213 214 if ((Address == NULL) && ACPI_FAILURE(AcpiFindRootPointer(&Address))) 215 Address = NULL; 216 217 return (Address); 218 } 219 220 /*ARGSUSED*/ 221 ACPI_STATUS 222 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *InitVal, 223 ACPI_STRING *NewVal) 224 { 225 226 *NewVal = 0; 227 return (AE_OK); 228 } 229 230 static void 231 acpica_strncpy(char *dest, const char *src, int len) 232 { 233 234 /*LINTED*/ 235 while ((*dest++ = *src++) && (--len > 0)) 236 /* copy the string */; 237 *dest = '\0'; 238 } 239 240 ACPI_STATUS 241 AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable, 242 ACPI_TABLE_HEADER **NewTable) 243 { 244 char signature[5]; 245 char oemid[7]; 246 char oemtableid[9]; 247 struct _buf *file; 248 char *buf1, *buf2; 249 int count; 250 char acpi_table_loc[128]; 251 252 acpica_strncpy(signature, ExistingTable->Signature, 4); 253 acpica_strncpy(oemid, ExistingTable->OemId, 6); 254 acpica_strncpy(oemtableid, ExistingTable->OemTableId, 8); 255 256 #ifdef DEBUG 257 cmn_err(CE_NOTE, "!acpica: table [%s] v%d OEM ID [%s]" 258 " OEM TABLE ID [%s] OEM rev %x", 259 signature, ExistingTable->Revision, oemid, oemtableid, 260 ExistingTable->OemRevision); 261 #endif 262 263 /* File name format is "signature_oemid_oemtableid.dat" */ 264 (void) strcpy(acpi_table_loc, acpi_table_path); 265 (void) strcat(acpi_table_loc, signature); /* for example, DSDT */ 266 (void) strcat(acpi_table_loc, "_"); 267 (void) strcat(acpi_table_loc, oemid); /* for example, IntelR */ 268 (void) strcat(acpi_table_loc, "_"); 269 (void) strcat(acpi_table_loc, oemtableid); /* for example, AWRDACPI */ 270 (void) strcat(acpi_table_loc, ".dat"); 271 272 file = kobj_open_file(acpi_table_loc); 273 if (file == (struct _buf *)-1) { 274 *NewTable = 0; 275 return (AE_OK); 276 } else { 277 buf1 = (char *)kmem_alloc(MAX_DAT_FILE_SIZE, KM_SLEEP); 278 count = kobj_read_file(file, buf1, MAX_DAT_FILE_SIZE-1, 0); 279 if (count >= MAX_DAT_FILE_SIZE) { 280 cmn_err(CE_WARN, "!acpica: table %s file size too big", 281 acpi_table_loc); 282 *NewTable = 0; 283 } else { 284 buf2 = (char *)kmem_alloc(count, KM_SLEEP); 285 (void) memcpy(buf2, buf1, count); 286 *NewTable = (ACPI_TABLE_HEADER *)buf2; 287 cmn_err(CE_NOTE, "!acpica: replacing table: %s", 288 acpi_table_loc); 289 } 290 } 291 kobj_close_file(file); 292 kmem_free(buf1, MAX_DAT_FILE_SIZE); 293 294 return (AE_OK); 295 } 296 297 298 /* 299 * ACPI semaphore implementation 300 */ 301 typedef struct { 302 kmutex_t mutex; 303 kcondvar_t cv; 304 uint32_t available; 305 uint32_t initial; 306 uint32_t maximum; 307 } acpi_sema_t; 308 309 /* 310 * 311 */ 312 void 313 acpi_sema_init(acpi_sema_t *sp, unsigned max, unsigned count) 314 { 315 mutex_init(&sp->mutex, NULL, MUTEX_DRIVER, NULL); 316 cv_init(&sp->cv, NULL, CV_DRIVER, NULL); 317 /* no need to enter mutex here at creation */ 318 sp->available = count; 319 sp->initial = count; 320 sp->maximum = max; 321 } 322 323 /* 324 * 325 */ 326 void 327 acpi_sema_destroy(acpi_sema_t *sp) 328 { 329 330 cv_destroy(&sp->cv); 331 mutex_destroy(&sp->mutex); 332 } 333 334 /* 335 * 336 */ 337 ACPI_STATUS 338 acpi_sema_p(acpi_sema_t *sp, unsigned count, uint16_t wait_time) 339 { 340 ACPI_STATUS rv = AE_OK; 341 clock_t deadline; 342 343 mutex_enter(&sp->mutex); 344 345 if (sp->available >= count) { 346 /* 347 * Enough units available, no blocking 348 */ 349 sp->available -= count; 350 mutex_exit(&sp->mutex); 351 return (rv); 352 } else if (wait_time == 0) { 353 /* 354 * Not enough units available and timeout 355 * specifies no blocking 356 */ 357 rv = AE_TIME; 358 mutex_exit(&sp->mutex); 359 return (rv); 360 } 361 362 /* 363 * Not enough units available and timeout specifies waiting 364 */ 365 if (wait_time != ACPI_WAIT_FOREVER) 366 deadline = ddi_get_lbolt() + 367 (clock_t)drv_usectohz(wait_time * 1000); 368 369 do { 370 if (wait_time == ACPI_WAIT_FOREVER) 371 cv_wait(&sp->cv, &sp->mutex); 372 else if (cv_timedwait(&sp->cv, &sp->mutex, deadline) < 0) { 373 rv = AE_TIME; 374 break; 375 } 376 } while (sp->available < count); 377 378 /* if we dropped out of the wait with AE_OK, we got the units */ 379 if (rv == AE_OK) 380 sp->available -= count; 381 382 mutex_exit(&sp->mutex); 383 return (rv); 384 } 385 386 /* 387 * 388 */ 389 void 390 acpi_sema_v(acpi_sema_t *sp, unsigned count) 391 { 392 mutex_enter(&sp->mutex); 393 sp->available += count; 394 cv_broadcast(&sp->cv); 395 mutex_exit(&sp->mutex); 396 } 397 398 399 ACPI_STATUS 400 AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, 401 ACPI_HANDLE *OutHandle) 402 { 403 acpi_sema_t *sp; 404 405 if ((OutHandle == NULL) || (InitialUnits > MaxUnits)) 406 return (AE_BAD_PARAMETER); 407 408 sp = (acpi_sema_t *)kmem_alloc(sizeof (acpi_sema_t), KM_SLEEP); 409 acpi_sema_init(sp, MaxUnits, InitialUnits); 410 *OutHandle = (ACPI_HANDLE)sp; 411 return (AE_OK); 412 } 413 414 415 ACPI_STATUS 416 AcpiOsDeleteSemaphore(ACPI_HANDLE Handle) 417 { 418 419 if (Handle == NULL) 420 return (AE_BAD_PARAMETER); 421 422 acpi_sema_destroy((acpi_sema_t *)Handle); 423 kmem_free((void *)Handle, sizeof (acpi_sema_t)); 424 return (AE_OK); 425 } 426 427 ACPI_STATUS 428 AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout) 429 { 430 431 if ((Handle == NULL) || (Units < 1)) 432 return (AE_BAD_PARAMETER); 433 434 return (acpi_sema_p((acpi_sema_t *)Handle, Units, Timeout)); 435 } 436 437 ACPI_STATUS 438 AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units) 439 { 440 441 if ((Handle == NULL) || (Units < 1)) 442 return (AE_BAD_PARAMETER); 443 444 acpi_sema_v((acpi_sema_t *)Handle, Units); 445 return (AE_OK); 446 } 447 448 ACPI_STATUS 449 AcpiOsCreateLock(ACPI_HANDLE *OutHandle) 450 { 451 kmutex_t *mp; 452 453 if (OutHandle == NULL) 454 return (AE_BAD_PARAMETER); 455 456 mp = (kmutex_t *)kmem_alloc(sizeof (kmutex_t), KM_SLEEP); 457 mutex_init(mp, NULL, MUTEX_DRIVER, NULL); 458 *OutHandle = (ACPI_HANDLE)mp; 459 return (AE_OK); 460 } 461 462 void 463 AcpiOsDeleteLock(ACPI_HANDLE Handle) 464 { 465 466 if (Handle == NULL) 467 return; 468 469 mutex_destroy((kmutex_t *)Handle); 470 kmem_free((void *)Handle, sizeof (kmutex_t)); 471 } 472 473 ACPI_CPU_FLAGS 474 AcpiOsAcquireLock(ACPI_HANDLE Handle) 475 { 476 477 mutex_enter((kmutex_t *)Handle); 478 return (0); 479 } 480 481 void 482 AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_CPU_FLAGS Flags) 483 { 484 _NOTE(ARGUNUSED(Flags)) 485 486 mutex_exit((kmutex_t *)Handle); 487 } 488 489 490 void * 491 AcpiOsAllocate(ACPI_SIZE Size) 492 { 493 ACPI_SIZE *tmp_ptr; 494 495 Size += sizeof (Size); 496 tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP); 497 *tmp_ptr++ = Size; 498 return (tmp_ptr); 499 } 500 501 void 502 AcpiOsFree(void *Memory) 503 { 504 ACPI_SIZE size, *tmp_ptr; 505 506 tmp_ptr = (ACPI_SIZE *)Memory; 507 tmp_ptr -= 1; 508 size = *tmp_ptr; 509 kmem_free(tmp_ptr, size); 510 } 511 512 void * 513 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size) 514 { 515 /* FUTUREWORK: test PhysicalAddress for > 32 bits */ 516 return (psm_map_new((paddr_t)PhysicalAddress, 517 (size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ)); 518 } 519 520 void 521 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size) 522 { 523 524 psm_unmap((caddr_t)LogicalAddress, (size_t)Size); 525 } 526 527 /*ARGSUSED*/ 528 ACPI_STATUS 529 AcpiOsGetPhysicalAddress(void *LogicalAddress, 530 ACPI_PHYSICAL_ADDRESS *PhysicalAddress) 531 { 532 533 /* UNIMPLEMENTED: not invoked by ACPI CA code */ 534 return (AE_NOT_IMPLEMENTED); 535 } 536 537 538 ACPI_OSD_HANDLER acpi_isr; 539 void *acpi_isr_context; 540 541 uint_t 542 acpi_wrapper_isr(char *arg) 543 { 544 _NOTE(ARGUNUSED(arg)) 545 546 int status; 547 548 status = (*acpi_isr)(acpi_isr_context); 549 550 if (status == ACPI_INTERRUPT_HANDLED) { 551 return (DDI_INTR_CLAIMED); 552 } else { 553 return (DDI_INTR_UNCLAIMED); 554 } 555 } 556 557 static int acpi_intr_hooked = 0; 558 559 ACPI_STATUS 560 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber, 561 ACPI_OSD_HANDLER ServiceRoutine, 562 void *Context) 563 { 564 _NOTE(ARGUNUSED(InterruptNumber)) 565 566 int retval; 567 int sci_vect; 568 iflag_t sci_flags; 569 570 acpi_isr = ServiceRoutine; 571 acpi_isr_context = Context; 572 573 /* 574 * Get SCI (adjusted for PIC/APIC mode if necessary) 575 */ 576 if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) { 577 return (AE_ERROR); 578 } 579 580 #ifdef DEBUG 581 cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect); 582 #endif 583 584 retval = add_avintr(NULL, SCI_IPL, (avfunc)acpi_wrapper_isr, 585 "ACPI SCI", sci_vect, NULL, NULL, NULL, NULL); 586 if (retval) { 587 acpi_intr_hooked = 1; 588 return (AE_OK); 589 } else 590 return (AE_BAD_PARAMETER); 591 } 592 593 ACPI_STATUS 594 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber, 595 ACPI_OSD_HANDLER ServiceRoutine) 596 { 597 _NOTE(ARGUNUSED(ServiceRoutine)) 598 599 #ifdef DEBUG 600 cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber); 601 #endif 602 if (acpi_intr_hooked) { 603 rem_avintr(NULL, LOCK_LEVEL - 1, (avfunc)acpi_wrapper_isr, 604 InterruptNumber); 605 acpi_intr_hooked = 0; 606 } 607 return (AE_OK); 608 } 609 610 611 ACPI_THREAD_ID 612 AcpiOsGetThreadId(void) 613 { 614 /* 615 * ACPI CA regards thread ID as an error, but it's valid 616 * on Solaris during kernel initialization. Thus, 1 is added 617 * to the kernel thread ID to avoid returning 0 618 */ 619 return (ddi_get_kt_did() + 1); 620 } 621 622 /* 623 * 624 */ 625 ACPI_STATUS 626 AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, 627 void *Context) 628 { 629 630 if (!acpica_eventq_init) { 631 /* 632 * Create taskqs for event handling 633 */ 634 if (init_event_queues() != AE_OK) 635 return (AE_ERROR); 636 } 637 638 if (ddi_taskq_dispatch(osl_eventq[Type], Function, Context, 639 DDI_NOSLEEP) == DDI_FAILURE) { 640 #ifdef DEBUG 641 cmn_err(CE_WARN, "!acpica: unable to dispatch event"); 642 #endif 643 return (AE_ERROR); 644 } 645 return (AE_OK); 646 647 } 648 649 void 650 AcpiOsSleep(ACPI_INTEGER Milliseconds) 651 { 652 /* 653 * During kernel startup, before the first tick interrupt 654 * has taken place, we can't call delay; very late in 655 * kernel shutdown or suspend/resume, clock interrupts 656 * are blocked, so delay doesn't work then either. 657 * So we busy wait if lbolt == 0 (kernel startup) 658 * or if acpica_use_safe_delay has been set to a 659 * non-zero value. 660 */ 661 if ((ddi_get_lbolt() == 0) || acpica_use_safe_delay) 662 drv_usecwait(Milliseconds * 1000); 663 else 664 delay(drv_usectohz(Milliseconds * 1000)); 665 } 666 667 void 668 AcpiOsStall(UINT32 Microseconds) 669 { 670 drv_usecwait(Microseconds); 671 } 672 673 674 /* 675 * Implementation of "Windows 2001" compatible I/O permission map 676 * 677 */ 678 #define OSL_IO_NONE (0) 679 #define OSL_IO_READ (1<<0) 680 #define OSL_IO_WRITE (1<<1) 681 #define OSL_IO_RW (OSL_IO_READ | OSL_IO_WRITE) 682 #define OSL_IO_TERM (1<<2) 683 #define OSL_IO_DEFAULT OSL_IO_RW 684 685 static struct io_perm { 686 ACPI_IO_ADDRESS low; 687 ACPI_IO_ADDRESS high; 688 uint8_t perm; 689 } osl_io_perm[] = { 690 { 0xcf8, 0xd00, OSL_IO_NONE | OSL_IO_TERM } 691 }; 692 693 694 /* 695 * 696 */ 697 static struct io_perm * 698 osl_io_find_perm(ACPI_IO_ADDRESS addr) 699 { 700 struct io_perm *p; 701 702 p = osl_io_perm; 703 while (p != NULL) { 704 if ((p->low <= addr) && (addr <= p->high)) 705 break; 706 p = (p->perm & OSL_IO_TERM) ? NULL : p+1; 707 } 708 709 return (p); 710 } 711 712 /* 713 * 714 */ 715 ACPI_STATUS 716 AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width) 717 { 718 struct io_perm *p; 719 720 /* verify permission */ 721 p = osl_io_find_perm(Address); 722 if (p && (p->perm & OSL_IO_READ) == 0) { 723 cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted", 724 (long)Address, Width); 725 *Value = 0xffffffff; 726 return (AE_ERROR); 727 } 728 729 switch (Width) { 730 case 8: 731 *Value = inb(Address); 732 break; 733 case 16: 734 *Value = inw(Address); 735 break; 736 case 32: 737 *Value = inl(Address); 738 break; 739 default: 740 cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed", 741 (long)Address, Width); 742 return (AE_BAD_PARAMETER); 743 } 744 return (AE_OK); 745 } 746 747 ACPI_STATUS 748 AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width) 749 { 750 struct io_perm *p; 751 752 /* verify permission */ 753 p = osl_io_find_perm(Address); 754 if (p && (p->perm & OSL_IO_WRITE) == 0) { 755 cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted", 756 (long)Address, Width); 757 return (AE_ERROR); 758 } 759 760 switch (Width) { 761 case 8: 762 outb(Address, Value); 763 break; 764 case 16: 765 outw(Address, Value); 766 break; 767 case 32: 768 outl(Address, Value); 769 break; 770 default: 771 cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed", 772 (long)Address, Width); 773 return (AE_BAD_PARAMETER); 774 } 775 return (AE_OK); 776 } 777 778 779 /* 780 * 781 */ 782 783 #define OSL_RW(ptr, val, type, rw) \ 784 { if (rw) *((type *)(ptr)) = *((type *) val); \ 785 else *((type *) val) = *((type *)(ptr)); } 786 787 788 static void 789 osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, 790 UINT32 Width, int write) 791 { 792 size_t maplen = Width / 8; 793 caddr_t ptr; 794 795 ptr = psm_map_new((paddr_t)Address, maplen, 796 PSM_PROT_WRITE | PSM_PROT_READ); 797 798 switch (maplen) { 799 case 1: 800 OSL_RW(ptr, Value, uint8_t, write); 801 break; 802 case 2: 803 OSL_RW(ptr, Value, uint16_t, write); 804 break; 805 case 4: 806 OSL_RW(ptr, Value, uint32_t, write); 807 break; 808 default: 809 cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d", 810 Width); 811 break; 812 } 813 814 psm_unmap(ptr, maplen); 815 } 816 817 ACPI_STATUS 818 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, 819 UINT32 *Value, UINT32 Width) 820 { 821 osl_rw_memory(Address, Value, Width, 0); 822 return (AE_OK); 823 } 824 825 ACPI_STATUS 826 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, 827 UINT32 Value, UINT32 Width) 828 { 829 osl_rw_memory(Address, &Value, Width, 1); 830 return (AE_OK); 831 } 832 833 834 ACPI_STATUS 835 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, 836 void *Value, UINT32 Width) 837 { 838 839 switch (Width) { 840 case 8: 841 *((UINT64 *)Value) = (UINT64)(*pci_getb_func) 842 (PciId->Bus, PciId->Device, PciId->Function, Register); 843 break; 844 case 16: 845 *((UINT64 *)Value) = (UINT64)(*pci_getw_func) 846 (PciId->Bus, PciId->Device, PciId->Function, Register); 847 break; 848 case 32: 849 *((UINT64 *)Value) = (UINT64)(*pci_getl_func) 850 (PciId->Bus, PciId->Device, PciId->Function, Register); 851 break; 852 case 64: 853 default: 854 cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed", 855 Register, Width); 856 return (AE_BAD_PARAMETER); 857 } 858 return (AE_OK); 859 } 860 861 /* 862 * 863 */ 864 int acpica_write_pci_config_ok = 1; 865 866 ACPI_STATUS 867 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, 868 ACPI_INTEGER Value, UINT32 Width) 869 { 870 871 if (!acpica_write_pci_config_ok) { 872 cmn_err(CE_NOTE, "!write to PCI cfg %x/%x/%x %x" 873 " %lx %d not permitted", PciId->Bus, PciId->Device, 874 PciId->Function, Register, (long)Value, Width); 875 return (AE_OK); 876 } 877 878 switch (Width) { 879 case 8: 880 (*pci_putb_func)(PciId->Bus, PciId->Device, PciId->Function, 881 Register, (uint8_t)Value); 882 break; 883 case 16: 884 (*pci_putw_func)(PciId->Bus, PciId->Device, PciId->Function, 885 Register, (uint16_t)Value); 886 break; 887 case 32: 888 (*pci_putl_func)(PciId->Bus, PciId->Device, PciId->Function, 889 Register, (uint32_t)Value); 890 break; 891 case 64: 892 default: 893 cmn_err(CE_WARN, "!AcpiOsWritePciConfiguration: %x %u failed", 894 Register, Width); 895 return (AE_BAD_PARAMETER); 896 } 897 return (AE_OK); 898 } 899 900 /* 901 * Called with ACPI_HANDLEs for both a PCI Config Space 902 * OpRegion and (what ACPI CA thinks is) the PCI device 903 * to which this ConfigSpace OpRegion belongs. Since 904 * ACPI CA depends on a valid _BBN object being present 905 * and this is not always true (one old x86 had broken _BBN), 906 * we go ahead and get the correct PCI bus number using the 907 * devinfo mapping (which compensates for broken _BBN). 908 * 909 * Default values for bus, segment, device and function are 910 * all 0 when ACPI CA can't figure them out. 911 * 912 * Some BIOSes implement _BBN() by reading PCI config space 913 * on bus #0 - which means that we'll recurse when we attempt 914 * to create the devinfo-to-ACPI map. If Derive is called during 915 * scan_d2a_map, we don't translate the bus # and return. 916 * 917 * We get the parent of the OpRegion, which must be a PCI 918 * node, fetch the associated devinfo node and snag the 919 * b/d/f from it. 920 */ 921 void 922 AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle, 923 ACPI_PCI_ID **PciId) 924 { 925 ACPI_HANDLE handle; 926 dev_info_t *dip; 927 int bus, device, func, devfn; 928 929 930 /* 931 * See above - avoid recursing during scanning_d2a_map. 932 */ 933 if (scanning_d2a_map) 934 return; 935 936 /* 937 * Get the OpRegion's parent 938 */ 939 if (AcpiGetParent(chandle, &handle) != AE_OK) 940 return; 941 942 /* 943 * If we've mapped the ACPI node to the devinfo 944 * tree, use the devinfo reg property 945 */ 946 if (acpica_get_devinfo(handle, &dip) == AE_OK) { 947 (void) acpica_get_bdf(dip, &bus, &device, &func); 948 (*PciId)->Bus = bus; 949 (*PciId)->Device = device; 950 (*PciId)->Function = func; 951 } else if (acpica_eval_int(handle, "_ADR", &devfn) == AE_OK) { 952 /* no devinfo node - just confirm the d/f */ 953 (*PciId)->Device = (devfn >> 16) & 0xFFFF; 954 (*PciId)->Function = devfn & 0xFFFF; 955 } 956 } 957 958 959 /*ARGSUSED*/ 960 BOOLEAN 961 AcpiOsReadable(void *Pointer, ACPI_SIZE Length) 962 { 963 964 /* Always says yes; all mapped memory assumed readable */ 965 return (1); 966 } 967 968 /*ARGSUSED*/ 969 BOOLEAN 970 AcpiOsWritable(void *Pointer, ACPI_SIZE Length) 971 { 972 973 /* Always says yes; all mapped memory assumed writable */ 974 return (1); 975 } 976 977 UINT64 978 AcpiOsGetTimer(void) 979 { 980 /* gethrtime() returns 1nS resolution; convert to 100nS granules */ 981 return ((gethrtime() + 50) / 100); 982 } 983 984 /*ARGSUSED*/ 985 ACPI_STATUS 986 AcpiOsValidateInterface(char *interface) 987 { 988 return (AE_SUPPORT); 989 } 990 991 /*ARGSUSED*/ 992 ACPI_STATUS 993 AcpiOsValidateAddress(UINT8 spaceid, ACPI_PHYSICAL_ADDRESS addr, 994 ACPI_SIZE length) 995 { 996 return (AE_OK); 997 } 998 999 ACPI_STATUS 1000 AcpiOsSignal(UINT32 Function, void *Info) 1001 { 1002 _NOTE(ARGUNUSED(Function, Info)) 1003 1004 /* FUTUREWORK: debugger support */ 1005 1006 cmn_err(CE_NOTE, "!OsSignal unimplemented"); 1007 return (AE_OK); 1008 } 1009 1010 void ACPI_INTERNAL_VAR_XFACE 1011 AcpiOsPrintf(const char *Format, ...) 1012 { 1013 va_list ap; 1014 1015 va_start(ap, Format); 1016 AcpiOsVprintf(Format, ap); 1017 va_end(ap); 1018 } 1019 1020 /* 1021 * When != 0, sends output to console 1022 * Patchable with kmdb or /etc/system. 1023 */ 1024 int acpica_console_out = 0; 1025 1026 #define ACPICA_OUTBUF_LEN 160 1027 char acpica_outbuf[ACPICA_OUTBUF_LEN]; 1028 int acpica_outbuf_offset; 1029 1030 /* 1031 * 1032 */ 1033 static void 1034 acpica_pr_buf(char *buf) 1035 { 1036 char c, *bufp, *outp; 1037 int out_remaining; 1038 1039 /* 1040 * copy the supplied buffer into the output buffer 1041 * when we hit a '\n' or overflow the output buffer, 1042 * output and reset the output buffer 1043 */ 1044 bufp = buf; 1045 outp = acpica_outbuf + acpica_outbuf_offset; 1046 out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1; 1047 while (c = *bufp++) { 1048 *outp++ = c; 1049 if (c == '\n' || --out_remaining == 0) { 1050 *outp = '\0'; 1051 if (acpica_console_out) 1052 printf(acpica_outbuf); 1053 else 1054 (void) strlog(0, 0, 0, 1055 SL_CONSOLE | SL_NOTE | SL_LOGONLY, 1056 acpica_outbuf); 1057 acpica_outbuf_offset = 0; 1058 outp = acpica_outbuf; 1059 out_remaining = ACPICA_OUTBUF_LEN - 1; 1060 } 1061 } 1062 1063 acpica_outbuf_offset = outp - acpica_outbuf; 1064 } 1065 1066 void 1067 AcpiOsVprintf(const char *Format, va_list Args) 1068 { 1069 1070 /* 1071 * If AcpiOsInitialize() failed to allocate a string buffer, 1072 * resort to vprintf(). 1073 */ 1074 if (acpi_osl_pr_buffer == NULL) { 1075 vprintf(Format, Args); 1076 return; 1077 } 1078 1079 /* 1080 * It is possible that a very long debug output statement will 1081 * be truncated; this is silently ignored. 1082 */ 1083 (void) vsnprintf(acpi_osl_pr_buffer, acpi_osl_pr_buflen, Format, Args); 1084 acpica_pr_buf(acpi_osl_pr_buffer); 1085 } 1086 1087 void 1088 AcpiOsRedirectOutput(void *Destination) 1089 { 1090 _NOTE(ARGUNUSED(Destination)) 1091 1092 /* FUTUREWORK: debugger support */ 1093 1094 #ifdef DEBUG 1095 cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called"); 1096 #endif 1097 } 1098 1099 1100 UINT32 1101 AcpiOsGetLine(char *Buffer) 1102 { 1103 _NOTE(ARGUNUSED(Buffer)) 1104 1105 /* FUTUREWORK: debugger support */ 1106 1107 return (0); 1108 } 1109 1110 1111 1112 1113 /* 1114 * Device tree binding 1115 */ 1116 1117 static int 1118 acpica_find_pcibus(int busno, ACPI_HANDLE *rh) 1119 { 1120 ACPI_HANDLE sbobj, busobj; 1121 int hid, bbn; 1122 1123 /* initialize static flag by querying ACPI namespace for bug */ 1124 if (acpi_has_broken_bbn == -1) 1125 acpi_has_broken_bbn = acpica_query_bbn_problem(); 1126 1127 busobj = NULL; 1128 AcpiGetHandle(NULL, "\\_SB", &sbobj); 1129 while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj, 1130 &busobj) == AE_OK) { 1131 if (acpica_eval_hid(busobj, "_HID", &hid) == AE_OK && 1132 (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS)) { 1133 if (acpi_has_broken_bbn) { 1134 ACPI_BUFFER rb; 1135 rb.Pointer = NULL; 1136 rb.Length = ACPI_ALLOCATE_BUFFER; 1137 1138 /* Decree _BBN == n from PCI<n> */ 1139 if (AcpiGetName(busobj, ACPI_SINGLE_NAME, &rb) 1140 != AE_OK) { 1141 return (AE_ERROR); 1142 } 1143 bbn = ((char *)rb.Pointer)[3] - '0'; 1144 AcpiOsFree(rb.Pointer); 1145 if (bbn == busno || busno == 0) { 1146 *rh = busobj; 1147 return (AE_OK); 1148 } 1149 } else { 1150 if (acpica_eval_int(busobj, "_BBN", &bbn) == 1151 AE_OK) { 1152 if (bbn == busno) { 1153 *rh = busobj; 1154 return (AE_OK); 1155 } 1156 } else if (busno == 0) { 1157 *rh = busobj; 1158 return (AE_OK); 1159 } 1160 } 1161 } 1162 } 1163 return (AE_ERROR); 1164 } 1165 1166 1167 /* 1168 * Look for ACPI problem where _BBN is zero for multiple PCI buses 1169 * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus() 1170 * below if it exists. 1171 */ 1172 static int 1173 acpica_query_bbn_problem(void) 1174 { 1175 ACPI_HANDLE sbobj, busobj; 1176 int hid, bbn; 1177 int zerobbncnt; 1178 1179 busobj = NULL; 1180 zerobbncnt = 0; 1181 1182 AcpiGetHandle(NULL, "\\_SB", &sbobj); 1183 1184 while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj, 1185 &busobj) == AE_OK) { 1186 if ((acpica_eval_hid(busobj, "_HID", &hid) == AE_OK) && 1187 (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS) && 1188 (acpica_eval_int(busobj, "_BBN", &bbn) == AE_OK)) { 1189 if (bbn == 0) { 1190 /* 1191 * If we find more than one bus with a 0 _BBN 1192 * we have the problem that BigBear's BIOS shows 1193 */ 1194 if (++zerobbncnt > 1) 1195 return (1); 1196 } 1197 } 1198 } 1199 return (0); 1200 } 1201 1202 static const char hextab[] = "0123456789ABCDEF"; 1203 1204 static int 1205 hexdig(int c) 1206 { 1207 /* 1208 * Get hex digit: 1209 * 1210 * Returns the 4-bit hex digit named by the input character. Returns 1211 * zero if the input character is not valid hex! 1212 */ 1213 1214 int x = ((c < 'a') || (c > 'z')) ? c : (c - ' '); 1215 int j = sizeof (hextab); 1216 1217 while (--j && (x != hextab[j])) { 1218 } 1219 return (j); 1220 } 1221 1222 static int 1223 CompressEisaID(char *np) 1224 { 1225 /* 1226 * Compress an EISA device name: 1227 * 1228 * This routine converts a 7-byte ASCII device name into the 4-byte 1229 * compressed form used by EISA (50 bytes of ROM to save 1 byte of 1230 * NV-RAM!) 1231 */ 1232 1233 union { char octets[4]; int retval; } myu; 1234 1235 myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03); 1236 myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F); 1237 myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]); 1238 myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]); 1239 1240 return (myu.retval); 1241 } 1242 1243 ACPI_STATUS 1244 acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint) 1245 { 1246 ACPI_STATUS status; 1247 ACPI_BUFFER rb; 1248 ACPI_OBJECT ro; 1249 1250 rb.Pointer = &ro; 1251 rb.Length = sizeof (ro); 1252 if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb, 1253 ACPI_TYPE_INTEGER)) == AE_OK) 1254 *rint = ro.Integer.Value; 1255 1256 return (status); 1257 } 1258 1259 static int 1260 acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint) 1261 { 1262 ACPI_BUFFER rb; 1263 ACPI_OBJECT *rv; 1264 1265 rb.Pointer = NULL; 1266 rb.Length = ACPI_ALLOCATE_BUFFER; 1267 if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK && 1268 rb.Length != 0) { 1269 rv = rb.Pointer; 1270 if (rv->Type == ACPI_TYPE_INTEGER) { 1271 *rint = rv->Integer.Value; 1272 AcpiOsFree(rv); 1273 return (AE_OK); 1274 } else if (rv->Type == ACPI_TYPE_STRING) { 1275 char *stringData; 1276 1277 /* Convert the string into an EISA ID */ 1278 if (rv->String.Pointer == NULL) { 1279 AcpiOsFree(rv); 1280 return (AE_ERROR); 1281 } 1282 1283 stringData = rv->String.Pointer; 1284 1285 /* 1286 * If the string is an EisaID, it must be 7 1287 * characters; if it's an ACPI ID, it will be 8 1288 * (and we don't care about ACPI ids here). 1289 */ 1290 if (strlen(stringData) != 7) { 1291 AcpiOsFree(rv); 1292 return (AE_ERROR); 1293 } 1294 1295 *rint = CompressEisaID(stringData); 1296 AcpiOsFree(rv); 1297 return (AE_OK); 1298 } else 1299 AcpiOsFree(rv); 1300 } 1301 return (AE_ERROR); 1302 } 1303 1304 /* 1305 * Create linkage between devinfo nodes and ACPI nodes 1306 */ 1307 static void 1308 acpica_tag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj) 1309 { 1310 ACPI_STATUS status; 1311 ACPI_BUFFER rb; 1312 1313 /* 1314 * Tag the ACPI node with the dip 1315 */ 1316 status = acpica_set_devinfo(acpiobj, dip); 1317 ASSERT(status == AE_OK); 1318 1319 /* 1320 * Tag the devinfo node with the ACPI name 1321 */ 1322 rb.Pointer = NULL; 1323 rb.Length = ACPI_ALLOCATE_BUFFER; 1324 if (AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb) == AE_OK) { 1325 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 1326 "acpi-namespace", (char *)rb.Pointer); 1327 AcpiOsFree(rb.Pointer); 1328 } else { 1329 cmn_err(CE_WARN, "acpica: could not get ACPI path!"); 1330 } 1331 } 1332 1333 static void 1334 acpica_add_processor_to_map(UINT32 acpi_id, ACPI_HANDLE obj) 1335 { 1336 int cpu_id; 1337 1338 /* 1339 * Special case: if we're a uppc system, there won't be 1340 * a CPU map yet. So we create one and use the passed-in 1341 * processor as CPU 0 1342 */ 1343 if (cpu_map == NULL) { 1344 cpu_map = kmem_zalloc(sizeof (cpu_map[0]) * NCPU, KM_SLEEP); 1345 cpu_map[0] = kmem_zalloc(sizeof (*cpu_map[0]), KM_SLEEP); 1346 cpu_map[0]->obj = obj; 1347 cpu_map_count = 1; 1348 return; 1349 } 1350 1351 for (cpu_id = 0; cpu_id < NCPU; cpu_id++) { 1352 if (cpu_map[cpu_id] == NULL) 1353 continue; 1354 1355 if (cpu_map[cpu_id]->proc_id == acpi_id) { 1356 if (cpu_map[cpu_id]->obj == NULL) 1357 cpu_map[cpu_id]->obj = obj; 1358 break; 1359 } 1360 } 1361 1362 } 1363 1364 /* 1365 * Return the ACPI device node matching the CPU dev_info node. 1366 */ 1367 ACPI_STATUS 1368 acpica_get_handle_cpu(dev_info_t *dip, ACPI_HANDLE *rh) 1369 { 1370 char *device_type_prop; 1371 int cpu_id; 1372 1373 /* 1374 * if "device_type" != "cpu", error 1375 */ 1376 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 1377 "device_type", &device_type_prop) != DDI_PROP_SUCCESS) 1378 return (AE_ERROR); 1379 1380 if (strcmp("cpu", device_type_prop) != 0) { 1381 ddi_prop_free(device_type_prop); 1382 return (AE_ERROR); 1383 } 1384 ddi_prop_free(device_type_prop); 1385 1386 /* 1387 * if cpu_map itself is NULL, we're a uppc system and 1388 * acpica_build_processor_map() hasn't been called yet. 1389 * So call it here 1390 */ 1391 if (cpu_map == NULL) { 1392 (void) acpica_build_processor_map(); 1393 if (cpu_map == NULL) 1394 return (AE_ERROR); 1395 } 1396 1397 /* 1398 * get 'reg' and get obj from cpu_map 1399 */ 1400 cpu_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1401 "reg", -1); 1402 if ((cpu_id < 0) || (cpu_map[cpu_id] == NULL) || 1403 (cpu_map[cpu_id]->obj == NULL)) 1404 return (AE_ERROR); 1405 1406 /* 1407 * tag devinfo and obj 1408 */ 1409 (void) acpica_tag_devinfo(dip, cpu_map[cpu_id]->obj); 1410 *rh = cpu_map[cpu_id]->obj; 1411 return (AE_OK); 1412 } 1413 1414 /* 1415 * Convert CPU device _UID strings into unique integers 1416 * ACPI 3.0 spec 6.1.9 permits _UID to be either 1417 * an arbitrary string or numeric value. ACPI CA converts 1418 * numeric types to a string, providing a consistent API, 1419 * but it can not be assumed that _UID is always numeric. 1420 * Keep a private list of CPU _UIDs and convert them to 1421 * an integer representation. 1422 */ 1423 1424 struct acpica_cpu_uid { 1425 struct acpica_cpu_uid *next; 1426 char *uid; 1427 }; 1428 1429 static struct acpica_cpu_uid *acpica_cpu_uid_list = NULL; 1430 1431 static UINT32 1432 acpica_cpu_uid_str_to_uint(char *uidstr) 1433 { 1434 UINT32 n; 1435 struct acpica_cpu_uid *current, **tail; 1436 1437 ASSERT(uidstr != NULL); 1438 1439 n = 0; 1440 current = acpica_cpu_uid_list; 1441 tail = &acpica_cpu_uid_list; 1442 while (current != NULL) { 1443 if (strcmp(current->uid, uidstr) == 0) 1444 break; 1445 n++; 1446 tail = ¤t->next; 1447 current = current->next; 1448 } 1449 1450 /* 1451 * failed to find a matching element; create it here 1452 */ 1453 if (current == NULL) { 1454 /* allocate new list element as current one */ 1455 current = (struct acpica_cpu_uid *)kmem_zalloc( 1456 sizeof (struct acpica_cpu_uid), KM_SLEEP); 1457 1458 /* allocate storage for the device ID string */ 1459 current->uid = (char *)kmem_zalloc(strlen(uidstr) + 1, 1460 KM_SLEEP); 1461 1462 strcpy(current->uid, uidstr); 1463 *tail = current; 1464 } 1465 1466 /* 1467 * 'n' correctly contains the index for either 1468 * a new element or an existing element 1469 */ 1470 return (n); 1471 } 1472 1473 /* 1474 * Determine if this object is a processor 1475 */ 1476 static ACPI_STATUS 1477 acpica_probe_processor(ACPI_HANDLE obj, UINT32 level, void *ctx, void **rv) 1478 { 1479 ACPI_STATUS status; 1480 ACPI_OBJECT_TYPE objtype; 1481 UINT32 acpi_id; 1482 ACPI_BUFFER rb; 1483 1484 if (AcpiGetType(obj, &objtype) != AE_OK) 1485 return (AE_OK); 1486 1487 if (objtype == ACPI_TYPE_PROCESSOR) { 1488 /* process a Processor */ 1489 rb.Pointer = NULL; 1490 rb.Length = ACPI_ALLOCATE_BUFFER; 1491 status = AcpiEvaluateObjectTyped(obj, NULL, NULL, &rb, 1492 ACPI_TYPE_PROCESSOR); 1493 if (status != AE_OK) { 1494 cmn_err(CE_WARN, "acpica: error probing Processor"); 1495 return (status); 1496 } 1497 acpi_id = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId; 1498 AcpiOsFree(rb.Pointer); 1499 } else if (objtype == ACPI_TYPE_DEVICE) { 1500 /* process a processor Device */ 1501 rb.Pointer = NULL; 1502 rb.Length = ACPI_ALLOCATE_BUFFER; 1503 status = AcpiGetObjectInfo(obj, &rb); 1504 if (status != AE_OK) { 1505 cmn_err(CE_WARN, 1506 "acpica: error probing Processor Device\n"); 1507 return (status); 1508 } 1509 ASSERT(((ACPI_OBJECT *)rb.Pointer)->Type == 1510 ACPI_TYPE_DEVICE); 1511 acpi_id = acpica_cpu_uid_str_to_uint( 1512 ((ACPI_DEVICE_INFO *)rb.Pointer)->UniqueId.Value); 1513 AcpiOsFree(rb.Pointer); 1514 } 1515 1516 acpica_add_processor_to_map(acpi_id, obj); 1517 return (AE_OK); 1518 } 1519 1520 1521 static void 1522 scan_d2a_map(void) 1523 { 1524 dev_info_t *dip, *cdip; 1525 ACPI_HANDLE acpiobj; 1526 char *device_type_prop; 1527 int bus; 1528 static int map_error = 0; 1529 1530 if (map_error) 1531 return; 1532 1533 scanning_d2a_map = 1; 1534 1535 /* 1536 * Find all child-of-root PCI buses, and find their corresponding 1537 * ACPI child-of-root PCI nodes. For each one, add to the 1538 * d2a table. 1539 */ 1540 1541 for (dip = ddi_get_child(ddi_root_node()); 1542 dip != NULL; 1543 dip = ddi_get_next_sibling(dip)) { 1544 1545 /* prune non-PCI nodes */ 1546 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 1547 "device_type", &device_type_prop) != DDI_PROP_SUCCESS) 1548 continue; 1549 1550 if ((strcmp("pci", device_type_prop) != 0) && 1551 (strcmp("pciex", device_type_prop) != 0)) { 1552 ddi_prop_free(device_type_prop); 1553 continue; 1554 } 1555 1556 ddi_prop_free(device_type_prop); 1557 1558 /* 1559 * To get bus number of dip, get first child and get its 1560 * bus number. If NULL, just continue, because we don't 1561 * care about bus nodes with no children anyway. 1562 */ 1563 if ((cdip = ddi_get_child(dip)) == NULL) 1564 continue; 1565 1566 if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) { 1567 #ifdef D2ADEBUG 1568 cmn_err(CE_WARN, "Can't get bus number of PCI child?"); 1569 #endif 1570 map_error = 1; 1571 scanning_d2a_map = 0; 1572 d2a_done = 1; 1573 return; 1574 } 1575 1576 if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) { 1577 #ifdef D2ADEBUG 1578 cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus); 1579 #endif 1580 map_error = 1; 1581 continue; 1582 } 1583 1584 acpica_tag_devinfo(dip, acpiobj); 1585 1586 /* call recursively to enumerate subtrees */ 1587 scan_d2a_subtree(dip, acpiobj, bus); 1588 } 1589 1590 scanning_d2a_map = 0; 1591 d2a_done = 1; 1592 } 1593 1594 /* 1595 * For all acpi child devices of acpiobj, find their matching 1596 * dip under "dip" argument. (matching means "matches dev/fn"). 1597 * bus is assumed to already be a match from caller, and is 1598 * used here only to record in the d2a entry. Recurse if necessary. 1599 */ 1600 static void 1601 scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus) 1602 { 1603 int acpi_devfn, hid; 1604 ACPI_HANDLE acld; 1605 dev_info_t *dcld; 1606 int dcld_b, dcld_d, dcld_f; 1607 int dev, func; 1608 char *device_type_prop; 1609 1610 acld = NULL; 1611 while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld) 1612 == AE_OK) { 1613 /* get the dev/func we're looking for in the devinfo tree */ 1614 if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK) 1615 continue; 1616 dev = (acpi_devfn >> 16) & 0xFFFF; 1617 func = acpi_devfn & 0xFFFF; 1618 1619 /* look through all the immediate children of dip */ 1620 for (dcld = ddi_get_child(dip); dcld != NULL; 1621 dcld = ddi_get_next_sibling(dcld)) { 1622 if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0) 1623 continue; 1624 1625 /* dev must match; function must match or wildcard */ 1626 if (dcld_d != dev || 1627 (func != 0xFFFF && func != dcld_f)) 1628 continue; 1629 bus = dcld_b; 1630 1631 /* found a match, record it */ 1632 acpica_tag_devinfo(dcld, acld); 1633 1634 /* if we find a bridge, recurse from here */ 1635 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dcld, 0, 1636 "device_type", &device_type_prop) == 1637 DDI_PROP_SUCCESS) { 1638 if ((strcmp("pci", device_type_prop) == 0) || 1639 (strcmp("pciex", device_type_prop) == 0)) 1640 scan_d2a_subtree(dcld, acld, bus); 1641 ddi_prop_free(device_type_prop); 1642 } 1643 1644 /* done finding a match, so break now */ 1645 break; 1646 } 1647 } 1648 } 1649 1650 /* 1651 * Return bus/dev/fn for PCI dip (note: not the parent "pci" node). 1652 */ 1653 int 1654 acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func) 1655 { 1656 pci_regspec_t *pci_rp; 1657 int len; 1658 1659 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1660 "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS) 1661 return (-1); 1662 1663 if (len < (sizeof (pci_regspec_t) / sizeof (int))) { 1664 ddi_prop_free(pci_rp); 1665 return (-1); 1666 } 1667 if (bus != NULL) 1668 *bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi); 1669 if (device != NULL) 1670 *device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi); 1671 if (func != NULL) 1672 *func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 1673 ddi_prop_free(pci_rp); 1674 return (0); 1675 } 1676 1677 /* 1678 * Return the ACPI device node matching this dev_info node, if it 1679 * exists in the ACPI tree. 1680 */ 1681 ACPI_STATUS 1682 acpica_get_handle(dev_info_t *dip, ACPI_HANDLE *rh) 1683 { 1684 ACPI_STATUS status; 1685 char *acpiname; 1686 1687 if (!d2a_done) 1688 scan_d2a_map(); 1689 1690 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1691 "acpi-namespace", &acpiname) != DDI_PROP_SUCCESS) { 1692 return (acpica_get_handle_cpu(dip, rh)); 1693 } 1694 1695 status = AcpiGetHandle(NULL, acpiname, rh); 1696 ddi_prop_free((void *)acpiname); 1697 return (status); 1698 } 1699 1700 1701 1702 /* 1703 * Manage OS data attachment to ACPI nodes 1704 */ 1705 1706 /* 1707 * Return the (dev_info_t *) associated with the ACPI node. 1708 */ 1709 ACPI_STATUS 1710 acpica_get_devinfo(ACPI_HANDLE obj, dev_info_t **dipp) 1711 { 1712 ACPI_STATUS status; 1713 void *ptr; 1714 1715 status = AcpiGetData(obj, acpica_devinfo_handler, &ptr); 1716 if (status == AE_OK) 1717 *dipp = (dev_info_t *)ptr; 1718 1719 return (status); 1720 } 1721 1722 /* 1723 * Set the dev_info_t associated with the ACPI node. 1724 */ 1725 static ACPI_STATUS 1726 acpica_set_devinfo(ACPI_HANDLE obj, dev_info_t *dip) 1727 { 1728 ACPI_STATUS status; 1729 1730 status = AcpiAttachData(obj, acpica_devinfo_handler, (void *)dip); 1731 return (status); 1732 } 1733 1734 1735 /* 1736 * 1737 */ 1738 void 1739 acpica_devinfo_handler(ACPI_HANDLE obj, UINT32 func, void *data) 1740 { 1741 /* noop */ 1742 } 1743 1744 1745 /* 1746 * 1747 */ 1748 void 1749 acpica_map_cpu(processorid_t cpuid, UINT32 proc_id) 1750 { 1751 struct cpu_map_item *item; 1752 1753 if (cpu_map == NULL) 1754 cpu_map = kmem_zalloc(sizeof (item) * NCPU, KM_SLEEP); 1755 1756 item = kmem_zalloc(sizeof (*item), KM_SLEEP); 1757 item->proc_id = proc_id; 1758 item->obj = NULL; 1759 cpu_map[cpuid] = item; 1760 cpu_map_count++; 1761 } 1762 1763 void 1764 acpica_build_processor_map() 1765 { 1766 ACPI_STATUS status; 1767 void *rv; 1768 1769 /* 1770 * shouldn't be called more than once anyway 1771 */ 1772 if (cpu_map_built) 1773 return; 1774 1775 /* 1776 * Look for Processor objects 1777 */ 1778 status = AcpiWalkNamespace(ACPI_TYPE_PROCESSOR, 1779 ACPI_ROOT_OBJECT, 1780 4, 1781 acpica_probe_processor, 1782 NULL, 1783 &rv); 1784 ASSERT(status == AE_OK); 1785 1786 /* 1787 * Look for processor Device objects 1788 */ 1789 status = AcpiGetDevices("ACPI0007", 1790 acpica_probe_processor, 1791 NULL, 1792 &rv); 1793 ASSERT(status == AE_OK); 1794 cpu_map_built = 1; 1795 } 1796