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