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