Kernel - Fix NOTE_EXIT.
[dragonfly.git] / sys / dev / acpica5 / acpi_resource.c
blob5005198a3e5a59ad1d30eaaf07c8d0c93ad7fcd2
1 /*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
27 * $FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.25 2004/06/13 22:52:30 njl Exp $
28 * $DragonFly: src/sys/dev/acpica5/acpi_resource.c,v 1.9 2007/10/23 03:04:48 y0netan1 Exp $
31 #include "opt_acpi.h"
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/bus.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/rman.h>
39 #include "acpi.h"
40 #include "accommon.h"
41 #include <dev/acpica5/acpivar.h>
43 /* Hooks for the ACPI CA debugging infrastructure */
44 #define _COMPONENT ACPI_BUS
45 ACPI_MODULE_NAME("RESOURCE")
48 * Fetch a device's resources and associate them with the device.
50 * Note that it might be nice to also locate ACPI-specific resource items, such
51 * as GPE bits.
53 * We really need to split the resource-fetching code out from the
54 * resource-parsing code, since we may want to use the parsing
55 * code for _PRS someday.
57 ACPI_STATUS
58 acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
59 struct acpi_parse_resource_set *set, void *arg)
61 ACPI_BUFFER buf;
62 ACPI_RESOURCE *res;
63 char *curr, *last;
64 ACPI_STATUS status;
65 void *context;
67 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
70 * Special-case some devices that abuse _PRS/_CRS to mean
71 * something other than "I consume this resource".
73 * XXX do we really need this? It's only relevant once
74 * we start always-allocating these resources, and even
75 * then, the only special-cased device is likely to be
76 * the PCI interrupt link.
79 /* Fetch the device's current resources. */
80 buf.Length = ACPI_ALLOCATE_BUFFER;
81 if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
82 if (status != AE_NOT_FOUND && status != AE_TYPE)
83 kprintf("can't fetch resources for %s - %s\n",
84 acpi_name(handle), AcpiFormatException(status));
85 return_ACPI_STATUS (status);
87 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
88 acpi_name(handle), (long)buf.Length));
89 set->set_init(dev, arg, &context);
91 /* Iterate through the resources */
92 curr = buf.Pointer;
93 last = (char *)buf.Pointer + buf.Length;
94 while (curr < last) {
95 res = (ACPI_RESOURCE *)curr;
96 curr += res->Length;
98 /* Handle the individual resource types */
99 switch(res->Type) {
100 case ACPI_RESOURCE_TYPE_END_TAG:
101 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
102 curr = last;
103 break;
104 case ACPI_RESOURCE_TYPE_FIXED_IO:
105 if (res->Data.FixedIo.AddressLength <= 0)
106 break;
107 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
108 res->Data.FixedIo.Address,
109 res->Data.FixedIo.AddressLength));
110 set->set_ioport(dev, context,
111 res->Data.FixedIo.Address,
112 res->Data.FixedIo.AddressLength);
113 break;
114 case ACPI_RESOURCE_TYPE_IO:
115 if (res->Data.Io.AddressLength <= 0)
116 break;
117 if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
118 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
119 res->Data.Io.Minimum,
120 res->Data.Io.AddressLength));
121 set->set_ioport(dev, context,
122 res->Data.Io.Minimum,
123 res->Data.Io.AddressLength);
124 } else {
125 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
126 res->Data.Io.Minimum,
127 res->Data.Io.Maximum,
128 res->Data.Io.AddressLength));
129 set->set_iorange(dev, context,
130 res->Data.Io.Minimum,
131 res->Data.Io.Maximum,
132 res->Data.Io.AddressLength,
133 res->Data.Io.Alignment);
135 break;
136 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
137 if (res->Data.FixedMemory32.AddressLength <= 0)
138 break;
139 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
140 res->Data.FixedMemory32.Address,
141 res->Data.FixedMemory32.AddressLength));
142 set->set_memory(dev, context,
143 res->Data.FixedMemory32.Address,
144 res->Data.FixedMemory32.AddressLength);
145 break;
146 case ACPI_RESOURCE_TYPE_MEMORY32:
147 if (res->Data.Memory32.AddressLength <= 0)
148 break;
149 if (res->Data.Memory32.Minimum ==
150 res->Data.Memory32.Maximum) {
152 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
153 res->Data.Memory32.Minimum,
154 res->Data.Memory32.AddressLength));
155 set->set_memory(dev, context,
156 res->Data.Memory32.Minimum,
157 res->Data.Memory32.AddressLength);
158 } else {
159 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
160 res->Data.Memory32.Minimum,
161 res->Data.Memory32.Maximum,
162 res->Data.Memory32.AddressLength));
163 set->set_memoryrange(dev, context,
164 res->Data.Memory32.Minimum,
165 res->Data.Memory32.Maximum,
166 res->Data.Memory32.AddressLength,
167 res->Data.Memory32.Alignment);
169 break;
170 case ACPI_RESOURCE_TYPE_MEMORY24:
171 if (res->Data.Memory24.AddressLength <= 0)
172 break;
173 if (res->Data.Memory24.Minimum ==
174 res->Data.Memory24.Maximum) {
176 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
177 res->Data.Memory24.Minimum,
178 res->Data.Memory24.AddressLength));
179 set->set_memory(dev, context, res->Data.Memory24.Minimum,
180 res->Data.Memory24.AddressLength);
181 } else {
182 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
183 res->Data.Memory24.Minimum,
184 res->Data.Memory24.Maximum,
185 res->Data.Memory24.AddressLength));
186 set->set_memoryrange(dev, context,
187 res->Data.Memory24.Minimum,
188 res->Data.Memory24.Maximum,
189 res->Data.Memory24.AddressLength,
190 res->Data.Memory24.Alignment);
192 break;
193 case ACPI_RESOURCE_TYPE_IRQ:
195 * from 1.0b 6.4.2
196 * "This structure is repeated for each separate interrupt
197 * required"
199 set->set_irq(dev, context, res->Data.Irq.Interrupts,
200 res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
201 res->Data.Irq.Polarity);
202 break;
203 case ACPI_RESOURCE_TYPE_DMA:
205 * from 1.0b 6.4.3
206 * "This structure is repeated for each separate dma channel
207 * required"
209 set->set_drq(dev, context, res->Data.Dma.Channels,
210 res->Data.Dma.ChannelCount);
211 break;
212 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
213 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
214 set->set_start_dependant(dev, context,
215 res->Data.StartDpf.CompatibilityPriority);
216 break;
217 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
218 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
219 set->set_end_dependant(dev, context);
220 break;
221 case ACPI_RESOURCE_TYPE_ADDRESS32:
222 if (res->Data.Address32.AddressLength <= 0)
223 break;
224 if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
225 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
226 "ignored Address32 %s producer\n",
227 res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
228 "IO" : "Memory"));
229 break;
231 if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
232 res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
233 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
234 "ignored Address32 for non-memory, non-I/O\n"));
235 break;
238 if (res->Data.Address32.Minimum == ACPI_ADDRESS_FIXED &&
239 res->Data.Address32.Maximum == ACPI_ADDRESS_FIXED) {
241 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
242 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
243 "Address32/Memory 0x%x/%d\n",
244 res->Data.Address32.Minimum,
245 res->Data.Address32.AddressLength));
246 set->set_memory(dev, context,
247 res->Data.Address32.Minimum,
248 res->Data.Address32.AddressLength);
249 } else {
250 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
251 "Address32/IO 0x%x/%d\n",
252 res->Data.Address32.Minimum,
253 res->Data.Address32.AddressLength));
254 set->set_ioport(dev, context,
255 res->Data.Address32.Minimum,
256 res->Data.Address32.AddressLength);
258 } else {
259 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
260 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
261 "Address32/Memory 0x%x-0x%x/%d\n",
262 res->Data.Address32.Minimum,
263 res->Data.Address32.Maximum,
264 res->Data.Address32.AddressLength));
265 set->set_memoryrange(dev, context,
266 res->Data.Address32.Minimum,
267 res->Data.Address32.Maximum,
268 res->Data.Address32.AddressLength,
269 res->Data.Address32.Granularity);
270 } else {
271 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
272 "Address32/IO 0x%x-0x%x/%d\n",
273 res->Data.Address32.Minimum,
274 res->Data.Address32.Maximum,
275 res->Data.Address32.AddressLength));
276 set->set_iorange(dev, context,
277 res->Data.Address32.Minimum,
278 res->Data.Address32.Maximum,
279 res->Data.Address32.AddressLength,
280 res->Data.Address32.Granularity);
283 break;
284 case ACPI_RESOURCE_TYPE_ADDRESS16:
285 if (res->Data.Address16.AddressLength <= 0)
286 break;
287 if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
288 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
289 "ignored Address16 %s producer\n",
290 res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
291 "IO" : "Memory"));
292 break;
294 if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
295 res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
296 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
297 "ignored Address16 for non-memory, non-I/O\n"));
298 break;
301 if (res->Data.Address16.Minimum == ACPI_ADDRESS_FIXED &&
302 res->Data.Address16.Maximum == ACPI_ADDRESS_FIXED) {
304 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
305 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
306 "Address16/Memory 0x%x/%d\n",
307 res->Data.Address16.Minimum,
308 res->Data.Address16.AddressLength));
309 set->set_memory(dev, context,
310 res->Data.Address16.Minimum,
311 res->Data.Address16.AddressLength);
312 } else {
313 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
314 "Address16/IO 0x%x/%d\n",
315 res->Data.Address16.Minimum,
316 res->Data.Address16.AddressLength));
317 set->set_ioport(dev, context,
318 res->Data.Address16.Minimum,
319 res->Data.Address16.AddressLength);
321 } else {
322 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
323 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
324 "Address16/Memory 0x%x-0x%x/%d\n",
325 res->Data.Address16.Minimum,
326 res->Data.Address16.Maximum,
327 res->Data.Address16.AddressLength));
328 set->set_memoryrange(dev, context,
329 res->Data.Address16.Minimum,
330 res->Data.Address16.Maximum,
331 res->Data.Address16.AddressLength,
332 res->Data.Address16.Granularity);
333 } else {
334 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
335 "Address16/IO 0x%x-0x%x/%d\n",
336 res->Data.Address16.Minimum,
337 res->Data.Address16.Maximum,
338 res->Data.Address16.AddressLength));
339 set->set_iorange(dev, context,
340 res->Data.Address16.Minimum,
341 res->Data.Address16.Maximum,
342 res->Data.Address16.AddressLength,
343 res->Data.Address16.Granularity);
346 break;
347 case ACPI_RESOURCE_TYPE_ADDRESS64:
348 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
349 "unimplemented Address64 resource\n"));
350 break;
351 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
352 /* XXX special handling? */
353 set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
354 res->Data.ExtendedIrq.InterruptCount,
355 res->Data.ExtendedIrq.Triggering,
356 res->Data.ExtendedIrq.Polarity);
357 break;
358 case ACPI_RESOURCE_TYPE_VENDOR:
359 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
360 "unimplemented VendorSpecific resource\n"));
361 break;
362 default:
363 break;
367 AcpiOsFree(buf.Pointer);
368 set->set_done(dev, context);
369 return_ACPI_STATUS (AE_OK);
373 * Resource-set vectors used to attach _CRS-derived resources
374 * to an ACPI device.
376 static void acpi_res_set_init(device_t dev, void *arg, void **context);
377 static void acpi_res_set_done(device_t dev, void *context);
378 static void acpi_res_set_ioport(device_t dev, void *context,
379 u_int32_t base, u_int32_t length);
380 static void acpi_res_set_iorange(device_t dev, void *context,
381 u_int32_t low, u_int32_t high,
382 u_int32_t length, u_int32_t align);
383 static void acpi_res_set_memory(device_t dev, void *context,
384 u_int32_t base, u_int32_t length);
385 static void acpi_res_set_memoryrange(device_t dev, void *context,
386 u_int32_t low, u_int32_t high,
387 u_int32_t length, u_int32_t align);
388 static void acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq,
389 int count, int trig, int pol);
390 static void acpi_res_set_ext_irq(device_t dev, void *context,
391 u_int32_t *irq, int count, int trig,
392 int pol);
393 static void acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq,
394 int count);
395 static void acpi_res_set_start_dependant(device_t dev, void *context,
396 int preference);
397 static void acpi_res_set_end_dependant(device_t dev, void *context);
399 struct acpi_parse_resource_set acpi_res_parse_set = {
400 acpi_res_set_init,
401 acpi_res_set_done,
402 acpi_res_set_ioport,
403 acpi_res_set_iorange,
404 acpi_res_set_memory,
405 acpi_res_set_memoryrange,
406 acpi_res_set_irq,
407 acpi_res_set_ext_irq,
408 acpi_res_set_drq,
409 acpi_res_set_start_dependant,
410 acpi_res_set_end_dependant
413 struct acpi_res_context {
414 int ar_nio;
415 int ar_nmem;
416 int ar_nirq;
417 int ar_ndrq;
418 void *ar_parent;
421 static void
422 acpi_res_set_init(device_t dev, void *arg, void **context)
424 struct acpi_res_context *cp;
426 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
427 bzero(cp, sizeof(*cp));
428 cp->ar_parent = arg;
429 *context = cp;
433 static void
434 acpi_res_set_done(device_t dev, void *context)
436 struct acpi_res_context *cp = (struct acpi_res_context *)context;
438 if (cp == NULL)
439 return;
440 AcpiOsFree(cp);
443 static void
444 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
445 u_int32_t length)
447 struct acpi_res_context *cp = (struct acpi_res_context *)context;
449 if (cp == NULL)
450 return;
451 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
454 static void
455 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
456 u_int32_t high, u_int32_t length, u_int32_t align)
458 struct acpi_res_context *cp = (struct acpi_res_context *)context;
460 if (cp == NULL)
461 return;
462 device_printf(dev, "I/O range not supported\n");
465 static void
466 acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
467 u_int32_t length)
469 struct acpi_res_context *cp = (struct acpi_res_context *)context;
471 if (cp == NULL)
472 return;
474 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
477 static void
478 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
479 u_int32_t high, u_int32_t length, u_int32_t align)
481 struct acpi_res_context *cp = (struct acpi_res_context *)context;
483 if (cp == NULL)
484 return;
485 device_printf(dev, "memory range not supported\n");
488 static void
489 acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count,
490 int trig, int pol)
492 struct acpi_res_context *cp = (struct acpi_res_context *)context;
494 if (cp == NULL || irq == NULL)
495 return;
497 /* This implements no resource relocation. */
498 if (count != 1)
499 return;
501 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
502 #if 0 /* From FreeBSD-5 XXX */
503 BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
504 INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
505 INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
506 #endif
509 static void
510 acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count,
511 int trig, int pol)
513 struct acpi_res_context *cp = (struct acpi_res_context *)context;
515 if (cp == NULL || irq == NULL)
516 return;
518 /* This implements no resource relocation. */
519 if (count != 1)
520 return;
522 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
523 #if 0 /* From FreeBSD-5 XXX */
524 BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
525 INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
526 INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
527 #endif
530 static void
531 acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count)
533 struct acpi_res_context *cp = (struct acpi_res_context *)context;
535 if (cp == NULL || drq == NULL)
536 return;
538 /* This implements no resource relocation. */
539 if (count != 1)
540 return;
542 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
545 static void
546 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
548 struct acpi_res_context *cp = (struct acpi_res_context *)context;
550 if (cp == NULL)
551 return;
552 device_printf(dev, "dependent functions not supported\n");
555 static void
556 acpi_res_set_end_dependant(device_t dev, void *context)
558 struct acpi_res_context *cp = (struct acpi_res_context *)context;
560 if (cp == NULL)
561 return;
562 device_printf(dev, "dependent functions not supported\n");
566 * Resource-owning placeholders for IO and memory pseudo-devices.
568 * This code allocates system resource objects that will be owned by ACPI
569 * child devices. Really, the acpi parent device should have the resources
570 * but this would significantly affect the device probe code.
573 static int acpi_sysres_probe(device_t dev);
574 static int acpi_sysres_attach(device_t dev);
576 static device_method_t acpi_sysres_methods[] = {
577 /* Device interface */
578 DEVMETHOD(device_probe, acpi_sysres_probe),
579 DEVMETHOD(device_attach, acpi_sysres_attach),
581 {0, 0}
584 static driver_t acpi_sysres_driver = {
585 "acpi_sysresource",
586 acpi_sysres_methods,
590 static devclass_t acpi_sysres_devclass;
591 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, acpi_sysres_devclass,
592 0, 0);
593 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
595 static int
596 acpi_sysres_probe(device_t dev)
598 ACPI_HANDLE h;
600 h = acpi_get_handle(dev);
601 if (acpi_disabled("sysresource") ||
602 (!acpi_MatchHid(h, "PNP0C01") && !acpi_MatchHid(h, "PNP0C02")))
603 return (ENXIO);
605 device_set_desc(dev, "System Resource");
606 device_quiet(dev);
607 return (-100);
610 static int
611 acpi_sysres_attach(device_t dev)
613 device_t gparent;
614 struct resource *res;
615 struct rman *rm;
616 struct resource_list_entry *rle;
617 struct resource_list *rl;
620 * Pre-allocate/manage all memory and IO resources. We detect duplicates
621 * by setting rle->res to the resource we got from the parent. We can't
622 * ignore them since rman can't handle duplicates.
624 rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
625 SLIST_FOREACH(rle, rl, link) {
626 if (rle->res != NULL) {
627 device_printf(dev, "duplicate resource for %lx\n", rle->start);
628 continue;
631 /* Only memory and IO resources are valid here. */
632 switch (rle->type) {
633 case SYS_RES_IOPORT:
634 rm = &acpi_rman_io;
635 break;
636 case SYS_RES_MEMORY:
637 rm = &acpi_rman_mem;
638 break;
639 default:
640 continue;
643 /* Pre-allocate resource and add to our rman pool. */
644 gparent = device_get_parent(device_get_parent(dev));
645 res = BUS_ALLOC_RESOURCE(gparent, dev, rle->type, &rle->rid,
646 rle->start, rle->start + rle->count - 1, rle->count, 0);
647 if (res != NULL) {
648 rman_manage_region(rm, rman_get_start(res), rman_get_end(res));
649 rle->res = res;
653 return (0);
656 struct resource_list_entry *
657 acpi_sysres_find(int type, u_long addr)
659 device_t *devs;
660 int i, numdevs;
661 struct resource_list *rl;
662 struct resource_list_entry *rle;
664 /* We only consider IO and memory resources for our pool. */
665 rle = NULL;
666 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
667 return (rle);
669 /* Find all the sysresource devices. */
670 if (devclass_get_devices(acpi_sysres_devclass, &devs, &numdevs) != 0)
671 return (rle);
673 /* Check each device for a resource that contains "addr". */
674 for (i = 0; i < numdevs && rle == NULL; i++) {
675 rl = BUS_GET_RESOURCE_LIST(device_get_parent(devs[i]), devs[i]);
676 if (rl == NULL)
677 continue;
678 SLIST_FOREACH(rle, rl, link) {
679 if (type == rle->type && addr >= rle->start &&
680 addr < rle->start + rle->count)
681 break;
685 kfree(devs, M_TEMP);
686 return (rle);