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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2016 Joyent, Inc.
28 * Copyright (c) 2009-2010, Intel Corporation.
29 * All rights reserved.
32 * ACPI CA OSL for Solaris x86
35 #include <sys/types.h>
38 #include <sys/pci_cfgspace.h>
41 #include <sys/sunddi.h>
42 #include <sys/sunndi.h>
45 #include <sys/taskq.h>
46 #include <sys/strlog.h>
47 #include <sys/x86_archext.h>
49 #include <sys/promif.h>
51 #include <sys/acpi/accommon.h>
52 #include <sys/acpica.h>
54 #define MAX_DAT_FILE_SIZE (64*1024)
57 static int CompressEisaID(char *np
);
59 static void scan_d2a_subtree(dev_info_t
*dip
, ACPI_HANDLE acpiobj
, int bus
);
60 static int acpica_query_bbn_problem(void);
61 static int acpica_find_pcibus(int busno
, ACPI_HANDLE
*rh
);
62 static int acpica_eval_hid(ACPI_HANDLE dev
, char *method
, int *rint
);
63 static ACPI_STATUS
acpica_set_devinfo(ACPI_HANDLE
, dev_info_t
*);
64 static ACPI_STATUS
acpica_unset_devinfo(ACPI_HANDLE
);
65 static void acpica_devinfo_handler(ACPI_HANDLE
, void *);
70 int acpica_eventq_init
= 0;
71 ddi_taskq_t
*osl_eventq
[OSL_EC_BURST_HANDLER
+1];
74 * Priorities relative to minclsyspri that each taskq
75 * run at; OSL_NOTIFY_HANDLER needs to run at a higher
76 * priority than OSL_GPE_HANDLER. There's an implicit
77 * assumption that no priority here results in exceeding
79 * Note: these initializations need to match the order of
82 int osl_eventq_pri_delta
[OSL_EC_BURST_HANDLER
+1] = {
83 0, /* OSL_GLOBAL_LOCK_HANDLER */
84 2, /* OSL_NOTIFY_HANDLER */
85 0, /* OSL_GPE_HANDLER */
86 0, /* OSL_DEBUGGER_THREAD */
87 0, /* OSL_EC_POLL_HANDLER */
88 0 /* OSL_EC_BURST_HANDLER */
92 * Note, if you change this path, you need to update
93 * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386
95 static char *acpi_table_path
= "/boot/acpi/tables/";
97 /* non-zero while scan_d2a_map() is working */
98 static int scanning_d2a_map
= 0;
99 static int d2a_done
= 0;
101 /* features supported by ACPICA and ACPI device configuration. */
102 uint64_t acpica_core_features
= ACPI_FEATURE_OSI_MODULE
;
103 static uint64_t acpica_devcfg_features
= 0;
105 /* set by acpi_poweroff() in PSMs and appm_ioctl() in acpippm for S3 */
106 int acpica_use_safe_delay
= 0;
108 /* CPU mapping data */
109 struct cpu_map_item
{
110 processorid_t cpu_id
;
116 kmutex_t cpu_map_lock
;
117 static struct cpu_map_item
**cpu_map
= NULL
;
118 static int cpu_map_count_max
= 0;
119 static int cpu_map_count
= 0;
120 static int cpu_map_built
= 0;
123 * On systems with the uppc PSM only, acpica_map_cpu() won't be called at all.
124 * This flag is used to check for uppc-only systems by detecting whether
125 * acpica_map_cpu() has been called or not.
127 static int cpu_map_called
= 0;
129 static int acpi_has_broken_bbn
= -1;
131 /* buffer for AcpiOsVprintf() */
132 #define ACPI_OSL_PR_BUFLEN 1024
133 static char *acpi_osl_pr_buffer
= NULL
;
134 static int acpi_osl_pr_buflen
;
142 discard_event_queues()
147 * destroy event queues
149 for (i
= OSL_GLOBAL_LOCK_HANDLER
; i
<= OSL_EC_BURST_HANDLER
; i
++) {
151 ddi_taskq_destroy(osl_eventq
[i
]);
166 * Initialize event queues
169 /* Always allocate only 1 thread per queue to force FIFO execution */
170 for (i
= OSL_GLOBAL_LOCK_HANDLER
; i
<= OSL_EC_BURST_HANDLER
; i
++) {
171 snprintf(namebuf
, 32, "ACPI%d", i
);
172 osl_eventq
[i
] = ddi_taskq_create(NULL
, namebuf
, 1,
173 osl_eventq_pri_delta
[i
] + minclsyspri
, 0);
174 if (osl_eventq
[i
] == NULL
)
179 discard_event_queues();
181 cmn_err(CE_WARN
, "!acpica: could not initialize event queues");
186 acpica_eventq_init
= 1;
191 * One-time initialization of OSL layer
194 AcpiOsInitialize(void)
197 * Allocate buffer for AcpiOsVprintf() here to avoid
198 * kmem_alloc()/kmem_free() at high PIL
200 acpi_osl_pr_buffer
= kmem_alloc(ACPI_OSL_PR_BUFLEN
, KM_SLEEP
);
201 if (acpi_osl_pr_buffer
!= NULL
)
202 acpi_osl_pr_buflen
= ACPI_OSL_PR_BUFLEN
;
208 * One-time shut-down of OSL layer
211 AcpiOsTerminate(void)
214 if (acpi_osl_pr_buffer
!= NULL
)
215 kmem_free(acpi_osl_pr_buffer
, acpi_osl_pr_buflen
);
217 discard_event_queues();
222 ACPI_PHYSICAL_ADDRESS
223 AcpiOsGetRootPointer()
225 ACPI_PHYSICAL_ADDRESS Address
;
228 * For EFI firmware, the root pointer is defined in EFI systab.
229 * The boot code process the table and put the physical address
230 * in the acpi-root-tab property.
232 Address
= ddi_prop_get_int(DDI_DEV_T_ANY
, ddi_root_node(),
233 DDI_PROP_DONTPASS
, "acpi-root-tab", NULL
);
235 if ((Address
== NULL
) && ACPI_FAILURE(AcpiFindRootPointer(&Address
)))
243 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES
*InitVal
,
252 acpica_strncpy(char *dest
, const char *src
, int len
)
256 while ((*dest
++ = *src
++) && (--len
> 0))
257 /* copy the string */;
262 AcpiOsTableOverride(ACPI_TABLE_HEADER
*ExistingTable
,
263 ACPI_TABLE_HEADER
**NewTable
)
271 char acpi_table_loc
[128];
273 acpica_strncpy(signature
, ExistingTable
->Signature
, 4);
274 acpica_strncpy(oemid
, ExistingTable
->OemId
, 6);
275 acpica_strncpy(oemtableid
, ExistingTable
->OemTableId
, 8);
277 /* File name format is "signature_oemid_oemtableid.dat" */
278 (void) strcpy(acpi_table_loc
, acpi_table_path
);
279 (void) strcat(acpi_table_loc
, signature
); /* for example, DSDT */
280 (void) strcat(acpi_table_loc
, "_");
281 (void) strcat(acpi_table_loc
, oemid
); /* for example, IntelR */
282 (void) strcat(acpi_table_loc
, "_");
283 (void) strcat(acpi_table_loc
, oemtableid
); /* for example, AWRDACPI */
284 (void) strcat(acpi_table_loc
, ".dat");
286 file
= kobj_open_file(acpi_table_loc
);
287 if (file
== (struct _buf
*)-1) {
291 buf1
= (char *)kmem_alloc(MAX_DAT_FILE_SIZE
, KM_SLEEP
);
292 count
= kobj_read_file(file
, buf1
, MAX_DAT_FILE_SIZE
-1, 0);
293 if (count
>= MAX_DAT_FILE_SIZE
) {
294 cmn_err(CE_WARN
, "!acpica: table %s file size too big",
298 buf2
= (char *)kmem_alloc(count
, KM_SLEEP
);
299 (void) memcpy(buf2
, buf1
, count
);
300 *NewTable
= (ACPI_TABLE_HEADER
*)buf2
;
301 cmn_err(CE_NOTE
, "!acpica: replacing table: %s",
305 kobj_close_file(file
);
306 kmem_free(buf1
, MAX_DAT_FILE_SIZE
);
312 AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER
*ExistingTable
,
313 ACPI_PHYSICAL_ADDRESS
*NewAddress
, UINT32
*NewTableLength
)
319 * ACPI semaphore implementation
333 acpi_sema_init(acpi_sema_t
*sp
, unsigned max
, unsigned count
)
335 mutex_init(&sp
->mutex
, NULL
, MUTEX_DRIVER
, NULL
);
336 cv_init(&sp
->cv
, NULL
, CV_DRIVER
, NULL
);
337 /* no need to enter mutex here at creation */
338 sp
->available
= count
;
347 acpi_sema_destroy(acpi_sema_t
*sp
)
351 mutex_destroy(&sp
->mutex
);
358 acpi_sema_p(acpi_sema_t
*sp
, unsigned count
, uint16_t wait_time
)
360 ACPI_STATUS rv
= AE_OK
;
363 mutex_enter(&sp
->mutex
);
365 if (sp
->available
>= count
) {
367 * Enough units available, no blocking
369 sp
->available
-= count
;
370 mutex_exit(&sp
->mutex
);
372 } else if (wait_time
== 0) {
374 * Not enough units available and timeout
375 * specifies no blocking
378 mutex_exit(&sp
->mutex
);
383 * Not enough units available and timeout specifies waiting
385 if (wait_time
!= ACPI_WAIT_FOREVER
)
386 deadline
= ddi_get_lbolt() +
387 (clock_t)drv_usectohz(wait_time
* 1000);
390 if (wait_time
== ACPI_WAIT_FOREVER
)
391 cv_wait(&sp
->cv
, &sp
->mutex
);
392 else if (cv_timedwait(&sp
->cv
, &sp
->mutex
, deadline
) < 0) {
396 } while (sp
->available
< count
);
398 /* if we dropped out of the wait with AE_OK, we got the units */
400 sp
->available
-= count
;
402 mutex_exit(&sp
->mutex
);
410 acpi_sema_v(acpi_sema_t
*sp
, unsigned count
)
412 mutex_enter(&sp
->mutex
);
413 sp
->available
+= count
;
414 cv_broadcast(&sp
->cv
);
415 mutex_exit(&sp
->mutex
);
420 AcpiOsCreateSemaphore(UINT32 MaxUnits
, UINT32 InitialUnits
,
421 ACPI_HANDLE
*OutHandle
)
425 if ((OutHandle
== NULL
) || (InitialUnits
> MaxUnits
))
426 return (AE_BAD_PARAMETER
);
428 sp
= (acpi_sema_t
*)kmem_alloc(sizeof (acpi_sema_t
), KM_SLEEP
);
429 acpi_sema_init(sp
, MaxUnits
, InitialUnits
);
430 *OutHandle
= (ACPI_HANDLE
)sp
;
436 AcpiOsDeleteSemaphore(ACPI_HANDLE Handle
)
440 return (AE_BAD_PARAMETER
);
442 acpi_sema_destroy((acpi_sema_t
*)Handle
);
443 kmem_free((void *)Handle
, sizeof (acpi_sema_t
));
448 AcpiOsWaitSemaphore(ACPI_HANDLE Handle
, UINT32 Units
, UINT16 Timeout
)
451 if ((Handle
== NULL
) || (Units
< 1))
452 return (AE_BAD_PARAMETER
);
454 return (acpi_sema_p((acpi_sema_t
*)Handle
, Units
, Timeout
));
458 AcpiOsSignalSemaphore(ACPI_HANDLE Handle
, UINT32 Units
)
461 if ((Handle
== NULL
) || (Units
< 1))
462 return (AE_BAD_PARAMETER
);
464 acpi_sema_v((acpi_sema_t
*)Handle
, Units
);
469 AcpiOsCreateLock(ACPI_HANDLE
*OutHandle
)
473 if (OutHandle
== NULL
)
474 return (AE_BAD_PARAMETER
);
476 mp
= (kmutex_t
*)kmem_alloc(sizeof (kmutex_t
), KM_SLEEP
);
477 mutex_init(mp
, NULL
, MUTEX_DRIVER
, NULL
);
478 *OutHandle
= (ACPI_HANDLE
)mp
;
483 AcpiOsDeleteLock(ACPI_HANDLE Handle
)
489 mutex_destroy((kmutex_t
*)Handle
);
490 kmem_free((void *)Handle
, sizeof (kmutex_t
));
494 AcpiOsAcquireLock(ACPI_HANDLE Handle
)
499 return (AE_BAD_PARAMETER
);
501 if (curthread
== CPU
->cpu_idle_thread
) {
502 while (!mutex_tryenter((kmutex_t
*)Handle
))
505 mutex_enter((kmutex_t
*)Handle
);
510 AcpiOsReleaseLock(ACPI_HANDLE Handle
, ACPI_CPU_FLAGS Flags
)
512 _NOTE(ARGUNUSED(Flags
))
514 mutex_exit((kmutex_t
*)Handle
);
519 AcpiOsAllocate(ACPI_SIZE Size
)
523 Size
+= sizeof (Size
);
524 tmp_ptr
= (ACPI_SIZE
*)kmem_zalloc(Size
, KM_SLEEP
);
530 AcpiOsFree(void *Memory
)
532 ACPI_SIZE size
, *tmp_ptr
;
534 tmp_ptr
= (ACPI_SIZE
*)Memory
;
537 kmem_free(tmp_ptr
, size
);
540 static int napics_found
; /* number of ioapic addresses in array */
541 static ACPI_PHYSICAL_ADDRESS ioapic_paddr
[MAX_IO_APIC
];
542 static ACPI_TABLE_MADT
*acpi_mapic_dtp
= NULL
;
543 static void *dummy_ioapicadr
;
546 acpica_find_ioapics(void)
548 int madt_seen
, madt_size
;
549 ACPI_SUBTABLE_HEADER
*ap
;
550 ACPI_MADT_IO_APIC
*mia
;
552 if (acpi_mapic_dtp
!= NULL
)
553 return; /* already parsed table */
554 if (AcpiGetTable(ACPI_SIG_MADT
, 1,
555 (ACPI_TABLE_HEADER
**) &acpi_mapic_dtp
) != AE_OK
)
561 * Search the MADT for ioapics
563 ap
= (ACPI_SUBTABLE_HEADER
*) (acpi_mapic_dtp
+ 1);
564 madt_size
= acpi_mapic_dtp
->Header
.Length
;
565 madt_seen
= sizeof (*acpi_mapic_dtp
);
567 while (madt_seen
< madt_size
) {
570 case ACPI_MADT_TYPE_IO_APIC
:
571 mia
= (ACPI_MADT_IO_APIC
*) ap
;
572 if (napics_found
< MAX_IO_APIC
) {
573 ioapic_paddr
[napics_found
++] =
574 (ACPI_PHYSICAL_ADDRESS
)
575 (mia
->Address
& PAGEMASK
);
583 /* advance to next entry */
584 madt_seen
+= ap
->Length
;
585 ap
= (ACPI_SUBTABLE_HEADER
*)(((char *)ap
) + ap
->Length
);
587 if (dummy_ioapicadr
== NULL
)
588 dummy_ioapicadr
= kmem_zalloc(PAGESIZE
, KM_SLEEP
);
593 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress
, ACPI_SIZE Size
)
598 * If the iopaic address table is populated, check if trying
599 * to access an ioapic. Instead, return a pointer to a dummy ioapic.
601 for (i
= 0; i
< napics_found
; i
++) {
602 if ((PhysicalAddress
& PAGEMASK
) == ioapic_paddr
[i
])
603 return (dummy_ioapicadr
);
605 /* FUTUREWORK: test PhysicalAddress for > 32 bits */
606 return (psm_map_new((paddr_t
)PhysicalAddress
,
607 (size_t)Size
, PSM_PROT_WRITE
| PSM_PROT_READ
));
611 AcpiOsUnmapMemory(void *LogicalAddress
, ACPI_SIZE Size
)
614 * Check if trying to unmap dummy ioapic address.
616 if (LogicalAddress
== dummy_ioapicadr
)
619 psm_unmap((caddr_t
)LogicalAddress
, (size_t)Size
);
624 AcpiOsGetPhysicalAddress(void *LogicalAddress
,
625 ACPI_PHYSICAL_ADDRESS
*PhysicalAddress
)
628 /* UNIMPLEMENTED: not invoked by ACPI CA code */
629 return (AE_NOT_IMPLEMENTED
);
633 ACPI_OSD_HANDLER acpi_isr
;
634 void *acpi_isr_context
;
637 acpi_wrapper_isr(char *arg
)
639 _NOTE(ARGUNUSED(arg
))
643 status
= (*acpi_isr
)(acpi_isr_context
);
645 if (status
== ACPI_INTERRUPT_HANDLED
) {
646 return (DDI_INTR_CLAIMED
);
648 return (DDI_INTR_UNCLAIMED
);
652 static int acpi_intr_hooked
= 0;
655 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber
,
656 ACPI_OSD_HANDLER ServiceRoutine
,
659 _NOTE(ARGUNUSED(InterruptNumber
))
665 acpi_isr
= ServiceRoutine
;
666 acpi_isr_context
= Context
;
669 * Get SCI (adjusted for PIC/APIC mode if necessary)
671 if (acpica_get_sci(&sci_vect
, &sci_flags
) != AE_OK
) {
676 cmn_err(CE_NOTE
, "!acpica: attaching SCI %d", sci_vect
);
679 retval
= add_avintr(NULL
, SCI_IPL
, (avfunc
)acpi_wrapper_isr
,
680 "ACPI SCI", sci_vect
, NULL
, NULL
, NULL
, NULL
);
682 acpi_intr_hooked
= 1;
685 return (AE_BAD_PARAMETER
);
689 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber
,
690 ACPI_OSD_HANDLER ServiceRoutine
)
692 _NOTE(ARGUNUSED(ServiceRoutine
))
695 cmn_err(CE_NOTE
, "!acpica: detaching SCI %d", InterruptNumber
);
697 if (acpi_intr_hooked
) {
698 rem_avintr(NULL
, LOCK_LEVEL
- 1, (avfunc
)acpi_wrapper_isr
,
700 acpi_intr_hooked
= 0;
707 AcpiOsGetThreadId(void)
710 * ACPI CA doesn't care what actual value is returned as long
711 * as it is non-zero and unique to each existing thread.
712 * ACPI CA assumes that thread ID is castable to a pointer,
713 * so we use the current thread pointer.
715 return (ACPI_CAST_PTHREAD_T((uintptr_t)curthread
));
722 AcpiOsExecute(ACPI_EXECUTE_TYPE Type
, ACPI_OSD_EXEC_CALLBACK Function
,
726 if (!acpica_eventq_init
) {
728 * Create taskqs for event handling
730 if (init_event_queues() != AE_OK
)
734 if (ddi_taskq_dispatch(osl_eventq
[Type
], Function
, Context
,
735 DDI_NOSLEEP
) == DDI_FAILURE
) {
737 cmn_err(CE_WARN
, "!acpica: unable to dispatch event");
747 AcpiOsWaitEventsComplete(void)
752 * Wait for event queues to be empty.
754 for (i
= OSL_GLOBAL_LOCK_HANDLER
; i
<= OSL_EC_BURST_HANDLER
; i
++) {
755 if (osl_eventq
[i
] != NULL
) {
756 ddi_taskq_wait(osl_eventq
[i
]);
762 AcpiOsSleep(ACPI_INTEGER Milliseconds
)
765 * During kernel startup, before the first tick interrupt
766 * has taken place, we can't call delay; very late in
767 * kernel shutdown or suspend/resume, clock interrupts
768 * are blocked, so delay doesn't work then either.
769 * So we busy wait if lbolt == 0 (kernel startup)
770 * or if acpica_use_safe_delay has been set to a
773 if ((ddi_get_lbolt() == 0) || acpica_use_safe_delay
)
774 drv_usecwait(Milliseconds
* 1000);
776 delay(drv_usectohz(Milliseconds
* 1000));
780 AcpiOsStall(UINT32 Microseconds
)
782 drv_usecwait(Microseconds
);
787 * Implementation of "Windows 2001" compatible I/O permission map
790 #define OSL_IO_NONE (0)
791 #define OSL_IO_READ (1<<0)
792 #define OSL_IO_WRITE (1<<1)
793 #define OSL_IO_RW (OSL_IO_READ | OSL_IO_WRITE)
794 #define OSL_IO_TERM (1<<2)
795 #define OSL_IO_DEFAULT OSL_IO_RW
797 static struct io_perm
{
799 ACPI_IO_ADDRESS high
;
802 { 0xcf8, 0xd00, OSL_IO_TERM
| OSL_IO_RW
}
809 static struct io_perm
*
810 osl_io_find_perm(ACPI_IO_ADDRESS addr
)
816 if ((p
->low
<= addr
) && (addr
<= p
->high
))
818 p
= (p
->perm
& OSL_IO_TERM
) ? NULL
: p
+1;
828 AcpiOsReadPort(ACPI_IO_ADDRESS Address
, UINT32
*Value
, UINT32 Width
)
832 /* verify permission */
833 p
= osl_io_find_perm(Address
);
834 if (p
&& (p
->perm
& OSL_IO_READ
) == 0) {
835 cmn_err(CE_WARN
, "!AcpiOsReadPort: %lx %u not permitted",
836 (long)Address
, Width
);
843 *Value
= inb(Address
);
846 *Value
= inw(Address
);
849 *Value
= inl(Address
);
852 cmn_err(CE_WARN
, "!AcpiOsReadPort: %lx %u failed",
853 (long)Address
, Width
);
854 return (AE_BAD_PARAMETER
);
860 AcpiOsWritePort(ACPI_IO_ADDRESS Address
, UINT32 Value
, UINT32 Width
)
864 /* verify permission */
865 p
= osl_io_find_perm(Address
);
866 if (p
&& (p
->perm
& OSL_IO_WRITE
) == 0) {
867 cmn_err(CE_WARN
, "!AcpiOsWritePort: %lx %u not permitted",
868 (long)Address
, Width
);
874 outb(Address
, Value
);
877 outw(Address
, Value
);
880 outl(Address
, Value
);
883 cmn_err(CE_WARN
, "!AcpiOsWritePort: %lx %u failed",
884 (long)Address
, Width
);
885 return (AE_BAD_PARAMETER
);
895 #define OSL_RW(ptr, val, type, rw) \
896 { if (rw) *((type *)(ptr)) = *((type *) val); \
897 else *((type *) val) = *((type *)(ptr)); }
901 osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address
, UINT64
*Value
,
902 UINT32 Width
, int write
)
904 size_t maplen
= Width
/ 8;
907 ptr
= psm_map_new((paddr_t
)Address
, maplen
,
908 PSM_PROT_WRITE
| PSM_PROT_READ
);
912 OSL_RW(ptr
, Value
, uint8_t, write
);
915 OSL_RW(ptr
, Value
, uint16_t, write
);
918 OSL_RW(ptr
, Value
, uint32_t, write
);
921 OSL_RW(ptr
, Value
, uint64_t, write
);
924 cmn_err(CE_WARN
, "!osl_rw_memory: invalid size %d",
929 psm_unmap(ptr
, maplen
);
933 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address
,
934 UINT64
*Value
, UINT32 Width
)
936 osl_rw_memory(Address
, Value
, Width
, 0);
941 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address
,
942 UINT64 Value
, UINT32 Width
)
944 osl_rw_memory(Address
, &Value
, Width
, 1);
950 AcpiOsReadPciConfiguration(ACPI_PCI_ID
*PciId
, UINT32 Reg
,
951 UINT64
*Value
, UINT32 Width
)
956 *Value
= (UINT64
)(*pci_getb_func
)
957 (PciId
->Bus
, PciId
->Device
, PciId
->Function
, Reg
);
960 *Value
= (UINT64
)(*pci_getw_func
)
961 (PciId
->Bus
, PciId
->Device
, PciId
->Function
, Reg
);
964 *Value
= (UINT64
)(*pci_getl_func
)
965 (PciId
->Bus
, PciId
->Device
, PciId
->Function
, Reg
);
969 cmn_err(CE_WARN
, "!AcpiOsReadPciConfiguration: %x %u failed",
971 return (AE_BAD_PARAMETER
);
979 int acpica_write_pci_config_ok
= 1;
982 AcpiOsWritePciConfiguration(ACPI_PCI_ID
*PciId
, UINT32 Reg
,
983 UINT64 Value
, UINT32 Width
)
986 if (!acpica_write_pci_config_ok
) {
987 cmn_err(CE_NOTE
, "!write to PCI cfg %x/%x/%x %x"
988 " %lx %d not permitted", PciId
->Bus
, PciId
->Device
,
989 PciId
->Function
, Reg
, (long)Value
, Width
);
995 (*pci_putb_func
)(PciId
->Bus
, PciId
->Device
, PciId
->Function
,
996 Reg
, (uint8_t)Value
);
999 (*pci_putw_func
)(PciId
->Bus
, PciId
->Device
, PciId
->Function
,
1000 Reg
, (uint16_t)Value
);
1003 (*pci_putl_func
)(PciId
->Bus
, PciId
->Device
, PciId
->Function
,
1004 Reg
, (uint32_t)Value
);
1008 cmn_err(CE_WARN
, "!AcpiOsWritePciConfiguration: %x %u failed",
1010 return (AE_BAD_PARAMETER
);
1016 * Called with ACPI_HANDLEs for both a PCI Config Space
1017 * OpRegion and (what ACPI CA thinks is) the PCI device
1018 * to which this ConfigSpace OpRegion belongs.
1020 * ACPI CA uses _BBN and _ADR objects to determine the default
1021 * values for bus, segment, device and function; anything ACPI CA
1022 * can't figure out from the ACPI tables will be 0. One very
1023 * old 32-bit x86 system is known to have broken _BBN; this is
1024 * not addressed here.
1026 * Some BIOSes implement _BBN() by reading PCI config space
1027 * on bus #0 - which means that we'll recurse when we attempt
1028 * to create the devinfo-to-ACPI map. If Derive is called during
1029 * scan_d2a_map, we don't translate the bus # and return.
1031 * We get the parent of the OpRegion, which must be a PCI
1032 * node, fetch the associated devinfo node and snag the
1036 AcpiOsDerivePciId(ACPI_HANDLE rhandle
, ACPI_HANDLE chandle
,
1037 ACPI_PCI_ID
**PciId
)
1041 int bus
, device
, func
, devfn
;
1044 * See above - avoid recursing during scanning_d2a_map.
1046 if (scanning_d2a_map
)
1050 * Get the OpRegion's parent
1052 if (AcpiGetParent(chandle
, &handle
) != AE_OK
)
1056 * If we've mapped the ACPI node to the devinfo
1057 * tree, use the devinfo reg property
1059 if (ACPI_SUCCESS(acpica_get_devinfo(handle
, &dip
)) &&
1060 (acpica_get_bdf(dip
, &bus
, &device
, &func
) >= 0)) {
1061 (*PciId
)->Bus
= bus
;
1062 (*PciId
)->Device
= device
;
1063 (*PciId
)->Function
= func
;
1070 AcpiOsReadable(void *Pointer
, ACPI_SIZE Length
)
1073 /* Always says yes; all mapped memory assumed readable */
1079 AcpiOsWritable(void *Pointer
, ACPI_SIZE Length
)
1082 /* Always says yes; all mapped memory assumed writable */
1087 AcpiOsGetTimer(void)
1089 /* gethrtime() returns 1nS resolution; convert to 100nS granules */
1090 return ((gethrtime() + 50) / 100);
1093 static struct AcpiOSIFeature_s
{
1094 uint64_t control_flag
;
1095 const char *feature_name
;
1096 } AcpiOSIFeatures
[] = {
1097 { ACPI_FEATURE_OSI_MODULE
, "Module Device" },
1098 { 0, "Processor Device" }
1103 AcpiOsValidateInterface(char *feature
)
1107 ASSERT(feature
!= NULL
);
1108 for (i
= 0; i
< sizeof (AcpiOSIFeatures
) / sizeof (AcpiOSIFeatures
[0]);
1110 if (strcmp(feature
, AcpiOSIFeatures
[i
].feature_name
) != 0) {
1113 /* Check whether required core features are available. */
1114 if (AcpiOSIFeatures
[i
].control_flag
!= 0 &&
1115 acpica_get_core_feature(AcpiOSIFeatures
[i
].control_flag
) !=
1116 AcpiOSIFeatures
[i
].control_flag
) {
1119 /* Feature supported. */
1123 return (AE_SUPPORT
);
1128 AcpiOsValidateAddress(UINT8 spaceid
, ACPI_PHYSICAL_ADDRESS addr
,
1135 AcpiOsSignal(UINT32 Function
, void *Info
)
1137 _NOTE(ARGUNUSED(Function
, Info
))
1139 /* FUTUREWORK: debugger support */
1141 cmn_err(CE_NOTE
, "!OsSignal unimplemented");
1145 void ACPI_INTERNAL_VAR_XFACE
1146 AcpiOsPrintf(const char *Format
, ...)
1150 va_start(ap
, Format
);
1151 AcpiOsVprintf(Format
, ap
);
1156 * When != 0, sends output to console
1157 * Patchable with kmdb or /etc/system.
1159 int acpica_console_out
= 0;
1161 #define ACPICA_OUTBUF_LEN 160
1162 char acpica_outbuf
[ACPICA_OUTBUF_LEN
];
1163 int acpica_outbuf_offset
;
1169 acpica_pr_buf(char *buf
)
1171 char c
, *bufp
, *outp
;
1175 * copy the supplied buffer into the output buffer
1176 * when we hit a '\n' or overflow the output buffer,
1177 * output and reset the output buffer
1180 outp
= acpica_outbuf
+ acpica_outbuf_offset
;
1181 out_remaining
= ACPICA_OUTBUF_LEN
- acpica_outbuf_offset
- 1;
1182 while (c
= *bufp
++) {
1184 if (c
== '\n' || --out_remaining
== 0) {
1186 switch (acpica_console_out
) {
1188 printf(acpica_outbuf
);
1191 prom_printf(acpica_outbuf
);
1195 (void) strlog(0, 0, 0,
1196 SL_CONSOLE
| SL_NOTE
| SL_LOGONLY
,
1200 acpica_outbuf_offset
= 0;
1201 outp
= acpica_outbuf
;
1202 out_remaining
= ACPICA_OUTBUF_LEN
- 1;
1206 acpica_outbuf_offset
= outp
- acpica_outbuf
;
1210 AcpiOsVprintf(const char *Format
, va_list Args
)
1214 * If AcpiOsInitialize() failed to allocate a string buffer,
1215 * resort to vprintf().
1217 if (acpi_osl_pr_buffer
== NULL
) {
1218 vprintf(Format
, Args
);
1223 * It is possible that a very long debug output statement will
1224 * be truncated; this is silently ignored.
1226 (void) vsnprintf(acpi_osl_pr_buffer
, acpi_osl_pr_buflen
, Format
, Args
);
1227 acpica_pr_buf(acpi_osl_pr_buffer
);
1231 AcpiOsRedirectOutput(void *Destination
)
1233 _NOTE(ARGUNUSED(Destination
))
1235 /* FUTUREWORK: debugger support */
1238 cmn_err(CE_WARN
, "!acpica: AcpiOsRedirectOutput called");
1244 AcpiOsGetLine(char *Buffer
, UINT32 len
, UINT32
*BytesRead
)
1246 _NOTE(ARGUNUSED(Buffer
))
1247 _NOTE(ARGUNUSED(len
))
1248 _NOTE(ARGUNUSED(BytesRead
))
1250 /* FUTUREWORK: debugger support */
1256 * Device tree binding
1259 acpica_find_pcibus_walker(ACPI_HANDLE hdl
, UINT32 lvl
, void *ctxp
, void **rvpp
)
1261 _NOTE(ARGUNUSED(lvl
));
1264 int busno
= (intptr_t)ctxp
;
1265 ACPI_HANDLE
*hdlp
= (ACPI_HANDLE
*)rvpp
;
1267 /* Check whether device exists. */
1268 if (ACPI_SUCCESS(acpica_eval_int(hdl
, "_STA", &sta
)) &&
1269 !(sta
& (ACPI_STA_DEVICE_PRESENT
| ACPI_STA_DEVICE_FUNCTIONING
))) {
1271 * Skip object if device doesn't exist.
1272 * According to ACPI Spec,
1273 * 1) setting either bit 0 or bit 3 means that device exists.
1274 * 2) Absence of _STA method means all status bits set.
1276 return (AE_CTRL_DEPTH
);
1279 if (ACPI_FAILURE(acpica_eval_hid(hdl
, "_HID", &hid
)) ||
1280 (hid
!= HID_PCI_BUS
&& hid
!= HID_PCI_EXPRESS_BUS
)) {
1281 /* Non PCI/PCIe host bridge. */
1285 if (acpi_has_broken_bbn
) {
1288 rb
.Length
= ACPI_ALLOCATE_BUFFER
;
1290 /* Decree _BBN == n from PCI<n> */
1291 if (AcpiGetName(hdl
, ACPI_SINGLE_NAME
, &rb
) != AE_OK
) {
1292 return (AE_CTRL_TERMINATE
);
1294 bbn
= ((char *)rb
.Pointer
)[3] - '0';
1295 AcpiOsFree(rb
.Pointer
);
1296 if (bbn
== busno
|| busno
== 0) {
1298 return (AE_CTRL_TERMINATE
);
1300 } else if (ACPI_SUCCESS(acpica_eval_int(hdl
, "_BBN", &bbn
))) {
1303 return (AE_CTRL_TERMINATE
);
1305 } else if (busno
== 0) {
1307 return (AE_CTRL_TERMINATE
);
1310 return (AE_CTRL_DEPTH
);
1314 acpica_find_pcibus(int busno
, ACPI_HANDLE
*rh
)
1316 ACPI_HANDLE sbobj
, busobj
;
1318 /* initialize static flag by querying ACPI namespace for bug */
1319 if (acpi_has_broken_bbn
== -1)
1320 acpi_has_broken_bbn
= acpica_query_bbn_problem();
1322 if (ACPI_SUCCESS(AcpiGetHandle(NULL
, "\\_SB", &sbobj
))) {
1324 (void) AcpiWalkNamespace(ACPI_TYPE_DEVICE
, sbobj
, UINT32_MAX
,
1325 acpica_find_pcibus_walker
, NULL
, (void *)(intptr_t)busno
,
1327 if (busobj
!= NULL
) {
1337 acpica_query_bbn_walker(ACPI_HANDLE hdl
, UINT32 lvl
, void *ctxp
, void **rvpp
)
1339 _NOTE(ARGUNUSED(lvl
));
1340 _NOTE(ARGUNUSED(rvpp
));
1343 int *cntp
= (int *)ctxp
;
1345 /* Check whether device exists. */
1346 if (ACPI_SUCCESS(acpica_eval_int(hdl
, "_STA", &sta
)) &&
1347 !(sta
& (ACPI_STA_DEVICE_PRESENT
| ACPI_STA_DEVICE_FUNCTIONING
))) {
1349 * Skip object if device doesn't exist.
1350 * According to ACPI Spec,
1351 * 1) setting either bit 0 or bit 3 means that device exists.
1352 * 2) Absence of _STA method means all status bits set.
1354 return (AE_CTRL_DEPTH
);
1357 if (ACPI_FAILURE(acpica_eval_hid(hdl
, "_HID", &hid
)) ||
1358 (hid
!= HID_PCI_BUS
&& hid
!= HID_PCI_EXPRESS_BUS
)) {
1359 /* Non PCI/PCIe host bridge. */
1361 } else if (ACPI_SUCCESS(acpica_eval_int(hdl
, "_BBN", &bbn
)) &&
1362 bbn
== 0 && ++(*cntp
) > 1) {
1364 * If we find more than one bus with a 0 _BBN
1365 * we have the problem that BigBear's BIOS shows
1367 return (AE_CTRL_TERMINATE
);
1370 * Skip children of PCI/PCIe host bridge.
1372 return (AE_CTRL_DEPTH
);
1377 * Look for ACPI problem where _BBN is zero for multiple PCI buses
1378 * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus()
1379 * below if it exists.
1382 acpica_query_bbn_problem(void)
1389 if (ACPI_SUCCESS(AcpiGetHandle(NULL
, "\\_SB", &sbobj
))) {
1390 (void) AcpiWalkNamespace(ACPI_TYPE_DEVICE
, sbobj
, UINT32_MAX
,
1391 acpica_query_bbn_walker
, NULL
, &zerobbncnt
, &rv
);
1394 return (zerobbncnt
> 1 ? 1 : 0);
1397 static const char hextab
[] = "0123456789ABCDEF";
1405 * Returns the 4-bit hex digit named by the input character. Returns
1406 * zero if the input character is not valid hex!
1409 int x
= ((c
< 'a') || (c
> 'z')) ? c
: (c
- ' ');
1410 int j
= sizeof (hextab
);
1412 while (--j
&& (x
!= hextab
[j
])) {
1418 CompressEisaID(char *np
)
1421 * Compress an EISA device name:
1423 * This routine converts a 7-byte ASCII device name into the 4-byte
1424 * compressed form used by EISA (50 bytes of ROM to save 1 byte of
1428 union { char octets
[4]; int retval
; } myu
;
1430 myu
.octets
[0] = ((np
[0] & 0x1F) << 2) + ((np
[1] >> 3) & 0x03);
1431 myu
.octets
[1] = ((np
[1] & 0x07) << 5) + (np
[2] & 0x1F);
1432 myu
.octets
[2] = (hexdig(np
[3]) << 4) + hexdig(np
[4]);
1433 myu
.octets
[3] = (hexdig(np
[5]) << 4) + hexdig(np
[6]);
1435 return (myu
.retval
);
1439 acpica_eval_int(ACPI_HANDLE dev
, char *method
, int *rint
)
1446 rb
.Length
= sizeof (ro
);
1447 if ((status
= AcpiEvaluateObjectTyped(dev
, method
, NULL
, &rb
,
1448 ACPI_TYPE_INTEGER
)) == AE_OK
)
1449 *rint
= ro
.Integer
.Value
;
1455 acpica_eval_hid(ACPI_HANDLE dev
, char *method
, int *rint
)
1461 rb
.Length
= ACPI_ALLOCATE_BUFFER
;
1462 if (AcpiEvaluateObject(dev
, method
, NULL
, &rb
) == AE_OK
&&
1465 if (rv
->Type
== ACPI_TYPE_INTEGER
) {
1466 *rint
= rv
->Integer
.Value
;
1469 } else if (rv
->Type
== ACPI_TYPE_STRING
) {
1472 /* Convert the string into an EISA ID */
1473 if (rv
->String
.Pointer
== NULL
) {
1478 stringData
= rv
->String
.Pointer
;
1481 * If the string is an EisaID, it must be 7
1482 * characters; if it's an ACPI ID, it will be 8
1483 * (and we don't care about ACPI ids here).
1485 if (strlen(stringData
) != 7) {
1490 *rint
= CompressEisaID(stringData
);
1500 * Create linkage between devinfo nodes and ACPI nodes
1503 acpica_tag_devinfo(dev_info_t
*dip
, ACPI_HANDLE acpiobj
)
1509 * Tag the devinfo node with the ACPI name
1512 rb
.Length
= ACPI_ALLOCATE_BUFFER
;
1513 status
= AcpiGetName(acpiobj
, ACPI_FULL_PATHNAME
, &rb
);
1514 if (ACPI_FAILURE(status
)) {
1515 cmn_err(CE_WARN
, "acpica: could not get ACPI path!");
1517 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1518 "acpi-namespace", (char *)rb
.Pointer
);
1519 AcpiOsFree(rb
.Pointer
);
1522 * Tag the ACPI node with the dip
1524 status
= acpica_set_devinfo(acpiobj
, dip
);
1525 ASSERT(ACPI_SUCCESS(status
));
1532 * Destroy linkage between devinfo nodes and ACPI nodes
1535 acpica_untag_devinfo(dev_info_t
*dip
, ACPI_HANDLE acpiobj
)
1537 (void) acpica_unset_devinfo(acpiobj
);
1538 (void) ndi_prop_remove(DDI_DEV_T_NONE
, dip
, "acpi-namespace");
1544 * Return the ACPI device node matching the CPU dev_info node.
1547 acpica_get_handle_cpu(int cpu_id
, ACPI_HANDLE
*rh
)
1552 * if cpu_map itself is NULL, we're a uppc system and
1553 * acpica_build_processor_map() hasn't been called yet.
1556 if (cpu_map
== NULL
) {
1557 (void) acpica_build_processor_map();
1558 if (cpu_map
== NULL
)
1567 * search object with cpuid in cpu_map
1569 mutex_enter(&cpu_map_lock
);
1570 for (i
= 0; i
< cpu_map_count
; i
++) {
1571 if (cpu_map
[i
]->cpu_id
== cpu_id
) {
1575 if (i
< cpu_map_count
&& (cpu_map
[i
]->obj
!= NULL
)) {
1576 *rh
= cpu_map
[i
]->obj
;
1577 mutex_exit(&cpu_map_lock
);
1581 /* Handle special case for uppc-only systems. */
1582 if (cpu_map_called
== 0) {
1583 uint32_t apicid
= cpuid_get_apicid(CPU
);
1584 if (apicid
!= UINT32_MAX
) {
1585 for (i
= 0; i
< cpu_map_count
; i
++) {
1586 if (cpu_map
[i
]->apic_id
== apicid
) {
1590 if (i
< cpu_map_count
&& (cpu_map
[i
]->obj
!= NULL
)) {
1591 *rh
= cpu_map
[i
]->obj
;
1592 mutex_exit(&cpu_map_lock
);
1597 mutex_exit(&cpu_map_lock
);
1603 * Determine if this object is a processor
1606 acpica_probe_processor(ACPI_HANDLE obj
, UINT32 level
, void *ctx
, void **rv
)
1609 ACPI_OBJECT_TYPE objtype
;
1610 unsigned long acpi_id
;
1612 ACPI_DEVICE_INFO
*di
;
1614 if (AcpiGetType(obj
, &objtype
) != AE_OK
)
1617 if (objtype
== ACPI_TYPE_PROCESSOR
) {
1618 /* process a Processor */
1620 rb
.Length
= ACPI_ALLOCATE_BUFFER
;
1621 status
= AcpiEvaluateObjectTyped(obj
, NULL
, NULL
, &rb
,
1622 ACPI_TYPE_PROCESSOR
);
1623 if (status
!= AE_OK
) {
1624 cmn_err(CE_WARN
, "!acpica: error probing Processor");
1627 acpi_id
= ((ACPI_OBJECT
*)rb
.Pointer
)->Processor
.ProcId
;
1628 AcpiOsFree(rb
.Pointer
);
1629 } else if (objtype
== ACPI_TYPE_DEVICE
) {
1630 /* process a processor Device */
1631 status
= AcpiGetObjectInfo(obj
, &di
);
1632 if (status
!= AE_OK
) {
1634 "!acpica: error probing Processor Device\n");
1638 if (!(di
->Valid
& ACPI_VALID_UID
) ||
1639 ddi_strtoul(di
->UniqueId
.String
, NULL
, 10, &acpi_id
) != 0) {
1642 "!acpica: error probing Processor Device _UID\n");
1647 (void) acpica_add_processor_to_map(acpi_id
, obj
, UINT32_MAX
);
1655 dev_info_t
*dip
, *cdip
;
1656 ACPI_HANDLE acpiobj
;
1657 char *device_type_prop
;
1659 static int map_error
= 0;
1661 if (map_error
|| (d2a_done
!= 0))
1664 scanning_d2a_map
= 1;
1667 * Find all child-of-root PCI buses, and find their corresponding
1668 * ACPI child-of-root PCI nodes. For each one, add to the
1672 for (dip
= ddi_get_child(ddi_root_node());
1674 dip
= ddi_get_next_sibling(dip
)) {
1676 /* prune non-PCI nodes */
1677 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, dip
,
1679 "device_type", &device_type_prop
) != DDI_PROP_SUCCESS
)
1682 if ((strcmp("pci", device_type_prop
) != 0) &&
1683 (strcmp("pciex", device_type_prop
) != 0)) {
1684 ddi_prop_free(device_type_prop
);
1688 ddi_prop_free(device_type_prop
);
1691 * To get bus number of dip, get first child and get its
1692 * bus number. If NULL, just continue, because we don't
1693 * care about bus nodes with no children anyway.
1695 if ((cdip
= ddi_get_child(dip
)) == NULL
)
1698 if (acpica_get_bdf(cdip
, &bus
, NULL
, NULL
) < 0) {
1700 cmn_err(CE_WARN
, "Can't get bus number of PCI child?");
1703 scanning_d2a_map
= 0;
1708 if (acpica_find_pcibus(bus
, &acpiobj
) == AE_ERROR
) {
1710 cmn_err(CE_WARN
, "No ACPI bus obj for bus %d?\n", bus
);
1716 acpica_tag_devinfo(dip
, acpiobj
);
1718 /* call recursively to enumerate subtrees */
1719 scan_d2a_subtree(dip
, acpiobj
, bus
);
1722 scanning_d2a_map
= 0;
1727 * For all acpi child devices of acpiobj, find their matching
1728 * dip under "dip" argument. (matching means "matches dev/fn").
1729 * bus is assumed to already be a match from caller, and is
1730 * used here only to record in the d2a entry. Recurse if necessary.
1733 scan_d2a_subtree(dev_info_t
*dip
, ACPI_HANDLE acpiobj
, int bus
)
1735 int acpi_devfn
, hid
;
1738 int dcld_b
, dcld_d
, dcld_f
;
1740 char *device_type_prop
;
1743 while (AcpiGetNextObject(ACPI_TYPE_DEVICE
, acpiobj
, acld
, &acld
)
1745 /* get the dev/func we're looking for in the devinfo tree */
1746 if (acpica_eval_int(acld
, "_ADR", &acpi_devfn
) != AE_OK
)
1748 dev
= (acpi_devfn
>> 16) & 0xFFFF;
1749 func
= acpi_devfn
& 0xFFFF;
1751 /* look through all the immediate children of dip */
1752 for (dcld
= ddi_get_child(dip
); dcld
!= NULL
;
1753 dcld
= ddi_get_next_sibling(dcld
)) {
1754 if (acpica_get_bdf(dcld
, &dcld_b
, &dcld_d
, &dcld_f
) < 0)
1757 /* dev must match; function must match or wildcard */
1758 if (dcld_d
!= dev
||
1759 (func
!= 0xFFFF && func
!= dcld_f
))
1763 /* found a match, record it */
1764 acpica_tag_devinfo(dcld
, acld
);
1766 /* if we find a bridge, recurse from here */
1767 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, dcld
,
1768 DDI_PROP_DONTPASS
, "device_type",
1769 &device_type_prop
) == DDI_PROP_SUCCESS
) {
1770 if ((strcmp("pci", device_type_prop
) == 0) ||
1771 (strcmp("pciex", device_type_prop
) == 0))
1772 scan_d2a_subtree(dcld
, acld
, bus
);
1773 ddi_prop_free(device_type_prop
);
1776 /* done finding a match, so break now */
1783 * Return bus/dev/fn for PCI dip (note: not the parent "pci" node).
1786 acpica_get_bdf(dev_info_t
*dip
, int *bus
, int *device
, int *func
)
1788 pci_regspec_t
*pci_rp
;
1791 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1792 "reg", (int **)&pci_rp
, (uint_t
*)&len
) != DDI_SUCCESS
)
1795 if (len
< (sizeof (pci_regspec_t
) / sizeof (int))) {
1796 ddi_prop_free(pci_rp
);
1800 *bus
= (int)PCI_REG_BUS_G(pci_rp
->pci_phys_hi
);
1802 *device
= (int)PCI_REG_DEV_G(pci_rp
->pci_phys_hi
);
1804 *func
= (int)PCI_REG_FUNC_G(pci_rp
->pci_phys_hi
);
1805 ddi_prop_free(pci_rp
);
1810 * Return the ACPI device node matching this dev_info node, if it
1811 * exists in the ACPI tree.
1814 acpica_get_handle(dev_info_t
*dip
, ACPI_HANDLE
*rh
)
1821 cmn_err(CE_WARN
, "!acpica_get_handle:"
1822 " no ACPI mapping for %s", ddi_node_name(dip
));
1825 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1826 "acpi-namespace", &acpiname
) != DDI_PROP_SUCCESS
) {
1830 status
= AcpiGetHandle(NULL
, acpiname
, rh
);
1831 ddi_prop_free((void *)acpiname
);
1838 * Manage OS data attachment to ACPI nodes
1842 * Return the (dev_info_t *) associated with the ACPI node.
1845 acpica_get_devinfo(ACPI_HANDLE obj
, dev_info_t
**dipp
)
1850 status
= AcpiGetData(obj
, acpica_devinfo_handler
, &ptr
);
1851 if (status
== AE_OK
)
1852 *dipp
= (dev_info_t
*)ptr
;
1858 * Set the dev_info_t associated with the ACPI node.
1861 acpica_set_devinfo(ACPI_HANDLE obj
, dev_info_t
*dip
)
1865 status
= AcpiAttachData(obj
, acpica_devinfo_handler
, (void *)dip
);
1870 * Unset the dev_info_t associated with the ACPI node.
1873 acpica_unset_devinfo(ACPI_HANDLE obj
)
1875 return (AcpiDetachData(obj
, acpica_devinfo_handler
));
1882 acpica_devinfo_handler(ACPI_HANDLE obj
, void *data
)
1888 acpica_build_processor_map(void)
1894 * shouldn't be called more than once anyway
1900 * ACPI device configuration driver has built mapping information
1901 * among processor id and object handle, no need to probe again.
1903 if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU
)) {
1909 * Look for Processor objects
1911 status
= AcpiWalkNamespace(ACPI_TYPE_PROCESSOR
,
1914 acpica_probe_processor
,
1918 ASSERT(status
== AE_OK
);
1921 * Look for processor Device objects
1923 status
= AcpiGetDevices("ACPI0007",
1924 acpica_probe_processor
,
1927 ASSERT(status
== AE_OK
);
1934 * Grow cpu map table on demand.
1937 acpica_grow_cpu_map(void)
1939 if (cpu_map_count
== cpu_map_count_max
) {
1941 struct cpu_map_item
**new_map
;
1943 ASSERT(cpu_map_count_max
< INT_MAX
/ 2);
1944 cpu_map_count_max
+= max_ncpus
;
1945 new_map
= kmem_zalloc(sizeof (cpu_map
[0]) * cpu_map_count_max
,
1947 if (cpu_map_count
!= 0) {
1948 ASSERT(cpu_map
!= NULL
);
1949 sz
= sizeof (cpu_map
[0]) * cpu_map_count
;
1950 kcopy(cpu_map
, new_map
, sz
);
1951 kmem_free(cpu_map
, sz
);
1958 * Maintain mapping information among (cpu id, ACPI processor id, APIC id,
1959 * ACPI handle). The mapping table will be setup in two steps:
1960 * 1) acpica_add_processor_to_map() builds mapping among APIC id, ACPI
1961 * processor id and ACPI object handle.
1962 * 2) acpica_map_cpu() builds mapping among cpu id and ACPI processor id.
1963 * On systems with which have ACPI device configuration for CPUs enabled,
1964 * acpica_map_cpu() will be called after acpica_add_processor_to_map(),
1965 * otherwise acpica_map_cpu() will be called before
1966 * acpica_add_processor_to_map().
1969 acpica_add_processor_to_map(UINT32 acpi_id
, ACPI_HANDLE obj
, UINT32 apic_id
)
1972 ACPI_STATUS rc
= AE_OK
;
1973 struct cpu_map_item
*item
= NULL
;
1975 ASSERT(obj
!= NULL
);
1980 mutex_enter(&cpu_map_lock
);
1983 * Special case for uppc
1984 * If we're a uppc system and ACPI device configuration for CPU has
1985 * been disabled, there won't be a CPU map yet because uppc psm doesn't
1986 * call acpica_map_cpu(). So create one and use the passed-in processor
1988 * Assumption: the first CPU returned by
1989 * AcpiGetDevices/AcpiWalkNamespace will be the BSP.
1990 * Unfortunately there appears to be no good way to ASSERT this.
1992 if (cpu_map
== NULL
&&
1993 !acpica_get_devcfg_feature(ACPI_DEVCFG_CPU
)) {
1994 acpica_grow_cpu_map();
1995 ASSERT(cpu_map
!= NULL
);
1996 item
= kmem_zalloc(sizeof (*item
), KM_SLEEP
);
1998 item
->proc_id
= acpi_id
;
1999 item
->apic_id
= apic_id
;
2003 mutex_exit(&cpu_map_lock
);
2007 for (i
= 0; i
< cpu_map_count
; i
++) {
2008 if (cpu_map
[i
]->obj
== obj
) {
2009 rc
= AE_ALREADY_EXISTS
;
2011 } else if (cpu_map
[i
]->proc_id
== acpi_id
) {
2012 ASSERT(item
== NULL
);
2020 * ACPI alias objects may cause more than one objects
2021 * with the same ACPI processor id, only remember the
2022 * the first object encountered.
2024 if (item
->obj
== NULL
) {
2026 item
->apic_id
= apic_id
;
2028 rc
= AE_ALREADY_EXISTS
;
2030 } else if (cpu_map_count
>= INT_MAX
/ 2) {
2033 acpica_grow_cpu_map();
2034 ASSERT(cpu_map
!= NULL
);
2035 ASSERT(cpu_map_count
< cpu_map_count_max
);
2036 item
= kmem_zalloc(sizeof (*item
), KM_SLEEP
);
2038 item
->proc_id
= acpi_id
;
2039 item
->apic_id
= apic_id
;
2041 cpu_map
[cpu_map_count
] = item
;
2046 mutex_exit(&cpu_map_lock
);
2052 acpica_remove_processor_from_map(UINT32 acpi_id
)
2055 ACPI_STATUS rc
= AE_NOT_EXIST
;
2057 mutex_enter(&cpu_map_lock
);
2058 for (i
= 0; i
< cpu_map_count
; i
++) {
2059 if (cpu_map
[i
]->proc_id
!= acpi_id
) {
2062 cpu_map
[i
]->obj
= NULL
;
2063 /* Free item if no more reference to it. */
2064 if (cpu_map
[i
]->cpu_id
== -1) {
2065 kmem_free(cpu_map
[i
], sizeof (struct cpu_map_item
));
2068 if (i
!= cpu_map_count
) {
2069 cpu_map
[i
] = cpu_map
[cpu_map_count
];
2070 cpu_map
[cpu_map_count
] = NULL
;
2076 mutex_exit(&cpu_map_lock
);
2082 acpica_map_cpu(processorid_t cpuid
, UINT32 acpi_id
)
2085 ACPI_STATUS rc
= AE_OK
;
2086 struct cpu_map_item
*item
= NULL
;
2088 ASSERT(cpuid
!= -1);
2093 mutex_enter(&cpu_map_lock
);
2095 for (i
= 0; i
< cpu_map_count
; i
++) {
2096 if (cpu_map
[i
]->cpu_id
== cpuid
) {
2097 rc
= AE_ALREADY_EXISTS
;
2099 } else if (cpu_map
[i
]->proc_id
== acpi_id
) {
2100 ASSERT(item
== NULL
);
2106 if (item
->cpu_id
== -1) {
2107 item
->cpu_id
= cpuid
;
2109 rc
= AE_ALREADY_EXISTS
;
2111 } else if (cpu_map_count
>= INT_MAX
/ 2) {
2114 acpica_grow_cpu_map();
2115 ASSERT(cpu_map
!= NULL
);
2116 ASSERT(cpu_map_count
< cpu_map_count_max
);
2117 item
= kmem_zalloc(sizeof (*item
), KM_SLEEP
);
2118 item
->cpu_id
= cpuid
;
2119 item
->proc_id
= acpi_id
;
2120 item
->apic_id
= UINT32_MAX
;
2122 cpu_map
[cpu_map_count
] = item
;
2126 mutex_exit(&cpu_map_lock
);
2132 acpica_unmap_cpu(processorid_t cpuid
)
2135 ACPI_STATUS rc
= AE_NOT_EXIST
;
2137 ASSERT(cpuid
!= -1);
2142 mutex_enter(&cpu_map_lock
);
2143 for (i
= 0; i
< cpu_map_count
; i
++) {
2144 if (cpu_map
[i
]->cpu_id
!= cpuid
) {
2147 cpu_map
[i
]->cpu_id
= -1;
2148 /* Free item if no more reference. */
2149 if (cpu_map
[i
]->obj
== NULL
) {
2150 kmem_free(cpu_map
[i
], sizeof (struct cpu_map_item
));
2153 if (i
!= cpu_map_count
) {
2154 cpu_map
[i
] = cpu_map
[cpu_map_count
];
2155 cpu_map
[cpu_map_count
] = NULL
;
2161 mutex_exit(&cpu_map_lock
);
2167 acpica_get_cpu_object_by_cpuid(processorid_t cpuid
, ACPI_HANDLE
*hdlp
)
2170 ACPI_STATUS rc
= AE_NOT_EXIST
;
2172 ASSERT(cpuid
!= -1);
2177 mutex_enter(&cpu_map_lock
);
2178 for (i
= 0; i
< cpu_map_count
; i
++) {
2179 if (cpu_map
[i
]->cpu_id
== cpuid
&& cpu_map
[i
]->obj
!= NULL
) {
2180 *hdlp
= cpu_map
[i
]->obj
;
2185 mutex_exit(&cpu_map_lock
);
2191 acpica_get_cpu_object_by_procid(UINT32 procid
, ACPI_HANDLE
*hdlp
)
2194 ACPI_STATUS rc
= AE_NOT_EXIST
;
2196 mutex_enter(&cpu_map_lock
);
2197 for (i
= 0; i
< cpu_map_count
; i
++) {
2198 if (cpu_map
[i
]->proc_id
== procid
&& cpu_map
[i
]->obj
!= NULL
) {
2199 *hdlp
= cpu_map
[i
]->obj
;
2204 mutex_exit(&cpu_map_lock
);
2210 acpica_get_cpu_object_by_apicid(UINT32 apicid
, ACPI_HANDLE
*hdlp
)
2213 ACPI_STATUS rc
= AE_NOT_EXIST
;
2215 ASSERT(apicid
!= UINT32_MAX
);
2216 if (apicid
== UINT32_MAX
) {
2220 mutex_enter(&cpu_map_lock
);
2221 for (i
= 0; i
< cpu_map_count
; i
++) {
2222 if (cpu_map
[i
]->apic_id
== apicid
&& cpu_map
[i
]->obj
!= NULL
) {
2223 *hdlp
= cpu_map
[i
]->obj
;
2228 mutex_exit(&cpu_map_lock
);
2234 acpica_get_cpu_id_by_object(ACPI_HANDLE hdl
, processorid_t
*cpuidp
)
2237 ACPI_STATUS rc
= AE_NOT_EXIST
;
2239 ASSERT(cpuidp
!= NULL
);
2240 if (hdl
== NULL
|| cpuidp
== NULL
) {
2245 mutex_enter(&cpu_map_lock
);
2246 for (i
= 0; i
< cpu_map_count
; i
++) {
2247 if (cpu_map
[i
]->obj
== hdl
&& cpu_map
[i
]->cpu_id
!= -1) {
2248 *cpuidp
= cpu_map
[i
]->cpu_id
;
2253 mutex_exit(&cpu_map_lock
);
2259 acpica_get_apicid_by_object(ACPI_HANDLE hdl
, UINT32
*rp
)
2262 ACPI_STATUS rc
= AE_NOT_EXIST
;
2265 if (hdl
== NULL
|| rp
== NULL
) {
2270 mutex_enter(&cpu_map_lock
);
2271 for (i
= 0; i
< cpu_map_count
; i
++) {
2272 if (cpu_map
[i
]->obj
== hdl
&&
2273 cpu_map
[i
]->apic_id
!= UINT32_MAX
) {
2274 *rp
= cpu_map
[i
]->apic_id
;
2279 mutex_exit(&cpu_map_lock
);
2285 acpica_get_procid_by_object(ACPI_HANDLE hdl
, UINT32
*rp
)
2288 ACPI_STATUS rc
= AE_NOT_EXIST
;
2291 if (hdl
== NULL
|| rp
== NULL
) {
2296 mutex_enter(&cpu_map_lock
);
2297 for (i
= 0; i
< cpu_map_count
; i
++) {
2298 if (cpu_map
[i
]->obj
== hdl
) {
2299 *rp
= cpu_map
[i
]->proc_id
;
2304 mutex_exit(&cpu_map_lock
);
2310 acpica_set_core_feature(uint64_t features
)
2312 atomic_or_64(&acpica_core_features
, features
);
2316 acpica_clear_core_feature(uint64_t features
)
2318 atomic_and_64(&acpica_core_features
, ~features
);
2322 acpica_get_core_feature(uint64_t features
)
2324 return (acpica_core_features
& features
);
2328 acpica_set_devcfg_feature(uint64_t features
)
2330 atomic_or_64(&acpica_devcfg_features
, features
);
2334 acpica_clear_devcfg_feature(uint64_t features
)
2336 atomic_and_64(&acpica_devcfg_features
, ~features
);
2340 acpica_get_devcfg_feature(uint64_t features
)
2342 return (acpica_devcfg_features
& features
);
2346 acpica_get_global_FADT(ACPI_TABLE_FADT
**gbl_FADT
)
2348 *gbl_FADT
= &AcpiGbl_FADT
;
2352 acpica_write_cpupm_capabilities(boolean_t pstates
, boolean_t cstates
)
2354 if (pstates
&& AcpiGbl_FADT
.PstateControl
!= 0)
2355 (void) AcpiHwRegisterWrite(ACPI_REGISTER_SMI_COMMAND_BLOCK
,
2356 AcpiGbl_FADT
.PstateControl
);
2358 if (cstates
&& AcpiGbl_FADT
.CstControl
!= 0)
2359 (void) AcpiHwRegisterWrite(ACPI_REGISTER_SMI_COMMAND_BLOCK
,
2360 AcpiGbl_FADT
.CstControl
);
2364 acpi_strtoul(const char *str
, char **ep
, int base
)
2368 if (ddi_strtoul(str
, ep
, base
, &v
) != 0 || v
> ACPI_UINT32_MAX
) {
2369 return (ACPI_UINT32_MAX
);
2372 return ((uint32_t)v
);