xref: /illumos-gate/usr/src/uts/intel/io/acpica/osl.c (revision 48633f182599946aebd63dccdc852ad722b57d0e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * ACPI CA OSL for Solaris x86
28  */
29 
30 #include <sys/types.h>
31 #include <sys/kmem.h>
32 #include <sys/psm.h>
33 #include <sys/pci_cfgspace.h>
34 #include <sys/ddi.h>
35 #include <sys/sunndi.h>
36 #include <sys/pci.h>
37 #include <sys/kobj.h>
38 #include <sys/taskq.h>
39 #include <sys/strlog.h>
40 #include <sys/note.h>
41 
42 #include <sys/acpi/acpi.h>
43 #include <sys/acpica.h>
44 #include <sys/acpi/acinterp.h>
45 
46 #define	MAX_DAT_FILE_SIZE	(64*1024)
47 
48 /* local functions */
49 static int CompressEisaID(char *np);
50 
51 static void scan_d2a_map(void);
52 static void scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus);
53 static void acpica_tag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj);
54 
55 static int acpica_query_bbn_problem(void);
56 static int acpica_find_pcibus(int busno, ACPI_HANDLE *rh);
57 static int acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint);
58 static ACPI_STATUS acpica_set_devinfo(ACPI_HANDLE, dev_info_t *);
59 static void acpica_devinfo_handler(ACPI_HANDLE, UINT32, void *);
60 
61 /*
62  * Event queue vars
63  */
64 int acpica_eventq_init = 0;
65 ddi_taskq_t *osl_eventq[OSL_EC_BURST_HANDLER+1];
66 
67 /*
68  * Priorities relative to minclsyspri that each taskq
69  * run at; OSL_NOTIFY_HANDLER needs to run at a higher
70  * priority than OSL_GPE_HANDLER.  There's an implicit
71  * assumption that no priority here results in exceeding
72  * maxclsyspri.
73  * Note: these initializations need to match the order of
74  * ACPI_EXECUTE_TYPE.
75  */
76 int osl_eventq_pri_delta[OSL_EC_BURST_HANDLER+1] = {
77 	0,	/* OSL_GLOBAL_LOCK_HANDLER */
78 	2,	/* OSL_NOTIFY_HANDLER */
79 	0,	/* OSL_GPE_HANDLER */
80 	0,	/* OSL_DEBUGGER_THREAD */
81 	0,	/* OSL_EC_POLL_HANDLER */
82 	0	/* OSL_EC_BURST_HANDLER */
83 };
84 
85 /*
86  * Note, if you change this path, you need to update
87  * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386
88  */
89 static char *acpi_table_path = "/boot/acpi/tables/";
90 
91 /* non-zero while scan_d2a_map() is working */
92 static int scanning_d2a_map = 0;
93 static int d2a_done = 0;
94 
95 /* set by acpi_poweroff() in PSMs and appm_ioctl() in acpippm for S3 */
96 int acpica_use_safe_delay = 0;
97 
98 /* CPU mapping data */
99 struct cpu_map_item {
100 	UINT32		proc_id;
101 	ACPI_HANDLE	obj;
102 };
103 
104 static struct cpu_map_item **cpu_map = NULL;
105 static int cpu_map_count = 0;
106 static int cpu_map_built = 0;
107 
108 static int acpi_has_broken_bbn = -1;
109 
110 /* buffer for AcpiOsVprintf() */
111 #define	ACPI_OSL_PR_BUFLEN	1024
112 static char *acpi_osl_pr_buffer = NULL;
113 static int acpi_osl_pr_buflen;
114 
115 #define	D2A_DEBUG
116 
117 /*
118  *
119  */
120 static void
121 discard_event_queues()
122 {
123 	int	i;
124 
125 	/*
126 	 * destroy event queues
127 	 */
128 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
129 		if (osl_eventq[i])
130 			ddi_taskq_destroy(osl_eventq[i]);
131 	}
132 }
133 
134 
135 /*
136  *
137  */
138 static ACPI_STATUS
139 init_event_queues()
140 {
141 	char	namebuf[32];
142 	int	i, error = 0;
143 
144 	/*
145 	 * Initialize event queues
146 	 */
147 
148 	/* Always allocate only 1 thread per queue to force FIFO execution */
149 	for (i = OSL_GLOBAL_LOCK_HANDLER; i <= OSL_EC_BURST_HANDLER; i++) {
150 		snprintf(namebuf, 32, "ACPI%d", i);
151 		osl_eventq[i] = ddi_taskq_create(NULL, namebuf, 1,
152 		    osl_eventq_pri_delta[i] + minclsyspri, 0);
153 		if (osl_eventq[i] == NULL)
154 			error++;
155 	}
156 
157 	if (error != 0) {
158 		discard_event_queues();
159 #ifdef	DEBUG
160 		cmn_err(CE_WARN, "!acpica: could not initialize event queues");
161 #endif
162 		return (AE_ERROR);
163 	}
164 
165 	acpica_eventq_init = 1;
166 	return (AE_OK);
167 }
168 
169 /*
170  * One-time initialization of OSL layer
171  */
172 ACPI_STATUS
173 AcpiOsInitialize(void)
174 {
175 	/*
176 	 * Allocate buffer for AcpiOsVprintf() here to avoid
177 	 * kmem_alloc()/kmem_free() at high PIL
178 	 */
179 	acpi_osl_pr_buffer = kmem_alloc(ACPI_OSL_PR_BUFLEN, KM_SLEEP);
180 	if (acpi_osl_pr_buffer != NULL)
181 		acpi_osl_pr_buflen = ACPI_OSL_PR_BUFLEN;
182 
183 	return (AE_OK);
184 }
185 
186 /*
187  * One-time shut-down of OSL layer
188  */
189 ACPI_STATUS
190 AcpiOsTerminate(void)
191 {
192 
193 	if (acpi_osl_pr_buffer != NULL)
194 		kmem_free(acpi_osl_pr_buffer, acpi_osl_pr_buflen);
195 
196 	discard_event_queues();
197 	return (AE_OK);
198 }
199 
200 
201 ACPI_PHYSICAL_ADDRESS
202 AcpiOsGetRootPointer()
203 {
204 	ACPI_PHYSICAL_ADDRESS Address;
205 
206 	/*
207 	 * For EFI firmware, the root pointer is defined in EFI systab.
208 	 * The boot code process the table and put the physical address
209 	 * in the acpi-root-tab property.
210 	 */
211 	Address = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0,
212 	    "acpi-root-tab", NULL);
213 
214 	if ((Address == NULL) && ACPI_FAILURE(AcpiFindRootPointer(&Address)))
215 		Address = NULL;
216 
217 	return (Address);
218 }
219 
220 /*ARGSUSED*/
221 ACPI_STATUS
222 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *InitVal,
223 				ACPI_STRING *NewVal)
224 {
225 
226 	*NewVal = 0;
227 	return (AE_OK);
228 }
229 
230 static void
231 acpica_strncpy(char *dest, const char *src, int len)
232 {
233 
234 	/*LINTED*/
235 	while ((*dest++ = *src++) && (--len > 0))
236 		/* copy the string */;
237 	*dest = '\0';
238 }
239 
240 ACPI_STATUS
241 AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable,
242 			ACPI_TABLE_HEADER **NewTable)
243 {
244 	char signature[5];
245 	char oemid[7];
246 	char oemtableid[9];
247 	struct _buf *file;
248 	char *buf1, *buf2;
249 	int count;
250 	char acpi_table_loc[128];
251 
252 	acpica_strncpy(signature, ExistingTable->Signature, 4);
253 	acpica_strncpy(oemid, ExistingTable->OemId, 6);
254 	acpica_strncpy(oemtableid, ExistingTable->OemTableId, 8);
255 
256 #ifdef	DEBUG
257 	cmn_err(CE_NOTE, "!acpica: table [%s] v%d OEM ID [%s]"
258 	    " OEM TABLE ID [%s] OEM rev %x",
259 	    signature, ExistingTable->Revision, oemid, oemtableid,
260 	    ExistingTable->OemRevision);
261 #endif
262 
263 	/* File name format is "signature_oemid_oemtableid.dat" */
264 	(void) strcpy(acpi_table_loc, acpi_table_path);
265 	(void) strcat(acpi_table_loc, signature); /* for example, DSDT */
266 	(void) strcat(acpi_table_loc, "_");
267 	(void) strcat(acpi_table_loc, oemid); /* for example, IntelR */
268 	(void) strcat(acpi_table_loc, "_");
269 	(void) strcat(acpi_table_loc, oemtableid); /* for example, AWRDACPI */
270 	(void) strcat(acpi_table_loc, ".dat");
271 
272 	file = kobj_open_file(acpi_table_loc);
273 	if (file == (struct _buf *)-1) {
274 		*NewTable = 0;
275 		return (AE_OK);
276 	} else {
277 		buf1 = (char *)kmem_alloc(MAX_DAT_FILE_SIZE, KM_SLEEP);
278 		count = kobj_read_file(file, buf1, MAX_DAT_FILE_SIZE-1, 0);
279 		if (count >= MAX_DAT_FILE_SIZE) {
280 			cmn_err(CE_WARN, "!acpica: table %s file size too big",
281 			    acpi_table_loc);
282 			*NewTable = 0;
283 		} else {
284 			buf2 = (char *)kmem_alloc(count, KM_SLEEP);
285 			(void) memcpy(buf2, buf1, count);
286 			*NewTable = (ACPI_TABLE_HEADER *)buf2;
287 			cmn_err(CE_NOTE, "!acpica: replacing table: %s",
288 			    acpi_table_loc);
289 		}
290 	}
291 	kobj_close_file(file);
292 	kmem_free(buf1, MAX_DAT_FILE_SIZE);
293 
294 	return (AE_OK);
295 }
296 
297 
298 /*
299  * ACPI semaphore implementation
300  */
301 typedef struct {
302 	kmutex_t	mutex;
303 	kcondvar_t	cv;
304 	uint32_t	available;
305 	uint32_t	initial;
306 	uint32_t	maximum;
307 } acpi_sema_t;
308 
309 /*
310  *
311  */
312 void
313 acpi_sema_init(acpi_sema_t *sp, unsigned max, unsigned count)
314 {
315 	mutex_init(&sp->mutex, NULL, MUTEX_DRIVER, NULL);
316 	cv_init(&sp->cv, NULL, CV_DRIVER, NULL);
317 	/* no need to enter mutex here at creation */
318 	sp->available = count;
319 	sp->initial = count;
320 	sp->maximum = max;
321 }
322 
323 /*
324  *
325  */
326 void
327 acpi_sema_destroy(acpi_sema_t *sp)
328 {
329 
330 	cv_destroy(&sp->cv);
331 	mutex_destroy(&sp->mutex);
332 }
333 
334 /*
335  *
336  */
337 ACPI_STATUS
338 acpi_sema_p(acpi_sema_t *sp, unsigned count, uint16_t wait_time)
339 {
340 	ACPI_STATUS rv = AE_OK;
341 	clock_t deadline;
342 
343 	mutex_enter(&sp->mutex);
344 
345 	if (sp->available >= count) {
346 		/*
347 		 * Enough units available, no blocking
348 		 */
349 		sp->available -= count;
350 		mutex_exit(&sp->mutex);
351 		return (rv);
352 	} else if (wait_time == 0) {
353 		/*
354 		 * Not enough units available and timeout
355 		 * specifies no blocking
356 		 */
357 		rv = AE_TIME;
358 		mutex_exit(&sp->mutex);
359 		return (rv);
360 	}
361 
362 	/*
363 	 * Not enough units available and timeout specifies waiting
364 	 */
365 	if (wait_time != ACPI_WAIT_FOREVER)
366 		deadline = ddi_get_lbolt() +
367 		    (clock_t)drv_usectohz(wait_time * 1000);
368 
369 	do {
370 		if (wait_time == ACPI_WAIT_FOREVER)
371 			cv_wait(&sp->cv, &sp->mutex);
372 		else if (cv_timedwait(&sp->cv, &sp->mutex, deadline) < 0) {
373 			rv = AE_TIME;
374 			break;
375 		}
376 	} while (sp->available < count);
377 
378 	/* if we dropped out of the wait with AE_OK, we got the units */
379 	if (rv == AE_OK)
380 		sp->available -= count;
381 
382 	mutex_exit(&sp->mutex);
383 	return (rv);
384 }
385 
386 /*
387  *
388  */
389 void
390 acpi_sema_v(acpi_sema_t *sp, unsigned count)
391 {
392 	mutex_enter(&sp->mutex);
393 	sp->available += count;
394 	cv_broadcast(&sp->cv);
395 	mutex_exit(&sp->mutex);
396 }
397 
398 
399 ACPI_STATUS
400 AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
401 ACPI_HANDLE *OutHandle)
402 {
403 	acpi_sema_t *sp;
404 
405 	if ((OutHandle == NULL) || (InitialUnits > MaxUnits))
406 		return (AE_BAD_PARAMETER);
407 
408 	sp = (acpi_sema_t *)kmem_alloc(sizeof (acpi_sema_t), KM_SLEEP);
409 	acpi_sema_init(sp, MaxUnits, InitialUnits);
410 	*OutHandle = (ACPI_HANDLE)sp;
411 	return (AE_OK);
412 }
413 
414 
415 ACPI_STATUS
416 AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
417 {
418 
419 	if (Handle == NULL)
420 		return (AE_BAD_PARAMETER);
421 
422 	acpi_sema_destroy((acpi_sema_t *)Handle);
423 	kmem_free((void *)Handle, sizeof (acpi_sema_t));
424 	return (AE_OK);
425 }
426 
427 ACPI_STATUS
428 AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
429 {
430 
431 	if ((Handle == NULL) || (Units < 1))
432 		return (AE_BAD_PARAMETER);
433 
434 	return (acpi_sema_p((acpi_sema_t *)Handle, Units, Timeout));
435 }
436 
437 ACPI_STATUS
438 AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
439 {
440 
441 	if ((Handle == NULL) || (Units < 1))
442 		return (AE_BAD_PARAMETER);
443 
444 	acpi_sema_v((acpi_sema_t *)Handle, Units);
445 	return (AE_OK);
446 }
447 
448 ACPI_STATUS
449 AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
450 {
451 	kmutex_t *mp;
452 
453 	if (OutHandle == NULL)
454 		return (AE_BAD_PARAMETER);
455 
456 	mp = (kmutex_t *)kmem_alloc(sizeof (kmutex_t), KM_SLEEP);
457 	mutex_init(mp, NULL, MUTEX_DRIVER, NULL);
458 	*OutHandle = (ACPI_HANDLE)mp;
459 	return (AE_OK);
460 }
461 
462 void
463 AcpiOsDeleteLock(ACPI_HANDLE Handle)
464 {
465 
466 	if (Handle == NULL)
467 		return;
468 
469 	mutex_destroy((kmutex_t *)Handle);
470 	kmem_free((void *)Handle, sizeof (kmutex_t));
471 }
472 
473 ACPI_CPU_FLAGS
474 AcpiOsAcquireLock(ACPI_HANDLE Handle)
475 {
476 
477 
478 	if (Handle == NULL)
479 		return (AE_BAD_PARAMETER);
480 
481 	if (curthread == CPU->cpu_idle_thread) {
482 		while (!mutex_tryenter((kmutex_t *)Handle))
483 			/* spin */;
484 	} else
485 		mutex_enter((kmutex_t *)Handle);
486 	return (AE_OK);
487 }
488 
489 void
490 AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_CPU_FLAGS Flags)
491 {
492 	_NOTE(ARGUNUSED(Flags))
493 
494 	mutex_exit((kmutex_t *)Handle);
495 }
496 
497 
498 void *
499 AcpiOsAllocate(ACPI_SIZE Size)
500 {
501 	ACPI_SIZE *tmp_ptr;
502 
503 	Size += sizeof (Size);
504 	tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP);
505 	*tmp_ptr++ = Size;
506 	return (tmp_ptr);
507 }
508 
509 void
510 AcpiOsFree(void *Memory)
511 {
512 	ACPI_SIZE	size, *tmp_ptr;
513 
514 	tmp_ptr = (ACPI_SIZE *)Memory;
515 	tmp_ptr -= 1;
516 	size = *tmp_ptr;
517 	kmem_free(tmp_ptr, size);
518 }
519 
520 void *
521 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size)
522 {
523 	/* FUTUREWORK: test PhysicalAddress for > 32 bits */
524 	return (psm_map_new((paddr_t)PhysicalAddress,
525 	    (size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ));
526 }
527 
528 void
529 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
530 {
531 
532 	psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
533 }
534 
535 /*ARGSUSED*/
536 ACPI_STATUS
537 AcpiOsGetPhysicalAddress(void *LogicalAddress,
538 			ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
539 {
540 
541 	/* UNIMPLEMENTED: not invoked by ACPI CA code */
542 	return (AE_NOT_IMPLEMENTED);
543 }
544 
545 
546 ACPI_OSD_HANDLER acpi_isr;
547 void *acpi_isr_context;
548 
549 uint_t
550 acpi_wrapper_isr(char *arg)
551 {
552 	_NOTE(ARGUNUSED(arg))
553 
554 	int	status;
555 
556 	status = (*acpi_isr)(acpi_isr_context);
557 
558 	if (status == ACPI_INTERRUPT_HANDLED) {
559 		return (DDI_INTR_CLAIMED);
560 	} else {
561 		return (DDI_INTR_UNCLAIMED);
562 	}
563 }
564 
565 static int acpi_intr_hooked = 0;
566 
567 ACPI_STATUS
568 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
569 		ACPI_OSD_HANDLER ServiceRoutine,
570 		void *Context)
571 {
572 	_NOTE(ARGUNUSED(InterruptNumber))
573 
574 	int retval;
575 	int sci_vect;
576 	iflag_t sci_flags;
577 
578 	acpi_isr = ServiceRoutine;
579 	acpi_isr_context = Context;
580 
581 	/*
582 	 * Get SCI (adjusted for PIC/APIC mode if necessary)
583 	 */
584 	if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) {
585 		return (AE_ERROR);
586 	}
587 
588 #ifdef	DEBUG
589 	cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect);
590 #endif
591 
592 	retval = add_avintr(NULL, SCI_IPL, (avfunc)acpi_wrapper_isr,
593 	    "ACPI SCI", sci_vect, NULL, NULL, NULL, NULL);
594 	if (retval) {
595 		acpi_intr_hooked = 1;
596 		return (AE_OK);
597 	} else
598 		return (AE_BAD_PARAMETER);
599 }
600 
601 ACPI_STATUS
602 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
603 			ACPI_OSD_HANDLER ServiceRoutine)
604 {
605 	_NOTE(ARGUNUSED(ServiceRoutine))
606 
607 #ifdef	DEBUG
608 	cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber);
609 #endif
610 	if (acpi_intr_hooked) {
611 		rem_avintr(NULL, LOCK_LEVEL - 1, (avfunc)acpi_wrapper_isr,
612 		    InterruptNumber);
613 		acpi_intr_hooked = 0;
614 	}
615 	return (AE_OK);
616 }
617 
618 
619 ACPI_THREAD_ID
620 AcpiOsGetThreadId(void)
621 {
622 	/*
623 	 * ACPI CA regards thread ID as an error, but it's valid
624 	 * on Solaris during kernel initialization.  Thus, 1 is added
625 	 * to the kernel thread ID to avoid returning 0
626 	 */
627 	return (ddi_get_kt_did() + 1);
628 }
629 
630 /*
631  *
632  */
633 ACPI_STATUS
634 AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK  Function,
635     void *Context)
636 {
637 
638 	if (!acpica_eventq_init) {
639 		/*
640 		 * Create taskqs for event handling
641 		 */
642 		if (init_event_queues() != AE_OK)
643 			return (AE_ERROR);
644 	}
645 
646 	if (ddi_taskq_dispatch(osl_eventq[Type], Function, Context,
647 	    DDI_NOSLEEP) == DDI_FAILURE) {
648 #ifdef	DEBUG
649 		cmn_err(CE_WARN, "!acpica: unable to dispatch event");
650 #endif
651 		return (AE_ERROR);
652 	}
653 	return (AE_OK);
654 
655 }
656 
657 void
658 AcpiOsSleep(ACPI_INTEGER Milliseconds)
659 {
660 	/*
661 	 * During kernel startup, before the first tick interrupt
662 	 * has taken place, we can't call delay; very late in
663 	 * kernel shutdown or suspend/resume, clock interrupts
664 	 * are blocked, so delay doesn't work then either.
665 	 * So we busy wait if lbolt == 0 (kernel startup)
666 	 * or if acpica_use_safe_delay has been set to a
667 	 * non-zero value.
668 	 */
669 	if ((ddi_get_lbolt() == 0) || acpica_use_safe_delay)
670 		drv_usecwait(Milliseconds * 1000);
671 	else
672 		delay(drv_usectohz(Milliseconds * 1000));
673 }
674 
675 void
676 AcpiOsStall(UINT32 Microseconds)
677 {
678 	drv_usecwait(Microseconds);
679 }
680 
681 
682 /*
683  * Implementation of "Windows 2001" compatible I/O permission map
684  *
685  */
686 #define	OSL_IO_NONE	(0)
687 #define	OSL_IO_READ	(1<<0)
688 #define	OSL_IO_WRITE	(1<<1)
689 #define	OSL_IO_RW	(OSL_IO_READ | OSL_IO_WRITE)
690 #define	OSL_IO_TERM	(1<<2)
691 #define	OSL_IO_DEFAULT	OSL_IO_RW
692 
693 static struct io_perm  {
694 	ACPI_IO_ADDRESS	low;
695 	ACPI_IO_ADDRESS	high;
696 	uint8_t		perm;
697 } osl_io_perm[] = {
698 	{ 0xcf8, 0xd00, OSL_IO_NONE | OSL_IO_TERM }
699 };
700 
701 
702 /*
703  *
704  */
705 static struct io_perm *
706 osl_io_find_perm(ACPI_IO_ADDRESS addr)
707 {
708 	struct io_perm *p;
709 
710 	p = osl_io_perm;
711 	while (p != NULL) {
712 		if ((p->low <= addr) && (addr <= p->high))
713 			break;
714 		p = (p->perm & OSL_IO_TERM) ? NULL : p+1;
715 	}
716 
717 	return (p);
718 }
719 
720 /*
721  *
722  */
723 ACPI_STATUS
724 AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
725 {
726 	struct io_perm *p;
727 
728 	/* verify permission */
729 	p = osl_io_find_perm(Address);
730 	if (p && (p->perm & OSL_IO_READ) == 0) {
731 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted",
732 		    (long)Address, Width);
733 		*Value = 0xffffffff;
734 		return (AE_ERROR);
735 	}
736 
737 	switch (Width) {
738 	case 8:
739 		*Value = inb(Address);
740 		break;
741 	case 16:
742 		*Value = inw(Address);
743 		break;
744 	case 32:
745 		*Value = inl(Address);
746 		break;
747 	default:
748 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed",
749 		    (long)Address, Width);
750 		return (AE_BAD_PARAMETER);
751 	}
752 	return (AE_OK);
753 }
754 
755 ACPI_STATUS
756 AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
757 {
758 	struct io_perm *p;
759 
760 	/* verify permission */
761 	p = osl_io_find_perm(Address);
762 	if (p && (p->perm & OSL_IO_WRITE) == 0) {
763 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted",
764 		    (long)Address, Width);
765 		return (AE_ERROR);
766 	}
767 
768 	switch (Width) {
769 	case 8:
770 		outb(Address, Value);
771 		break;
772 	case 16:
773 		outw(Address, Value);
774 		break;
775 	case 32:
776 		outl(Address, Value);
777 		break;
778 	default:
779 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed",
780 		    (long)Address, Width);
781 		return (AE_BAD_PARAMETER);
782 	}
783 	return (AE_OK);
784 }
785 
786 
787 /*
788  *
789  */
790 
791 #define	OSL_RW(ptr, val, type, rw) \
792 	{ if (rw) *((type *)(ptr)) = *((type *) val); \
793 	    else *((type *) val) = *((type *)(ptr)); }
794 
795 
796 static void
797 osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value,
798     UINT32 Width, int write)
799 {
800 	size_t	maplen = Width / 8;
801 	caddr_t	ptr;
802 
803 	ptr = psm_map_new((paddr_t)Address, maplen,
804 	    PSM_PROT_WRITE | PSM_PROT_READ);
805 
806 	switch (maplen) {
807 	case 1:
808 		OSL_RW(ptr, Value, uint8_t, write);
809 		break;
810 	case 2:
811 		OSL_RW(ptr, Value, uint16_t, write);
812 		break;
813 	case 4:
814 		OSL_RW(ptr, Value, uint32_t, write);
815 		break;
816 	default:
817 		cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d",
818 		    Width);
819 		break;
820 	}
821 
822 	psm_unmap(ptr, maplen);
823 }
824 
825 ACPI_STATUS
826 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,
827 		UINT32 *Value, UINT32 Width)
828 {
829 	osl_rw_memory(Address, Value, Width, 0);
830 	return (AE_OK);
831 }
832 
833 ACPI_STATUS
834 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,
835 		UINT32 Value, UINT32 Width)
836 {
837 	osl_rw_memory(Address, &Value, Width, 1);
838 	return (AE_OK);
839 }
840 
841 
842 ACPI_STATUS
843 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
844 			void *Value, UINT32 Width)
845 {
846 
847 	switch (Width) {
848 	case 8:
849 		*((UINT64 *)Value) = (UINT64)(*pci_getb_func)
850 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
851 		break;
852 	case 16:
853 		*((UINT64 *)Value) = (UINT64)(*pci_getw_func)
854 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
855 		break;
856 	case 32:
857 		*((UINT64 *)Value) = (UINT64)(*pci_getl_func)
858 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
859 		break;
860 	case 64:
861 	default:
862 		cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed",
863 		    Register, Width);
864 		return (AE_BAD_PARAMETER);
865 	}
866 	return (AE_OK);
867 }
868 
869 /*
870  *
871  */
872 int acpica_write_pci_config_ok = 1;
873 
874 ACPI_STATUS
875 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
876 		ACPI_INTEGER Value, UINT32 Width)
877 {
878 
879 	if (!acpica_write_pci_config_ok) {
880 		cmn_err(CE_NOTE, "!write to PCI cfg %x/%x/%x %x"
881 		    " %lx %d not permitted", PciId->Bus, PciId->Device,
882 		    PciId->Function, Register, (long)Value, Width);
883 		return (AE_OK);
884 	}
885 
886 	switch (Width) {
887 	case 8:
888 		(*pci_putb_func)(PciId->Bus, PciId->Device, PciId->Function,
889 		    Register, (uint8_t)Value);
890 		break;
891 	case 16:
892 		(*pci_putw_func)(PciId->Bus, PciId->Device, PciId->Function,
893 		    Register, (uint16_t)Value);
894 		break;
895 	case 32:
896 		(*pci_putl_func)(PciId->Bus, PciId->Device, PciId->Function,
897 		    Register, (uint32_t)Value);
898 		break;
899 	case 64:
900 	default:
901 		cmn_err(CE_WARN, "!AcpiOsWritePciConfiguration: %x %u failed",
902 		    Register, Width);
903 		return (AE_BAD_PARAMETER);
904 	}
905 	return (AE_OK);
906 }
907 
908 /*
909  * Called with ACPI_HANDLEs for both a PCI Config Space
910  * OpRegion and (what ACPI CA thinks is) the PCI device
911  * to which this ConfigSpace OpRegion belongs.  Since
912  * ACPI CA depends on a valid _BBN object being present
913  * and this is not always true (one old x86 had broken _BBN),
914  * we go ahead and get the correct PCI bus number using the
915  * devinfo mapping (which compensates for broken _BBN).
916  *
917  * Default values for bus, segment, device and function are
918  * all 0 when ACPI CA can't figure them out.
919  *
920  * Some BIOSes implement _BBN() by reading PCI config space
921  * on bus #0 - which means that we'll recurse when we attempt
922  * to create the devinfo-to-ACPI map.  If Derive is called during
923  * scan_d2a_map, we don't translate the bus # and return.
924  *
925  * We get the parent of the OpRegion, which must be a PCI
926  * node, fetch the associated devinfo node and snag the
927  * b/d/f from it.
928  */
929 void
930 AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle,
931 		ACPI_PCI_ID **PciId)
932 {
933 	ACPI_HANDLE handle;
934 	dev_info_t *dip;
935 	int bus, device, func, devfn;
936 
937 
938 	/*
939 	 * See above - avoid recursing during scanning_d2a_map.
940 	 */
941 	if (scanning_d2a_map)
942 		return;
943 
944 	/*
945 	 * Get the OpRegion's parent
946 	 */
947 	if (AcpiGetParent(chandle, &handle) != AE_OK)
948 		return;
949 
950 	/*
951 	 * If we've mapped the ACPI node to the devinfo
952 	 * tree, use the devinfo reg property
953 	 */
954 	if (acpica_get_devinfo(handle, &dip) == AE_OK) {
955 		(void) acpica_get_bdf(dip, &bus, &device, &func);
956 		(*PciId)->Bus = bus;
957 		(*PciId)->Device = device;
958 		(*PciId)->Function = func;
959 	} else if (acpica_eval_int(handle, "_ADR", &devfn) == AE_OK) {
960 		/* no devinfo node - just confirm the d/f */
961 		(*PciId)->Device = (devfn >> 16) & 0xFFFF;
962 		(*PciId)->Function = devfn & 0xFFFF;
963 	}
964 }
965 
966 
967 /*ARGSUSED*/
968 BOOLEAN
969 AcpiOsReadable(void *Pointer, ACPI_SIZE Length)
970 {
971 
972 	/* Always says yes; all mapped memory assumed readable */
973 	return (1);
974 }
975 
976 /*ARGSUSED*/
977 BOOLEAN
978 AcpiOsWritable(void *Pointer, ACPI_SIZE Length)
979 {
980 
981 	/* Always says yes; all mapped memory assumed writable */
982 	return (1);
983 }
984 
985 UINT64
986 AcpiOsGetTimer(void)
987 {
988 	/* gethrtime() returns 1nS resolution; convert to 100nS granules */
989 	return ((gethrtime() + 50) / 100);
990 }
991 
992 /*ARGSUSED*/
993 ACPI_STATUS
994 AcpiOsValidateInterface(char *interface)
995 {
996 	return (AE_SUPPORT);
997 }
998 
999 /*ARGSUSED*/
1000 ACPI_STATUS
1001 AcpiOsValidateAddress(UINT8 spaceid, ACPI_PHYSICAL_ADDRESS addr,
1002     ACPI_SIZE length)
1003 {
1004 	return (AE_OK);
1005 }
1006 
1007 ACPI_STATUS
1008 AcpiOsSignal(UINT32 Function, void *Info)
1009 {
1010 	_NOTE(ARGUNUSED(Function, Info))
1011 
1012 	/* FUTUREWORK: debugger support */
1013 
1014 	cmn_err(CE_NOTE, "!OsSignal unimplemented");
1015 	return (AE_OK);
1016 }
1017 
1018 void ACPI_INTERNAL_VAR_XFACE
1019 AcpiOsPrintf(const char *Format, ...)
1020 {
1021 	va_list ap;
1022 
1023 	va_start(ap, Format);
1024 	AcpiOsVprintf(Format, ap);
1025 	va_end(ap);
1026 }
1027 
1028 /*
1029  * When != 0, sends output to console
1030  * Patchable with kmdb or /etc/system.
1031  */
1032 int acpica_console_out = 0;
1033 
1034 #define	ACPICA_OUTBUF_LEN	160
1035 char	acpica_outbuf[ACPICA_OUTBUF_LEN];
1036 int	acpica_outbuf_offset;
1037 
1038 /*
1039  *
1040  */
1041 static void
1042 acpica_pr_buf(char *buf)
1043 {
1044 	char c, *bufp, *outp;
1045 	int	out_remaining;
1046 
1047 	/*
1048 	 * copy the supplied buffer into the output buffer
1049 	 * when we hit a '\n' or overflow the output buffer,
1050 	 * output and reset the output buffer
1051 	 */
1052 	bufp = buf;
1053 	outp = acpica_outbuf + acpica_outbuf_offset;
1054 	out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1;
1055 	while (c = *bufp++) {
1056 		*outp++ = c;
1057 		if (c == '\n' || --out_remaining == 0) {
1058 			*outp = '\0';
1059 			if (acpica_console_out)
1060 				printf(acpica_outbuf);
1061 			else
1062 				(void) strlog(0, 0, 0,
1063 				    SL_CONSOLE | SL_NOTE | SL_LOGONLY,
1064 				    acpica_outbuf);
1065 			acpica_outbuf_offset = 0;
1066 			outp = acpica_outbuf;
1067 			out_remaining = ACPICA_OUTBUF_LEN - 1;
1068 		}
1069 	}
1070 
1071 	acpica_outbuf_offset = outp - acpica_outbuf;
1072 }
1073 
1074 void
1075 AcpiOsVprintf(const char *Format, va_list Args)
1076 {
1077 
1078 	/*
1079 	 * If AcpiOsInitialize() failed to allocate a string buffer,
1080 	 * resort to vprintf().
1081 	 */
1082 	if (acpi_osl_pr_buffer == NULL) {
1083 		vprintf(Format, Args);
1084 		return;
1085 	}
1086 
1087 	/*
1088 	 * It is possible that a very long debug output statement will
1089 	 * be truncated; this is silently ignored.
1090 	 */
1091 	(void) vsnprintf(acpi_osl_pr_buffer, acpi_osl_pr_buflen, Format, Args);
1092 	acpica_pr_buf(acpi_osl_pr_buffer);
1093 }
1094 
1095 void
1096 AcpiOsRedirectOutput(void *Destination)
1097 {
1098 	_NOTE(ARGUNUSED(Destination))
1099 
1100 	/* FUTUREWORK: debugger support */
1101 
1102 #ifdef	DEBUG
1103 	cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called");
1104 #endif
1105 }
1106 
1107 
1108 UINT32
1109 AcpiOsGetLine(char *Buffer)
1110 {
1111 	_NOTE(ARGUNUSED(Buffer))
1112 
1113 	/* FUTUREWORK: debugger support */
1114 
1115 	return (0);
1116 }
1117 
1118 
1119 
1120 
1121 /*
1122  * Device tree binding
1123  */
1124 
1125 static int
1126 acpica_find_pcibus(int busno, ACPI_HANDLE *rh)
1127 {
1128 	ACPI_HANDLE sbobj, busobj;
1129 	int hid, bbn;
1130 
1131 	/* initialize static flag by querying ACPI namespace for bug */
1132 	if (acpi_has_broken_bbn == -1)
1133 		acpi_has_broken_bbn = acpica_query_bbn_problem();
1134 
1135 	busobj = NULL;
1136 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
1137 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
1138 	    &busobj) == AE_OK) {
1139 		if (acpica_eval_hid(busobj, "_HID", &hid) == AE_OK &&
1140 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS)) {
1141 			if (acpi_has_broken_bbn) {
1142 				ACPI_BUFFER rb;
1143 				rb.Pointer = NULL;
1144 				rb.Length = ACPI_ALLOCATE_BUFFER;
1145 
1146 				/* Decree _BBN == n from PCI<n> */
1147 				if (AcpiGetName(busobj, ACPI_SINGLE_NAME, &rb)
1148 				    != AE_OK) {
1149 					return (AE_ERROR);
1150 				}
1151 				bbn = ((char *)rb.Pointer)[3] - '0';
1152 				AcpiOsFree(rb.Pointer);
1153 				if (bbn == busno || busno == 0) {
1154 					*rh = busobj;
1155 					return (AE_OK);
1156 				}
1157 			} else {
1158 				if (acpica_eval_int(busobj, "_BBN", &bbn) ==
1159 				    AE_OK) {
1160 					if (bbn == busno) {
1161 						*rh = busobj;
1162 						return (AE_OK);
1163 					}
1164 				} else if (busno == 0) {
1165 					*rh = busobj;
1166 					return (AE_OK);
1167 				}
1168 			}
1169 		}
1170 	}
1171 	return (AE_ERROR);
1172 }
1173 
1174 
1175 /*
1176  * Look for ACPI problem where _BBN is zero for multiple PCI buses
1177  * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus()
1178  * below if it exists.
1179  */
1180 static int
1181 acpica_query_bbn_problem(void)
1182 {
1183 	ACPI_HANDLE sbobj, busobj;
1184 	int hid, bbn;
1185 	int zerobbncnt;
1186 
1187 	busobj = NULL;
1188 	zerobbncnt = 0;
1189 
1190 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
1191 
1192 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
1193 	    &busobj) == AE_OK) {
1194 		if ((acpica_eval_hid(busobj, "_HID", &hid) == AE_OK) &&
1195 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS) &&
1196 		    (acpica_eval_int(busobj, "_BBN", &bbn) == AE_OK)) {
1197 			if (bbn == 0) {
1198 			/*
1199 			 * If we find more than one bus with a 0 _BBN
1200 			 * we have the problem that BigBear's BIOS shows
1201 			 */
1202 				if (++zerobbncnt > 1)
1203 					return (1);
1204 			}
1205 		}
1206 	}
1207 	return (0);
1208 }
1209 
1210 static const char hextab[] = "0123456789ABCDEF";
1211 
1212 static int
1213 hexdig(int c)
1214 {
1215 	/*
1216 	 *  Get hex digit:
1217 	 *
1218 	 *  Returns the 4-bit hex digit named by the input character.  Returns
1219 	 *  zero if the input character is not valid hex!
1220 	 */
1221 
1222 	int x = ((c < 'a') || (c > 'z')) ? c : (c - ' ');
1223 	int j = sizeof (hextab);
1224 
1225 	while (--j && (x != hextab[j])) {
1226 	}
1227 	return (j);
1228 }
1229 
1230 static int
1231 CompressEisaID(char *np)
1232 {
1233 	/*
1234 	 *  Compress an EISA device name:
1235 	 *
1236 	 *  This routine converts a 7-byte ASCII device name into the 4-byte
1237 	 *  compressed form used by EISA (50 bytes of ROM to save 1 byte of
1238 	 *  NV-RAM!)
1239 	 */
1240 
1241 	union { char octets[4]; int retval; } myu;
1242 
1243 	myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03);
1244 	myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F);
1245 	myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]);
1246 	myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]);
1247 
1248 	return (myu.retval);
1249 }
1250 
1251 ACPI_STATUS
1252 acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint)
1253 {
1254 	ACPI_STATUS status;
1255 	ACPI_BUFFER rb;
1256 	ACPI_OBJECT ro;
1257 
1258 	rb.Pointer = &ro;
1259 	rb.Length = sizeof (ro);
1260 	if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb,
1261 	    ACPI_TYPE_INTEGER)) == AE_OK)
1262 		*rint = ro.Integer.Value;
1263 
1264 	return (status);
1265 }
1266 
1267 static int
1268 acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint)
1269 {
1270 	ACPI_BUFFER rb;
1271 	ACPI_OBJECT *rv;
1272 
1273 	rb.Pointer = NULL;
1274 	rb.Length = ACPI_ALLOCATE_BUFFER;
1275 	if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK &&
1276 	    rb.Length != 0) {
1277 		rv = rb.Pointer;
1278 		if (rv->Type == ACPI_TYPE_INTEGER) {
1279 			*rint = rv->Integer.Value;
1280 			AcpiOsFree(rv);
1281 			return (AE_OK);
1282 		} else if (rv->Type == ACPI_TYPE_STRING) {
1283 			char *stringData;
1284 
1285 			/* Convert the string into an EISA ID */
1286 			if (rv->String.Pointer == NULL) {
1287 				AcpiOsFree(rv);
1288 				return (AE_ERROR);
1289 			}
1290 
1291 			stringData = rv->String.Pointer;
1292 
1293 			/*
1294 			 * If the string is an EisaID, it must be 7
1295 			 * characters; if it's an ACPI ID, it will be 8
1296 			 * (and we don't care about ACPI ids here).
1297 			 */
1298 			if (strlen(stringData) != 7) {
1299 				AcpiOsFree(rv);
1300 				return (AE_ERROR);
1301 			}
1302 
1303 			*rint = CompressEisaID(stringData);
1304 			AcpiOsFree(rv);
1305 			return (AE_OK);
1306 		} else
1307 			AcpiOsFree(rv);
1308 	}
1309 	return (AE_ERROR);
1310 }
1311 
1312 /*
1313  * Create linkage between devinfo nodes and ACPI nodes
1314  */
1315 static void
1316 acpica_tag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj)
1317 {
1318 	ACPI_STATUS status;
1319 	ACPI_BUFFER rb;
1320 
1321 	/*
1322 	 * Tag the ACPI node with the dip
1323 	 */
1324 	status = acpica_set_devinfo(acpiobj, dip);
1325 	ASSERT(status == AE_OK);
1326 
1327 	/*
1328 	 * Tag the devinfo node with the ACPI name
1329 	 */
1330 	rb.Pointer = NULL;
1331 	rb.Length = ACPI_ALLOCATE_BUFFER;
1332 	if (AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb) == AE_OK) {
1333 		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
1334 		    "acpi-namespace", (char *)rb.Pointer);
1335 		AcpiOsFree(rb.Pointer);
1336 	} else {
1337 		cmn_err(CE_WARN, "acpica: could not get ACPI path!");
1338 	}
1339 }
1340 
1341 static void
1342 acpica_add_processor_to_map(UINT32 acpi_id, ACPI_HANDLE obj)
1343 {
1344 	int	cpu_id;
1345 
1346 	/*
1347 	 * Special case: if we're a uppc system, there won't be
1348 	 * a CPU map yet.  So we create one and use the passed-in
1349 	 * processor as CPU 0
1350 	 */
1351 	if (cpu_map == NULL) {
1352 		cpu_map = kmem_zalloc(sizeof (cpu_map[0]) * NCPU, KM_SLEEP);
1353 		cpu_map[0] = kmem_zalloc(sizeof (*cpu_map[0]), KM_SLEEP);
1354 		cpu_map[0]->obj = obj;
1355 		cpu_map_count = 1;
1356 		return;
1357 	}
1358 
1359 	for (cpu_id = 0; cpu_id < NCPU; cpu_id++) {
1360 		if (cpu_map[cpu_id] == NULL)
1361 			continue;
1362 
1363 		if (cpu_map[cpu_id]->proc_id == acpi_id) {
1364 			if (cpu_map[cpu_id]->obj == NULL)
1365 				cpu_map[cpu_id]->obj = obj;
1366 			break;
1367 		}
1368 	}
1369 
1370 }
1371 
1372 /*
1373  * Return the ACPI device node matching the CPU dev_info node.
1374  */
1375 ACPI_STATUS
1376 acpica_get_handle_cpu(int cpu_id, ACPI_HANDLE *rh)
1377 {
1378 	/*
1379 	 * if cpu_map itself is NULL, we're a uppc system and
1380 	 * acpica_build_processor_map() hasn't been called yet.
1381 	 * So call it here
1382 	 */
1383 	if (cpu_map == NULL) {
1384 		(void) acpica_build_processor_map();
1385 		if (cpu_map == NULL)
1386 			return (AE_ERROR);
1387 	}
1388 
1389 	if ((cpu_id < 0) || (cpu_map[cpu_id] == NULL) ||
1390 	    (cpu_map[cpu_id]->obj == NULL))
1391 		return (AE_ERROR);
1392 
1393 	*rh = cpu_map[cpu_id]->obj;
1394 	return (AE_OK);
1395 }
1396 
1397 /*
1398  * Convert CPU device _UID strings into unique integers
1399  * ACPI 3.0 spec 6.1.9 permits _UID to be either
1400  * an arbitrary string or numeric value.  ACPI CA converts
1401  * numeric types to a string, providing a consistent API,
1402  * but it can not be assumed that _UID is always numeric.
1403  * Keep a private list of CPU _UIDs and convert them to
1404  * an integer representation.
1405  */
1406 
1407 struct acpica_cpu_uid {
1408 	struct acpica_cpu_uid *next;
1409 	char *uid;
1410 };
1411 
1412 static struct acpica_cpu_uid *acpica_cpu_uid_list = NULL;
1413 
1414 static UINT32
1415 acpica_cpu_uid_str_to_uint(char *uidstr)
1416 {
1417 	UINT32	n;
1418 	struct acpica_cpu_uid *current, **tail;
1419 
1420 	ASSERT(uidstr != NULL);
1421 
1422 	n = 0;
1423 	current = acpica_cpu_uid_list;
1424 	tail = &acpica_cpu_uid_list;
1425 	while (current != NULL) {
1426 		if (strcmp(current->uid, uidstr) == 0)
1427 			break;
1428 		n++;
1429 		tail = &current->next;
1430 		current = current->next;
1431 	}
1432 
1433 	/*
1434 	 * failed to find a matching element; create it here
1435 	 */
1436 	if (current == NULL) {
1437 		/* allocate new list element as current one */
1438 		current = (struct acpica_cpu_uid *)kmem_zalloc(
1439 		    sizeof (struct acpica_cpu_uid), KM_SLEEP);
1440 
1441 		/* allocate storage for the device ID string */
1442 		current->uid = (char *)kmem_zalloc(strlen(uidstr) + 1,
1443 		    KM_SLEEP);
1444 
1445 		strcpy(current->uid, uidstr);
1446 		*tail = current;
1447 	}
1448 
1449 	/*
1450 	 * 'n' correctly contains the index for either
1451 	 * a new element or an existing element
1452 	 */
1453 	return (n);
1454 }
1455 
1456 /*
1457  * Determine if this object is a processor
1458  */
1459 static ACPI_STATUS
1460 acpica_probe_processor(ACPI_HANDLE obj, UINT32 level, void *ctx, void **rv)
1461 {
1462 	ACPI_STATUS status;
1463 	ACPI_OBJECT_TYPE objtype;
1464 	UINT32 acpi_id;
1465 	ACPI_BUFFER rb;
1466 
1467 	if (AcpiGetType(obj, &objtype) != AE_OK)
1468 		return (AE_OK);
1469 
1470 	if (objtype == ACPI_TYPE_PROCESSOR) {
1471 		/* process a Processor */
1472 		rb.Pointer = NULL;
1473 		rb.Length = ACPI_ALLOCATE_BUFFER;
1474 		status = AcpiEvaluateObjectTyped(obj, NULL, NULL, &rb,
1475 		    ACPI_TYPE_PROCESSOR);
1476 		if (status != AE_OK) {
1477 			cmn_err(CE_WARN, "acpica: error probing Processor");
1478 			return (status);
1479 		}
1480 		acpi_id = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId;
1481 		AcpiOsFree(rb.Pointer);
1482 	} else if (objtype == ACPI_TYPE_DEVICE) {
1483 		/* process a processor Device */
1484 		rb.Pointer = NULL;
1485 		rb.Length = ACPI_ALLOCATE_BUFFER;
1486 		status = AcpiGetObjectInfo(obj, &rb);
1487 		if (status != AE_OK) {
1488 			cmn_err(CE_WARN,
1489 			    "acpica: error probing Processor Device\n");
1490 			return (status);
1491 		}
1492 		ASSERT(((ACPI_OBJECT *)rb.Pointer)->Type ==
1493 		    ACPI_TYPE_DEVICE);
1494 		acpi_id = acpica_cpu_uid_str_to_uint(
1495 		    ((ACPI_DEVICE_INFO *)rb.Pointer)->UniqueId.Value);
1496 		AcpiOsFree(rb.Pointer);
1497 	}
1498 
1499 	acpica_add_processor_to_map(acpi_id, obj);
1500 	return (AE_OK);
1501 }
1502 
1503 
1504 static void
1505 scan_d2a_map(void)
1506 {
1507 	dev_info_t *dip, *cdip;
1508 	ACPI_HANDLE acpiobj;
1509 	char *device_type_prop;
1510 	int bus;
1511 	static int map_error = 0;
1512 
1513 	if (map_error)
1514 		return;
1515 
1516 	scanning_d2a_map = 1;
1517 
1518 	/*
1519 	 * Find all child-of-root PCI buses, and find their corresponding
1520 	 * ACPI child-of-root PCI nodes.  For each one, add to the
1521 	 * d2a table.
1522 	 */
1523 
1524 	for (dip = ddi_get_child(ddi_root_node());
1525 	    dip != NULL;
1526 	    dip = ddi_get_next_sibling(dip)) {
1527 
1528 		/* prune non-PCI nodes */
1529 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
1530 		    "device_type", &device_type_prop) != DDI_PROP_SUCCESS)
1531 			continue;
1532 
1533 		if ((strcmp("pci", device_type_prop) != 0) &&
1534 		    (strcmp("pciex", device_type_prop) != 0)) {
1535 			ddi_prop_free(device_type_prop);
1536 			continue;
1537 		}
1538 
1539 		ddi_prop_free(device_type_prop);
1540 
1541 		/*
1542 		 * To get bus number of dip, get first child and get its
1543 		 * bus number.  If NULL, just continue, because we don't
1544 		 * care about bus nodes with no children anyway.
1545 		 */
1546 		if ((cdip = ddi_get_child(dip)) == NULL)
1547 			continue;
1548 
1549 		if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) {
1550 #ifdef D2ADEBUG
1551 			cmn_err(CE_WARN, "Can't get bus number of PCI child?");
1552 #endif
1553 			map_error = 1;
1554 			scanning_d2a_map = 0;
1555 			d2a_done = 1;
1556 			return;
1557 		}
1558 
1559 		if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) {
1560 #ifdef D2ADEBUG
1561 			cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus);
1562 #endif
1563 			map_error = 1;
1564 			continue;
1565 		}
1566 
1567 		acpica_tag_devinfo(dip, acpiobj);
1568 
1569 		/* call recursively to enumerate subtrees */
1570 		scan_d2a_subtree(dip, acpiobj, bus);
1571 	}
1572 
1573 	scanning_d2a_map = 0;
1574 	d2a_done = 1;
1575 }
1576 
1577 /*
1578  * For all acpi child devices of acpiobj, find their matching
1579  * dip under "dip" argument.  (matching means "matches dev/fn").
1580  * bus is assumed to already be a match from caller, and is
1581  * used here only to record in the d2a entry.  Recurse if necessary.
1582  */
1583 static void
1584 scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus)
1585 {
1586 	int acpi_devfn, hid;
1587 	ACPI_HANDLE acld;
1588 	dev_info_t *dcld;
1589 	int dcld_b, dcld_d, dcld_f;
1590 	int dev, func;
1591 	char *device_type_prop;
1592 
1593 	acld = NULL;
1594 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld)
1595 	    == AE_OK) {
1596 		/* get the dev/func we're looking for in the devinfo tree */
1597 		if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK)
1598 			continue;
1599 		dev = (acpi_devfn >> 16) & 0xFFFF;
1600 		func = acpi_devfn & 0xFFFF;
1601 
1602 		/* look through all the immediate children of dip */
1603 		for (dcld = ddi_get_child(dip); dcld != NULL;
1604 		    dcld = ddi_get_next_sibling(dcld)) {
1605 			if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0)
1606 				continue;
1607 
1608 			/* dev must match; function must match or wildcard */
1609 			if (dcld_d != dev ||
1610 			    (func != 0xFFFF && func != dcld_f))
1611 				continue;
1612 			bus = dcld_b;
1613 
1614 			/* found a match, record it */
1615 			acpica_tag_devinfo(dcld, acld);
1616 
1617 			/* if we find a bridge, recurse from here */
1618 			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dcld, 0,
1619 			    "device_type", &device_type_prop) ==
1620 			    DDI_PROP_SUCCESS) {
1621 				if ((strcmp("pci", device_type_prop) == 0) ||
1622 				    (strcmp("pciex", device_type_prop) == 0))
1623 					scan_d2a_subtree(dcld, acld, bus);
1624 				ddi_prop_free(device_type_prop);
1625 			}
1626 
1627 			/* done finding a match, so break now */
1628 			break;
1629 		}
1630 	}
1631 }
1632 
1633 /*
1634  * Return bus/dev/fn for PCI dip (note: not the parent "pci" node).
1635  */
1636 int
1637 acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func)
1638 {
1639 	pci_regspec_t *pci_rp;
1640 	int len;
1641 
1642 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1643 	    "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS)
1644 		return (-1);
1645 
1646 	if (len < (sizeof (pci_regspec_t) / sizeof (int))) {
1647 		ddi_prop_free(pci_rp);
1648 		return (-1);
1649 	}
1650 	if (bus != NULL)
1651 		*bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1652 	if (device != NULL)
1653 		*device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1654 	if (func != NULL)
1655 		*func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1656 	ddi_prop_free(pci_rp);
1657 	return (0);
1658 }
1659 
1660 /*
1661  * Return the ACPI device node matching this dev_info node, if it
1662  * exists in the ACPI tree.
1663  */
1664 ACPI_STATUS
1665 acpica_get_handle(dev_info_t *dip, ACPI_HANDLE *rh)
1666 {
1667 	ACPI_STATUS status;
1668 	char *acpiname;
1669 
1670 	if (!d2a_done)
1671 		scan_d2a_map();
1672 
1673 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1674 	    "acpi-namespace", &acpiname) != DDI_PROP_SUCCESS) {
1675 		return (AE_ERROR);
1676 	}
1677 
1678 	status = AcpiGetHandle(NULL, acpiname, rh);
1679 	ddi_prop_free((void *)acpiname);
1680 	return (status);
1681 }
1682 
1683 
1684 
1685 /*
1686  * Manage OS data attachment to ACPI nodes
1687  */
1688 
1689 /*
1690  * Return the (dev_info_t *) associated with the ACPI node.
1691  */
1692 ACPI_STATUS
1693 acpica_get_devinfo(ACPI_HANDLE obj, dev_info_t **dipp)
1694 {
1695 	ACPI_STATUS status;
1696 	void *ptr;
1697 
1698 	status = AcpiGetData(obj, acpica_devinfo_handler, &ptr);
1699 	if (status == AE_OK)
1700 		*dipp = (dev_info_t *)ptr;
1701 
1702 	return (status);
1703 }
1704 
1705 /*
1706  * Set the dev_info_t associated with the ACPI node.
1707  */
1708 static ACPI_STATUS
1709 acpica_set_devinfo(ACPI_HANDLE obj, dev_info_t *dip)
1710 {
1711 	ACPI_STATUS status;
1712 
1713 	status = AcpiAttachData(obj, acpica_devinfo_handler, (void *)dip);
1714 	return (status);
1715 }
1716 
1717 
1718 /*
1719  *
1720  */
1721 void
1722 acpica_devinfo_handler(ACPI_HANDLE obj, UINT32 func, void *data)
1723 {
1724 	/* noop */
1725 }
1726 
1727 
1728 /*
1729  *
1730  */
1731 void
1732 acpica_map_cpu(processorid_t cpuid, UINT32 proc_id)
1733 {
1734 	struct cpu_map_item *item;
1735 
1736 	if (cpu_map == NULL)
1737 		cpu_map = kmem_zalloc(sizeof (item) * NCPU, KM_SLEEP);
1738 
1739 	item = kmem_zalloc(sizeof (*item), KM_SLEEP);
1740 	item->proc_id = proc_id;
1741 	item->obj = NULL;
1742 	cpu_map[cpuid] = item;
1743 	cpu_map_count++;
1744 }
1745 
1746 void
1747 acpica_build_processor_map()
1748 {
1749 	ACPI_STATUS status;
1750 	void *rv;
1751 
1752 	/*
1753 	 * shouldn't be called more than once anyway
1754 	 */
1755 	if (cpu_map_built)
1756 		return;
1757 
1758 	/*
1759 	 * Look for Processor objects
1760 	 */
1761 	status = AcpiWalkNamespace(ACPI_TYPE_PROCESSOR,
1762 	    ACPI_ROOT_OBJECT,
1763 	    4,
1764 	    acpica_probe_processor,
1765 	    NULL,
1766 	    &rv);
1767 	ASSERT(status == AE_OK);
1768 
1769 	/*
1770 	 * Look for processor Device objects
1771 	 */
1772 	status = AcpiGetDevices("ACPI0007",
1773 	    acpica_probe_processor,
1774 	    NULL,
1775 	    &rv);
1776 	ASSERT(status == AE_OK);
1777 	cpu_map_built = 1;
1778 }
1779 
1780 void
1781 acpica_get_global_FADT(ACPI_TABLE_FADT **gbl_FADT)
1782 {
1783 	*gbl_FADT = &AcpiGbl_FADT;
1784 }
1785