1b72d5b75SMichael Corcoran /*
2b72d5b75SMichael Corcoran  * CDDL HEADER START
3b72d5b75SMichael Corcoran  *
4b72d5b75SMichael Corcoran  * The contents of this file are subject to the terms of the
5b72d5b75SMichael Corcoran  * Common Development and Distribution License (the "License").
6b72d5b75SMichael Corcoran  * You may not use this file except in compliance with the License.
7b72d5b75SMichael Corcoran  *
8b72d5b75SMichael Corcoran  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9b72d5b75SMichael Corcoran  * or http://www.opensolaris.org/os/licensing.
10b72d5b75SMichael Corcoran  * See the License for the specific language governing permissions
11b72d5b75SMichael Corcoran  * and limitations under the License.
12b72d5b75SMichael Corcoran  *
13b72d5b75SMichael Corcoran  * When distributing Covered Code, include this CDDL HEADER in each
14b72d5b75SMichael Corcoran  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15b72d5b75SMichael Corcoran  * If applicable, add the following below this CDDL HEADER, with the
16b72d5b75SMichael Corcoran  * fields enclosed by brackets "[]" replaced with your own identifying
17b72d5b75SMichael Corcoran  * information: Portions Copyright [yyyy] [name of copyright owner]
18b72d5b75SMichael Corcoran  *
19b72d5b75SMichael Corcoran  * CDDL HEADER END
20b72d5b75SMichael Corcoran  */
2157190917SDana Myers /*
2257190917SDana Myers  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2357190917SDana Myers  * Use is subject to license terms.
24*7b1019a6SJerry Jelinek  *
25*7b1019a6SJerry Jelinek  * Copyright 2016, Joyent, Inc.
2657190917SDana Myers  */
27b72d5b75SMichael Corcoran /*
28a3114836SGerry Liu  * Copyright (c) 2009-2010, Intel Corporation.
29b72d5b75SMichael Corcoran  * All rights reserved.
30b72d5b75SMichael Corcoran  */
31b72d5b75SMichael Corcoran 
32b72d5b75SMichael Corcoran #include <sys/types.h>
33b72d5b75SMichael Corcoran #include <sys/cmn_err.h>
34b72d5b75SMichael Corcoran #include <sys/sysmacros.h>
35b72d5b75SMichael Corcoran #include <sys/sunddi.h>
36b72d5b75SMichael Corcoran #include <sys/sunndi.h>
37b72d5b75SMichael Corcoran #include <sys/acpi/acpi.h>
38b72d5b75SMichael Corcoran #include <sys/acpica.h>
39b72d5b75SMichael Corcoran #include <sys/acpidev.h>
40b72d5b75SMichael Corcoran #include <sys/acpidev_rsc.h>
41b72d5b75SMichael Corcoran #include <sys/acpidev_impl.h>
42b72d5b75SMichael Corcoran 
43b72d5b75SMichael Corcoran #define	ACPIDEV_RES_INIT_ITEMS		8
44b72d5b75SMichael Corcoran #define	ACPIDEV_RES_INCR_ITEMS		8
45b72d5b75SMichael Corcoran 
46b72d5b75SMichael Corcoran /* Data structure to hold parsed resources during walking. */
47b72d5b75SMichael Corcoran struct acpidev_resource_handle {
48b72d5b75SMichael Corcoran 	boolean_t			acpidev_consumer;
49b72d5b75SMichael Corcoran 	int				acpidev_reg_count;
50b72d5b75SMichael Corcoran 	int				acpidev_reg_max;
51b72d5b75SMichael Corcoran 	acpidev_phys_spec_t		*acpidev_regp;
52b72d5b75SMichael Corcoran 	acpidev_phys_spec_t		acpidev_regs[ACPIDEV_RES_INIT_ITEMS];
53b72d5b75SMichael Corcoran 	int				acpidev_range_count;
54b72d5b75SMichael Corcoran 	int				acpidev_range_max;
55b72d5b75SMichael Corcoran 	acpidev_ranges_t		*acpidev_rangep;
56b72d5b75SMichael Corcoran 	acpidev_ranges_t		acpidev_ranges[ACPIDEV_RES_INIT_ITEMS];
57b72d5b75SMichael Corcoran 	int				acpidev_bus_count;
58b72d5b75SMichael Corcoran 	int				acpidev_bus_max;
59b72d5b75SMichael Corcoran 	acpidev_bus_range_t		*acpidev_busp;
60b72d5b75SMichael Corcoran 	acpidev_bus_range_t		acpidev_buses[ACPIDEV_RES_INIT_ITEMS];
61b72d5b75SMichael Corcoran 	int				acpidev_irq_count;
62b72d5b75SMichael Corcoran 	int				acpidev_irqp[ACPIDEV_RES_IRQ_MAX];
63b72d5b75SMichael Corcoran 	int				acpidev_dma_count;
64b72d5b75SMichael Corcoran 	int				acpidev_dmap[ACPIDEV_RES_DMA_MAX];
65b72d5b75SMichael Corcoran };
66b72d5b75SMichael Corcoran 
67b72d5b75SMichael Corcoran acpidev_resource_handle_t
acpidev_resource_handle_alloc(boolean_t consumer)68b72d5b75SMichael Corcoran acpidev_resource_handle_alloc(boolean_t consumer)
69b72d5b75SMichael Corcoran {
70b72d5b75SMichael Corcoran 	acpidev_resource_handle_t rhdl;
71b72d5b75SMichael Corcoran 
72b72d5b75SMichael Corcoran 	rhdl = kmem_zalloc(sizeof (*rhdl), KM_SLEEP);
73b72d5b75SMichael Corcoran 	rhdl->acpidev_consumer = consumer;
74b72d5b75SMichael Corcoran 	rhdl->acpidev_reg_max = ACPIDEV_RES_INIT_ITEMS;
75b72d5b75SMichael Corcoran 	rhdl->acpidev_regp = rhdl->acpidev_regs;
76b72d5b75SMichael Corcoran 	rhdl->acpidev_range_max = ACPIDEV_RES_INIT_ITEMS;
77b72d5b75SMichael Corcoran 	rhdl->acpidev_rangep = rhdl->acpidev_ranges;
78b72d5b75SMichael Corcoran 	rhdl->acpidev_bus_max = ACPIDEV_RES_INIT_ITEMS;
79b72d5b75SMichael Corcoran 	rhdl->acpidev_busp = rhdl->acpidev_buses;
80b72d5b75SMichael Corcoran 
81b72d5b75SMichael Corcoran 	return (rhdl);
82b72d5b75SMichael Corcoran }
83b72d5b75SMichael Corcoran 
84b72d5b75SMichael Corcoran void
acpidev_resource_handle_free(acpidev_resource_handle_t rhdl)85b72d5b75SMichael Corcoran acpidev_resource_handle_free(acpidev_resource_handle_t rhdl)
86b72d5b75SMichael Corcoran {
87b72d5b75SMichael Corcoran 	size_t sz;
88b72d5b75SMichael Corcoran 
89b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
90b72d5b75SMichael Corcoran 	if (rhdl != NULL) {
91b72d5b75SMichael Corcoran 		if (rhdl->acpidev_regp != rhdl->acpidev_regs) {
92b72d5b75SMichael Corcoran 			sz = sizeof (acpidev_phys_spec_t) *
93b72d5b75SMichael Corcoran 			    rhdl->acpidev_reg_max;
94b72d5b75SMichael Corcoran 			kmem_free(rhdl->acpidev_regp, sz);
95b72d5b75SMichael Corcoran 		}
96b72d5b75SMichael Corcoran 		if (rhdl->acpidev_rangep != rhdl->acpidev_ranges) {
97b72d5b75SMichael Corcoran 			sz = sizeof (acpidev_ranges_t) *
98b72d5b75SMichael Corcoran 			    rhdl->acpidev_range_max;
99b72d5b75SMichael Corcoran 			kmem_free(rhdl->acpidev_rangep, sz);
100b72d5b75SMichael Corcoran 		}
101b72d5b75SMichael Corcoran 		if (rhdl->acpidev_busp != rhdl->acpidev_buses) {
102b72d5b75SMichael Corcoran 			sz = sizeof (acpidev_bus_range_t) *
103b72d5b75SMichael Corcoran 			    rhdl->acpidev_bus_max;
104b72d5b75SMichael Corcoran 			kmem_free(rhdl->acpidev_busp, sz);
105b72d5b75SMichael Corcoran 		}
106b72d5b75SMichael Corcoran 		kmem_free(rhdl, sizeof (struct acpidev_resource_handle));
107b72d5b75SMichael Corcoran 	}
108b72d5b75SMichael Corcoran }
109b72d5b75SMichael Corcoran 
110b72d5b75SMichael Corcoran static void
acpidev_resource_handle_grow(acpidev_resource_handle_t rhdl)111b72d5b75SMichael Corcoran acpidev_resource_handle_grow(acpidev_resource_handle_t rhdl)
112b72d5b75SMichael Corcoran {
113b72d5b75SMichael Corcoran 	size_t sz;
114b72d5b75SMichael Corcoran 
115b72d5b75SMichael Corcoran 	if (rhdl->acpidev_reg_count == rhdl->acpidev_reg_max) {
116b72d5b75SMichael Corcoran 		acpidev_phys_spec_t *regp;
117b72d5b75SMichael Corcoran 
118b72d5b75SMichael Corcoran 		/* Prefer linear incremental here. */
119b72d5b75SMichael Corcoran 		rhdl->acpidev_reg_max += ACPIDEV_RES_INCR_ITEMS;
120b72d5b75SMichael Corcoran 		sz = sizeof (*regp) * rhdl->acpidev_reg_max;
121b72d5b75SMichael Corcoran 		regp = kmem_zalloc(sz, KM_SLEEP);
122b72d5b75SMichael Corcoran 		sz = sizeof (*regp) * rhdl->acpidev_reg_count;
123b72d5b75SMichael Corcoran 		bcopy(rhdl->acpidev_regp, regp, sz);
124b72d5b75SMichael Corcoran 		if (rhdl->acpidev_regp != rhdl->acpidev_regs) {
125b72d5b75SMichael Corcoran 			kmem_free(rhdl->acpidev_regp, sz);
126b72d5b75SMichael Corcoran 		}
127b72d5b75SMichael Corcoran 		rhdl->acpidev_regp = regp;
128b72d5b75SMichael Corcoran 	}
129b72d5b75SMichael Corcoran 
130b72d5b75SMichael Corcoran 	if (rhdl->acpidev_range_count == rhdl->acpidev_range_max) {
131b72d5b75SMichael Corcoran 		acpidev_ranges_t *rngp;
132b72d5b75SMichael Corcoran 
133b72d5b75SMichael Corcoran 		/* Prefer linear incremental here. */
134b72d5b75SMichael Corcoran 		rhdl->acpidev_range_max += ACPIDEV_RES_INCR_ITEMS;
135b72d5b75SMichael Corcoran 		sz = sizeof (*rngp) * rhdl->acpidev_range_max;
136b72d5b75SMichael Corcoran 		rngp = kmem_zalloc(sz, KM_SLEEP);
137b72d5b75SMichael Corcoran 		sz = sizeof (*rngp) * rhdl->acpidev_range_count;
138b72d5b75SMichael Corcoran 		bcopy(rhdl->acpidev_rangep, rngp, sz);
139b72d5b75SMichael Corcoran 		if (rhdl->acpidev_rangep != rhdl->acpidev_ranges) {
140b72d5b75SMichael Corcoran 			kmem_free(rhdl->acpidev_rangep, sz);
141b72d5b75SMichael Corcoran 		}
142b72d5b75SMichael Corcoran 		rhdl->acpidev_rangep = rngp;
143b72d5b75SMichael Corcoran 	}
144b72d5b75SMichael Corcoran 
145b72d5b75SMichael Corcoran 	if (rhdl->acpidev_bus_count == rhdl->acpidev_bus_max) {
146b72d5b75SMichael Corcoran 		acpidev_bus_range_t *busp;
147b72d5b75SMichael Corcoran 
148b72d5b75SMichael Corcoran 		/* Prefer linear incremental here. */
149b72d5b75SMichael Corcoran 		rhdl->acpidev_bus_max += ACPIDEV_RES_INCR_ITEMS;
150b72d5b75SMichael Corcoran 		sz = sizeof (*busp) * rhdl->acpidev_bus_max;
151b72d5b75SMichael Corcoran 		busp = kmem_zalloc(sz, KM_SLEEP);
152b72d5b75SMichael Corcoran 		sz = sizeof (*busp) * rhdl->acpidev_bus_count;
153b72d5b75SMichael Corcoran 		bcopy(rhdl->acpidev_busp, busp, sz);
154b72d5b75SMichael Corcoran 		if (rhdl->acpidev_busp != rhdl->acpidev_buses) {
155b72d5b75SMichael Corcoran 			kmem_free(rhdl->acpidev_busp, sz);
156b72d5b75SMichael Corcoran 		}
157b72d5b75SMichael Corcoran 		rhdl->acpidev_busp = busp;
158b72d5b75SMichael Corcoran 	}
159b72d5b75SMichael Corcoran }
160b72d5b75SMichael Corcoran 
161b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_insert_reg(acpidev_resource_handle_t rhdl,acpidev_regspec_t * regp)162b72d5b75SMichael Corcoran acpidev_resource_insert_reg(acpidev_resource_handle_t rhdl,
163b72d5b75SMichael Corcoran     acpidev_regspec_t *regp)
164b72d5b75SMichael Corcoran {
165b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
166b72d5b75SMichael Corcoran 	ASSERT(regp != NULL);
167b72d5b75SMichael Corcoran 	if (rhdl->acpidev_reg_count >= rhdl->acpidev_reg_max) {
168b72d5b75SMichael Corcoran 		acpidev_resource_handle_grow(rhdl);
169b72d5b75SMichael Corcoran 	}
170b72d5b75SMichael Corcoran 	ASSERT(rhdl->acpidev_reg_count < rhdl->acpidev_reg_max);
171b72d5b75SMichael Corcoran 	rhdl->acpidev_regp[rhdl->acpidev_reg_count] = *regp;
172b72d5b75SMichael Corcoran 	rhdl->acpidev_reg_count++;
173b72d5b75SMichael Corcoran 
174b72d5b75SMichael Corcoran 	return (AE_OK);
175b72d5b75SMichael Corcoran }
176b72d5b75SMichael Corcoran 
177b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_get_regs(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value,acpidev_regspec_t * regp,uint_t * cntp)178b72d5b75SMichael Corcoran acpidev_resource_get_regs(acpidev_resource_handle_t rhdl,
179b72d5b75SMichael Corcoran     uint_t mask, uint_t value, acpidev_regspec_t *regp, uint_t *cntp)
180b72d5b75SMichael Corcoran {
181b72d5b75SMichael Corcoran 	uint_t i, j;
182b72d5b75SMichael Corcoran 
183b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
184b72d5b75SMichael Corcoran 	ASSERT(cntp != NULL);
185b72d5b75SMichael Corcoran 	if (rhdl == NULL || cntp == NULL || (regp == NULL && *cntp != 0)) {
186b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
187b72d5b75SMichael Corcoran 	}
188b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_reg_count; i++) {
189b72d5b75SMichael Corcoran 		if ((rhdl->acpidev_regp[i].phys_hi & mask) == value) {
190b72d5b75SMichael Corcoran 			if (j < *cntp) {
191b72d5b75SMichael Corcoran 				regp[j] = rhdl->acpidev_regp[i];
192b72d5b75SMichael Corcoran 			}
193b72d5b75SMichael Corcoran 			j++;
194b72d5b75SMichael Corcoran 		}
195b72d5b75SMichael Corcoran 	}
196b72d5b75SMichael Corcoran 	if (j >= *cntp) {
197b72d5b75SMichael Corcoran 		*cntp = j;
198b72d5b75SMichael Corcoran 		return (AE_LIMIT);
199b72d5b75SMichael Corcoran 	} else {
200b72d5b75SMichael Corcoran 		*cntp = j;
201b72d5b75SMichael Corcoran 		return (AE_OK);
202b72d5b75SMichael Corcoran 	}
203b72d5b75SMichael Corcoran }
204b72d5b75SMichael Corcoran 
205b72d5b75SMichael Corcoran uint_t
acpidev_resource_get_reg_count(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value)206b72d5b75SMichael Corcoran acpidev_resource_get_reg_count(acpidev_resource_handle_t rhdl,
207b72d5b75SMichael Corcoran     uint_t mask, uint_t value)
208b72d5b75SMichael Corcoran {
209b72d5b75SMichael Corcoran 	uint_t i, j;
210b72d5b75SMichael Corcoran 
211b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
212b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_reg_count; i++) {
213b72d5b75SMichael Corcoran 		if ((rhdl->acpidev_regp[i].phys_hi & mask) == value) {
214b72d5b75SMichael Corcoran 			j++;
215b72d5b75SMichael Corcoran 		}
216b72d5b75SMichael Corcoran 	}
217b72d5b75SMichael Corcoran 
218b72d5b75SMichael Corcoran 	return (j);
219b72d5b75SMichael Corcoran }
220b72d5b75SMichael Corcoran 
221b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_insert_range(acpidev_resource_handle_t rhdl,acpidev_ranges_t * rangep)222b72d5b75SMichael Corcoran acpidev_resource_insert_range(acpidev_resource_handle_t rhdl,
223b72d5b75SMichael Corcoran     acpidev_ranges_t *rangep)
224b72d5b75SMichael Corcoran {
225b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
226b72d5b75SMichael Corcoran 	ASSERT(rangep != NULL);
227b72d5b75SMichael Corcoran 	if (rhdl->acpidev_range_count >= rhdl->acpidev_range_max) {
228b72d5b75SMichael Corcoran 		acpidev_resource_handle_grow(rhdl);
229b72d5b75SMichael Corcoran 	}
230b72d5b75SMichael Corcoran 	ASSERT(rhdl->acpidev_range_count < rhdl->acpidev_range_max);
231b72d5b75SMichael Corcoran 	rhdl->acpidev_rangep[rhdl->acpidev_range_count] = *rangep;
232b72d5b75SMichael Corcoran 	rhdl->acpidev_range_count++;
233b72d5b75SMichael Corcoran 
234b72d5b75SMichael Corcoran 	return (AE_OK);
235b72d5b75SMichael Corcoran }
236b72d5b75SMichael Corcoran 
237b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_get_ranges(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value,acpidev_ranges_t * rangep,uint_t * cntp)238b72d5b75SMichael Corcoran acpidev_resource_get_ranges(acpidev_resource_handle_t rhdl,
239b72d5b75SMichael Corcoran     uint_t mask, uint_t value, acpidev_ranges_t *rangep, uint_t *cntp)
240b72d5b75SMichael Corcoran {
241b72d5b75SMichael Corcoran 	uint_t i, j;
242b72d5b75SMichael Corcoran 
243b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
244b72d5b75SMichael Corcoran 	ASSERT(cntp != NULL);
245b72d5b75SMichael Corcoran 	if (rhdl == NULL || cntp == NULL || (rangep == NULL && *cntp != 0)) {
246b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
247b72d5b75SMichael Corcoran 	}
248b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_range_count; i++) {
249b72d5b75SMichael Corcoran 		if ((rhdl->acpidev_rangep[i].child_hi & mask) == value) {
250b72d5b75SMichael Corcoran 			if (j < *cntp) {
251b72d5b75SMichael Corcoran 				rangep[j] = rhdl->acpidev_rangep[i];
252b72d5b75SMichael Corcoran 			}
253b72d5b75SMichael Corcoran 			j++;
254b72d5b75SMichael Corcoran 		}
255b72d5b75SMichael Corcoran 	}
256b72d5b75SMichael Corcoran 	if (j >= *cntp) {
257b72d5b75SMichael Corcoran 		*cntp = j;
258b72d5b75SMichael Corcoran 		return (AE_LIMIT);
259b72d5b75SMichael Corcoran 	} else {
260b72d5b75SMichael Corcoran 		*cntp = j;
261b72d5b75SMichael Corcoran 		return (AE_OK);
262b72d5b75SMichael Corcoran 	}
263b72d5b75SMichael Corcoran }
264b72d5b75SMichael Corcoran 
265b72d5b75SMichael Corcoran uint_t
acpidev_resource_get_range_count(acpidev_resource_handle_t rhdl,uint_t mask,uint_t value)266b72d5b75SMichael Corcoran acpidev_resource_get_range_count(acpidev_resource_handle_t rhdl,
267b72d5b75SMichael Corcoran     uint_t mask, uint_t value)
268b72d5b75SMichael Corcoran {
269b72d5b75SMichael Corcoran 	uint_t i, j;
270b72d5b75SMichael Corcoran 
271b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
272b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_range_count; i++) {
273b72d5b75SMichael Corcoran 		if ((rhdl->acpidev_rangep[i].child_hi & mask) == value) {
274b72d5b75SMichael Corcoran 			j++;
275b72d5b75SMichael Corcoran 		}
276b72d5b75SMichael Corcoran 	}
277b72d5b75SMichael Corcoran 
278b72d5b75SMichael Corcoran 	return (j);
279b72d5b75SMichael Corcoran }
280b72d5b75SMichael Corcoran 
281b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_insert_bus(acpidev_resource_handle_t rhdl,acpidev_bus_range_t * busp)282b72d5b75SMichael Corcoran acpidev_resource_insert_bus(acpidev_resource_handle_t rhdl,
283b72d5b75SMichael Corcoran     acpidev_bus_range_t *busp)
284b72d5b75SMichael Corcoran {
285b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
286b72d5b75SMichael Corcoran 	ASSERT(busp != NULL);
287b72d5b75SMichael Corcoran 	if (rhdl->acpidev_bus_count >= rhdl->acpidev_bus_max) {
288b72d5b75SMichael Corcoran 		acpidev_resource_handle_grow(rhdl);
289b72d5b75SMichael Corcoran 	}
290b72d5b75SMichael Corcoran 	ASSERT(rhdl->acpidev_bus_count < rhdl->acpidev_bus_max);
291b72d5b75SMichael Corcoran 	rhdl->acpidev_busp[rhdl->acpidev_bus_count] = *busp;
292b72d5b75SMichael Corcoran 	rhdl->acpidev_bus_count++;
293b72d5b75SMichael Corcoran 
294b72d5b75SMichael Corcoran 	return (AE_OK);
295b72d5b75SMichael Corcoran }
296b72d5b75SMichael Corcoran 
297b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_get_buses(acpidev_resource_handle_t rhdl,acpidev_bus_range_t * busp,uint_t * cntp)298b72d5b75SMichael Corcoran acpidev_resource_get_buses(acpidev_resource_handle_t rhdl,
299b72d5b75SMichael Corcoran     acpidev_bus_range_t *busp, uint_t *cntp)
300b72d5b75SMichael Corcoran {
301b72d5b75SMichael Corcoran 	uint_t i, j;
302b72d5b75SMichael Corcoran 
303b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
304b72d5b75SMichael Corcoran 	ASSERT(cntp != NULL);
305b72d5b75SMichael Corcoran 	if (rhdl == NULL || cntp == NULL || (busp == NULL && *cntp != 0)) {
306b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
307b72d5b75SMichael Corcoran 	}
308b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_bus_count; i++) {
309b72d5b75SMichael Corcoran 		if (j < *cntp) {
310b72d5b75SMichael Corcoran 			busp[j] = rhdl->acpidev_busp[i];
311b72d5b75SMichael Corcoran 		}
312b72d5b75SMichael Corcoran 		j++;
313b72d5b75SMichael Corcoran 	}
314b72d5b75SMichael Corcoran 	if (j >= *cntp) {
315b72d5b75SMichael Corcoran 		*cntp = j;
316b72d5b75SMichael Corcoran 		return (AE_LIMIT);
317b72d5b75SMichael Corcoran 	} else {
318b72d5b75SMichael Corcoran 		*cntp = j;
319b72d5b75SMichael Corcoran 		return (AE_OK);
320b72d5b75SMichael Corcoran 	}
321b72d5b75SMichael Corcoran }
322b72d5b75SMichael Corcoran 
323b72d5b75SMichael Corcoran uint_t
acpidev_resource_get_bus_count(acpidev_resource_handle_t rhdl)324b72d5b75SMichael Corcoran acpidev_resource_get_bus_count(acpidev_resource_handle_t rhdl)
325b72d5b75SMichael Corcoran {
326b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
327b72d5b75SMichael Corcoran 	return (rhdl->acpidev_bus_count);
328b72d5b75SMichael Corcoran }
329b72d5b75SMichael Corcoran 
330b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_insert_dma(acpidev_resource_handle_t rhdl,int dma)331b72d5b75SMichael Corcoran acpidev_resource_insert_dma(acpidev_resource_handle_t rhdl, int dma)
332b72d5b75SMichael Corcoran {
333b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
334b72d5b75SMichael Corcoran 	if (rhdl->acpidev_dma_count >= ACPIDEV_RES_DMA_MAX) {
335b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_WARN,
336a3114836SGerry Liu 		    "!acpidev: too many DMA resources, max %u.",
337b72d5b75SMichael Corcoran 		    ACPIDEV_RES_DMA_MAX);
338b72d5b75SMichael Corcoran 		return (AE_LIMIT);
339b72d5b75SMichael Corcoran 	}
340b72d5b75SMichael Corcoran 	rhdl->acpidev_dmap[rhdl->acpidev_dma_count] = dma;
341b72d5b75SMichael Corcoran 	rhdl->acpidev_dma_count++;
342b72d5b75SMichael Corcoran 
343b72d5b75SMichael Corcoran 	return (AE_OK);
344b72d5b75SMichael Corcoran }
345b72d5b75SMichael Corcoran 
346b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_get_dmas(acpidev_resource_handle_t rhdl,uint_t * dmap,uint_t * cntp)347b72d5b75SMichael Corcoran acpidev_resource_get_dmas(acpidev_resource_handle_t rhdl,
348b72d5b75SMichael Corcoran     uint_t *dmap, uint_t *cntp)
349b72d5b75SMichael Corcoran {
350b72d5b75SMichael Corcoran 	uint_t i, j;
351b72d5b75SMichael Corcoran 
352b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
353b72d5b75SMichael Corcoran 	ASSERT(cntp != NULL);
354b72d5b75SMichael Corcoran 	if (rhdl == NULL || cntp == NULL || (dmap == NULL && *cntp != 0)) {
355b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
356b72d5b75SMichael Corcoran 	}
357b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_dma_count; i++) {
358b72d5b75SMichael Corcoran 		if (j < *cntp) {
359b72d5b75SMichael Corcoran 			dmap[j] = rhdl->acpidev_dmap[i];
360b72d5b75SMichael Corcoran 		}
361b72d5b75SMichael Corcoran 		j++;
362b72d5b75SMichael Corcoran 	}
363b72d5b75SMichael Corcoran 	if (j >= *cntp) {
364b72d5b75SMichael Corcoran 		*cntp = j;
365b72d5b75SMichael Corcoran 		return (AE_LIMIT);
366b72d5b75SMichael Corcoran 	} else {
367b72d5b75SMichael Corcoran 		*cntp = j;
368b72d5b75SMichael Corcoran 		return (AE_OK);
369b72d5b75SMichael Corcoran 	}
370b72d5b75SMichael Corcoran }
371b72d5b75SMichael Corcoran 
372b72d5b75SMichael Corcoran uint_t
acpidev_resource_get_dma_count(acpidev_resource_handle_t rhdl)373b72d5b75SMichael Corcoran acpidev_resource_get_dma_count(acpidev_resource_handle_t rhdl)
374b72d5b75SMichael Corcoran {
375b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
376b72d5b75SMichael Corcoran 	return (rhdl->acpidev_dma_count);
377b72d5b75SMichael Corcoran }
378b72d5b75SMichael Corcoran 
379b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_insert_irq(acpidev_resource_handle_t rhdl,int irq)380b72d5b75SMichael Corcoran acpidev_resource_insert_irq(acpidev_resource_handle_t rhdl, int irq)
381b72d5b75SMichael Corcoran {
382b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
383b72d5b75SMichael Corcoran 	if (rhdl->acpidev_irq_count >= ACPIDEV_RES_IRQ_MAX) {
384b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_WARN,
385a3114836SGerry Liu 		    "!acpidev: too many IRQ resources, max %u.",
386b72d5b75SMichael Corcoran 		    ACPIDEV_RES_IRQ_MAX);
387b72d5b75SMichael Corcoran 		return (AE_LIMIT);
388b72d5b75SMichael Corcoran 	}
389b72d5b75SMichael Corcoran 	rhdl->acpidev_irqp[rhdl->acpidev_irq_count] = irq;
390b72d5b75SMichael Corcoran 	rhdl->acpidev_irq_count++;
391b72d5b75SMichael Corcoran 
392b72d5b75SMichael Corcoran 	return (AE_OK);
393b72d5b75SMichael Corcoran }
394b72d5b75SMichael Corcoran 
395b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_get_irqs(acpidev_resource_handle_t rhdl,uint_t * irqp,uint_t * cntp)396b72d5b75SMichael Corcoran acpidev_resource_get_irqs(acpidev_resource_handle_t rhdl,
397b72d5b75SMichael Corcoran     uint_t *irqp, uint_t *cntp)
398b72d5b75SMichael Corcoran {
399b72d5b75SMichael Corcoran 	uint_t i, j;
400b72d5b75SMichael Corcoran 
401b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
402b72d5b75SMichael Corcoran 	ASSERT(cntp != NULL);
403b72d5b75SMichael Corcoran 	if (rhdl == NULL || cntp == NULL || (irqp == NULL && *cntp != 0)) {
404b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
405b72d5b75SMichael Corcoran 	}
406b72d5b75SMichael Corcoran 	for (i = 0, j = 0; i < rhdl->acpidev_irq_count; i++) {
407b72d5b75SMichael Corcoran 		if (j < *cntp) {
408b72d5b75SMichael Corcoran 			irqp[j] = rhdl->acpidev_irqp[i];
409b72d5b75SMichael Corcoran 		}
410b72d5b75SMichael Corcoran 		j++;
411b72d5b75SMichael Corcoran 	}
412b72d5b75SMichael Corcoran 	if (j >= *cntp) {
413b72d5b75SMichael Corcoran 		*cntp = j;
414b72d5b75SMichael Corcoran 		return (AE_LIMIT);
415b72d5b75SMichael Corcoran 	} else {
416b72d5b75SMichael Corcoran 		*cntp = j;
417b72d5b75SMichael Corcoran 		return (AE_OK);
418b72d5b75SMichael Corcoran 	}
419b72d5b75SMichael Corcoran }
420b72d5b75SMichael Corcoran 
421b72d5b75SMichael Corcoran uint_t
acpidev_resource_get_irq_count(acpidev_resource_handle_t rhdl)422b72d5b75SMichael Corcoran acpidev_resource_get_irq_count(acpidev_resource_handle_t rhdl)
423b72d5b75SMichael Corcoran {
424b72d5b75SMichael Corcoran 	ASSERT(rhdl != NULL);
425b72d5b75SMichael Corcoran 	return (rhdl->acpidev_irq_count);
426b72d5b75SMichael Corcoran }
427b72d5b75SMichael Corcoran 
428b72d5b75SMichael Corcoran static ACPI_STATUS
acpidev_resource_address64(acpidev_resource_handle_t rhdl,ACPI_RESOURCE_ADDRESS64 * addrp)429b72d5b75SMichael Corcoran acpidev_resource_address64(acpidev_resource_handle_t rhdl,
430b72d5b75SMichael Corcoran     ACPI_RESOURCE_ADDRESS64 *addrp)
431b72d5b75SMichael Corcoran {
432b72d5b75SMichael Corcoran 	ACPI_STATUS rc = AE_OK;
433b72d5b75SMichael Corcoran 	uint_t high;
434b72d5b75SMichael Corcoran 
435b72d5b75SMichael Corcoran 	ASSERT(addrp != NULL && rhdl != NULL);
436*7b1019a6SJerry Jelinek 	if (addrp->Address.AddressLength == 0) {
437b72d5b75SMichael Corcoran 		return (AE_OK);
438b72d5b75SMichael Corcoran 	}
439b72d5b75SMichael Corcoran 
440b72d5b75SMichael Corcoran 	switch (addrp->ResourceType) {
441b72d5b75SMichael Corcoran 	case ACPI_MEMORY_RANGE:
442b72d5b75SMichael Corcoran 		high = ACPIDEV_REG_TYPE_MEMORY;
443b72d5b75SMichael Corcoran 		if (addrp->Decode == ACPI_SUB_DECODE) {
444b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_SUB_DEC;
445b72d5b75SMichael Corcoran 		}
446b72d5b75SMichael Corcoran 		if (addrp->Info.Mem.Translation) {
447b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_TRANSLATED;
448b72d5b75SMichael Corcoran 		}
449b72d5b75SMichael Corcoran 		if (addrp->Info.Mem.Caching == ACPI_NON_CACHEABLE_MEMORY) {
450b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_MEM_COHERENT_NC;
451b72d5b75SMichael Corcoran 		} else if (addrp->Info.Mem.Caching == ACPI_CACHABLE_MEMORY) {
452b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_MEM_COHERENT_CA;
453b72d5b75SMichael Corcoran 		} else if (addrp->Info.Mem.Caching ==
454b72d5b75SMichael Corcoran 		    ACPI_WRITE_COMBINING_MEMORY) {
455b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_MEM_COHERENT_WC;
456b72d5b75SMichael Corcoran 		} else if (addrp->Info.Mem.Caching ==
457b72d5b75SMichael Corcoran 		    ACPI_PREFETCHABLE_MEMORY) {
458b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_MEM_COHERENT_PF;
459b72d5b75SMichael Corcoran 		} else {
460b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
461a3114836SGerry Liu 			    "!acpidev: unknown memory caching type %u.",
462b72d5b75SMichael Corcoran 			    addrp->Info.Mem.Caching);
463b72d5b75SMichael Corcoran 			rc = AE_ERROR;
464b72d5b75SMichael Corcoran 			break;
465b72d5b75SMichael Corcoran 		}
466b72d5b75SMichael Corcoran 		if (addrp->Info.Mem.WriteProtect == ACPI_READ_WRITE_MEMORY) {
467b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_MEM_WRITABLE;
468b72d5b75SMichael Corcoran 		}
469b72d5b75SMichael Corcoran 
470b72d5b75SMichael Corcoran 		/* Generate 'reg' for producer. */
471b72d5b75SMichael Corcoran 		if (addrp->ProducerConsumer == ACPI_CONSUMER &&
472b72d5b75SMichael Corcoran 		    rhdl->acpidev_consumer == B_TRUE) {
473b72d5b75SMichael Corcoran 			acpidev_regspec_t reg;
474b72d5b75SMichael Corcoran 
475b72d5b75SMichael Corcoran 			reg.phys_hi = high;
476*7b1019a6SJerry Jelinek 			reg.phys_mid = addrp->Address.Minimum >> 32;
477*7b1019a6SJerry Jelinek 			reg.phys_low = addrp->Address.Minimum & 0xFFFFFFFF;
478*7b1019a6SJerry Jelinek 			reg.size_hi = addrp->Address.AddressLength >> 32;
479*7b1019a6SJerry Jelinek 			reg.size_low = addrp->Address.AddressLength &
480*7b1019a6SJerry Jelinek 			    0xFFFFFFFF;
481b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_reg(rhdl, &reg);
482b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
483a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
484b72d5b75SMichael Corcoran 				    "insert regspec into resource handle.");
485b72d5b75SMichael Corcoran 			}
486b72d5b75SMichael Corcoran 		/* Generate 'ranges' for producer. */
487b72d5b75SMichael Corcoran 		} else if (addrp->ProducerConsumer == ACPI_PRODUCER &&
488b72d5b75SMichael Corcoran 		    rhdl->acpidev_consumer == B_FALSE) {
489b72d5b75SMichael Corcoran 			uint64_t paddr;
490b72d5b75SMichael Corcoran 			acpidev_ranges_t range;
491b72d5b75SMichael Corcoran 
492b72d5b75SMichael Corcoran 			range.child_hi = high;
493*7b1019a6SJerry Jelinek 			range.child_mid = addrp->Address.Minimum >> 32;
494*7b1019a6SJerry Jelinek 			range.child_low = addrp->Address.Minimum & 0xFFFFFFFF;
495b72d5b75SMichael Corcoran 			/* It's IO on parent side if Translation is true. */
496b72d5b75SMichael Corcoran 			if (addrp->Info.Mem.Translation) {
497b72d5b75SMichael Corcoran 				range.parent_hi = ACPIDEV_REG_TYPE_IO;
498b72d5b75SMichael Corcoran 			} else {
499b72d5b75SMichael Corcoran 				range.parent_hi = high;
500b72d5b75SMichael Corcoran 			}
501*7b1019a6SJerry Jelinek 			paddr = addrp->Address.Minimum +
502*7b1019a6SJerry Jelinek 			    addrp->Address.TranslationOffset;
503b72d5b75SMichael Corcoran 			range.parent_mid = paddr >> 32;
504b72d5b75SMichael Corcoran 			range.parent_low = paddr & 0xFFFFFFFF;
505*7b1019a6SJerry Jelinek 			range.size_hi = addrp->Address.AddressLength >> 32;
506*7b1019a6SJerry Jelinek 			range.size_low = addrp->Address.AddressLength &
507*7b1019a6SJerry Jelinek 			    0xFFFFFFFF;
508b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_range(rhdl, &range);
509b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
510a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
511b72d5b75SMichael Corcoran 				    "insert range into resource handle.");
512b72d5b75SMichael Corcoran 			}
513b72d5b75SMichael Corcoran 		}
514b72d5b75SMichael Corcoran 		break;
515b72d5b75SMichael Corcoran 
516b72d5b75SMichael Corcoran 	case ACPI_IO_RANGE:
517b72d5b75SMichael Corcoran 		high = ACPIDEV_REG_TYPE_IO;
518b72d5b75SMichael Corcoran 		if (addrp->Decode == ACPI_SUB_DECODE) {
519b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_SUB_DEC;
520b72d5b75SMichael Corcoran 		}
521b72d5b75SMichael Corcoran 		if (addrp->Info.Io.Translation) {
522b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_TRANSLATED;
523b72d5b75SMichael Corcoran 		}
524b72d5b75SMichael Corcoran 		if (addrp->Info.Io.RangeType == ACPI_NON_ISA_ONLY_RANGES) {
525b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_IO_RANGE_NONISA;
526b72d5b75SMichael Corcoran 		} else if (addrp->Info.Io.RangeType == ACPI_ISA_ONLY_RANGES) {
527b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_IO_RANGE_ISA;
528b72d5b75SMichael Corcoran 		} else if (addrp->Info.Io.RangeType == ACPI_ENTIRE_RANGE) {
529b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_IO_RANGE_FULL;
530b72d5b75SMichael Corcoran 		} else {
531b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
532a3114836SGerry Liu 			    "!acpidev: unknown IO range type %u.",
533b72d5b75SMichael Corcoran 			    addrp->Info.Io.RangeType);
534b72d5b75SMichael Corcoran 			rc = AE_ERROR;
535b72d5b75SMichael Corcoran 			break;
536b72d5b75SMichael Corcoran 		}
537b72d5b75SMichael Corcoran 		if (addrp->Info.Io.TranslationType == ACPI_SPARSE_TRANSLATION) {
538b72d5b75SMichael Corcoran 			high |= ACPIDEV_REG_IO_SPARSE;
539b72d5b75SMichael Corcoran 		}
540b72d5b75SMichael Corcoran 
541b72d5b75SMichael Corcoran 		/* Generate 'reg' for producer. */
542b72d5b75SMichael Corcoran 		if (addrp->ProducerConsumer == ACPI_CONSUMER &&
543b72d5b75SMichael Corcoran 		    rhdl->acpidev_consumer == B_TRUE) {
544b72d5b75SMichael Corcoran 			acpidev_regspec_t reg;
545b72d5b75SMichael Corcoran 
546b72d5b75SMichael Corcoran 			reg.phys_hi = high;
547*7b1019a6SJerry Jelinek 			reg.phys_mid = addrp->Address.Minimum >> 32;
548*7b1019a6SJerry Jelinek 			reg.phys_low = addrp->Address.Minimum & 0xFFFFFFFF;
549*7b1019a6SJerry Jelinek 			reg.size_hi = addrp->Address.AddressLength >> 32;
550*7b1019a6SJerry Jelinek 			reg.size_low = addrp->Address.AddressLength &
551*7b1019a6SJerry Jelinek 			    0xFFFFFFFF;
552b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_reg(rhdl, &reg);
553b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
554a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
555b72d5b75SMichael Corcoran 				    "insert regspec into resource handle.");
556b72d5b75SMichael Corcoran 			}
557b72d5b75SMichael Corcoran 		/* Generate 'ranges' for producer. */
558b72d5b75SMichael Corcoran 		} else if (addrp->ProducerConsumer == ACPI_PRODUCER &&
559b72d5b75SMichael Corcoran 		    rhdl->acpidev_consumer == B_FALSE) {
560b72d5b75SMichael Corcoran 			uint64_t paddr;
561b72d5b75SMichael Corcoran 			acpidev_ranges_t range;
562b72d5b75SMichael Corcoran 
563b72d5b75SMichael Corcoran 			range.child_hi = high;
564*7b1019a6SJerry Jelinek 			range.child_mid = addrp->Address.Minimum >> 32;
565*7b1019a6SJerry Jelinek 			range.child_low = addrp->Address.Minimum & 0xFFFFFFFF;
566b72d5b75SMichael Corcoran 			/* It's Memory on parent side if Translation is true. */
567b72d5b75SMichael Corcoran 			if (addrp->Info.Io.Translation) {
568b72d5b75SMichael Corcoran 				range.parent_hi = ACPIDEV_REG_TYPE_MEMORY;
569b72d5b75SMichael Corcoran 			} else {
570b72d5b75SMichael Corcoran 				range.parent_hi = high;
571b72d5b75SMichael Corcoran 			}
572*7b1019a6SJerry Jelinek 			paddr = addrp->Address.Minimum +
573*7b1019a6SJerry Jelinek 			    addrp->Address.TranslationOffset;
574b72d5b75SMichael Corcoran 			range.parent_mid = paddr >> 32;
575b72d5b75SMichael Corcoran 			range.parent_low = paddr & 0xFFFFFFFF;
576*7b1019a6SJerry Jelinek 			range.size_hi = addrp->Address.AddressLength >> 32;
577*7b1019a6SJerry Jelinek 			range.size_low = addrp->Address.AddressLength &
578*7b1019a6SJerry Jelinek 			    0xFFFFFFFF;
579b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_range(rhdl, &range);
580b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
581a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
582b72d5b75SMichael Corcoran 				    "insert range into resource handle.");
583b72d5b75SMichael Corcoran 			}
584b72d5b75SMichael Corcoran 		}
585b72d5b75SMichael Corcoran 		break;
586b72d5b75SMichael Corcoran 
587b72d5b75SMichael Corcoran 	case ACPI_BUS_NUMBER_RANGE:
588b72d5b75SMichael Corcoran 		/* Only support producer of BUS. */
589b72d5b75SMichael Corcoran 		if (addrp->ProducerConsumer == ACPI_PRODUCER &&
590b72d5b75SMichael Corcoran 		    rhdl->acpidev_consumer == B_FALSE) {
591b72d5b75SMichael Corcoran 			uint64_t end;
592b72d5b75SMichael Corcoran 			acpidev_bus_range_t bus;
593b72d5b75SMichael Corcoran 
594*7b1019a6SJerry Jelinek 			end = addrp->Address.Minimum +
595*7b1019a6SJerry Jelinek 			    addrp->Address.AddressLength;
596*7b1019a6SJerry Jelinek 			if (end < addrp->Address.Minimum || end > UINT_MAX) {
597a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: bus range "
598b72d5b75SMichael Corcoran 				    "in ADDRESS64 is invalid.");
599b72d5b75SMichael Corcoran 				rc = AE_ERROR;
600b72d5b75SMichael Corcoran 				break;
601b72d5b75SMichael Corcoran 			}
602*7b1019a6SJerry Jelinek 			bus.bus_start = addrp->Address.Minimum & 0xFFFFFFFF;
603b72d5b75SMichael Corcoran 			bus.bus_end = end & 0xFFFFFFFF;
604b72d5b75SMichael Corcoran 			ASSERT(bus.bus_start <= bus.bus_end);
605b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_bus(rhdl, &bus);
606b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
607a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
608b72d5b75SMichael Corcoran 				    "insert bus range into resource handle.");
609b72d5b75SMichael Corcoran 			}
610b72d5b75SMichael Corcoran 		}
611b72d5b75SMichael Corcoran 		break;
612b72d5b75SMichael Corcoran 
613b72d5b75SMichael Corcoran 	default:
614b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_WARN,
615a3114836SGerry Liu 		    "!acpidev: unknown resource type %u in ADDRESS64.",
616b72d5b75SMichael Corcoran 		    addrp->ResourceType);
617b72d5b75SMichael Corcoran 		rc = AE_BAD_PARAMETER;
618b72d5b75SMichael Corcoran 	}
619b72d5b75SMichael Corcoran 
620b72d5b75SMichael Corcoran 	return (rc);
621b72d5b75SMichael Corcoran }
622b72d5b75SMichael Corcoran 
623b72d5b75SMichael Corcoran static ACPI_STATUS
acpidev_resource_walk_producer(ACPI_RESOURCE * rscp,void * ctxp)624b72d5b75SMichael Corcoran acpidev_resource_walk_producer(ACPI_RESOURCE *rscp, void *ctxp)
625b72d5b75SMichael Corcoran {
626b72d5b75SMichael Corcoran 	ACPI_STATUS rc = AE_OK;
627b72d5b75SMichael Corcoran 	acpidev_resource_handle_t rhdl;
628b72d5b75SMichael Corcoran 
629b72d5b75SMichael Corcoran 	ASSERT(ctxp != NULL);
630b72d5b75SMichael Corcoran 	rhdl = (acpidev_resource_handle_t)ctxp;
631b72d5b75SMichael Corcoran 	ASSERT(rhdl->acpidev_consumer == B_FALSE);
632b72d5b75SMichael Corcoran 
633b72d5b75SMichael Corcoran 	switch (rscp->Type) {
634b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_DMA:
635b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_IRQ:
636b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
637b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_FIXED_IO:
638b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_MEMORY24:
639b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_MEMORY32:
640b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
641b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
642b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_VENDOR:
643b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_NOTE,
644a3114836SGerry Liu 		    "!acpidev: unsupported producer resource type %u, ignored.",
645b72d5b75SMichael Corcoran 		    rscp->Type);
646b72d5b75SMichael Corcoran 		break;
647b72d5b75SMichael Corcoran 
648b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_IO:
649b72d5b75SMichael Corcoran 	{
650b72d5b75SMichael Corcoran 		acpidev_ranges_t range;
651b72d5b75SMichael Corcoran 
652b72d5b75SMichael Corcoran 		range.child_hi = ACPIDEV_REG_TYPE_IO;
653b72d5b75SMichael Corcoran 		range.child_hi |= ACPIDEV_REG_IO_RANGE_FULL;
654b72d5b75SMichael Corcoran 		if (rscp->Data.Io.IoDecode == ACPI_DECODE_16) {
655b72d5b75SMichael Corcoran 			range.child_hi |= ACPIDEV_REG_IO_DECODE16;
656b72d5b75SMichael Corcoran 		}
657b72d5b75SMichael Corcoran 		range.parent_hi = range.child_hi;
658b72d5b75SMichael Corcoran 		range.parent_mid = range.child_mid = 0;
659b72d5b75SMichael Corcoran 		range.parent_low = range.child_low = rscp->Data.Io.Minimum;
660b72d5b75SMichael Corcoran 		range.size_hi = 0;
661b72d5b75SMichael Corcoran 		range.size_low = rscp->Data.Io.AddressLength;
662b72d5b75SMichael Corcoran 		if ((uint64_t)range.child_low + range.size_low > UINT16_MAX) {
663a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid IO record, "
664b72d5b75SMichael Corcoran 			    "IO max is out of range.");
665b72d5b75SMichael Corcoran 			rc = AE_ERROR;
666b72d5b75SMichael Corcoran 		} else if (range.size_low != 0) {
667b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_range(rhdl, &range);
668b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
669a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
670b72d5b75SMichael Corcoran 				    "insert range into resource handle.");
671b72d5b75SMichael Corcoran 			}
672b72d5b75SMichael Corcoran 		}
673b72d5b75SMichael Corcoran 		break;
674b72d5b75SMichael Corcoran 	}
675b72d5b75SMichael Corcoran 
676b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_ADDRESS16:
677b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_ADDRESS32:
678b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_ADDRESS64:
679b72d5b75SMichael Corcoran 	{
680b72d5b75SMichael Corcoran 		ACPI_RESOURCE_ADDRESS64 addr64;
681b72d5b75SMichael Corcoran 
682b72d5b75SMichael Corcoran 		if (rscp->Data.Address.ProducerConsumer != ACPI_PRODUCER) {
683a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
684b72d5b75SMichael Corcoran 			    "a CONSUMER resource, ignored.");
685b72d5b75SMichael Corcoran 		} else if (ACPI_FAILURE(AcpiResourceToAddress64(rscp,
686b72d5b75SMichael Corcoran 		    &addr64))) {
687b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
688a3114836SGerry Liu 			    "!acpidev: failed to convert resource to ADDR64.");
689b72d5b75SMichael Corcoran 		} else if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
690b72d5b75SMichael Corcoran 		    &addr64))) {
691b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
692a3114836SGerry Liu 			    "!acpidev: failed to handle ADDRESS resource.");
693b72d5b75SMichael Corcoran 		}
694b72d5b75SMichael Corcoran 		break;
695b72d5b75SMichael Corcoran 	}
696b72d5b75SMichael Corcoran 
697b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
698b72d5b75SMichael Corcoran 	{
699b72d5b75SMichael Corcoran 		ACPI_RESOURCE_ADDRESS64 addr64;
700b72d5b75SMichael Corcoran 
701b72d5b75SMichael Corcoran 		if (rscp->Data.ExtAddress64.ProducerConsumer != ACPI_PRODUCER) {
702a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
703b72d5b75SMichael Corcoran 			    "a CONSUMER resource, ignored.");
704b72d5b75SMichael Corcoran 			break;
705b72d5b75SMichael Corcoran 		}
706b72d5b75SMichael Corcoran 
707b72d5b75SMichael Corcoran 		*(ACPI_RESOURCE_ADDRESS *)&addr64 = rscp->Data.Address;
708*7b1019a6SJerry Jelinek 		addr64.Address.Granularity =
709*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.Granularity;
710*7b1019a6SJerry Jelinek 		addr64.Address.Minimum =
711*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.Minimum;
712*7b1019a6SJerry Jelinek 		addr64.Address.Maximum =
713*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.Maximum;
714*7b1019a6SJerry Jelinek 		addr64.Address.TranslationOffset =
715*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.TranslationOffset;
716*7b1019a6SJerry Jelinek 		addr64.Address.AddressLength =
717*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.AddressLength;
718b72d5b75SMichael Corcoran 		if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
719b72d5b75SMichael Corcoran 		    &addr64))) {
720b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
721a3114836SGerry Liu 			    "!acpidev: failed to handle EXTADDRESS resource.");
722b72d5b75SMichael Corcoran 		}
723b72d5b75SMichael Corcoran 		break;
724b72d5b75SMichael Corcoran 	}
725b72d5b75SMichael Corcoran 
726b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
727b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
728a3114836SGerry Liu 		ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
729b72d5b75SMichael Corcoran 		    "START_DEPENDENT or END_DEPENDENT tag, ignored.");
730b72d5b75SMichael Corcoran 		break;
731b72d5b75SMichael Corcoran 
732b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_END_TAG:
733b72d5b75SMichael Corcoran 		/* Finish walking when we encounter END_TAG. */
734b72d5b75SMichael Corcoran 		rc = AE_CTRL_TERMINATE;
735b72d5b75SMichael Corcoran 		break;
736b72d5b75SMichael Corcoran 
737b72d5b75SMichael Corcoran 	default:
738b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_NOTE,
739a3114836SGerry Liu 		    "!acpidev: unknown ACPI resource type %u, ignored.",
740b72d5b75SMichael Corcoran 		    rscp->Type);
741b72d5b75SMichael Corcoran 		break;
742b72d5b75SMichael Corcoran 	}
743b72d5b75SMichael Corcoran 
744b72d5b75SMichael Corcoran 	return (rc);
745b72d5b75SMichael Corcoran }
746b72d5b75SMichael Corcoran 
747b72d5b75SMichael Corcoran static ACPI_STATUS
acpidev_resource_walk_consumer(ACPI_RESOURCE * rscp,void * ctxp)748b72d5b75SMichael Corcoran acpidev_resource_walk_consumer(ACPI_RESOURCE *rscp, void *ctxp)
749b72d5b75SMichael Corcoran {
750b72d5b75SMichael Corcoran 	ACPI_STATUS rc = AE_OK;
751b72d5b75SMichael Corcoran 	acpidev_resource_handle_t rhdl;
752b72d5b75SMichael Corcoran 
753b72d5b75SMichael Corcoran 	ASSERT(ctxp != NULL);
754b72d5b75SMichael Corcoran 	rhdl = (acpidev_resource_handle_t)ctxp;
755b72d5b75SMichael Corcoran 	ASSERT(rhdl->acpidev_consumer == B_TRUE);
756b72d5b75SMichael Corcoran 
757b72d5b75SMichael Corcoran 	switch (rscp->Type) {
758b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_MEMORY24:
759b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
760b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_VENDOR:
761b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_NOTE,
762a3114836SGerry Liu 		    "!acpidev: unsupported consumer resource type %u, ignored.",
763b72d5b75SMichael Corcoran 		    rscp->Type);
764b72d5b75SMichael Corcoran 		break;
765b72d5b75SMichael Corcoran 
766b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
767b72d5b75SMichael Corcoran 	{
768b72d5b75SMichael Corcoran 		int i;
769b72d5b75SMichael Corcoran 
770b72d5b75SMichael Corcoran 		if (rscp->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
771a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
772b72d5b75SMichael Corcoran 			    "a PRODUCER resource, ignored.");
773b72d5b75SMichael Corcoran 			break;
774b72d5b75SMichael Corcoran 		}
775b72d5b75SMichael Corcoran 		for (i = 0; i < rscp->Data.ExtendedIrq.InterruptCount; i++) {
776b72d5b75SMichael Corcoran 			if (ACPI_SUCCESS(acpidev_resource_insert_irq(rhdl,
777b72d5b75SMichael Corcoran 			    rscp->Data.ExtendedIrq.Interrupts[i]))) {
778b72d5b75SMichael Corcoran 				continue;
779b72d5b75SMichael Corcoran 			}
780a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
781b72d5b75SMichael Corcoran 			    "Extended IRQ into resource handle.");
782b72d5b75SMichael Corcoran 			rc = AE_ERROR;
783b72d5b75SMichael Corcoran 			break;
784b72d5b75SMichael Corcoran 		}
785b72d5b75SMichael Corcoran 		break;
786b72d5b75SMichael Corcoran 	}
787b72d5b75SMichael Corcoran 
788b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_IRQ:
789b72d5b75SMichael Corcoran 	{
790b72d5b75SMichael Corcoran 		int i;
791b72d5b75SMichael Corcoran 
792b72d5b75SMichael Corcoran 		for (i = 0; i < rscp->Data.Irq.InterruptCount; i++) {
793b72d5b75SMichael Corcoran 			if (ACPI_SUCCESS(acpidev_resource_insert_irq(rhdl,
794b72d5b75SMichael Corcoran 			    rscp->Data.Irq.Interrupts[i]))) {
795b72d5b75SMichael Corcoran 				continue;
796b72d5b75SMichael Corcoran 			}
797a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
798b72d5b75SMichael Corcoran 			    "IRQ into resource handle.");
799b72d5b75SMichael Corcoran 			rc = AE_ERROR;
800b72d5b75SMichael Corcoran 			break;
801b72d5b75SMichael Corcoran 		}
802b72d5b75SMichael Corcoran 		break;
803b72d5b75SMichael Corcoran 	}
804b72d5b75SMichael Corcoran 
805b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_DMA:
806b72d5b75SMichael Corcoran 	{
807b72d5b75SMichael Corcoran 		int i;
808b72d5b75SMichael Corcoran 
809b72d5b75SMichael Corcoran 		for (i = 0; i < rscp->Data.Dma.ChannelCount; i++) {
810b72d5b75SMichael Corcoran 			if (ACPI_SUCCESS(acpidev_resource_insert_dma(rhdl,
811b72d5b75SMichael Corcoran 			    rscp->Data.Dma.Channels[i]))) {
812b72d5b75SMichael Corcoran 				continue;
813b72d5b75SMichael Corcoran 			}
814a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
815b72d5b75SMichael Corcoran 			    "dma into resource handle.");
816b72d5b75SMichael Corcoran 			rc = AE_ERROR;
817b72d5b75SMichael Corcoran 			break;
818b72d5b75SMichael Corcoran 		}
819b72d5b75SMichael Corcoran 		break;
820b72d5b75SMichael Corcoran 	}
821b72d5b75SMichael Corcoran 
822b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_IO:
823b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_FIXED_IO:
824b72d5b75SMichael Corcoran 	{
825b72d5b75SMichael Corcoran 		acpidev_regspec_t reg;
826b72d5b75SMichael Corcoran 
827b72d5b75SMichael Corcoran 		reg.phys_hi = ACPIDEV_REG_TYPE_IO;
828b72d5b75SMichael Corcoran 		reg.phys_hi |= ACPIDEV_REG_IO_RANGE_FULL;
829b72d5b75SMichael Corcoran 		if (rscp->Type == ACPI_RESOURCE_TYPE_IO) {
830b72d5b75SMichael Corcoran 			if (rscp->Data.Io.IoDecode == ACPI_DECODE_16) {
831b72d5b75SMichael Corcoran 				reg.phys_hi |= ACPIDEV_REG_IO_DECODE16;
832b72d5b75SMichael Corcoran 			}
833b72d5b75SMichael Corcoran 			reg.phys_low = rscp->Data.Io.Minimum;
834b72d5b75SMichael Corcoran 			reg.size_low = rscp->Data.Io.AddressLength;
835b72d5b75SMichael Corcoran 		} else {
836b72d5b75SMichael Corcoran 			reg.phys_hi |= ACPIDEV_REG_IO_DECODE16;
837b72d5b75SMichael Corcoran 			reg.phys_low = rscp->Data.FixedIo.Address;
838b72d5b75SMichael Corcoran 			reg.size_low = rscp->Data.FixedIo.AddressLength;
839b72d5b75SMichael Corcoran 		}
840b72d5b75SMichael Corcoran 		reg.phys_mid = 0;
841b72d5b75SMichael Corcoran 		reg.size_hi = 0;
842b72d5b75SMichael Corcoran 		if ((uint64_t)reg.phys_low + reg.size_low > UINT16_MAX) {
843a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid IO/FIXEDIO "
844b72d5b75SMichael Corcoran 			    "record, IO max is out of range.");
845b72d5b75SMichael Corcoran 			rc = AE_ERROR;
846b72d5b75SMichael Corcoran 		} else if (reg.size_low != 0) {
847b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_reg(rhdl, &reg);
848b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
849a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
850b72d5b75SMichael Corcoran 				    "insert reg into resource handle.");
851b72d5b75SMichael Corcoran 			}
852b72d5b75SMichael Corcoran 		}
853b72d5b75SMichael Corcoran 		break;
854b72d5b75SMichael Corcoran 	}
855b72d5b75SMichael Corcoran 
856b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_MEMORY32:
857b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
858b72d5b75SMichael Corcoran 	{
859b72d5b75SMichael Corcoran 		acpidev_regspec_t reg;
860b72d5b75SMichael Corcoran 
861b72d5b75SMichael Corcoran 		reg.phys_hi = ACPIDEV_REG_TYPE_MEMORY;
862b72d5b75SMichael Corcoran 		reg.phys_hi |= ACPIDEV_REG_MEM_COHERENT_CA;
863b72d5b75SMichael Corcoran 		if (rscp->Type == ACPI_RESOURCE_TYPE_MEMORY32) {
864b72d5b75SMichael Corcoran 			if (rscp->Data.Memory32.WriteProtect ==
865b72d5b75SMichael Corcoran 			    ACPI_READ_WRITE_MEMORY) {
866b72d5b75SMichael Corcoran 				reg.phys_hi |= ACPIDEV_REG_MEM_WRITABLE;
867b72d5b75SMichael Corcoran 			}
868b72d5b75SMichael Corcoran 			reg.phys_low = rscp->Data.Memory32.Minimum;
869b72d5b75SMichael Corcoran 			reg.size_low = rscp->Data.Memory32.AddressLength;
870b72d5b75SMichael Corcoran 		} else {
871b72d5b75SMichael Corcoran 			if (rscp->Data.FixedMemory32.WriteProtect ==
872b72d5b75SMichael Corcoran 			    ACPI_READ_WRITE_MEMORY) {
873b72d5b75SMichael Corcoran 				reg.phys_hi |= ACPIDEV_REG_MEM_WRITABLE;
874b72d5b75SMichael Corcoran 			}
875b72d5b75SMichael Corcoran 			reg.phys_low = rscp->Data.FixedMemory32.Address;
876b72d5b75SMichael Corcoran 			reg.size_low = rscp->Data.FixedMemory32.AddressLength;
877b72d5b75SMichael Corcoran 		}
878b72d5b75SMichael Corcoran 		reg.phys_mid = 0;
879b72d5b75SMichael Corcoran 		reg.size_hi = 0;
880b72d5b75SMichael Corcoran 		if ((uint64_t)reg.phys_low + reg.size_low > UINT32_MAX) {
881b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
882a3114836SGerry Liu 			    "!acpidev: invalid MEMORY32/FIXEDMEMORY32 record, "
883b72d5b75SMichael Corcoran 			    "memory max is out of range.");
884b72d5b75SMichael Corcoran 			rc = AE_ERROR;
885b72d5b75SMichael Corcoran 		} else if (reg.size_low != 0) {
886b72d5b75SMichael Corcoran 			rc = acpidev_resource_insert_reg(rhdl, &reg);
887b72d5b75SMichael Corcoran 			if (ACPI_FAILURE(rc)) {
888a3114836SGerry Liu 				ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
889b72d5b75SMichael Corcoran 				    "insert reg into resource handle.");
890b72d5b75SMichael Corcoran 			}
891b72d5b75SMichael Corcoran 		}
892b72d5b75SMichael Corcoran 		break;
893b72d5b75SMichael Corcoran 	}
894b72d5b75SMichael Corcoran 
895b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_ADDRESS16:
896b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_ADDRESS32:
897b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_ADDRESS64:
898b72d5b75SMichael Corcoran 	{
899b72d5b75SMichael Corcoran 		ACPI_RESOURCE_ADDRESS64 addr64;
900b72d5b75SMichael Corcoran 
901b72d5b75SMichael Corcoran 		if (rscp->Data.Address.ProducerConsumer != ACPI_CONSUMER) {
902a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
903b72d5b75SMichael Corcoran 			    "a PRODUCER resource, ignored.");
904b72d5b75SMichael Corcoran 		} else if (ACPI_FAILURE(AcpiResourceToAddress64(rscp,
905b72d5b75SMichael Corcoran 		    &addr64))) {
906b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
907a3114836SGerry Liu 			    "!acpidev: failed to convert resource to ADDR64.");
908b72d5b75SMichael Corcoran 		} else if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
909b72d5b75SMichael Corcoran 		    &addr64))) {
910b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
911a3114836SGerry Liu 			    "!acpidev: failed to handle ADDRESS resource.");
912b72d5b75SMichael Corcoran 		}
913b72d5b75SMichael Corcoran 		break;
914b72d5b75SMichael Corcoran 	}
915b72d5b75SMichael Corcoran 
916b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
917b72d5b75SMichael Corcoran 	{
918b72d5b75SMichael Corcoran 		ACPI_RESOURCE_ADDRESS64 addr64;
919b72d5b75SMichael Corcoran 
920b72d5b75SMichael Corcoran 		if (rscp->Data.ExtAddress64.ProducerConsumer != ACPI_CONSUMER) {
921a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
922b72d5b75SMichael Corcoran 			    "a PRODUCER resource, ignored.");
923b72d5b75SMichael Corcoran 			break;
924b72d5b75SMichael Corcoran 		}
925b72d5b75SMichael Corcoran 
926b72d5b75SMichael Corcoran 		*(ACPI_RESOURCE_ADDRESS *)&addr64 = rscp->Data.Address;
927*7b1019a6SJerry Jelinek 		addr64.Address.Granularity =
928*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.Granularity;
929*7b1019a6SJerry Jelinek 		addr64.Address.Minimum =
930*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.Minimum;
931*7b1019a6SJerry Jelinek 		addr64.Address.Maximum =
932*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.Maximum;
933*7b1019a6SJerry Jelinek 		addr64.Address.TranslationOffset =
934*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.TranslationOffset;
935*7b1019a6SJerry Jelinek 		addr64.Address.AddressLength =
936*7b1019a6SJerry Jelinek 		    rscp->Data.ExtAddress64.Address.AddressLength;
937b72d5b75SMichael Corcoran 		if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
938b72d5b75SMichael Corcoran 		    &addr64))) {
939b72d5b75SMichael Corcoran 			ACPIDEV_DEBUG(CE_WARN,
940a3114836SGerry Liu 			    "!acpidev: failed to handle EXTADDRESS resource.");
941b72d5b75SMichael Corcoran 		}
942b72d5b75SMichael Corcoran 		break;
943b72d5b75SMichael Corcoran 	}
944b72d5b75SMichael Corcoran 
945b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
946b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
947a3114836SGerry Liu 		ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
948b72d5b75SMichael Corcoran 		    "START_DEPENDENT or END_DEPENDENT tag, ignored.");
949b72d5b75SMichael Corcoran 		break;
950b72d5b75SMichael Corcoran 
951b72d5b75SMichael Corcoran 	case ACPI_RESOURCE_TYPE_END_TAG:
952b72d5b75SMichael Corcoran 		/* Finish walking when we encounter END_TAG. */
953b72d5b75SMichael Corcoran 		rc = AE_CTRL_TERMINATE;
954b72d5b75SMichael Corcoran 		break;
955b72d5b75SMichael Corcoran 
956b72d5b75SMichael Corcoran 	default:
957b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_NOTE,
958a3114836SGerry Liu 		    "!acpidev: unknown ACPI resource type %u, ignored.",
959b72d5b75SMichael Corcoran 		    rscp->Type);
960b72d5b75SMichael Corcoran 		break;
961b72d5b75SMichael Corcoran 	}
962b72d5b75SMichael Corcoran 
963b72d5b75SMichael Corcoran 	return (rc);
964b72d5b75SMichael Corcoran }
965b72d5b75SMichael Corcoran 
966b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_walk(ACPI_HANDLE hdl,char * method,boolean_t consumer,acpidev_resource_handle_t * rhdlp)967b72d5b75SMichael Corcoran acpidev_resource_walk(ACPI_HANDLE hdl, char *method,
968b72d5b75SMichael Corcoran     boolean_t consumer, acpidev_resource_handle_t *rhdlp)
969b72d5b75SMichael Corcoran {
970b72d5b75SMichael Corcoran 	ACPI_STATUS rc = AE_OK;
971b72d5b75SMichael Corcoran 	ACPI_HANDLE mhdl = NULL;
972b72d5b75SMichael Corcoran 	acpidev_resource_handle_t rhdl = NULL;
973b72d5b75SMichael Corcoran 
974b72d5b75SMichael Corcoran 	ASSERT(hdl != NULL);
975b72d5b75SMichael Corcoran 	ASSERT(method != NULL);
976b72d5b75SMichael Corcoran 	ASSERT(rhdlp != NULL);
977b72d5b75SMichael Corcoran 	if (hdl == NULL) {
978b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_WARN,
979a3114836SGerry Liu 		    "!acpidev: hdl is NULL in acpidev_resource_walk().");
980b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
981b72d5b75SMichael Corcoran 	} else if (method == NULL) {
982b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_WARN,
983a3114836SGerry Liu 		    "!acpidev: method is NULL in acpidev_resource_walk().");
984b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
985b72d5b75SMichael Corcoran 	} else if (rhdlp == NULL) {
986a3114836SGerry Liu 		ACPIDEV_DEBUG(CE_WARN, "!acpidev: resource handle ptr is NULL "
987b72d5b75SMichael Corcoran 		    "in acpidev_resource_walk().");
988b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
989b72d5b75SMichael Corcoran 	}
990b72d5b75SMichael Corcoran 
991b72d5b75SMichael Corcoran 	/* Check whether method exists under object. */
992b72d5b75SMichael Corcoran 	if (ACPI_FAILURE(AcpiGetHandle(hdl, method, &mhdl))) {
993b72d5b75SMichael Corcoran 		char *objname = acpidev_get_object_name(hdl);
994b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_NOTE,
995a3114836SGerry Liu 		    "!acpidev: method %s doesn't exist under %s",
996b72d5b75SMichael Corcoran 		    method, objname);
99757190917SDana Myers 		acpidev_free_object_name(objname);
998b72d5b75SMichael Corcoran 		return (AE_NOT_FOUND);
999b72d5b75SMichael Corcoran 	}
1000b72d5b75SMichael Corcoran 
1001b72d5b75SMichael Corcoran 	/* Walk all resources. */
1002b72d5b75SMichael Corcoran 	rhdl = acpidev_resource_handle_alloc(consumer);
1003b72d5b75SMichael Corcoran 	if (consumer) {
1004b72d5b75SMichael Corcoran 		rc = AcpiWalkResources(hdl, method,
1005b72d5b75SMichael Corcoran 		    acpidev_resource_walk_consumer, rhdl);
1006b72d5b75SMichael Corcoran 	} else {
1007b72d5b75SMichael Corcoran 		rc = AcpiWalkResources(hdl, method,
1008b72d5b75SMichael Corcoran 		    acpidev_resource_walk_producer, rhdl);
1009b72d5b75SMichael Corcoran 	}
1010b72d5b75SMichael Corcoran 	if (ACPI_SUCCESS(rc)) {
1011b72d5b75SMichael Corcoran 		*rhdlp = rhdl;
1012b72d5b75SMichael Corcoran 	} else {
1013b72d5b75SMichael Corcoran 		acpidev_resource_handle_free(rhdl);
1014b72d5b75SMichael Corcoran 	}
1015b72d5b75SMichael Corcoran 	if (ACPI_FAILURE(rc)) {
1016b72d5b75SMichael Corcoran 		char *objname = acpidev_get_object_name(hdl);
1017a3114836SGerry Liu 		ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to walk resource from "
1018a3114836SGerry Liu 		    "method %s under %s.", method, objname);
101957190917SDana Myers 		acpidev_free_object_name(objname);
1020b72d5b75SMichael Corcoran 	}
1021b72d5b75SMichael Corcoran 
1022b72d5b75SMichael Corcoran 	return (rc);
1023b72d5b75SMichael Corcoran }
1024b72d5b75SMichael Corcoran 
1025b72d5b75SMichael Corcoran ACPI_STATUS
acpidev_resource_process(acpidev_walk_info_t * infop,boolean_t consumer)1026b72d5b75SMichael Corcoran acpidev_resource_process(acpidev_walk_info_t *infop, boolean_t consumer)
1027b72d5b75SMichael Corcoran {
1028b72d5b75SMichael Corcoran 	ACPI_STATUS rc;
1029b72d5b75SMichael Corcoran 	char path[MAXPATHLEN];
1030b72d5b75SMichael Corcoran 	acpidev_resource_handle_t rhdl = NULL;
1031b72d5b75SMichael Corcoran 
1032b72d5b75SMichael Corcoran 	ASSERT(infop != NULL);
1033b72d5b75SMichael Corcoran 	if (infop == NULL) {
1034a3114836SGerry Liu 		ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter "
1035b72d5b75SMichael Corcoran 		    "in acpidev_resource_process().");
1036b72d5b75SMichael Corcoran 		return (AE_BAD_PARAMETER);
1037b72d5b75SMichael Corcoran 	}
1038b72d5b75SMichael Corcoran 
1039b72d5b75SMichael Corcoran 	/* Walk all resources. */
1040b72d5b75SMichael Corcoran 	(void) ddi_pathname(infop->awi_dip, path);
1041b72d5b75SMichael Corcoran 	rc = acpidev_resource_walk(infop->awi_hdl, METHOD_NAME__CRS,
1042b72d5b75SMichael Corcoran 	    consumer, &rhdl);
1043b72d5b75SMichael Corcoran 	if (ACPI_FAILURE(rc)) {
1044b72d5b75SMichael Corcoran 		ACPIDEV_DEBUG(CE_WARN,
1045a3114836SGerry Liu 		    "!acpidev: failed to walk ACPI resources of %s(%s).",
1046b72d5b75SMichael Corcoran 		    path, infop->awi_name);
1047b72d5b75SMichael Corcoran 		return (rc);
1048b72d5b75SMichael Corcoran 	}
1049b72d5b75SMichael Corcoran 
1050b72d5b75SMichael Corcoran 	if (consumer) {
1051b72d5b75SMichael Corcoran 		/* Create device properties for consumer. */
1052b72d5b75SMichael Corcoran 
1053b72d5b75SMichael Corcoran 		/* Create 'reg' and 'assigned-addresses' properties. */
1054b72d5b75SMichael Corcoran 		if (rhdl->acpidev_reg_count > 0 &&
1055b72d5b75SMichael Corcoran 		    ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1056b72d5b75SMichael Corcoran 		    "reg", (int *)rhdl->acpidev_regp,
1057b72d5b75SMichael Corcoran 		    rhdl->acpidev_reg_count * sizeof (acpidev_regspec_t) /
1058b72d5b75SMichael Corcoran 		    sizeof (int)) != NDI_SUCCESS) {
1059a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1060b72d5b75SMichael Corcoran 			    "'reg' property for %s.", path);
1061b72d5b75SMichael Corcoran 			rc = AE_ERROR;
1062b72d5b75SMichael Corcoran 			goto out;
1063b72d5b75SMichael Corcoran 		}
1064b72d5b75SMichael Corcoran 		if (rhdl->acpidev_reg_count > 0 &&
1065b72d5b75SMichael Corcoran 		    ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1066b72d5b75SMichael Corcoran 		    "assigned-addresses", (int *)rhdl->acpidev_regp,
1067b72d5b75SMichael Corcoran 		    rhdl->acpidev_reg_count * sizeof (acpidev_regspec_t) /
1068b72d5b75SMichael Corcoran 		    sizeof (int)) != NDI_SUCCESS) {
1069a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1070b72d5b75SMichael Corcoran 			    "'assigned-addresses' property for %s.", path);
1071b72d5b75SMichael Corcoran 			rc = AE_ERROR;
1072b72d5b75SMichael Corcoran 			goto out;
1073b72d5b75SMichael Corcoran 		}
1074b72d5b75SMichael Corcoran 
1075b72d5b75SMichael Corcoran 		/* Create 'interrupts' property. */
1076b72d5b75SMichael Corcoran 		if (rhdl->acpidev_irq_count > 0 &&
1077b72d5b75SMichael Corcoran 		    ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1078b72d5b75SMichael Corcoran 		    "interrupts", (int *)rhdl->acpidev_irqp,
1079b72d5b75SMichael Corcoran 		    rhdl->acpidev_irq_count) != NDI_SUCCESS) {
1080a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1081b72d5b75SMichael Corcoran 			    "'interrupts' property for %s.", path);
1082b72d5b75SMichael Corcoran 			rc = AE_ERROR;
1083b72d5b75SMichael Corcoran 			goto out;
1084b72d5b75SMichael Corcoran 		}
1085b72d5b75SMichael Corcoran 
1086b72d5b75SMichael Corcoran 		/* Create 'dma-channels' property. */
1087b72d5b75SMichael Corcoran 		if (rhdl->acpidev_dma_count > 0 &&
1088b72d5b75SMichael Corcoran 		    ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1089b72d5b75SMichael Corcoran 		    "dma-channels", (int *)rhdl->acpidev_dmap,
1090b72d5b75SMichael Corcoran 		    rhdl->acpidev_dma_count) != NDI_SUCCESS) {
1091a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1092b72d5b75SMichael Corcoran 			    "'dma-channels' property for %s.", path);
1093b72d5b75SMichael Corcoran 			rc = AE_ERROR;
1094b72d5b75SMichael Corcoran 			goto out;
1095b72d5b75SMichael Corcoran 		}
1096b72d5b75SMichael Corcoran 
1097b72d5b75SMichael Corcoran 	} else {
1098b72d5b75SMichael Corcoran 		/* Create device properties for producer. */
1099b72d5b75SMichael Corcoran 
1100b72d5b75SMichael Corcoran 		/* Create 'ranges' property. */
1101b72d5b75SMichael Corcoran 		if (rhdl->acpidev_range_count > 0 &&
1102b72d5b75SMichael Corcoran 		    ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1103b72d5b75SMichael Corcoran 		    "ranges", (int *)rhdl->acpidev_rangep,
1104b72d5b75SMichael Corcoran 		    rhdl->acpidev_range_count * sizeof (acpidev_ranges_t) /
1105b72d5b75SMichael Corcoran 		    sizeof (int)) != NDI_SUCCESS) {
1106a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1107b72d5b75SMichael Corcoran 			    "'ranges' property for %s.", path);
1108b72d5b75SMichael Corcoran 			rc = AE_ERROR;
1109b72d5b75SMichael Corcoran 			goto out;
1110b72d5b75SMichael Corcoran 		}
1111b72d5b75SMichael Corcoran 
1112b72d5b75SMichael Corcoran 		/* Create 'bus-range' property. */
1113b72d5b75SMichael Corcoran 		if (rhdl->acpidev_bus_count > 0 &&
1114b72d5b75SMichael Corcoran 		    ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1115b72d5b75SMichael Corcoran 		    "bus-range", (int *)rhdl->acpidev_busp,
1116b72d5b75SMichael Corcoran 		    rhdl->acpidev_bus_count * sizeof (acpidev_bus_range_t) /
1117b72d5b75SMichael Corcoran 		    sizeof (int)) != NDI_SUCCESS) {
1118a3114836SGerry Liu 			ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1119b72d5b75SMichael Corcoran 			    "'bus-range' property for %s.", path);
1120b72d5b75SMichael Corcoran 			rc = AE_ERROR;
1121b72d5b75SMichael Corcoran 			goto out;
1122b72d5b75SMichael Corcoran 		}
1123b72d5b75SMichael Corcoran 	}
1124b72d5b75SMichael Corcoran 
1125b72d5b75SMichael Corcoran out:
1126b72d5b75SMichael Corcoran 	/* Free resources allocated by acpidev_resource_walk. */
1127b72d5b75SMichael Corcoran 	acpidev_resource_handle_free(rhdl);
1128b72d5b75SMichael Corcoran 
1129b72d5b75SMichael Corcoran 	return (rc);
1130b72d5b75SMichael Corcoran }
1131