xref: /illumos-gate/usr/src/uts/intel/io/acpica/osl.c (revision 3349e36e)
17c478bd9Sstevel@tonic-gate /*
28e56767dSsmall  * CDDL HEADER START
38e56767dSsmall  *
48e56767dSsmall  * The contents of this file are subject to the terms of the
530082d0cSmyers  * Common Development and Distribution License (the "License").
630082d0cSmyers  * You may not use this file except in compliance with the License.
78e56767dSsmall  *
88e56767dSsmall  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98e56767dSsmall  * or http://www.opensolaris.org/os/licensing.
108e56767dSsmall  * See the License for the specific language governing permissions
118e56767dSsmall  * and limitations under the License.
128e56767dSsmall  *
138e56767dSsmall  * When distributing Covered Code, include this CDDL HEADER in each
148e56767dSsmall  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158e56767dSsmall  * If applicable, add the following below this CDDL HEADER, with the
168e56767dSsmall  * fields enclosed by brackets "[]" replaced with your own identifying
178e56767dSsmall  * information: Portions Copyright [yyyy] [name of copyright owner]
188e56767dSsmall  *
198e56767dSsmall  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21450d6964Smyers 
227c478bd9Sstevel@tonic-gate /*
230e751525SEric Saxe  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
2535786f68SRobert Mustacchi  * Copyright 2018 Joyent, Inc.
26*3349e36eSPaul Winder  * Copyright 2019 Western Digital Corporation
277c478bd9Sstevel@tonic-gate  */
28fa96bd91SMichael Corcoran /*
29a3114836SGerry Liu  * Copyright (c) 2009-2010, Intel Corporation.
30fa96bd91SMichael Corcoran  * All rights reserved.
31fa96bd91SMichael Corcoran  */
328e56767dSsmall /*
338e56767dSsmall  * ACPI CA OSL for Solaris x86
348e56767dSsmall  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
387c478bd9Sstevel@tonic-gate #include <sys/psm.h>
397c478bd9Sstevel@tonic-gate #include <sys/pci_cfgspace.h>
40b9bfdccdSStuart Maybee #include <sys/apic.h>
417c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
424b1ce0a9SDana Myers #include <sys/sunddi.h>
435cff7825Smh #include <sys/sunndi.h>
447c478bd9Sstevel@tonic-gate #include <sys/pci.h>
457c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
467c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
477c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
48b72d5b75SMichael Corcoran #include <sys/x86_archext.h>
497c478bd9Sstevel@tonic-gate #include <sys/note.h>
509bb29364SDana Myers #include <sys/promif.h>
517c478bd9Sstevel@tonic-gate 
5278d5422cSMark Haywood #include <sys/acpi/accommon.h>
537c478bd9Sstevel@tonic-gate #include <sys/acpica.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #define	MAX_DAT_FILE_SIZE	(64*1024)
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* local functions */
587c478bd9Sstevel@tonic-gate static int CompressEisaID(char *np);
597c478bd9Sstevel@tonic-gate 
605cff7825Smh static void scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus);
617c478bd9Sstevel@tonic-gate static int acpica_query_bbn_problem(void);
627c478bd9Sstevel@tonic-gate static int acpica_find_pcibus(int busno, ACPI_HANDLE *rh);
637c478bd9Sstevel@tonic-gate static int acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint);
645cff7825Smh static ACPI_STATUS acpica_set_devinfo(ACPI_HANDLE, dev_info_t *);
65fa96bd91SMichael Corcoran static ACPI_STATUS acpica_unset_devinfo(ACPI_HANDLE);
6657190917SDana Myers static void acpica_devinfo_handler(ACPI_HANDLE, void *);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * Event queue vars
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate int acpica_eventq_init = 0;
7227f7c583Smyers ddi_taskq_t *osl_eventq[OSL_EC_BURST_HANDLER+1];
737c478bd9Sstevel@tonic-gate 
74db2bae30SDana Myers /*
75db2bae30SDana Myers  * Priorities relative to minclsyspri that each taskq
76db2bae30SDana Myers  * run at; OSL_NOTIFY_HANDLER needs to run at a higher
77db2bae30SDana Myers  * priority than OSL_GPE_HANDLER.  There's an implicit
78db2bae30SDana Myers  * assumption that no priority here results in exceeding
79db2bae30SDana Myers  * maxclsyspri.
80db2bae30SDana Myers  * Note: these initializations need to match the order of
81db2bae30SDana Myers  * ACPI_EXECUTE_TYPE.
82db2bae30SDana Myers  */
83db2bae30SDana Myers int osl_eventq_pri_delta[OSL_EC_BURST_HANDLER+1] = {
84db2bae30SDana Myers 	0,	/* OSL_GLOBAL_LOCK_HANDLER */
85db2bae30SDana Myers 	2,	/* OSL_NOTIFY_HANDLER */
86db2bae30SDana Myers 	0,	/* OSL_GPE_HANDLER */
87db2bae30SDana Myers 	0,	/* OSL_DEBUGGER_THREAD */
88db2bae30SDana Myers 	0,	/* OSL_EC_POLL_HANDLER */
89db2bae30SDana Myers 	0	/* OSL_EC_BURST_HANDLER */
90db2bae30SDana Myers };
91db2bae30SDana Myers 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * Note, if you change this path, you need to update
947c478bd9Sstevel@tonic-gate  * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate static char *acpi_table_path = "/boot/acpi/tables/";
977c478bd9Sstevel@tonic-gate 
985cff7825Smh /* non-zero while scan_d2a_map() is working */
995cff7825Smh static int scanning_d2a_map = 0;
1005cff7825Smh static int d2a_done = 0;
1017c478bd9Sstevel@tonic-gate 
102fa96bd91SMichael Corcoran /* features supported by ACPICA and ACPI device configuration. */
103a3114836SGerry Liu uint64_t acpica_core_features = ACPI_FEATURE_OSI_MODULE;
104fa96bd91SMichael Corcoran static uint64_t acpica_devcfg_features = 0;
105fa96bd91SMichael Corcoran 
106137e2f25SGuoli Shu /* set by acpi_poweroff() in PSMs and appm_ioctl() in acpippm for S3 */
107137e2f25SGuoli Shu int acpica_use_safe_delay = 0;
108859dcd3dSmyers 
1095cff7825Smh /* CPU mapping data */
1105cff7825Smh struct cpu_map_item {
111fa96bd91SMichael Corcoran 	processorid_t	cpu_id;
112b6917abeSmishra 	UINT32		proc_id;
113fa96bd91SMichael Corcoran 	UINT32		apic_id;
1145cff7825Smh 	ACPI_HANDLE	obj;
1155cff7825Smh };
1165cff7825Smh 
117a3114836SGerry Liu kmutex_t cpu_map_lock;
1185cff7825Smh static struct cpu_map_item **cpu_map = NULL;
119fa96bd91SMichael Corcoran static int cpu_map_count_max = 0;
1205cff7825Smh static int cpu_map_count = 0;
1215cff7825Smh static int cpu_map_built = 0;
1225cff7825Smh 
123b72d5b75SMichael Corcoran /*
124b72d5b75SMichael Corcoran  * On systems with the uppc PSM only, acpica_map_cpu() won't be called at all.
125b72d5b75SMichael Corcoran  * This flag is used to check for uppc-only systems by detecting whether
126b72d5b75SMichael Corcoran  * acpica_map_cpu() has been called or not.
127b72d5b75SMichael Corcoran  */
128b72d5b75SMichael Corcoran static int cpu_map_called = 0;
129b72d5b75SMichael Corcoran 
1305cff7825Smh static int acpi_has_broken_bbn = -1;
1315cff7825Smh 
13287bb58d6Smyers /* buffer for AcpiOsVprintf() */
13387bb58d6Smyers #define	ACPI_OSL_PR_BUFLEN	1024
13487bb58d6Smyers static char *acpi_osl_pr_buffer = NULL;
13587bb58d6Smyers static int acpi_osl_pr_buflen;
13687bb58d6Smyers 
1375cff7825Smh #define	D2A_DEBUG
1385cff7825Smh 
1397c478bd9Sstevel@tonic-gate /*
1407c478bd9Sstevel@tonic-gate  *
1417c478bd9Sstevel@tonic-gate  */
1427c478bd9Sstevel@tonic-gate static void
discard_event_queues()1437c478bd9Sstevel@tonic-gate discard_event_queues()
1447c478bd9Sstevel@tonic-gate {
14527f7c583Smyers 	int	i;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	/*
1487c478bd9Sstevel@tonic-gate 	 * destroy event queues
1497c478bd9Sstevel@tonic-gate 	 */
15027f7c583Smyers 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
15127f7c583Smyers 		if (osl_eventq[i])
15227f7c583Smyers 			ddi_taskq_destroy(osl_eventq[i]);
15327f7c583Smyers 	}
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  *
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate static ACPI_STATUS
init_event_queues()1617c478bd9Sstevel@tonic-gate init_event_queues()
1627c478bd9Sstevel@tonic-gate {
16327f7c583Smyers 	char	namebuf[32];
16427f7c583Smyers 	int	i, error = 0;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	/*
1677c478bd9Sstevel@tonic-gate 	 * Initialize event queues
1687c478bd9Sstevel@tonic-gate 	 */
1697c478bd9Sstevel@tonic-gate 
170db2bae30SDana Myers 	/* Always allocate only 1 thread per queue to force FIFO execution */
17127f7c583Smyers 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
17227f7c583Smyers 		snprintf(namebuf, 32, "ACPI%d", i);
173db2bae30SDana Myers 		osl_eventq[i] = ddi_taskq_create(NULL, namebuf, 1,
174db2bae30SDana Myers 		    osl_eventq_pri_delta[i] + minclsyspri, 0);
17527f7c583Smyers 		if (osl_eventq[i] == NULL)
17627f7c583Smyers 			error++;
17727f7c583Smyers 	}
17827f7c583Smyers 
17927f7c583Smyers 	if (error != 0) {
1807c478bd9Sstevel@tonic-gate 		discard_event_queues();
1817c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1827c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!acpica: could not initialize event queues");
1837c478bd9Sstevel@tonic-gate #endif
1847c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	acpica_eventq_init = 1;
1887c478bd9Sstevel@tonic-gate 	return (AE_OK);
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
19287bb58d6Smyers  * One-time initialization of OSL layer
1937c478bd9Sstevel@tonic-gate  */
1947c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsInitialize(void)1957c478bd9Sstevel@tonic-gate AcpiOsInitialize(void)
1967c478bd9Sstevel@tonic-gate {
19787bb58d6Smyers 	/*
19887bb58d6Smyers 	 * Allocate buffer for AcpiOsVprintf() here to avoid
19987bb58d6Smyers 	 * kmem_alloc()/kmem_free() at high PIL
20087bb58d6Smyers 	 */
20187bb58d6Smyers 	acpi_osl_pr_buffer = kmem_alloc(ACPI_OSL_PR_BUFLEN, KM_SLEEP);
20287bb58d6Smyers 	if (acpi_osl_pr_buffer != NULL)
20387bb58d6Smyers 		acpi_osl_pr_buflen = ACPI_OSL_PR_BUFLEN;
20487bb58d6Smyers 
2057c478bd9Sstevel@tonic-gate 	return (AE_OK);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /*
20987bb58d6Smyers  * One-time shut-down of OSL layer
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsTerminate(void)2127c478bd9Sstevel@tonic-gate AcpiOsTerminate(void)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 
21587bb58d6Smyers 	if (acpi_osl_pr_buffer != NULL)
21687bb58d6Smyers 		kmem_free(acpi_osl_pr_buffer, acpi_osl_pr_buflen);
21787bb58d6Smyers 
2187c478bd9Sstevel@tonic-gate 	discard_event_queues();
2197c478bd9Sstevel@tonic-gate 	return (AE_OK);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 
223db2bae30SDana Myers ACPI_PHYSICAL_ADDRESS
AcpiOsGetRootPointer()224db2bae30SDana Myers AcpiOsGetRootPointer()
2257c478bd9Sstevel@tonic-gate {
226db2bae30SDana Myers 	ACPI_PHYSICAL_ADDRESS Address;
227f2be5148Sszhou 
228f2be5148Sszhou 	/*
229f2be5148Sszhou 	 * For EFI firmware, the root pointer is defined in EFI systab.
230f2be5148Sszhou 	 * The boot code process the table and put the physical address
231f2be5148Sszhou 	 * in the acpi-root-tab property.
232f2be5148Sszhou 	 */
2331738dd6eSToomas Soome 	Address = ddi_prop_get_int64(DDI_DEV_T_ANY, ddi_root_node(),
234ee441788SToomas Soome 	    DDI_PROP_DONTPASS, "acpi-root-tab", 0);
235db2bae30SDana Myers 
236ee441788SToomas Soome 	if ((Address == 0) && ACPI_FAILURE(AcpiFindRootPointer(&Address)))
237ee441788SToomas Soome 		Address = 0;
238db2bae30SDana Myers 
239db2bae30SDana Myers 	return (Address);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2437c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES * InitVal,ACPI_STRING * NewVal)2447c478bd9Sstevel@tonic-gate AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *InitVal,
2451738dd6eSToomas Soome     ACPI_STRING *NewVal)
2467c478bd9Sstevel@tonic-gate {
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	*NewVal = 0;
2497c478bd9Sstevel@tonic-gate 	return (AE_OK);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate static void
acpica_strncpy(char * dest,const char * src,int len)2537c478bd9Sstevel@tonic-gate acpica_strncpy(char *dest, const char *src, int len)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	/*LINTED*/
2577c478bd9Sstevel@tonic-gate 	while ((*dest++ = *src++) && (--len > 0))
2587c478bd9Sstevel@tonic-gate 		/* copy the string */;
2597c478bd9Sstevel@tonic-gate 	*dest = '\0';
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsTableOverride(ACPI_TABLE_HEADER * ExistingTable,ACPI_TABLE_HEADER ** NewTable)2637c478bd9Sstevel@tonic-gate AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable,
2641738dd6eSToomas Soome     ACPI_TABLE_HEADER **NewTable)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate 	char signature[5];
2677c478bd9Sstevel@tonic-gate 	char oemid[7];
2687c478bd9Sstevel@tonic-gate 	char oemtableid[9];
2697c478bd9Sstevel@tonic-gate 	struct _buf *file;
2707c478bd9Sstevel@tonic-gate 	char *buf1, *buf2;
2717c478bd9Sstevel@tonic-gate 	int count;
2727c478bd9Sstevel@tonic-gate 	char acpi_table_loc[128];
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	acpica_strncpy(signature, ExistingTable->Signature, 4);
2757c478bd9Sstevel@tonic-gate 	acpica_strncpy(oemid, ExistingTable->OemId, 6);
2767c478bd9Sstevel@tonic-gate 	acpica_strncpy(oemtableid, ExistingTable->OemTableId, 8);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	/* File name format is "signature_oemid_oemtableid.dat" */
2797c478bd9Sstevel@tonic-gate 	(void) strcpy(acpi_table_loc, acpi_table_path);
2807c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, signature); /* for example, DSDT */
2817c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, "_");
2827c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, oemid); /* for example, IntelR */
2837c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, "_");
2847c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, oemtableid); /* for example, AWRDACPI */
2857c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, ".dat");
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	file = kobj_open_file(acpi_table_loc);
2887c478bd9Sstevel@tonic-gate 	if (file == (struct _buf *)-1) {
2897c478bd9Sstevel@tonic-gate 		*NewTable = 0;
2907c478bd9Sstevel@tonic-gate 		return (AE_OK);
2917c478bd9Sstevel@tonic-gate 	} else {
2927c478bd9Sstevel@tonic-gate 		buf1 = (char *)kmem_alloc(MAX_DAT_FILE_SIZE, KM_SLEEP);
2937c478bd9Sstevel@tonic-gate 		count = kobj_read_file(file, buf1, MAX_DAT_FILE_SIZE-1, 0);
2947c478bd9Sstevel@tonic-gate 		if (count >= MAX_DAT_FILE_SIZE) {
2957c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "!acpica: table %s file size too big",
2967c478bd9Sstevel@tonic-gate 			    acpi_table_loc);
2977c478bd9Sstevel@tonic-gate 			*NewTable = 0;
2987c478bd9Sstevel@tonic-gate 		} else {
2997c478bd9Sstevel@tonic-gate 			buf2 = (char *)kmem_alloc(count, KM_SLEEP);
3007c478bd9Sstevel@tonic-gate 			(void) memcpy(buf2, buf1, count);
3017c478bd9Sstevel@tonic-gate 			*NewTable = (ACPI_TABLE_HEADER *)buf2;
3027c478bd9Sstevel@tonic-gate 			cmn_err(CE_NOTE, "!acpica: replacing table: %s",
3037c478bd9Sstevel@tonic-gate 			    acpi_table_loc);
3047c478bd9Sstevel@tonic-gate 		}
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 	kobj_close_file(file);
3077c478bd9Sstevel@tonic-gate 	kmem_free(buf1, MAX_DAT_FILE_SIZE);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	return (AE_OK);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3127b1019a6SJerry Jelinek ACPI_STATUS
AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER * ExistingTable,ACPI_PHYSICAL_ADDRESS * NewAddress,UINT32 * NewTableLength)3137b1019a6SJerry Jelinek AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExistingTable,
3147b1019a6SJerry Jelinek     ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
3157b1019a6SJerry Jelinek {
3167b1019a6SJerry Jelinek 	return (AE_SUPPORT);
3177b1019a6SJerry Jelinek }
3187c478bd9Sstevel@tonic-gate 
31930082d0cSmyers /*
32030082d0cSmyers  * ACPI semaphore implementation
32130082d0cSmyers  */
32230082d0cSmyers typedef struct {
32330082d0cSmyers 	kmutex_t	mutex;
32430082d0cSmyers 	kcondvar_t	cv;
32530082d0cSmyers 	uint32_t	available;
32630082d0cSmyers 	uint32_t	initial;
32730082d0cSmyers 	uint32_t	maximum;
32830082d0cSmyers } acpi_sema_t;
32930082d0cSmyers 
33030082d0cSmyers /*
33130082d0cSmyers  *
33230082d0cSmyers  */
33330082d0cSmyers void
acpi_sema_init(acpi_sema_t * sp,unsigned max,unsigned count)33427f7c583Smyers acpi_sema_init(acpi_sema_t *sp, unsigned max, unsigned count)
33530082d0cSmyers {
33630082d0cSmyers 	mutex_init(&sp->mutex, NULL, MUTEX_DRIVER, NULL);
33730082d0cSmyers 	cv_init(&sp->cv, NULL, CV_DRIVER, NULL);
33830082d0cSmyers 	/* no need to enter mutex here at creation */
33930082d0cSmyers 	sp->available = count;
34030082d0cSmyers 	sp->initial = count;
34130082d0cSmyers 	sp->maximum = max;
34230082d0cSmyers }
34330082d0cSmyers 
34430082d0cSmyers /*
34530082d0cSmyers  *
34630082d0cSmyers  */
34730082d0cSmyers void
acpi_sema_destroy(acpi_sema_t * sp)34830082d0cSmyers acpi_sema_destroy(acpi_sema_t *sp)
34930082d0cSmyers {
35030082d0cSmyers 
35130082d0cSmyers 	cv_destroy(&sp->cv);
35230082d0cSmyers 	mutex_destroy(&sp->mutex);
35330082d0cSmyers }
35430082d0cSmyers 
35530082d0cSmyers /*
35630082d0cSmyers  *
35730082d0cSmyers  */
35830082d0cSmyers ACPI_STATUS
acpi_sema_p(acpi_sema_t * sp,unsigned count,uint16_t wait_time)35930082d0cSmyers acpi_sema_p(acpi_sema_t *sp, unsigned count, uint16_t wait_time)
36030082d0cSmyers {
36130082d0cSmyers 	ACPI_STATUS rv = AE_OK;
36230082d0cSmyers 	clock_t deadline;
36330082d0cSmyers 
36430082d0cSmyers 	mutex_enter(&sp->mutex);
36530082d0cSmyers 
36630082d0cSmyers 	if (sp->available >= count) {
36730082d0cSmyers 		/*
36830082d0cSmyers 		 * Enough units available, no blocking
36930082d0cSmyers 		 */
37030082d0cSmyers 		sp->available -= count;
37130082d0cSmyers 		mutex_exit(&sp->mutex);
37230082d0cSmyers 		return (rv);
37330082d0cSmyers 	} else if (wait_time == 0) {
37430082d0cSmyers 		/*
37530082d0cSmyers 		 * Not enough units available and timeout
37630082d0cSmyers 		 * specifies no blocking
37730082d0cSmyers 		 */
37830082d0cSmyers 		rv = AE_TIME;
37930082d0cSmyers 		mutex_exit(&sp->mutex);
38030082d0cSmyers 		return (rv);
38130082d0cSmyers 	}
38230082d0cSmyers 
38330082d0cSmyers 	/*
38430082d0cSmyers 	 * Not enough units available and timeout specifies waiting
38530082d0cSmyers 	 */
38630082d0cSmyers 	if (wait_time != ACPI_WAIT_FOREVER)
38730082d0cSmyers 		deadline = ddi_get_lbolt() +
38830082d0cSmyers 		    (clock_t)drv_usectohz(wait_time * 1000);
38930082d0cSmyers 
39030082d0cSmyers 	do {
39130082d0cSmyers 		if (wait_time == ACPI_WAIT_FOREVER)
39230082d0cSmyers 			cv_wait(&sp->cv, &sp->mutex);
39330082d0cSmyers 		else if (cv_timedwait(&sp->cv, &sp->mutex, deadline) < 0) {
39430082d0cSmyers 			rv = AE_TIME;
39530082d0cSmyers 			break;
39630082d0cSmyers 		}
39730082d0cSmyers 	} while (sp->available < count);
39830082d0cSmyers 
39930082d0cSmyers 	/* if we dropped out of the wait with AE_OK, we got the units */
40030082d0cSmyers 	if (rv == AE_OK)
40130082d0cSmyers 		sp->available -= count;
40230082d0cSmyers 
40330082d0cSmyers 	mutex_exit(&sp->mutex);
40430082d0cSmyers 	return (rv);
40530082d0cSmyers }
40630082d0cSmyers 
40730082d0cSmyers /*
40830082d0cSmyers  *
40930082d0cSmyers  */
41030082d0cSmyers void
acpi_sema_v(acpi_sema_t * sp,unsigned count)41130082d0cSmyers acpi_sema_v(acpi_sema_t *sp, unsigned count)
41230082d0cSmyers {
41330082d0cSmyers 	mutex_enter(&sp->mutex);
41430082d0cSmyers 	sp->available += count;
41530082d0cSmyers 	cv_broadcast(&sp->cv);
41630082d0cSmyers 	mutex_exit(&sp->mutex);
41730082d0cSmyers }
41830082d0cSmyers 
41930082d0cSmyers 
4207c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsCreateSemaphore(UINT32 MaxUnits,UINT32 InitialUnits,ACPI_HANDLE * OutHandle)4217c478bd9Sstevel@tonic-gate AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
4221738dd6eSToomas Soome     ACPI_HANDLE *OutHandle)
4237c478bd9Sstevel@tonic-gate {
42430082d0cSmyers 	acpi_sema_t *sp;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	if ((OutHandle == NULL) || (InitialUnits > MaxUnits))
4277c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
4287c478bd9Sstevel@tonic-gate 
42930082d0cSmyers 	sp = (acpi_sema_t *)kmem_alloc(sizeof (acpi_sema_t), KM_SLEEP);
43027f7c583Smyers 	acpi_sema_init(sp, MaxUnits, InitialUnits);
43130082d0cSmyers 	*OutHandle = (ACPI_HANDLE)sp;
4327c478bd9Sstevel@tonic-gate 	return (AE_OK);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)4377c478bd9Sstevel@tonic-gate AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
4387c478bd9Sstevel@tonic-gate {
4397c478bd9Sstevel@tonic-gate 
44030082d0cSmyers 	if (Handle == NULL)
44130082d0cSmyers 		return (AE_BAD_PARAMETER);
44230082d0cSmyers 
44330082d0cSmyers 	acpi_sema_destroy((acpi_sema_t *)Handle);
44430082d0cSmyers 	kmem_free((void *)Handle, sizeof (acpi_sema_t));
4457c478bd9Sstevel@tonic-gate 	return (AE_OK);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsWaitSemaphore(ACPI_HANDLE Handle,UINT32 Units,UINT16 Timeout)4497c478bd9Sstevel@tonic-gate AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 
45230082d0cSmyers 	if ((Handle == NULL) || (Units < 1))
45330082d0cSmyers 		return (AE_BAD_PARAMETER);
4547c478bd9Sstevel@tonic-gate 
45530082d0cSmyers 	return (acpi_sema_p((acpi_sema_t *)Handle, Units, Timeout));
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsSignalSemaphore(ACPI_HANDLE Handle,UINT32 Units)4597c478bd9Sstevel@tonic-gate AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
4607c478bd9Sstevel@tonic-gate {
4617c478bd9Sstevel@tonic-gate 
46230082d0cSmyers 	if ((Handle == NULL) || (Units < 1))
46330082d0cSmyers 		return (AE_BAD_PARAMETER);
46430082d0cSmyers 
46530082d0cSmyers 	acpi_sema_v((acpi_sema_t *)Handle, Units);
4667c478bd9Sstevel@tonic-gate 	return (AE_OK);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsCreateLock(ACPI_HANDLE * OutHandle)4707c478bd9Sstevel@tonic-gate AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
4717c478bd9Sstevel@tonic-gate {
47230082d0cSmyers 	kmutex_t *mp;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	if (OutHandle == NULL)
4757c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
4767c478bd9Sstevel@tonic-gate 
47730082d0cSmyers 	mp = (kmutex_t *)kmem_alloc(sizeof (kmutex_t), KM_SLEEP);
47830082d0cSmyers 	mutex_init(mp, NULL, MUTEX_DRIVER, NULL);
47930082d0cSmyers 	*OutHandle = (ACPI_HANDLE)mp;
4807c478bd9Sstevel@tonic-gate 	return (AE_OK);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate void
AcpiOsDeleteLock(ACPI_HANDLE Handle)4847c478bd9Sstevel@tonic-gate AcpiOsDeleteLock(ACPI_HANDLE Handle)
4857c478bd9Sstevel@tonic-gate {
48630082d0cSmyers 
48730082d0cSmyers 	if (Handle == NULL)
48830082d0cSmyers 		return;
48930082d0cSmyers 
49030082d0cSmyers 	mutex_destroy((kmutex_t *)Handle);
49130082d0cSmyers 	kmem_free((void *)Handle, sizeof (kmutex_t));
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate 
494db2bae30SDana Myers ACPI_CPU_FLAGS
AcpiOsAcquireLock(ACPI_HANDLE Handle)495450d6964Smyers AcpiOsAcquireLock(ACPI_HANDLE Handle)
4967c478bd9Sstevel@tonic-gate {
49730082d0cSmyers 
4980e751525SEric Saxe 
4990e751525SEric Saxe 	if (Handle == NULL)
5000e751525SEric Saxe 		return (AE_BAD_PARAMETER);
5010e751525SEric Saxe 
5020e751525SEric Saxe 	if (curthread == CPU->cpu_idle_thread) {
5030e751525SEric Saxe 		while (!mutex_tryenter((kmutex_t *)Handle))
5040e751525SEric Saxe 			/* spin */;
5050e751525SEric Saxe 	} else
5060e751525SEric Saxe 		mutex_enter((kmutex_t *)Handle);
5070e751525SEric Saxe 	return (AE_OK);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate void
AcpiOsReleaseLock(ACPI_HANDLE Handle,ACPI_CPU_FLAGS Flags)511db2bae30SDana Myers AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_CPU_FLAGS Flags)
5127c478bd9Sstevel@tonic-gate {
513450d6964Smyers 	_NOTE(ARGUNUSED(Flags))
5147c478bd9Sstevel@tonic-gate 
51530082d0cSmyers 	mutex_exit((kmutex_t *)Handle);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate void *
AcpiOsAllocate(ACPI_SIZE Size)5207c478bd9Sstevel@tonic-gate AcpiOsAllocate(ACPI_SIZE Size)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate 	ACPI_SIZE *tmp_ptr;
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	Size += sizeof (Size);
5257c478bd9Sstevel@tonic-gate 	tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP);
5267c478bd9Sstevel@tonic-gate 	*tmp_ptr++ = Size;
52730082d0cSmyers 	return (tmp_ptr);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate void
AcpiOsFree(void * Memory)5317c478bd9Sstevel@tonic-gate AcpiOsFree(void *Memory)
5327c478bd9Sstevel@tonic-gate {
5337c478bd9Sstevel@tonic-gate 	ACPI_SIZE	size, *tmp_ptr;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	tmp_ptr = (ACPI_SIZE *)Memory;
5367c478bd9Sstevel@tonic-gate 	tmp_ptr -= 1;
5377c478bd9Sstevel@tonic-gate 	size = *tmp_ptr;
53830082d0cSmyers 	kmem_free(tmp_ptr, size);
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate 
541b9bfdccdSStuart Maybee static int napics_found;	/* number of ioapic addresses in array */
542b9bfdccdSStuart Maybee static ACPI_PHYSICAL_ADDRESS ioapic_paddr[MAX_IO_APIC];
543b9bfdccdSStuart Maybee static ACPI_TABLE_MADT *acpi_mapic_dtp = NULL;
544b9bfdccdSStuart Maybee static void *dummy_ioapicadr;
545b9bfdccdSStuart Maybee 
546b9bfdccdSStuart Maybee void
acpica_find_ioapics(void)547b9bfdccdSStuart Maybee acpica_find_ioapics(void)
548b9bfdccdSStuart Maybee {
549b9bfdccdSStuart Maybee 	int			madt_seen, madt_size;
550b9bfdccdSStuart Maybee 	ACPI_SUBTABLE_HEADER		*ap;
551b9bfdccdSStuart Maybee 	ACPI_MADT_IO_APIC		*mia;
552b9bfdccdSStuart Maybee 
553b9bfdccdSStuart Maybee 	if (acpi_mapic_dtp != NULL)
554b9bfdccdSStuart Maybee 		return;	/* already parsed table */
555b9bfdccdSStuart Maybee 	if (AcpiGetTable(ACPI_SIG_MADT, 1,
556b9bfdccdSStuart Maybee 	    (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK)
557b9bfdccdSStuart Maybee 		return;
558b9bfdccdSStuart Maybee 
559b9bfdccdSStuart Maybee 	napics_found = 0;
560b9bfdccdSStuart Maybee 
561b9bfdccdSStuart Maybee 	/*
562b9bfdccdSStuart Maybee 	 * Search the MADT for ioapics
563b9bfdccdSStuart Maybee 	 */
564b9bfdccdSStuart Maybee 	ap = (ACPI_SUBTABLE_HEADER *) (acpi_mapic_dtp + 1);
565b9bfdccdSStuart Maybee 	madt_size = acpi_mapic_dtp->Header.Length;
566b9bfdccdSStuart Maybee 	madt_seen = sizeof (*acpi_mapic_dtp);
567b9bfdccdSStuart Maybee 
568b9bfdccdSStuart Maybee 	while (madt_seen < madt_size) {
569b9bfdccdSStuart Maybee 
570b9bfdccdSStuart Maybee 		switch (ap->Type) {
571b9bfdccdSStuart Maybee 		case ACPI_MADT_TYPE_IO_APIC:
572b9bfdccdSStuart Maybee 			mia = (ACPI_MADT_IO_APIC *) ap;
573b9bfdccdSStuart Maybee 			if (napics_found < MAX_IO_APIC) {
574b9bfdccdSStuart Maybee 				ioapic_paddr[napics_found++] =
575b9bfdccdSStuart Maybee 				    (ACPI_PHYSICAL_ADDRESS)
576b9bfdccdSStuart Maybee 				    (mia->Address & PAGEMASK);
577b9bfdccdSStuart Maybee 			}
578b9bfdccdSStuart Maybee 			break;
579b9bfdccdSStuart Maybee 
580b9bfdccdSStuart Maybee 		default:
581b9bfdccdSStuart Maybee 			break;
582b9bfdccdSStuart Maybee 		}
583b9bfdccdSStuart Maybee 
584b9bfdccdSStuart Maybee 		/* advance to next entry */
585b9bfdccdSStuart Maybee 		madt_seen += ap->Length;
586b9bfdccdSStuart Maybee 		ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length);
587b9bfdccdSStuart Maybee 	}
588b9bfdccdSStuart Maybee 	if (dummy_ioapicadr == NULL)
589b9bfdccdSStuart Maybee 		dummy_ioapicadr = kmem_zalloc(PAGESIZE, KM_SLEEP);
590b9bfdccdSStuart Maybee }
591b9bfdccdSStuart Maybee 
592b9bfdccdSStuart Maybee 
593db2bae30SDana Myers void *
AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress,ACPI_SIZE Size)594db2bae30SDana Myers AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size)
5957c478bd9Sstevel@tonic-gate {
596b9bfdccdSStuart Maybee 	int	i;
597b9bfdccdSStuart Maybee 
598b9bfdccdSStuart Maybee 	/*
599b9bfdccdSStuart Maybee 	 * If the iopaic address table is populated, check if trying
600b9bfdccdSStuart Maybee 	 * to access an ioapic.  Instead, return a pointer to a dummy ioapic.
601b9bfdccdSStuart Maybee 	 */
602b9bfdccdSStuart Maybee 	for (i = 0; i < napics_found; i++) {
603b9bfdccdSStuart Maybee 		if ((PhysicalAddress & PAGEMASK) == ioapic_paddr[i])
604b9bfdccdSStuart Maybee 			return (dummy_ioapicadr);
605b9bfdccdSStuart Maybee 	}
6067c478bd9Sstevel@tonic-gate 	/* FUTUREWORK: test PhysicalAddress for > 32 bits */
607db2bae30SDana Myers 	return (psm_map_new((paddr_t)PhysicalAddress,
608db2bae30SDana Myers 	    (size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ));
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate void
AcpiOsUnmapMemory(void * LogicalAddress,ACPI_SIZE Size)6127c478bd9Sstevel@tonic-gate AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
6137c478bd9Sstevel@tonic-gate {
614b9bfdccdSStuart Maybee 	/*
615b9bfdccdSStuart Maybee 	 * Check if trying to unmap dummy ioapic address.
616b9bfdccdSStuart Maybee 	 */
617b9bfdccdSStuart Maybee 	if (LogicalAddress == dummy_ioapicadr)
618b9bfdccdSStuart Maybee 		return;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6247c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsGetPhysicalAddress(void * LogicalAddress,ACPI_PHYSICAL_ADDRESS * PhysicalAddress)6257c478bd9Sstevel@tonic-gate AcpiOsGetPhysicalAddress(void *LogicalAddress,
6261738dd6eSToomas Soome     ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	/* UNIMPLEMENTED: not invoked by ACPI CA code */
63003335b7aSmyers 	return (AE_NOT_IMPLEMENTED);
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate ACPI_OSD_HANDLER acpi_isr;
6357c478bd9Sstevel@tonic-gate void *acpi_isr_context;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate uint_t
acpi_wrapper_isr(char * arg,char * arg1 __unused)63816d00323SToomas Soome acpi_wrapper_isr(char *arg, char *arg1 __unused)
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(arg))
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	int	status;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	status = (*acpi_isr)(acpi_isr_context);
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	if (status == ACPI_INTERRUPT_HANDLED) {
6477c478bd9Sstevel@tonic-gate 		return (DDI_INTR_CLAIMED);
6487c478bd9Sstevel@tonic-gate 	} else {
6497c478bd9Sstevel@tonic-gate 		return (DDI_INTR_UNCLAIMED);
6507c478bd9Sstevel@tonic-gate 	}
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate 
653186507a7Smyers static int acpi_intr_hooked = 0;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,ACPI_OSD_HANDLER ServiceRoutine,void * Context)6567c478bd9Sstevel@tonic-gate AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
6571738dd6eSToomas Soome     ACPI_OSD_HANDLER ServiceRoutine,
6581738dd6eSToomas Soome     void *Context)
6597c478bd9Sstevel@tonic-gate {
66027f7c583Smyers 	_NOTE(ARGUNUSED(InterruptNumber))
66127f7c583Smyers 
6627c478bd9Sstevel@tonic-gate 	int retval;
663450d6964Smyers 	int sci_vect;
664450d6964Smyers 	iflag_t sci_flags;
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	acpi_isr = ServiceRoutine;
6677c478bd9Sstevel@tonic-gate 	acpi_isr_context = Context;
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	/*
670450d6964Smyers 	 * Get SCI (adjusted for PIC/APIC mode if necessary)
6717c478bd9Sstevel@tonic-gate 	 */
672450d6964Smyers 	if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) {
673450d6964Smyers 		return (AE_ERROR);
674450d6964Smyers 	}
675450d6964Smyers 
676450d6964Smyers #ifdef	DEBUG
677450d6964Smyers 	cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect);
678450d6964Smyers #endif
679450d6964Smyers 
68016d00323SToomas Soome 	retval = add_avintr(NULL, SCI_IPL, acpi_wrapper_isr,
6815dff2f34Smyers 	    "ACPI SCI", sci_vect, NULL, NULL, NULL, NULL);
6827c478bd9Sstevel@tonic-gate 	if (retval) {
683186507a7Smyers 		acpi_intr_hooked = 1;
6847c478bd9Sstevel@tonic-gate 		return (AE_OK);
685186507a7Smyers 	} else
6867c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,ACPI_OSD_HANDLER ServiceRoutine)6907c478bd9Sstevel@tonic-gate AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
6911738dd6eSToomas Soome     ACPI_OSD_HANDLER ServiceRoutine)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(ServiceRoutine))
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6967c478bd9Sstevel@tonic-gate 	cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber);
6977c478bd9Sstevel@tonic-gate #endif
698186507a7Smyers 	if (acpi_intr_hooked) {
69916d00323SToomas Soome 		rem_avintr(NULL, LOCK_LEVEL - 1, acpi_wrapper_isr,
7005dff2f34Smyers 		    InterruptNumber);
701186507a7Smyers 		acpi_intr_hooked = 0;
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 	return (AE_OK);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 
70727f7c583Smyers ACPI_THREAD_ID
AcpiOsGetThreadId(void)7087c478bd9Sstevel@tonic-gate AcpiOsGetThreadId(void)
7097c478bd9Sstevel@tonic-gate {
71027f7c583Smyers 	/*
711aa2aa9a6SDana Myers 	 * ACPI CA doesn't care what actual value is returned as long
712aa2aa9a6SDana Myers 	 * as it is non-zero and unique to each existing thread.
713aa2aa9a6SDana Myers 	 * ACPI CA assumes that thread ID is castable to a pointer,
714aa2aa9a6SDana Myers 	 * so we use the current thread pointer.
71527f7c583Smyers 	 */
71626f3cdf0SGordon Ross 	return (ACPI_CAST_PTHREAD_T((uintptr_t)curthread));
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate /*
7207c478bd9Sstevel@tonic-gate  *
7217c478bd9Sstevel@tonic-gate  */
7227c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsExecute(ACPI_EXECUTE_TYPE Type,ACPI_OSD_EXEC_CALLBACK Function,void * Context)72327f7c583Smyers AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK  Function,
72427f7c583Smyers     void *Context)
7257c478bd9Sstevel@tonic-gate {
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	if (!acpica_eventq_init) {
7287c478bd9Sstevel@tonic-gate 		/*
7297c478bd9Sstevel@tonic-gate 		 * Create taskqs for event handling
7307c478bd9Sstevel@tonic-gate 		 */
7317c478bd9Sstevel@tonic-gate 		if (init_event_queues() != AE_OK)
7325dff2f34Smyers 			return (AE_ERROR);
7337c478bd9Sstevel@tonic-gate 	}
7347c478bd9Sstevel@tonic-gate 
73527f7c583Smyers 	if (ddi_taskq_dispatch(osl_eventq[Type], Function, Context,
73627f7c583Smyers 	    DDI_NOSLEEP) == DDI_FAILURE) {
7377c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7387c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!acpica: unable to dispatch event");
7397c478bd9Sstevel@tonic-gate #endif
7407c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
7417c478bd9Sstevel@tonic-gate 	}
7427c478bd9Sstevel@tonic-gate 	return (AE_OK);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate 
7467b1019a6SJerry Jelinek 
7477b1019a6SJerry Jelinek void
AcpiOsWaitEventsComplete(void)7487b1019a6SJerry Jelinek AcpiOsWaitEventsComplete(void)
7497b1019a6SJerry Jelinek {
7507b1019a6SJerry Jelinek 	int	i;
7517b1019a6SJerry Jelinek 
7527b1019a6SJerry Jelinek 	/*
7537b1019a6SJerry Jelinek 	 * Wait for event queues to be empty.
7547b1019a6SJerry Jelinek 	 */
7557b1019a6SJerry Jelinek 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
7567b1019a6SJerry Jelinek 		if (osl_eventq[i] != NULL) {
7577b1019a6SJerry Jelinek 			ddi_taskq_wait(osl_eventq[i]);
7587b1019a6SJerry Jelinek 		}
7597b1019a6SJerry Jelinek 	}
7607b1019a6SJerry Jelinek }
7617b1019a6SJerry Jelinek 
7627c478bd9Sstevel@tonic-gate void
AcpiOsSleep(ACPI_INTEGER Milliseconds)7637c478bd9Sstevel@tonic-gate AcpiOsSleep(ACPI_INTEGER Milliseconds)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate 	/*
766137e2f25SGuoli Shu 	 * During kernel startup, before the first tick interrupt
767137e2f25SGuoli Shu 	 * has taken place, we can't call delay; very late in
768137e2f25SGuoli Shu 	 * kernel shutdown or suspend/resume, clock interrupts
769859dcd3dSmyers 	 * are blocked, so delay doesn't work then either.
770859dcd3dSmyers 	 * So we busy wait if lbolt == 0 (kernel startup)
771137e2f25SGuoli Shu 	 * or if acpica_use_safe_delay has been set to a
772137e2f25SGuoli Shu 	 * non-zero value.
7737c478bd9Sstevel@tonic-gate 	 */
774137e2f25SGuoli Shu 	if ((ddi_get_lbolt() == 0) || acpica_use_safe_delay)
7757c478bd9Sstevel@tonic-gate 		drv_usecwait(Milliseconds * 1000);
7767c478bd9Sstevel@tonic-gate 	else
7777c478bd9Sstevel@tonic-gate 		delay(drv_usectohz(Milliseconds * 1000));
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate void
AcpiOsStall(UINT32 Microseconds)7817c478bd9Sstevel@tonic-gate AcpiOsStall(UINT32 Microseconds)
7827c478bd9Sstevel@tonic-gate {
7837c478bd9Sstevel@tonic-gate 	drv_usecwait(Microseconds);
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate /*
7887c478bd9Sstevel@tonic-gate  * Implementation of "Windows 2001" compatible I/O permission map
7897c478bd9Sstevel@tonic-gate  *
7907c478bd9Sstevel@tonic-gate  */
7917c478bd9Sstevel@tonic-gate #define	OSL_IO_NONE	(0)
7927c478bd9Sstevel@tonic-gate #define	OSL_IO_READ	(1<<0)
7937c478bd9Sstevel@tonic-gate #define	OSL_IO_WRITE	(1<<1)
7947c478bd9Sstevel@tonic-gate #define	OSL_IO_RW	(OSL_IO_READ | OSL_IO_WRITE)
7957c478bd9Sstevel@tonic-gate #define	OSL_IO_TERM	(1<<2)
7967c478bd9Sstevel@tonic-gate #define	OSL_IO_DEFAULT	OSL_IO_RW
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate static struct io_perm  {
7997c478bd9Sstevel@tonic-gate 	ACPI_IO_ADDRESS	low;
8007c478bd9Sstevel@tonic-gate 	ACPI_IO_ADDRESS	high;
8017c478bd9Sstevel@tonic-gate 	uint8_t		perm;
8027c478bd9Sstevel@tonic-gate } osl_io_perm[] = {
8034cf02d40SSaurabh Misra 	{ 0xcf8, 0xd00, OSL_IO_TERM | OSL_IO_RW}
8047c478bd9Sstevel@tonic-gate };
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate /*
8087c478bd9Sstevel@tonic-gate  *
8097c478bd9Sstevel@tonic-gate  */
8107c478bd9Sstevel@tonic-gate static struct io_perm *
osl_io_find_perm(ACPI_IO_ADDRESS addr)8117c478bd9Sstevel@tonic-gate osl_io_find_perm(ACPI_IO_ADDRESS addr)
8127c478bd9Sstevel@tonic-gate {
8137c478bd9Sstevel@tonic-gate 	struct io_perm *p;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	p = osl_io_perm;
8167c478bd9Sstevel@tonic-gate 	while (p != NULL) {
8177c478bd9Sstevel@tonic-gate 		if ((p->low <= addr) && (addr <= p->high))
8187c478bd9Sstevel@tonic-gate 			break;
8197c478bd9Sstevel@tonic-gate 		p = (p->perm & OSL_IO_TERM) ? NULL : p+1;
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 	return (p);
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate /*
8267c478bd9Sstevel@tonic-gate  *
8277c478bd9Sstevel@tonic-gate  */
8287c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsReadPort(ACPI_IO_ADDRESS Address,UINT32 * Value,UINT32 Width)8297c478bd9Sstevel@tonic-gate AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
8307c478bd9Sstevel@tonic-gate {
8317c478bd9Sstevel@tonic-gate 	struct io_perm *p;
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	/* verify permission */
8347c478bd9Sstevel@tonic-gate 	p = osl_io_find_perm(Address);
8357c478bd9Sstevel@tonic-gate 	if (p && (p->perm & OSL_IO_READ) == 0) {
8367c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted",
8375dff2f34Smyers 		    (long)Address, Width);
8387c478bd9Sstevel@tonic-gate 		*Value = 0xffffffff;
8397c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
8407c478bd9Sstevel@tonic-gate 	}
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	switch (Width) {
8437c478bd9Sstevel@tonic-gate 	case 8:
8447c478bd9Sstevel@tonic-gate 		*Value = inb(Address);
8457c478bd9Sstevel@tonic-gate 		break;
8467c478bd9Sstevel@tonic-gate 	case 16:
8477c478bd9Sstevel@tonic-gate 		*Value = inw(Address);
8487c478bd9Sstevel@tonic-gate 		break;
8497c478bd9Sstevel@tonic-gate 	case 32:
8507c478bd9Sstevel@tonic-gate 		*Value = inl(Address);
8517c478bd9Sstevel@tonic-gate 		break;
8527c478bd9Sstevel@tonic-gate 	default:
8537c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed",
8545dff2f34Smyers 		    (long)Address, Width);
8557c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 	return (AE_OK);
8587c478bd9Sstevel@tonic-gate }
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsWritePort(ACPI_IO_ADDRESS Address,UINT32 Value,UINT32 Width)8617c478bd9Sstevel@tonic-gate AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
8627c478bd9Sstevel@tonic-gate {
8637c478bd9Sstevel@tonic-gate 	struct io_perm *p;
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	/* verify permission */
8667c478bd9Sstevel@tonic-gate 	p = osl_io_find_perm(Address);
8677c478bd9Sstevel@tonic-gate 	if (p && (p->perm & OSL_IO_WRITE) == 0) {
8687c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted",
8697c478bd9Sstevel@tonic-gate 		    (long)Address, Width);
8707c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
8717c478bd9Sstevel@tonic-gate 	}
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 	switch (Width) {
8747c478bd9Sstevel@tonic-gate 	case 8:
8757c478bd9Sstevel@tonic-gate 		outb(Address, Value);
8767c478bd9Sstevel@tonic-gate 		break;
8777c478bd9Sstevel@tonic-gate 	case 16:
8787c478bd9Sstevel@tonic-gate 		outw(Address, Value);
8797c478bd9Sstevel@tonic-gate 		break;
8807c478bd9Sstevel@tonic-gate 	case 32:
8817c478bd9Sstevel@tonic-gate 		outl(Address, Value);
8827c478bd9Sstevel@tonic-gate 		break;
8837c478bd9Sstevel@tonic-gate 	default:
8847c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed",
8857c478bd9Sstevel@tonic-gate 		    (long)Address, Width);
8867c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
8877c478bd9Sstevel@tonic-gate 	}
8887c478bd9Sstevel@tonic-gate 	return (AE_OK);
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate /*
8937c478bd9Sstevel@tonic-gate  *
8947c478bd9Sstevel@tonic-gate  */
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate #define	OSL_RW(ptr, val, type, rw) \
8977c478bd9Sstevel@tonic-gate 	{ if (rw) *((type *)(ptr)) = *((type *) val); \
8987c478bd9Sstevel@tonic-gate 	    else *((type *) val) = *((type *)(ptr)); }
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate static void
osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address,UINT64 * Value,UINT32 Width,int write)9027b1019a6SJerry Jelinek osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value,
9037c478bd9Sstevel@tonic-gate     UINT32 Width, int write)
9047c478bd9Sstevel@tonic-gate {
9057c478bd9Sstevel@tonic-gate 	size_t	maplen = Width / 8;
9067c478bd9Sstevel@tonic-gate 	caddr_t	ptr;
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	ptr = psm_map_new((paddr_t)Address, maplen,
9097c478bd9Sstevel@tonic-gate 	    PSM_PROT_WRITE | PSM_PROT_READ);
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	switch (maplen) {
9127c478bd9Sstevel@tonic-gate 	case 1:
9137c478bd9Sstevel@tonic-gate 		OSL_RW(ptr, Value, uint8_t, write);
9147c478bd9Sstevel@tonic-gate 		break;
9157c478bd9Sstevel@tonic-gate 	case 2:
9167c478bd9Sstevel@tonic-gate 		OSL_RW(ptr, Value, uint16_t, write);
9177c478bd9Sstevel@tonic-gate 		break;
9187c478bd9Sstevel@tonic-gate 	case 4:
9197c478bd9Sstevel@tonic-gate 		OSL_RW(ptr, Value, uint32_t, write);
9207c478bd9Sstevel@tonic-gate 		break;
9217b1019a6SJerry Jelinek 	case 8:
9227b1019a6SJerry Jelinek 		OSL_RW(ptr, Value, uint64_t, write);
9237b1019a6SJerry Jelinek 		break;
9247c478bd9Sstevel@tonic-gate 	default:
9257c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d",
9267c478bd9Sstevel@tonic-gate 		    Width);
9277c478bd9Sstevel@tonic-gate 		break;
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	psm_unmap(ptr, maplen);
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,UINT64 * Value,UINT32 Width)9347c478bd9Sstevel@tonic-gate AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,
9351738dd6eSToomas Soome     UINT64 *Value, UINT32 Width)
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate 	osl_rw_memory(Address, Value, Width, 0);
9387c478bd9Sstevel@tonic-gate 	return (AE_OK);
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,UINT64 Value,UINT32 Width)9427c478bd9Sstevel@tonic-gate AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,
9431738dd6eSToomas Soome     UINT64 Value, UINT32 Width)
9447c478bd9Sstevel@tonic-gate {
9457c478bd9Sstevel@tonic-gate 	osl_rw_memory(Address, &Value, Width, 1);
9467c478bd9Sstevel@tonic-gate 	return (AE_OK);
9477c478bd9Sstevel@tonic-gate }
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsReadPciConfiguration(ACPI_PCI_ID * PciId,UINT32 Reg,UINT64 * Value,UINT32 Width)95126f3cdf0SGordon Ross AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Reg,
9521738dd6eSToomas Soome     UINT64 *Value, UINT32 Width)
9537c478bd9Sstevel@tonic-gate {
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	switch (Width) {
9567c478bd9Sstevel@tonic-gate 	case 8:
95726f3cdf0SGordon Ross 		*Value = (UINT64)(*pci_getb_func)
95826f3cdf0SGordon Ross 		    (PciId->Bus, PciId->Device, PciId->Function, Reg);
9597c478bd9Sstevel@tonic-gate 		break;
9607c478bd9Sstevel@tonic-gate 	case 16:
96126f3cdf0SGordon Ross 		*Value = (UINT64)(*pci_getw_func)
96226f3cdf0SGordon Ross 		    (PciId->Bus, PciId->Device, PciId->Function, Reg);
9637c478bd9Sstevel@tonic-gate 		break;
9647c478bd9Sstevel@tonic-gate 	case 32:
96526f3cdf0SGordon Ross 		*Value = (UINT64)(*pci_getl_func)
96626f3cdf0SGordon Ross 		    (PciId->Bus, PciId->Device, PciId->Function, Reg);
9677c478bd9Sstevel@tonic-gate 		break;
9687c478bd9Sstevel@tonic-gate 	case 64:
9697c478bd9Sstevel@tonic-gate 	default:
9707c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed",
97126f3cdf0SGordon Ross 		    Reg, Width);
9727c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 	return (AE_OK);
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate /*
9787c478bd9Sstevel@tonic-gate  *
9797c478bd9Sstevel@tonic-gate  */
9807c478bd9Sstevel@tonic-gate int acpica_write_pci_config_ok = 1;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate ACPI_STATUS
AcpiOsWritePciConfiguration(ACPI_PCI_ID * PciId,UINT32 Reg,UINT64 Value,UINT32 Width)98326f3cdf0SGordon Ross AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Reg,
9841738dd6eSToomas Soome     UINT64 Value, UINT32 Width)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	if (!acpica_write_pci_config_ok) {
9887c478bd9Sstevel@tonic-gate