Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / acpi / acpi_resource.c
blob55b32c714bfe9df5d9b67cbd9ee0c1ab61bffeec
1 /* $NetBSD: acpi_resource.c,v 1.29 2009/07/13 12:55:21 kiyohara Exp $ */
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
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.
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.
38 /*-
39 * Copyright (c) 2000 Michael Smith
40 * Copyright (c) 2000 BSDi
41 * All rights reserved.
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.
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.
66 * ACPI resource parsing.
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: acpi_resource.c,v 1.29 2009/07/13 12:55:21 kiyohara Exp $");
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/device.h>
76 #include <dev/acpi/acpica.h>
77 #include <dev/acpi/acpireg.h>
78 #include <dev/acpi/acpivar.h>
80 #define _COMPONENT ACPI_RESOURCE_COMPONENT
81 ACPI_MODULE_NAME("RESOURCE")
83 static ACPI_STATUS acpi_resource_parse_callback(ACPI_RESOURCE *, void *);
85 struct resource_parse_callback_arg {
86 const struct acpi_resource_parse_ops *ops;
87 device_t dev;
88 void *context;
91 static ACPI_STATUS
92 acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context)
94 struct resource_parse_callback_arg *arg = context;
95 const struct acpi_resource_parse_ops *ops;
96 int i;
98 ACPI_FUNCTION_TRACE(__func__);
100 ops = arg->ops;
102 switch (res->Type) {
103 case ACPI_RESOURCE_TYPE_FIXED_IO:
104 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
105 "FixedIo 0x%x/%d\n",
106 res->Data.FixedIo.Address,
107 res->Data.FixedIo.AddressLength));
108 if (ops->ioport)
109 (*ops->ioport)(arg->dev, arg->context,
110 res->Data.FixedIo.Address,
111 res->Data.FixedIo.AddressLength);
112 break;
114 case ACPI_RESOURCE_TYPE_IO:
115 if (res->Data.Io.Minimum ==
116 res->Data.Io.Maximum) {
117 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
118 "Io 0x%x/%d\n",
119 res->Data.Io.Minimum,
120 res->Data.Io.AddressLength));
121 if (ops->ioport)
122 (*ops->ioport)(arg->dev, arg->context,
123 res->Data.Io.Minimum,
124 res->Data.Io.AddressLength);
125 } else {
126 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
127 "Io 0x%x-0x%x/%d\n",
128 res->Data.Io.Minimum,
129 res->Data.Io.Maximum,
130 res->Data.Io.AddressLength));
131 if (ops->iorange)
132 (*ops->iorange)(arg->dev, arg->context,
133 res->Data.Io.Minimum,
134 res->Data.Io.Maximum,
135 res->Data.Io.AddressLength,
136 res->Data.Io.Alignment);
138 break;
140 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
141 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
142 "FixedMemory32 0x%x/%d\n",
143 res->Data.FixedMemory32.Address,
144 res->Data.FixedMemory32.AddressLength));
145 if (ops->memory)
146 (*ops->memory)(arg->dev, arg->context,
147 res->Data.FixedMemory32.Address,
148 res->Data.FixedMemory32.AddressLength);
149 break;
151 case ACPI_RESOURCE_TYPE_MEMORY32:
152 if (res->Data.Memory32.Minimum ==
153 res->Data.Memory32.Maximum) {
154 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
155 "Memory32 0x%x/%d\n",
156 res->Data.Memory32.Minimum,
157 res->Data.Memory32.AddressLength));
158 if (ops->memory)
159 (*ops->memory)(arg->dev, arg->context,
160 res->Data.Memory32.Minimum,
161 res->Data.Memory32.AddressLength);
162 } else {
163 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
164 "Memory32 0x%x-0x%x/%d\n",
165 res->Data.Memory32.Minimum,
166 res->Data.Memory32.Maximum,
167 res->Data.Memory32.AddressLength));
168 if (ops->memrange)
169 (*ops->memrange)(arg->dev, arg->context,
170 res->Data.Memory32.Minimum,
171 res->Data.Memory32.Maximum,
172 res->Data.Memory32.AddressLength,
173 res->Data.Memory32.Alignment);
175 break;
177 case ACPI_RESOURCE_TYPE_MEMORY24:
178 if (res->Data.Memory24.Minimum ==
179 res->Data.Memory24.Maximum) {
180 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
181 "Memory24 0x%x/%d\n",
182 res->Data.Memory24.Minimum,
183 res->Data.Memory24.AddressLength));
184 if (ops->memory)
185 (*ops->memory)(arg->dev, arg->context,
186 res->Data.Memory24.Minimum,
187 res->Data.Memory24.AddressLength);
188 } else {
189 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
190 "Memory24 0x%x-0x%x/%d\n",
191 res->Data.Memory24.Minimum,
192 res->Data.Memory24.Maximum,
193 res->Data.Memory24.AddressLength));
194 if (ops->memrange)
195 (*ops->memrange)(arg->dev, arg->context,
196 res->Data.Memory24.Minimum,
197 res->Data.Memory24.Maximum,
198 res->Data.Memory24.AddressLength,
199 res->Data.Memory24.Alignment);
201 break;
203 case ACPI_RESOURCE_TYPE_IRQ:
204 for (i = 0; i < res->Data.Irq.InterruptCount; 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.Triggering);
213 break;
215 case ACPI_RESOURCE_TYPE_DMA:
216 for (i = 0; i < res->Data.Dma.ChannelCount; 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]);
224 break;
226 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
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;
235 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
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 break;
242 case ACPI_RESOURCE_TYPE_ADDRESS32:
243 /* XXX Only fixed size supported for now */
244 if (res->Data.Address32.AddressLength == 0 ||
245 res->Data.Address32.ProducerConsumer != ACPI_CONSUMER)
246 break;
247 #define ADRRESS32_FIXED2(r) \
248 ((r)->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED && \
249 (r)->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)
250 switch (res->Data.Address32.ResourceType) {
251 case ACPI_MEMORY_RANGE:
252 if (ADRRESS32_FIXED2(res)) {
253 if (ops->memory)
254 (*ops->memory)(arg->dev, arg->context,
255 res->Data.Address32.Minimum,
256 res->Data.Address32.AddressLength);
257 } else {
258 if (ops->memrange)
259 (*ops->memrange)(arg->dev, arg->context,
260 res->Data.Address32.Minimum,
261 res->Data.Address32.Maximum,
262 res->Data.Address32.AddressLength,
263 res->Data.Address32.Granularity);
265 break;
266 case ACPI_IO_RANGE:
267 if (ADRRESS32_FIXED2(res)) {
268 if (ops->ioport)
269 (*ops->ioport)(arg->dev, arg->context,
270 res->Data.Address32.Minimum,
271 res->Data.Address32.AddressLength);
272 } else {
273 if (ops->iorange)
274 (*ops->iorange)(arg->dev, arg->context,
275 res->Data.Address32.Minimum,
276 res->Data.Address32.Maximum,
277 res->Data.Address32.AddressLength,
278 res->Data.Address32.Granularity);
280 break;
281 case ACPI_BUS_NUMBER_RANGE:
282 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
283 "Address32/BusNumber unimplemented\n"));
284 break;
286 #undef ADRRESS32_FIXED2
287 break;
289 case ACPI_RESOURCE_TYPE_ADDRESS16:
290 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
291 "Address16 unimplemented\n"));
292 break;
294 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
295 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
296 "Extended address64 unimplemented\n"));
297 break;
299 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
300 if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
301 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
302 "ignored ExtIRQ producer\n"));
303 break;
305 for (i = 0; i < res->Data.ExtendedIrq.InterruptCount; i++) {
306 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
307 "ExtIRQ %d\n",
308 res->Data.ExtendedIrq.Interrupts[i]));
309 if (ops->irq)
310 (*ops->irq)(arg->dev, arg->context,
311 res->Data.ExtendedIrq.Interrupts[i],
312 res->Data.ExtendedIrq.Triggering);
314 break;
316 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
317 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
318 "GenericRegister unimplemented\n"));
319 break;
321 case ACPI_RESOURCE_TYPE_VENDOR:
322 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
323 "VendorSpecific unimplemented\n"));
324 break;
326 default:
327 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
328 "Unknown resource type: %d\n", res->Type));
329 break;
332 return_ACPI_STATUS(AE_OK);
337 * acpi_resource_parse:
339 * Parse a device node's resources and fill them in for the
340 * client.
342 * This API supports _CRS (current resources) and
343 * _PRS (possible resources).
345 * Note that it might be nice to also locate ACPI-specific resource
346 * items, such as GPE bits.
348 ACPI_STATUS
349 acpi_resource_parse(device_t dev, ACPI_HANDLE handle, const char *path,
350 void *arg, const struct acpi_resource_parse_ops *ops)
352 struct resource_parse_callback_arg cbarg;
353 ACPI_STATUS rv;
355 ACPI_FUNCTION_TRACE(__func__);
357 if (ops->init)
358 (*ops->init)(dev, arg, &cbarg.context);
359 else
360 cbarg.context = arg;
361 cbarg.ops = ops;
362 cbarg.dev = dev;
364 rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
365 &cbarg);
366 if (ACPI_FAILURE(rv)) {
367 aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n",
368 path, AcpiFormatException(rv));
369 return_ACPI_STATUS(rv);
372 if (ops->fini)
373 (*ops->fini)(dev, cbarg.context);
375 return_ACPI_STATUS(AE_OK);
379 * acpi_resource_print:
381 * Print the resources assigned to a device.
383 void
384 acpi_resource_print(device_t dev, struct acpi_resources *res)
386 const char *sep;
388 if (SIMPLEQ_EMPTY(&res->ar_io) &&
389 SIMPLEQ_EMPTY(&res->ar_iorange) &&
390 SIMPLEQ_EMPTY(&res->ar_mem) &&
391 SIMPLEQ_EMPTY(&res->ar_memrange) &&
392 SIMPLEQ_EMPTY(&res->ar_irq) &&
393 SIMPLEQ_EMPTY(&res->ar_drq))
394 return;
396 aprint_normal(":");
398 if (SIMPLEQ_EMPTY(&res->ar_io) == 0) {
399 struct acpi_io *ar;
401 sep = "";
402 aprint_normal(" io ");
403 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
404 aprint_normal("%s0x%x", sep, ar->ar_base);
405 if (ar->ar_length > 1)
406 aprint_normal("-0x%x", ar->ar_base +
407 ar->ar_length - 1);
408 sep = ",";
412 /* XXX iorange */
414 if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) {
415 struct acpi_mem *ar;
417 sep = "";
418 aprint_normal(" mem ");
419 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
420 aprint_normal("%s0x%x", sep, ar->ar_base);
421 if (ar->ar_length > 1)
422 aprint_normal("-0x%x", ar->ar_base +
423 ar->ar_length - 1);
424 sep = ",";
428 /* XXX memrange */
430 if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) {
431 struct acpi_irq *ar;
433 sep = "";
434 aprint_normal(" irq ");
435 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
436 aprint_normal("%s%d", sep, ar->ar_irq);
437 sep = ",";
441 if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) {
442 struct acpi_drq *ar;
444 sep = "";
445 aprint_normal(" drq ");
446 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
447 aprint_normal("%s%d", sep, ar->ar_drq);
448 sep = ",";
452 aprint_normal("\n");
453 aprint_naive("\n");
457 * acpi_resource_cleanup:
459 * Free all allocated buffers
461 void
462 acpi_resource_cleanup(struct acpi_resources *res)
464 while (!SIMPLEQ_EMPTY(&res->ar_io)) {
465 struct acpi_io *ar;
466 ar = SIMPLEQ_FIRST(&res->ar_io);
467 SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list);
468 ACPI_FREE(ar);
471 while (!SIMPLEQ_EMPTY(&res->ar_iorange)) {
472 struct acpi_iorange *ar;
473 ar = SIMPLEQ_FIRST(&res->ar_iorange);
474 SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list);
475 ACPI_FREE(ar);
478 while (!SIMPLEQ_EMPTY(&res->ar_mem)) {
479 struct acpi_mem *ar;
480 ar = SIMPLEQ_FIRST(&res->ar_mem);
481 SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list);
482 ACPI_FREE(ar);
485 while (!SIMPLEQ_EMPTY(&res->ar_memrange)) {
486 struct acpi_memrange *ar;
487 ar = SIMPLEQ_FIRST(&res->ar_memrange);
488 SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list);
489 ACPI_FREE(ar);
492 while (!SIMPLEQ_EMPTY(&res->ar_irq)) {
493 struct acpi_irq *ar;
494 ar = SIMPLEQ_FIRST(&res->ar_irq);
495 SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list);
496 ACPI_FREE(ar);
499 while (!SIMPLEQ_EMPTY(&res->ar_drq)) {
500 struct acpi_drq *ar;
501 ar = SIMPLEQ_FIRST(&res->ar_drq);
502 SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list);
503 ACPI_FREE(ar);
506 res->ar_nio = res->ar_niorange = res->ar_nmem =
507 res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0;
510 struct acpi_io *
511 acpi_res_io(struct acpi_resources *res, int idx)
513 struct acpi_io *ar;
515 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
516 if (ar->ar_index == idx)
517 return ar;
519 return NULL;
522 struct acpi_iorange *
523 acpi_res_iorange(struct acpi_resources *res, int idx)
525 struct acpi_iorange *ar;
527 SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) {
528 if (ar->ar_index == idx)
529 return ar;
531 return NULL;
534 struct acpi_mem *
535 acpi_res_mem(struct acpi_resources *res, int idx)
537 struct acpi_mem *ar;
539 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
540 if (ar->ar_index == idx)
541 return ar;
543 return NULL;
546 struct acpi_memrange *
547 acpi_res_memrange(struct acpi_resources *res, int idx)
549 struct acpi_memrange *ar;
551 SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) {
552 if (ar->ar_index == idx)
553 return ar;
555 return NULL;
558 struct acpi_irq *
559 acpi_res_irq(struct acpi_resources *res, int idx)
561 struct acpi_irq *ar;
563 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
564 if (ar->ar_index == idx)
565 return ar;
567 return NULL;
570 struct acpi_drq *
571 acpi_res_drq(struct acpi_resources *res, int idx)
573 struct acpi_drq *ar;
575 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
576 if (ar->ar_index == idx)
577 return ar;
579 return NULL;
582 /*****************************************************************************
583 * Default ACPI resource parse operations.
584 *****************************************************************************/
586 static void acpi_res_parse_init(device_t, void *, void **);
587 static void acpi_res_parse_fini(device_t, void *);
589 static void acpi_res_parse_ioport(device_t, void *, uint32_t,
590 uint32_t);
591 static void acpi_res_parse_iorange(device_t, void *, uint32_t,
592 uint32_t, uint32_t, uint32_t);
594 static void acpi_res_parse_memory(device_t, void *, uint32_t,
595 uint32_t);
596 static void acpi_res_parse_memrange(device_t, void *, uint32_t,
597 uint32_t, uint32_t, uint32_t);
599 static void acpi_res_parse_irq(device_t, void *, uint32_t, uint32_t);
600 static void acpi_res_parse_drq(device_t, void *, uint32_t);
602 static void acpi_res_parse_start_dep(device_t, void *, int);
603 static void acpi_res_parse_end_dep(device_t, void *);
605 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = {
606 .init = acpi_res_parse_init,
607 .fini = acpi_res_parse_fini,
609 .ioport = acpi_res_parse_ioport,
610 .iorange = acpi_res_parse_iorange,
612 .memory = acpi_res_parse_memory,
613 .memrange = acpi_res_parse_memrange,
615 .irq = acpi_res_parse_irq,
616 .drq = acpi_res_parse_drq,
618 .start_dep = acpi_res_parse_start_dep,
619 .end_dep = acpi_res_parse_end_dep,
622 static void
623 acpi_res_parse_init(device_t dev, void *arg, void **contextp)
625 struct acpi_resources *res = arg;
627 SIMPLEQ_INIT(&res->ar_io);
628 res->ar_nio = 0;
630 SIMPLEQ_INIT(&res->ar_iorange);
631 res->ar_niorange = 0;
633 SIMPLEQ_INIT(&res->ar_mem);
634 res->ar_nmem = 0;
636 SIMPLEQ_INIT(&res->ar_memrange);
637 res->ar_nmemrange = 0;
639 SIMPLEQ_INIT(&res->ar_irq);
640 res->ar_nirq = 0;
642 SIMPLEQ_INIT(&res->ar_drq);
643 res->ar_ndrq = 0;
645 *contextp = res;
648 static void
649 acpi_res_parse_fini(device_t dev, void *context)
651 struct acpi_resources *res = context;
653 /* Print the resources we're using. */
654 acpi_resource_print(dev, res);
657 static void
658 acpi_res_parse_ioport(device_t dev, void *context, uint32_t base,
659 uint32_t length)
661 struct acpi_resources *res = context;
662 struct acpi_io *ar;
665 * Check if there is another I/O port directly below/under
666 * this one.
668 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
669 if (ar->ar_base == base + length ) {
671 * Entry just below existing entry - adjust
672 * the entry and return.
674 ar->ar_base = base;
675 ar->ar_length += length;
676 return;
677 } else if (ar->ar_base + ar->ar_length == base) {
679 * Entry just above existing entry - adjust
680 * the entry and return.
682 ar->ar_length += length;
683 return;
687 ar = ACPI_ALLOCATE(sizeof(*ar));
688 if (ar == NULL) {
689 aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n",
690 res->ar_nio);
691 res->ar_nio++;
692 return;
695 ar->ar_index = res->ar_nio++;
696 ar->ar_base = base;
697 ar->ar_length = length;
699 SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list);
702 static void
703 acpi_res_parse_iorange(device_t dev, void *context, uint32_t low,
704 uint32_t high, uint32_t length, uint32_t align)
706 struct acpi_resources *res = context;
707 struct acpi_iorange *ar;
709 ar = ACPI_ALLOCATE(sizeof(*ar));
710 if (ar == NULL) {
711 aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n",
712 res->ar_niorange);
713 res->ar_niorange++;
714 return;
717 ar->ar_index = res->ar_niorange++;
718 ar->ar_low = low;
719 ar->ar_high = high;
720 ar->ar_length = length;
721 ar->ar_align = align;
723 SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list);
726 static void
727 acpi_res_parse_memory(device_t dev, void *context, uint32_t base,
728 uint32_t length)
730 struct acpi_resources *res = context;
731 struct acpi_mem *ar;
733 ar = ACPI_ALLOCATE(sizeof(*ar));
734 if (ar == NULL) {
735 aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n",
736 res->ar_nmem);
737 res->ar_nmem++;
738 return;
741 ar->ar_index = res->ar_nmem++;
742 ar->ar_base = base;
743 ar->ar_length = length;
745 SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list);
748 static void
749 acpi_res_parse_memrange(device_t dev, void *context, uint32_t low,
750 uint32_t high, uint32_t length, uint32_t align)
752 struct acpi_resources *res = context;
753 struct acpi_memrange *ar;
755 ar = ACPI_ALLOCATE(sizeof(*ar));
756 if (ar == NULL) {
757 aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n",
758 res->ar_nmemrange);
759 res->ar_nmemrange++;
760 return;
763 ar->ar_index = res->ar_nmemrange++;
764 ar->ar_low = low;
765 ar->ar_high = high;
766 ar->ar_length = length;
767 ar->ar_align = align;
769 SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list);
772 static void
773 acpi_res_parse_irq(device_t dev, void *context, uint32_t irq, uint32_t type)
775 struct acpi_resources *res = context;
776 struct acpi_irq *ar;
778 ar = ACPI_ALLOCATE(sizeof(*ar));
779 if (ar == NULL) {
780 aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n",
781 res->ar_nirq);
782 res->ar_nirq++;
783 return;
786 ar->ar_index = res->ar_nirq++;
787 ar->ar_irq = irq;
788 ar->ar_type = type;
790 SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list);
793 static void
794 acpi_res_parse_drq(device_t dev, void *context, uint32_t drq)
796 struct acpi_resources *res = context;
797 struct acpi_drq *ar;
799 ar = ACPI_ALLOCATE(sizeof(*ar));
800 if (ar == NULL) {
801 aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n",
802 res->ar_ndrq);
803 res->ar_ndrq++;
804 return;
807 ar->ar_index = res->ar_ndrq++;
808 ar->ar_drq = drq;
810 SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list);
813 static void
814 acpi_res_parse_start_dep(device_t dev, void *context,
815 int preference)
818 aprint_error_dev(dev, "ACPI: dependant functions not supported\n");
821 static void
822 acpi_res_parse_end_dep(device_t dev, void *context)
825 /* Nothing to do. */