acpi_resource.c revision 1.23 1 /* $NetBSD: acpi_resource.c,v 1.23 2007/12/01 04:51:27 jmcneill 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.23 2007/12/01 04:51:27 jmcneill 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->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;
113
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);
137 }
138 break;
139
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;
150
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);
174 }
175 break;
176
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);
200 }
201 break;
202
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);
212 }
213 break;
214
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]);
223 }
224 break;
225
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;
234
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;
241
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);
264 }
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);
279 }
280 break;
281 case ACPI_BUS_NUMBER_RANGE:
282 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
283 "Address32/BusNumber unimplemented\n"));
284 break;
285 }
286 #undef ADRRESS32_FIXED2
287 break;
288
289 case ACPI_RESOURCE_TYPE_ADDRESS16:
290 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
291 "Address16 unimplemented\n"));
292 break;
293
294 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
295 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
296 "Extended address64 unimplemented\n"));
297 break;
298
299 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
300 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
301 "ExtendedIrq unimplemented\n"));
302 break;
303
304 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
305 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
306 "GenericRegister unimplemented\n"));
307 break;
308
309 case ACPI_RESOURCE_TYPE_VENDOR:
310 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
311 "VendorSpecific unimplemented\n"));
312 break;
313
314 default:
315 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
316 "Unknown resource type: %d\n", res->Type));
317 break;
318 }
319
320 return_ACPI_STATUS(AE_OK);
321 }
322
323
324 /*
325 * acpi_resource_parse:
326 *
327 * Parse a device node's resources and fill them in for the
328 * client.
329 *
330 * This API supports _CRS (current resources) and
331 * _PRS (possible resources).
332 *
333 * Note that it might be nice to also locate ACPI-specific resource
334 * items, such as GPE bits.
335 */
336 ACPI_STATUS
337 acpi_resource_parse(struct device *dev, ACPI_HANDLE handle, const char *path,
338 void *arg, const struct acpi_resource_parse_ops *ops)
339 {
340 struct resource_parse_callback_arg cbarg;
341 ACPI_STATUS rv;
342
343 ACPI_FUNCTION_TRACE(__FUNCTION__);
344
345 if (ops->init)
346 (*ops->init)(dev, arg, &cbarg.context);
347 else
348 cbarg.context = arg;
349 cbarg.ops = ops;
350 cbarg.dev = dev;
351
352 rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
353 &cbarg);
354 if (ACPI_FAILURE(rv)) {
355 aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n",
356 path, AcpiFormatException(rv));
357 return_ACPI_STATUS(rv);
358 }
359
360 if (ops->fini)
361 (*ops->fini)(dev, cbarg.context);
362
363 return_ACPI_STATUS(AE_OK);
364 }
365
366 /*
367 * acpi_resource_print:
368 *
369 * Print the resources assigned to a device.
370 */
371 void
372 acpi_resource_print(struct device *dev, struct acpi_resources *res)
373 {
374 const char *sep;
375
376 if (SIMPLEQ_EMPTY(&res->ar_io) &&
377 SIMPLEQ_EMPTY(&res->ar_iorange) &&
378 SIMPLEQ_EMPTY(&res->ar_mem) &&
379 SIMPLEQ_EMPTY(&res->ar_memrange) &&
380 SIMPLEQ_EMPTY(&res->ar_irq) &&
381 SIMPLEQ_EMPTY(&res->ar_drq))
382 return;
383
384 aprint_normal("%s:", dev->dv_xname);
385
386 if (SIMPLEQ_EMPTY(&res->ar_io) == 0) {
387 struct acpi_io *ar;
388
389 sep = "";
390 aprint_normal(" io ");
391 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
392 aprint_normal("%s0x%x", sep, ar->ar_base);
393 if (ar->ar_length > 1)
394 aprint_normal("-0x%x", ar->ar_base +
395 ar->ar_length - 1);
396 sep = ",";
397 }
398 }
399
400 /* XXX iorange */
401
402 if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) {
403 struct acpi_mem *ar;
404
405 sep = "";
406 aprint_normal(" mem ");
407 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
408 aprint_normal("%s0x%x", sep, ar->ar_base);
409 if (ar->ar_length > 1)
410 aprint_normal("-0x%x", ar->ar_base +
411 ar->ar_length - 1);
412 sep = ",";
413 }
414 }
415
416 /* XXX memrange */
417
418 if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) {
419 struct acpi_irq *ar;
420
421 sep = "";
422 aprint_normal(" irq ");
423 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
424 aprint_normal("%s%d", sep, ar->ar_irq);
425 sep = ",";
426 }
427 }
428
429 if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) {
430 struct acpi_drq *ar;
431
432 sep = "";
433 aprint_normal(" drq ");
434 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
435 aprint_normal("%s%d", sep, ar->ar_drq);
436 sep = ",";
437 }
438 }
439
440 aprint_normal("\n");
441 }
442
443 /*
444 * acpi_resource_cleanup:
445 *
446 * Free all allocated buffers
447 */
448 void
449 acpi_resource_cleanup(struct acpi_resources *res)
450 {
451 while (!SIMPLEQ_EMPTY(&res->ar_io)) {
452 struct acpi_io *ar;
453 ar = SIMPLEQ_FIRST(&res->ar_io);
454 SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list);
455 AcpiOsFree(ar);
456 }
457
458 while (!SIMPLEQ_EMPTY(&res->ar_iorange)) {
459 struct acpi_iorange *ar;
460 ar = SIMPLEQ_FIRST(&res->ar_iorange);
461 SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list);
462 AcpiOsFree(ar);
463 }
464
465 while (!SIMPLEQ_EMPTY(&res->ar_mem)) {
466 struct acpi_mem *ar;
467 ar = SIMPLEQ_FIRST(&res->ar_mem);
468 SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list);
469 AcpiOsFree(ar);
470 }
471
472 while (!SIMPLEQ_EMPTY(&res->ar_memrange)) {
473 struct acpi_memrange *ar;
474 ar = SIMPLEQ_FIRST(&res->ar_memrange);
475 SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list);
476 AcpiOsFree(ar);
477 }
478
479 while (!SIMPLEQ_EMPTY(&res->ar_irq)) {
480 struct acpi_irq *ar;
481 ar = SIMPLEQ_FIRST(&res->ar_irq);
482 SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list);
483 AcpiOsFree(ar);
484 }
485
486 while (!SIMPLEQ_EMPTY(&res->ar_drq)) {
487 struct acpi_drq *ar;
488 ar = SIMPLEQ_FIRST(&res->ar_drq);
489 SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list);
490 AcpiOsFree(ar);
491 }
492
493 res->ar_nio = res->ar_niorange = res->ar_nmem =
494 res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0;
495 }
496
497 struct acpi_io *
498 acpi_res_io(struct acpi_resources *res, int idx)
499 {
500 struct acpi_io *ar;
501
502 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
503 if (ar->ar_index == idx)
504 return ar;
505 }
506 return NULL;
507 }
508
509 struct acpi_iorange *
510 acpi_res_iorange(struct acpi_resources *res, int idx)
511 {
512 struct acpi_iorange *ar;
513
514 SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) {
515 if (ar->ar_index == idx)
516 return ar;
517 }
518 return NULL;
519 }
520
521 struct acpi_mem *
522 acpi_res_mem(struct acpi_resources *res, int idx)
523 {
524 struct acpi_mem *ar;
525
526 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
527 if (ar->ar_index == idx)
528 return ar;
529 }
530 return NULL;
531 }
532
533 struct acpi_memrange *
534 acpi_res_memrange(struct acpi_resources *res, int idx)
535 {
536 struct acpi_memrange *ar;
537
538 SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) {
539 if (ar->ar_index == idx)
540 return ar;
541 }
542 return NULL;
543 }
544
545 struct acpi_irq *
546 acpi_res_irq(struct acpi_resources *res, int idx)
547 {
548 struct acpi_irq *ar;
549
550 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
551 if (ar->ar_index == idx)
552 return ar;
553 }
554 return NULL;
555 }
556
557 struct acpi_drq *
558 acpi_res_drq(struct acpi_resources *res, int idx)
559 {
560 struct acpi_drq *ar;
561
562 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
563 if (ar->ar_index == idx)
564 return ar;
565 }
566 return NULL;
567 }
568
569 /*****************************************************************************
570 * Default ACPI resource parse operations.
571 *****************************************************************************/
572
573 static void acpi_res_parse_init(struct device *, void *, void **);
574 static void acpi_res_parse_fini(struct device *, void *);
575
576 static void acpi_res_parse_ioport(struct device *, void *, uint32_t,
577 uint32_t);
578 static void acpi_res_parse_iorange(struct device *, void *, uint32_t,
579 uint32_t, uint32_t, uint32_t);
580
581 static void acpi_res_parse_memory(struct device *, void *, uint32_t,
582 uint32_t);
583 static void acpi_res_parse_memrange(struct device *, void *, uint32_t,
584 uint32_t, uint32_t, uint32_t);
585
586 static void acpi_res_parse_irq(struct device *, void *, uint32_t, uint32_t);
587 static void acpi_res_parse_drq(struct device *, void *, uint32_t);
588
589 static void acpi_res_parse_start_dep(struct device *, void *, int);
590 static void acpi_res_parse_end_dep(struct device *, void *);
591
592 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = {
593 .init = acpi_res_parse_init,
594 .fini = acpi_res_parse_fini,
595
596 .ioport = acpi_res_parse_ioport,
597 .iorange = acpi_res_parse_iorange,
598
599 .memory = acpi_res_parse_memory,
600 .memrange = acpi_res_parse_memrange,
601
602 .irq = acpi_res_parse_irq,
603 .drq = acpi_res_parse_drq,
604
605 .start_dep = acpi_res_parse_start_dep,
606 .end_dep = acpi_res_parse_end_dep,
607 };
608
609 static void
610 acpi_res_parse_init(struct device *dev, void *arg, void **contextp)
611 {
612 struct acpi_resources *res = arg;
613
614 SIMPLEQ_INIT(&res->ar_io);
615 res->ar_nio = 0;
616
617 SIMPLEQ_INIT(&res->ar_iorange);
618 res->ar_niorange = 0;
619
620 SIMPLEQ_INIT(&res->ar_mem);
621 res->ar_nmem = 0;
622
623 SIMPLEQ_INIT(&res->ar_memrange);
624 res->ar_nmemrange = 0;
625
626 SIMPLEQ_INIT(&res->ar_irq);
627 res->ar_nirq = 0;
628
629 SIMPLEQ_INIT(&res->ar_drq);
630 res->ar_ndrq = 0;
631
632 *contextp = res;
633 }
634
635 static void
636 acpi_res_parse_fini(struct device *dev, void *context)
637 {
638 struct acpi_resources *res = context;
639
640 /* Print the resources we're using. */
641 acpi_resource_print(dev, res);
642 }
643
644 static void
645 acpi_res_parse_ioport(struct device *dev, void *context, uint32_t base,
646 uint32_t length)
647 {
648 struct acpi_resources *res = context;
649 struct acpi_io *ar;
650
651 /*
652 * Check if there is another I/O port directly below/under
653 * this one.
654 */
655 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
656 if (ar->ar_base == base + length ) {
657 /*
658 * Entry just below existing entry - adjust
659 * the entry and return.
660 */
661 ar->ar_base = base;
662 ar->ar_length += length;
663 return;
664 } else if (ar->ar_base + ar->ar_length == base) {
665 /*
666 * Entry just above existing entry - adjust
667 * the entry and return.
668 */
669 ar->ar_length += length;
670 return;
671 }
672 }
673
674 ar = AcpiOsAllocate(sizeof(*ar));
675 if (ar == NULL) {
676 aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n",
677 res->ar_nio);
678 res->ar_nio++;
679 return;
680 }
681
682 ar->ar_index = res->ar_nio++;
683 ar->ar_base = base;
684 ar->ar_length = length;
685
686 SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list);
687 }
688
689 static void
690 acpi_res_parse_iorange(struct device *dev, void *context, uint32_t low,
691 uint32_t high, uint32_t length, uint32_t align)
692 {
693 struct acpi_resources *res = context;
694 struct acpi_iorange *ar;
695
696 ar = AcpiOsAllocate(sizeof(*ar));
697 if (ar == NULL) {
698 aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n",
699 res->ar_niorange);
700 res->ar_niorange++;
701 return;
702 }
703
704 ar->ar_index = res->ar_niorange++;
705 ar->ar_low = low;
706 ar->ar_high = high;
707 ar->ar_length = length;
708 ar->ar_align = align;
709
710 SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list);
711 }
712
713 static void
714 acpi_res_parse_memory(struct device *dev, void *context, uint32_t base,
715 uint32_t length)
716 {
717 struct acpi_resources *res = context;
718 struct acpi_mem *ar;
719
720 ar = AcpiOsAllocate(sizeof(*ar));
721 if (ar == NULL) {
722 aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n",
723 res->ar_nmem);
724 res->ar_nmem++;
725 return;
726 }
727
728 ar->ar_index = res->ar_nmem++;
729 ar->ar_base = base;
730 ar->ar_length = length;
731
732 SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list);
733 }
734
735 static void
736 acpi_res_parse_memrange(struct device *dev, void *context, uint32_t low,
737 uint32_t high, uint32_t length, uint32_t align)
738 {
739 struct acpi_resources *res = context;
740 struct acpi_memrange *ar;
741
742 ar = AcpiOsAllocate(sizeof(*ar));
743 if (ar == NULL) {
744 aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n",
745 res->ar_nmemrange);
746 res->ar_nmemrange++;
747 return;
748 }
749
750 ar->ar_index = res->ar_nmemrange++;
751 ar->ar_low = low;
752 ar->ar_high = high;
753 ar->ar_length = length;
754 ar->ar_align = align;
755
756 SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list);
757 }
758
759 static void
760 acpi_res_parse_irq(struct device *dev, void *context, uint32_t irq, uint32_t type)
761 {
762 struct acpi_resources *res = context;
763 struct acpi_irq *ar;
764
765 ar = AcpiOsAllocate(sizeof(*ar));
766 if (ar == NULL) {
767 aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n",
768 res->ar_nirq);
769 res->ar_nirq++;
770 return;
771 }
772
773 ar->ar_index = res->ar_nirq++;
774 ar->ar_irq = irq;
775 ar->ar_type = type;
776
777 SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list);
778 }
779
780 static void
781 acpi_res_parse_drq(struct device *dev, void *context, uint32_t drq)
782 {
783 struct acpi_resources *res = context;
784 struct acpi_drq *ar;
785
786 ar = AcpiOsAllocate(sizeof(*ar));
787 if (ar == NULL) {
788 aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n",
789 res->ar_ndrq);
790 res->ar_ndrq++;
791 return;
792 }
793
794 ar->ar_index = res->ar_ndrq++;
795 ar->ar_drq = drq;
796
797 SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list);
798 }
799
800 static void
801 acpi_res_parse_start_dep(struct device *dev, void *context,
802 int preference)
803 {
804
805 aprint_error_dev(dev, "ACPI: dependant functions not supported\n");
806 }
807
808 static void
809 acpi_res_parse_end_dep(struct device *dev, void *context)
810 {
811
812 /* Nothing to do. */
813 }
814