13446Smrj /*
23446Smrj * CDDL HEADER START
33446Smrj *
43446Smrj * The contents of this file are subject to the terms of the
53446Smrj * Common Development and Distribution License (the "License").
63446Smrj * You may not use this file except in compliance with the License.
73446Smrj *
83446Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93446Smrj * or http://www.opensolaris.org/os/licensing.
103446Smrj * See the License for the specific language governing permissions
113446Smrj * and limitations under the License.
123446Smrj *
133446Smrj * When distributing Covered Code, include this CDDL HEADER in each
143446Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153446Smrj * If applicable, add the following below this CDDL HEADER, with the
163446Smrj * fields enclosed by brackets "[]" replaced with your own identifying
173446Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
183446Smrj *
193446Smrj * CDDL HEADER END
203446Smrj */
213446Smrj
223446Smrj /*
238906SEric.Saxe@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
243446Smrj * Use is subject to license terms.
253446Smrj */
263446Smrj /*
27*12004Sjiang.liu@intel.com * Copyright (c) 2009-2010, Intel Corporation.
289652SMichael.Corcoran@Sun.COM * All rights reserved.
299652SMichael.Corcoran@Sun.COM */
309652SMichael.Corcoran@Sun.COM /*
313446Smrj * ACPI CA OSL for Solaris x86
323446Smrj */
333446Smrj
343446Smrj #include <sys/types.h>
353446Smrj #include <sys/kmem.h>
363446Smrj #include <sys/psm.h>
373446Smrj #include <sys/pci_cfgspace.h>
389000SStuart.Maybee@Sun.COM #include <sys/apic.h>
393446Smrj #include <sys/ddi.h>
408973SDana.Myers@Sun.COM #include <sys/sunddi.h>
414667Smh27603 #include <sys/sunndi.h>
423446Smrj #include <sys/pci.h>
433446Smrj #include <sys/kobj.h>
443446Smrj #include <sys/taskq.h>
453446Smrj #include <sys/strlog.h>
4610394SMichael.Corcoran@Sun.COM #include <sys/x86_archext.h>
473446Smrj #include <sys/note.h>
4810235SDana.Myers@Sun.COM #include <sys/promif.h>
493446Smrj
5010147SMark.Haywood@Sun.COM #include <sys/acpi/accommon.h>
513446Smrj #include <sys/acpica.h>
523446Smrj
533446Smrj #define MAX_DAT_FILE_SIZE (64*1024)
543446Smrj
553446Smrj /* local functions */
563446Smrj static int CompressEisaID(char *np);
573446Smrj
584667Smh27603 static void scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus);
593446Smrj static int acpica_query_bbn_problem(void);
603446Smrj static int acpica_find_pcibus(int busno, ACPI_HANDLE *rh);
613446Smrj static int acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint);
624667Smh27603 static ACPI_STATUS acpica_set_devinfo(ACPI_HANDLE, dev_info_t *);
639652SMichael.Corcoran@Sun.COM static ACPI_STATUS acpica_unset_devinfo(ACPI_HANDLE);
6411225SDana.Myers@Sun.COM static void acpica_devinfo_handler(ACPI_HANDLE, void *);
653446Smrj
663446Smrj /*
673446Smrj * Event queue vars
683446Smrj */
693446Smrj int acpica_eventq_init = 0;
703446Smrj ddi_taskq_t *osl_eventq[OSL_EC_BURST_HANDLER+1];
713446Smrj
723446Smrj /*
737851SDana.Myers@Sun.COM * Priorities relative to minclsyspri that each taskq
747851SDana.Myers@Sun.COM * run at; OSL_NOTIFY_HANDLER needs to run at a higher
757851SDana.Myers@Sun.COM * priority than OSL_GPE_HANDLER. There's an implicit
767851SDana.Myers@Sun.COM * assumption that no priority here results in exceeding
777851SDana.Myers@Sun.COM * maxclsyspri.
787851SDana.Myers@Sun.COM * Note: these initializations need to match the order of
797851SDana.Myers@Sun.COM * ACPI_EXECUTE_TYPE.
807851SDana.Myers@Sun.COM */
817851SDana.Myers@Sun.COM int osl_eventq_pri_delta[OSL_EC_BURST_HANDLER+1] = {
827851SDana.Myers@Sun.COM 0, /* OSL_GLOBAL_LOCK_HANDLER */
837851SDana.Myers@Sun.COM 2, /* OSL_NOTIFY_HANDLER */
847851SDana.Myers@Sun.COM 0, /* OSL_GPE_HANDLER */
857851SDana.Myers@Sun.COM 0, /* OSL_DEBUGGER_THREAD */
867851SDana.Myers@Sun.COM 0, /* OSL_EC_POLL_HANDLER */
877851SDana.Myers@Sun.COM 0 /* OSL_EC_BURST_HANDLER */
887851SDana.Myers@Sun.COM };
897851SDana.Myers@Sun.COM
907851SDana.Myers@Sun.COM /*
913446Smrj * Note, if you change this path, you need to update
923446Smrj * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386
933446Smrj */
943446Smrj static char *acpi_table_path = "/boot/acpi/tables/";
953446Smrj
964667Smh27603 /* non-zero while scan_d2a_map() is working */
974667Smh27603 static int scanning_d2a_map = 0;
984667Smh27603 static int d2a_done = 0;
993446Smrj
1009652SMichael.Corcoran@Sun.COM /* features supported by ACPICA and ACPI device configuration. */
101*12004Sjiang.liu@intel.com uint64_t acpica_core_features = ACPI_FEATURE_OSI_MODULE;
1029652SMichael.Corcoran@Sun.COM static uint64_t acpica_devcfg_features = 0;
1039652SMichael.Corcoran@Sun.COM
1048122SKerry.Shu@Sun.COM /* set by acpi_poweroff() in PSMs and appm_ioctl() in acpippm for S3 */
1058122SKerry.Shu@Sun.COM int acpica_use_safe_delay = 0;
1063446Smrj
1074667Smh27603 /* CPU mapping data */
1084667Smh27603 struct cpu_map_item {
1099652SMichael.Corcoran@Sun.COM processorid_t cpu_id;
1107282Smishra UINT32 proc_id;
1119652SMichael.Corcoran@Sun.COM UINT32 apic_id;
1124667Smh27603 ACPI_HANDLE obj;
1134667Smh27603 };
1144667Smh27603
115*12004Sjiang.liu@intel.com kmutex_t cpu_map_lock;
1164667Smh27603 static struct cpu_map_item **cpu_map = NULL;
1179652SMichael.Corcoran@Sun.COM static int cpu_map_count_max = 0;
1184667Smh27603 static int cpu_map_count = 0;
1194667Smh27603 static int cpu_map_built = 0;
1204667Smh27603
12110394SMichael.Corcoran@Sun.COM /*
12210394SMichael.Corcoran@Sun.COM * On systems with the uppc PSM only, acpica_map_cpu() won't be called at all.
12310394SMichael.Corcoran@Sun.COM * This flag is used to check for uppc-only systems by detecting whether
12410394SMichael.Corcoran@Sun.COM * acpica_map_cpu() has been called or not.
12510394SMichael.Corcoran@Sun.COM */
12610394SMichael.Corcoran@Sun.COM static int cpu_map_called = 0;
12710394SMichael.Corcoran@Sun.COM
1284667Smh27603 static int acpi_has_broken_bbn = -1;
1294667Smh27603
1305155Smyers /* buffer for AcpiOsVprintf() */
1315155Smyers #define ACPI_OSL_PR_BUFLEN 1024
1325155Smyers static char *acpi_osl_pr_buffer = NULL;
1335155Smyers static int acpi_osl_pr_buflen;
1345155Smyers
1354667Smh27603 #define D2A_DEBUG
1364667Smh27603
1373446Smrj /*
1383446Smrj *
1393446Smrj */
1403446Smrj static void
discard_event_queues()1413446Smrj discard_event_queues()
1423446Smrj {
1433446Smrj int i;
1443446Smrj
1453446Smrj /*
1463446Smrj * destroy event queues
1473446Smrj */
1483446Smrj for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
1493446Smrj if (osl_eventq[i])
1503446Smrj ddi_taskq_destroy(osl_eventq[i]);
1513446Smrj }
1523446Smrj }
1533446Smrj
1543446Smrj
1553446Smrj /*
1563446Smrj *
1573446Smrj */
1583446Smrj static ACPI_STATUS
init_event_queues()1593446Smrj init_event_queues()
1603446Smrj {
1613446Smrj char namebuf[32];
1623446Smrj int i, error = 0;
1633446Smrj
1643446Smrj /*
1653446Smrj * Initialize event queues
1663446Smrj */
1673446Smrj
1687851SDana.Myers@Sun.COM /* Always allocate only 1 thread per queue to force FIFO execution */
1693446Smrj for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
1703446Smrj snprintf(namebuf, 32, "ACPI%d", i);
1717851SDana.Myers@Sun.COM osl_eventq[i] = ddi_taskq_create(NULL, namebuf, 1,
1727851SDana.Myers@Sun.COM osl_eventq_pri_delta[i] + minclsyspri, 0);
1733446Smrj if (osl_eventq[i] == NULL)
1743446Smrj error++;
1753446Smrj }
1763446Smrj
1773446Smrj if (error != 0) {
1783446Smrj discard_event_queues();
1793446Smrj #ifdef DEBUG
1803446Smrj cmn_err(CE_WARN, "!acpica: could not initialize event queues");
1813446Smrj #endif
1823446Smrj return (AE_ERROR);
1833446Smrj }
1843446Smrj
1853446Smrj acpica_eventq_init = 1;
1863446Smrj return (AE_OK);
1873446Smrj }
1883446Smrj
1893446Smrj /*
1905155Smyers * One-time initialization of OSL layer
1913446Smrj */
1923446Smrj ACPI_STATUS
AcpiOsInitialize(void)1933446Smrj AcpiOsInitialize(void)
1943446Smrj {
1955155Smyers /*
1965155Smyers * Allocate buffer for AcpiOsVprintf() here to avoid
1975155Smyers * kmem_alloc()/kmem_free() at high PIL
1985155Smyers */
1995155Smyers acpi_osl_pr_buffer = kmem_alloc(ACPI_OSL_PR_BUFLEN, KM_SLEEP);
2005155Smyers if (acpi_osl_pr_buffer != NULL)
2015155Smyers acpi_osl_pr_buflen = ACPI_OSL_PR_BUFLEN;
2025155Smyers
2033446Smrj return (AE_OK);
2043446Smrj }
2053446Smrj
2063446Smrj /*
2075155Smyers * One-time shut-down of OSL layer
2083446Smrj */
2093446Smrj ACPI_STATUS
AcpiOsTerminate(void)2103446Smrj AcpiOsTerminate(void)
2113446Smrj {
2123446Smrj
2135155Smyers if (acpi_osl_pr_buffer != NULL)
2145155Smyers kmem_free(acpi_osl_pr_buffer, acpi_osl_pr_buflen);
2155155Smyers
2163446Smrj discard_event_queues();
2173446Smrj return (AE_OK);
2183446Smrj }
2193446Smrj
2203446Smrj
2217851SDana.Myers@Sun.COM ACPI_PHYSICAL_ADDRESS
AcpiOsGetRootPointer()2227851SDana.Myers@Sun.COM AcpiOsGetRootPointer()
2233446Smrj {
2247851SDana.Myers@Sun.COM ACPI_PHYSICAL_ADDRESS Address;
2253446Smrj
2263446Smrj /*
2273446Smrj * For EFI firmware, the root pointer is defined in EFI systab.
2283446Smrj * The boot code process the table and put the physical address
2293446Smrj * in the acpi-root-tab property.
2303446Smrj */
2319388SDana.Myers@Sun.COM Address = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(),
2329388SDana.Myers@Sun.COM DDI_PROP_DONTPASS, "acpi-root-tab", NULL);
2337851SDana.Myers@Sun.COM
2347851SDana.Myers@Sun.COM if ((Address == NULL) && ACPI_FAILURE(AcpiFindRootPointer(&Address)))
2357851SDana.Myers@Sun.COM Address = NULL;
2367851SDana.Myers@Sun.COM
2377851SDana.Myers@Sun.COM return (Address);
2383446Smrj }
2393446Smrj
2403446Smrj /*ARGSUSED*/
2413446Smrj ACPI_STATUS
AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES * InitVal,ACPI_STRING * NewVal)2423446Smrj AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *InitVal,
2433446Smrj ACPI_STRING *NewVal)
2443446Smrj {
2453446Smrj
2463446Smrj *NewVal = 0;
2473446Smrj return (AE_OK);
2483446Smrj }
2493446Smrj
2503446Smrj static void
acpica_strncpy(char * dest,const char * src,int len)2513446Smrj acpica_strncpy(char *dest, const char *src, int len)
2523446Smrj {
2533446Smrj
2543446Smrj /*LINTED*/
2553446Smrj while ((*dest++ = *src++) && (--len > 0))
2563446Smrj /* copy the string */;
2573446Smrj *dest = '\0';
2583446Smrj }
2593446Smrj
2603446Smrj ACPI_STATUS
AcpiOsTableOverride(ACPI_TABLE_HEADER * ExistingTable,ACPI_TABLE_HEADER ** NewTable)2613446Smrj AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable,
2623446Smrj ACPI_TABLE_HEADER **NewTable)
2633446Smrj {
2643446Smrj char signature[5];
2653446Smrj char oemid[7];
2663446Smrj char oemtableid[9];
2673446Smrj struct _buf *file;
2683446Smrj char *buf1, *buf2;
2693446Smrj int count;
2703446Smrj char acpi_table_loc[128];
2713446Smrj
2723446Smrj acpica_strncpy(signature, ExistingTable->Signature, 4);
2733446Smrj acpica_strncpy(oemid, ExistingTable->OemId, 6);
2743446Smrj acpica_strncpy(oemtableid, ExistingTable->OemTableId, 8);
2753446Smrj
2763446Smrj #ifdef DEBUG
2773446Smrj cmn_err(CE_NOTE, "!acpica: table [%s] v%d OEM ID [%s]"
2784476Smyers " OEM TABLE ID [%s] OEM rev %x",
2794476Smyers signature, ExistingTable->Revision, oemid, oemtableid,
2804476Smyers ExistingTable->OemRevision);
2813446Smrj #endif
2823446Smrj
2833446Smrj /* File name format is "signature_oemid_oemtableid.dat" */
2843446Smrj (void) strcpy(acpi_table_loc, acpi_table_path);
2853446Smrj (void) strcat(acpi_table_loc, signature); /* for example, DSDT */
2863446Smrj (void) strcat(acpi_table_loc, "_");
2873446Smrj (void) strcat(acpi_table_loc, oemid); /* for example, IntelR */
2883446Smrj (void) strcat(acpi_table_loc, "_");
2893446Smrj (void) strcat(acpi_table_loc, oemtableid); /* for example, AWRDACPI */
2903446Smrj (void) strcat(acpi_table_loc, ".dat");
2913446Smrj
2923446Smrj file = kobj_open_file(acpi_table_loc);
2933446Smrj if (file == (struct _buf *)-1) {
2943446Smrj *NewTable = 0;
2953446Smrj return (AE_OK);
2963446Smrj } else {
2973446Smrj buf1 = (char *)kmem_alloc(MAX_DAT_FILE_SIZE, KM_SLEEP);
2983446Smrj count = kobj_read_file(file, buf1, MAX_DAT_FILE_SIZE-1, 0);
2993446Smrj if (count >= MAX_DAT_FILE_SIZE) {
3003446Smrj cmn_err(CE_WARN, "!acpica: table %s file size too big",
3013446Smrj acpi_table_loc);
3023446Smrj *NewTable = 0;
3033446Smrj } else {
3043446Smrj buf2 = (char *)kmem_alloc(count, KM_SLEEP);
3053446Smrj (void) memcpy(buf2, buf1, count);
3063446Smrj *NewTable = (ACPI_TABLE_HEADER *)buf2;
3073446Smrj cmn_err(CE_NOTE, "!acpica: replacing table: %s",
3083446Smrj acpi_table_loc);
3093446Smrj }
3103446Smrj }
3113446Smrj kobj_close_file(file);
3123446Smrj kmem_free(buf1, MAX_DAT_FILE_SIZE);
3133446Smrj
3143446Smrj return (AE_OK);
3153446Smrj }
3163446Smrj
3173446Smrj
3183446Smrj /*
3193446Smrj * ACPI semaphore implementation
3203446Smrj */
3213446Smrj typedef struct {
3223446Smrj kmutex_t mutex;
3233446Smrj kcondvar_t cv;
3243446Smrj uint32_t available;
3253446Smrj uint32_t initial;
3263446Smrj uint32_t maximum;
3273446Smrj } acpi_sema_t;
3283446Smrj
3293446Smrj /*
3303446Smrj *
3313446Smrj */
3323446Smrj void
acpi_sema_init(acpi_sema_t * sp,unsigned max,unsigned count)3333446Smrj acpi_sema_init(acpi_sema_t *sp, unsigned max, unsigned count)
3343446Smrj {
3353446Smrj mutex_init(&sp->mutex, NULL, MUTEX_DRIVER, NULL);
3363446Smrj cv_init(&sp->cv, NULL, CV_DRIVER, NULL);
3373446Smrj /* no need to enter mutex here at creation */
3383446Smrj sp->available = count;
3393446Smrj sp->initial = count;
3403446Smrj sp->maximum = max;
3413446Smrj }
3423446Smrj
3433446Smrj /*
3443446Smrj *
3453446Smrj */
3463446Smrj void
acpi_sema_destroy(acpi_sema_t * sp)3473446Smrj acpi_sema_destroy(acpi_sema_t *sp)
3483446Smrj {
3493446Smrj
3503446Smrj cv_destroy(&sp->cv);
3513446Smrj mutex_destroy(&sp->mutex);
3523446Smrj }
3533446Smrj
3543446Smrj /*
3553446Smrj *
3563446Smrj */
3573446Smrj ACPI_STATUS
acpi_sema_p(acpi_sema_t * sp,unsigned count,uint16_t wait_time)3583446Smrj acpi_sema_p(acpi_sema_t *sp, unsigned count, uint16_t wait_time)
3593446Smrj {
3603446Smrj ACPI_STATUS rv = AE_OK;
3613446Smrj clock_t deadline;
3623446Smrj
3633446Smrj mutex_enter(&sp->mutex);
3643446Smrj
3653446Smrj if (sp->available >= count) {
3663446Smrj /*
3673446Smrj * Enough units available, no blocking
3683446Smrj */
3693446Smrj sp->available -= count;
3703446Smrj mutex_exit(&sp->mutex);
3713446Smrj return (rv);
3723446Smrj } else if (wait_time == 0) {
3733446Smrj /*
3743446Smrj * Not enough units available and timeout
3753446Smrj * specifies no blocking
3763446Smrj */
3773446Smrj rv = AE_TIME;
3783446Smrj mutex_exit(&sp->mutex);
3793446Smrj return (rv);
3803446Smrj }
3813446Smrj
3823446Smrj /*
3833446Smrj * Not enough units available and timeout specifies waiting
3843446Smrj */
3853446Smrj if (wait_time != ACPI_WAIT_FOREVER)
3863446Smrj deadline = ddi_get_lbolt() +
3873446Smrj (clock_t)drv_usectohz(wait_time * 1000);
3883446Smrj
3893446Smrj do {
3903446Smrj if (wait_time == ACPI_WAIT_FOREVER)
3913446Smrj cv_wait(&sp->cv, &sp->mutex);
3923446Smrj else if (cv_timedwait(&sp->cv, &sp->mutex, deadline) < 0) {
3933446Smrj rv = AE_TIME;
3943446Smrj break;
3953446Smrj }
3963446Smrj } while (sp->available < count);
3973446Smrj
3983446Smrj /* if we dropped out of the wait with AE_OK, we got the units */
3993446Smrj if (rv == AE_OK)
4003446Smrj sp->available -= count;
4013446Smrj
4023446Smrj mutex_exit(&sp->mutex);
4033446Smrj return (rv);
4043446Smrj }
4053446Smrj
4063446Smrj /*
4073446Smrj *
4083446Smrj */
4093446Smrj void
acpi_sema_v(acpi_sema_t * sp,unsigned count)4103446Smrj acpi_sema_v(acpi_sema_t *sp, unsigned count)
4113446Smrj {
4123446Smrj mutex_enter(&sp->mutex);
4133446Smrj sp->available += count;
4143446Smrj cv_broadcast(&sp->cv);
4153446Smrj mutex_exit(&sp->mutex);
4163446Smrj }
4173446Smrj
4183446Smrj
4193446Smrj ACPI_STATUS
AcpiOsCreateSemaphore(UINT32 MaxUnits,UINT32 InitialUnits,ACPI_HANDLE * OutHandle)4203446Smrj AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
4213446Smrj ACPI_HANDLE *OutHandle)
4223446Smrj {
4233446Smrj acpi_sema_t *sp;
4243446Smrj
4253446Smrj if ((OutHandle == NULL) || (InitialUnits > MaxUnits))
4263446Smrj return (AE_BAD_PARAMETER);
4273446Smrj
4283446Smrj sp = (acpi_sema_t *)kmem_alloc(sizeof (acpi_sema_t), KM_SLEEP);
4293446Smrj acpi_sema_init(sp, MaxUnits, InitialUnits);
4303446Smrj *OutHandle = (ACPI_HANDLE)sp;
4313446Smrj return (AE_OK);
4323446Smrj }
4333446Smrj
4343446Smrj
4353446Smrj ACPI_STATUS
AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)4363446Smrj AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
4373446Smrj {
4383446Smrj
4393446Smrj if (Handle == NULL)
4403446Smrj return (AE_BAD_PARAMETER);
4413446Smrj
4423446Smrj acpi_sema_destroy((acpi_sema_t *)Handle);
4433446Smrj kmem_free((void *)Handle, sizeof (acpi_sema_t));
4443446Smrj return (AE_OK);
4453446Smrj }
4463446Smrj
4473446Smrj ACPI_STATUS
AcpiOsWaitSemaphore(ACPI_HANDLE Handle,UINT32 Units,UINT16 Timeout)4483446Smrj AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
4493446Smrj {
4503446Smrj
4513446Smrj if ((Handle == NULL) || (Units < 1))
4523446Smrj return (AE_BAD_PARAMETER);
4533446Smrj
4543446Smrj return (acpi_sema_p((acpi_sema_t *)Handle, Units, Timeout));
4553446Smrj }
4563446Smrj
4573446Smrj ACPI_STATUS
AcpiOsSignalSemaphore(ACPI_HANDLE Handle,UINT32 Units)4583446Smrj AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
4593446Smrj {
4603446Smrj
4613446Smrj if ((Handle == NULL) || (Units < 1))
4623446Smrj return (AE_BAD_PARAMETER);
4633446Smrj
4643446Smrj acpi_sema_v((acpi_sema_t *)Handle, Units);
4653446Smrj return (AE_OK);
4663446Smrj }
4673446Smrj
4683446Smrj ACPI_STATUS
AcpiOsCreateLock(ACPI_HANDLE * OutHandle)4693446Smrj AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
4703446Smrj {
4713446Smrj kmutex_t *mp;
4723446Smrj
4733446Smrj if (OutHandle == NULL)
4743446Smrj return (AE_BAD_PARAMETER);
4753446Smrj
4763446Smrj mp = (kmutex_t *)kmem_alloc(sizeof (kmutex_t), KM_SLEEP);
4773446Smrj mutex_init(mp, NULL, MUTEX_DRIVER, NULL);
4783446Smrj *OutHandle = (ACPI_HANDLE)mp;
4793446Smrj return (AE_OK);
4803446Smrj }
4813446Smrj
4823446Smrj void
AcpiOsDeleteLock(ACPI_HANDLE Handle)4833446Smrj AcpiOsDeleteLock(ACPI_HANDLE Handle)
4843446Smrj {
4853446Smrj
4863446Smrj if (Handle == NULL)
4873446Smrj return;
4883446Smrj
4893446Smrj mutex_destroy((kmutex_t *)Handle);
4903446Smrj kmem_free((void *)Handle, sizeof (kmutex_t));
4913446Smrj }
4923446Smrj
4937851SDana.Myers@Sun.COM ACPI_CPU_FLAGS
AcpiOsAcquireLock(ACPI_HANDLE Handle)4943446Smrj AcpiOsAcquireLock(ACPI_HANDLE Handle)
4953446Smrj {
4963446Smrj
4978906SEric.Saxe@Sun.COM
4988906SEric.Saxe@Sun.COM if (Handle == NULL)
4998906SEric.Saxe@Sun.COM return (AE_BAD_PARAMETER);
5008906SEric.Saxe@Sun.COM
5018906SEric.Saxe@Sun.COM if (curthread == CPU->cpu_idle_thread) {
5028906SEric.Saxe@Sun.COM while (!mutex_tryenter((kmutex_t *)Handle))
5038906SEric.Saxe@Sun.COM /* spin */;
5048906SEric.Saxe@Sun.COM } else
5058906SEric.Saxe@Sun.COM mutex_enter((kmutex_t *)Handle);
5068906SEric.Saxe@Sun.COM return (AE_OK);
5073446Smrj }
5083446Smrj
5093446Smrj void
AcpiOsReleaseLock(ACPI_HANDLE Handle,ACPI_CPU_FLAGS Flags)5107851SDana.Myers@Sun.COM AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_CPU_FLAGS Flags)
5113446Smrj {
5123446Smrj _NOTE(ARGUNUSED(Flags))
5133446Smrj
5143446Smrj mutex_exit((kmutex_t *)Handle);
5153446Smrj }
5163446Smrj
5173446Smrj
5183446Smrj void *
AcpiOsAllocate(ACPI_SIZE Size)5193446Smrj AcpiOsAllocate(ACPI_SIZE Size)
5203446Smrj {
5213446Smrj ACPI_SIZE *tmp_ptr;
5223446Smrj
5233446Smrj Size += sizeof (Size);
5243446Smrj tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP);
5253446Smrj *tmp_ptr++ = Size;
5263446Smrj return (tmp_ptr);
5273446Smrj }
5283446Smrj
5293446Smrj void
AcpiOsFree(void * Memory)5303446Smrj AcpiOsFree(void *Memory)
5313446Smrj {
5323446Smrj ACPI_SIZE size, *tmp_ptr;
5333446Smrj
5343446Smrj tmp_ptr = (ACPI_SIZE *)Memory;
5353446Smrj tmp_ptr -= 1;
5363446Smrj size = *tmp_ptr;
5373446Smrj kmem_free(tmp_ptr, size);
5383446Smrj }
5393446Smrj
5409000SStuart.Maybee@Sun.COM static int napics_found; /* number of ioapic addresses in array */
5419000SStuart.Maybee@Sun.COM static ACPI_PHYSICAL_ADDRESS ioapic_paddr[MAX_IO_APIC];
5429000SStuart.Maybee@Sun.COM static ACPI_TABLE_MADT *acpi_mapic_dtp = NULL;
5439000SStuart.Maybee@Sun.COM static void *dummy_ioapicadr;
5449000SStuart.Maybee@Sun.COM
5459000SStuart.Maybee@Sun.COM void
acpica_find_ioapics(void)5469000SStuart.Maybee@Sun.COM acpica_find_ioapics(void)
5479000SStuart.Maybee@Sun.COM {
5489000SStuart.Maybee@Sun.COM int madt_seen, madt_size;
5499000SStuart.Maybee@Sun.COM ACPI_SUBTABLE_HEADER *ap;
5509000SStuart.Maybee@Sun.COM ACPI_MADT_IO_APIC *mia;
5519000SStuart.Maybee@Sun.COM
5529000SStuart.Maybee@Sun.COM if (acpi_mapic_dtp != NULL)
5539000SStuart.Maybee@Sun.COM return; /* already parsed table */
5549000SStuart.Maybee@Sun.COM if (AcpiGetTable(ACPI_SIG_MADT, 1,
5559000SStuart.Maybee@Sun.COM (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK)
5569000SStuart.Maybee@Sun.COM return;
5579000SStuart.Maybee@Sun.COM
5589000SStuart.Maybee@Sun.COM napics_found = 0;
5599000SStuart.Maybee@Sun.COM
5609000SStuart.Maybee@Sun.COM /*
5619000SStuart.Maybee@Sun.COM * Search the MADT for ioapics
5629000SStuart.Maybee@Sun.COM */
5639000SStuart.Maybee@Sun.COM ap = (ACPI_SUBTABLE_HEADER *) (acpi_mapic_dtp + 1);
5649000SStuart.Maybee@Sun.COM madt_size = acpi_mapic_dtp->Header.Length;
5659000SStuart.Maybee@Sun.COM madt_seen = sizeof (*acpi_mapic_dtp);
5669000SStuart.Maybee@Sun.COM
5679000SStuart.Maybee@Sun.COM while (madt_seen < madt_size) {
5689000SStuart.Maybee@Sun.COM
5699000SStuart.Maybee@Sun.COM switch (ap->Type) {
5709000SStuart.Maybee@Sun.COM case ACPI_MADT_TYPE_IO_APIC:
5719000SStuart.Maybee@Sun.COM mia = (ACPI_MADT_IO_APIC *) ap;
5729000SStuart.Maybee@Sun.COM if (napics_found < MAX_IO_APIC) {
5739000SStuart.Maybee@Sun.COM ioapic_paddr[napics_found++] =
5749000SStuart.Maybee@Sun.COM (ACPI_PHYSICAL_ADDRESS)
5759000SStuart.Maybee@Sun.COM (mia->Address & PAGEMASK);
5769000SStuart.Maybee@Sun.COM }
5779000SStuart.Maybee@Sun.COM break;
5789000SStuart.Maybee@Sun.COM
5799000SStuart.Maybee@Sun.COM default:
5809000SStuart.Maybee@Sun.COM break;
5819000SStuart.Maybee@Sun.COM }
5829000SStuart.Maybee@Sun.COM
5839000SStuart.Maybee@Sun.COM /* advance to next entry */
5849000SStuart.Maybee@Sun.COM madt_seen += ap->Length;
5859000SStuart.Maybee@Sun.COM ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length);
5869000SStuart.Maybee@Sun.COM }
5879000SStuart.Maybee@Sun.COM if (dummy_ioapicadr == NULL)
5889000SStuart.Maybee@Sun.COM dummy_ioapicadr = kmem_zalloc(PAGESIZE, KM_SLEEP);
5899000SStuart.Maybee@Sun.COM }
5909000SStuart.Maybee@Sun.COM
5919000SStuart.Maybee@Sun.COM
5927851SDana.Myers@Sun.COM void *
AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress,ACPI_SIZE Size)5937851SDana.Myers@Sun.COM AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size)
5943446Smrj {
5959000SStuart.Maybee@Sun.COM int i;
5969000SStuart.Maybee@Sun.COM
5979000SStuart.Maybee@Sun.COM /*
5989000SStuart.Maybee@Sun.COM * If the iopaic address table is populated, check if trying
5999000SStuart.Maybee@Sun.COM * to access an ioapic. Instead, return a pointer to a dummy ioapic.
6009000SStuart.Maybee@Sun.COM */
6019000SStuart.Maybee@Sun.COM for (i = 0; i < napics_found; i++) {
6029000SStuart.Maybee@Sun.COM if ((PhysicalAddress & PAGEMASK) == ioapic_paddr[i])
6039000SStuart.Maybee@Sun.COM return (dummy_ioapicadr);
6049000SStuart.Maybee@Sun.COM }
6053446Smrj /* FUTUREWORK: test PhysicalAddress for > 32 bits */
6067851SDana.Myers@Sun.COM return (psm_map_new((paddr_t)PhysicalAddress,
6077851SDana.Myers@Sun.COM (size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ));
6083446Smrj }
6093446Smrj
6103446Smrj void
AcpiOsUnmapMemory(void * LogicalAddress,ACPI_SIZE Size)6113446Smrj AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
6123446Smrj {
6139000SStuart.Maybee@Sun.COM /*
6149000SStuart.Maybee@Sun.COM * Check if trying to unmap dummy ioapic address.
6159000SStuart.Maybee@Sun.COM */
6169000SStuart.Maybee@Sun.COM if (LogicalAddress == dummy_ioapicadr)
6179000SStuart.Maybee@Sun.COM return;
6183446Smrj
6193446Smrj psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
6203446Smrj }
6213446Smrj
6223446Smrj /*ARGSUSED*/
6233446Smrj ACPI_STATUS
AcpiOsGetPhysicalAddress(void * LogicalAddress,ACPI_PHYSICAL_ADDRESS * PhysicalAddress)6243446Smrj AcpiOsGetPhysicalAddress(void *LogicalAddress,
6253446Smrj ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
6263446Smrj {
6273446Smrj
6283446Smrj /* UNIMPLEMENTED: not invoked by ACPI CA code */
6293446Smrj return (AE_NOT_IMPLEMENTED);
6303446Smrj }
6313446Smrj
6323446Smrj
6333446Smrj ACPI_OSD_HANDLER acpi_isr;
6343446Smrj void *acpi_isr_context;
6353446Smrj
6363446Smrj uint_t
acpi_wrapper_isr(char * arg)6373446Smrj acpi_wrapper_isr(char *arg)
6383446Smrj {
6393446Smrj _NOTE(ARGUNUSED(arg))
6403446Smrj
6413446Smrj int status;
6423446Smrj
6433446Smrj status = (*acpi_isr)(acpi_isr_context);
6443446Smrj
6453446Smrj if (status == ACPI_INTERRUPT_HANDLED) {
6463446Smrj return (DDI_INTR_CLAIMED);
6473446Smrj } else {
6483446Smrj return (DDI_INTR_UNCLAIMED);
6493446Smrj }
6503446Smrj }
6513446Smrj
6523446Smrj static int acpi_intr_hooked = 0;
6533446Smrj
6543446Smrj ACPI_STATUS
AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,ACPI_OSD_HANDLER ServiceRoutine,void * Context)6553446Smrj AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
6563446Smrj ACPI_OSD_HANDLER ServiceRoutine,
6573446Smrj void *Context)
6583446Smrj {
6593446Smrj _NOTE(ARGUNUSED(InterruptNumber))
6603446Smrj
6613446Smrj int retval;
6623446Smrj int sci_vect;
6633446Smrj iflag_t sci_flags;
6643446Smrj
6653446Smrj acpi_isr = ServiceRoutine;
6663446Smrj acpi_isr_context = Context;
6673446Smrj
6683446Smrj /*
6693446Smrj * Get SCI (adjusted for PIC/APIC mode if necessary)
6703446Smrj */
6713446Smrj if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) {
6723446Smrj return (AE_ERROR);
6733446Smrj }
6743446Smrj
6753446Smrj #ifdef DEBUG
6763446Smrj cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect);
6773446Smrj #endif
6783446Smrj
6793446Smrj retval = add_avintr(NULL, SCI_IPL, (avfunc)acpi_wrapper_isr,
6804476Smyers "ACPI SCI", sci_vect, NULL, NULL, NULL, NULL);
6813446Smrj if (retval) {
6823446Smrj acpi_intr_hooked = 1;
6833446Smrj return (AE_OK);
6843446Smrj } else
6853446Smrj return (AE_BAD_PARAMETER);
6863446Smrj }
6873446Smrj
6883446Smrj ACPI_STATUS
AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,ACPI_OSD_HANDLER ServiceRoutine)6893446Smrj AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
6903446Smrj ACPI_OSD_HANDLER ServiceRoutine)
6913446Smrj {
6923446Smrj _NOTE(ARGUNUSED(ServiceRoutine))
6933446Smrj
6943446Smrj #ifdef DEBUG
6953446Smrj cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber);
6963446Smrj #endif
6973446Smrj if (acpi_intr_hooked) {
6983446Smrj rem_avintr(NULL, LOCK_LEVEL - 1, (avfunc)acpi_wrapper_isr,
6994476Smyers InterruptNumber);
7003446Smrj acpi_intr_hooked = 0;
7013446Smrj }
7023446Smrj return (AE_OK);
7033446Smrj }
7043446Smrj
7053446Smrj
7063446Smrj ACPI_THREAD_ID
AcpiOsGetThreadId(void)7073446Smrj AcpiOsGetThreadId(void)
7083446Smrj {
7093446Smrj /*
7109980SDana.Myers@Sun.COM * ACPI CA doesn't care what actual value is returned as long
7119980SDana.Myers@Sun.COM * as it is non-zero and unique to each existing thread.
7129980SDana.Myers@Sun.COM * ACPI CA assumes that thread ID is castable to a pointer,
7139980SDana.Myers@Sun.COM * so we use the current thread pointer.
7143446Smrj */
7159980SDana.Myers@Sun.COM return (curthread);
7163446Smrj }
7173446Smrj
7183446Smrj /*
7193446Smrj *
7203446Smrj */
7213446Smrj ACPI_STATUS
AcpiOsExecute(ACPI_EXECUTE_TYPE Type,ACPI_OSD_EXEC_CALLBACK Function,void * Context)7223446Smrj AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
7233446Smrj void *Context)
7243446Smrj {
7253446Smrj
7263446Smrj if (!acpica_eventq_init) {
7273446Smrj /*
7283446Smrj * Create taskqs for event handling
7293446Smrj */
7303446Smrj if (init_event_queues() != AE_OK)
7314476Smyers return (AE_ERROR);
7323446Smrj }
7333446Smrj
7343446Smrj if (ddi_taskq_dispatch(osl_eventq[Type], Function, Context,
7353446Smrj DDI_NOSLEEP) == DDI_FAILURE) {
7363446Smrj #ifdef DEBUG
7373446Smrj cmn_err(CE_WARN, "!acpica: unable to dispatch event");
7383446Smrj #endif
7393446Smrj return (AE_ERROR);
7403446Smrj }
7413446Smrj return (AE_OK);
7423446Smrj
7433446Smrj }
7443446Smrj
7453446Smrj void
AcpiOsSleep(ACPI_INTEGER Milliseconds)7463446Smrj AcpiOsSleep(ACPI_INTEGER Milliseconds)
7473446Smrj {
7483446Smrj /*
7498122SKerry.Shu@Sun.COM * During kernel startup, before the first tick interrupt
7508122SKerry.Shu@Sun.COM * has taken place, we can't call delay; very late in
7518122SKerry.Shu@Sun.COM * kernel shutdown or suspend/resume, clock interrupts
7523446Smrj * are blocked, so delay doesn't work then either.
7533446Smrj * So we busy wait if lbolt == 0 (kernel startup)
7548122SKerry.Shu@Sun.COM * or if acpica_use_safe_delay has been set to a
7558122SKerry.Shu@Sun.COM * non-zero value.
7563446Smrj */
7578122SKerry.Shu@Sun.COM if ((ddi_get_lbolt() == 0) || acpica_use_safe_delay)
7583446Smrj drv_usecwait(Milliseconds * 1000);
7593446Smrj else
7603446Smrj delay(drv_usectohz(Milliseconds * 1000));
7613446Smrj }
7623446Smrj
7633446Smrj void
AcpiOsStall(UINT32 Microseconds)7643446Smrj AcpiOsStall(UINT32 Microseconds)
7653446Smrj {
7663446Smrj drv_usecwait(Microseconds);
7673446Smrj }
7683446Smrj
7693446Smrj
7703446Smrj /*
7713446Smrj * Implementation of "Windows 2001" compatible I/O permission map
7723446Smrj *
7733446Smrj */
7743446Smrj #define OSL_IO_NONE (0)
7753446Smrj #define OSL_IO_READ (1<<0)
7763446Smrj #define OSL_IO_WRITE (1<<1)
7773446Smrj #define OSL_IO_RW (OSL_IO_READ | OSL_IO_WRITE)
7783446Smrj #define OSL_IO_TERM (1<<2)
7793446Smrj #define OSL_IO_DEFAULT OSL_IO_RW
7803446Smrj
7813446Smrj static struct io_perm {
7823446Smrj ACPI_IO_ADDRESS low;
7833446Smrj ACPI_IO_ADDRESS high;
7843446Smrj uint8_t perm;
7853446Smrj } osl_io_perm[] = {
78610457SSaurabh.Mishra@Sun.COM { 0xcf8, 0xd00, OSL_IO_TERM | OSL_IO_RW}
7873446Smrj };
7883446Smrj
7893446Smrj
7903446Smrj /*
7913446Smrj *
7923446Smrj */
7933446Smrj static struct io_perm *
osl_io_find_perm(ACPI_IO_ADDRESS addr)7943446Smrj osl_io_find_perm(ACPI_IO_ADDRESS addr)
7953446Smrj {
7963446Smrj struct io_perm *p;
7973446Smrj
7983446Smrj p = osl_io_perm;
7993446Smrj while (p != NULL) {
8003446Smrj if ((p->low <= addr) && (addr <= p->high))
8013446Smrj break;
8023446Smrj p = (p->perm & OSL_IO_TERM) ? NULL : p+1;
8033446Smrj }
8043446Smrj
8053446Smrj return (p);
8063446Smrj }
8073446Smrj
8083446Smrj /*
8093446Smrj *
8103446Smrj */
8113446Smrj ACPI_STATUS
AcpiOsReadPort(ACPI_IO_ADDRESS Address,UINT32 * Value,UINT32 Width)8123446Smrj AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
8133446Smrj {
8143446Smrj struct io_perm *p;
8153446Smrj
8163446Smrj /* verify permission */
8173446Smrj p = osl_io_find_perm(Address);
8183446Smrj if (p && (p->perm & OSL_IO_READ) == 0) {
8193446Smrj cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted",
8204476Smyers (long)Address, Width);
8213446Smrj *Value = 0xffffffff;
8223446Smrj return (AE_ERROR);
8233446Smrj }
8243446Smrj
8253446Smrj switch (Width) {
8263446Smrj case 8:
8273446Smrj *Value = inb(Address);
8283446Smrj break;
8293446Smrj case 16:
8303446Smrj *Value = inw(Address);
8313446Smrj break;
8323446Smrj case 32:
8333446Smrj *Value = inl(Address);
8343446Smrj break;
8353446Smrj default:
8363446Smrj cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed",
8374476Smyers (long)Address, Width);
8383446Smrj return (AE_BAD_PARAMETER);
8393446Smrj }
8403446Smrj return (AE_OK);
8413446Smrj }
8423446Smrj
8433446Smrj ACPI_STATUS
AcpiOsWritePort(ACPI_IO_ADDRESS Address,UINT32 Value,UINT32 Width)8443446Smrj AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
8453446Smrj {
8463446Smrj struct io_perm *p;
8473446Smrj
8483446Smrj /* verify permission */
8493446Smrj p = osl_io_find_perm(Address);
8503446Smrj if (p && (p->perm & OSL_IO_WRITE) == 0) {
8513446Smrj cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted",
8523446Smrj (long)Address, Width);
8533446Smrj return (AE_ERROR);
8543446Smrj }
8553446Smrj
8563446Smrj switch (Width) {
8573446Smrj case 8:
8583446Smrj outb(Address, Value);
8593446Smrj break;
8603446Smrj case 16:
8613446Smrj outw(Address, Value);
8623446Smrj break;
8633446Smrj case 32:
8643446Smrj outl(Address, Value);
8653446Smrj break;
8663446Smrj default:
8673446Smrj cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed",
8683446Smrj (long)Address, Width);
8693446Smrj return (AE_BAD_PARAMETER);
8703446Smrj }
8713446Smrj return (AE_OK);
8723446Smrj }
8733446Smrj
8743446Smrj
8753446Smrj /*
8763446Smrj *
8773446Smrj */
8783446Smrj
8793446Smrj #define OSL_RW(ptr, val, type, rw) \
8803446Smrj { if (rw) *((type *)(ptr)) = *((type *) val); \
8813446Smrj else *((type *) val) = *((type *)(ptr)); }
8823446Smrj
8833446Smrj
8843446Smrj static void
osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address,UINT32 * Value,UINT32 Width,int write)8853446Smrj osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value,
8863446Smrj UINT32 Width, int write)
8873446Smrj {
8883446Smrj size_t maplen = Width / 8;
8893446Smrj caddr_t ptr;
8903446Smrj
8913446Smrj ptr = psm_map_new((paddr_t)Address, maplen,
8923446Smrj PSM_PROT_WRITE | PSM_PROT_READ);
8933446Smrj
8943446Smrj switch (maplen) {
8953446Smrj case 1:
8963446Smrj OSL_RW(ptr, Value, uint8_t, write);
8973446Smrj break;
8983446Smrj case 2:
8993446Smrj OSL_RW(ptr, Value, uint16_t, write);
9003446Smrj break;
9013446Smrj case 4:
9023446Smrj OSL_RW(ptr, Value, uint32_t, write);
9033446Smrj break;
9043446Smrj default:
9053446Smrj cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d",
9063446Smrj Width);
9073446Smrj break;
9083446Smrj }
9093446Smrj
9103446Smrj psm_unmap(ptr, maplen);
9113446Smrj }
9123446Smrj
9133446Smrj ACPI_STATUS
AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,UINT32 * Value,UINT32 Width)9143446Smrj AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,
9153446Smrj UINT32 *Value, UINT32 Width)
9163446Smrj {
9173446Smrj osl_rw_memory(Address, Value, Width, 0);
9183446Smrj return (AE_OK);
9193446Smrj }
9203446Smrj
9213446Smrj ACPI_STATUS
AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,UINT32 Value,UINT32 Width)9223446Smrj AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,
9233446Smrj UINT32 Value, UINT32 Width)
9243446Smrj {
9253446Smrj osl_rw_memory(Address, &Value, Width, 1);
9263446Smrj return (AE_OK);
9273446Smrj }
9283446Smrj
9293446Smrj
9303446Smrj ACPI_STATUS
AcpiOsReadPciConfiguration(ACPI_PCI_ID * PciId,UINT32 Register,void * Value,UINT32 Width)9313446Smrj AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
9323446Smrj void *Value, UINT32 Width)
9333446Smrj {
9343446Smrj
9353446Smrj switch (Width) {
9363446Smrj case 8:
9373446Smrj *((UINT64 *)Value) = (UINT64)(*pci_getb_func)
9384476Smyers (PciId->Bus, PciId->Device, PciId->Function, Register);
9393446Smrj break;
9403446Smrj case 16:
9413446Smrj *((UINT64 *)Value) = (UINT64)(*pci_getw_func)
9424476Smyers (PciId->Bus, PciId->Device, PciId->Function, Register);
9433446Smrj break;
9443446Smrj case 32:
9453446Smrj *((UINT64 *)Value) = (UINT64)(*pci_getl_func)
9464476Smyers (PciId->Bus, PciId->Device, PciId->Function, Register);
9473446Smrj break;
9483446Smrj case 64:
9493446Smrj default:
9503446Smrj cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed",
9513446Smrj Register, Width);
9523446Smrj return (AE_BAD_PARAMETER);
9533446Smrj }
9543446Smrj return (AE_OK);
9553446Smrj }
9563446Smrj
9573446Smrj /*
9583446Smrj *
9593446Smrj */
9603446Smrj int acpica_write_pci_config_ok = 1;
9613446Smrj
9623446Smrj ACPI_STATUS
AcpiOsWritePciConfiguration(ACPI_PCI_ID * PciId,UINT32 Register,ACPI_INTEGER Value,UINT32 Width)9633446Smrj AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
9643446Smrj ACPI_INTEGER Value, UINT32 Width)
9653446Smrj {
9663446Smrj
9673446Smrj if (!acpica_write_pci_config_ok) {
9683446Smrj cmn_err(CE_NOTE, "!write to PCI cfg %x/%x/%x %x"
9693446Smrj " %lx %d not permitted", PciId->Bus, PciId->Device,
9703446Smrj PciId->Function, Register, (long)Value, Width);
9713446Smrj return (AE_OK);
9723446Smrj }
9733446Smrj
9743446Smrj switch (Width) {
9753446Smrj case 8:
9763446Smrj (*pci_putb_func)(PciId->Bus, PciId->Device, PciId->Function,
9774476Smyers Register, (uint8_t)Value);
9783446Smrj break;
9793446Smrj case 16:
9803446Smrj (*pci_putw_func)(PciId->Bus, PciId->Device, PciId->Function,
9814476Smyers Register, (uint16_t)Value);
9823446Smrj break;
9833446Smrj case 32:
9843446Smrj (*pci_putl_func)(PciId->Bus, PciId->Device, PciId->Function,
9854476Smyers Register, (uint32_t)Value);
9863446Smrj break;
9873446Smrj case 64:
9883446Smrj default:
9893446Smrj cmn_err(CE_WARN, "!AcpiOsWritePciConfiguration: %x %u failed",
9903446Smrj Register, Width);
9913446Smrj return (AE_BAD_PARAMETER);
9923446Smrj }
9933446Smrj return (AE_OK);
9943446Smrj }
9953446Smrj
9963446Smrj /*
9973446Smrj * Called with ACPI_HANDLEs for both a PCI Config Space
9983446Smrj * OpRegion and (what ACPI CA thinks is) the PCI device
99911335SDana.Myers@Sun.COM * to which this ConfigSpace OpRegion belongs.
10003446Smrj *
100111335SDana.Myers@Sun.COM * ACPI CA uses _BBN and _ADR objects to determine the default
100211335SDana.Myers@Sun.COM * values for bus, segment, device and function; anything ACPI CA
100311335SDana.Myers@Sun.COM * can't figure out from the ACPI tables will be 0. One very
100411335SDana.Myers@Sun.COM * old 32-bit x86 system is known to have broken _BBN; this is
100511335SDana.Myers@Sun.COM * not addressed here.
10063446Smrj *
10073446Smrj * Some BIOSes implement _BBN() by reading PCI config space
10084476Smyers * on bus #0 - which means that we'll recurse when we attempt
10093446Smrj * to create the devinfo-to-ACPI map. If Derive is called during
10104667Smh27603 * scan_d2a_map, we don't translate the bus # and return.
10114667Smh27603 *
10124667Smh27603 * We get the parent of the OpRegion, which must be a PCI
10134667Smh27603 * node, fetch the associated devinfo node and snag the
10144667Smh27603 * b/d/f from it.
10153446Smrj */
10163446Smrj void
AcpiOsDerivePciId(ACPI_HANDLE rhandle,ACPI_HANDLE chandle,ACPI_PCI_ID ** PciId)10173446Smrj AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle,
10183446Smrj ACPI_PCI_ID **PciId)
10193446Smrj {
10203446Smrj ACPI_HANDLE handle;
10214667Smh27603 dev_info_t *dip;
10224667Smh27603 int bus, device, func, devfn;
10233446Smrj
10243446Smrj /*
10254667Smh27603 * See above - avoid recursing during scanning_d2a_map.
10263446Smrj */
10274667Smh27603 if (scanning_d2a_map)
10283446Smrj return;
10293446Smrj
10303446Smrj /*
10314667Smh27603 * Get the OpRegion's parent
10323446Smrj */
10333446Smrj if (AcpiGetParent(chandle, &handle) != AE_OK)
10343446Smrj return;
10353446Smrj
10364667Smh27603 /*
10374667Smh27603 * If we've mapped the ACPI node to the devinfo
10384667Smh27603 * tree, use the devinfo reg property
10394667Smh27603 */
104011335SDana.Myers@Sun.COM if (ACPI_SUCCESS(acpica_get_devinfo(handle, &dip)) &&
104111335SDana.Myers@Sun.COM (acpica_get_bdf(dip, &bus, &device, &func) >= 0)) {
10424667Smh27603 (*PciId)->Bus = bus;
10434667Smh27603 (*PciId)->Device = device;
10444667Smh27603 (*PciId)->Function = func;
10453446Smrj }
10463446Smrj }
10473446Smrj
10483446Smrj
10493446Smrj /*ARGSUSED*/
10503446Smrj BOOLEAN
AcpiOsReadable(void * Pointer,ACPI_SIZE Length)10513446Smrj AcpiOsReadable(void *Pointer, ACPI_SIZE Length)
10523446Smrj {
10533446Smrj
10543446Smrj /* Always says yes; all mapped memory assumed readable */
10553446Smrj return (1);
10563446Smrj }
10573446Smrj
10583446Smrj /*ARGSUSED*/
10593446Smrj BOOLEAN
AcpiOsWritable(void * Pointer,ACPI_SIZE Length)10603446Smrj AcpiOsWritable(void *Pointer, ACPI_SIZE Length)
10613446Smrj {
10623446Smrj
10633446Smrj /* Always says yes; all mapped memory assumed writable */
10643446Smrj return (1);
10653446Smrj }
10663446Smrj
10673446Smrj UINT64
AcpiOsGetTimer(void)10683446Smrj AcpiOsGetTimer(void)
10693446Smrj {
10703446Smrj /* gethrtime() returns 1nS resolution; convert to 100nS granules */
10713446Smrj return ((gethrtime() + 50) / 100);
10723446Smrj }
10733446Smrj
10749652SMichael.Corcoran@Sun.COM static struct AcpiOSIFeature_s {
10759652SMichael.Corcoran@Sun.COM uint64_t control_flag;
10769652SMichael.Corcoran@Sun.COM const char *feature_name;
10779652SMichael.Corcoran@Sun.COM } AcpiOSIFeatures[] = {
10789652SMichael.Corcoran@Sun.COM { ACPI_FEATURE_OSI_MODULE, "Module Device" },
10799652SMichael.Corcoran@Sun.COM { 0, "Processor Device" }
10809652SMichael.Corcoran@Sun.COM };
10819652SMichael.Corcoran@Sun.COM
10823446Smrj /*ARGSUSED*/
10833446Smrj ACPI_STATUS
AcpiOsValidateInterface(char * feature)10849652SMichael.Corcoran@Sun.COM AcpiOsValidateInterface(char *feature)
10853446Smrj {
10869652SMichael.Corcoran@Sun.COM int i;
10879652SMichael.Corcoran@Sun.COM
10889652SMichael.Corcoran@Sun.COM ASSERT(feature != NULL);
10899652SMichael.Corcoran@Sun.COM for (i = 0; i < sizeof (AcpiOSIFeatures) / sizeof (AcpiOSIFeatures[0]);
10909652SMichael.Corcoran@Sun.COM i++) {
10919652SMichael.Corcoran@Sun.COM if (strcmp(feature, AcpiOSIFeatures[i].feature_name) != 0) {
10929652SMichael.Corcoran@Sun.COM continue;
10939652SMichael.Corcoran@Sun.COM }
10949652SMichael.Corcoran@Sun.COM /* Check whether required core features are available. */
10959652SMichael.Corcoran@Sun.COM if (AcpiOSIFeatures[i].control_flag != 0 &&
10969652SMichael.Corcoran@Sun.COM acpica_get_core_feature(AcpiOSIFeatures[i].control_flag) !=
10979652SMichael.Corcoran@Sun.COM AcpiOSIFeatures[i].control_flag) {
10989652SMichael.Corcoran@Sun.COM break;
10999652SMichael.Corcoran@Sun.COM }
11009652SMichael.Corcoran@Sun.COM /* Feature supported. */
11019652SMichael.Corcoran@Sun.COM return (AE_OK);
11029652SMichael.Corcoran@Sun.COM }
11039652SMichael.Corcoran@Sun.COM
11043446Smrj return (AE_SUPPORT);
11053446Smrj }
11063446Smrj
11073446Smrj /*ARGSUSED*/
11083446Smrj ACPI_STATUS
AcpiOsValidateAddress(UINT8 spaceid,ACPI_PHYSICAL_ADDRESS addr,ACPI_SIZE length)11093446Smrj AcpiOsValidateAddress(UINT8 spaceid, ACPI_PHYSICAL_ADDRESS addr,
11103446Smrj ACPI_SIZE length)
11113446Smrj {
11123446Smrj return (AE_OK);
11133446Smrj }
11143446Smrj
11153446Smrj ACPI_STATUS
AcpiOsSignal(UINT32 Function,void * Info)11163446Smrj AcpiOsSignal(UINT32 Function, void *Info)
11173446Smrj {
11183446Smrj _NOTE(ARGUNUSED(Function, Info))
11193446Smrj
11203446Smrj /* FUTUREWORK: debugger support */
11213446Smrj
11223446Smrj cmn_err(CE_NOTE, "!OsSignal unimplemented");
11233446Smrj return (AE_OK);
11243446Smrj }
11253446Smrj
11263446Smrj void ACPI_INTERNAL_VAR_XFACE
AcpiOsPrintf(const char * Format,...)11273446Smrj AcpiOsPrintf(const char *Format, ...)
11283446Smrj {
11293446Smrj va_list ap;
11303446Smrj
11313446Smrj va_start(ap, Format);
11323446Smrj AcpiOsVprintf(Format, ap);
11333446Smrj va_end(ap);
11343446Smrj }
11353446Smrj
11363446Smrj /*
11373446Smrj * When != 0, sends output to console
11383446Smrj * Patchable with kmdb or /etc/system.
11393446Smrj */
11403446Smrj int acpica_console_out = 0;
11413446Smrj
11423446Smrj #define ACPICA_OUTBUF_LEN 160
11433446Smrj char acpica_outbuf[ACPICA_OUTBUF_LEN];
11443446Smrj int acpica_outbuf_offset;
11453446Smrj
11463446Smrj /*
11473446Smrj *
11483446Smrj */
11493446Smrj static void
acpica_pr_buf(char * buf)11505155Smyers acpica_pr_buf(char *buf)
11513446Smrj {
11523446Smrj char c, *bufp, *outp;
11533446Smrj int out_remaining;
11543446Smrj
11553446Smrj /*
11563446Smrj * copy the supplied buffer into the output buffer
11573446Smrj * when we hit a '\n' or overflow the output buffer,
11583446Smrj * output and reset the output buffer
11593446Smrj */
11603446Smrj bufp = buf;
11613446Smrj outp = acpica_outbuf + acpica_outbuf_offset;
11623446Smrj out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1;
11633446Smrj while (c = *bufp++) {
11643446Smrj *outp++ = c;
11653446Smrj if (c == '\n' || --out_remaining == 0) {
11663446Smrj *outp = '\0';
116710235SDana.Myers@Sun.COM switch (acpica_console_out) {
116810235SDana.Myers@Sun.COM case 1:
11693446Smrj printf(acpica_outbuf);
117010235SDana.Myers@Sun.COM break;
117110235SDana.Myers@Sun.COM case 2:
117210235SDana.Myers@Sun.COM prom_printf(acpica_outbuf);
117310235SDana.Myers@Sun.COM break;
117410235SDana.Myers@Sun.COM case 0:
117510235SDana.Myers@Sun.COM default:
11763446Smrj (void) strlog(0, 0, 0,
11773446Smrj SL_CONSOLE | SL_NOTE | SL_LOGONLY,
11783446Smrj acpica_outbuf);
117910235SDana.Myers@Sun.COM break;
118010235SDana.Myers@Sun.COM }
11813446Smrj acpica_outbuf_offset = 0;
11823446Smrj outp = acpica_outbuf;
11833446Smrj out_remaining = ACPICA_OUTBUF_LEN - 1;
11843446Smrj }
11853446Smrj }
11863446Smrj
11873446Smrj acpica_outbuf_offset = outp - acpica_outbuf;
11883446Smrj }
11893446Smrj
11903446Smrj void
AcpiOsVprintf(const char * Format,va_list Args)11913446Smrj AcpiOsVprintf(const char *Format, va_list Args)
11923446Smrj {
11933446Smrj
11943446Smrj /*
11955155Smyers * If AcpiOsInitialize() failed to allocate a string buffer,
11965155Smyers * resort to vprintf().
11973446Smrj */
11985155Smyers if (acpi_osl_pr_buffer == NULL) {
11993446Smrj vprintf(Format, Args);
12003446Smrj return;
12013446Smrj }
12025155Smyers
12035155Smyers /*
12045155Smyers * It is possible that a very long debug output statement will
12055155Smyers * be truncated; this is silently ignored.
12065155Smyers */
12075155Smyers (void) vsnprintf(acpi_osl_pr_buffer, acpi_osl_pr_buflen, Format, Args);
12085155Smyers acpica_pr_buf(acpi_osl_pr_buffer);
12093446Smrj }
12103446Smrj
12113446Smrj void
AcpiOsRedirectOutput(void * Destination)12123446Smrj AcpiOsRedirectOutput(void *Destination)
12133446Smrj {
12143446Smrj _NOTE(ARGUNUSED(Destination))
12153446Smrj
12163446Smrj /* FUTUREWORK: debugger support */
12173446Smrj
12183446Smrj #ifdef DEBUG
12193446Smrj cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called");
12203446Smrj #endif
12213446Smrj }
12223446Smrj
12233446Smrj
12243446Smrj UINT32
AcpiOsGetLine(char * Buffer)12253446Smrj AcpiOsGetLine(char *Buffer)
12263446Smrj {
12273446Smrj _NOTE(ARGUNUSED(Buffer))
12283446Smrj
12293446Smrj /* FUTUREWORK: debugger support */
12303446Smrj
12313446Smrj return (0);
12323446Smrj }
12333446Smrj
12343446Smrj /*
12353446Smrj * Device tree binding
12363446Smrj */
12379652SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpica_find_pcibus_walker(ACPI_HANDLE hdl,UINT32 lvl,void * ctxp,void ** rvpp)12389652SMichael.Corcoran@Sun.COM acpica_find_pcibus_walker(ACPI_HANDLE hdl, UINT32 lvl, void *ctxp, void **rvpp)
12399652SMichael.Corcoran@Sun.COM {
12409652SMichael.Corcoran@Sun.COM _NOTE(ARGUNUSED(lvl));
12419652SMichael.Corcoran@Sun.COM
12429652SMichael.Corcoran@Sun.COM int sta, hid, bbn;
12439652SMichael.Corcoran@Sun.COM int busno = (intptr_t)ctxp;
12449652SMichael.Corcoran@Sun.COM ACPI_HANDLE *hdlp = (ACPI_HANDLE *)rvpp;
12459652SMichael.Corcoran@Sun.COM
12469652SMichael.Corcoran@Sun.COM /* Check whether device exists. */
12479652SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(acpica_eval_int(hdl, "_STA", &sta)) &&
12489652SMichael.Corcoran@Sun.COM !(sta & (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_FUNCTIONING))) {
12499652SMichael.Corcoran@Sun.COM /*
12509652SMichael.Corcoran@Sun.COM * Skip object if device doesn't exist.
12519652SMichael.Corcoran@Sun.COM * According to ACPI Spec,
12529652SMichael.Corcoran@Sun.COM * 1) setting either bit 0 or bit 3 means that device exists.
12539652SMichael.Corcoran@Sun.COM * 2) Absence of _STA method means all status bits set.
12549652SMichael.Corcoran@Sun.COM */
12559652SMichael.Corcoran@Sun.COM return (AE_CTRL_DEPTH);
12569652SMichael.Corcoran@Sun.COM }
12579652SMichael.Corcoran@Sun.COM
12589652SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpica_eval_hid(hdl, "_HID", &hid)) ||
12599652SMichael.Corcoran@Sun.COM (hid != HID_PCI_BUS && hid != HID_PCI_EXPRESS_BUS)) {
12609652SMichael.Corcoran@Sun.COM /* Non PCI/PCIe host bridge. */
12619652SMichael.Corcoran@Sun.COM return (AE_OK);
12629652SMichael.Corcoran@Sun.COM }
12639652SMichael.Corcoran@Sun.COM
12649652SMichael.Corcoran@Sun.COM if (acpi_has_broken_bbn) {
12659652SMichael.Corcoran@Sun.COM ACPI_BUFFER rb;
12669652SMichael.Corcoran@Sun.COM rb.Pointer = NULL;
12679652SMichael.Corcoran@Sun.COM rb.Length = ACPI_ALLOCATE_BUFFER;
12689652SMichael.Corcoran@Sun.COM
12699652SMichael.Corcoran@Sun.COM /* Decree _BBN == n from PCI<n> */
12709652SMichael.Corcoran@Sun.COM if (AcpiGetName(hdl, ACPI_SINGLE_NAME, &rb) != AE_OK) {
12719652SMichael.Corcoran@Sun.COM return (AE_CTRL_TERMINATE);
12729652SMichael.Corcoran@Sun.COM }
12739652SMichael.Corcoran@Sun.COM bbn = ((char *)rb.Pointer)[3] - '0';
12749652SMichael.Corcoran@Sun.COM AcpiOsFree(rb.Pointer);
12759652SMichael.Corcoran@Sun.COM if (bbn == busno || busno == 0) {
12769652SMichael.Corcoran@Sun.COM *hdlp = hdl;
12779652SMichael.Corcoran@Sun.COM return (AE_CTRL_TERMINATE);
12789652SMichael.Corcoran@Sun.COM }
12799652SMichael.Corcoran@Sun.COM } else if (ACPI_SUCCESS(acpica_eval_int(hdl, "_BBN", &bbn))) {
12809652SMichael.Corcoran@Sun.COM if (bbn == busno) {
12819652SMichael.Corcoran@Sun.COM *hdlp = hdl;
12829652SMichael.Corcoran@Sun.COM return (AE_CTRL_TERMINATE);
12839652SMichael.Corcoran@Sun.COM }
12849652SMichael.Corcoran@Sun.COM } else if (busno == 0) {
12859652SMichael.Corcoran@Sun.COM *hdlp = hdl;
12869652SMichael.Corcoran@Sun.COM return (AE_CTRL_TERMINATE);
12879652SMichael.Corcoran@Sun.COM }
12889652SMichael.Corcoran@Sun.COM
12899652SMichael.Corcoran@Sun.COM return (AE_CTRL_DEPTH);
12909652SMichael.Corcoran@Sun.COM }
12913446Smrj
12923446Smrj static int
acpica_find_pcibus(int busno,ACPI_HANDLE * rh)12933446Smrj acpica_find_pcibus(int busno, ACPI_HANDLE *rh)
12943446Smrj {
12953446Smrj ACPI_HANDLE sbobj, busobj;
12963446Smrj
12973446Smrj /* initialize static flag by querying ACPI namespace for bug */
12983446Smrj if (acpi_has_broken_bbn == -1)
12993446Smrj acpi_has_broken_bbn = acpica_query_bbn_problem();
13003446Smrj
13019652SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(AcpiGetHandle(NULL, "\\_SB", &sbobj))) {
13029652SMichael.Corcoran@Sun.COM busobj = NULL;
13039652SMichael.Corcoran@Sun.COM (void) AcpiWalkNamespace(ACPI_TYPE_DEVICE, sbobj, UINT32_MAX,
130411225SDana.Myers@Sun.COM acpica_find_pcibus_walker, NULL, (void *)(intptr_t)busno,
13059652SMichael.Corcoran@Sun.COM (void **)&busobj);
13069652SMichael.Corcoran@Sun.COM if (busobj != NULL) {
13079652SMichael.Corcoran@Sun.COM *rh = busobj;
13089652SMichael.Corcoran@Sun.COM return (AE_OK);
13093446Smrj }
13103446Smrj }
13119652SMichael.Corcoran@Sun.COM
13123446Smrj return (AE_ERROR);
13133446Smrj }
13143446Smrj
13159652SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpica_query_bbn_walker(ACPI_HANDLE hdl,UINT32 lvl,void * ctxp,void ** rvpp)13169652SMichael.Corcoran@Sun.COM acpica_query_bbn_walker(ACPI_HANDLE hdl, UINT32 lvl, void *ctxp, void **rvpp)
13179652SMichael.Corcoran@Sun.COM {
13189652SMichael.Corcoran@Sun.COM _NOTE(ARGUNUSED(lvl));
13199652SMichael.Corcoran@Sun.COM _NOTE(ARGUNUSED(rvpp));
13209652SMichael.Corcoran@Sun.COM
13219652SMichael.Corcoran@Sun.COM int sta, hid, bbn;
13229652SMichael.Corcoran@Sun.COM int *cntp = (int *)ctxp;
13239652SMichael.Corcoran@Sun.COM
13249652SMichael.Corcoran@Sun.COM /* Check whether device exists. */
13259652SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(acpica_eval_int(hdl, "_STA", &sta)) &&
13269652SMichael.Corcoran@Sun.COM !(sta & (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_FUNCTIONING))) {
13279652SMichael.Corcoran@Sun.COM /*
13289652SMichael.Corcoran@Sun.COM * Skip object if device doesn't exist.
13299652SMichael.Corcoran@Sun.COM * According to ACPI Spec,
13309652SMichael.Corcoran@Sun.COM * 1) setting either bit 0 or bit 3 means that device exists.
13319652SMichael.Corcoran@Sun.COM * 2) Absence of _STA method means all status bits set.
13329652SMichael.Corcoran@Sun.COM */
13339652SMichael.Corcoran@Sun.COM return (AE_CTRL_DEPTH);
13349652SMichael.Corcoran@Sun.COM }
13359652SMichael.Corcoran@Sun.COM
13369652SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpica_eval_hid(hdl, "_HID", &hid)) ||
13379652SMichael.Corcoran@Sun.COM (hid != HID_PCI_BUS && hid != HID_PCI_EXPRESS_BUS)) {
13389652SMichael.Corcoran@Sun.COM /* Non PCI/PCIe host bridge. */
13399652SMichael.Corcoran@Sun.COM return (AE_OK);
13409652SMichael.Corcoran@Sun.COM } else if (ACPI_SUCCESS(acpica_eval_int(hdl, "_BBN", &bbn)) &&
13419652SMichael.Corcoran@Sun.COM bbn == 0 && ++(*cntp) > 1) {
13429652SMichael.Corcoran@Sun.COM /*
13439652SMichael.Corcoran@Sun.COM * If we find more than one bus with a 0 _BBN
13449652SMichael.Corcoran@Sun.COM * we have the problem that BigBear's BIOS shows
13459652SMichael.Corcoran@Sun.COM */
13469652SMichael.Corcoran@Sun.COM return (AE_CTRL_TERMINATE);
13479652SMichael.Corcoran@Sun.COM } else {
13489652SMichael.Corcoran@Sun.COM /*
13499652SMichael.Corcoran@Sun.COM * Skip children of PCI/PCIe host bridge.
13509652SMichael.Corcoran@Sun.COM */
13519652SMichael.Corcoran@Sun.COM return (AE_CTRL_DEPTH);
13529652SMichael.Corcoran@Sun.COM }
13539652SMichael.Corcoran@Sun.COM }
13543446Smrj
13553446Smrj /*
13563446Smrj * Look for ACPI problem where _BBN is zero for multiple PCI buses
13573446Smrj * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus()
13583446Smrj * below if it exists.
13593446Smrj */
13603446Smrj static int
acpica_query_bbn_problem(void)13613446Smrj acpica_query_bbn_problem(void)
13623446Smrj {
13639652SMichael.Corcoran@Sun.COM ACPI_HANDLE sbobj;
13643446Smrj int zerobbncnt;
13659652SMichael.Corcoran@Sun.COM void *rv;
13663446Smrj
13679652SMichael.Corcoran@Sun.COM zerobbncnt = 0;
13689652SMichael.Corcoran@Sun.COM if (ACPI_SUCCESS(AcpiGetHandle(NULL, "\\_SB", &sbobj))) {
13699652SMichael.Corcoran@Sun.COM (void) AcpiWalkNamespace(ACPI_TYPE_DEVICE, sbobj, UINT32_MAX,
137011225SDana.Myers@Sun.COM acpica_query_bbn_walker, NULL, &zerobbncnt, &rv);
13713446Smrj }
13729652SMichael.Corcoran@Sun.COM
13739652SMichael.Corcoran@Sun.COM return (zerobbncnt > 1 ? 1 : 0);
13743446Smrj }
13753446Smrj
13763446Smrj static const char hextab[] = "0123456789ABCDEF";
13773446Smrj
13783446Smrj static int
hexdig(int c)13793446Smrj hexdig(int c)
13803446Smrj {
13813446Smrj /*
13823446Smrj * Get hex digit:
13833446Smrj *
13843446Smrj * Returns the 4-bit hex digit named by the input character. Returns
13853446Smrj * zero if the input character is not valid hex!
13863446Smrj */
13873446Smrj
13883446Smrj int x = ((c < 'a') || (c > 'z')) ? c : (c - ' ');
13893446Smrj int j = sizeof (hextab);
13903446Smrj
13914476Smyers while (--j && (x != hextab[j])) {
13924476Smyers }
13933446Smrj return (j);
13943446Smrj }
13953446Smrj
13963446Smrj static int
CompressEisaID(char * np)13973446Smrj CompressEisaID(char *np)
13983446Smrj {
13993446Smrj /*
14003446Smrj * Compress an EISA device name:
14013446Smrj *
14023446Smrj * This routine converts a 7-byte ASCII device name into the 4-byte
14033446Smrj * compressed form used by EISA (50 bytes of ROM to save 1 byte of
14043446Smrj * NV-RAM!)
14053446Smrj */
14063446Smrj
14073446Smrj union { char octets[4]; int retval; } myu;
14083446Smrj
14093446Smrj myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03);
14103446Smrj myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F);
14113446Smrj myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]);
14123446Smrj myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]);
14133446Smrj
14143446Smrj return (myu.retval);
14153446Smrj }
14163446Smrj
14174667Smh27603 ACPI_STATUS
acpica_eval_int(ACPI_HANDLE dev,char * method,int * rint)14183446Smrj acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint)
14193446Smrj {
14203446Smrj ACPI_STATUS status;
14213446Smrj ACPI_BUFFER rb;
14223446Smrj ACPI_OBJECT ro;
14233446Smrj
14243446Smrj rb.Pointer = &ro;
14253446Smrj rb.Length = sizeof (ro);
14263446Smrj if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb,
14274476Smyers ACPI_TYPE_INTEGER)) == AE_OK)
14283446Smrj *rint = ro.Integer.Value;
14293446Smrj
14303446Smrj return (status);
14313446Smrj }
14323446Smrj
14333446Smrj static int
acpica_eval_hid(ACPI_HANDLE dev,char * method,int * rint)14343446Smrj acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint)
14353446Smrj {
14363446Smrj ACPI_BUFFER rb;
14373446Smrj ACPI_OBJECT *rv;
14383446Smrj
14393446Smrj rb.Pointer = NULL;
14403446Smrj rb.Length = ACPI_ALLOCATE_BUFFER;
14417851SDana.Myers@Sun.COM if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK &&
14427851SDana.Myers@Sun.COM rb.Length != 0) {
14433446Smrj rv = rb.Pointer;
14443446Smrj if (rv->Type == ACPI_TYPE_INTEGER) {
14453446Smrj *rint = rv->Integer.Value;
14463446Smrj AcpiOsFree(rv);
14473446Smrj return (AE_OK);
14483446Smrj } else if (rv->Type == ACPI_TYPE_STRING) {
14493446Smrj char *stringData;
14503446Smrj
14513446Smrj /* Convert the string into an EISA ID */
14523446Smrj if (rv->String.Pointer == NULL) {
14533446Smrj AcpiOsFree(rv);
14543446Smrj return (AE_ERROR);
14553446Smrj }
14563446Smrj
14573446Smrj stringData = rv->String.Pointer;
14583446Smrj
14593446Smrj /*
14603446Smrj * If the string is an EisaID, it must be 7
14613446Smrj * characters; if it's an ACPI ID, it will be 8
14623446Smrj * (and we don't care about ACPI ids here).
14633446Smrj */
14643446Smrj if (strlen(stringData) != 7) {
14653446Smrj AcpiOsFree(rv);
14663446Smrj return (AE_ERROR);
14673446Smrj }
14683446Smrj
14693446Smrj *rint = CompressEisaID(stringData);
14703446Smrj AcpiOsFree(rv);
14713446Smrj return (AE_OK);
14723446Smrj } else
14733446Smrj AcpiOsFree(rv);
14743446Smrj }
14753446Smrj return (AE_ERROR);
14763446Smrj }
14773446Smrj
14783446Smrj /*
14794667Smh27603 * Create linkage between devinfo nodes and ACPI nodes
14803446Smrj */
14819652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_tag_devinfo(dev_info_t * dip,ACPI_HANDLE acpiobj)14824667Smh27603 acpica_tag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj)
14833446Smrj {
14844667Smh27603 ACPI_STATUS status;
14854667Smh27603 ACPI_BUFFER rb;
14863446Smrj
14874667Smh27603 /*
14884667Smh27603 * Tag the devinfo node with the ACPI name
14894667Smh27603 */
14904667Smh27603 rb.Pointer = NULL;
14914667Smh27603 rb.Length = ACPI_ALLOCATE_BUFFER;
14929652SMichael.Corcoran@Sun.COM status = AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb);
14939652SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(status)) {
14949652SMichael.Corcoran@Sun.COM cmn_err(CE_WARN, "acpica: could not get ACPI path!");
14959652SMichael.Corcoran@Sun.COM } else {
14964667Smh27603 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
14974667Smh27603 "acpi-namespace", (char *)rb.Pointer);
14984667Smh27603 AcpiOsFree(rb.Pointer);
14999652SMichael.Corcoran@Sun.COM
15009652SMichael.Corcoran@Sun.COM /*
15019652SMichael.Corcoran@Sun.COM * Tag the ACPI node with the dip
15029652SMichael.Corcoran@Sun.COM */
15039652SMichael.Corcoran@Sun.COM status = acpica_set_devinfo(acpiobj, dip);
15049652SMichael.Corcoran@Sun.COM ASSERT(ACPI_SUCCESS(status));
15054667Smh27603 }
15069652SMichael.Corcoran@Sun.COM
15079652SMichael.Corcoran@Sun.COM return (status);
15083446Smrj }
15093446Smrj
15109652SMichael.Corcoran@Sun.COM /*
15119652SMichael.Corcoran@Sun.COM * Destroy linkage between devinfo nodes and ACPI nodes
15129652SMichael.Corcoran@Sun.COM */
15139652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_untag_devinfo(dev_info_t * dip,ACPI_HANDLE acpiobj)15149652SMichael.Corcoran@Sun.COM acpica_untag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj)
15153446Smrj {
15169652SMichael.Corcoran@Sun.COM (void) acpica_unset_devinfo(acpiobj);
15179652SMichael.Corcoran@Sun.COM (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "acpi-namespace");
15183446Smrj
15199652SMichael.Corcoran@Sun.COM return (AE_OK);
15203446Smrj }
15213446Smrj
15223446Smrj /*
15234687Smh27603 * Return the ACPI device node matching the CPU dev_info node.
15243446Smrj */
15254667Smh27603 ACPI_STATUS
acpica_get_handle_cpu(int cpu_id,ACPI_HANDLE * rh)15268906SEric.Saxe@Sun.COM acpica_get_handle_cpu(int cpu_id, ACPI_HANDLE *rh)
15273446Smrj {
15289652SMichael.Corcoran@Sun.COM int i;
15299652SMichael.Corcoran@Sun.COM
15304667Smh27603 /*
15314667Smh27603 * if cpu_map itself is NULL, we're a uppc system and
15324667Smh27603 * acpica_build_processor_map() hasn't been called yet.
15334667Smh27603 * So call it here
15344667Smh27603 */
15354667Smh27603 if (cpu_map == NULL) {
15364667Smh27603 (void) acpica_build_processor_map();
15374667Smh27603 if (cpu_map == NULL)
15384667Smh27603 return (AE_ERROR);
15394667Smh27603 }
15403446Smrj
15419652SMichael.Corcoran@Sun.COM if (cpu_id < 0) {
15424667Smh27603 return (AE_ERROR);
15439652SMichael.Corcoran@Sun.COM }
15444667Smh27603
15459652SMichael.Corcoran@Sun.COM /*
15469652SMichael.Corcoran@Sun.COM * search object with cpuid in cpu_map
15479652SMichael.Corcoran@Sun.COM */
15489652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
15499652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
15509652SMichael.Corcoran@Sun.COM if (cpu_map[i]->cpu_id == cpu_id) {
15519652SMichael.Corcoran@Sun.COM break;
15529652SMichael.Corcoran@Sun.COM }
15539652SMichael.Corcoran@Sun.COM }
155410394SMichael.Corcoran@Sun.COM if (i < cpu_map_count && (cpu_map[i]->obj != NULL)) {
1555*12004Sjiang.liu@intel.com *rh = cpu_map[i]->obj;
15569652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
155710394SMichael.Corcoran@Sun.COM return (AE_OK);
15589652SMichael.Corcoran@Sun.COM }
155910394SMichael.Corcoran@Sun.COM
156010394SMichael.Corcoran@Sun.COM /* Handle special case for uppc-only systems. */
156110394SMichael.Corcoran@Sun.COM if (cpu_map_called == 0) {
156210394SMichael.Corcoran@Sun.COM uint32_t apicid = cpuid_get_apicid(CPU);
156310394SMichael.Corcoran@Sun.COM if (apicid != UINT32_MAX) {
156410394SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
156510394SMichael.Corcoran@Sun.COM if (cpu_map[i]->apic_id == apicid) {
156610394SMichael.Corcoran@Sun.COM break;
156710394SMichael.Corcoran@Sun.COM }
156810394SMichael.Corcoran@Sun.COM }
156910394SMichael.Corcoran@Sun.COM if (i < cpu_map_count && (cpu_map[i]->obj != NULL)) {
1570*12004Sjiang.liu@intel.com *rh = cpu_map[i]->obj;
157110394SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
157210394SMichael.Corcoran@Sun.COM return (AE_OK);
157310394SMichael.Corcoran@Sun.COM }
157410394SMichael.Corcoran@Sun.COM }
157510394SMichael.Corcoran@Sun.COM }
15769652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
15779652SMichael.Corcoran@Sun.COM
157810394SMichael.Corcoran@Sun.COM return (AE_ERROR);
15794667Smh27603 }
15803446Smrj
15814667Smh27603 /*
15824667Smh27603 * Determine if this object is a processor
15834667Smh27603 */
15844667Smh27603 static ACPI_STATUS
acpica_probe_processor(ACPI_HANDLE obj,UINT32 level,void * ctx,void ** rv)15854667Smh27603 acpica_probe_processor(ACPI_HANDLE obj, UINT32 level, void *ctx, void **rv)
15864667Smh27603 {
15874667Smh27603 ACPI_STATUS status;
15884667Smh27603 ACPI_OBJECT_TYPE objtype;
15898973SDana.Myers@Sun.COM unsigned long acpi_id;
15904667Smh27603 ACPI_BUFFER rb;
159111225SDana.Myers@Sun.COM ACPI_DEVICE_INFO *di;
15924667Smh27603
15934667Smh27603 if (AcpiGetType(obj, &objtype) != AE_OK)
15944667Smh27603 return (AE_OK);
15954667Smh27603
15964667Smh27603 if (objtype == ACPI_TYPE_PROCESSOR) {
15974667Smh27603 /* process a Processor */
15983446Smrj rb.Pointer = NULL;
15993446Smrj rb.Length = ACPI_ALLOCATE_BUFFER;
16007851SDana.Myers@Sun.COM status = AcpiEvaluateObjectTyped(obj, NULL, NULL, &rb,
16017851SDana.Myers@Sun.COM ACPI_TYPE_PROCESSOR);
16024667Smh27603 if (status != AE_OK) {
16038973SDana.Myers@Sun.COM cmn_err(CE_WARN, "!acpica: error probing Processor");
16044667Smh27603 return (status);
16054667Smh27603 }
16064667Smh27603 acpi_id = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId;
16074667Smh27603 AcpiOsFree(rb.Pointer);
16084667Smh27603 } else if (objtype == ACPI_TYPE_DEVICE) {
16094667Smh27603 /* process a processor Device */
161011225SDana.Myers@Sun.COM status = AcpiGetObjectInfo(obj, &di);
16117282Smishra if (status != AE_OK) {
16127282Smishra cmn_err(CE_WARN,
16138973SDana.Myers@Sun.COM "!acpica: error probing Processor Device\n");
16147282Smishra return (status);
16157282Smishra }
16168973SDana.Myers@Sun.COM
161711225SDana.Myers@Sun.COM if (!(di->Valid & ACPI_VALID_UID) ||
161811225SDana.Myers@Sun.COM ddi_strtoul(di->UniqueId.String, NULL, 10, &acpi_id) != 0) {
161911225SDana.Myers@Sun.COM ACPI_FREE(di);
16208973SDana.Myers@Sun.COM cmn_err(CE_WARN,
16218973SDana.Myers@Sun.COM "!acpica: error probing Processor Device _UID\n");
16228973SDana.Myers@Sun.COM return (AE_ERROR);
16238973SDana.Myers@Sun.COM }
162411225SDana.Myers@Sun.COM ACPI_FREE(di);
16254667Smh27603 }
16269652SMichael.Corcoran@Sun.COM (void) acpica_add_processor_to_map(acpi_id, obj, UINT32_MAX);
16273446Smrj
16284667Smh27603 return (AE_OK);
16293446Smrj }
16303446Smrj
163111177SDana.Myers@Sun.COM void
scan_d2a_map(void)16324667Smh27603 scan_d2a_map(void)
16333446Smrj {
16343446Smrj dev_info_t *dip, *cdip;
16353446Smrj ACPI_HANDLE acpiobj;
16363446Smrj char *device_type_prop;
16373446Smrj int bus;
16383446Smrj static int map_error = 0;
16393446Smrj
164011177SDana.Myers@Sun.COM if (map_error || (d2a_done != 0))
16413446Smrj return;
16423446Smrj
16434667Smh27603 scanning_d2a_map = 1;
16443446Smrj
16453446Smrj /*
16463446Smrj * Find all child-of-root PCI buses, and find their corresponding
16473446Smrj * ACPI child-of-root PCI nodes. For each one, add to the
16483446Smrj * d2a table.
16493446Smrj */
16503446Smrj
16513446Smrj for (dip = ddi_get_child(ddi_root_node());
16523446Smrj dip != NULL;
16533446Smrj dip = ddi_get_next_sibling(dip)) {
16543446Smrj
16553446Smrj /* prune non-PCI nodes */
16569652SMichael.Corcoran@Sun.COM if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
16579652SMichael.Corcoran@Sun.COM DDI_PROP_DONTPASS,
16583446Smrj "device_type", &device_type_prop) != DDI_PROP_SUCCESS)
16593446Smrj continue;
16603446Smrj
16613446Smrj if ((strcmp("pci", device_type_prop) != 0) &&
16623446Smrj (strcmp("pciex", device_type_prop) != 0)) {
16633446Smrj ddi_prop_free(device_type_prop);
16643446Smrj continue;
16653446Smrj }
16663446Smrj
16673446Smrj ddi_prop_free(device_type_prop);
16683446Smrj
16693446Smrj /*
16703446Smrj * To get bus number of dip, get first child and get its
16713446Smrj * bus number. If NULL, just continue, because we don't
16723446Smrj * care about bus nodes with no children anyway.
16733446Smrj */
16743446Smrj if ((cdip = ddi_get_child(dip)) == NULL)
16753446Smrj continue;
16763446Smrj
16773446Smrj if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) {
16783446Smrj #ifdef D2ADEBUG
16793446Smrj cmn_err(CE_WARN, "Can't get bus number of PCI child?");
16803446Smrj #endif
16813446Smrj map_error = 1;
16824667Smh27603 scanning_d2a_map = 0;
16834667Smh27603 d2a_done = 1;
16843446Smrj return;
16853446Smrj }
16863446Smrj
16873446Smrj if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) {
16883446Smrj #ifdef D2ADEBUG
16893446Smrj cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus);
16903446Smrj #endif
16913446Smrj map_error = 1;
16923446Smrj continue;
16933446Smrj }
16943446Smrj
16954667Smh27603 acpica_tag_devinfo(dip, acpiobj);
16963446Smrj
16974667Smh27603 /* call recursively to enumerate subtrees */
16984667Smh27603 scan_d2a_subtree(dip, acpiobj, bus);
16994667Smh27603 }
17003446Smrj
17014667Smh27603 scanning_d2a_map = 0;
17024667Smh27603 d2a_done = 1;
17033446Smrj }
17043446Smrj
17053446Smrj /*
17063446Smrj * For all acpi child devices of acpiobj, find their matching
17073446Smrj * dip under "dip" argument. (matching means "matches dev/fn").
17083446Smrj * bus is assumed to already be a match from caller, and is
17093446Smrj * used here only to record in the d2a entry. Recurse if necessary.
17103446Smrj */
17113446Smrj static void
scan_d2a_subtree(dev_info_t * dip,ACPI_HANDLE acpiobj,int bus)17124667Smh27603 scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus)
17133446Smrj {
17143446Smrj int acpi_devfn, hid;
17153446Smrj ACPI_HANDLE acld;
17163446Smrj dev_info_t *dcld;
17173446Smrj int dcld_b, dcld_d, dcld_f;
17183446Smrj int dev, func;
17194667Smh27603 char *device_type_prop;
17203446Smrj
17213446Smrj acld = NULL;
17223446Smrj while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld)
17233446Smrj == AE_OK) {
17243446Smrj /* get the dev/func we're looking for in the devinfo tree */
17253446Smrj if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK)
17263446Smrj continue;
17273446Smrj dev = (acpi_devfn >> 16) & 0xFFFF;
17283446Smrj func = acpi_devfn & 0xFFFF;
17293446Smrj
17303446Smrj /* look through all the immediate children of dip */
17313446Smrj for (dcld = ddi_get_child(dip); dcld != NULL;
17323446Smrj dcld = ddi_get_next_sibling(dcld)) {
17333446Smrj if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0)
17343446Smrj continue;
17353446Smrj
17363446Smrj /* dev must match; function must match or wildcard */
17373446Smrj if (dcld_d != dev ||
17383446Smrj (func != 0xFFFF && func != dcld_f))
17393446Smrj continue;
17403446Smrj bus = dcld_b;
17413446Smrj
17423446Smrj /* found a match, record it */
17434667Smh27603 acpica_tag_devinfo(dcld, acld);
17443446Smrj
17454667Smh27603 /* if we find a bridge, recurse from here */
17469652SMichael.Corcoran@Sun.COM if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dcld,
17479652SMichael.Corcoran@Sun.COM DDI_PROP_DONTPASS, "device_type",
17489652SMichael.Corcoran@Sun.COM &device_type_prop) == DDI_PROP_SUCCESS) {
17494667Smh27603 if ((strcmp("pci", device_type_prop) == 0) ||
17504667Smh27603 (strcmp("pciex", device_type_prop) == 0))
17514667Smh27603 scan_d2a_subtree(dcld, acld, bus);
17524667Smh27603 ddi_prop_free(device_type_prop);
17534667Smh27603 }
17543446Smrj
17553446Smrj /* done finding a match, so break now */
17563446Smrj break;
17573446Smrj }
17583446Smrj }
17593446Smrj }
17603446Smrj
17613446Smrj /*
17623446Smrj * Return bus/dev/fn for PCI dip (note: not the parent "pci" node).
17633446Smrj */
17643446Smrj int
acpica_get_bdf(dev_info_t * dip,int * bus,int * device,int * func)17653446Smrj acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func)
17663446Smrj {
17673446Smrj pci_regspec_t *pci_rp;
17683446Smrj int len;
17693446Smrj
17703446Smrj if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
17713446Smrj "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS)
17723446Smrj return (-1);
17733446Smrj
17743446Smrj if (len < (sizeof (pci_regspec_t) / sizeof (int))) {
17753446Smrj ddi_prop_free(pci_rp);
17763446Smrj return (-1);
17773446Smrj }
17783446Smrj if (bus != NULL)
17793446Smrj *bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi);
17803446Smrj if (device != NULL)
17813446Smrj *device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi);
17823446Smrj if (func != NULL)
17833446Smrj *func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
17843446Smrj ddi_prop_free(pci_rp);
17853446Smrj return (0);
17863446Smrj }
17874667Smh27603
17884667Smh27603 /*
17894667Smh27603 * Return the ACPI device node matching this dev_info node, if it
17904667Smh27603 * exists in the ACPI tree.
17914667Smh27603 */
17924667Smh27603 ACPI_STATUS
acpica_get_handle(dev_info_t * dip,ACPI_HANDLE * rh)17934667Smh27603 acpica_get_handle(dev_info_t *dip, ACPI_HANDLE *rh)
17944667Smh27603 {
17954667Smh27603 ACPI_STATUS status;
17964667Smh27603 char *acpiname;
17974667Smh27603
179811277SDana.Myers@Sun.COM #ifdef DEBUG
179911277SDana.Myers@Sun.COM if (d2a_done == 0)
180011277SDana.Myers@Sun.COM cmn_err(CE_WARN, "!acpica_get_handle:"
180111277SDana.Myers@Sun.COM " no ACPI mapping for %s", ddi_node_name(dip));
180211277SDana.Myers@Sun.COM #endif
18034667Smh27603
18044667Smh27603 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
18054667Smh27603 "acpi-namespace", &acpiname) != DDI_PROP_SUCCESS) {
18068906SEric.Saxe@Sun.COM return (AE_ERROR);
18074667Smh27603 }
18084667Smh27603
18094667Smh27603 status = AcpiGetHandle(NULL, acpiname, rh);
18104667Smh27603 ddi_prop_free((void *)acpiname);
18114667Smh27603 return (status);
18124667Smh27603 }
18134667Smh27603
18144667Smh27603
18154667Smh27603
18164667Smh27603 /*
18174667Smh27603 * Manage OS data attachment to ACPI nodes
18184667Smh27603 */
18194667Smh27603
18204667Smh27603 /*
18214667Smh27603 * Return the (dev_info_t *) associated with the ACPI node.
18224667Smh27603 */
18234667Smh27603 ACPI_STATUS
acpica_get_devinfo(ACPI_HANDLE obj,dev_info_t ** dipp)18244667Smh27603 acpica_get_devinfo(ACPI_HANDLE obj, dev_info_t **dipp)
18254667Smh27603 {
18264667Smh27603 ACPI_STATUS status;
18274667Smh27603 void *ptr;
18284667Smh27603
18294667Smh27603 status = AcpiGetData(obj, acpica_devinfo_handler, &ptr);
18304667Smh27603 if (status == AE_OK)
18314667Smh27603 *dipp = (dev_info_t *)ptr;
18324667Smh27603
18334667Smh27603 return (status);
18344667Smh27603 }
18354667Smh27603
18364667Smh27603 /*
18374667Smh27603 * Set the dev_info_t associated with the ACPI node.
18384667Smh27603 */
18394667Smh27603 static ACPI_STATUS
acpica_set_devinfo(ACPI_HANDLE obj,dev_info_t * dip)18404667Smh27603 acpica_set_devinfo(ACPI_HANDLE obj, dev_info_t *dip)
18414667Smh27603 {
18424667Smh27603 ACPI_STATUS status;
18434667Smh27603
18444667Smh27603 status = AcpiAttachData(obj, acpica_devinfo_handler, (void *)dip);
18454667Smh27603 return (status);
18464667Smh27603 }
18474667Smh27603
18489652SMichael.Corcoran@Sun.COM /*
18499652SMichael.Corcoran@Sun.COM * Unset the dev_info_t associated with the ACPI node.
18509652SMichael.Corcoran@Sun.COM */
18519652SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpica_unset_devinfo(ACPI_HANDLE obj)18529652SMichael.Corcoran@Sun.COM acpica_unset_devinfo(ACPI_HANDLE obj)
18539652SMichael.Corcoran@Sun.COM {
18549652SMichael.Corcoran@Sun.COM return (AcpiDetachData(obj, acpica_devinfo_handler));
18559652SMichael.Corcoran@Sun.COM }
18564667Smh27603
18574667Smh27603 /*
18584667Smh27603 *
18594667Smh27603 */
18604667Smh27603 void
acpica_devinfo_handler(ACPI_HANDLE obj,void * data)186111225SDana.Myers@Sun.COM acpica_devinfo_handler(ACPI_HANDLE obj, void *data)
18624667Smh27603 {
186311225SDana.Myers@Sun.COM /* no-op */
18644667Smh27603 }
18654667Smh27603
18669652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_build_processor_map(void)18679652SMichael.Corcoran@Sun.COM acpica_build_processor_map(void)
18684667Smh27603 {
18694667Smh27603 ACPI_STATUS status;
18704667Smh27603 void *rv;
18714667Smh27603
18724667Smh27603 /*
18734667Smh27603 * shouldn't be called more than once anyway
18744667Smh27603 */
18754667Smh27603 if (cpu_map_built)
18769652SMichael.Corcoran@Sun.COM return (AE_OK);
18779652SMichael.Corcoran@Sun.COM
18789652SMichael.Corcoran@Sun.COM /*
18799652SMichael.Corcoran@Sun.COM * ACPI device configuration driver has built mapping information
18809652SMichael.Corcoran@Sun.COM * among processor id and object handle, no need to probe again.
18819652SMichael.Corcoran@Sun.COM */
18829652SMichael.Corcoran@Sun.COM if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) {
18839652SMichael.Corcoran@Sun.COM cpu_map_built = 1;
18849652SMichael.Corcoran@Sun.COM return (AE_OK);
18859652SMichael.Corcoran@Sun.COM }
18864667Smh27603
18874667Smh27603 /*
18884667Smh27603 * Look for Processor objects
18894667Smh27603 */
18904667Smh27603 status = AcpiWalkNamespace(ACPI_TYPE_PROCESSOR,
18914667Smh27603 ACPI_ROOT_OBJECT,
18924667Smh27603 4,
18934667Smh27603 acpica_probe_processor,
18944667Smh27603 NULL,
189511225SDana.Myers@Sun.COM NULL,
18964667Smh27603 &rv);
18974667Smh27603 ASSERT(status == AE_OK);
18984667Smh27603
18994667Smh27603 /*
19004667Smh27603 * Look for processor Device objects
19014667Smh27603 */
19024667Smh27603 status = AcpiGetDevices("ACPI0007",
19034667Smh27603 acpica_probe_processor,
19044667Smh27603 NULL,
19054667Smh27603 &rv);
19064667Smh27603 ASSERT(status == AE_OK);
19074667Smh27603 cpu_map_built = 1;
19089652SMichael.Corcoran@Sun.COM
19099652SMichael.Corcoran@Sun.COM return (status);
19109652SMichael.Corcoran@Sun.COM }
19119652SMichael.Corcoran@Sun.COM
19129652SMichael.Corcoran@Sun.COM /*
19139652SMichael.Corcoran@Sun.COM * Grow cpu map table on demand.
19149652SMichael.Corcoran@Sun.COM */
19159652SMichael.Corcoran@Sun.COM static void
acpica_grow_cpu_map(void)19169652SMichael.Corcoran@Sun.COM acpica_grow_cpu_map(void)
19179652SMichael.Corcoran@Sun.COM {
19189652SMichael.Corcoran@Sun.COM if (cpu_map_count == cpu_map_count_max) {
19199652SMichael.Corcoran@Sun.COM size_t sz;
19209652SMichael.Corcoran@Sun.COM struct cpu_map_item **new_map;
19219652SMichael.Corcoran@Sun.COM
19229652SMichael.Corcoran@Sun.COM ASSERT(cpu_map_count_max < INT_MAX / 2);
19239652SMichael.Corcoran@Sun.COM cpu_map_count_max += max_ncpus;
19249652SMichael.Corcoran@Sun.COM new_map = kmem_zalloc(sizeof (cpu_map[0]) * cpu_map_count_max,
19259652SMichael.Corcoran@Sun.COM KM_SLEEP);
19269652SMichael.Corcoran@Sun.COM if (cpu_map_count != 0) {
19279652SMichael.Corcoran@Sun.COM ASSERT(cpu_map != NULL);
19289652SMichael.Corcoran@Sun.COM sz = sizeof (cpu_map[0]) * cpu_map_count;
19299652SMichael.Corcoran@Sun.COM kcopy(cpu_map, new_map, sz);
19309652SMichael.Corcoran@Sun.COM kmem_free(cpu_map, sz);
19319652SMichael.Corcoran@Sun.COM }
19329652SMichael.Corcoran@Sun.COM cpu_map = new_map;
19339652SMichael.Corcoran@Sun.COM }
19349652SMichael.Corcoran@Sun.COM }
19359652SMichael.Corcoran@Sun.COM
19369652SMichael.Corcoran@Sun.COM /*
19379652SMichael.Corcoran@Sun.COM * Maintain mapping information among (cpu id, ACPI processor id, APIC id,
19389652SMichael.Corcoran@Sun.COM * ACPI handle). The mapping table will be setup in two steps:
19399652SMichael.Corcoran@Sun.COM * 1) acpica_add_processor_to_map() builds mapping among APIC id, ACPI
19409652SMichael.Corcoran@Sun.COM * processor id and ACPI object handle.
19419652SMichael.Corcoran@Sun.COM * 2) acpica_map_cpu() builds mapping among cpu id and ACPI processor id.
194210394SMichael.Corcoran@Sun.COM * On systems with which have ACPI device configuration for CPUs enabled,
194310394SMichael.Corcoran@Sun.COM * acpica_map_cpu() will be called after acpica_add_processor_to_map(),
194410394SMichael.Corcoran@Sun.COM * otherwise acpica_map_cpu() will be called before
194510394SMichael.Corcoran@Sun.COM * acpica_add_processor_to_map().
19469652SMichael.Corcoran@Sun.COM */
19479652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_add_processor_to_map(UINT32 acpi_id,ACPI_HANDLE obj,UINT32 apic_id)19489652SMichael.Corcoran@Sun.COM acpica_add_processor_to_map(UINT32 acpi_id, ACPI_HANDLE obj, UINT32 apic_id)
19499652SMichael.Corcoran@Sun.COM {
19509652SMichael.Corcoran@Sun.COM int i;
19519652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_OK;
19529652SMichael.Corcoran@Sun.COM struct cpu_map_item *item = NULL;
19539652SMichael.Corcoran@Sun.COM
19549652SMichael.Corcoran@Sun.COM ASSERT(obj != NULL);
19559652SMichael.Corcoran@Sun.COM if (obj == NULL) {
19569652SMichael.Corcoran@Sun.COM return (AE_ERROR);
19579652SMichael.Corcoran@Sun.COM }
19589652SMichael.Corcoran@Sun.COM
19599652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
19609652SMichael.Corcoran@Sun.COM
19619652SMichael.Corcoran@Sun.COM /*
19629652SMichael.Corcoran@Sun.COM * Special case for uppc
19639652SMichael.Corcoran@Sun.COM * If we're a uppc system and ACPI device configuration for CPU has
19649652SMichael.Corcoran@Sun.COM * been disabled, there won't be a CPU map yet because uppc psm doesn't
19659652SMichael.Corcoran@Sun.COM * call acpica_map_cpu(). So create one and use the passed-in processor
19669652SMichael.Corcoran@Sun.COM * as CPU 0
196710394SMichael.Corcoran@Sun.COM * Assumption: the first CPU returned by
196810394SMichael.Corcoran@Sun.COM * AcpiGetDevices/AcpiWalkNamespace will be the BSP.
196910394SMichael.Corcoran@Sun.COM * Unfortunately there appears to be no good way to ASSERT this.
19709652SMichael.Corcoran@Sun.COM */
19719652SMichael.Corcoran@Sun.COM if (cpu_map == NULL &&
19729652SMichael.Corcoran@Sun.COM !acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) {
19739652SMichael.Corcoran@Sun.COM acpica_grow_cpu_map();
19749652SMichael.Corcoran@Sun.COM ASSERT(cpu_map != NULL);
19759652SMichael.Corcoran@Sun.COM item = kmem_zalloc(sizeof (*item), KM_SLEEP);
19769652SMichael.Corcoran@Sun.COM item->cpu_id = 0;
19779652SMichael.Corcoran@Sun.COM item->proc_id = acpi_id;
19789652SMichael.Corcoran@Sun.COM item->apic_id = apic_id;
19799652SMichael.Corcoran@Sun.COM item->obj = obj;
19809652SMichael.Corcoran@Sun.COM cpu_map[0] = item;
19819652SMichael.Corcoran@Sun.COM cpu_map_count = 1;
19829652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
19839652SMichael.Corcoran@Sun.COM return (AE_OK);
19849652SMichael.Corcoran@Sun.COM }
19859652SMichael.Corcoran@Sun.COM
19869652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
19879652SMichael.Corcoran@Sun.COM if (cpu_map[i]->obj == obj) {
19889652SMichael.Corcoran@Sun.COM rc = AE_ALREADY_EXISTS;
19899652SMichael.Corcoran@Sun.COM break;
19909652SMichael.Corcoran@Sun.COM } else if (cpu_map[i]->proc_id == acpi_id) {
19919652SMichael.Corcoran@Sun.COM ASSERT(item == NULL);
19929652SMichael.Corcoran@Sun.COM item = cpu_map[i];
19939652SMichael.Corcoran@Sun.COM }
19949652SMichael.Corcoran@Sun.COM }
19959652SMichael.Corcoran@Sun.COM
19969652SMichael.Corcoran@Sun.COM if (rc == AE_OK) {
19979652SMichael.Corcoran@Sun.COM if (item != NULL) {
19989652SMichael.Corcoran@Sun.COM /*
19999652SMichael.Corcoran@Sun.COM * ACPI alias objects may cause more than one objects
20009652SMichael.Corcoran@Sun.COM * with the same ACPI processor id, only remember the
20019652SMichael.Corcoran@Sun.COM * the first object encountered.
20029652SMichael.Corcoran@Sun.COM */
20039652SMichael.Corcoran@Sun.COM if (item->obj == NULL) {
20049652SMichael.Corcoran@Sun.COM item->obj = obj;
20059652SMichael.Corcoran@Sun.COM item->apic_id = apic_id;
20069652SMichael.Corcoran@Sun.COM } else {
20079652SMichael.Corcoran@Sun.COM rc = AE_ALREADY_EXISTS;
20089652SMichael.Corcoran@Sun.COM }
20099652SMichael.Corcoran@Sun.COM } else if (cpu_map_count >= INT_MAX / 2) {
20109652SMichael.Corcoran@Sun.COM rc = AE_NO_MEMORY;
20119652SMichael.Corcoran@Sun.COM } else {
20129652SMichael.Corcoran@Sun.COM acpica_grow_cpu_map();
20139652SMichael.Corcoran@Sun.COM ASSERT(cpu_map != NULL);
20149652SMichael.Corcoran@Sun.COM ASSERT(cpu_map_count < cpu_map_count_max);
20159652SMichael.Corcoran@Sun.COM item = kmem_zalloc(sizeof (*item), KM_SLEEP);
20169652SMichael.Corcoran@Sun.COM item->cpu_id = -1;
20179652SMichael.Corcoran@Sun.COM item->proc_id = acpi_id;
20189652SMichael.Corcoran@Sun.COM item->apic_id = apic_id;
20199652SMichael.Corcoran@Sun.COM item->obj = obj;
20209652SMichael.Corcoran@Sun.COM cpu_map[cpu_map_count] = item;
20219652SMichael.Corcoran@Sun.COM cpu_map_count++;
20229652SMichael.Corcoran@Sun.COM }
20239652SMichael.Corcoran@Sun.COM }
20249652SMichael.Corcoran@Sun.COM
20259652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
20269652SMichael.Corcoran@Sun.COM
20279652SMichael.Corcoran@Sun.COM return (rc);
20289652SMichael.Corcoran@Sun.COM }
20299652SMichael.Corcoran@Sun.COM
20309652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_remove_processor_from_map(UINT32 acpi_id)20319652SMichael.Corcoran@Sun.COM acpica_remove_processor_from_map(UINT32 acpi_id)
20329652SMichael.Corcoran@Sun.COM {
20339652SMichael.Corcoran@Sun.COM int i;
20349652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_NOT_EXIST;
20359652SMichael.Corcoran@Sun.COM
20369652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
20379652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
20389652SMichael.Corcoran@Sun.COM if (cpu_map[i]->proc_id != acpi_id) {
20399652SMichael.Corcoran@Sun.COM continue;
20409652SMichael.Corcoran@Sun.COM }
20419652SMichael.Corcoran@Sun.COM cpu_map[i]->obj = NULL;
20429652SMichael.Corcoran@Sun.COM /* Free item if no more reference to it. */
20439652SMichael.Corcoran@Sun.COM if (cpu_map[i]->cpu_id == -1) {
20449652SMichael.Corcoran@Sun.COM kmem_free(cpu_map[i], sizeof (struct cpu_map_item));
20459652SMichael.Corcoran@Sun.COM cpu_map[i] = NULL;
20469652SMichael.Corcoran@Sun.COM cpu_map_count--;
20479652SMichael.Corcoran@Sun.COM if (i != cpu_map_count) {
20489652SMichael.Corcoran@Sun.COM cpu_map[i] = cpu_map[cpu_map_count];
20499652SMichael.Corcoran@Sun.COM cpu_map[cpu_map_count] = NULL;
20509652SMichael.Corcoran@Sun.COM }
20519652SMichael.Corcoran@Sun.COM }
20529652SMichael.Corcoran@Sun.COM rc = AE_OK;
20539652SMichael.Corcoran@Sun.COM break;
20549652SMichael.Corcoran@Sun.COM }
20559652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
20569652SMichael.Corcoran@Sun.COM
20579652SMichael.Corcoran@Sun.COM return (rc);
20589652SMichael.Corcoran@Sun.COM }
20599652SMichael.Corcoran@Sun.COM
20609652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_map_cpu(processorid_t cpuid,UINT32 acpi_id)20619652SMichael.Corcoran@Sun.COM acpica_map_cpu(processorid_t cpuid, UINT32 acpi_id)
20629652SMichael.Corcoran@Sun.COM {
20639652SMichael.Corcoran@Sun.COM int i;
20649652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_OK;
20659652SMichael.Corcoran@Sun.COM struct cpu_map_item *item = NULL;
20669652SMichael.Corcoran@Sun.COM
20679652SMichael.Corcoran@Sun.COM ASSERT(cpuid != -1);
20689652SMichael.Corcoran@Sun.COM if (cpuid == -1) {
20699652SMichael.Corcoran@Sun.COM return (AE_ERROR);
20709652SMichael.Corcoran@Sun.COM }
20719652SMichael.Corcoran@Sun.COM
20729652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
207310394SMichael.Corcoran@Sun.COM cpu_map_called = 1;
20749652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
20759652SMichael.Corcoran@Sun.COM if (cpu_map[i]->cpu_id == cpuid) {
20769652SMichael.Corcoran@Sun.COM rc = AE_ALREADY_EXISTS;
20779652SMichael.Corcoran@Sun.COM break;
20789652SMichael.Corcoran@Sun.COM } else if (cpu_map[i]->proc_id == acpi_id) {
20799652SMichael.Corcoran@Sun.COM ASSERT(item == NULL);
20809652SMichael.Corcoran@Sun.COM item = cpu_map[i];
20819652SMichael.Corcoran@Sun.COM }
20829652SMichael.Corcoran@Sun.COM }
20839652SMichael.Corcoran@Sun.COM if (rc == AE_OK) {
20849652SMichael.Corcoran@Sun.COM if (item != NULL) {
20859652SMichael.Corcoran@Sun.COM if (item->cpu_id == -1) {
20869652SMichael.Corcoran@Sun.COM item->cpu_id = cpuid;
20879652SMichael.Corcoran@Sun.COM } else {
20889652SMichael.Corcoran@Sun.COM rc = AE_ALREADY_EXISTS;
20899652SMichael.Corcoran@Sun.COM }
20909652SMichael.Corcoran@Sun.COM } else if (cpu_map_count >= INT_MAX / 2) {
20919652SMichael.Corcoran@Sun.COM rc = AE_NO_MEMORY;
20929652SMichael.Corcoran@Sun.COM } else {
20939652SMichael.Corcoran@Sun.COM acpica_grow_cpu_map();
20949652SMichael.Corcoran@Sun.COM ASSERT(cpu_map != NULL);
20959652SMichael.Corcoran@Sun.COM ASSERT(cpu_map_count < cpu_map_count_max);
20969652SMichael.Corcoran@Sun.COM item = kmem_zalloc(sizeof (*item), KM_SLEEP);
20979652SMichael.Corcoran@Sun.COM item->cpu_id = cpuid;
20989652SMichael.Corcoran@Sun.COM item->proc_id = acpi_id;
20999652SMichael.Corcoran@Sun.COM item->apic_id = UINT32_MAX;
21009652SMichael.Corcoran@Sun.COM item->obj = NULL;
21019652SMichael.Corcoran@Sun.COM cpu_map[cpu_map_count] = item;
21029652SMichael.Corcoran@Sun.COM cpu_map_count++;
21039652SMichael.Corcoran@Sun.COM }
21049652SMichael.Corcoran@Sun.COM }
21059652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
21069652SMichael.Corcoran@Sun.COM
21079652SMichael.Corcoran@Sun.COM return (rc);
21089652SMichael.Corcoran@Sun.COM }
21099652SMichael.Corcoran@Sun.COM
21109652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_unmap_cpu(processorid_t cpuid)21119652SMichael.Corcoran@Sun.COM acpica_unmap_cpu(processorid_t cpuid)
21129652SMichael.Corcoran@Sun.COM {
21139652SMichael.Corcoran@Sun.COM int i;
21149652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_NOT_EXIST;
21159652SMichael.Corcoran@Sun.COM
21169652SMichael.Corcoran@Sun.COM ASSERT(cpuid != -1);
21179652SMichael.Corcoran@Sun.COM if (cpuid == -1) {
21189652SMichael.Corcoran@Sun.COM return (rc);
21199652SMichael.Corcoran@Sun.COM }
21209652SMichael.Corcoran@Sun.COM
21219652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
21229652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
21239652SMichael.Corcoran@Sun.COM if (cpu_map[i]->cpu_id != cpuid) {
21249652SMichael.Corcoran@Sun.COM continue;
21259652SMichael.Corcoran@Sun.COM }
21269652SMichael.Corcoran@Sun.COM cpu_map[i]->cpu_id = -1;
21279652SMichael.Corcoran@Sun.COM /* Free item if no more reference. */
21289652SMichael.Corcoran@Sun.COM if (cpu_map[i]->obj == NULL) {
21299652SMichael.Corcoran@Sun.COM kmem_free(cpu_map[i], sizeof (struct cpu_map_item));
21309652SMichael.Corcoran@Sun.COM cpu_map[i] = NULL;
21319652SMichael.Corcoran@Sun.COM cpu_map_count--;
21329652SMichael.Corcoran@Sun.COM if (i != cpu_map_count) {
21339652SMichael.Corcoran@Sun.COM cpu_map[i] = cpu_map[cpu_map_count];
21349652SMichael.Corcoran@Sun.COM cpu_map[cpu_map_count] = NULL;
21359652SMichael.Corcoran@Sun.COM }
21369652SMichael.Corcoran@Sun.COM }
21379652SMichael.Corcoran@Sun.COM rc = AE_OK;
21389652SMichael.Corcoran@Sun.COM break;
21399652SMichael.Corcoran@Sun.COM }
21409652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
21419652SMichael.Corcoran@Sun.COM
21429652SMichael.Corcoran@Sun.COM return (rc);
21439652SMichael.Corcoran@Sun.COM }
21449652SMichael.Corcoran@Sun.COM
21459652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_get_cpu_object_by_cpuid(processorid_t cpuid,ACPI_HANDLE * hdlp)21469652SMichael.Corcoran@Sun.COM acpica_get_cpu_object_by_cpuid(processorid_t cpuid, ACPI_HANDLE *hdlp)
21479652SMichael.Corcoran@Sun.COM {
21489652SMichael.Corcoran@Sun.COM int i;
21499652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_NOT_EXIST;
21509652SMichael.Corcoran@Sun.COM
21519652SMichael.Corcoran@Sun.COM ASSERT(cpuid != -1);
21529652SMichael.Corcoran@Sun.COM if (cpuid == -1) {
21539652SMichael.Corcoran@Sun.COM return (rc);
21549652SMichael.Corcoran@Sun.COM }
21559652SMichael.Corcoran@Sun.COM
21569652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
21579652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
21589652SMichael.Corcoran@Sun.COM if (cpu_map[i]->cpu_id == cpuid && cpu_map[i]->obj != NULL) {
21599652SMichael.Corcoran@Sun.COM *hdlp = cpu_map[i]->obj;
21609652SMichael.Corcoran@Sun.COM rc = AE_OK;
21619652SMichael.Corcoran@Sun.COM break;
21629652SMichael.Corcoran@Sun.COM }
21639652SMichael.Corcoran@Sun.COM }
21649652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
21659652SMichael.Corcoran@Sun.COM
21669652SMichael.Corcoran@Sun.COM return (rc);
21679652SMichael.Corcoran@Sun.COM }
21689652SMichael.Corcoran@Sun.COM
21699652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_get_cpu_object_by_procid(UINT32 procid,ACPI_HANDLE * hdlp)21709652SMichael.Corcoran@Sun.COM acpica_get_cpu_object_by_procid(UINT32 procid, ACPI_HANDLE *hdlp)
21719652SMichael.Corcoran@Sun.COM {
21729652SMichael.Corcoran@Sun.COM int i;
21739652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_NOT_EXIST;
21749652SMichael.Corcoran@Sun.COM
21759652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
21769652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
21779652SMichael.Corcoran@Sun.COM if (cpu_map[i]->proc_id == procid && cpu_map[i]->obj != NULL) {
21789652SMichael.Corcoran@Sun.COM *hdlp = cpu_map[i]->obj;
21799652SMichael.Corcoran@Sun.COM rc = AE_OK;
21809652SMichael.Corcoran@Sun.COM break;
21819652SMichael.Corcoran@Sun.COM }
21829652SMichael.Corcoran@Sun.COM }
21839652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
21849652SMichael.Corcoran@Sun.COM
21859652SMichael.Corcoran@Sun.COM return (rc);
21869652SMichael.Corcoran@Sun.COM }
21879652SMichael.Corcoran@Sun.COM
21889652SMichael.Corcoran@Sun.COM ACPI_STATUS
acpica_get_cpu_object_by_apicid(UINT32 apicid,ACPI_HANDLE * hdlp)21899652SMichael.Corcoran@Sun.COM acpica_get_cpu_object_by_apicid(UINT32 apicid, ACPI_HANDLE *hdlp)
21909652SMichael.Corcoran@Sun.COM {
21919652SMichael.Corcoran@Sun.COM int i;
21929652SMichael.Corcoran@Sun.COM ACPI_STATUS rc = AE_NOT_EXIST;
21939652SMichael.Corcoran@Sun.COM
21949652SMichael.Corcoran@Sun.COM ASSERT(apicid != UINT32_MAX);
21959652SMichael.Corcoran@Sun.COM if (apicid == UINT32_MAX) {
21969652SMichael.Corcoran@Sun.COM return (rc);
21979652SMichael.Corcoran@Sun.COM }
21989652SMichael.Corcoran@Sun.COM
21999652SMichael.Corcoran@Sun.COM mutex_enter(&cpu_map_lock);
22009652SMichael.Corcoran@Sun.COM for (i = 0; i < cpu_map_count; i++) {
22019652SMichael.Corcoran@Sun.COM if (cpu_map[i]->apic_id == apicid && cpu_map[i]->obj != NULL) {
22029652SMichael.Corcoran@Sun.COM *hdlp = cpu_map[i]->obj;
22039652SMichael.Corcoran@Sun.COM rc = AE_OK;
22049652SMichael.Corcoran@Sun.COM break;
22059652SMichael.Corcoran@Sun.COM }
22069652SMichael.Corcoran@Sun.COM }
22079652SMichael.Corcoran@Sun.COM mutex_exit(&cpu_map_lock);
22089652SMichael.Corcoran@Sun.COM
22099652SMichael.Corcoran@Sun.COM return (rc);
22109652SMichael.Corcoran@Sun.COM }
22119652SMichael.Corcoran@Sun.COM
2212*12004Sjiang.liu@intel.com ACPI_STATUS
acpica_get_cpu_id_by_object(ACPI_HANDLE hdl,processorid_t * cpuidp)2213*12004Sjiang.liu@intel.com acpica_get_cpu_id_by_object(ACPI_HANDLE hdl, processorid_t *cpuidp)
2214*12004Sjiang.liu@intel.com {
2215*12004Sjiang.liu@intel.com int i;
2216*12004Sjiang.liu@intel.com ACPI_STATUS rc = AE_NOT_EXIST;
2217*12004Sjiang.liu@intel.com
2218*12004Sjiang.liu@intel.com ASSERT(cpuidp != NULL);
2219*12004Sjiang.liu@intel.com if (hdl == NULL || cpuidp == NULL) {
2220*12004Sjiang.liu@intel.com return (rc);
2221*12004Sjiang.liu@intel.com }
2222*12004Sjiang.liu@intel.com
2223*12004Sjiang.liu@intel.com *cpuidp = -1;
2224*12004Sjiang.liu@intel.com mutex_enter(&cpu_map_lock);
2225*12004Sjiang.liu@intel.com for (i = 0; i < cpu_map_count; i++) {
2226*12004Sjiang.liu@intel.com if (cpu_map[i]->obj == hdl && cpu_map[i]->cpu_id != -1) {
2227*12004Sjiang.liu@intel.com *cpuidp = cpu_map[i]->cpu_id;
2228*12004Sjiang.liu@intel.com rc = AE_OK;
2229*12004Sjiang.liu@intel.com break;
2230*12004Sjiang.liu@intel.com }
2231*12004Sjiang.liu@intel.com }
2232*12004Sjiang.liu@intel.com mutex_exit(&cpu_map_lock);
2233*12004Sjiang.liu@intel.com
2234*12004Sjiang.liu@intel.com return (rc);
2235*12004Sjiang.liu@intel.com }
2236*12004Sjiang.liu@intel.com
2237*12004Sjiang.liu@intel.com ACPI_STATUS
acpica_get_apicid_by_object(ACPI_HANDLE hdl,UINT32 * rp)2238*12004Sjiang.liu@intel.com acpica_get_apicid_by_object(ACPI_HANDLE hdl, UINT32 *rp)
2239*12004Sjiang.liu@intel.com {
2240*12004Sjiang.liu@intel.com int i;
2241*12004Sjiang.liu@intel.com ACPI_STATUS rc = AE_NOT_EXIST;
2242*12004Sjiang.liu@intel.com
2243*12004Sjiang.liu@intel.com ASSERT(rp != NULL);
2244*12004Sjiang.liu@intel.com if (hdl == NULL || rp == NULL) {
2245*12004Sjiang.liu@intel.com return (rc);
2246*12004Sjiang.liu@intel.com }
2247*12004Sjiang.liu@intel.com
2248*12004Sjiang.liu@intel.com *rp = UINT32_MAX;
2249*12004Sjiang.liu@intel.com mutex_enter(&cpu_map_lock);
2250*12004Sjiang.liu@intel.com for (i = 0; i < cpu_map_count; i++) {
2251*12004Sjiang.liu@intel.com if (cpu_map[i]->obj == hdl &&
2252*12004Sjiang.liu@intel.com cpu_map[i]->apic_id != UINT32_MAX) {
2253*12004Sjiang.liu@intel.com *rp = cpu_map[i]->apic_id;
2254*12004Sjiang.liu@intel.com rc = AE_OK;
2255*12004Sjiang.liu@intel.com break;
2256*12004Sjiang.liu@intel.com }
2257*12004Sjiang.liu@intel.com }
2258*12004Sjiang.liu@intel.com mutex_exit(&cpu_map_lock);
2259*12004Sjiang.liu@intel.com
2260*12004Sjiang.liu@intel.com return (rc);
2261*12004Sjiang.liu@intel.com }
2262*12004Sjiang.liu@intel.com
2263*12004Sjiang.liu@intel.com ACPI_STATUS
acpica_get_procid_by_object(ACPI_HANDLE hdl,UINT32 * rp)2264*12004Sjiang.liu@intel.com acpica_get_procid_by_object(ACPI_HANDLE hdl, UINT32 *rp)
2265*12004Sjiang.liu@intel.com {
2266*12004Sjiang.liu@intel.com int i;
2267*12004Sjiang.liu@intel.com ACPI_STATUS rc = AE_NOT_EXIST;
2268*12004Sjiang.liu@intel.com
2269*12004Sjiang.liu@intel.com ASSERT(rp != NULL);
2270*12004Sjiang.liu@intel.com if (hdl == NULL || rp == NULL) {
2271*12004Sjiang.liu@intel.com return (rc);
2272*12004Sjiang.liu@intel.com }
2273*12004Sjiang.liu@intel.com
2274*12004Sjiang.liu@intel.com *rp = UINT32_MAX;
2275*12004Sjiang.liu@intel.com mutex_enter(&cpu_map_lock);
2276*12004Sjiang.liu@intel.com for (i = 0; i < cpu_map_count; i++) {
2277*12004Sjiang.liu@intel.com if (cpu_map[i]->obj == hdl) {
2278*12004Sjiang.liu@intel.com *rp = cpu_map[i]->proc_id;
2279*12004Sjiang.liu@intel.com rc = AE_OK;
2280*12004Sjiang.liu@intel.com break;
2281*12004Sjiang.liu@intel.com }
2282*12004Sjiang.liu@intel.com }
2283*12004Sjiang.liu@intel.com mutex_exit(&cpu_map_lock);
2284*12004Sjiang.liu@intel.com
2285*12004Sjiang.liu@intel.com return (rc);
2286*12004Sjiang.liu@intel.com }
2287*12004Sjiang.liu@intel.com
22889652SMichael.Corcoran@Sun.COM void
acpica_set_core_feature(uint64_t features)22899652SMichael.Corcoran@Sun.COM acpica_set_core_feature(uint64_t features)
22909652SMichael.Corcoran@Sun.COM {
22919652SMichael.Corcoran@Sun.COM atomic_or_64(&acpica_core_features, features);
22929652SMichael.Corcoran@Sun.COM }
22939652SMichael.Corcoran@Sun.COM
22949652SMichael.Corcoran@Sun.COM void
acpica_clear_core_feature(uint64_t features)22959652SMichael.Corcoran@Sun.COM acpica_clear_core_feature(uint64_t features)
22969652SMichael.Corcoran@Sun.COM {
22979652SMichael.Corcoran@Sun.COM atomic_and_64(&acpica_core_features, ~features);
22989652SMichael.Corcoran@Sun.COM }
22999652SMichael.Corcoran@Sun.COM
23009652SMichael.Corcoran@Sun.COM uint64_t
acpica_get_core_feature(uint64_t features)23019652SMichael.Corcoran@Sun.COM acpica_get_core_feature(uint64_t features)
23029652SMichael.Corcoran@Sun.COM {
23039652SMichael.Corcoran@Sun.COM return (acpica_core_features & features);
23049652SMichael.Corcoran@Sun.COM }
23059652SMichael.Corcoran@Sun.COM
23069652SMichael.Corcoran@Sun.COM void
acpica_set_devcfg_feature(uint64_t features)23079652SMichael.Corcoran@Sun.COM acpica_set_devcfg_feature(uint64_t features)
23089652SMichael.Corcoran@Sun.COM {
23099652SMichael.Corcoran@Sun.COM atomic_or_64(&acpica_devcfg_features, features);
23109652SMichael.Corcoran@Sun.COM }
23119652SMichael.Corcoran@Sun.COM
23129652SMichael.Corcoran@Sun.COM void
acpica_clear_devcfg_feature(uint64_t features)23139652SMichael.Corcoran@Sun.COM acpica_clear_devcfg_feature(uint64_t features)
23149652SMichael.Corcoran@Sun.COM {
23159652SMichael.Corcoran@Sun.COM atomic_and_64(&acpica_devcfg_features, ~features);
23169652SMichael.Corcoran@Sun.COM }
23179652SMichael.Corcoran@Sun.COM
23189652SMichael.Corcoran@Sun.COM uint64_t
acpica_get_devcfg_feature(uint64_t features)23199652SMichael.Corcoran@Sun.COM acpica_get_devcfg_feature(uint64_t features)
23209652SMichael.Corcoran@Sun.COM {
23219652SMichael.Corcoran@Sun.COM return (acpica_devcfg_features & features);
23224667Smh27603 }
23238906SEric.Saxe@Sun.COM
23248906SEric.Saxe@Sun.COM void
acpica_get_global_FADT(ACPI_TABLE_FADT ** gbl_FADT)23258906SEric.Saxe@Sun.COM acpica_get_global_FADT(ACPI_TABLE_FADT **gbl_FADT)
23268906SEric.Saxe@Sun.COM {
23278906SEric.Saxe@Sun.COM *gbl_FADT = &AcpiGbl_FADT;
23288906SEric.Saxe@Sun.COM }
232910147SMark.Haywood@Sun.COM
233010147SMark.Haywood@Sun.COM void
acpica_write_cpupm_capabilities(boolean_t pstates,boolean_t cstates)233110147SMark.Haywood@Sun.COM acpica_write_cpupm_capabilities(boolean_t pstates, boolean_t cstates)
233210147SMark.Haywood@Sun.COM {
233310147SMark.Haywood@Sun.COM if (pstates && AcpiGbl_FADT.PstateControl != 0)
233410147SMark.Haywood@Sun.COM (void) AcpiHwRegisterWrite(ACPI_REGISTER_SMI_COMMAND_BLOCK,
233510147SMark.Haywood@Sun.COM AcpiGbl_FADT.PstateControl);
233610147SMark.Haywood@Sun.COM
233710147SMark.Haywood@Sun.COM if (cstates && AcpiGbl_FADT.CstControl != 0)
233810147SMark.Haywood@Sun.COM (void) AcpiHwRegisterWrite(ACPI_REGISTER_SMI_COMMAND_BLOCK,
233910147SMark.Haywood@Sun.COM AcpiGbl_FADT.CstControl);
234010147SMark.Haywood@Sun.COM }
2341