xref: /illumos-gate/usr/src/uts/intel/io/acpica/osl.c (revision 5dff2f34)
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 /*
23*5dff2f34Smyers  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
268e56767dSsmall /*
278e56767dSsmall  * ACPI CA OSL for Solaris x86
288e56767dSsmall  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
357c478bd9Sstevel@tonic-gate #include <sys/psm.h>
367c478bd9Sstevel@tonic-gate #include <sys/pci_cfgspace.h>
377c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
387c478bd9Sstevel@tonic-gate #include <sys/pci.h>
397c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
407c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
417c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
427c478bd9Sstevel@tonic-gate #include <sys/note.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include <sys/acpi/acpi.h>
457c478bd9Sstevel@tonic-gate #include <sys/acpica.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate extern int (*psm_translate_irq)(dev_info_t *, int);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #define	MAX_DAT_FILE_SIZE	(64*1024)
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #define	D2A_INITLEN	20
527c478bd9Sstevel@tonic-gate static int d2a_len = 0;
537c478bd9Sstevel@tonic-gate static int d2a_valid = 0;
547c478bd9Sstevel@tonic-gate static d2a *d2a_table;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static int acpi_has_broken_bbn = -1;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /* local functions */
597c478bd9Sstevel@tonic-gate static int CompressEisaID(char *np);
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static void create_d2a_map(void);
627c478bd9Sstevel@tonic-gate static void create_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus);
637c478bd9Sstevel@tonic-gate static void new_d2a_entry(dev_info_t *dip, ACPI_HANDLE acpiobj,
647c478bd9Sstevel@tonic-gate 	int bus, int dev, int func);
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate static int acpica_query_bbn_problem(void);
677c478bd9Sstevel@tonic-gate static int acpica_find_pcibus(int busno, ACPI_HANDLE *rh);
687c478bd9Sstevel@tonic-gate static int acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate int acpica_find_pciobj(dev_info_t *dip, ACPI_HANDLE *rh);
717c478bd9Sstevel@tonic-gate static int acpica_find_pcid2a(ACPI_HANDLE, d2a **);
727c478bd9Sstevel@tonic-gate int acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint);
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * Event queue vars
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate int acpica_eventq_thread_count = 1;
787c478bd9Sstevel@tonic-gate int acpica_eventq_init = 0;
7927f7c583Smyers ddi_taskq_t *osl_eventq[OSL_EC_BURST_HANDLER+1];
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * Note, if you change this path, you need to update
837c478bd9Sstevel@tonic-gate  * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate static char *acpi_table_path = "/boot/acpi/tables/";
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /* non-zero while create_d2a_map() is working */
887c478bd9Sstevel@tonic-gate static int creating_d2a_map = 0;
897c478bd9Sstevel@tonic-gate 
90859dcd3dSmyers /* set by acpi_poweroff() in PSMs */
91859dcd3dSmyers int acpica_powering_off = 0;
92859dcd3dSmyers 
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate  *
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate static void
977c478bd9Sstevel@tonic-gate discard_event_queues()
987c478bd9Sstevel@tonic-gate {
9927f7c583Smyers 	int	i;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	/*
1027c478bd9Sstevel@tonic-gate 	 * destroy event queues
1037c478bd9Sstevel@tonic-gate 	 */
10427f7c583Smyers 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
10527f7c583Smyers 		if (osl_eventq[i])
10627f7c583Smyers 			ddi_taskq_destroy(osl_eventq[i]);
10727f7c583Smyers 	}
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate  *
1137c478bd9Sstevel@tonic-gate  */
1147c478bd9Sstevel@tonic-gate static ACPI_STATUS
1157c478bd9Sstevel@tonic-gate init_event_queues()
1167c478bd9Sstevel@tonic-gate {
11727f7c583Smyers 	char	namebuf[32];
11827f7c583Smyers 	int	i, error = 0;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	/*
1217c478bd9Sstevel@tonic-gate 	 * Initialize event queues
1227c478bd9Sstevel@tonic-gate 	 */
1237c478bd9Sstevel@tonic-gate 
12427f7c583Smyers 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
12527f7c583Smyers 		snprintf(namebuf, 32, "ACPI%d", i);
12627f7c583Smyers 		osl_eventq[i] = ddi_taskq_create(NULL, namebuf,
12727f7c583Smyers 		    acpica_eventq_thread_count, TASKQ_DEFAULTPRI, 0);
12827f7c583Smyers 		if (osl_eventq[i] == NULL)
12927f7c583Smyers 			error++;
13027f7c583Smyers 	}
13127f7c583Smyers 
13227f7c583Smyers 	if (error != 0) {
1337c478bd9Sstevel@tonic-gate 		discard_event_queues();
1347c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1357c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!acpica: could not initialize event queues");
1367c478bd9Sstevel@tonic-gate #endif
1377c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	acpica_eventq_init = 1;
1417c478bd9Sstevel@tonic-gate 	return (AE_OK);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  *
1467c478bd9Sstevel@tonic-gate  */
1477c478bd9Sstevel@tonic-gate ACPI_STATUS
1487c478bd9Sstevel@tonic-gate AcpiOsInitialize(void)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	return (AE_OK);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate  *
1567c478bd9Sstevel@tonic-gate  */
1577c478bd9Sstevel@tonic-gate ACPI_STATUS
1587c478bd9Sstevel@tonic-gate AcpiOsTerminate(void)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	discard_event_queues();
1627c478bd9Sstevel@tonic-gate 	return (AE_OK);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate ACPI_STATUS
1677c478bd9Sstevel@tonic-gate AcpiOsGetRootPointer(UINT32 Flags, ACPI_POINTER *Address)
1687c478bd9Sstevel@tonic-gate {
169f2be5148Sszhou 	uint_t acpi_root_tab;
170f2be5148Sszhou 
171f2be5148Sszhou 	/*
172f2be5148Sszhou 	 * For EFI firmware, the root pointer is defined in EFI systab.
173f2be5148Sszhou 	 * The boot code process the table and put the physical address
174f2be5148Sszhou 	 * in the acpi-root-tab property.
175f2be5148Sszhou 	 */
176f2be5148Sszhou 	acpi_root_tab = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0,
177f2be5148Sszhou 	    "acpi-root-tab", 0);
178f2be5148Sszhou 	if (acpi_root_tab != 0) {
179f2be5148Sszhou 		Address->PointerType = ACPI_PHYSICAL_POINTER;
180f2be5148Sszhou 		Address->Pointer.Physical = acpi_root_tab;
181f2be5148Sszhou 		return (AE_OK);
182f2be5148Sszhou 	}
1837c478bd9Sstevel@tonic-gate 	return (AcpiFindRootPointer(Flags, Address));
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1877c478bd9Sstevel@tonic-gate ACPI_STATUS
1887c478bd9Sstevel@tonic-gate AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *InitVal,
1897c478bd9Sstevel@tonic-gate 				ACPI_STRING *NewVal)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	*NewVal = 0;
1937c478bd9Sstevel@tonic-gate 	return (AE_OK);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate static void
1977c478bd9Sstevel@tonic-gate acpica_strncpy(char *dest, const char *src, int len)
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	/*LINTED*/
2017c478bd9Sstevel@tonic-gate 	while ((*dest++ = *src++) && (--len > 0))
2027c478bd9Sstevel@tonic-gate 		/* copy the string */;
2037c478bd9Sstevel@tonic-gate 	*dest = '\0';
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate ACPI_STATUS
2077c478bd9Sstevel@tonic-gate AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable,
2087c478bd9Sstevel@tonic-gate 			ACPI_TABLE_HEADER **NewTable)
2097c478bd9Sstevel@tonic-gate {
2107c478bd9Sstevel@tonic-gate 	char signature[5];
2117c478bd9Sstevel@tonic-gate 	char oemid[7];
2127c478bd9Sstevel@tonic-gate 	char oemtableid[9];
2137c478bd9Sstevel@tonic-gate 	struct _buf *file;
2147c478bd9Sstevel@tonic-gate 	char *buf1, *buf2;
2157c478bd9Sstevel@tonic-gate 	int count;
2167c478bd9Sstevel@tonic-gate 	char acpi_table_loc[128];
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	acpica_strncpy(signature, ExistingTable->Signature, 4);
2197c478bd9Sstevel@tonic-gate 	acpica_strncpy(oemid, ExistingTable->OemId, 6);
2207c478bd9Sstevel@tonic-gate 	acpica_strncpy(oemtableid, ExistingTable->OemTableId, 8);
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2237c478bd9Sstevel@tonic-gate 	cmn_err(CE_NOTE, "!acpica: table [%s] v%d OEM ID [%s]"
224*5dff2f34Smyers 	    " OEM TABLE ID [%s] OEM rev %x",
225*5dff2f34Smyers 	    signature, ExistingTable->Revision, oemid, oemtableid,
226*5dff2f34Smyers 	    ExistingTable->OemRevision);
2277c478bd9Sstevel@tonic-gate #endif
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	/* File name format is "signature_oemid_oemtableid.dat" */
2307c478bd9Sstevel@tonic-gate 	(void) strcpy(acpi_table_loc, acpi_table_path);
2317c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, signature); /* for example, DSDT */
2327c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, "_");
2337c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, oemid); /* for example, IntelR */
2347c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, "_");
2357c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, oemtableid); /* for example, AWRDACPI */
2367c478bd9Sstevel@tonic-gate 	(void) strcat(acpi_table_loc, ".dat");
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	file = kobj_open_file(acpi_table_loc);
2397c478bd9Sstevel@tonic-gate 	if (file == (struct _buf *)-1) {
2407c478bd9Sstevel@tonic-gate 		*NewTable = 0;
2417c478bd9Sstevel@tonic-gate 		return (AE_OK);
2427c478bd9Sstevel@tonic-gate 	} else {
2437c478bd9Sstevel@tonic-gate 		buf1 = (char *)kmem_alloc(MAX_DAT_FILE_SIZE, KM_SLEEP);
2447c478bd9Sstevel@tonic-gate 		count = kobj_read_file(file, buf1, MAX_DAT_FILE_SIZE-1, 0);
2457c478bd9Sstevel@tonic-gate 		if (count >= MAX_DAT_FILE_SIZE) {
2467c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "!acpica: table %s file size too big",
2477c478bd9Sstevel@tonic-gate 			    acpi_table_loc);
2487c478bd9Sstevel@tonic-gate 			*NewTable = 0;
2497c478bd9Sstevel@tonic-gate 		} else {
2507c478bd9Sstevel@tonic-gate 			buf2 = (char *)kmem_alloc(count, KM_SLEEP);
2517c478bd9Sstevel@tonic-gate 			(void) memcpy(buf2, buf1, count);
2527c478bd9Sstevel@tonic-gate 			*NewTable = (ACPI_TABLE_HEADER *)buf2;
2537c478bd9Sstevel@tonic-gate 			cmn_err(CE_NOTE, "!acpica: replacing table: %s",
2547c478bd9Sstevel@tonic-gate 			    acpi_table_loc);
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 	kobj_close_file(file);
2587c478bd9Sstevel@tonic-gate 	kmem_free(buf1, MAX_DAT_FILE_SIZE);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	return (AE_OK);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 
26430082d0cSmyers /*
26530082d0cSmyers  * ACPI semaphore implementation
26630082d0cSmyers  */
26730082d0cSmyers typedef struct {
26830082d0cSmyers 	kmutex_t	mutex;
26930082d0cSmyers 	kcondvar_t	cv;
27030082d0cSmyers 	uint32_t	available;
27130082d0cSmyers 	uint32_t	initial;
27230082d0cSmyers 	uint32_t	maximum;
27330082d0cSmyers } acpi_sema_t;
27430082d0cSmyers 
27530082d0cSmyers /*
27630082d0cSmyers  *
27730082d0cSmyers  */
27830082d0cSmyers void
27927f7c583Smyers acpi_sema_init(acpi_sema_t *sp, unsigned max, unsigned count)
28030082d0cSmyers {
28130082d0cSmyers 	mutex_init(&sp->mutex, NULL, MUTEX_DRIVER, NULL);
28230082d0cSmyers 	cv_init(&sp->cv, NULL, CV_DRIVER, NULL);
28330082d0cSmyers 	/* no need to enter mutex here at creation */
28430082d0cSmyers 	sp->available = count;
28530082d0cSmyers 	sp->initial = count;
28630082d0cSmyers 	sp->maximum = max;
28730082d0cSmyers }
28830082d0cSmyers 
28930082d0cSmyers /*
29030082d0cSmyers  *
29130082d0cSmyers  */
29230082d0cSmyers void
29330082d0cSmyers acpi_sema_destroy(acpi_sema_t *sp)
29430082d0cSmyers {
29530082d0cSmyers 
29630082d0cSmyers 	cv_destroy(&sp->cv);
29730082d0cSmyers 	mutex_destroy(&sp->mutex);
29830082d0cSmyers }
29930082d0cSmyers 
30030082d0cSmyers /*
30130082d0cSmyers  *
30230082d0cSmyers  */
30330082d0cSmyers ACPI_STATUS
30430082d0cSmyers acpi_sema_p(acpi_sema_t *sp, unsigned count, uint16_t wait_time)
30530082d0cSmyers {
30630082d0cSmyers 	ACPI_STATUS rv = AE_OK;
30730082d0cSmyers 	clock_t deadline;
30830082d0cSmyers 
30930082d0cSmyers 	mutex_enter(&sp->mutex);
31030082d0cSmyers 
31130082d0cSmyers 	if (sp->available >= count) {
31230082d0cSmyers 		/*
31330082d0cSmyers 		 * Enough units available, no blocking
31430082d0cSmyers 		 */
31530082d0cSmyers 		sp->available -= count;
31630082d0cSmyers 		mutex_exit(&sp->mutex);
31730082d0cSmyers 		return (rv);
31830082d0cSmyers 	} else if (wait_time == 0) {
31930082d0cSmyers 		/*
32030082d0cSmyers 		 * Not enough units available and timeout
32130082d0cSmyers 		 * specifies no blocking
32230082d0cSmyers 		 */
32330082d0cSmyers 		rv = AE_TIME;
32430082d0cSmyers 		mutex_exit(&sp->mutex);
32530082d0cSmyers 		return (rv);
32630082d0cSmyers 	}
32730082d0cSmyers 
32830082d0cSmyers 	/*
32930082d0cSmyers 	 * Not enough units available and timeout specifies waiting
33030082d0cSmyers 	 */
33130082d0cSmyers 	if (wait_time != ACPI_WAIT_FOREVER)
33230082d0cSmyers 		deadline = ddi_get_lbolt() +
33330082d0cSmyers 		    (clock_t)drv_usectohz(wait_time * 1000);
33430082d0cSmyers 
33530082d0cSmyers 	do {
33630082d0cSmyers 		if (wait_time == ACPI_WAIT_FOREVER)
33730082d0cSmyers 			cv_wait(&sp->cv, &sp->mutex);
33830082d0cSmyers 		else if (cv_timedwait(&sp->cv, &sp->mutex, deadline) < 0) {
33930082d0cSmyers 			rv = AE_TIME;
34030082d0cSmyers 			break;
34130082d0cSmyers 		}
34230082d0cSmyers 	} while (sp->available < count);
34330082d0cSmyers 
34430082d0cSmyers 	/* if we dropped out of the wait with AE_OK, we got the units */
34530082d0cSmyers 	if (rv == AE_OK)
34630082d0cSmyers 		sp->available -= count;
34730082d0cSmyers 
34830082d0cSmyers 	mutex_exit(&sp->mutex);
34930082d0cSmyers 	return (rv);
35030082d0cSmyers }
35130082d0cSmyers 
35230082d0cSmyers /*
35330082d0cSmyers  *
35430082d0cSmyers  */
35530082d0cSmyers void
35630082d0cSmyers acpi_sema_v(acpi_sema_t *sp, unsigned count)
35730082d0cSmyers {
35830082d0cSmyers 	mutex_enter(&sp->mutex);
35930082d0cSmyers 	sp->available += count;
36030082d0cSmyers 	cv_broadcast(&sp->cv);
36130082d0cSmyers 	mutex_exit(&sp->mutex);
36230082d0cSmyers }
36330082d0cSmyers 
36430082d0cSmyers 
3657c478bd9Sstevel@tonic-gate ACPI_STATUS
3667c478bd9Sstevel@tonic-gate AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
3677c478bd9Sstevel@tonic-gate ACPI_HANDLE *OutHandle)
3687c478bd9Sstevel@tonic-gate {
36930082d0cSmyers 	acpi_sema_t *sp;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if ((OutHandle == NULL) || (InitialUnits > MaxUnits))
3727c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
3737c478bd9Sstevel@tonic-gate 
37430082d0cSmyers 	sp = (acpi_sema_t *)kmem_alloc(sizeof (acpi_sema_t), KM_SLEEP);
37527f7c583Smyers 	acpi_sema_init(sp, MaxUnits, InitialUnits);
37630082d0cSmyers 	*OutHandle = (ACPI_HANDLE)sp;
3777c478bd9Sstevel@tonic-gate 	return (AE_OK);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate ACPI_STATUS
3827c478bd9Sstevel@tonic-gate AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate 
38530082d0cSmyers 	if (Handle == NULL)
38630082d0cSmyers 		return (AE_BAD_PARAMETER);
38730082d0cSmyers 
38830082d0cSmyers 	acpi_sema_destroy((acpi_sema_t *)Handle);
38930082d0cSmyers 	kmem_free((void *)Handle, sizeof (acpi_sema_t));
3907c478bd9Sstevel@tonic-gate 	return (AE_OK);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate ACPI_STATUS
3947c478bd9Sstevel@tonic-gate AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate 
39730082d0cSmyers 	if ((Handle == NULL) || (Units < 1))
39830082d0cSmyers 		return (AE_BAD_PARAMETER);
3997c478bd9Sstevel@tonic-gate 
40030082d0cSmyers 	return (acpi_sema_p((acpi_sema_t *)Handle, Units, Timeout));
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate ACPI_STATUS
4047c478bd9Sstevel@tonic-gate AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate 
40730082d0cSmyers 	if ((Handle == NULL) || (Units < 1))
40830082d0cSmyers 		return (AE_BAD_PARAMETER);
40930082d0cSmyers 
41030082d0cSmyers 	acpi_sema_v((acpi_sema_t *)Handle, Units);
4117c478bd9Sstevel@tonic-gate 	return (AE_OK);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate ACPI_STATUS
4157c478bd9Sstevel@tonic-gate AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
4167c478bd9Sstevel@tonic-gate {
41730082d0cSmyers 	kmutex_t *mp;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	if (OutHandle == NULL)
4207c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
4217c478bd9Sstevel@tonic-gate 
42230082d0cSmyers 	mp = (kmutex_t *)kmem_alloc(sizeof (kmutex_t), KM_SLEEP);
42330082d0cSmyers 	mutex_init(mp, NULL, MUTEX_DRIVER, NULL);
42430082d0cSmyers 	*OutHandle = (ACPI_HANDLE)mp;
4257c478bd9Sstevel@tonic-gate 	return (AE_OK);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate void
4297c478bd9Sstevel@tonic-gate AcpiOsDeleteLock(ACPI_HANDLE Handle)
4307c478bd9Sstevel@tonic-gate {
43130082d0cSmyers 
43230082d0cSmyers 	if (Handle == NULL)
43330082d0cSmyers 		return;
43430082d0cSmyers 
43530082d0cSmyers 	mutex_destroy((kmutex_t *)Handle);
43630082d0cSmyers 	kmem_free((void *)Handle, sizeof (kmutex_t));
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
43930082d0cSmyers ACPI_NATIVE_UINT
440450d6964Smyers AcpiOsAcquireLock(ACPI_HANDLE Handle)
4417c478bd9Sstevel@tonic-gate {
44230082d0cSmyers 
44330082d0cSmyers 	if (Handle == NULL)
44430082d0cSmyers 		return (AE_BAD_PARAMETER);
44530082d0cSmyers 
44630082d0cSmyers 	mutex_enter((kmutex_t *)Handle);
44730082d0cSmyers 	return (AE_OK);
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate void
45130082d0cSmyers AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_NATIVE_UINT Flags)
4527c478bd9Sstevel@tonic-gate {
453450d6964Smyers 	_NOTE(ARGUNUSED(Flags))
4547c478bd9Sstevel@tonic-gate 
45530082d0cSmyers 	if (Handle == NULL)
45630082d0cSmyers 		return;
45730082d0cSmyers 
45830082d0cSmyers 	mutex_exit((kmutex_t *)Handle);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate void *
4637c478bd9Sstevel@tonic-gate AcpiOsAllocate(ACPI_SIZE Size)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate 	ACPI_SIZE *tmp_ptr;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	Size += sizeof (Size);
4687c478bd9Sstevel@tonic-gate 	tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP);
4697c478bd9Sstevel@tonic-gate 	*tmp_ptr++ = Size;
47030082d0cSmyers 	return (tmp_ptr);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate void
4747c478bd9Sstevel@tonic-gate AcpiOsFree(void *Memory)
4757c478bd9Sstevel@tonic-gate {
4767c478bd9Sstevel@tonic-gate 	ACPI_SIZE	size, *tmp_ptr;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	tmp_ptr = (ACPI_SIZE *)Memory;
4797c478bd9Sstevel@tonic-gate 	tmp_ptr -= 1;
4807c478bd9Sstevel@tonic-gate 	size = *tmp_ptr;
48130082d0cSmyers 	kmem_free(tmp_ptr, size);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate ACPI_STATUS
4857c478bd9Sstevel@tonic-gate AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress,
4867c478bd9Sstevel@tonic-gate 		    ACPI_SIZE Size, void **LogicalAddress)
4877c478bd9Sstevel@tonic-gate {
4887c478bd9Sstevel@tonic-gate 	/* FUTUREWORK: test PhysicalAddress for > 32 bits */
4897c478bd9Sstevel@tonic-gate 	*LogicalAddress = psm_map_new((paddr_t)PhysicalAddress,
490*5dff2f34Smyers 	    (size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ);
49103335b7aSmyers 
49203335b7aSmyers 	return (*LogicalAddress == NULL ? AE_NO_MEMORY : AE_OK);
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate void
4967c478bd9Sstevel@tonic-gate AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
4977c478bd9Sstevel@tonic-gate {
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5037c478bd9Sstevel@tonic-gate ACPI_STATUS
5047c478bd9Sstevel@tonic-gate AcpiOsGetPhysicalAddress(void *LogicalAddress,
5057c478bd9Sstevel@tonic-gate 			ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
5067c478bd9Sstevel@tonic-gate {
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	/* UNIMPLEMENTED: not invoked by ACPI CA code */
50903335b7aSmyers 	return (AE_NOT_IMPLEMENTED);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate ACPI_OSD_HANDLER acpi_isr;
5147c478bd9Sstevel@tonic-gate void *acpi_isr_context;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate uint_t
5177c478bd9Sstevel@tonic-gate acpi_wrapper_isr(char *arg)
5187c478bd9Sstevel@tonic-gate {
5197c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(arg))
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	int	status;
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	status = (*acpi_isr)(acpi_isr_context);
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	if (status == ACPI_INTERRUPT_HANDLED) {
5267c478bd9Sstevel@tonic-gate 		return (DDI_INTR_CLAIMED);
5277c478bd9Sstevel@tonic-gate 	} else {
5287c478bd9Sstevel@tonic-gate 		return (DDI_INTR_UNCLAIMED);
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate 
532186507a7Smyers static int acpi_intr_hooked = 0;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate ACPI_STATUS
5357c478bd9Sstevel@tonic-gate AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
5367c478bd9Sstevel@tonic-gate 		ACPI_OSD_HANDLER ServiceRoutine,
5377c478bd9Sstevel@tonic-gate 		void *Context)
5387c478bd9Sstevel@tonic-gate {
53927f7c583Smyers 	_NOTE(ARGUNUSED(InterruptNumber))
54027f7c583Smyers 
5417c478bd9Sstevel@tonic-gate 	int retval;
542450d6964Smyers 	int sci_vect;
543450d6964Smyers 	iflag_t sci_flags;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	acpi_isr = ServiceRoutine;
5467c478bd9Sstevel@tonic-gate 	acpi_isr_context = Context;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	/*
549450d6964Smyers 	 * Get SCI (adjusted for PIC/APIC mode if necessary)
5507c478bd9Sstevel@tonic-gate 	 */
551450d6964Smyers 	if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) {
552450d6964Smyers 		return (AE_ERROR);
553450d6964Smyers 	}
554450d6964Smyers 
555450d6964Smyers #ifdef	DEBUG
556450d6964Smyers 	cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect);
557450d6964Smyers #endif
558450d6964Smyers 
5597c478bd9Sstevel@tonic-gate 	retval = add_avintr(NULL, SCI_IPL, (avfunc)acpi_wrapper_isr,
560*5dff2f34Smyers 	    "ACPI SCI", sci_vect, NULL, NULL, NULL, NULL);
5617c478bd9Sstevel@tonic-gate 	if (retval) {
562186507a7Smyers 		acpi_intr_hooked = 1;
5637c478bd9Sstevel@tonic-gate 		return (AE_OK);
564186507a7Smyers 	} else
5657c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate ACPI_STATUS
5697c478bd9Sstevel@tonic-gate AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
5707c478bd9Sstevel@tonic-gate 			ACPI_OSD_HANDLER ServiceRoutine)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(ServiceRoutine))
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5757c478bd9Sstevel@tonic-gate 	cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber);
5767c478bd9Sstevel@tonic-gate #endif
577186507a7Smyers 	if (acpi_intr_hooked) {
5787c478bd9Sstevel@tonic-gate 		rem_avintr(NULL, LOCK_LEVEL - 1, (avfunc)acpi_wrapper_isr,
579*5dff2f34Smyers 		    InterruptNumber);
580186507a7Smyers 		acpi_intr_hooked = 0;
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 	return (AE_OK);
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 
58627f7c583Smyers ACPI_THREAD_ID
5877c478bd9Sstevel@tonic-gate AcpiOsGetThreadId(void)
5887c478bd9Sstevel@tonic-gate {
58927f7c583Smyers 	/*
59027f7c583Smyers 	 * ACPI CA regards thread ID as an error, but it's valid
59127f7c583Smyers 	 * on Solaris during kernel initialization.  Thus, 1 is added
59227f7c583Smyers 	 * to the kernel thread ID to avoid returning 0
59327f7c583Smyers 	 */
59427f7c583Smyers 	return (ddi_get_kt_did() + 1);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate /*
5987c478bd9Sstevel@tonic-gate  *
5997c478bd9Sstevel@tonic-gate  */
6007c478bd9Sstevel@tonic-gate ACPI_STATUS
60127f7c583Smyers AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK  Function,
60227f7c583Smyers     void *Context)
6037c478bd9Sstevel@tonic-gate {
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	if (!acpica_eventq_init) {
6067c478bd9Sstevel@tonic-gate 		/*
6077c478bd9Sstevel@tonic-gate 		 * Create taskqs for event handling
6087c478bd9Sstevel@tonic-gate 		 */
6097c478bd9Sstevel@tonic-gate 		if (init_event_queues() != AE_OK)
610*5dff2f34Smyers 			return (AE_ERROR);
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 
61327f7c583Smyers 	if (ddi_taskq_dispatch(osl_eventq[Type], Function, Context,
61427f7c583Smyers 	    DDI_NOSLEEP) == DDI_FAILURE) {
6157c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6167c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!acpica: unable to dispatch event");
6177c478bd9Sstevel@tonic-gate #endif
6187c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 	return (AE_OK);
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate void
6257c478bd9Sstevel@tonic-gate AcpiOsSleep(ACPI_INTEGER Milliseconds)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate 	/*
6287c478bd9Sstevel@tonic-gate 	 * During kernel startup, before the first
6297c478bd9Sstevel@tonic-gate 	 * tick interrupt has taken place, we can't call
630859dcd3dSmyers 	 * delay; very late in kernel shutdown, clock interrupts
631859dcd3dSmyers 	 * are blocked, so delay doesn't work then either.
632859dcd3dSmyers 	 * So we busy wait if lbolt == 0 (kernel startup)
633859dcd3dSmyers 	 * or if psm_shutdown() has set acpi_powering_off to
634859dcd3dSmyers 	 * a non-zero value.
6357c478bd9Sstevel@tonic-gate 	 */
636859dcd3dSmyers 	if ((ddi_get_lbolt() == 0) || acpica_powering_off)
6377c478bd9Sstevel@tonic-gate 		drv_usecwait(Milliseconds * 1000);
6387c478bd9Sstevel@tonic-gate 	else
6397c478bd9Sstevel@tonic-gate 		delay(drv_usectohz(Milliseconds * 1000));
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate void
6437c478bd9Sstevel@tonic-gate AcpiOsStall(UINT32 Microseconds)
6447c478bd9Sstevel@tonic-gate {
6457c478bd9Sstevel@tonic-gate 	drv_usecwait(Microseconds);
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate  * Implementation of "Windows 2001" compatible I/O permission map
6517c478bd9Sstevel@tonic-gate  *
6527c478bd9Sstevel@tonic-gate  */
6537c478bd9Sstevel@tonic-gate #define	OSL_IO_NONE	(0)
6547c478bd9Sstevel@tonic-gate #define	OSL_IO_READ	(1<<0)
6557c478bd9Sstevel@tonic-gate #define	OSL_IO_WRITE	(1<<1)
6567c478bd9Sstevel@tonic-gate #define	OSL_IO_RW	(OSL_IO_READ | OSL_IO_WRITE)
6577c478bd9Sstevel@tonic-gate #define	OSL_IO_TERM	(1<<2)
6587c478bd9Sstevel@tonic-gate #define	OSL_IO_DEFAULT	OSL_IO_RW
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate static struct io_perm  {
6617c478bd9Sstevel@tonic-gate 	ACPI_IO_ADDRESS	low;
6627c478bd9Sstevel@tonic-gate 	ACPI_IO_ADDRESS	high;
6637c478bd9Sstevel@tonic-gate 	uint8_t		perm;
6647c478bd9Sstevel@tonic-gate } osl_io_perm[] = {
6657c478bd9Sstevel@tonic-gate 	{ 0xcf8, 0xd00, OSL_IO_NONE | OSL_IO_TERM }
6667c478bd9Sstevel@tonic-gate };
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate  *
6717c478bd9Sstevel@tonic-gate  */
6727c478bd9Sstevel@tonic-gate static struct io_perm *
6737c478bd9Sstevel@tonic-gate osl_io_find_perm(ACPI_IO_ADDRESS addr)
6747c478bd9Sstevel@tonic-gate {
6757c478bd9Sstevel@tonic-gate 	struct io_perm *p;
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	p = osl_io_perm;
6787c478bd9Sstevel@tonic-gate 	while (p != NULL) {
6797c478bd9Sstevel@tonic-gate 		if ((p->low <= addr) && (addr <= p->high))
6807c478bd9Sstevel@tonic-gate 			break;
6817c478bd9Sstevel@tonic-gate 		p = (p->perm & OSL_IO_TERM) ? NULL : p+1;
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	return (p);
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate  *
6897c478bd9Sstevel@tonic-gate  */
6907c478bd9Sstevel@tonic-gate ACPI_STATUS
6917c478bd9Sstevel@tonic-gate AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate 	struct io_perm *p;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/* verify permission */
6967c478bd9Sstevel@tonic-gate 	p = osl_io_find_perm(Address);
6977c478bd9Sstevel@tonic-gate 	if (p && (p->perm & OSL_IO_READ) == 0) {
6987c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted",
699*5dff2f34Smyers 		    (long)Address, Width);
7007c478bd9Sstevel@tonic-gate 		*Value = 0xffffffff;
7017c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	switch (Width) {
7057c478bd9Sstevel@tonic-gate 	case 8:
7067c478bd9Sstevel@tonic-gate 		*Value = inb(Address);
7077c478bd9Sstevel@tonic-gate 		break;
7087c478bd9Sstevel@tonic-gate 	case 16:
7097c478bd9Sstevel@tonic-gate 		*Value = inw(Address);
7107c478bd9Sstevel@tonic-gate 		break;
7117c478bd9Sstevel@tonic-gate 	case 32:
7127c478bd9Sstevel@tonic-gate 		*Value = inl(Address);
7137c478bd9Sstevel@tonic-gate 		break;
7147c478bd9Sstevel@tonic-gate 	default:
7157c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed",
716*5dff2f34Smyers 		    (long)Address, Width);
7177c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 	return (AE_OK);
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate ACPI_STATUS
7237c478bd9Sstevel@tonic-gate AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
7247c478bd9Sstevel@tonic-gate {
7257c478bd9Sstevel@tonic-gate 	struct io_perm *p;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	/* verify permission */
7287c478bd9Sstevel@tonic-gate 	p = osl_io_find_perm(Address);
7297c478bd9Sstevel@tonic-gate 	if (p && (p->perm & OSL_IO_WRITE) == 0) {
7307c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted",
7317c478bd9Sstevel@tonic-gate 		    (long)Address, Width);
7327c478bd9Sstevel@tonic-gate 		return (AE_ERROR);
7337c478bd9Sstevel@tonic-gate 	}
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	switch (Width) {
7367c478bd9Sstevel@tonic-gate 	case 8:
7377c478bd9Sstevel@tonic-gate 		outb(Address, Value);
7387c478bd9Sstevel@tonic-gate 		break;
7397c478bd9Sstevel@tonic-gate 	case 16:
7407c478bd9Sstevel@tonic-gate 		outw(Address, Value);
7417c478bd9Sstevel@tonic-gate 		break;
7427c478bd9Sstevel@tonic-gate 	case 32:
7437c478bd9Sstevel@tonic-gate 		outl(Address, Value);
7447c478bd9Sstevel@tonic-gate 		break;
7457c478bd9Sstevel@tonic-gate 	default:
7467c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed",
7477c478bd9Sstevel@tonic-gate 		    (long)Address, Width);
7487c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 	return (AE_OK);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate  *
7567c478bd9Sstevel@tonic-gate  */
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate #define	OSL_RW(ptr, val, type, rw) \
7597c478bd9Sstevel@tonic-gate 	{ if (rw) *((type *)(ptr)) = *((type *) val); \
7607c478bd9Sstevel@tonic-gate 	    else *((type *) val) = *((type *)(ptr)); }
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate static void
7647c478bd9Sstevel@tonic-gate osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value,
7657c478bd9Sstevel@tonic-gate     UINT32 Width, int write)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate 	size_t	maplen = Width / 8;
7687c478bd9Sstevel@tonic-gate 	caddr_t	ptr;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 	ptr = psm_map_new((paddr_t)Address, maplen,
7717c478bd9Sstevel@tonic-gate 	    PSM_PROT_WRITE | PSM_PROT_READ);
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 	switch (maplen) {
7747c478bd9Sstevel@tonic-gate 	case 1:
7757c478bd9Sstevel@tonic-gate 		OSL_RW(ptr, Value, uint8_t, write);
7767c478bd9Sstevel@tonic-gate 		break;
7777c478bd9Sstevel@tonic-gate 	case 2:
7787c478bd9Sstevel@tonic-gate 		OSL_RW(ptr, Value, uint16_t, write);
7797c478bd9Sstevel@tonic-gate 		break;
7807c478bd9Sstevel@tonic-gate 	case 4:
7817c478bd9Sstevel@tonic-gate 		OSL_RW(ptr, Value, uint32_t, write);
7827c478bd9Sstevel@tonic-gate 		break;
7837c478bd9Sstevel@tonic-gate 	default:
7847c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d",
7857c478bd9Sstevel@tonic-gate 		    Width);
7867c478bd9Sstevel@tonic-gate 		break;
7877c478bd9Sstevel@tonic-gate 	}
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	psm_unmap(ptr, maplen);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate ACPI_STATUS
7937c478bd9Sstevel@tonic-gate AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,
7947c478bd9Sstevel@tonic-gate 		UINT32 *Value, UINT32 Width)
7957c478bd9Sstevel@tonic-gate {
7967c478bd9Sstevel@tonic-gate 	osl_rw_memory(Address, Value, Width, 0);
7977c478bd9Sstevel@tonic-gate 	return (AE_OK);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate ACPI_STATUS
8017c478bd9Sstevel@tonic-gate AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,
8027c478bd9Sstevel@tonic-gate 		UINT32 Value, UINT32 Width)
8037c478bd9Sstevel@tonic-gate {
8047c478bd9Sstevel@tonic-gate 	osl_rw_memory(Address, &Value, Width, 1);
8057c478bd9Sstevel@tonic-gate 	return (AE_OK);
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate ACPI_STATUS
8107c478bd9Sstevel@tonic-gate AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
8117c478bd9Sstevel@tonic-gate 			void *Value, UINT32 Width)
8127c478bd9Sstevel@tonic-gate {
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	switch (Width) {
8157c478bd9Sstevel@tonic-gate 	case 8:
8167c478bd9Sstevel@tonic-gate 		*((UINT64 *)Value) = (UINT64)(*pci_getb_func)
817*5dff2f34Smyers 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
8187c478bd9Sstevel@tonic-gate 		break;
8197c478bd9Sstevel@tonic-gate 	case 16:
8207c478bd9Sstevel@tonic-gate 		*((UINT64 *)Value) = (UINT64)(*pci_getw_func)
821*5dff2f34Smyers 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
8227c478bd9Sstevel@tonic-gate 		break;
8237c478bd9Sstevel@tonic-gate 	case 32:
8247c478bd9Sstevel@tonic-gate 		*((UINT64 *)Value) = (UINT64)(*pci_getl_func)
825*5dff2f34Smyers 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
8267c478bd9Sstevel@tonic-gate 		break;
8277c478bd9Sstevel@tonic-gate 	case 64:
8287c478bd9Sstevel@tonic-gate 	default:
8297c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed",
8307c478bd9Sstevel@tonic-gate 		    Register, Width);
8317c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
8327c478bd9Sstevel@tonic-gate 	}
8337c478bd9Sstevel@tonic-gate 	return (AE_OK);
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate /*
8377c478bd9Sstevel@tonic-gate  *
8387c478bd9Sstevel@tonic-gate  */
8397c478bd9Sstevel@tonic-gate int acpica_write_pci_config_ok = 1;
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate ACPI_STATUS
8427c478bd9Sstevel@tonic-gate AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
8437c478bd9Sstevel@tonic-gate 		ACPI_INTEGER Value, UINT32 Width)
8447c478bd9Sstevel@tonic-gate {
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	if (!acpica_write_pci_config_ok) {
8477c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!write to PCI cfg %x/%x/%x %x"
8487c478bd9Sstevel@tonic-gate 		    " %lx %d not permitted", PciId->Bus, PciId->Device,
8497c478bd9Sstevel@tonic-gate 		    PciId->Function, Register, (long)Value, Width);
8507c478bd9Sstevel@tonic-gate 		return (AE_OK);
8517c478bd9Sstevel@tonic-gate 	}
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	switch (Width) {
8547c478bd9Sstevel@tonic-gate 	case 8:
8557c478bd9Sstevel@tonic-gate 		(*pci_putb_func)(PciId->Bus, PciId->Device, PciId->Function,
856*5dff2f34Smyers 		    Register, (uint8_t)Value);
8577c478bd9Sstevel@tonic-gate 		break;
8587c478bd9Sstevel@tonic-gate 	case 16:
8597c478bd9Sstevel@tonic-gate 		(*pci_putw_func)(PciId->Bus, PciId->Device, PciId->Function,
860*5dff2f34Smyers 		    Register, (uint16_t)Value);
8617c478bd9Sstevel@tonic-gate 		break;
8627c478bd9Sstevel@tonic-gate 	case 32:
8637c478bd9Sstevel@tonic-gate 		(*pci_putl_func)(PciId->Bus, PciId->Device, PciId->Function,
864*5dff2f34Smyers 		    Register, (uint32_t)Value);
8657c478bd9Sstevel@tonic-gate 		break;
8667c478bd9Sstevel@tonic-gate 	case 64:
8677c478bd9Sstevel@tonic-gate 	default:
8687c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "!AcpiOsWritePciConfiguration: %x %u failed",
8697c478bd9Sstevel@tonic-gate 		    Register, Width);
8707c478bd9Sstevel@tonic-gate 		return (AE_BAD_PARAMETER);
8717c478bd9Sstevel@tonic-gate 	}
8727c478bd9Sstevel@tonic-gate 	return (AE_OK);
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate  * Called with ACPI_HANDLEs for both a PCI Config Space
8777c478bd9Sstevel@tonic-gate  * OpRegion and (what ACPI CA thinks is) the PCI device
87827f7c583Smyers  * to which this ConfigSpace OpRegion belongs.  Since
87927f7c583Smyers  * ACPI CA depends on a valid _BBN object being present
88027f7c583Smyers  * and this is not always true (one old x86 had broken _BBN),
88127f7c583Smyers  * we go ahead and get the correct PCI bus number using the
88227f7c583Smyers  * devinfo mapping (which compensates for broken _BBN).
8837c478bd9Sstevel@tonic-gate  *
8847c478bd9Sstevel@tonic-gate  * Default values for bus, segment, device and function are
8857c478bd9Sstevel@tonic-gate  * all 0 when ACPI CA can't figure them out.
8867c478bd9Sstevel@tonic-gate  *
88727f7c583Smyers  * Some BIOSes implement _BBN() by reading PCI config space
888*5dff2f34Smyers  * on bus #0 - which means that we'll recurse when we attempt
88927f7c583Smyers  * to create the devinfo-to-ACPI map.  If Derive is called during
890*5dff2f34Smyers  * create_d2a_map, we don't translate the bus # and return.
8917c478bd9Sstevel@tonic-gate  */
8927c478bd9Sstevel@tonic-gate void
8937c478bd9Sstevel@tonic-gate AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle,
8947c478bd9Sstevel@tonic-gate 		ACPI_PCI_ID **PciId)
8957c478bd9Sstevel@tonic-gate {
8967c478bd9Sstevel@tonic-gate 	ACPI_HANDLE handle;
8977c478bd9Sstevel@tonic-gate 	d2a *d2ap;
8987c478bd9Sstevel@tonic-gate 	int devfn;
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 
90127f7c583Smyers 	/*
902*5dff2f34Smyers 	 * See above - avoid recursing during create_d2a_map.
90327f7c583Smyers 	 */
904*5dff2f34Smyers 	if (creating_d2a_map)
9057c478bd9Sstevel@tonic-gate 		return;
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	/*
9087c478bd9Sstevel@tonic-gate 	 * We start with the parent node of the OpRegion
9097c478bd9Sstevel@tonic-gate 	 * and ascend, looking for a matching dip2acpi
9107c478bd9Sstevel@tonic-gate 	 * node; once located, we use the bus from the d2a
9117c478bd9Sstevel@tonic-gate 	 * node and the device/function return from the _ADR
9127c478bd9Sstevel@tonic-gate 	 * method on the ACPI node.
9137c478bd9Sstevel@tonic-gate 	 * If we encounter any kind of failure, we just
9147c478bd9Sstevel@tonic-gate 	 * return, possibly after updating the bus value
9157c478bd9Sstevel@tonic-gate 	 * This is probably always better than nothing.
9167c478bd9Sstevel@tonic-gate 	 */
9177c478bd9Sstevel@tonic-gate 	if (AcpiGetParent(chandle, &handle) != AE_OK)
9187c478bd9Sstevel@tonic-gate 		return;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	while (handle != rhandle) {
9217c478bd9Sstevel@tonic-gate 		if (acpica_find_pcid2a(handle, &d2ap) == AE_OK) {
9227c478bd9Sstevel@tonic-gate 			(*PciId)->Bus = d2ap->bus;
9237c478bd9Sstevel@tonic-gate 			if (acpica_eval_int(handle, "_ADR", &devfn) == AE_OK) {
9247c478bd9Sstevel@tonic-gate 				(*PciId)->Device = (devfn >> 16) & 0xFFFF;
9257c478bd9Sstevel@tonic-gate 				(*PciId)->Function = devfn & 0xFFFF;
9267c478bd9Sstevel@tonic-gate 			}
9277c478bd9Sstevel@tonic-gate 			break;
9287c478bd9Sstevel@tonic-gate 		}
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 		if (AcpiGetParent(handle, &handle) != AE_OK)
9317c478bd9Sstevel@tonic-gate 			break;
9327c478bd9Sstevel@tonic-gate 	}
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 
93627f7c583Smyers /*ARGSUSED*/
9377c478bd9Sstevel@tonic-gate BOOLEAN
9387c478bd9Sstevel@tonic-gate AcpiOsReadable(void *Pointer, ACPI_SIZE Length)
9397c478bd9Sstevel@tonic-gate {
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	/* Always says yes; all mapped memory assumed readable */
9427c478bd9Sstevel@tonic-gate 	return (1);
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate 
94527f7c583Smyers /*ARGSUSED*/
9467c478bd9Sstevel@tonic-gate BOOLEAN
9477c478bd9Sstevel@tonic-gate AcpiOsWritable(void *Pointer, ACPI_SIZE Length)
9487c478bd9Sstevel@tonic-gate {
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	/* Always says yes; all mapped memory assumed writable */
9517c478bd9Sstevel@tonic-gate 	return (1);
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate UINT64
9557c478bd9Sstevel@tonic-gate AcpiOsGetTimer(void)
9567c478bd9Sstevel@tonic-gate {
95727f7c583Smyers 	/* gethrtime() returns 1nS resolution; convert to 100nS granules */
95827f7c583Smyers 	return ((gethrtime() + 50) / 100);
95927f7c583Smyers }
9607c478bd9Sstevel@tonic-gate 
96127f7c583Smyers /*ARGSUSED*/
96227f7c583Smyers ACPI_STATUS
96327f7c583Smyers AcpiOsValidateInterface(char *interface)
96427f7c583Smyers {
96527f7c583Smyers 	return (AE_SUPPORT);
96627f7c583Smyers }
9677c478bd9Sstevel@tonic-gate 
96827f7c583Smyers /*ARGSUSED*/
96927f7c583Smyers ACPI_STATUS
97027f7c583Smyers AcpiOsValidateAddress(UINT8 spaceid, ACPI_PHYSICAL_ADDRESS addr,
97127f7c583Smyers     ACPI_SIZE length)
97227f7c583Smyers {
97327f7c583Smyers 	return (AE_OK);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate ACPI_STATUS
9777c478bd9Sstevel@tonic-gate AcpiOsSignal(UINT32 Function, void *Info)
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(Function, Info))
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	/* FUTUREWORK: debugger support */
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 	cmn_err(CE_NOTE, "!OsSignal unimplemented");
9847c478bd9Sstevel@tonic-gate 	return (AE_OK);
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate void ACPI_INTERNAL_VAR_XFACE
9887c478bd9Sstevel@tonic-gate AcpiOsPrintf(const char *Format, ...)
9897c478bd9Sstevel@tonic-gate {
9907c478bd9Sstevel@tonic-gate 	va_list ap;
991186507a7Smyers 
992186507a7Smyers 	va_start(ap, Format);
993186507a7Smyers 	AcpiOsVprintf(Format, ap);
994186507a7Smyers 	va_end(ap);
995186507a7Smyers }
996186507a7Smyers 
997186507a7Smyers /*
998186507a7Smyers  * When != 0, sends output to console
999186507a7Smyers  * Patchable with kmdb or /etc/system.
1000186507a7Smyers  */
1001186507a7Smyers int acpica_console_out = 0;
1002186507a7Smyers 
1003186507a7Smyers #define	ACPICA_OUTBUF_LEN	160
1004186507a7Smyers char	acpica_outbuf[ACPICA_OUTBUF_LEN];
1005186507a7Smyers int	acpica_outbuf_offset;
1006186507a7Smyers 
1007186507a7Smyers /*
1008186507a7Smyers  *
1009186507a7Smyers  */
1010186507a7Smyers static void
1011186507a7Smyers acpica_pr_buf(char *buf, int buflen)
1012186507a7Smyers {
1013186507a7Smyers 	char c, *bufp, *outp;
1014186507a7Smyers 	int	out_remaining;
1015186507a7Smyers 
1016186507a7Smyers 	/*
1017186507a7Smyers 	 * copy the supplied buffer into the output buffer
1018186507a7Smyers 	 * when we hit a '\n' or overflow the output buffer,
1019186507a7Smyers 	 * output and reset the output buffer
1020186507a7Smyers 	 */
1021186507a7Smyers 	bufp = buf;
1022186507a7Smyers 	outp = acpica_outbuf + acpica_outbuf_offset;
1023186507a7Smyers 	out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1;
1024186507a7Smyers 	while (c = *bufp++) {
1025186507a7Smyers 		*outp++ = c;
1026186507a7Smyers 		if (c == '\n' || --out_remaining == 0) {
1027186507a7Smyers 			*outp = '\0';
1028186507a7Smyers 			if (acpica_console_out)
1029186507a7Smyers 				printf(acpica_outbuf);
1030186507a7Smyers 			else
1031186507a7Smyers 				(void) strlog(0, 0, 0,
1032186507a7Smyers 				    SL_CONSOLE | SL_NOTE | SL_LOGONLY,
1033186507a7Smyers 				    acpica_outbuf);
1034186507a7Smyers 			acpica_outbuf_offset = 0;
1035186507a7Smyers 			outp = acpica_outbuf;
1036186507a7Smyers 			out_remaining = ACPICA_OUTBUF_LEN - 1;
1037186507a7Smyers 		}
1038186507a7Smyers 	}
1039186507a7Smyers 
1040186507a7Smyers 	acpica_outbuf_offset = outp - acpica_outbuf;
1041186507a7Smyers 	kmem_free(buf, buflen);
1042186507a7Smyers }
1043186507a7Smyers 
1044186507a7Smyers void
1045186507a7Smyers AcpiOsVprintf(const char *Format, va_list Args)
1046186507a7Smyers {
1047186507a7Smyers 	va_list	save;
10487c478bd9Sstevel@tonic-gate 	int	buflen;
10497c478bd9Sstevel@tonic-gate 	char	*buf;
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	/*
10527c478bd9Sstevel@tonic-gate 	 * Try to be nice and emit the message via strlog().
10537c478bd9Sstevel@tonic-gate 	 * Unfortunately, vstrlog() doesn't define the format
10547c478bd9Sstevel@tonic-gate 	 * string as const char, so we allocate a local buffer
10557c478bd9Sstevel@tonic-gate 	 * use vsnprintf().
10567c478bd9Sstevel@tonic-gate 	 *
10577c478bd9Sstevel@tonic-gate 	 * If we fail to allocate a string buffer, we resort
10587c478bd9Sstevel@tonic-gate 	 * to printf().
10597c478bd9Sstevel@tonic-gate 	 */
1060186507a7Smyers 	va_copy(save, Args);
1061186507a7Smyers 	buflen = vsnprintf(NULL, 0, Format, save) + 1;
10627c478bd9Sstevel@tonic-gate 	buf = kmem_alloc(buflen, KM_NOSLEEP);
10637c478bd9Sstevel@tonic-gate 	if (buf == NULL) {
1064186507a7Smyers 		vprintf(Format, Args);
10657c478bd9Sstevel@tonic-gate 		return;
10667c478bd9Sstevel@tonic-gate 	}
1067186507a7Smyers 	(void) vsnprintf(buf, buflen, Format, Args);
1068186507a7Smyers 	acpica_pr_buf(buf, buflen);
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate void
10727c478bd9Sstevel@tonic-gate AcpiOsRedirectOutput(void *Destination)
10737c478bd9Sstevel@tonic-gate {
10747c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(Destination))
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	/* FUTUREWORK: debugger support */
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate #ifdef	DEBUG
10797c478bd9Sstevel@tonic-gate 	cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called");
10807c478bd9Sstevel@tonic-gate #endif
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate UINT32
10857c478bd9Sstevel@tonic-gate AcpiOsGetLine(char *Buffer)
10867c478bd9Sstevel@tonic-gate {
10877c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(Buffer))
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	/* FUTUREWORK: debugger support */
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	return (0);
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate /*
10987c478bd9Sstevel@tonic-gate  * Device tree binding
10997c478bd9Sstevel@tonic-gate  */
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate static int
11027c478bd9Sstevel@tonic-gate acpica_find_pcibus(int busno, ACPI_HANDLE *rh)
11037c478bd9Sstevel@tonic-gate {
11047c478bd9Sstevel@tonic-gate 	ACPI_HANDLE sbobj, busobj;
11057c478bd9Sstevel@tonic-gate 	int hid, bbn;
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	/* initialize static flag by querying ACPI namespace for bug */
11087c478bd9Sstevel@tonic-gate 	if (acpi_has_broken_bbn == -1)
11097c478bd9Sstevel@tonic-gate 		acpi_has_broken_bbn = acpica_query_bbn_problem();
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	busobj = NULL;
11127c478bd9Sstevel@tonic-gate 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
11137c478bd9Sstevel@tonic-gate 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
11147c478bd9Sstevel@tonic-gate 	    &busobj) == AE_OK) {
11157c478bd9Sstevel@tonic-gate 		if (acpica_eval_hid(busobj, "_HID", &hid) == AE_OK &&
11167c478bd9Sstevel@tonic-gate 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS)) {
11177c478bd9Sstevel@tonic-gate 			if (acpi_has_broken_bbn) {
11187c478bd9Sstevel@tonic-gate 				ACPI_BUFFER rb;
11197c478bd9Sstevel@tonic-gate 				rb.Pointer = NULL;
11207c478bd9Sstevel@tonic-gate 				rb.Length = ACPI_ALLOCATE_BUFFER;
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 				/* Decree _BBN == n from PCI<n> */
11237c478bd9Sstevel@tonic-gate 				if (AcpiGetName(busobj, ACPI_SINGLE_NAME, &rb)
1124*5dff2f34Smyers 				    != AE_OK) {
11257c478bd9Sstevel@tonic-gate 					return (AE_ERROR);
11267c478bd9Sstevel@tonic-gate 				}
11277c478bd9Sstevel@tonic-gate 				bbn = ((char *)rb.Pointer)[3] - '0';
11287c478bd9Sstevel@tonic-gate 				AcpiOsFree(rb.Pointer);
11297c478bd9Sstevel@tonic-gate 				if (bbn == busno || busno == 0) {
11307c478bd9Sstevel@tonic-gate 					*rh = busobj;
11317c478bd9Sstevel@tonic-gate 					return (AE_OK);
11327c478bd9Sstevel@tonic-gate 				}
11337c478bd9Sstevel@tonic-gate 			} else {
11347c478bd9Sstevel@tonic-gate 				if (acpica_eval_int(busobj, "_BBN", &bbn) ==
11357c478bd9Sstevel@tonic-gate 				    AE_OK) {
11367c478bd9Sstevel@tonic-gate 					if (bbn == busno) {
11377c478bd9Sstevel@tonic-gate 						*rh = busobj;
11387c478bd9Sstevel@tonic-gate 						return (AE_OK);
11397c478bd9Sstevel@tonic-gate 					}
11407c478bd9Sstevel@tonic-gate 				} else if (busno == 0) {
11417c478bd9Sstevel@tonic-gate 					*rh = busobj;
11427c478bd9Sstevel@tonic-gate 					return (AE_OK);
11437c478bd9Sstevel@tonic-gate 				}
11447c478bd9Sstevel@tonic-gate 			}
11457c478bd9Sstevel@tonic-gate 		}
11467c478bd9Sstevel@tonic-gate 	}
11477c478bd9Sstevel@tonic-gate 	return (AE_ERROR);
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate /*
11527c478bd9Sstevel@tonic-gate  * Look for ACPI problem where _BBN is zero for multiple PCI buses
11537c478bd9Sstevel@tonic-gate  * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus()
11547c478bd9Sstevel@tonic-gate  * below if it exists.
11557c478bd9Sstevel@tonic-gate  */
11567c478bd9Sstevel@tonic-gate static int
11577c478bd9Sstevel@tonic-gate acpica_query_bbn_problem(void)
11587c478bd9Sstevel@tonic-gate {
11597c478bd9Sstevel@tonic-gate 	ACPI_HANDLE sbobj, busobj;
11607c478bd9Sstevel@tonic-gate 	int hid, bbn;
11617c478bd9Sstevel@tonic-gate 	int zerobbncnt;
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	busobj = NULL;
11647c478bd9Sstevel@tonic-gate 	zerobbncnt = 0;
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
11697c478bd9Sstevel@tonic-gate 	    &busobj) == AE_OK) {
11707c478bd9Sstevel@tonic-gate 		if ((acpica_eval_hid(busobj, "_HID", &hid) == AE_OK) &&
11717c478bd9Sstevel@tonic-gate 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS) &&
11727c478bd9Sstevel@tonic-gate 		    (acpica_eval_int(busobj, "_BBN", &bbn) == AE_OK)) {
11737c478bd9Sstevel@tonic-gate 			if (bbn == 0) {
11747c478bd9Sstevel@tonic-gate 			/*
11757c478bd9Sstevel@tonic-gate 			 * If we find more than one bus with a 0 _BBN
11767c478bd9Sstevel@tonic-gate 			 * we have the problem that BigBear's BIOS shows
11777c478bd9Sstevel@tonic-gate 			 */
11787c478bd9Sstevel@tonic-gate 				if (++zerobbncnt > 1)
11797c478bd9Sstevel@tonic-gate 					return (1);
11807c478bd9Sstevel@tonic-gate 			}
11817c478bd9Sstevel@tonic-gate 		}
11827c478bd9Sstevel@tonic-gate 	}
11837c478bd9Sstevel@tonic-gate 	return (0);
11847c478bd9Sstevel@tonic-gate }
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate static const char hextab[] = "0123456789ABCDEF";
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate static int
11897c478bd9Sstevel@tonic-gate hexdig(int c)
11907c478bd9Sstevel@tonic-gate {
11917c478bd9Sstevel@tonic-gate 	/*
11927c478bd9Sstevel@tonic-gate 	 *  Get hex digit:
11937c478bd9Sstevel@tonic-gate 	 *
11947c478bd9Sstevel@tonic-gate 	 *  Returns the 4-bit hex digit named by the input character.  Returns
11957c478bd9Sstevel@tonic-gate 	 *  zero if the input character is not valid hex!
11967c478bd9Sstevel@tonic-gate 	 */
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	int x = ((c < 'a') || (c > 'z')) ? c : (c - ' ');
11997c478bd9Sstevel@tonic-gate 	int j = sizeof (hextab);
12007c478bd9Sstevel@tonic-gate 
1201*5dff2f34Smyers 	while (--j && (x != hextab[j])) {
1202*5dff2f34Smyers 	}
12037c478bd9Sstevel@tonic-gate 	return (j);
12047c478bd9Sstevel@tonic-gate }
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate static int
12077c478bd9Sstevel@tonic-gate CompressEisaID(char *np)
12087c478bd9Sstevel@tonic-gate {
12097c478bd9Sstevel@tonic-gate 	/*
12107c478bd9Sstevel@tonic-gate 	 *  Compress an EISA device name:
12117c478bd9Sstevel@tonic-gate 	 *
12127c478bd9Sstevel@tonic-gate 	 *  This routine converts a 7-byte ASCII device name into the 4-byte
12137c478bd9Sstevel@tonic-gate 	 *  compressed form used by EISA (50 bytes of ROM to save 1 byte of
12147c478bd9Sstevel@tonic-gate 	 *  NV-RAM!)
12157c478bd9Sstevel@tonic-gate 	 */
12167c478bd9Sstevel@tonic-gate 
12177c478bd9Sstevel@tonic-gate 	union { char octets[4]; int retval; } myu;
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate 	myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03);
12207c478bd9Sstevel@tonic-gate 	myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F);
12217c478bd9Sstevel@tonic-gate 	myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]);
12227c478bd9Sstevel@tonic-gate 	myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]);
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 	return (myu.retval);
12257c478bd9Sstevel@tonic-gate }
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate int
12287c478bd9Sstevel@tonic-gate acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint)
12297c478bd9Sstevel@tonic-gate {
12307c478bd9Sstevel@tonic-gate 	ACPI_STATUS status;
12317c478bd9Sstevel@tonic-gate 	ACPI_BUFFER rb;
12327c478bd9Sstevel@tonic-gate 	ACPI_OBJECT ro;
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	rb.Pointer = &ro;
12357c478bd9Sstevel@tonic-gate 	rb.Length = sizeof (ro);
12367c478bd9Sstevel@tonic-gate 	if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb,
1237*5dff2f34Smyers 	    ACPI_TYPE_INTEGER)) == AE_OK)
12387c478bd9Sstevel@tonic-gate 		*rint = ro.Integer.Value;
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	return (status);
12417c478bd9Sstevel@tonic-gate }
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate static int
12447c478bd9Sstevel@tonic-gate acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint)
12457c478bd9Sstevel@tonic-gate {
12467c478bd9Sstevel@tonic-gate 	ACPI_BUFFER rb;
12477c478bd9Sstevel@tonic-gate 	ACPI_OBJECT *rv;
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	rb.Pointer = NULL;
12507c478bd9Sstevel@tonic-gate 	rb.Length = ACPI_ALLOCATE_BUFFER;
12517c478bd9Sstevel@tonic-gate 	if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK) {
12527c478bd9Sstevel@tonic-gate 		rv = rb.Pointer;
12537c478bd9Sstevel@tonic-gate 		if (rv->Type == ACPI_TYPE_INTEGER) {
12547c478bd9Sstevel@tonic-gate 			*rint = rv->Integer.Value;
12557c478bd9Sstevel@tonic-gate 			AcpiOsFree(rv);
12567c478bd9Sstevel@tonic-gate 			return (AE_OK);
12577c478bd9Sstevel@tonic-gate 		} else if (rv->Type == ACPI_TYPE_STRING) {
12587c478bd9Sstevel@tonic-gate 			char *stringData;
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 			/* Convert the string into an EISA ID */
12617c478bd9Sstevel@tonic-gate 			if (rv->String.Pointer == NULL) {
12627c478bd9Sstevel@tonic-gate 				AcpiOsFree(rv);
12637c478bd9Sstevel@tonic-gate 				return (AE_ERROR);
12647c478bd9Sstevel@tonic-gate 			}
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 			stringData = rv->String.Pointer;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 			/*
12697c478bd9Sstevel@tonic-gate 			 * If the string is an EisaID, it must be 7
12707c478bd9Sstevel@tonic-gate 			 * characters; if it's an ACPI ID, it will be 8
12717c478bd9Sstevel@tonic-gate 			 * (and we don't care about ACPI ids here).
12727c478bd9Sstevel@tonic-gate 			 */
12737c478bd9Sstevel@tonic-gate 			if (strlen(stringData) != 7) {
12747c478bd9Sstevel@tonic-gate 				AcpiOsFree(rv);
12757c478bd9Sstevel@tonic-gate 				return (AE_ERROR);
12767c478bd9Sstevel@tonic-gate 			}
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 			*rint = CompressEisaID(stringData);
12797c478bd9Sstevel@tonic-gate 			AcpiOsFree(rv);
12807c478bd9Sstevel@tonic-gate 			return (AE_OK);
12817c478bd9Sstevel@tonic-gate 		} else
12827c478bd9Sstevel@tonic-gate 			AcpiOsFree(rv);
12837c478bd9Sstevel@tonic-gate 	}
12847c478bd9Sstevel@tonic-gate 	return (AE_ERROR);
12857c478bd9Sstevel@tonic-gate }
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate /*
12887c478bd9Sstevel@tonic-gate  * Return the d2a node matching this ACPI_HANDLE, if one exists
12897c478bd9Sstevel@tonic-gate  */
12907c478bd9Sstevel@tonic-gate int
12917c478bd9Sstevel@tonic-gate acpica_find_pcid2a(ACPI_HANDLE rh, d2a **dp)
12927c478bd9Sstevel@tonic-gate {
12937c478bd9Sstevel@tonic-gate 	d2a *d2ap;
12947c478bd9Sstevel@tonic-gate 	int i;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	if (d2a_len == 0)
12977c478bd9Sstevel@tonic-gate 		create_d2a_map();
12987c478bd9Sstevel@tonic-gate 	for (d2ap = d2a_table, i = 0; i < d2a_valid; d2ap++, i++)
12997c478bd9Sstevel@tonic-gate 		if (d2ap->acpiobj == rh) {
13007c478bd9Sstevel@tonic-gate 			*dp = d2ap;
13017c478bd9Sstevel@tonic-gate 			return (AE_OK);
13027c478bd9Sstevel@tonic-gate 		}
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	return (AE_ERROR);
13057c478bd9Sstevel@tonic-gate }
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate /*
13097c478bd9Sstevel@tonic-gate  * Return the ACPI device node matching this dev_info node, if it
13107c478bd9Sstevel@tonic-gate  * exists in the ACPI tree.
13117c478bd9Sstevel@tonic-gate  */
13127c478bd9Sstevel@tonic-gate int
13137c478bd9Sstevel@tonic-gate acpica_find_pciobj(dev_info_t *dip, ACPI_HANDLE *rh)
13147c478bd9Sstevel@tonic-gate {
13157c478bd9Sstevel@tonic-gate 	d2a *d2ap;
13167c478bd9Sstevel@tonic-gate 	int i;
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 	if (d2a_len == 0)
13197c478bd9Sstevel@tonic-gate 		create_d2a_map();
13207c478bd9Sstevel@tonic-gate 	for (d2ap = d2a_table, i = 0; i < d2a_valid; d2ap++, i++)
13217c478bd9Sstevel@tonic-gate 		if (d2ap->dip == dip) {
13227c478bd9Sstevel@tonic-gate 			*rh = d2ap->acpiobj;
13237c478bd9Sstevel@tonic-gate 			return (AE_OK);
13247c478bd9Sstevel@tonic-gate 		}
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 	return (AE_ERROR);
13277c478bd9Sstevel@tonic-gate }
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate /*
13307c478bd9Sstevel@tonic-gate  * Create a table mapping PCI dips to ACPI objects
13317c478bd9Sstevel@tonic-gate  */
13327c478bd9Sstevel@tonic-gate static void
13337c478bd9Sstevel@tonic-gate new_d2a_entry(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus, int dev, int func)
13347c478bd9Sstevel@tonic-gate {
13357c478bd9Sstevel@tonic-gate 	int newsize;
13367c478bd9Sstevel@tonic-gate 	d2a *new_arr, *ep;
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	if (d2a_valid >= d2a_len) {
13397c478bd9Sstevel@tonic-gate 		/* initially, or re-, allocate array */
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 		newsize = (d2a_len ? d2a_len * 2 : D2A_INITLEN);
13427c478bd9Sstevel@tonic-gate 		new_arr = kmem_zalloc(newsize * sizeof (d2a), KM_SLEEP);
13437c478bd9Sstevel@tonic-gate 		if (d2a_len != 0) {
13447c478bd9Sstevel@tonic-gate 			/* realloc: copy data, free old */
13457c478bd9Sstevel@tonic-gate 			bcopy(d2a_table, new_arr, d2a_len * sizeof (d2a));
13467c478bd9Sstevel@tonic-gate 			kmem_free(d2a_table, d2a_len * sizeof (d2a));
13477c478bd9Sstevel@tonic-gate 		}
13487c478bd9Sstevel@tonic-gate 		d2a_len = newsize;
13497c478bd9Sstevel@tonic-gate 		d2a_table = new_arr;
13507c478bd9Sstevel@tonic-gate 	}
13517c478bd9Sstevel@tonic-gate 	ep = &d2a_table[d2a_valid++];
13527c478bd9Sstevel@tonic-gate 	ep->bus = (unsigned char)bus;
13537c478bd9Sstevel@tonic-gate 	ep->dev = (unsigned char)dev;
13547c478bd9Sstevel@tonic-gate 	ep->func = (unsigned char)func;
13557c478bd9Sstevel@tonic-gate 	ep->dip = dip;
13567c478bd9Sstevel@tonic-gate 	ep->acpiobj = acpiobj;
13577c478bd9Sstevel@tonic-gate #ifdef D2ADEBUG
13587c478bd9Sstevel@tonic-gate 	{
13597c478bd9Sstevel@tonic-gate 		ACPI_BUFFER rb;
13607c478bd9Sstevel@tonic-gate 		char pathname[60];
13617c478bd9Sstevel@tonic-gate 		ddi_pathname(dip, pathname);
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 		rb.Pointer = NULL;
13647c478bd9Sstevel@tonic-gate 		rb.Length = ACPI_ALLOCATE_BUFFER;
13657c478bd9Sstevel@tonic-gate 		if (AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb) == AE_OK) {
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 			cmn_err(CE_NOTE, "d2a entry: %s %s %d/0x%x/%d",
1368*5dff2f34Smyers 			    pathname, (char *)rb.Pointer, bus, dev, func);
13697c478bd9Sstevel@tonic-gate 			AcpiOsFree(rb.Pointer);
13707c478bd9Sstevel@tonic-gate 		}
13717c478bd9Sstevel@tonic-gate 	}
13727c478bd9Sstevel@tonic-gate #endif
13737c478bd9Sstevel@tonic-gate }
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate static void
13767c478bd9Sstevel@tonic-gate create_d2a_map(void)
13777c478bd9Sstevel@tonic-gate {
13787c478bd9Sstevel@tonic-gate 	dev_info_t *dip, *cdip;
13797c478bd9Sstevel@tonic-gate 	ACPI_HANDLE acpiobj;
13807c478bd9Sstevel@tonic-gate 	char *device_type_prop;
13817c478bd9Sstevel@tonic-gate 	int bus;
13827c478bd9Sstevel@tonic-gate 	static int map_error = 0;
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate 	if (map_error)
13857c478bd9Sstevel@tonic-gate 		return;
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	creating_d2a_map = 1;
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 	/*
13907c478bd9Sstevel@tonic-gate 	 * Find all child-of-root PCI buses, and find their corresponding
13917c478bd9Sstevel@tonic-gate 	 * ACPI child-of-root PCI nodes.  For each one, add to the
13927c478bd9Sstevel@tonic-gate 	 * d2a table.
13937c478bd9Sstevel@tonic-gate 	 */
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 	for (dip = ddi_get_child(ddi_root_node());
13967c478bd9Sstevel@tonic-gate 	    dip != NULL;
13977c478bd9Sstevel@tonic-gate 	    dip = ddi_get_next_sibling(dip)) {
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 		/* prune non-PCI nodes */
14007c478bd9Sstevel@tonic-gate 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
14017c478bd9Sstevel@tonic-gate 		    "device_type", &device_type_prop) != DDI_PROP_SUCCESS)
14027c478bd9Sstevel@tonic-gate 			continue;
14037c478bd9Sstevel@tonic-gate 
140470025d76Sjohnny 		if ((strcmp("pci", device_type_prop) != 0) &&
140570025d76Sjohnny 		    (strcmp("pciex", device_type_prop) != 0)) {
14067c478bd9Sstevel@tonic-gate 			ddi_prop_free(device_type_prop);
14077c478bd9Sstevel@tonic-gate 			continue;
14087c478bd9Sstevel@tonic-gate 		}
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 		ddi_prop_free(device_type_prop);
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 		/*
14137c478bd9Sstevel@tonic-gate 		 * To get bus number of dip, get first child and get its
14147c478bd9Sstevel@tonic-gate 		 * bus number.  If NULL, just continue, because we don't
14157c478bd9Sstevel@tonic-gate 		 * care about bus nodes with no children anyway.
14167c478bd9Sstevel@tonic-gate 		 */
14177c478bd9Sstevel@tonic-gate 		if ((cdip = ddi_get_child(dip)) == NULL)
14187c478bd9Sstevel@tonic-gate 			continue;
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 		if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) {
14217c478bd9Sstevel@tonic-gate #ifdef D2ADEBUG
14227c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "Can't get bus number of PCI child?");
14237c478bd9Sstevel@tonic-gate #endif
14247c478bd9Sstevel@tonic-gate 			map_error = 1;
14257c478bd9Sstevel@tonic-gate 			creating_d2a_map = 0;
14267c478bd9Sstevel@tonic-gate 			return;
14277c478bd9Sstevel@tonic-gate 		}
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 		if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) {
14307c478bd9Sstevel@tonic-gate #ifdef D2ADEBUG
14317c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus);
14327c478bd9Sstevel@tonic-gate #endif
14337c478bd9Sstevel@tonic-gate 			map_error = 1;
14347c478bd9Sstevel@tonic-gate 			continue;
14357c478bd9Sstevel@tonic-gate 		}
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 		/*
14387c478bd9Sstevel@tonic-gate 		 * map this node, with illegal device and fn numbers
14397c478bd9Sstevel@tonic-gate 		 * (since, as a PCI root node, it exists on the system
14407c478bd9Sstevel@tonic-gate 		 * bus
14417c478bd9Sstevel@tonic-gate 		 */
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 		new_d2a_entry(dip, acpiobj, bus, 32, 8);
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 		/* call recursive function to enumerate subtrees */
14467c478bd9Sstevel@tonic-gate 		create_d2a_subtree(dip, acpiobj, bus);
14477c478bd9Sstevel@tonic-gate 	}
14487c478bd9Sstevel@tonic-gate 	creating_d2a_map = 0;
14497c478bd9Sstevel@tonic-gate }
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate /*
14527c478bd9Sstevel@tonic-gate  * For all acpi child devices of acpiobj, find their matching
14537c478bd9Sstevel@tonic-gate  * dip under "dip" argument.  (matching means "matches dev/fn").
14547c478bd9Sstevel@tonic-gate  * bus is assumed to already be a match from caller, and is
14557c478bd9Sstevel@tonic-gate  * used here only to record in the d2a entry.  Recurse if necessary.
14567c478bd9Sstevel@tonic-gate  */
14577c478bd9Sstevel@tonic-gate static void
14587c478bd9Sstevel@tonic-gate create_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus)
14597c478bd9Sstevel@tonic-gate {
14607c478bd9Sstevel@tonic-gate 	int acpi_devfn, hid;
14617c478bd9Sstevel@tonic-gate 	ACPI_HANDLE acld;
14627c478bd9Sstevel@tonic-gate 	dev_info_t *dcld;
14637c478bd9Sstevel@tonic-gate 	int dcld_b, dcld_d, dcld_f;
14647c478bd9Sstevel@tonic-gate 	int dev, func;
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	acld = NULL;
1467186507a7Smyers 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld)
14687c478bd9Sstevel@tonic-gate 	    == AE_OK) {
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 		/*
14717c478bd9Sstevel@tonic-gate 		 * Skip ACPI devices that are obviously not PCI, i.e.,
14727c478bd9Sstevel@tonic-gate 		 * that have a _HID that is *not* the PCI HID
14737c478bd9Sstevel@tonic-gate 		 */
14747c478bd9Sstevel@tonic-gate 
14757c478bd9Sstevel@tonic-gate 		if (acpica_eval_hid(acld, "_HID", &hid) == AE_OK &&
14767c478bd9Sstevel@tonic-gate 		    hid != HID_PCI_BUS && hid != HID_PCI_EXPRESS_BUS)
14777c478bd9Sstevel@tonic-gate 			continue;
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 		/* get the dev/func we're looking for in the devinfo tree */
14807c478bd9Sstevel@tonic-gate 		if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK)
14817c478bd9Sstevel@tonic-gate 			continue;
14827c478bd9Sstevel@tonic-gate 		dev = (acpi_devfn >> 16) & 0xFFFF;
14837c478bd9Sstevel@tonic-gate 		func = acpi_devfn & 0xFFFF;
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 		/* look through all the immediate children of dip */
14867c478bd9Sstevel@tonic-gate 		for (dcld = ddi_get_child(dip); dcld != NULL;
14877c478bd9Sstevel@tonic-gate 		    dcld = ddi_get_next_sibling(dcld)) {
14887c478bd9Sstevel@tonic-gate 			if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0)
14897c478bd9Sstevel@tonic-gate 				continue;
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 			/* dev must match; function must match or wildcard */
14927c478bd9Sstevel@tonic-gate 			if (dcld_d != dev ||
14937c478bd9Sstevel@tonic-gate 			    (func != 0xFFFF && func != dcld_f))
14947c478bd9Sstevel@tonic-gate 				continue;
14957c478bd9Sstevel@tonic-gate 			bus = dcld_b;
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 			/* found a match, record it */
14987c478bd9Sstevel@tonic-gate 			new_d2a_entry(dcld, acld, bus, dev, func);
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 			/* recurse from here to pick up child trees */
15017c478bd9Sstevel@tonic-gate 			create_d2a_subtree(dcld, acld, bus);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 			/* done finding a match, so break now */
15047c478bd9Sstevel@tonic-gate 			break;
15057c478bd9Sstevel@tonic-gate 		}
15068e56767dSsmall 	}
15077c478bd9Sstevel@tonic-gate }
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate /*
15107c478bd9Sstevel@tonic-gate  * Return bus/dev/fn for PCI dip (note: not the parent "pci" node).
15117c478bd9Sstevel@tonic-gate  */
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate int
15147c478bd9Sstevel@tonic-gate acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func)
15157c478bd9Sstevel@tonic-gate {
15167c478bd9Sstevel@tonic-gate 	pci_regspec_t *pci_rp;
15177c478bd9Sstevel@tonic-gate 	int len;
15187c478bd9Sstevel@tonic-gate 
15197c478bd9Sstevel@tonic-gate 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
15207c478bd9Sstevel@tonic-gate 	    "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS)
15217c478bd9Sstevel@tonic-gate 		return (-1);
15227c478bd9Sstevel@tonic-gate 
15237c478bd9Sstevel@tonic-gate 	if (len < (sizeof (pci_regspec_t) / sizeof (int))) {
15247c478bd9Sstevel@tonic-gate 		ddi_prop_free(pci_rp);
15257c478bd9Sstevel@tonic-gate 		return (-1);
15267c478bd9Sstevel@tonic-gate 	}
15277c478bd9Sstevel@tonic-gate 	if (bus != NULL)
15287c478bd9Sstevel@tonic-gate 		*bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi);
15297c478bd9Sstevel@tonic-gate 	if (device != NULL)
15307c478bd9Sstevel@tonic-gate 		*device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi);
15317c478bd9Sstevel@tonic-gate 	if (func != NULL)
15327c478bd9Sstevel@tonic-gate 		*func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
15337c478bd9Sstevel@tonic-gate 	ddi_prop_free(pci_rp);
15347c478bd9Sstevel@tonic-gate 	return (0);
15357c478bd9Sstevel@tonic-gate }
1536