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 2006 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, 818 PciId->Function, Register); 819 break; 820 case 16: 821 *((UINT64 *)Value) = (UINT64)(*pci_getw_func) 822 (PciId->Bus, PciId->Device, 823 PciId->Function, Register); 824 break; 825 case 32: 826 *((UINT64 *)Value) = (UINT64)(*pci_getl_func) 827 (PciId->Bus, PciId->Device, 828 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 * one 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 * create_d2a_map or with bus #0, we don't translate the bus # and 894 * return. 895 */ 896 void 897 AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle, 898 ACPI_PCI_ID **PciId) 899 { 900 ACPI_HANDLE handle; 901 d2a *d2ap; 902 int devfn; 903 904 905 /* 906 * See above - avoid recursing during create_d2a_map, 907 * and never translate bus# 0. 908 */ 909 if ((creating_d2a_map) || ((*PciId)->Bus == 0)) 910 return; 911 912 /* 913 * We start with the parent node of the OpRegion 914 * and ascend, looking for a matching dip2acpi 915 * node; once located, we use the bus from the d2a 916 * node and the device/function return from the _ADR 917 * method on the ACPI node. 918 * If we encounter any kind of failure, we just 919 * return, possibly after updating the bus value 920 * This is probably always better than nothing. 921 */ 922 if (AcpiGetParent(chandle, &handle) != AE_OK) 923 return; 924 925 while (handle != rhandle) { 926 if (acpica_find_pcid2a(handle, &d2ap) == AE_OK) { 927 (*PciId)->Bus = d2ap->bus; 928 if (acpica_eval_int(handle, "_ADR", &devfn) == AE_OK) { 929 (*PciId)->Device = (devfn >> 16) & 0xFFFF; 930 (*PciId)->Function = devfn & 0xFFFF; 931 } 932 break; 933 } 934 935 if (AcpiGetParent(handle, &handle) != AE_OK) 936 break; 937 } 938 } 939 940 941 /*ARGSUSED*/ 942 BOOLEAN 943 AcpiOsReadable(void *Pointer, ACPI_SIZE Length) 944 { 945 946 /* Always says yes; all mapped memory assumed readable */ 947 return (1); 948 } 949 950 /*ARGSUSED*/ 951 BOOLEAN 952 AcpiOsWritable(void *Pointer, ACPI_SIZE Length) 953 { 954 955 /* Always says yes; all mapped memory assumed writable */ 956 return (1); 957 } 958 959 UINT64 960 AcpiOsGetTimer(void) 961 { 962 /* gethrtime() returns 1nS resolution; convert to 100nS granules */ 963 return ((gethrtime() + 50) / 100); 964 } 965 966 /*ARGSUSED*/ 967 ACPI_STATUS 968 AcpiOsValidateInterface(char *interface) 969 { 970 return (AE_SUPPORT); 971 } 972 973 /*ARGSUSED*/ 974 ACPI_STATUS 975 AcpiOsValidateAddress(UINT8 spaceid, ACPI_PHYSICAL_ADDRESS addr, 976 ACPI_SIZE length) 977 { 978 return (AE_OK); 979 } 980 981 ACPI_STATUS 982 AcpiOsSignal(UINT32 Function, void *Info) 983 { 984 _NOTE(ARGUNUSED(Function, Info)) 985 986 /* FUTUREWORK: debugger support */ 987 988 cmn_err(CE_NOTE, "!OsSignal unimplemented"); 989 return (AE_OK); 990 } 991 992 void ACPI_INTERNAL_VAR_XFACE 993 AcpiOsPrintf(const char *Format, ...) 994 { 995 va_list ap; 996 997 va_start(ap, Format); 998 AcpiOsVprintf(Format, ap); 999 va_end(ap); 1000 } 1001 1002 /* 1003 * When != 0, sends output to console 1004 * Patchable with kmdb or /etc/system. 1005 */ 1006 int acpica_console_out = 0; 1007 1008 #define ACPICA_OUTBUF_LEN 160 1009 char acpica_outbuf[ACPICA_OUTBUF_LEN]; 1010 int acpica_outbuf_offset; 1011 1012 /* 1013 * 1014 */ 1015 static void 1016 acpica_pr_buf(char *buf, int buflen) 1017 { 1018 char c, *bufp, *outp; 1019 int out_remaining; 1020 1021 /* 1022 * copy the supplied buffer into the output buffer 1023 * when we hit a '\n' or overflow the output buffer, 1024 * output and reset the output buffer 1025 */ 1026 bufp = buf; 1027 outp = acpica_outbuf + acpica_outbuf_offset; 1028 out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1; 1029 while (c = *bufp++) { 1030 *outp++ = c; 1031 if (c == '\n' || --out_remaining == 0) { 1032 *outp = '\0'; 1033 if (acpica_console_out) 1034 printf(acpica_outbuf); 1035 else 1036 (void) strlog(0, 0, 0, 1037 SL_CONSOLE | SL_NOTE | SL_LOGONLY, 1038 acpica_outbuf); 1039 acpica_outbuf_offset = 0; 1040 outp = acpica_outbuf; 1041 out_remaining = ACPICA_OUTBUF_LEN - 1; 1042 } 1043 } 1044 1045 acpica_outbuf_offset = outp - acpica_outbuf; 1046 kmem_free(buf, buflen); 1047 } 1048 1049 void 1050 AcpiOsVprintf(const char *Format, va_list Args) 1051 { 1052 va_list save; 1053 int buflen; 1054 char *buf; 1055 1056 /* 1057 * Try to be nice and emit the message via strlog(). 1058 * Unfortunately, vstrlog() doesn't define the format 1059 * string as const char, so we allocate a local buffer 1060 * use vsnprintf(). 1061 * 1062 * If we fail to allocate a string buffer, we resort 1063 * to printf(). 1064 */ 1065 va_copy(save, Args); 1066 buflen = vsnprintf(NULL, 0, Format, save) + 1; 1067 buf = kmem_alloc(buflen, KM_NOSLEEP); 1068 if (buf == NULL) { 1069 vprintf(Format, Args); 1070 return; 1071 } 1072 (void) vsnprintf(buf, buflen, Format, Args); 1073 acpica_pr_buf(buf, buflen); 1074 } 1075 1076 void 1077 AcpiOsRedirectOutput(void *Destination) 1078 { 1079 _NOTE(ARGUNUSED(Destination)) 1080 1081 /* FUTUREWORK: debugger support */ 1082 1083 #ifdef DEBUG 1084 cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called"); 1085 #endif 1086 } 1087 1088 1089 UINT32 1090 AcpiOsGetLine(char *Buffer) 1091 { 1092 _NOTE(ARGUNUSED(Buffer)) 1093 1094 /* FUTUREWORK: debugger support */ 1095 1096 return (0); 1097 } 1098 1099 1100 1101 1102 /* 1103 * Device tree binding 1104 */ 1105 1106 static int 1107 acpica_find_pcibus(int busno, ACPI_HANDLE *rh) 1108 { 1109 ACPI_HANDLE sbobj, busobj; 1110 int hid, bbn; 1111 1112 /* initialize static flag by querying ACPI namespace for bug */ 1113 if (acpi_has_broken_bbn == -1) 1114 acpi_has_broken_bbn = acpica_query_bbn_problem(); 1115 1116 busobj = NULL; 1117 AcpiGetHandle(NULL, "\\_SB", &sbobj); 1118 while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj, 1119 &busobj) == AE_OK) { 1120 if (acpica_eval_hid(busobj, "_HID", &hid) == AE_OK && 1121 (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS)) { 1122 if (acpi_has_broken_bbn) { 1123 ACPI_BUFFER rb; 1124 rb.Pointer = NULL; 1125 rb.Length = ACPI_ALLOCATE_BUFFER; 1126 1127 /* Decree _BBN == n from PCI<n> */ 1128 if (AcpiGetName(busobj, ACPI_SINGLE_NAME, &rb) 1129 != AE_OK) { 1130 return (AE_ERROR); 1131 } 1132 bbn = ((char *)rb.Pointer)[3] - '0'; 1133 AcpiOsFree(rb.Pointer); 1134 if (bbn == busno || busno == 0) { 1135 *rh = busobj; 1136 return (AE_OK); 1137 } 1138 } else { 1139 if (acpica_eval_int(busobj, "_BBN", &bbn) == 1140 AE_OK) { 1141 if (bbn == busno) { 1142 *rh = busobj; 1143 return (AE_OK); 1144 } 1145 } else if (busno == 0) { 1146 *rh = busobj; 1147 return (AE_OK); 1148 } 1149 } 1150 } 1151 } 1152 return (AE_ERROR); 1153 } 1154 1155 1156 /* 1157 * Look for ACPI problem where _BBN is zero for multiple PCI buses 1158 * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus() 1159 * below if it exists. 1160 */ 1161 static int 1162 acpica_query_bbn_problem(void) 1163 { 1164 ACPI_HANDLE sbobj, busobj; 1165 int hid, bbn; 1166 int zerobbncnt; 1167 1168 busobj = NULL; 1169 zerobbncnt = 0; 1170 1171 AcpiGetHandle(NULL, "\\_SB", &sbobj); 1172 1173 while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj, 1174 &busobj) == AE_OK) { 1175 if ((acpica_eval_hid(busobj, "_HID", &hid) == AE_OK) && 1176 (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS) && 1177 (acpica_eval_int(busobj, "_BBN", &bbn) == AE_OK)) { 1178 if (bbn == 0) { 1179 /* 1180 * If we find more than one bus with a 0 _BBN 1181 * we have the problem that BigBear's BIOS shows 1182 */ 1183 if (++zerobbncnt > 1) 1184 return (1); 1185 } 1186 } 1187 } 1188 return (0); 1189 } 1190 1191 static const char hextab[] = "0123456789ABCDEF"; 1192 1193 static int 1194 hexdig(int c) 1195 { 1196 /* 1197 * Get hex digit: 1198 * 1199 * Returns the 4-bit hex digit named by the input character. Returns 1200 * zero if the input character is not valid hex! 1201 */ 1202 1203 int x = ((c < 'a') || (c > 'z')) ? c : (c - ' '); 1204 int j = sizeof (hextab); 1205 1206 while (--j && (x != hextab[j])); 1207 return (j); 1208 } 1209 1210 static int 1211 CompressEisaID(char *np) 1212 { 1213 /* 1214 * Compress an EISA device name: 1215 * 1216 * This routine converts a 7-byte ASCII device name into the 4-byte 1217 * compressed form used by EISA (50 bytes of ROM to save 1 byte of 1218 * NV-RAM!) 1219 */ 1220 1221 union { char octets[4]; int retval; } myu; 1222 1223 myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03); 1224 myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F); 1225 myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]); 1226 myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]); 1227 1228 return (myu.retval); 1229 } 1230 1231 int 1232 acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint) 1233 { 1234 ACPI_STATUS status; 1235 ACPI_BUFFER rb; 1236 ACPI_OBJECT ro; 1237 1238 rb.Pointer = &ro; 1239 rb.Length = sizeof (ro); 1240 if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb, 1241 ACPI_TYPE_INTEGER)) == AE_OK) 1242 *rint = ro.Integer.Value; 1243 1244 return (status); 1245 } 1246 1247 static int 1248 acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint) 1249 { 1250 ACPI_BUFFER rb; 1251 ACPI_OBJECT *rv; 1252 1253 rb.Pointer = NULL; 1254 rb.Length = ACPI_ALLOCATE_BUFFER; 1255 if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK) { 1256 rv = rb.Pointer; 1257 if (rv->Type == ACPI_TYPE_INTEGER) { 1258 *rint = rv->Integer.Value; 1259 AcpiOsFree(rv); 1260 return (AE_OK); 1261 } else if (rv->Type == ACPI_TYPE_STRING) { 1262 char *stringData; 1263 1264 /* Convert the string into an EISA ID */ 1265 if (rv->String.Pointer == NULL) { 1266 AcpiOsFree(rv); 1267 return (AE_ERROR); 1268 } 1269 1270 stringData = rv->String.Pointer; 1271 1272 /* 1273 * If the string is an EisaID, it must be 7 1274 * characters; if it's an ACPI ID, it will be 8 1275 * (and we don't care about ACPI ids here). 1276 */ 1277 if (strlen(stringData) != 7) { 1278 AcpiOsFree(rv); 1279 return (AE_ERROR); 1280 } 1281 1282 *rint = CompressEisaID(stringData); 1283 AcpiOsFree(rv); 1284 return (AE_OK); 1285 } else 1286 AcpiOsFree(rv); 1287 } 1288 return (AE_ERROR); 1289 } 1290 1291 /* 1292 * Return the d2a node matching this ACPI_HANDLE, if one exists 1293 */ 1294 int 1295 acpica_find_pcid2a(ACPI_HANDLE rh, d2a **dp) 1296 { 1297 d2a *d2ap; 1298 int i; 1299 1300 if (d2a_len == 0) 1301 create_d2a_map(); 1302 for (d2ap = d2a_table, i = 0; i < d2a_valid; d2ap++, i++) 1303 if (d2ap->acpiobj == rh) { 1304 *dp = d2ap; 1305 return (AE_OK); 1306 } 1307 1308 return (AE_ERROR); 1309 } 1310 1311 1312 /* 1313 * Return the ACPI device node matching this dev_info node, if it 1314 * exists in the ACPI tree. 1315 */ 1316 int 1317 acpica_find_pciobj(dev_info_t *dip, ACPI_HANDLE *rh) 1318 { 1319 d2a *d2ap; 1320 int i; 1321 1322 if (d2a_len == 0) 1323 create_d2a_map(); 1324 for (d2ap = d2a_table, i = 0; i < d2a_valid; d2ap++, i++) 1325 if (d2ap->dip == dip) { 1326 *rh = d2ap->acpiobj; 1327 return (AE_OK); 1328 } 1329 1330 return (AE_ERROR); 1331 } 1332 1333 /* 1334 * Create a table mapping PCI dips to ACPI objects 1335 */ 1336 static void 1337 new_d2a_entry(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus, int dev, int func) 1338 { 1339 int newsize; 1340 d2a *new_arr, *ep; 1341 1342 if (d2a_valid >= d2a_len) { 1343 /* initially, or re-, allocate array */ 1344 1345 newsize = (d2a_len ? d2a_len * 2 : D2A_INITLEN); 1346 new_arr = kmem_zalloc(newsize * sizeof (d2a), KM_SLEEP); 1347 if (d2a_len != 0) { 1348 /* realloc: copy data, free old */ 1349 bcopy(d2a_table, new_arr, d2a_len * sizeof (d2a)); 1350 kmem_free(d2a_table, d2a_len * sizeof (d2a)); 1351 } 1352 d2a_len = newsize; 1353 d2a_table = new_arr; 1354 } 1355 ep = &d2a_table[d2a_valid++]; 1356 ep->bus = (unsigned char)bus; 1357 ep->dev = (unsigned char)dev; 1358 ep->func = (unsigned char)func; 1359 ep->dip = dip; 1360 ep->acpiobj = acpiobj; 1361 #ifdef D2ADEBUG 1362 { 1363 ACPI_BUFFER rb; 1364 char pathname[60]; 1365 ddi_pathname(dip, pathname); 1366 1367 rb.Pointer = NULL; 1368 rb.Length = ACPI_ALLOCATE_BUFFER; 1369 if (AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb) == AE_OK) { 1370 1371 cmn_err(CE_NOTE, "d2a entry: %s %s %d/0x%x/%d", 1372 pathname, (char *)rb.Pointer, bus, dev, func); 1373 AcpiOsFree(rb.Pointer); 1374 } 1375 } 1376 #endif 1377 } 1378 1379 static void 1380 create_d2a_map(void) 1381 { 1382 dev_info_t *dip, *cdip; 1383 ACPI_HANDLE acpiobj; 1384 char *device_type_prop; 1385 int bus; 1386 static int map_error = 0; 1387 1388 if (map_error) 1389 return; 1390 1391 creating_d2a_map = 1; 1392 1393 /* 1394 * Find all child-of-root PCI buses, and find their corresponding 1395 * ACPI child-of-root PCI nodes. For each one, add to the 1396 * d2a table. 1397 */ 1398 1399 for (dip = ddi_get_child(ddi_root_node()); 1400 dip != NULL; 1401 dip = ddi_get_next_sibling(dip)) { 1402 1403 /* prune non-PCI nodes */ 1404 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 1405 "device_type", &device_type_prop) != DDI_PROP_SUCCESS) 1406 continue; 1407 1408 if ((strcmp("pci", device_type_prop) != 0) && 1409 (strcmp("pciex", device_type_prop) != 0)) { 1410 ddi_prop_free(device_type_prop); 1411 continue; 1412 } 1413 1414 ddi_prop_free(device_type_prop); 1415 1416 /* 1417 * To get bus number of dip, get first child and get its 1418 * bus number. If NULL, just continue, because we don't 1419 * care about bus nodes with no children anyway. 1420 */ 1421 if ((cdip = ddi_get_child(dip)) == NULL) 1422 continue; 1423 1424 if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) { 1425 #ifdef D2ADEBUG 1426 cmn_err(CE_WARN, "Can't get bus number of PCI child?"); 1427 #endif 1428 map_error = 1; 1429 creating_d2a_map = 0; 1430 return; 1431 } 1432 1433 if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) { 1434 #ifdef D2ADEBUG 1435 cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus); 1436 #endif 1437 map_error = 1; 1438 continue; 1439 } 1440 1441 /* 1442 * map this node, with illegal device and fn numbers 1443 * (since, as a PCI root node, it exists on the system 1444 * bus 1445 */ 1446 1447 new_d2a_entry(dip, acpiobj, bus, 32, 8); 1448 1449 /* call recursive function to enumerate subtrees */ 1450 create_d2a_subtree(dip, acpiobj, bus); 1451 } 1452 creating_d2a_map = 0; 1453 } 1454 1455 /* 1456 * For all acpi child devices of acpiobj, find their matching 1457 * dip under "dip" argument. (matching means "matches dev/fn"). 1458 * bus is assumed to already be a match from caller, and is 1459 * used here only to record in the d2a entry. Recurse if necessary. 1460 */ 1461 static void 1462 create_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus) 1463 { 1464 int acpi_devfn, hid; 1465 ACPI_HANDLE acld; 1466 dev_info_t *dcld; 1467 int dcld_b, dcld_d, dcld_f; 1468 int dev, func; 1469 1470 acld = NULL; 1471 while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld) 1472 == AE_OK) { 1473 1474 /* 1475 * Skip ACPI devices that are obviously not PCI, i.e., 1476 * that have a _HID that is *not* the PCI HID 1477 */ 1478 1479 if (acpica_eval_hid(acld, "_HID", &hid) == AE_OK && 1480 hid != HID_PCI_BUS && hid != HID_PCI_EXPRESS_BUS) 1481 continue; 1482 1483 /* get the dev/func we're looking for in the devinfo tree */ 1484 if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK) 1485 continue; 1486 dev = (acpi_devfn >> 16) & 0xFFFF; 1487 func = acpi_devfn & 0xFFFF; 1488 1489 /* look through all the immediate children of dip */ 1490 for (dcld = ddi_get_child(dip); dcld != NULL; 1491 dcld = ddi_get_next_sibling(dcld)) { 1492 if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0) 1493 continue; 1494 1495 /* dev must match; function must match or wildcard */ 1496 if (dcld_d != dev || 1497 (func != 0xFFFF && func != dcld_f)) 1498 continue; 1499 bus = dcld_b; 1500 1501 /* found a match, record it */ 1502 new_d2a_entry(dcld, acld, bus, dev, func); 1503 1504 /* recurse from here to pick up child trees */ 1505 create_d2a_subtree(dcld, acld, bus); 1506 1507 /* done finding a match, so break now */ 1508 break; 1509 } 1510 } 1511 } 1512 1513 /* 1514 * Return bus/dev/fn for PCI dip (note: not the parent "pci" node). 1515 */ 1516 1517 int 1518 acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func) 1519 { 1520 pci_regspec_t *pci_rp; 1521 int len; 1522 1523 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1524 "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS) 1525 return (-1); 1526 1527 if (len < (sizeof (pci_regspec_t) / sizeof (int))) { 1528 ddi_prop_free(pci_rp); 1529 return (-1); 1530 } 1531 if (bus != NULL) 1532 *bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi); 1533 if (device != NULL) 1534 *device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi); 1535 if (func != NULL) 1536 *func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 1537 ddi_prop_free(pci_rp); 1538 return (0); 1539 } 1540