xref: /illumos-gate/usr/src/uts/intel/io/acpica/osl.c (revision 03335b7a)
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 2006 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 
33 #include <sys/types.h>
34 #include <sys/kmem.h>
35 #include <sys/psm.h>
36 #include <sys/pci_cfgspace.h>
37 #include <sys/ddi.h>
38 #include <sys/pci.h>
39 #include <sys/kobj.h>
40 #include <sys/taskq.h>
41 #include <sys/strlog.h>
42 #include <sys/note.h>
43 
44 #include <sys/acpi/acpi.h>
45 #include <sys/acpica.h>
46 
47 extern int (*psm_translate_irq)(dev_info_t *, int);
48 
49 #define	MAX_DAT_FILE_SIZE	(64*1024)
50 
51 #define	D2A_INITLEN	20
52 static int d2a_len = 0;
53 static int d2a_valid = 0;
54 static d2a *d2a_table;
55 
56 static int acpi_has_broken_bbn = -1;
57 
58 /* local functions */
59 static int CompressEisaID(char *np);
60 
61 static void create_d2a_map(void);
62 static void create_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus);
63 static void new_d2a_entry(dev_info_t *dip, ACPI_HANDLE acpiobj,
64 	int bus, int dev, int func);
65 
66 static int acpica_query_bbn_problem(void);
67 static int acpica_find_pcibus(int busno, ACPI_HANDLE *rh);
68 static int acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint);
69 
70 int acpica_find_pciobj(dev_info_t *dip, ACPI_HANDLE *rh);
71 static int acpica_find_pcid2a(ACPI_HANDLE, d2a **);
72 int acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint);
73 
74 /*
75  * Event queue vars
76  */
77 int acpica_eventq_thread_count = 1;
78 int acpica_eventq_init = 0;
79 ddi_taskq_t *eventq_gpe = NULL;
80 ddi_taskq_t *eventq_high = NULL;
81 ddi_taskq_t *eventq_medium = NULL;
82 ddi_taskq_t *eventq_low = NULL;
83 
84 /*
85  * Note, if you change this path, you need to update
86  * /boot/grub/filelist.ramdisk and pkg SUNWckr/prototype_i386
87  */
88 static char *acpi_table_path = "/boot/acpi/tables/";
89 
90 /* non-zero while create_d2a_map() is working */
91 static int creating_d2a_map = 0;
92 
93 /*
94  *
95  */
96 static void
97 discard_event_queues()
98 {
99 
100 	/*
101 	 * destroy event queues
102 	 */
103 	if (eventq_gpe)
104 		ddi_taskq_destroy(eventq_gpe);
105 	if (eventq_high)
106 		ddi_taskq_destroy(eventq_high);
107 	if (eventq_low)
108 		ddi_taskq_destroy(eventq_low);
109 	if (eventq_medium)
110 		ddi_taskq_destroy(eventq_medium);
111 }
112 
113 
114 /*
115  *
116  */
117 static ACPI_STATUS
118 init_event_queues()
119 {
120 
121 	/*
122 	 * Initialize event queues
123 	 * FUTUREWORK: taskq priorities currently the same
124 	 */
125 
126 	eventq_gpe = ddi_taskq_create(NULL, "ACPIGPE",
127 	    acpica_eventq_thread_count, TASKQ_DEFAULTPRI, 0);
128 	eventq_high = ddi_taskq_create(NULL, "ACPIHIGH",
129 	    acpica_eventq_thread_count, TASKQ_DEFAULTPRI, 0);
130 	eventq_medium = ddi_taskq_create(NULL, "ACPIMED",
131 	    acpica_eventq_thread_count, TASKQ_DEFAULTPRI, 0);
132 	eventq_low = ddi_taskq_create(NULL, "ACPILOW",
133 	    acpica_eventq_thread_count, TASKQ_DEFAULTPRI, 0);
134 
135 	if ((eventq_gpe == NULL) || (eventq_high == NULL) ||
136 	    (eventq_medium == NULL) || (eventq_low == NULL)) {
137 		discard_event_queues();
138 #ifdef	DEBUG
139 		cmn_err(CE_WARN, "!acpica: could not initialize event queues");
140 #endif
141 		return (AE_ERROR);
142 	}
143 
144 	acpica_eventq_init = 1;
145 	return (AE_OK);
146 }
147 
148 /*
149  *
150  */
151 ACPI_STATUS
152 AcpiOsInitialize(void)
153 {
154 
155 	return (AE_OK);
156 }
157 
158 /*
159  *
160  */
161 ACPI_STATUS
162 AcpiOsTerminate(void)
163 {
164 
165 	discard_event_queues();
166 	return (AE_OK);
167 }
168 
169 
170 ACPI_STATUS
171 AcpiOsGetRootPointer(UINT32 Flags, ACPI_POINTER *Address)
172 {
173 	return (AcpiFindRootPointer(Flags, Address));
174 }
175 
176 /*ARGSUSED*/
177 ACPI_STATUS
178 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *InitVal,
179 				ACPI_STRING *NewVal)
180 {
181 
182 	*NewVal = 0;
183 	return (AE_OK);
184 }
185 
186 static void
187 acpica_strncpy(char *dest, const char *src, int len)
188 {
189 
190 	/*LINTED*/
191 	while ((*dest++ = *src++) && (--len > 0))
192 		/* copy the string */;
193 	*dest = '\0';
194 }
195 
196 ACPI_STATUS
197 AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable,
198 			ACPI_TABLE_HEADER **NewTable)
199 {
200 	char signature[5];
201 	char oemid[7];
202 	char oemtableid[9];
203 	struct _buf *file;
204 	char *buf1, *buf2;
205 	int count;
206 	char acpi_table_loc[128];
207 
208 	acpica_strncpy(signature, ExistingTable->Signature, 4);
209 	acpica_strncpy(oemid, ExistingTable->OemId, 6);
210 	acpica_strncpy(oemtableid, ExistingTable->OemTableId, 8);
211 
212 #ifdef	DEBUG
213 	cmn_err(CE_NOTE, "!acpica: table [%s] v%d OEM ID [%s]"
214 		    " OEM TABLE ID [%s] OEM rev %x",
215 		    signature, ExistingTable->Revision, oemid, oemtableid,
216 		    ExistingTable->OemRevision);
217 #endif
218 
219 	/* File name format is "signature_oemid_oemtableid.dat" */
220 	(void) strcpy(acpi_table_loc, acpi_table_path);
221 	(void) strcat(acpi_table_loc, signature); /* for example, DSDT */
222 	(void) strcat(acpi_table_loc, "_");
223 	(void) strcat(acpi_table_loc, oemid); /* for example, IntelR */
224 	(void) strcat(acpi_table_loc, "_");
225 	(void) strcat(acpi_table_loc, oemtableid); /* for example, AWRDACPI */
226 	(void) strcat(acpi_table_loc, ".dat");
227 
228 	file = kobj_open_file(acpi_table_loc);
229 	if (file == (struct _buf *)-1) {
230 		*NewTable = 0;
231 		return (AE_OK);
232 	} else {
233 		buf1 = (char *)kmem_alloc(MAX_DAT_FILE_SIZE, KM_SLEEP);
234 		count = kobj_read_file(file, buf1, MAX_DAT_FILE_SIZE-1, 0);
235 		if (count >= MAX_DAT_FILE_SIZE) {
236 			cmn_err(CE_WARN, "!acpica: table %s file size too big",
237 			    acpi_table_loc);
238 			*NewTable = 0;
239 		} else {
240 			buf2 = (char *)kmem_alloc(count, KM_SLEEP);
241 			(void) memcpy(buf2, buf1, count);
242 			*NewTable = (ACPI_TABLE_HEADER *)buf2;
243 			cmn_err(CE_NOTE, "!acpica: replacing table: %s",
244 			    acpi_table_loc);
245 		}
246 	}
247 	kobj_close_file(file);
248 	kmem_free(buf1, MAX_DAT_FILE_SIZE);
249 
250 	return (AE_OK);
251 }
252 
253 
254 /*
255  * ACPI semaphore implementation
256  */
257 typedef struct {
258 	kmutex_t	mutex;
259 	kcondvar_t	cv;
260 	uint32_t	available;
261 	uint32_t	initial;
262 	uint32_t	maximum;
263 } acpi_sema_t;
264 
265 /*
266  *
267  */
268 void
269 acpi_sema_init(acpi_sema_t *sp, unsigned max, unsigned count, void *name,
270     int type, void *arg)
271 {
272 	mutex_init(&sp->mutex, NULL, MUTEX_DRIVER, NULL);
273 	cv_init(&sp->cv, NULL, CV_DRIVER, NULL);
274 	/* no need to enter mutex here at creation */
275 	sp->available = count;
276 	sp->initial = count;
277 	sp->maximum = max;
278 }
279 
280 /*
281  *
282  */
283 void
284 acpi_sema_destroy(acpi_sema_t *sp)
285 {
286 
287 	cv_destroy(&sp->cv);
288 	mutex_destroy(&sp->mutex);
289 }
290 
291 /*
292  *
293  */
294 ACPI_STATUS
295 acpi_sema_p(acpi_sema_t *sp, unsigned count, uint16_t wait_time)
296 {
297 	ACPI_STATUS rv = AE_OK;
298 	clock_t deadline;
299 
300 	mutex_enter(&sp->mutex);
301 
302 	if (sp->available >= count) {
303 		/*
304 		 * Enough units available, no blocking
305 		 */
306 		sp->available -= count;
307 		mutex_exit(&sp->mutex);
308 		return (rv);
309 	} else if (wait_time == 0) {
310 		/*
311 		 * Not enough units available and timeout
312 		 * specifies no blocking
313 		 */
314 		rv = AE_TIME;
315 		mutex_exit(&sp->mutex);
316 		return (rv);
317 	}
318 
319 	/*
320 	 * Not enough units available and timeout specifies waiting
321 	 */
322 	if (wait_time != ACPI_WAIT_FOREVER)
323 		deadline = ddi_get_lbolt() +
324 		    (clock_t)drv_usectohz(wait_time * 1000);
325 
326 	do {
327 		if (wait_time == ACPI_WAIT_FOREVER)
328 			cv_wait(&sp->cv, &sp->mutex);
329 		else if (cv_timedwait(&sp->cv, &sp->mutex, deadline) < 0) {
330 			rv = AE_TIME;
331 			break;
332 		}
333 	} while (sp->available < count);
334 
335 	/* if we dropped out of the wait with AE_OK, we got the units */
336 	if (rv == AE_OK)
337 		sp->available -= count;
338 
339 	mutex_exit(&sp->mutex);
340 	return (rv);
341 }
342 
343 /*
344  *
345  */
346 void
347 acpi_sema_v(acpi_sema_t *sp, unsigned count)
348 {
349 	mutex_enter(&sp->mutex);
350 	sp->available += count;
351 	cv_broadcast(&sp->cv);
352 	mutex_exit(&sp->mutex);
353 }
354 
355 
356 ACPI_STATUS
357 AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
358 ACPI_HANDLE *OutHandle)
359 {
360 	acpi_sema_t *sp;
361 
362 	if ((OutHandle == NULL) || (InitialUnits > MaxUnits))
363 		return (AE_BAD_PARAMETER);
364 
365 	sp = (acpi_sema_t *)kmem_alloc(sizeof (acpi_sema_t), KM_SLEEP);
366 	acpi_sema_init(sp, MaxUnits, InitialUnits, NULL, SEMA_DRIVER, NULL);
367 	*OutHandle = (ACPI_HANDLE)sp;
368 	return (AE_OK);
369 }
370 
371 
372 ACPI_STATUS
373 AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
374 {
375 
376 	if (Handle == NULL)
377 		return (AE_BAD_PARAMETER);
378 
379 	acpi_sema_destroy((acpi_sema_t *)Handle);
380 	kmem_free((void *)Handle, sizeof (acpi_sema_t));
381 	return (AE_OK);
382 }
383 
384 ACPI_STATUS
385 AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT16 Timeout)
386 {
387 
388 	if ((Handle == NULL) || (Units < 1))
389 		return (AE_BAD_PARAMETER);
390 
391 	return (acpi_sema_p((acpi_sema_t *)Handle, Units, Timeout));
392 }
393 
394 ACPI_STATUS
395 AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
396 {
397 
398 	if ((Handle == NULL) || (Units < 1))
399 		return (AE_BAD_PARAMETER);
400 
401 	acpi_sema_v((acpi_sema_t *)Handle, Units);
402 	return (AE_OK);
403 }
404 
405 ACPI_STATUS
406 AcpiOsCreateLock(ACPI_HANDLE *OutHandle)
407 {
408 	kmutex_t *mp;
409 
410 	if (OutHandle == NULL)
411 		return (AE_BAD_PARAMETER);
412 
413 	mp = (kmutex_t *)kmem_alloc(sizeof (kmutex_t), KM_SLEEP);
414 	mutex_init(mp, NULL, MUTEX_DRIVER, NULL);
415 	*OutHandle = (ACPI_HANDLE)mp;
416 	return (AE_OK);
417 }
418 
419 void
420 AcpiOsDeleteLock(ACPI_HANDLE Handle)
421 {
422 
423 	if (Handle == NULL)
424 		return;
425 
426 	mutex_destroy((kmutex_t *)Handle);
427 	kmem_free((void *)Handle, sizeof (kmutex_t));
428 }
429 
430 ACPI_NATIVE_UINT
431 AcpiOsAcquireLock(ACPI_HANDLE Handle)
432 {
433 
434 	if (Handle == NULL)
435 		return (AE_BAD_PARAMETER);
436 
437 	mutex_enter((kmutex_t *)Handle);
438 	return (AE_OK);
439 }
440 
441 void
442 AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_NATIVE_UINT Flags)
443 {
444 	_NOTE(ARGUNUSED(Flags))
445 
446 	if (Handle == NULL)
447 		return;
448 
449 	mutex_exit((kmutex_t *)Handle);
450 }
451 
452 
453 void *
454 AcpiOsAllocate(ACPI_SIZE Size)
455 {
456 	ACPI_SIZE *tmp_ptr;
457 
458 	Size += sizeof (Size);
459 	tmp_ptr = (ACPI_SIZE *)kmem_zalloc(Size, KM_SLEEP);
460 	*tmp_ptr++ = Size;
461 	return (tmp_ptr);
462 }
463 
464 void
465 AcpiOsFree(void *Memory)
466 {
467 	ACPI_SIZE	size, *tmp_ptr;
468 
469 	tmp_ptr = (ACPI_SIZE *)Memory;
470 	tmp_ptr -= 1;
471 	size = *tmp_ptr;
472 	kmem_free(tmp_ptr, size);
473 }
474 
475 ACPI_STATUS
476 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress,
477 		    ACPI_SIZE Size, void **LogicalAddress)
478 {
479 	/* FUTUREWORK: test PhysicalAddress for > 32 bits */
480 	*LogicalAddress = psm_map_new((paddr_t)PhysicalAddress,
481 		(size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ);
482 
483 	return (*LogicalAddress == NULL ? AE_NO_MEMORY : AE_OK);
484 }
485 
486 void
487 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
488 {
489 
490 	psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
491 }
492 
493 /*ARGSUSED*/
494 ACPI_STATUS
495 AcpiOsGetPhysicalAddress(void *LogicalAddress,
496 			ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
497 {
498 
499 	/* UNIMPLEMENTED: not invoked by ACPI CA code */
500 	return (AE_NOT_IMPLEMENTED);
501 }
502 
503 
504 ACPI_OSD_HANDLER acpi_isr;
505 void *acpi_isr_context;
506 
507 uint_t
508 acpi_wrapper_isr(char *arg)
509 {
510 	_NOTE(ARGUNUSED(arg))
511 
512 	int	status;
513 
514 	status = (*acpi_isr)(acpi_isr_context);
515 
516 	if (status == ACPI_INTERRUPT_HANDLED) {
517 		return (DDI_INTR_CLAIMED);
518 	} else {
519 		return (DDI_INTR_UNCLAIMED);
520 	}
521 }
522 
523 static int acpi_intr_hooked = 0;
524 
525 ACPI_STATUS
526 AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
527 		ACPI_OSD_HANDLER ServiceRoutine,
528 		void *Context)
529 {
530 	int retval;
531 	int sci_vect;
532 	iflag_t sci_flags;
533 
534 	acpi_isr = ServiceRoutine;
535 	acpi_isr_context = Context;
536 
537 	/*
538 	 * Get SCI (adjusted for PIC/APIC mode if necessary)
539 	 */
540 	if (acpica_get_sci(&sci_vect, &sci_flags) != AE_OK) {
541 		return (AE_ERROR);
542 	}
543 
544 #ifdef	DEBUG
545 	cmn_err(CE_NOTE, "!acpica: attaching SCI %d", sci_vect);
546 #endif
547 
548 	retval = add_avintr(NULL, SCI_IPL, (avfunc)acpi_wrapper_isr,
549 				"ACPI SCI", sci_vect, NULL, NULL, NULL, NULL);
550 	if (retval) {
551 		acpi_intr_hooked = 1;
552 		return (AE_OK);
553 	} else
554 		return (AE_BAD_PARAMETER);
555 }
556 
557 ACPI_STATUS
558 AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber,
559 			ACPI_OSD_HANDLER ServiceRoutine)
560 {
561 	_NOTE(ARGUNUSED(ServiceRoutine))
562 
563 #ifdef	DEBUG
564 	cmn_err(CE_NOTE, "!acpica: detaching SCI %d", InterruptNumber);
565 #endif
566 	if (acpi_intr_hooked) {
567 		rem_avintr(NULL, LOCK_LEVEL - 1, (avfunc)acpi_wrapper_isr,
568 				InterruptNumber);
569 		acpi_intr_hooked = 0;
570 	}
571 	return (AE_OK);
572 }
573 
574 
575 UINT32
576 AcpiOsGetThreadId(void)
577 {
578 	kt_did_t thread_id;
579 
580 	/* FUTUREWORK: give back a real thread id */
581 	thread_id = ddi_get_kt_did();
582 	return ((UINT32)thread_id);
583 }
584 
585 /*
586  *
587  */
588 ACPI_STATUS
589 AcpiOsQueueForExecution(UINT32 Priority,
590 		ACPI_OSD_EXEC_CALLBACK  Function,
591 		void *Context)
592 {
593 	ddi_taskq_t *q;
594 
595 	if (!acpica_eventq_init) {
596 		/*
597 		 * Create taskqs for event handling
598 		 */
599 		if (init_event_queues() != AE_OK)
600 		    return (AE_ERROR);
601 	}
602 
603 	switch (Priority) {
604 	case OSD_PRIORITY_GPE:
605 		q = eventq_gpe;
606 		break;
607 	case OSD_PRIORITY_HIGH:
608 		q = eventq_high;
609 		break;
610 	case OSD_PRIORITY_MED:
611 		q = eventq_medium;
612 		break;
613 	case OSD_PRIORITY_LO:
614 		q = eventq_low;
615 		break;
616 	default:
617 		q = NULL;
618 		break;
619 	}
620 
621 	if (q == NULL) {
622 #ifdef	DEBUG
623 		cmn_err(CE_WARN, "!acpica: unknown priority %d", Priority);
624 #endif
625 		return (AE_ERROR);
626 	}
627 	if (ddi_taskq_dispatch(q, Function, Context, DDI_NOSLEEP) ==
628 	    DDI_FAILURE) {
629 #ifdef	DEBUG
630 		cmn_err(CE_WARN, "!acpica: unable to dispatch event");
631 #endif
632 		return (AE_ERROR);
633 	}
634 	return (AE_OK);
635 
636 }
637 
638 void
639 AcpiOsSleep(ACPI_INTEGER Milliseconds)
640 {
641 	/*
642 	 * During kernel startup, before the first
643 	 * tick interrupt has taken place, we can't call
644 	 * delay.  So we busy wait if lbolt == 0.
645 	 */
646 	if (ddi_get_lbolt() == 0)
647 		drv_usecwait(Milliseconds * 1000);
648 	else
649 		delay(drv_usectohz(Milliseconds * 1000));
650 }
651 
652 void
653 AcpiOsStall(UINT32 Microseconds)
654 {
655 	drv_usecwait(Microseconds);
656 }
657 
658 
659 /*
660  * Implementation of "Windows 2001" compatible I/O permission map
661  *
662  */
663 #define	OSL_IO_NONE	(0)
664 #define	OSL_IO_READ	(1<<0)
665 #define	OSL_IO_WRITE	(1<<1)
666 #define	OSL_IO_RW	(OSL_IO_READ | OSL_IO_WRITE)
667 #define	OSL_IO_TERM	(1<<2)
668 #define	OSL_IO_DEFAULT	OSL_IO_RW
669 
670 static struct io_perm  {
671 	ACPI_IO_ADDRESS	low;
672 	ACPI_IO_ADDRESS	high;
673 	uint8_t		perm;
674 } osl_io_perm[] = {
675 	{ 0xcf8, 0xd00, OSL_IO_NONE | OSL_IO_TERM }
676 };
677 
678 
679 /*
680  *
681  */
682 static struct io_perm *
683 osl_io_find_perm(ACPI_IO_ADDRESS addr)
684 {
685 	struct io_perm *p;
686 
687 	p = osl_io_perm;
688 	while (p != NULL) {
689 		if ((p->low <= addr) && (addr <= p->high))
690 			break;
691 		p = (p->perm & OSL_IO_TERM) ? NULL : p+1;
692 	}
693 
694 	return (p);
695 }
696 
697 /*
698  *
699  */
700 ACPI_STATUS
701 AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
702 {
703 	struct io_perm *p;
704 
705 	/* verify permission */
706 	p = osl_io_find_perm(Address);
707 	if (p && (p->perm & OSL_IO_READ) == 0) {
708 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u not permitted",
709 			    (long)Address, Width);
710 		*Value = 0xffffffff;
711 		return (AE_ERROR);
712 	}
713 
714 	switch (Width) {
715 	case 8:
716 		*Value = inb(Address);
717 		break;
718 	case 16:
719 		*Value = inw(Address);
720 		break;
721 	case 32:
722 		*Value = inl(Address);
723 		break;
724 	default:
725 		cmn_err(CE_WARN, "!AcpiOsReadPort: %lx %u failed",
726 			    (long)Address, Width);
727 		return (AE_BAD_PARAMETER);
728 	}
729 	return (AE_OK);
730 }
731 
732 ACPI_STATUS
733 AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
734 {
735 	struct io_perm *p;
736 
737 	/* verify permission */
738 	p = osl_io_find_perm(Address);
739 	if (p && (p->perm & OSL_IO_WRITE) == 0) {
740 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u not permitted",
741 		    (long)Address, Width);
742 		return (AE_ERROR);
743 	}
744 
745 	switch (Width) {
746 	case 8:
747 		outb(Address, Value);
748 		break;
749 	case 16:
750 		outw(Address, Value);
751 		break;
752 	case 32:
753 		outl(Address, Value);
754 		break;
755 	default:
756 		cmn_err(CE_WARN, "!AcpiOsWritePort: %lx %u failed",
757 		    (long)Address, Width);
758 		return (AE_BAD_PARAMETER);
759 	}
760 	return (AE_OK);
761 }
762 
763 
764 /*
765  *
766  */
767 
768 #define	OSL_RW(ptr, val, type, rw) \
769 	{ if (rw) *((type *)(ptr)) = *((type *) val); \
770 	    else *((type *) val) = *((type *)(ptr)); }
771 
772 
773 static void
774 osl_rw_memory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value,
775     UINT32 Width, int write)
776 {
777 	size_t	maplen = Width / 8;
778 	caddr_t	ptr;
779 
780 	ptr = psm_map_new((paddr_t)Address, maplen,
781 	    PSM_PROT_WRITE | PSM_PROT_READ);
782 
783 	switch (maplen) {
784 	case 1:
785 		OSL_RW(ptr, Value, uint8_t, write);
786 		break;
787 	case 2:
788 		OSL_RW(ptr, Value, uint16_t, write);
789 		break;
790 	case 4:
791 		OSL_RW(ptr, Value, uint32_t, write);
792 		break;
793 	default:
794 		cmn_err(CE_WARN, "!osl_rw_memory: invalid size %d",
795 		    Width);
796 		break;
797 	}
798 
799 	psm_unmap(ptr, maplen);
800 }
801 
802 ACPI_STATUS
803 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,
804 		UINT32 *Value, UINT32 Width)
805 {
806 	osl_rw_memory(Address, Value, Width, 0);
807 	return (AE_OK);
808 }
809 
810 ACPI_STATUS
811 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,
812 		UINT32 Value, UINT32 Width)
813 {
814 	osl_rw_memory(Address, &Value, Width, 1);
815 	return (AE_OK);
816 }
817 
818 
819 ACPI_STATUS
820 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
821 			void *Value, UINT32 Width)
822 {
823 
824 	switch (Width) {
825 	case 8:
826 		*((UINT64 *)Value) = (UINT64)(*pci_getb_func)
827 					(PciId->Bus, PciId->Device,
828 						PciId->Function, Register);
829 		break;
830 	case 16:
831 		*((UINT64 *)Value) = (UINT64)(*pci_getw_func)
832 					(PciId->Bus, PciId->Device,
833 						PciId->Function, Register);
834 		break;
835 	case 32:
836 		*((UINT64 *)Value) = (UINT64)(*pci_getl_func)
837 					(PciId->Bus, PciId->Device,
838 						PciId->Function, Register);
839 		break;
840 	case 64:
841 	default:
842 		cmn_err(CE_WARN, "!AcpiOsReadPciConfiguration: %x %u failed",
843 		    Register, Width);
844 		return (AE_BAD_PARAMETER);
845 	}
846 	return (AE_OK);
847 }
848 
849 /*
850  *
851  */
852 int acpica_write_pci_config_ok = 1;
853 
854 ACPI_STATUS
855 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
856 		ACPI_INTEGER Value, UINT32 Width)
857 {
858 
859 	if (!acpica_write_pci_config_ok) {
860 		cmn_err(CE_NOTE, "!write to PCI cfg %x/%x/%x %x"
861 		    " %lx %d not permitted", PciId->Bus, PciId->Device,
862 		    PciId->Function, Register, (long)Value, Width);
863 		return (AE_OK);
864 	}
865 
866 	switch (Width) {
867 	case 8:
868 		(*pci_putb_func)(PciId->Bus, PciId->Device, PciId->Function,
869 					Register, (uint8_t)Value);
870 		break;
871 	case 16:
872 		(*pci_putw_func)(PciId->Bus, PciId->Device, PciId->Function,
873 					Register, (uint16_t)Value);
874 		break;
875 	case 32:
876 		(*pci_putl_func)(PciId->Bus, PciId->Device, PciId->Function,
877 					Register, (uint32_t)Value);
878 		break;
879 	case 64:
880 	default:
881 		cmn_err(CE_WARN, "!AcpiOsWritePciConfiguration: %x %u failed",
882 		    Register, Width);
883 		return (AE_BAD_PARAMETER);
884 	}
885 	return (AE_OK);
886 }
887 
888 /*
889  * This took me a while to figure out, and thus warrants
890  * detailed explanation lest I forget it.
891  *
892  * Called with ACPI_HANDLEs for both a PCI Config Space
893  * OpRegion and (what ACPI CA thinks is) the PCI device
894  * to which this ConfigSpace OpRegion belongs.  Problems
895  * with this are:
896  * - ACPI CA currently only thinks "PNP0A03" is a PCI bridge;
897  *   and doesn't recognize "PNP0A08" which is a PCI Express bridge
898  *   (in which case the root handle may be higher in the ACPI
899  *   namespace than it should, including a non-PCI device)
900  *
901  * - ACPI CA depends on a valid _BBN object being present
902  *   and this is known to not always be true
903  *
904  * Default values for bus, segment, device and function are
905  * all 0 when ACPI CA can't figure them out.
906  *
907  * This is further complicated by BIOSes that implement
908  * _BBN() by reading PCI config space - it means that we'll
909  * recurse when we attempt to create the devinfo-to-ACPI
910  * map.  If Derive is called during create_d2a_map, we simply
911  * can't help and return.  It seems this ends up doing the right
912  * thing, at least on the LX50 which gets base bus numbers other
913  * than 0 from PCI Config space on bus 0.
914  *
915  */
916 void
917 AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle,
918 		ACPI_PCI_ID **PciId)
919 {
920 	ACPI_HANDLE handle;
921 	d2a *d2ap;
922 	int devfn;
923 
924 
925 	/* See above - avoid recursing during create_d2a_map */
926 	/* doesn't matter if multi-threaded here, either */
927 	if (creating_d2a_map)
928 		return;
929 
930 	/*
931 	 * We start with the parent node of the OpRegion
932 	 * and ascend, looking for a matching dip2acpi
933 	 * node; once located, we use the bus from the d2a
934 	 * node and the device/function return from the _ADR
935 	 * method on the ACPI node.
936 	 * If we encounter any kind of failure, we just
937 	 * return, possibly after updating the bus value
938 	 * This is probably always better than nothing.
939 	 */
940 	if (AcpiGetParent(chandle, &handle) != AE_OK)
941 		return;
942 
943 	while (handle != rhandle) {
944 		if (acpica_find_pcid2a(handle, &d2ap) == AE_OK) {
945 			(*PciId)->Bus = d2ap->bus;
946 			if (acpica_eval_int(handle, "_ADR", &devfn) == AE_OK) {
947 				(*PciId)->Device = (devfn >> 16) & 0xFFFF;
948 				(*PciId)->Function = devfn & 0xFFFF;
949 			}
950 			break;
951 		}
952 
953 		if (AcpiGetParent(handle, &handle) != AE_OK)
954 			break;
955 	}
956 }
957 
958 
959 BOOLEAN
960 AcpiOsReadable(void *Pointer, ACPI_SIZE Length)
961 {
962 
963 	/* Always says yes; all mapped memory assumed readable */
964 	return (1);
965 }
966 
967 BOOLEAN
968 AcpiOsWritable(void *Pointer, ACPI_SIZE Length)
969 {
970 
971 	/* Always says yes; all mapped memory assumed writable */
972 	return (1);
973 }
974 
975 UINT64
976 AcpiOsGetTimer(void)
977 {
978 
979 	/* New ACPI 3.0 Timer() support */
980 	/* FUTUREWORK: need to integrate with PSM? */
981 
982 	cmn_err(CE_NOTE, "!AcpiOsGetTimer unimplemented");
983 	return (0);
984 }
985 
986 ACPI_STATUS
987 AcpiOsSignal(UINT32 Function, void *Info)
988 {
989 	_NOTE(ARGUNUSED(Function, Info))
990 
991 	/* FUTUREWORK: debugger support */
992 
993 	cmn_err(CE_NOTE, "!OsSignal unimplemented");
994 	return (AE_OK);
995 }
996 
997 void ACPI_INTERNAL_VAR_XFACE
998 AcpiOsPrintf(const char *Format, ...)
999 {
1000 	va_list ap;
1001 
1002 	va_start(ap, Format);
1003 	AcpiOsVprintf(Format, ap);
1004 	va_end(ap);
1005 }
1006 
1007 /*
1008  * When != 0, sends output to console
1009  * Patchable with kmdb or /etc/system.
1010  */
1011 int acpica_console_out = 0;
1012 
1013 #define	ACPICA_OUTBUF_LEN	160
1014 char	acpica_outbuf[ACPICA_OUTBUF_LEN];
1015 int	acpica_outbuf_offset;
1016 
1017 /*
1018  *
1019  */
1020 static void
1021 acpica_pr_buf(char *buf, int buflen)
1022 {
1023 	char c, *bufp, *outp;
1024 	int	out_remaining;
1025 
1026 	/*
1027 	 * copy the supplied buffer into the output buffer
1028 	 * when we hit a '\n' or overflow the output buffer,
1029 	 * output and reset the output buffer
1030 	 */
1031 	bufp = buf;
1032 	outp = acpica_outbuf + acpica_outbuf_offset;
1033 	out_remaining = ACPICA_OUTBUF_LEN - acpica_outbuf_offset - 1;
1034 	while (c = *bufp++) {
1035 		*outp++ = c;
1036 		if (c == '\n' || --out_remaining == 0) {
1037 			*outp = '\0';
1038 			if (acpica_console_out)
1039 				printf(acpica_outbuf);
1040 			else
1041 				(void) strlog(0, 0, 0,
1042 				    SL_CONSOLE | SL_NOTE | SL_LOGONLY,
1043 				    acpica_outbuf);
1044 			acpica_outbuf_offset = 0;
1045 			outp = acpica_outbuf;
1046 			out_remaining = ACPICA_OUTBUF_LEN - 1;
1047 		}
1048 	}
1049 
1050 	acpica_outbuf_offset = outp - acpica_outbuf;
1051 	kmem_free(buf, buflen);
1052 }
1053 
1054 void
1055 AcpiOsVprintf(const char *Format, va_list Args)
1056 {
1057 	va_list	save;
1058 	int	buflen;
1059 	char	*buf;
1060 
1061 	/*
1062 	 * Try to be nice and emit the message via strlog().
1063 	 * Unfortunately, vstrlog() doesn't define the format
1064 	 * string as const char, so we allocate a local buffer
1065 	 * use vsnprintf().
1066 	 *
1067 	 * If we fail to allocate a string buffer, we resort
1068 	 * to printf().
1069 	 */
1070 	va_copy(save, Args);
1071 	buflen = vsnprintf(NULL, 0, Format, save) + 1;
1072 	buf = kmem_alloc(buflen, KM_NOSLEEP);
1073 	if (buf == NULL) {
1074 		vprintf(Format, Args);
1075 		return;
1076 	}
1077 	(void) vsnprintf(buf, buflen, Format, Args);
1078 	acpica_pr_buf(buf, buflen);
1079 }
1080 
1081 void
1082 AcpiOsRedirectOutput(void *Destination)
1083 {
1084 	_NOTE(ARGUNUSED(Destination))
1085 
1086 	/* FUTUREWORK: debugger support */
1087 
1088 #ifdef	DEBUG
1089 	cmn_err(CE_WARN, "!acpica: AcpiOsRedirectOutput called");
1090 #endif
1091 }
1092 
1093 
1094 UINT32
1095 AcpiOsGetLine(char *Buffer)
1096 {
1097 	_NOTE(ARGUNUSED(Buffer))
1098 
1099 	/* FUTUREWORK: debugger support */
1100 
1101 	return (0);
1102 }
1103 
1104 
1105 
1106 
1107 /*
1108  * Device tree binding
1109  */
1110 
1111 static int
1112 acpica_find_pcibus(int busno, ACPI_HANDLE *rh)
1113 {
1114 	ACPI_HANDLE sbobj, busobj;
1115 	int hid, bbn;
1116 
1117 	/* initialize static flag by querying ACPI namespace for bug */
1118 	if (acpi_has_broken_bbn == -1)
1119 		acpi_has_broken_bbn = acpica_query_bbn_problem();
1120 
1121 	busobj = NULL;
1122 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
1123 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
1124 	    &busobj) == AE_OK) {
1125 		if (acpica_eval_hid(busobj, "_HID", &hid) == AE_OK &&
1126 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS)) {
1127 			if (acpi_has_broken_bbn) {
1128 				ACPI_BUFFER rb;
1129 				rb.Pointer = NULL;
1130 				rb.Length = ACPI_ALLOCATE_BUFFER;
1131 
1132 				/* Decree _BBN == n from PCI<n> */
1133 				if (AcpiGetName(busobj, ACPI_SINGLE_NAME, &rb)
1134 					    != AE_OK) {
1135 					return (AE_ERROR);
1136 				}
1137 				bbn = ((char *)rb.Pointer)[3] - '0';
1138 				AcpiOsFree(rb.Pointer);
1139 				if (bbn == busno || busno == 0) {
1140 					*rh = busobj;
1141 					return (AE_OK);
1142 				}
1143 			} else {
1144 				if (acpica_eval_int(busobj, "_BBN", &bbn) ==
1145 				    AE_OK) {
1146 					if (bbn == busno) {
1147 						*rh = busobj;
1148 						return (AE_OK);
1149 					}
1150 				} else if (busno == 0) {
1151 					*rh = busobj;
1152 					return (AE_OK);
1153 				}
1154 			}
1155 		}
1156 	}
1157 	return (AE_ERROR);
1158 }
1159 
1160 
1161 /*
1162  * Look for ACPI problem where _BBN is zero for multiple PCI buses
1163  * This is a clear ACPI bug, but we have a workaround in acpica_find_pcibus()
1164  * below if it exists.
1165  */
1166 static int
1167 acpica_query_bbn_problem(void)
1168 {
1169 	ACPI_HANDLE sbobj, busobj;
1170 	int hid, bbn;
1171 	int zerobbncnt;
1172 
1173 	busobj = NULL;
1174 	zerobbncnt = 0;
1175 
1176 	AcpiGetHandle(NULL, "\\_SB", &sbobj);
1177 
1178 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, sbobj, busobj,
1179 	    &busobj) == AE_OK) {
1180 		if ((acpica_eval_hid(busobj, "_HID", &hid) == AE_OK) &&
1181 		    (hid == HID_PCI_BUS || hid == HID_PCI_EXPRESS_BUS) &&
1182 		    (acpica_eval_int(busobj, "_BBN", &bbn) == AE_OK)) {
1183 			if (bbn == 0) {
1184 			/*
1185 			 * If we find more than one bus with a 0 _BBN
1186 			 * we have the problem that BigBear's BIOS shows
1187 			 */
1188 				if (++zerobbncnt > 1)
1189 					return (1);
1190 			}
1191 		}
1192 	}
1193 	return (0);
1194 }
1195 
1196 static const char hextab[] = "0123456789ABCDEF";
1197 
1198 static int
1199 hexdig(int c)
1200 {
1201 	/*
1202 	 *  Get hex digit:
1203 	 *
1204 	 *  Returns the 4-bit hex digit named by the input character.  Returns
1205 	 *  zero if the input character is not valid hex!
1206 	 */
1207 
1208 	int x = ((c < 'a') || (c > 'z')) ? c : (c - ' ');
1209 	int j = sizeof (hextab);
1210 
1211 	while (--j && (x != hextab[j]));
1212 	return (j);
1213 }
1214 
1215 static int
1216 CompressEisaID(char *np)
1217 {
1218 	/*
1219 	 *  Compress an EISA device name:
1220 	 *
1221 	 *  This routine converts a 7-byte ASCII device name into the 4-byte
1222 	 *  compressed form used by EISA (50 bytes of ROM to save 1 byte of
1223 	 *  NV-RAM!)
1224 	 */
1225 
1226 	union { char octets[4]; int retval; } myu;
1227 
1228 	myu.octets[0] = ((np[0] & 0x1F) << 2) + ((np[1] >> 3) & 0x03);
1229 	myu.octets[1] = ((np[1] & 0x07) << 5) + (np[2] & 0x1F);
1230 	myu.octets[2] = (hexdig(np[3]) << 4) + hexdig(np[4]);
1231 	myu.octets[3] = (hexdig(np[5]) << 4) + hexdig(np[6]);
1232 
1233 	return (myu.retval);
1234 }
1235 
1236 int
1237 acpica_eval_int(ACPI_HANDLE dev, char *method, int *rint)
1238 {
1239 	ACPI_STATUS status;
1240 	ACPI_BUFFER rb;
1241 	ACPI_OBJECT ro;
1242 
1243 	rb.Pointer = &ro;
1244 	rb.Length = sizeof (ro);
1245 	if ((status = AcpiEvaluateObjectTyped(dev, method, NULL, &rb,
1246 						ACPI_TYPE_INTEGER)) == AE_OK)
1247 		*rint = ro.Integer.Value;
1248 
1249 	return (status);
1250 }
1251 
1252 static int
1253 acpica_eval_hid(ACPI_HANDLE dev, char *method, int *rint)
1254 {
1255 	ACPI_BUFFER rb;
1256 	ACPI_OBJECT *rv;
1257 
1258 	rb.Pointer = NULL;
1259 	rb.Length = ACPI_ALLOCATE_BUFFER;
1260 	if (AcpiEvaluateObject(dev, method, NULL, &rb) == AE_OK) {
1261 		rv = rb.Pointer;
1262 		if (rv->Type == ACPI_TYPE_INTEGER) {
1263 			*rint = rv->Integer.Value;
1264 			AcpiOsFree(rv);
1265 			return (AE_OK);
1266 		} else if (rv->Type == ACPI_TYPE_STRING) {
1267 			char *stringData;
1268 
1269 			/* Convert the string into an EISA ID */
1270 			if (rv->String.Pointer == NULL) {
1271 				AcpiOsFree(rv);
1272 				return (AE_ERROR);
1273 			}
1274 
1275 			stringData = rv->String.Pointer;
1276 
1277 			/*
1278 			 * If the string is an EisaID, it must be 7
1279 			 * characters; if it's an ACPI ID, it will be 8
1280 			 * (and we don't care about ACPI ids here).
1281 			 */
1282 			if (strlen(stringData) != 7) {
1283 				AcpiOsFree(rv);
1284 				return (AE_ERROR);
1285 			}
1286 
1287 			*rint = CompressEisaID(stringData);
1288 			AcpiOsFree(rv);
1289 			return (AE_OK);
1290 		} else
1291 			AcpiOsFree(rv);
1292 	}
1293 	return (AE_ERROR);
1294 }
1295 
1296 /*
1297  * Return the d2a node matching this ACPI_HANDLE, if one exists
1298  */
1299 int
1300 acpica_find_pcid2a(ACPI_HANDLE rh, d2a **dp)
1301 {
1302 	d2a *d2ap;
1303 	int i;
1304 
1305 	if (d2a_len == 0)
1306 		create_d2a_map();
1307 	for (d2ap = d2a_table, i = 0; i < d2a_valid; d2ap++, i++)
1308 		if (d2ap->acpiobj == rh) {
1309 			*dp = d2ap;
1310 			return (AE_OK);
1311 		}
1312 
1313 	return (AE_ERROR);
1314 }
1315 
1316 
1317 /*
1318  * Return the ACPI device node matching this dev_info node, if it
1319  * exists in the ACPI tree.
1320  */
1321 int
1322 acpica_find_pciobj(dev_info_t *dip, ACPI_HANDLE *rh)
1323 {
1324 	d2a *d2ap;
1325 	int i;
1326 
1327 	if (d2a_len == 0)
1328 		create_d2a_map();
1329 	for (d2ap = d2a_table, i = 0; i < d2a_valid; d2ap++, i++)
1330 		if (d2ap->dip == dip) {
1331 			*rh = d2ap->acpiobj;
1332 			return (AE_OK);
1333 		}
1334 
1335 	return (AE_ERROR);
1336 }
1337 
1338 /*
1339  * Create a table mapping PCI dips to ACPI objects
1340  */
1341 static void
1342 new_d2a_entry(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus, int dev, int func)
1343 {
1344 	int newsize;
1345 	d2a *new_arr, *ep;
1346 
1347 	if (d2a_valid >= d2a_len) {
1348 		/* initially, or re-, allocate array */
1349 
1350 		newsize = (d2a_len ? d2a_len * 2 : D2A_INITLEN);
1351 		new_arr = kmem_zalloc(newsize * sizeof (d2a), KM_SLEEP);
1352 		if (d2a_len != 0) {
1353 			/* realloc: copy data, free old */
1354 			bcopy(d2a_table, new_arr, d2a_len * sizeof (d2a));
1355 			kmem_free(d2a_table, d2a_len * sizeof (d2a));
1356 		}
1357 		d2a_len = newsize;
1358 		d2a_table = new_arr;
1359 	}
1360 	ep = &d2a_table[d2a_valid++];
1361 	ep->bus = (unsigned char)bus;
1362 	ep->dev = (unsigned char)dev;
1363 	ep->func = (unsigned char)func;
1364 	ep->dip = dip;
1365 	ep->acpiobj = acpiobj;
1366 #ifdef D2ADEBUG
1367 	{
1368 		ACPI_BUFFER rb;
1369 		char pathname[60];
1370 		ddi_pathname(dip, pathname);
1371 
1372 		rb.Pointer = NULL;
1373 		rb.Length = ACPI_ALLOCATE_BUFFER;
1374 		if (AcpiGetName(acpiobj, ACPI_FULL_PATHNAME, &rb) == AE_OK) {
1375 
1376 			cmn_err(CE_NOTE, "d2a entry: %s %s %d/0x%x/%d",
1377 				pathname, (char *)rb.Pointer, bus, dev, func);
1378 			AcpiOsFree(rb.Pointer);
1379 		}
1380 	}
1381 #endif
1382 }
1383 
1384 static void
1385 create_d2a_map(void)
1386 {
1387 	dev_info_t *dip, *cdip;
1388 	ACPI_HANDLE acpiobj;
1389 	char *device_type_prop;
1390 	int bus;
1391 	static int map_error = 0;
1392 
1393 	if (map_error)
1394 		return;
1395 
1396 	creating_d2a_map = 1;
1397 
1398 	/*
1399 	 * Find all child-of-root PCI buses, and find their corresponding
1400 	 * ACPI child-of-root PCI nodes.  For each one, add to the
1401 	 * d2a table.
1402 	 */
1403 
1404 	for (dip = ddi_get_child(ddi_root_node());
1405 	    dip != NULL;
1406 	    dip = ddi_get_next_sibling(dip)) {
1407 
1408 		/* prune non-PCI nodes */
1409 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
1410 		    "device_type", &device_type_prop) != DDI_PROP_SUCCESS)
1411 			continue;
1412 
1413 		if ((strcmp("pci", device_type_prop) != 0) &&
1414 		    (strcmp("pciex", device_type_prop) != 0)) {
1415 			ddi_prop_free(device_type_prop);
1416 			continue;
1417 		}
1418 
1419 		ddi_prop_free(device_type_prop);
1420 
1421 		/*
1422 		 * To get bus number of dip, get first child and get its
1423 		 * bus number.  If NULL, just continue, because we don't
1424 		 * care about bus nodes with no children anyway.
1425 		 */
1426 		if ((cdip = ddi_get_child(dip)) == NULL)
1427 			continue;
1428 
1429 		if (acpica_get_bdf(cdip, &bus, NULL, NULL) < 0) {
1430 #ifdef D2ADEBUG
1431 			cmn_err(CE_WARN, "Can't get bus number of PCI child?");
1432 #endif
1433 			map_error = 1;
1434 			creating_d2a_map = 0;
1435 			return;
1436 		}
1437 
1438 		if (acpica_find_pcibus(bus, &acpiobj) == AE_ERROR) {
1439 #ifdef D2ADEBUG
1440 			cmn_err(CE_WARN, "No ACPI bus obj for bus %d?\n", bus);
1441 #endif
1442 			map_error = 1;
1443 			continue;
1444 		}
1445 
1446 		/*
1447 		 * map this node, with illegal device and fn numbers
1448 		 * (since, as a PCI root node, it exists on the system
1449 		 * bus
1450 		 */
1451 
1452 		new_d2a_entry(dip, acpiobj, bus, 32, 8);
1453 
1454 		/* call recursive function to enumerate subtrees */
1455 		create_d2a_subtree(dip, acpiobj, bus);
1456 	}
1457 	creating_d2a_map = 0;
1458 }
1459 
1460 /*
1461  * For all acpi child devices of acpiobj, find their matching
1462  * dip under "dip" argument.  (matching means "matches dev/fn").
1463  * bus is assumed to already be a match from caller, and is
1464  * used here only to record in the d2a entry.  Recurse if necessary.
1465  */
1466 static void
1467 create_d2a_subtree(dev_info_t *dip, ACPI_HANDLE acpiobj, int bus)
1468 {
1469 	int acpi_devfn, hid;
1470 	ACPI_HANDLE acld;
1471 	dev_info_t *dcld;
1472 	int dcld_b, dcld_d, dcld_f;
1473 	int dev, func;
1474 
1475 	acld = NULL;
1476 	while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpiobj, acld, &acld)
1477 	    == AE_OK) {
1478 
1479 		/*
1480 		 * Skip ACPI devices that are obviously not PCI, i.e.,
1481 		 * that have a _HID that is *not* the PCI HID
1482 		 */
1483 
1484 		if (acpica_eval_hid(acld, "_HID", &hid) == AE_OK &&
1485 		    hid != HID_PCI_BUS && hid != HID_PCI_EXPRESS_BUS)
1486 			continue;
1487 
1488 		/* get the dev/func we're looking for in the devinfo tree */
1489 		if (acpica_eval_int(acld, "_ADR", &acpi_devfn) != AE_OK)
1490 			continue;
1491 		dev = (acpi_devfn >> 16) & 0xFFFF;
1492 		func = acpi_devfn & 0xFFFF;
1493 
1494 		/* look through all the immediate children of dip */
1495 		for (dcld = ddi_get_child(dip); dcld != NULL;
1496 		    dcld = ddi_get_next_sibling(dcld)) {
1497 			if (acpica_get_bdf(dcld, &dcld_b, &dcld_d, &dcld_f) < 0)
1498 				continue;
1499 
1500 			/* dev must match; function must match or wildcard */
1501 			if (dcld_d != dev ||
1502 			    (func != 0xFFFF && func != dcld_f))
1503 				continue;
1504 			bus = dcld_b;
1505 
1506 			/* found a match, record it */
1507 			new_d2a_entry(dcld, acld, bus, dev, func);
1508 
1509 			/* recurse from here to pick up child trees */
1510 			create_d2a_subtree(dcld, acld, bus);
1511 
1512 			/* done finding a match, so break now */
1513 			break;
1514 		}
1515 	}
1516 }
1517 
1518 /*
1519  * Return bus/dev/fn for PCI dip (note: not the parent "pci" node).
1520  */
1521 
1522 int
1523 acpica_get_bdf(dev_info_t *dip, int *bus, int *device, int *func)
1524 {
1525 	pci_regspec_t *pci_rp;
1526 	int len;
1527 
1528 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1529 	    "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS)
1530 		return (-1);
1531 
1532 	if (len < (sizeof (pci_regspec_t) / sizeof (int))) {
1533 		ddi_prop_free(pci_rp);
1534 		return (-1);
1535 	}
1536 	if (bus != NULL)
1537 		*bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1538 	if (device != NULL)
1539 		*device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1540 	if (func != NULL)
1541 		*func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1542 	ddi_prop_free(pci_rp);
1543 	return (0);
1544 }
1545