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