xref: /netbsd-src/sys/dev/acpi/acpi_resource.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: acpi_resource.c,v 1.15 2004/04/12 15:11:04 kochi Exp $	*/
2 
3 /*
4  * Copyright 2001 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed for the NetBSD Project by
20  *	Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*-
39  * Copyright (c) 2000 Michael Smith
40  * Copyright (c) 2000 BSDi
41  * All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  */
64 
65 /*
66  * ACPI resource parsing.
67  */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: acpi_resource.c,v 1.15 2004/04/12 15:11:04 kochi Exp $");
71 
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/device.h>
75 
76 #include <dev/acpi/acpica.h>
77 #include <dev/acpi/acpireg.h>
78 #include <dev/acpi/acpivar.h>
79 
80 #define	_COMPONENT	ACPI_RESOURCE_COMPONENT
81 ACPI_MODULE_NAME("RESOURCE")
82 
83 static ACPI_STATUS acpi_resource_parse_callback(ACPI_RESOURCE *, void *);
84 
85 struct resource_parse_callback_arg {
86 	const struct acpi_resource_parse_ops *ops;
87 	struct device *dev;
88 	void *context;
89 };
90 
91 static ACPI_STATUS
92 acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context)
93 {
94 	struct resource_parse_callback_arg *arg = context;
95 	const struct acpi_resource_parse_ops *ops;
96 	int i;
97 
98 	ACPI_FUNCTION_TRACE(__FUNCTION__);
99 
100 	ops = arg->ops;
101 
102 	switch (res->Id) {
103 	case ACPI_RSTYPE_FIXED_IO:
104 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
105 				     "FixedIo 0x%x/%d\n",
106 				     res->Data.FixedIo.BaseAddress,
107 				     res->Data.FixedIo.RangeLength));
108 		if (ops->ioport)
109 			(*ops->ioport)(arg->dev, arg->context,
110 			    res->Data.FixedIo.BaseAddress,
111 			    res->Data.FixedIo.RangeLength);
112 		break;
113 
114 	case ACPI_RSTYPE_IO:
115 		if (res->Data.Io.MinBaseAddress ==
116 			    res->Data.Io.MaxBaseAddress) {
117 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
118 					     "Io 0x%x/%d\n",
119 					     res->Data.Io.MinBaseAddress,
120 					     res->Data.Io.RangeLength));
121 			if (ops->ioport)
122 				(*ops->ioport)(arg->dev, arg->context,
123 				    res->Data.Io.MinBaseAddress,
124 				    res->Data.Io.RangeLength);
125 		} else {
126 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
127 					     "Io 0x%x-0x%x/%d\n",
128 					     res->Data.Io.MinBaseAddress,
129 					     res->Data.Io.MaxBaseAddress,
130 					     res->Data.Io.RangeLength));
131 			if (ops->ioport)
132 				(*ops->iorange)(arg->dev, arg->context,
133 				    res->Data.Io.MinBaseAddress,
134 				    res->Data.Io.MaxBaseAddress,
135 				    res->Data.Io.RangeLength,
136 				    res->Data.Io.Alignment);
137 		}
138 		break;
139 
140 	case ACPI_RSTYPE_FIXED_MEM32:
141 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
142 				     "FixedMemory32 0x%x/%d\n",
143 				     res->Data.FixedMemory32.RangeBaseAddress,
144 				     res->Data.FixedMemory32.RangeLength));
145 		if (ops->memory)
146 			(*ops->memory)(arg->dev, arg->context,
147 			    res->Data.FixedMemory32.RangeBaseAddress,
148 			    res->Data.FixedMemory32.RangeLength);
149 		break;
150 
151 	case ACPI_RSTYPE_MEM32:
152 		if (res->Data.Memory32.MinBaseAddress ==
153 		    res->Data.Memory32.MaxBaseAddress) {
154 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
155 					     "Memory32 0x%x/%d\n",
156 					     res->Data.Memory32.MinBaseAddress,
157 					     res->Data.Memory32.RangeLength));
158 			if (ops->memory)
159 				(*ops->memory)(arg->dev, arg->context,
160 				    res->Data.Memory32.MinBaseAddress,
161 				    res->Data.Memory32.RangeLength);
162 		} else {
163 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
164 					     "Memory32 0x%x-0x%x/%d\n",
165 					     res->Data.Memory32.MinBaseAddress,
166 					     res->Data.Memory32.MaxBaseAddress,
167 					     res->Data.Memory32.RangeLength));
168 			if (ops->memrange)
169 				(*ops->memrange)(arg->dev, arg->context,
170 				    res->Data.Memory32.MinBaseAddress,
171 				    res->Data.Memory32.MaxBaseAddress,
172 				    res->Data.Memory32.RangeLength,
173 				    res->Data.Memory32.Alignment);
174 		}
175 		break;
176 
177 	case ACPI_RSTYPE_MEM24:
178 		if (res->Data.Memory24.MinBaseAddress ==
179 		    res->Data.Memory24.MaxBaseAddress) {
180 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
181 					     "Memory24 0x%x/%d\n",
182 					     res->Data.Memory24.MinBaseAddress,
183 					     res->Data.Memory24.RangeLength));
184 			if (ops->memory)
185 				(*ops->memory)(arg->dev, arg->context,
186 				    res->Data.Memory24.MinBaseAddress,
187 				    res->Data.Memory24.RangeLength);
188 		} else {
189 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
190 					     "Memory24 0x%x-0x%x/%d\n",
191 					     res->Data.Memory24.MinBaseAddress,
192 					     res->Data.Memory24.MaxBaseAddress,
193 					     res->Data.Memory24.RangeLength));
194 			if (ops->memrange)
195 				(*ops->memrange)(arg->dev, arg->context,
196 				    res->Data.Memory24.MinBaseAddress,
197 				    res->Data.Memory24.MaxBaseAddress,
198 				    res->Data.Memory24.RangeLength,
199 				    res->Data.Memory24.Alignment);
200 		}
201 		break;
202 
203 	case ACPI_RSTYPE_IRQ:
204 		for (i = 0; i < res->Data.Irq.NumberOfInterrupts; i++) {
205 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
206 					     "IRQ %d\n",
207 					     res->Data.Irq.Interrupts[i]));
208 			if (ops->irq)
209 				(*ops->irq)(arg->dev, arg->context,
210 				    res->Data.Irq.Interrupts[i],
211 				    res->Data.Irq.EdgeLevel);
212 		}
213 		break;
214 
215 	case ACPI_RSTYPE_DMA:
216 		for (i = 0; i < res->Data.Dma.NumberOfChannels; i++) {
217 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
218 					     "DRQ %d\n",
219 					     res->Data.Dma.Channels[i]));
220 			if (ops->drq)
221 				(*ops->drq)(arg->dev, arg->context,
222 				    res->Data.Dma.Channels[i]);
223 		}
224 		break;
225 
226 	case ACPI_RSTYPE_START_DPF:
227 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
228 				     "Start dependant functions: %d\n",
229 				     res->Data.StartDpf.CompatibilityPriority));
230 		if (ops->start_dep)
231 			(*ops->start_dep)(arg->dev, arg->context,
232 			    res->Data.StartDpf.CompatibilityPriority);
233 		break;
234 
235 	case ACPI_RSTYPE_END_DPF:
236 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
237 				     "End dependant functions\n"));
238 		if (ops->end_dep)
239 			(*ops->end_dep)(arg->dev, arg->context);
240 
241 	case ACPI_RSTYPE_ADDRESS32:
242 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
243 				     "Address32 unimplemented\n"));
244 		break;
245 
246 	case ACPI_RSTYPE_ADDRESS16:
247 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
248 				     "Address16 unimplemented\n"));
249 		break;
250 
251 	case ACPI_RSTYPE_EXT_IRQ:
252 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
253 				     "ExtendedIrq unimplemented\n"));
254 		break;
255 
256 	case ACPI_RSTYPE_VENDOR:
257 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
258 				     "VendorSpecific unimplemented\n"));
259 		break;
260 
261 	default:
262 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
263 				     "Unknown resource type: %d\n", res->Id));
264 		break;
265 	}
266 
267 	return_ACPI_STATUS(AE_OK);
268 }
269 
270 
271 /*
272  * acpi_resource_parse:
273  *
274  *	Parse a device node's resources and fill them in for the
275  *	client.
276  *
277  *	This API supports _CRS (current resources) and
278  *	_PRS (possible resources).
279  *
280  *	Note that it might be nice to also locate ACPI-specific resource
281  *	items, such as GPE bits.
282  */
283 ACPI_STATUS
284 acpi_resource_parse(struct device *dev, ACPI_HANDLE handle, char *path,
285     void *arg, const struct acpi_resource_parse_ops *ops)
286 {
287 	struct resource_parse_callback_arg cbarg;
288 	ACPI_STATUS rv;
289 
290 	ACPI_FUNCTION_TRACE(__FUNCTION__);
291 
292 	if (ops->init)
293 		(*ops->init)(dev, arg, &cbarg.context);
294 	else
295 		cbarg.context = arg;
296 	cbarg.ops = ops;
297 	cbarg.dev = dev;
298 
299 	rv =AcpiWalkResources(handle, path, acpi_resource_parse_callback,
300 	    &cbarg);
301 	if (ACPI_FAILURE(rv)) {
302 		printf("%s: ACPI: unable to get %s resources: %s\n",
303 		    dev->dv_xname, path, AcpiFormatException(rv));
304 		return_ACPI_STATUS(rv);
305 	}
306 
307 	if (ops->fini)
308 		(*ops->fini)(dev, cbarg.context);
309 
310 	return_ACPI_STATUS(AE_OK);
311 }
312 
313 /*
314  * acpi_resource_print:
315  *
316  *	Print the resources assigned to a device.
317  */
318 void
319 acpi_resource_print(struct device *dev, struct acpi_resources *res)
320 {
321 	const char *sep;
322 
323 	if (SIMPLEQ_EMPTY(&res->ar_io) &&
324 	    SIMPLEQ_EMPTY(&res->ar_iorange) &&
325 	    SIMPLEQ_EMPTY(&res->ar_mem) &&
326 	    SIMPLEQ_EMPTY(&res->ar_memrange) &&
327 	    SIMPLEQ_EMPTY(&res->ar_irq) &&
328 	    SIMPLEQ_EMPTY(&res->ar_drq))
329 		return;
330 
331 	printf("%s:", dev->dv_xname);
332 
333 	if (SIMPLEQ_EMPTY(&res->ar_io) == 0) {
334 		struct acpi_io *ar;
335 
336 		sep = "";
337 		printf(" io ");
338 		SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
339 			printf("%s0x%x", sep, ar->ar_base);
340 			if (ar->ar_length > 1)
341 				printf("-0x%x", ar->ar_base +
342 				    ar->ar_length - 1);
343 			sep = ",";
344 		}
345 	}
346 
347 	/* XXX iorange */
348 
349 	if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) {
350 		struct acpi_mem *ar;
351 
352 		sep = "";
353 		printf(" mem ");
354 		SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
355 			printf("%s0x%x", sep, ar->ar_base);
356 			if (ar->ar_length > 1)
357 				printf("-0x%x", ar->ar_base +
358 				    ar->ar_length - 1);
359 			sep = ",";
360 		}
361 	}
362 
363 	/* XXX memrange */
364 
365 	if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) {
366 		struct acpi_irq *ar;
367 
368 		sep = "";
369 		printf(" irq ");
370 		SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
371 			printf("%s%d", sep, ar->ar_irq);
372 			sep = ",";
373 		}
374 	}
375 
376 	if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) {
377 		struct acpi_drq *ar;
378 
379 		sep = "";
380 		printf(" drq ");
381 		SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
382 			printf("%s%d", sep, ar->ar_drq);
383 			sep = ",";
384 		}
385 	}
386 
387 	printf("\n");
388 }
389 
390 /*
391  * acpi_resource_cleanup:
392  *
393  *	Free all allocated buffers
394  */
395 void
396 acpi_resource_cleanup(struct acpi_resources *res)
397 {
398 	while (!SIMPLEQ_EMPTY(&res->ar_io)) {
399 		struct acpi_io *ar;
400 		ar = SIMPLEQ_FIRST(&res->ar_io);
401 		SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list);
402 		AcpiOsFree(ar);
403 	}
404 
405 	while (!SIMPLEQ_EMPTY(&res->ar_iorange)) {
406 		struct acpi_iorange *ar;
407 		ar = SIMPLEQ_FIRST(&res->ar_iorange);
408 		SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list);
409 		AcpiOsFree(ar);
410 	}
411 
412 	while (!SIMPLEQ_EMPTY(&res->ar_mem)) {
413 		struct acpi_mem *ar;
414 		ar = SIMPLEQ_FIRST(&res->ar_mem);
415 		SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list);
416 		AcpiOsFree(ar);
417 	}
418 
419 	while (!SIMPLEQ_EMPTY(&res->ar_memrange)) {
420 		struct acpi_memrange *ar;
421 		ar = SIMPLEQ_FIRST(&res->ar_memrange);
422 		SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list);
423 		AcpiOsFree(ar);
424 	}
425 
426 	while (!SIMPLEQ_EMPTY(&res->ar_irq)) {
427 		struct acpi_irq *ar;
428 		ar = SIMPLEQ_FIRST(&res->ar_irq);
429 		SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list);
430 		AcpiOsFree(ar);
431 	}
432 
433 	while (!SIMPLEQ_EMPTY(&res->ar_drq)) {
434 		struct acpi_drq *ar;
435 		ar = SIMPLEQ_FIRST(&res->ar_drq);
436 		SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list);
437 		AcpiOsFree(ar);
438 	}
439 
440 	res->ar_nio = res->ar_niorange = res->ar_nmem =
441 	    res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0;
442 }
443 
444 struct acpi_io *
445 acpi_res_io(struct acpi_resources *res, int idx)
446 {
447 	struct acpi_io *ar;
448 
449 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
450 		if (ar->ar_index == idx)
451 			return ar;
452 	}
453 	return NULL;
454 }
455 
456 struct acpi_iorange *
457 acpi_res_iorange(struct acpi_resources *res, int idx)
458 {
459 	struct acpi_iorange *ar;
460 
461 	SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) {
462 		if (ar->ar_index == idx)
463 			return ar;
464 	}
465 	return NULL;
466 }
467 
468 struct acpi_mem *
469 acpi_res_mem(struct acpi_resources *res, int idx)
470 {
471 	struct acpi_mem *ar;
472 
473 	SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
474 		if (ar->ar_index == idx)
475 			return ar;
476 	}
477 	return NULL;
478 }
479 
480 struct acpi_memrange *
481 acpi_res_memrange(struct acpi_resources *res, int idx)
482 {
483 	struct acpi_memrange *ar;
484 
485 	SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) {
486 		if (ar->ar_index == idx)
487 			return ar;
488 	}
489 	return NULL;
490 }
491 
492 struct acpi_irq *
493 acpi_res_irq(struct acpi_resources *res, int idx)
494 {
495 	struct acpi_irq *ar;
496 
497 	SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
498 		if (ar->ar_index == idx)
499 			return ar;
500 	}
501 	return NULL;
502 }
503 
504 struct acpi_drq *
505 acpi_res_drq(struct acpi_resources *res, int idx)
506 {
507 	struct acpi_drq *ar;
508 
509 	SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
510 		if (ar->ar_index == idx)
511 			return ar;
512 	}
513 	return NULL;
514 }
515 
516 /*****************************************************************************
517  * Default ACPI resource parse operations.
518  *****************************************************************************/
519 
520 static void	acpi_res_parse_init(struct device *, void *, void **);
521 static void	acpi_res_parse_fini(struct device *, void *);
522 
523 static void	acpi_res_parse_ioport(struct device *, void *, uint32_t,
524 		    uint32_t);
525 static void	acpi_res_parse_iorange(struct device *, void *, uint32_t,
526 		    uint32_t, uint32_t, uint32_t);
527 
528 static void	acpi_res_parse_memory(struct device *, void *, uint32_t,
529 		    uint32_t);
530 static void	acpi_res_parse_memrange(struct device *, void *, uint32_t,
531 		    uint32_t, uint32_t, uint32_t);
532 
533 static void	acpi_res_parse_irq(struct device *, void *, uint32_t, uint32_t);
534 static void	acpi_res_parse_drq(struct device *, void *, uint32_t);
535 
536 static void	acpi_res_parse_start_dep(struct device *, void *, int);
537 static void	acpi_res_parse_end_dep(struct device *, void *);
538 
539 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = {
540 	.init = acpi_res_parse_init,
541 	.fini = acpi_res_parse_fini,
542 
543 	.ioport = acpi_res_parse_ioport,
544 	.iorange = acpi_res_parse_iorange,
545 
546 	.memory = acpi_res_parse_memory,
547 	.memrange = acpi_res_parse_memrange,
548 
549 	.irq = acpi_res_parse_irq,
550 	.drq = acpi_res_parse_drq,
551 
552 	.start_dep = acpi_res_parse_start_dep,
553 	.end_dep = acpi_res_parse_end_dep,
554 };
555 
556 static void
557 acpi_res_parse_init(struct device *dev, void *arg, void **contextp)
558 {
559 	struct acpi_resources *res = arg;
560 
561 	SIMPLEQ_INIT(&res->ar_io);
562 	res->ar_nio = 0;
563 
564 	SIMPLEQ_INIT(&res->ar_iorange);
565 	res->ar_niorange = 0;
566 
567 	SIMPLEQ_INIT(&res->ar_mem);
568 	res->ar_nmem = 0;
569 
570 	SIMPLEQ_INIT(&res->ar_memrange);
571 	res->ar_nmemrange = 0;
572 
573 	SIMPLEQ_INIT(&res->ar_irq);
574 	res->ar_nirq = 0;
575 
576 	SIMPLEQ_INIT(&res->ar_drq);
577 	res->ar_ndrq = 0;
578 
579 	*contextp = res;
580 }
581 
582 static void
583 acpi_res_parse_fini(struct device *dev, void *context)
584 {
585 	struct acpi_resources *res = context;
586 
587 	/* Print the resources we're using. */
588 	acpi_resource_print(dev, res);
589 }
590 
591 static void
592 acpi_res_parse_ioport(struct device *dev, void *context, uint32_t base,
593     uint32_t length)
594 {
595 	struct acpi_resources *res = context;
596 	struct acpi_io *ar;
597 
598 	/*
599 	 * Check if there is another I/O port directly below/under
600 	 * this one.
601 	 */
602 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
603 		if (ar->ar_base == base + length ) {
604 			/*
605 			 * Entry just below existing entry - adjust
606 			 * the entry and return.
607 			 */
608 			ar->ar_base = base;
609 			ar->ar_length += length;
610 			return;
611 		} else if (ar->ar_base + ar->ar_length == base) {
612 			/*
613 			 * Entry just above existing entry - adjust
614 			 * the entry and return.
615 			 */
616 			ar->ar_length += length;
617 			return;
618 		}
619 	}
620 
621 	ar = AcpiOsAllocate(sizeof(*ar));
622 	if (ar == NULL) {
623 		printf("%s: ACPI: unable to allocate I/O resource %d\n",
624 		    dev->dv_xname, res->ar_nio);
625 		res->ar_nio++;
626 		return;
627 	}
628 
629 	ar->ar_index = res->ar_nio++;
630 	ar->ar_base = base;
631 	ar->ar_length = length;
632 
633 	SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list);
634 }
635 
636 static void
637 acpi_res_parse_iorange(struct device *dev, void *context, uint32_t low,
638     uint32_t high, uint32_t length, uint32_t align)
639 {
640 	struct acpi_resources *res = context;
641 	struct acpi_iorange *ar;
642 
643 	ar = AcpiOsAllocate(sizeof(*ar));
644 	if (ar == NULL) {
645 		printf("%s: ACPI: unable to allocate I/O range resource %d\n",
646 		    dev->dv_xname, res->ar_niorange);
647 		res->ar_niorange++;
648 		return;
649 	}
650 
651 	ar->ar_index = res->ar_niorange++;
652 	ar->ar_low = low;
653 	ar->ar_high = high;
654 	ar->ar_length = length;
655 	ar->ar_align = align;
656 
657 	SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list);
658 }
659 
660 static void
661 acpi_res_parse_memory(struct device *dev, void *context, uint32_t base,
662     uint32_t length)
663 {
664 	struct acpi_resources *res = context;
665 	struct acpi_mem *ar;
666 
667 	ar = AcpiOsAllocate(sizeof(*ar));
668 	if (ar == NULL) {
669 		printf("%s: ACPI: unable to allocate Memory resource %d\n",
670 		    dev->dv_xname, res->ar_nmem);
671 		res->ar_nmem++;
672 		return;
673 	}
674 
675 	ar->ar_index = res->ar_nmem++;
676 	ar->ar_base = base;
677 	ar->ar_length = length;
678 
679 	SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list);
680 }
681 
682 static void
683 acpi_res_parse_memrange(struct device *dev, void *context, uint32_t low,
684     uint32_t high, uint32_t length, uint32_t align)
685 {
686 	struct acpi_resources *res = context;
687 	struct acpi_memrange *ar;
688 
689 	ar = AcpiOsAllocate(sizeof(*ar));
690 	if (ar == NULL) {
691 		printf("%s: ACPI: unable to allocate Memory range resource "
692 		    "%d\n", dev->dv_xname, res->ar_nmemrange);
693 		res->ar_nmemrange++;
694 		return;
695 	}
696 
697 	ar->ar_index = res->ar_nmemrange++;
698 	ar->ar_low = low;
699 	ar->ar_high = high;
700 	ar->ar_length = length;
701 	ar->ar_align = align;
702 
703 	SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list);
704 }
705 
706 static void
707 acpi_res_parse_irq(struct device *dev, void *context, uint32_t irq, uint32_t type)
708 {
709 	struct acpi_resources *res = context;
710 	struct acpi_irq *ar;
711 
712 	ar = AcpiOsAllocate(sizeof(*ar));
713 	if (ar == NULL) {
714 		printf("%s: ACPI: unable to allocate IRQ resource %d\n",
715 		    dev->dv_xname, res->ar_nirq);
716 		res->ar_nirq++;
717 		return;
718 	}
719 
720 	ar->ar_index = res->ar_nirq++;
721 	ar->ar_irq = irq;
722 	ar->ar_type = type;
723 
724 	SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list);
725 }
726 
727 static void
728 acpi_res_parse_drq(struct device *dev, void *context, uint32_t drq)
729 {
730 	struct acpi_resources *res = context;
731 	struct acpi_drq *ar;
732 
733 	ar = AcpiOsAllocate(sizeof(*ar));
734 	if (ar == NULL) {
735 		printf("%s: ACPI: unable to allocate DRQ resource %d\n",
736 		    dev->dv_xname, res->ar_ndrq);
737 		res->ar_ndrq++;
738 		return;
739 	}
740 
741 	ar->ar_index = res->ar_ndrq++;
742 	ar->ar_drq = drq;
743 
744 	SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list);
745 }
746 
747 static void
748 acpi_res_parse_start_dep(struct device *dev, void *context, int preference)
749 {
750 
751 	printf("%s: ACPI: dependant functions not supported\n",
752 	    dev->dv_xname);
753 }
754 
755 static void
756 acpi_res_parse_end_dep(struct device *dev, void *context)
757 {
758 
759 	/* Nothing to do. */
760 }
761