xref: /titanic_51/usr/src/uts/intel/io/acpica/osl.c (revision 53a7b6b6763f5865522a76e5e887390a8f4777d7)
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 2008 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 	mutex_enter((kmutex_t *)Handle);
478 	return (0);
479 }
480 
481 void
482 AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_CPU_FLAGS Flags)
483 {
484 	_NOTE(ARGUNUSED(Flags))
485 
486 	mutex_exit((kmutex_t *)Handle);
487 }
488 
489 
490 void *
491 AcpiOsAllocate(ACPI_SIZE Size)
492 {
493 	ACPI_SIZE *tmp_ptr;
494 
495 	Size += sizeof (Size);
496 	tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP);
497 	*tmp_ptr++ = Size;
498 	return (tmp_ptr);
499 }
500 
501 void
502 AcpiOsFree(void *Memory)
503 {
504 	ACPI_SIZE	size, *tmp_ptr;
505 
506 	tmp_ptr = (ACPI_SIZE *)Memory;
507 	tmp_ptr -= 1;
508 	size = *tmp_ptr;
509 	kmem_free(tmp_ptr, size);
510 }
511 
512 void *
513 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size)
514 {
515 	/* FUTUREWORK: test PhysicalAddress for > 32 bits */
516 	return (psm_map_new((paddr_t)PhysicalAddress,
517 	    (size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ));
518 }
519 
520 void
521 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
522 {
523 
524 	psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
525 }
526 
527 /*ARGSUSED*/
528 ACPI_STATUS
529 AcpiOsGetPhysicalAddress(void *LogicalAddress,
530 			ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
531 {
532 
533 	/* UNIMPLEMENTED: not invoked by ACPI CA code */
534 	return (AE_NOT_IMPLEMENTED);
535 }
536 
537 
538 ACPI_OSD_HANDLER acpi_isr;
539 void *acpi_isr_context;
540 
541 uint_t
542 acpi_wrapper_isr(char *arg)
543 {
544 	_NOTE(ARGUNUSED(arg))
545 
546 	int	status;
547 
548 	status = (*acpi_isr)(acpi_isr_context);
549 
550 	if (status == ACPI_INTERRUPT_HANDLED) {
551 		return (DDI_INTR_CLAIMED);
552 	} else {
553 		return (DDI_INTR_UNCLAIMED);
554 	}
555 }
556 
557 static int acpi_intr_hooked = 0;
558 
559 ACPI_STATUS
560 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
561 		ACPI_OSD_HANDLER ServiceRoutine,
562 		void *Context)
563 {
564 	_NOTE(ARGUNUSED(InterruptNumber))
565 
566 	int retval;
567 	int sci_vect;
568 	iflag_t sci_flags;
569 
570 	acpi_isr = ServiceRoutine;
571 	acpi_isr_context = Context;
572 
573 	/*
574 	 * Get SCI (adjusted for PIC/APIC mode if necessary)
575 	 */
576 	if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) {
577 		return (AE_ERROR);
578 	}
579 
580 #ifdef	DEBUG
581 	cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect);
582 #endif
583 
584 	retval = add_avintr(NULL, SCI_IPL, (avfunc)acpi_wrapper_isr,
585 	    "ACPI SCI", sci_vect, NULL, NULL, NULL, NULL);
586 	if (retval) {
587 		acpi_intr_hooked = 1;
588 		return (AE_OK);
589 	} else
590 		return (AE_BAD_PARAMETER);
591 }
592 
593 ACPI_STATUS
594 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
595 			ACPI_OSD_HANDLER ServiceRoutine)
596 {
597 	_NOTE(ARGUNUSED(ServiceRoutine))
598 
599 #ifdef	DEBUG
600 	cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber);
601 #endif
602 	if (acpi_intr_hooked) {
603 		rem_avintr(NULL, LOCK_LEVEL - 1, (avfunc)acpi_wrapper_isr,
604 		    InterruptNumber);
605 		acpi_intr_hooked = 0;
606 	}
607 	return (AE_OK);
608 }
609 
610 
611 ACPI_THREAD_ID
612 AcpiOsGetThreadId(void)
613 {
614 	/*
615 	 * ACPI CA regards thread ID as an error, but it's valid
616 	 * on Solaris during kernel initialization.  Thus, 1 is added
617 	 * to the kernel thread ID to avoid returning 0
618 	 */
619 	return (ddi_get_kt_did() + 1);
620 }
621 
622 /*
623  *
624  */
625 ACPI_STATUS
626 AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK  Function,
627     void *Context)
628 {
629 
630 	if (!acpica_eventq_init) {
631 		/*
632 		 * Create taskqs for event handling
633 		 */
634 		if (init_event_queues() != AE_OK)
635 			return (AE_ERROR);
636 	}
637 
638 	if (ddi_taskq_dispatch(osl_eventq[Type], Function, Context,
639 	    DDI_NOSLEEP) == DDI_FAILURE) {
640 #ifdef	DEBUG
641 		cmn_err(CE_WARN, "!acpica: unable to dispatch event");
642 #endif
643 		return (AE_ERROR);
644 	}
645 	return (AE_OK);
646 
647 }
648 
649 void
650 AcpiOsSleep(ACPI_INTEGER Milliseconds)
651 {
652 	/*
653 	 * During kernel startup, before the first tick interrupt
654 	 * has taken place, we can't call delay; very late in
655 	 * kernel shutdown or suspend/resume, clock interrupts
656 	 * are blocked, so delay doesn't work then either.
657 	 * So we busy wait if lbolt == 0 (kernel startup)
658 	 * or if acpica_use_safe_delay has been set to a
659 	 * non-zero value.
660 	 */
661 	if ((ddi_get_lbolt() == 0) || acpica_use_safe_delay)
662 		drv_usecwait(Milliseconds * 1000);
663 	else
664 		delay(drv_usectohz(Milliseconds * 1000));
665 }
666 
667 void
668 AcpiOsStall(UINT32 Microseconds)
669 {
670 	drv_usecwait(Microseconds);
671 }
672 
673 
674 /*
675  * Implementation of "Windows 2001" compatible I/O permission map
676  *
677  */
678 #define	OSL_IO_NONE	(0)
679 #define	OSL_IO_READ	(1<<0)
680 #define	OSL_IO_WRITE	(1<<1)
681 #define	OSL_IO_RW	(OSL_IO_READ | OSL_IO_WRITE)
682 #define	OSL_IO_TERM	(1<<2)
683 #define	OSL_IO_DEFAULT	OSL_IO_RW
684 
685 static struct io_perm  {
686 	ACPI_IO_ADDRESS	low;
687 	ACPI_IO_ADDRESS	high;
688 	uint8_t		perm;
689 } osl_io_perm[] = {
690 	{ 0xcf8, 0xd00, OSL_IO_NONE | OSL_IO_TERM }
691 };
692 
693 
694 /*
695  *
696  */
697 static struct io_perm *
698 osl_io_find_perm(ACPI_IO_ADDRESS addr)
699 {
700 	struct io_perm *p;
701 
702 	p = osl_io_perm;
703 	while (p != NULL) {
704 		if ((p->low <= addr) && (addr <= p->high))
705 			break;
706 		p = (p->perm & OSL_IO_TERM) ? NULL : p+1;
707 	}
708 
709 	return (p);
710 }
711 
712 /*
713  *
714  */
715 ACPI_STATUS
716 AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
717 {
718 	struct io_perm *p;
719 
720 	/* verify permission */
721 	p = osl_io_find_perm(Address);
722 	if (p && (p->perm & OSL_IO_READ) == 0) {
723 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted",
724 		    (long)Address, Width);
725 		*Value = 0xffffffff;
726 		return (AE_ERROR);
727 	}
728 
729 	switch (Width) {
730 	case 8:
731 		*Value = inb(Address);
732 		break;
733 	case 16:
734 		*Value = inw(Address);
735 		break;
736 	case 32:
737 		*Value = inl(Address);
738 		break;
739 	default:
740 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed",
741 		    (long)Address, Width);
742 		return (AE_BAD_PARAMETER);
743 	}
744 	return (AE_OK);
745 }
746 
747 ACPI_STATUS
748 AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
749 {
750 	struct io_perm *p;
751 
752 	/* verify permission */
753 	p = osl_io_find_perm(Address);
754 	if (p && (p->perm & OSL_IO_WRITE) == 0) {
755 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted",
756 		    (long)Address, Width);
757 		return (AE_ERROR);
758 	}
759 
760 	switch (Width) {
761 	case 8:
762 		outb(Address, Value);
763 		break;
764 	case 16:
765 		outw(Address, Value);
766 		break;
767 	case 32:
768 		outl(Address, Value);
769 		break;
770 	default:
771 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed",
772 		    (long)Address, Width);
773 		return (AE_BAD_PARAMETER);
774 	}
775 	return (AE_OK);
776 }
777 
778 
779 /*
780  *
781  */
782 
783 #define	OSL_RW(ptr, val, type, rw) \
784 	{ if (rw) *((type *)(ptr)) = *((type *) val); \
785 	    else *((type *) val) = *((type *)(ptr)); }
786 
787 
788 static void
789 osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value,
790     UINT32 Width, int write)
791 {
792 	size_t	maplen = Width / 8;
793 	caddr_t	ptr;
794 
795 	ptr = psm_map_new((paddr_t)Address, maplen,
796 	    PSM_PROT_WRITE | PSM_PROT_READ);
797 
798 	switch (maplen) {
799 	case 1:
800 		OSL_RW(ptr, Value, uint8_t, write);
801 		break;
802 	case 2:
803 		OSL_RW(ptr, Value, uint16_t, write);
804 		break;
805 	case 4:
806 		OSL_RW(ptr, Value, uint32_t, write);
807 		break;
808 	default:
809 		cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d",
810 		    Width);
811 		break;
812 	}
813 
814 	psm_unmap(ptr, maplen);
815 }
816 
817 ACPI_STATUS
818 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,
819 		UINT32 *Value, UINT32 Width)
820 {
821 	osl_rw_memory(Address, Value, Width, 0);
822 	return (AE_OK);
823 }
824 
825 ACPI_STATUS
826 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,
827 		UINT32 Value, UINT32 Width)
828 {
829 	osl_rw_memory(Address, &Value, Width, 1);
830 	return (AE_OK);
831 }
832 
833 
834 ACPI_STATUS
835 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
836 			void *Value, UINT32 Width)
837 {
838 
839 	switch (Width) {
840 	case 8:
841 		*((UINT64 *)Value) = (UINT64)(*pci_getb_func)
842 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
843 		break;
844 	case 16:
845 		*((UINT64 *)Value) = (UINT64)(*pci_getw_func)
846 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
847 		break;
848 	case 32:
849 		*((UINT64 *)Value) = (UINT64)(*pci_getl_func)
850 		    (PciId->Bus, PciId->Device, PciId->Function, Register);
851 		break;
852 	case 64:
853 	default:
854 		cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed",
855 		    Register, Width);
856 		return (AE_BAD_PARAMETER);
857 	}
858 	return (AE_OK);
859 }
860 
861 /*
862  *
863  */
864 int acpica_write_pci_config_ok = 1;
865 
866 ACPI_STATUS
867 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
868 		ACPI_INTEGER Value, UINT32 Width)
869 {
870 
871 	if (!acpica_write_pci_config_ok) {
872 		cmn_err(CE_NOTE, "!write to PCI cfg %x/%x/%x %x"
873 		    " %lx %d not permitted", PciId->Bus, PciId->Device,
874 		    PciId->Function, Register, (long)Value, Width);
875 		return (AE_OK);
876 	}
877 
878 	switch (Width) {
879 	case 8:
880 		(*pci_putb_func)(PciId->Bus, PciId->Device, PciId->Function,
881 		    Register, (uint8_t)Value);
882 		break;
883 	case 16:
884 		(*pci_putw_func)(PciId->Bus, PciId->Device, PciId->Function,
885 		    Register, (uint16_t)Value);
886 		break;
887 	case 32:
888 		(*pci_putl_func)(PciId->Bus, PciId->Device, PciId->Function,
889 		    Register, (uint32_t)Value);
890 		break;
891 	case 64:
892 	default:
893 		cmn_err(CE_WARN, "!AcpiOsWritePciConfiguration: %x %u failed",
894 		    Register, Width);
895 		return (AE_BAD_PARAMETER);
896 	}
897 	return (AE_OK);
898 }
899 
900 /*
901  * Called with ACPI_HANDLEs for both a PCI Config Space
902  * OpRegion and (what ACPI CA thinks is) the PCI device
903  * to which this ConfigSpace OpRegion belongs.  Since
904  * ACPI CA depends on a valid _BBN object being present
905  * and this is not always true (one old x86 had broken _BBN),
906  * we go ahead and get the correct PCI bus number using the
907  * devinfo mapping (which compensates for broken _BBN).
908  *
909  * Default values for bus, segment, device and function are
910  * all 0 when ACPI CA can't figure them out.
911  *
912  * Some BIOSes implement _BBN() by reading PCI config space
913  * on bus #0 - which means that we'll recurse when we attempt
914  * to create the devinfo-to-ACPI map.  If Derive is called during
915  * scan_d2a_map, we don't translate the bus # and return.
916  *
917  * We get the parent of the OpRegion, which must be a PCI
918  * node, fetch the associated devinfo node and snag the
919  * b/d/f from it.
920  */
921 void
922 AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle,
923 		ACPI_PCI_ID **PciId)
924 {
925 	ACPI_HANDLE handle;
926 	dev_info_t *dip;
927 	int bus, device, func, devfn;
928 
929 
930 	/*
931 	 * See above - avoid recursing during scanning_d2a_map.
932 	 */
933 	if (scanning_d2a_map)
934 		return;
935 
936 	/*
937 	 * Get the OpRegion's parent
938 	 */
939 	if (AcpiGetParent(chandle, &handle) != AE_OK)
940 		return;
941 
942 	/*
943 	 * If we've mapped the ACPI node to the devinfo
944 	 * tree, use the devinfo reg property
945 	 */
946 	if (acpica_get_devinfo(handle, &dip) == AE_OK) {
947 		(void) acpica_get_bdf(dip, &bus, &device, &func);
948 		(*PciId)->Bus = bus;
949 		(*PciId)->Device = device;
950 		(*PciId)->Function = func;
951 	} else if (acpica_eval_int(handle, "_ADR", &devfn) == AE_OK) {
952 		/* no devinfo node - just confirm the d/f */
953 		(*PciId)->Device = (devfn >> 16) & 0xFFFF;
954 		(*PciId)->Function = devfn & 0xFFFF;
955 	}
956 }
957 
958 
959 /*ARGSUSED*/
960 BOOLEAN
961 AcpiOsReadable(void *Pointer, ACPI_SIZE Length)
962 {
963 
964 	/* Always says yes; all mapped memory assumed readable */
965 	return (1);
966 }
967 
968 /*ARGSUSED*/
969 BOOLEAN
970 AcpiOsWritable(void *Pointer, ACPI_SIZE Length)
971 {
972 
973 	/* Always says yes; all mapped memory assumed writable */
974 	return (1);
975 }
976 
977 UINT64
978 AcpiOsGetTimer(void)
979 {
980 	/* gethrtime() returns 1nS resolution; convert to 100nS granules */
981 	return ((gethrtime() + 50) / 100);
982 }
983 
984 /*ARGSUSED*/
985 ACPI_STATUS
986 AcpiOsValidateInterface(char *interface)
987 {
988 	return (AE_SUPPORT);
989 }
990 
991 /*ARGSUSED*/
992 ACPI_STATUS
993 AcpiOsValidateAddress(UINT8 spaceid, ACPI_PHYSICAL_ADDRESS addr,
994     ACPI_SIZE length)
995 {
996 	return (AE_OK);
997 }
998 
999 ACPI_STATUS
1000 AcpiOsSignal(UINT32 Function, void *Info)
1001 {
1002 	_NOTE(ARGUNUSED(Function, Info))
1003 
1004 	/* FUTUREWORK: debugger support */
1005 
1006 	cmn_err(CE_NOTE, "!OsSignal unimplemented");
1007 	return (AE_OK);
1008 }
1009 
1010 void ACPI_INTERNAL_VAR_XFACE
1011 AcpiOsPrintf(const char *Format, ...)
1012 {
1013 	va_list ap;
1014 
1015 	va_start(ap, Format);
1016 	AcpiOsVprintf(Format, ap);
1017 	va_end(ap);
1018 }
1019 
1020 /*
1021  * When != 0, sends output to console
1022  * Patchable with kmdb or /etc/system.
1023  */
1024 int acpica_console_out = 0;
1025 
1026 #define	ACPICA_OUTBUF_LEN	160
1027 char	acpica_outbuf[ACPICA_OUTBUF_LEN];
1028 int	acpica_outbuf_offset;
1029 
1030 /*
1031  *
1032  */
1033 static void
1034 acpica_pr_buf(char *buf)
1035 {
1036 	char c, *bufp, *outp;
1037 	int	out_remaining;
1038 
1039 	/*
1040 	 * copy the supplied buffer into the output buffer
1041 	 * when we hit a '\n' or overflow the output buffer,
1042 	 * output and reset the output buffer
1043 	 */
1044 	bufp = buf;
1045 	outp = acpica_outbuf + acpica_outbuf_offset;
1046 	out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1;
1047 	while (c = *bufp++) {
1048 		*outp++ = c;
1049 		if (c == '\n' || --out_remaining == 0) {
1050 			*outp = '\0';
1051 			if (acpica_console_out)
1052 				printf(acpica_outbuf);
1053 			else
1054 				(void) strlog(0, 0, 0,
1055 				    SL_CONSOLE | SL_NOTE | SL_LOGONLY,
1056 				    acpica_outbuf);
1057 			acpica_outbuf_offset = 0;
1058 			outp = acpica_outbuf;
1059 			out_remaining = ACPICA_OUTBUF_LEN - 1;
1060 		}
1061 	}
1062 
1063 	acpica_outbuf_offset = outp - acpica_outbuf;
1064 }
1065 
1066 void
1067 AcpiOsVprintf(const char *Format, va_list Args)
1068 {
1069 
1070 	/*
1071 	 * If AcpiOsInitialize() failed to allocate a string buffer,
1072 	 * resort to vprintf().
1073 	 */
1074 	if (acpi_osl_pr_buffer == NULL) {
1075 		vprintf(Format, Args);
1076 		return;
1077 	}
1078 
1079 	/*
1080 	 * It is possible that a very long debug output statement will
1081 	 * be truncated; this is silently ignored.
1082 	 */
1083 	(void) vsnprintf(acpi_osl_pr_buffer, acpi_osl_pr_buflen, Format, Args);
1084 	acpica_pr_buf(acpi_osl_pr_buffer);
1085 }
1086 
1087 void
1088 AcpiOsRedirectOutput(void *Destination)
1089 {
1090 	_NOTE(ARGUNUSED(Destination))
1091 
1092 	/* FUTUREWORK: debugger support */
1093 
1094 #ifdef	DEBUG
1095 	cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called");
1096 #endif
1097 }
1098 
1099 
1100 UINT32
1101 AcpiOsGetLine(char *Buffer)
1102 {
1103 	_NOTE(ARGUNUSED(Buffer))
1104 
1105 	/* FUTUREWORK: debugger support */
1106 
1107 	return (0);
1108 }
1109 
1110 
1111 
1112 
1113 /*
1114  * Device tree binding
1115  */
1116 
1117 static int
1118 acpica_find_pcibus(int busno, ACPI_HANDLE *rh)
1119 {
1120 	ACPI_HANDLE sbobj, busobj;
1121 	int hid, bbn;
1122 
1123 	/* initialize static flag by querying ACPI namespace for bug */
1124 	if (acpi_has_broken_bbn == -1)
1125 		acpi_has_broken_bbn = acpica_query_bbn_problem();
1126 
1127 	busobj = NULL;
1128 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
1129 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
1130 	    &busobj) == AE_OK) {
1131 		if (acpica_eval_hid(busobj, "_HID", &hid) == AE_OK &&
1132 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS)) {
1133 			if (acpi_has_broken_bbn) {
1134 				ACPI_BUFFER rb;
1135 				rb.Pointer = NULL;
1136 				rb.Length = ACPI_ALLOCATE_BUFFER;
1137 
1138 				/* Decree _BBN == n from PCI<n> */
1139 				if (AcpiGetName(busobj, ACPI_SINGLE_NAME, &rb)
1140 				    != AE_OK) {
1141 					return (AE_ERROR);
1142 				}
1143 				bbn = ((char *)rb.Pointer)[3] - '0';
1144 				AcpiOsFree(rb.Pointer);
1145 				if (bbn == busno || busno == 0) {
1146 					*rh = busobj;
1147 					return (AE_OK);
1148 				}
1149 			} else {
1150 				if (acpica_eval_int(busobj, "_BBN", &bbn) ==
1151 				    AE_OK) {
1152 					if (bbn == busno) {
1153 						*rh = busobj;
1154 						return (AE_OK);
1155 					}
1156 				} else if (busno == 0) {
1157 					*rh = busobj;
1158 					return (AE_OK);
1159 				}
1160 			}
1161 		}
1162 	}
1163 	return (AE_ERROR);
1164 }
1165 
1166 
1167 /*
1168  * Look for ACPI problem where _BBN is zero for multiple PCI buses
1169  * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus()
1170  * below if it exists.
1171  */
1172 static int
1173 acpica_query_bbn_problem(void)
1174 {
1175 	ACPI_HANDLE sbobj, busobj;
1176 	int hid, bbn;
1177 	int zerobbncnt;
1178 
1179 	busobj = NULL;
1180 	zerobbncnt = 0;
1181 
1182 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
1183 
1184 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
1185 	    &busobj) == AE_OK) {
1186 		if ((acpica_eval_hid(busobj, "_HID", &hid) == AE_OK) &&
1187 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS) &&
1188 		    (acpica_eval_int(busobj, "_BBN", &bbn) == AE_OK)) {
1189 			if (bbn == 0) {
1190 			/*
1191 			 * If we find more than one bus with a 0 _BBN
1192 			 * we have the problem that BigBear's BIOS shows
1193 			 */
1194 				if (++zerobbncnt > 1)
1195 					return (1);
1196 			}
1197 		}
1198 	}
1199 	return (0);
1200 }
1201 
1202 static const char hextab[] = "0123456789ABCDEF";
1203 
1204 static int
1205 hexdig(int c)
1206 {
1207 	/*
1208 	 *  Get hex digit:
1209 	 *
1210 	 *  Returns the 4-bit hex digit named by the input character.  Returns
1211 	 *  zero if the input character is not valid hex!
1212 	 */
1213 
1214 	int x = ((c < 'a') || (c > 'z')) ? c : (c - ' ');
1215 	int j = sizeof (hextab);
1216 
1217 	while (--j && (x != hextab[j])) {
1218 	}
1219 	return (j);
1220 }
1221 
1222 static int
1223 CompressEisaID(char *np)
1224 {
1225 	/*
1226 	 *  Compress an EISA device name:
1227 	 *
1228 	 *  This routine converts a 7-byte ASCII device name into the 4-byte
1229 	 *  compressed form used by EISA (50 bytes of ROM to save 1 byte of
1230 	 *  NV-RAM!)
1231 	 */
1232 
1233 	union { char octets[4]; int retval; } myu;
1234 
1235 	myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03);
1236 	myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F);
1237 	myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]);
1238 	myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]);
1239 
1240 	return (myu.retval);
1241 }
1242 
1243 ACPI_STATUS
1244 acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint)
1245 {
1246 	ACPI_STATUS status;
1247 	ACPI_BUFFER rb;
1248 	ACPI_OBJECT ro;
1249 
1250 	rb.Pointer = &ro;
1251 	rb.Length = sizeof (ro);
1252 	if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb,
1253 	    ACPI_TYPE_INTEGER)) == AE_OK)
1254 		*rint = ro.Integer.Value;
1255 
1256 	return (status);
1257 }
1258 
1259 static int
1260 acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint)
1261 {
1262 	ACPI_BUFFER rb;
1263 	ACPI_OBJECT *rv;
1264 
1265 	rb.Pointer = NULL;
1266 	rb.Length = ACPI_ALLOCATE_BUFFER;
1267 	if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK &&
1268 	    rb.Length != 0) {
1269 		rv = rb.Pointer;
1270 		if (rv->Type == ACPI_TYPE_INTEGER) {
1271 			*rint = rv->Integer.Value;
1272 			AcpiOsFree(rv);
1273 			return (AE_OK);
1274 		} else if (rv->Type == ACPI_TYPE_STRING) {
1275 			char *stringData;
1276 
1277 			/* Convert the string into an EISA ID */
1278 			if (rv->String.Pointer == NULL) {
1279 				AcpiOsFree(rv);
1280 				return (AE_ERROR);
1281 			}
1282 
1283 			stringData = rv->String.Pointer;
1284 
1285 			/*
1286 			 * If the string is an EisaID, it must be 7
1287 			 * characters; if it's an ACPI ID, it will be 8
1288 			 * (and we don't care about ACPI ids here).
1289 			 */
1290 			if (strlen(stringData) != 7) {
1291 				AcpiOsFree(rv);
1292 				return (AE_ERROR);
1293 			}
1294 
1295 			*rint = CompressEisaID(stringData);
1296 			AcpiOsFree(rv);
1297 			return (AE_OK);
1298 		} else
1299 			AcpiOsFree(rv);
1300 	}
1301 	return (AE_ERROR);
1302 }
1303 
1304 /*
1305  * Create linkage between devinfo nodes and ACPI nodes
1306  */
1307 static void
1308 acpica_tag_devinfo(dev_info_t *dip, ACPI_HANDLE acpiobj)
1309 {
1310 	ACPI_STATUS status;
1311 	ACPI_BUFFER rb;
1312 
1313 	/*
1314 	 * Tag the ACPI node with the dip
1315 	 */
1316 	status = acpica_set_devinfo(acpiobj, dip);
1317 	ASSERT(status == AE_OK);
1318 
1319 	/*
1320 	 * Tag the devinfo node with the ACPI name
1321 	 */
1322 	rb.Pointer = NULL;
1323 	rb.Length = ACPI_ALLOCATE_BUFFER;
1324 	if (AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb) == AE_OK) {
1325 		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
1326 		    "acpi-namespace", (char *)rb.Pointer);
1327 		AcpiOsFree(rb.Pointer);
1328 	} else {
1329 		cmn_err(CE_WARN, "acpica: could not get ACPI path!");
1330 	}
1331 }
1332 
1333 static void
1334 acpica_add_processor_to_map(UINT32 acpi_id, ACPI_HANDLE obj)
1335 {
1336 	int	cpu_id;
1337 
1338 	/*
1339 	 * Special case: if we're a uppc system, there won't be
1340 	 * a CPU map yet.  So we create one and use the passed-in
1341 	 * processor as CPU 0
1342 	 */
1343 	if (cpu_map == NULL) {
1344 		cpu_map = kmem_zalloc(sizeof (cpu_map[0]) * NCPU, KM_SLEEP);
1345 		cpu_map[0] = kmem_zalloc(sizeof (*cpu_map[0]), KM_SLEEP);
1346 		cpu_map[0]->obj = obj;
1347 		cpu_map_count = 1;
1348 		return;
1349 	}
1350 
1351 	for (cpu_id = 0; cpu_id < NCPU; cpu_id++) {
1352 		if (cpu_map[cpu_id] == NULL)
1353 			continue;
1354 
1355 		if (cpu_map[cpu_id]->proc_id == acpi_id) {
1356 			if (cpu_map[cpu_id]->obj == NULL)
1357 				cpu_map[cpu_id]->obj = obj;
1358 			break;
1359 		}
1360 	}
1361 
1362 }
1363 
1364 /*
1365  * Return the ACPI device node matching the CPU dev_info node.
1366  */
1367 ACPI_STATUS
1368 acpica_get_handle_cpu(dev_info_t *dip, ACPI_HANDLE *rh)
1369 {
1370 	char	*device_type_prop;
1371 	int	cpu_id;
1372 
1373 	/*
1374 	 * if "device_type" != "cpu", error
1375 	 */
1376 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
1377 	    "device_type", &device_type_prop) != DDI_PROP_SUCCESS)
1378 		return (AE_ERROR);
1379 
1380 	if (strcmp("cpu", device_type_prop) != 0) {
1381 		ddi_prop_free(device_type_prop);
1382 		return (AE_ERROR);
1383 	}
1384 	ddi_prop_free(device_type_prop);
1385 
1386 	/*
1387 	 * if cpu_map itself is NULL, we're a uppc system and
1388 	 * acpica_build_processor_map() hasn't been called yet.
1389 	 * So call it here
1390 	 */
1391 	if (cpu_map == NULL) {
1392 		(void) acpica_build_processor_map();
1393 		if (cpu_map == NULL)
1394 			return (AE_ERROR);
1395 	}
1396 
1397 	/*
1398 	 * get 'reg' and get obj from cpu_map
1399 	 */
1400 	cpu_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1401 	    "reg", -1);
1402 	if ((cpu_id < 0) || (cpu_map[cpu_id] == NULL) ||
1403 	    (cpu_map[cpu_id]->obj == NULL))
1404 		return (AE_ERROR);
1405 
1406 	/*
1407 	 * tag devinfo and obj
1408 	 */
1409 	(void) acpica_tag_devinfo(dip, cpu_map[cpu_id]->obj);
1410 	*rh = cpu_map[cpu_id]->obj;
1411 	return (AE_OK);
1412 }
1413 
1414 /*
1415  * Convert CPU device _UID strings into unique integers
1416  * ACPI 3.0 spec 6.1.9 permits _UID to be either
1417  * an arbitrary string or numeric value.  ACPI CA converts
1418  * numeric types to a string, providing a consistent API,
1419  * but it can not be assumed that _UID is always numeric.
1420  * Keep a private list of CPU _UIDs and convert them to
1421  * an integer representation.
1422  */
1423 
1424 struct acpica_cpu_uid {
1425 	struct acpica_cpu_uid *next;
1426 	char *uid;
1427 };
1428 
1429 static struct acpica_cpu_uid *acpica_cpu_uid_list = NULL;
1430 
1431 static UINT32
1432 acpica_cpu_uid_str_to_uint(char *uidstr)
1433 {
1434 	UINT32	n;
1435 	struct acpica_cpu_uid *current, **tail;
1436 
1437 	ASSERT(uidstr != NULL);
1438 
1439 	n = 0;
1440 	current = acpica_cpu_uid_list;
1441 	tail = &acpica_cpu_uid_list;
1442 	while (current != NULL) {
1443 		if (strcmp(current->uid, uidstr) == 0)
1444 			break;
1445 		n++;
1446 		tail = &current->next;
1447 		current = current->next;
1448 	}
1449 
1450 	/*
1451 	 * failed to find a matching element; create it here
1452 	 */
1453 	if (current == NULL) {
1454 		/* allocate new list element as current one */
1455 		current = (struct acpica_cpu_uid *)kmem_zalloc(
1456 		    sizeof (struct acpica_cpu_uid), KM_SLEEP);
1457 
1458 		/* allocate storage for the device ID string */
1459 		current->uid = (char *)kmem_zalloc(strlen(uidstr) + 1,
1460 		    KM_SLEEP);
1461 
1462 		strcpy(current->uid, uidstr);
1463 		*tail = current;
1464 	}
1465 
1466 	/*
1467 	 * 'n' correctly contains the index for either
1468 	 * a new element or an existing element
1469 	 */
1470 	return (n);
1471 }
1472 
1473 /*
1474  * Determine if this object is a processor
1475  */
1476 static ACPI_STATUS
1477 acpica_probe_processor(ACPI_HANDLE obj, UINT32 level, void *ctx, void **rv)
1478 {
1479 	ACPI_STATUS status;
1480 	ACPI_OBJECT_TYPE objtype;
1481 	UINT32 acpi_id;
1482 	ACPI_BUFFER rb;
1483 
1484 	if (AcpiGetType(obj, &objtype) != AE_OK)
1485 		return (AE_OK);
1486 
1487 	if (objtype == ACPI_TYPE_PROCESSOR) {
1488 		/* process a Processor */
1489 		rb.Pointer = NULL;
1490 		rb.Length = ACPI_ALLOCATE_BUFFER;
1491 		status = AcpiEvaluateObjectTyped(obj, NULL, NULL, &rb,
1492 		    ACPI_TYPE_PROCESSOR);
1493 		if (status != AE_OK) {
1494 			cmn_err(CE_WARN, "acpica: error probing Processor");
1495 			return (status);
1496 		}
1497 		acpi_id = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId;
1498 		AcpiOsFree(rb.Pointer);
1499 	} else if (objtype == ACPI_TYPE_DEVICE) {
1500 		/* process a processor Device */
1501 		rb.Pointer = NULL;
1502 		rb.Length = ACPI_ALLOCATE_BUFFER;
1503 		status = AcpiGetObjectInfo(obj, &rb);
1504 		if (status != AE_OK) {
1505 			cmn_err(CE_WARN,
1506 			    "acpica: error probing Processor Device\n");
1507 			return (status);
1508 		}
1509 		ASSERT(((ACPI_OBJECT *)rb.Pointer)->Type ==
1510 		    ACPI_TYPE_DEVICE);
1511 		acpi_id = acpica_cpu_uid_str_to_uint(
1512 		    ((ACPI_DEVICE_INFO *)rb.Pointer)->UniqueId.Value);
1513 		AcpiOsFree(rb.Pointer);
1514 	}
1515 
1516 	acpica_add_processor_to_map(acpi_id, obj);
1517 	return (AE_OK);
1518 }
1519 
1520 
1521 static void
1522 scan_d2a_map(void)
1523 {
1524 	dev_info_t *dip, *cdip;
1525 	ACPI_HANDLE acpiobj;
1526 	char *device_type_prop;
1527 	int bus;
1528 	static int map_error = 0;
1529 
1530 	if (map_error)
1531 		return;
1532 
1533 	scanning_d2a_map = 1;
1534 
1535 	/*
1536 	 * Find all child-of-root PCI buses, and find their corresponding
1537 	 * ACPI child-of-root PCI nodes.  For each one, add to the
1538 	 * d2a table.
1539 	 */
1540 
1541 	for (dip = ddi_get_child(ddi_root_node());
1542 	    dip != NULL;
1543 	    dip = ddi_get_next_sibling(dip)) {
1544 
1545 		/* prune non-PCI nodes */
1546 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
1547 		    "device_type", &device_type_prop) != DDI_PROP_SUCCESS)
1548 			continue;
1549 
1550 		if ((strcmp("pci", device_type_prop) != 0) &&
1551 		    (strcmp("pciex", device_type_prop) != 0)) {
1552 			ddi_prop_free(device_type_prop);
1553 			continue;
1554 		}
1555 
1556 		ddi_prop_free(device_type_prop);
1557 
1558 		/*
1559 		 * To get bus number of dip, get first child and get its
1560 		 * bus number.  If NULL, just continue, because we don't
1561 		 * care about bus nodes with no children anyway.
1562 		 */
1563 		if ((cdip = ddi_get_child(dip)) == NULL)
1564 			continue;
1565 
1566 		if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) {
1567 #ifdef D2ADEBUG
1568 			cmn_err(CE_WARN, "Can't get bus number of PCI child?");
1569 #endif
1570 			map_error = 1;
1571 			scanning_d2a_map = 0;
1572 			d2a_done = 1;
1573 			return;
1574 		}
1575 
1576 		if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) {
1577 #ifdef D2ADEBUG
1578 			cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus);
1579 #endif
1580 			map_error = 1;
1581 			continue;
1582 		}
1583 
1584 		acpica_tag_devinfo(dip, acpiobj);
1585 
1586 		/* call recursively to enumerate subtrees */
1587 		scan_d2a_subtree(dip, acpiobj, bus);
1588 	}
1589 
1590 	scanning_d2a_map = 0;
1591 	d2a_done = 1;
1592 }
1593 
1594 /*
1595  * For all acpi child devices of acpiobj, find their matching
1596  * dip under "dip" argument.  (matching means "matches dev/fn").
1597  * bus is assumed to already be a match from caller, and is
1598  * used here only to record in the d2a entry.  Recurse if necessary.
1599  */
1600 static void
1601 scan_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus)
1602 {
1603 	int acpi_devfn, hid;
1604 	ACPI_HANDLE acld;
1605 	dev_info_t *dcld;
1606 	int dcld_b, dcld_d, dcld_f;
1607 	int dev, func;
1608 	char *device_type_prop;
1609 
1610 	acld = NULL;
1611 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld)
1612 	    == AE_OK) {
1613 		/* get the dev/func we're looking for in the devinfo tree */
1614 		if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK)
1615 			continue;
1616 		dev = (acpi_devfn >> 16) & 0xFFFF;
1617 		func = acpi_devfn & 0xFFFF;
1618 
1619 		/* look through all the immediate children of dip */
1620 		for (dcld = ddi_get_child(dip); dcld != NULL;
1621 		    dcld = ddi_get_next_sibling(dcld)) {
1622 			if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0)
1623 				continue;
1624 
1625 			/* dev must match; function must match or wildcard */
1626 			if (dcld_d != dev ||
1627 			    (func != 0xFFFF && func != dcld_f))
1628 				continue;
1629 			bus = dcld_b;
1630 
1631 			/* found a match, record it */
1632 			acpica_tag_devinfo(dcld, acld);
1633 
1634 			/* if we find a bridge, recurse from here */
1635 			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dcld, 0,
1636 			    "device_type", &device_type_prop) ==
1637 			    DDI_PROP_SUCCESS) {
1638 				if ((strcmp("pci", device_type_prop) == 0) ||
1639 				    (strcmp("pciex", device_type_prop) == 0))
1640 					scan_d2a_subtree(dcld, acld, bus);
1641 				ddi_prop_free(device_type_prop);
1642 			}
1643 
1644 			/* done finding a match, so break now */
1645 			break;
1646 		}
1647 	}
1648 }
1649 
1650 /*
1651  * Return bus/dev/fn for PCI dip (note: not the parent "pci" node).
1652  */
1653 int
1654 acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func)
1655 {
1656 	pci_regspec_t *pci_rp;
1657 	int len;
1658 
1659 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1660 	    "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS)
1661 		return (-1);
1662 
1663 	if (len < (sizeof (pci_regspec_t) / sizeof (int))) {
1664 		ddi_prop_free(pci_rp);
1665 		return (-1);
1666 	}
1667 	if (bus != NULL)
1668 		*bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1669 	if (device != NULL)
1670 		*device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1671 	if (func != NULL)
1672 		*func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1673 	ddi_prop_free(pci_rp);
1674 	return (0);
1675 }
1676 
1677 /*
1678  * Return the ACPI device node matching this dev_info node, if it
1679  * exists in the ACPI tree.
1680  */
1681 ACPI_STATUS
1682 acpica_get_handle(dev_info_t *dip, ACPI_HANDLE *rh)
1683 {
1684 	ACPI_STATUS status;
1685 	char *acpiname;
1686 
1687 	if (!d2a_done)
1688 		scan_d2a_map();
1689 
1690 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1691 	    "acpi-namespace", &acpiname) != DDI_PROP_SUCCESS) {
1692 		return (acpica_get_handle_cpu(dip, rh));
1693 	}
1694 
1695 	status = AcpiGetHandle(NULL, acpiname, rh);
1696 	ddi_prop_free((void *)acpiname);
1697 	return (status);
1698 }
1699 
1700 
1701 
1702 /*
1703  * Manage OS data attachment to ACPI nodes
1704  */
1705 
1706 /*
1707  * Return the (dev_info_t *) associated with the ACPI node.
1708  */
1709 ACPI_STATUS
1710 acpica_get_devinfo(ACPI_HANDLE obj, dev_info_t **dipp)
1711 {
1712 	ACPI_STATUS status;
1713 	void *ptr;
1714 
1715 	status = AcpiGetData(obj, acpica_devinfo_handler, &ptr);
1716 	if (status == AE_OK)
1717 		*dipp = (dev_info_t *)ptr;
1718 
1719 	return (status);
1720 }
1721 
1722 /*
1723  * Set the dev_info_t associated with the ACPI node.
1724  */
1725 static ACPI_STATUS
1726 acpica_set_devinfo(ACPI_HANDLE obj, dev_info_t *dip)
1727 {
1728 	ACPI_STATUS status;
1729 
1730 	status = AcpiAttachData(obj, acpica_devinfo_handler, (void *)dip);
1731 	return (status);
1732 }
1733 
1734 
1735 /*
1736  *
1737  */
1738 void
1739 acpica_devinfo_handler(ACPI_HANDLE obj, UINT32 func, void *data)
1740 {
1741 	/* noop */
1742 }
1743 
1744 
1745 /*
1746  *
1747  */
1748 void
1749 acpica_map_cpu(processorid_t cpuid, UINT32 proc_id)
1750 {
1751 	struct cpu_map_item *item;
1752 
1753 	if (cpu_map == NULL)
1754 		cpu_map = kmem_zalloc(sizeof (item) * NCPU, KM_SLEEP);
1755 
1756 	item = kmem_zalloc(sizeof (*item), KM_SLEEP);
1757 	item->proc_id = proc_id;
1758 	item->obj = NULL;
1759 	cpu_map[cpuid] = item;
1760 	cpu_map_count++;
1761 }
1762 
1763 void
1764 acpica_build_processor_map()
1765 {
1766 	ACPI_STATUS status;
1767 	void *rv;
1768 
1769 	/*
1770 	 * shouldn't be called more than once anyway
1771 	 */
1772 	if (cpu_map_built)
1773 		return;
1774 
1775 	/*
1776 	 * Look for Processor objects
1777 	 */
1778 	status = AcpiWalkNamespace(ACPI_TYPE_PROCESSOR,
1779 	    ACPI_ROOT_OBJECT,
1780 	    4,
1781 	    acpica_probe_processor,
1782 	    NULL,
1783 	    &rv);
1784 	ASSERT(status == AE_OK);
1785 
1786 	/*
1787 	 * Look for processor Device objects
1788 	 */
1789 	status = AcpiGetDevices("ACPI0007",
1790 	    acpica_probe_processor,
1791 	    NULL,
1792 	    &rv);
1793 	ASSERT(status == AE_OK);
1794 	cpu_map_built = 1;
1795 }
1796