2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
26 * __FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.40.8.1 2009/04/15 03:14:26 kensmith Exp $");
29 #include <sys/cdefs.h>
32 #include <sys/param.h>
33 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/resource.h>
42 #include <dev/acpica5/acpivar.h>
44 /* Hooks for the ACPI CA debugging infrastructure */
45 #define _COMPONENT ACPI_BUS
46 ACPI_MODULE_NAME("RESOURCE")
48 struct lookup_irq_request
{
49 ACPI_RESOURCE
*acpi_res
;
57 acpi_lookup_irq_handler(ACPI_RESOURCE
*res
, void *context
)
59 struct lookup_irq_request
*req
;
63 case ACPI_RESOURCE_TYPE_IRQ
:
64 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
65 if (res
->Type
== ACPI_RESOURCE_TYPE_IRQ
) {
66 irqnum
= res
->Data
.Irq
.InterruptCount
;
67 irq
= res
->Data
.Irq
.Interrupts
[0];
69 irqnum
= res
->Data
.ExtendedIrq
.InterruptCount
;
70 irq
= res
->Data
.ExtendedIrq
.Interrupts
[0];
74 req
= (struct lookup_irq_request
*)context
;
75 if (req
->counter
!= req
->rid
) {
80 KASSERT(irq
== rman_get_start(req
->res
),
81 ("IRQ resources do not match"));
82 bcopy(res
, req
->acpi_res
, sizeof(ACPI_RESOURCE
));
83 return (AE_CTRL_TERMINATE
);
89 acpi_lookup_irq_resource(device_t dev
, int rid
, struct resource
*res
,
90 ACPI_RESOURCE
*acpi_res
)
92 struct lookup_irq_request req
;
95 req
.acpi_res
= acpi_res
;
100 status
= AcpiWalkResources(acpi_get_handle(dev
), "_CRS",
101 acpi_lookup_irq_handler
, &req
);
102 if (ACPI_SUCCESS(status
) && req
.found
== 0)
103 status
= AE_NOT_FOUND
;
108 acpi_config_intr(device_t dev
, ACPI_RESOURCE
*res
)
113 case ACPI_RESOURCE_TYPE_IRQ
:
114 KASSERT(res
->Data
.Irq
.InterruptCount
== 1,
115 ("%s: multiple interrupts", __func__
));
116 irq
= res
->Data
.Irq
.Interrupts
[0];
117 trig
= res
->Data
.Irq
.Triggering
;
118 pol
= res
->Data
.Irq
.Polarity
;
120 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
121 KASSERT(res
->Data
.ExtendedIrq
.InterruptCount
== 1,
122 ("%s: multiple interrupts", __func__
));
123 irq
= res
->Data
.ExtendedIrq
.Interrupts
[0];
124 trig
= res
->Data
.ExtendedIrq
.Triggering
;
125 pol
= res
->Data
.ExtendedIrq
.Polarity
;
128 panic("%s: bad resource type %u", __func__
, res
->Type
);
130 BUS_CONFIG_INTR(dev
, dev
, irq
, (trig
== ACPI_EDGE_SENSITIVE
) ?
131 INTR_TRIGGER_EDGE
: INTR_TRIGGER_LEVEL
, (pol
== ACPI_ACTIVE_HIGH
) ?
132 INTR_POLARITY_HIGH
: INTR_POLARITY_LOW
);
136 * Fetch a device's resources and associate them with the device.
138 * Note that it might be nice to also locate ACPI-specific resource items, such
141 * We really need to split the resource-fetching code out from the
142 * resource-parsing code, since we may want to use the parsing
143 * code for _PRS someday.
146 acpi_parse_resources(device_t dev
, ACPI_HANDLE handle
,
147 struct acpi_parse_resource_set
*set
, void *arg
)
155 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__
);
158 * Special-case some devices that abuse _PRS/_CRS to mean
159 * something other than "I consume this resource".
161 * XXX do we really need this? It's only relevant once
162 * we start always-allocating these resources, and even
163 * then, the only special-cased device is likely to be
164 * the PCI interrupt link.
167 /* Fetch the device's current resources. */
168 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
169 if (ACPI_FAILURE((status
= AcpiGetCurrentResources(handle
, &buf
)))) {
170 if (status
!= AE_NOT_FOUND
&& status
!= AE_TYPE
)
171 kprintf("can't fetch resources for %s - %s\n",
172 acpi_name(handle
), AcpiFormatException(status
));
173 return_ACPI_STATUS (status
);
175 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "%s - got %ld bytes of resources\n",
176 acpi_name(handle
), (long)buf
.Length
));
177 set
->set_init(dev
, arg
, &context
);
179 /* Iterate through the resources */
181 last
= (char *)buf
.Pointer
+ buf
.Length
;
182 while (curr
< last
) {
183 res
= (ACPI_RESOURCE
*)curr
;
186 /* Handle the individual resource types */
188 case ACPI_RESOURCE_TYPE_END_TAG
:
189 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "EndTag\n"));
192 case ACPI_RESOURCE_TYPE_FIXED_IO
:
193 if (res
->Data
.FixedIo
.AddressLength
<= 0)
195 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "FixedIo 0x%x/%d\n",
196 res
->Data
.FixedIo
.Address
,
197 res
->Data
.FixedIo
.AddressLength
));
198 set
->set_ioport(dev
, context
,
199 res
->Data
.FixedIo
.Address
,
200 res
->Data
.FixedIo
.AddressLength
);
202 case ACPI_RESOURCE_TYPE_IO
:
203 if (res
->Data
.Io
.AddressLength
<= 0)
205 if (res
->Data
.Io
.Minimum
== res
->Data
.Io
.Maximum
) {
206 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "Io 0x%x/%d\n",
207 res
->Data
.Io
.Minimum
,
208 res
->Data
.Io
.AddressLength
));
209 set
->set_ioport(dev
, context
,
210 res
->Data
.Io
.Minimum
,
211 res
->Data
.Io
.AddressLength
);
213 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "Io 0x%x-0x%x/%d\n",
214 res
->Data
.Io
.Minimum
,
215 res
->Data
.Io
.Maximum
,
216 res
->Data
.Io
.AddressLength
));
217 set
->set_iorange(dev
, context
,
218 res
->Data
.Io
.Minimum
,
219 res
->Data
.Io
.Maximum
,
220 res
->Data
.Io
.AddressLength
,
221 res
->Data
.Io
.Alignment
);
224 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32
:
225 if (res
->Data
.FixedMemory32
.AddressLength
<= 0)
227 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "FixedMemory32 0x%x/%d\n",
228 res
->Data
.FixedMemory32
.Address
,
229 res
->Data
.FixedMemory32
.AddressLength
));
230 set
->set_memory(dev
, context
,
231 res
->Data
.FixedMemory32
.Address
,
232 res
->Data
.FixedMemory32
.AddressLength
);
234 case ACPI_RESOURCE_TYPE_MEMORY32
:
235 if (res
->Data
.Memory32
.AddressLength
<= 0)
237 if (res
->Data
.Memory32
.Minimum
==
238 res
->Data
.Memory32
.Maximum
) {
240 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "Memory32 0x%x/%d\n",
241 res
->Data
.Memory32
.Minimum
,
242 res
->Data
.Memory32
.AddressLength
));
243 set
->set_memory(dev
, context
,
244 res
->Data
.Memory32
.Minimum
,
245 res
->Data
.Memory32
.AddressLength
);
247 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "Memory32 0x%x-0x%x/%d\n",
248 res
->Data
.Memory32
.Minimum
,
249 res
->Data
.Memory32
.Maximum
,
250 res
->Data
.Memory32
.AddressLength
));
251 set
->set_memoryrange(dev
, context
,
252 res
->Data
.Memory32
.Minimum
,
253 res
->Data
.Memory32
.Maximum
,
254 res
->Data
.Memory32
.AddressLength
,
255 res
->Data
.Memory32
.Alignment
);
258 case ACPI_RESOURCE_TYPE_MEMORY24
:
259 if (res
->Data
.Memory24
.AddressLength
<= 0)
261 if (res
->Data
.Memory24
.Minimum
==
262 res
->Data
.Memory24
.Maximum
) {
264 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "Memory24 0x%x/%d\n",
265 res
->Data
.Memory24
.Minimum
,
266 res
->Data
.Memory24
.AddressLength
));
267 set
->set_memory(dev
, context
, res
->Data
.Memory24
.Minimum
,
268 res
->Data
.Memory24
.AddressLength
);
270 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "Memory24 0x%x-0x%x/%d\n",
271 res
->Data
.Memory24
.Minimum
,
272 res
->Data
.Memory24
.Maximum
,
273 res
->Data
.Memory24
.AddressLength
));
274 set
->set_memoryrange(dev
, context
,
275 res
->Data
.Memory24
.Minimum
,
276 res
->Data
.Memory24
.Maximum
,
277 res
->Data
.Memory24
.AddressLength
,
278 res
->Data
.Memory24
.Alignment
);
281 case ACPI_RESOURCE_TYPE_IRQ
:
284 * "This structure is repeated for each separate interrupt
287 set
->set_irq(dev
, context
, res
->Data
.Irq
.Interrupts
,
288 res
->Data
.Irq
.InterruptCount
, res
->Data
.Irq
.Triggering
,
289 res
->Data
.Irq
.Polarity
);
291 case ACPI_RESOURCE_TYPE_DMA
:
294 * "This structure is repeated for each separate dma channel
297 set
->set_drq(dev
, context
, res
->Data
.Dma
.Channels
,
298 res
->Data
.Dma
.ChannelCount
);
300 case ACPI_RESOURCE_TYPE_START_DEPENDENT
:
301 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "start dependent functions\n"));
302 set
->set_start_dependent(dev
, context
,
303 res
->Data
.StartDpf
.CompatibilityPriority
);
305 case ACPI_RESOURCE_TYPE_END_DEPENDENT
:
306 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
, "end dependent functions\n"));
307 set
->set_end_dependent(dev
, context
);
309 case ACPI_RESOURCE_TYPE_ADDRESS32
:
310 if (res
->Data
.Address32
.AddressLength
<= 0)
312 if (res
->Data
.Address32
.ProducerConsumer
!= ACPI_CONSUMER
) {
313 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
314 "ignored Address32 %s producer\n",
315 res
->Data
.Address32
.ResourceType
== ACPI_IO_RANGE
?
319 if (res
->Data
.Address32
.ResourceType
!= ACPI_MEMORY_RANGE
&&
320 res
->Data
.Address32
.ResourceType
!= ACPI_IO_RANGE
) {
321 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
322 "ignored Address32 for non-memory, non-I/O\n"));
326 if (res
->Data
.Address32
.MinAddressFixed
== ACPI_ADDRESS_FIXED
&&
327 res
->Data
.Address32
.MaxAddressFixed
== ACPI_ADDRESS_FIXED
) {
329 if (res
->Data
.Address32
.ResourceType
== ACPI_MEMORY_RANGE
) {
330 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
331 "Address32/Memory 0x%x/%d\n",
332 res
->Data
.Address32
.Minimum
,
333 res
->Data
.Address32
.AddressLength
));
334 set
->set_memory(dev
, context
,
335 res
->Data
.Address32
.Minimum
,
336 res
->Data
.Address32
.AddressLength
);
338 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
339 "Address32/IO 0x%x/%d\n",
340 res
->Data
.Address32
.Minimum
,
341 res
->Data
.Address32
.AddressLength
));
342 set
->set_ioport(dev
, context
,
343 res
->Data
.Address32
.Minimum
,
344 res
->Data
.Address32
.AddressLength
);
347 if (res
->Data
.Address32
.ResourceType
== ACPI_MEMORY_RANGE
) {
348 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
349 "Address32/Memory 0x%x-0x%x/%d\n",
350 res
->Data
.Address32
.Minimum
,
351 res
->Data
.Address32
.Maximum
,
352 res
->Data
.Address32
.AddressLength
));
353 set
->set_memoryrange(dev
, context
,
354 res
->Data
.Address32
.Minimum
,
355 res
->Data
.Address32
.Maximum
,
356 res
->Data
.Address32
.AddressLength
,
357 res
->Data
.Address32
.Granularity
);
359 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
360 "Address32/IO 0x%x-0x%x/%d\n",
361 res
->Data
.Address32
.Minimum
,
362 res
->Data
.Address32
.Maximum
,
363 res
->Data
.Address32
.AddressLength
));
364 set
->set_iorange(dev
, context
,
365 res
->Data
.Address32
.Minimum
,
366 res
->Data
.Address32
.Maximum
,
367 res
->Data
.Address32
.AddressLength
,
368 res
->Data
.Address32
.Granularity
);
372 case ACPI_RESOURCE_TYPE_ADDRESS16
:
373 if (res
->Data
.Address16
.AddressLength
<= 0)
375 if (res
->Data
.Address16
.ProducerConsumer
!= ACPI_CONSUMER
) {
376 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
377 "ignored Address16 %s producer\n",
378 res
->Data
.Address16
.ResourceType
== ACPI_IO_RANGE
?
382 if (res
->Data
.Address16
.ResourceType
!= ACPI_MEMORY_RANGE
&&
383 res
->Data
.Address16
.ResourceType
!= ACPI_IO_RANGE
) {
384 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
385 "ignored Address16 for non-memory, non-I/O\n"));
389 if (res
->Data
.Address16
.MinAddressFixed
== ACPI_ADDRESS_FIXED
&&
390 res
->Data
.Address16
.MaxAddressFixed
== ACPI_ADDRESS_FIXED
) {
392 if (res
->Data
.Address16
.ResourceType
== ACPI_MEMORY_RANGE
) {
393 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
394 "Address16/Memory 0x%x/%d\n",
395 res
->Data
.Address16
.Minimum
,
396 res
->Data
.Address16
.AddressLength
));
397 set
->set_memory(dev
, context
,
398 res
->Data
.Address16
.Minimum
,
399 res
->Data
.Address16
.AddressLength
);
401 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
402 "Address16/IO 0x%x/%d\n",
403 res
->Data
.Address16
.Minimum
,
404 res
->Data
.Address16
.AddressLength
));
405 set
->set_ioport(dev
, context
,
406 res
->Data
.Address16
.Minimum
,
407 res
->Data
.Address16
.AddressLength
);
410 if (res
->Data
.Address16
.ResourceType
== ACPI_MEMORY_RANGE
) {
411 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
412 "Address16/Memory 0x%x-0x%x/%d\n",
413 res
->Data
.Address16
.Minimum
,
414 res
->Data
.Address16
.Maximum
,
415 res
->Data
.Address16
.AddressLength
));
416 set
->set_memoryrange(dev
, context
,
417 res
->Data
.Address16
.Minimum
,
418 res
->Data
.Address16
.Maximum
,
419 res
->Data
.Address16
.AddressLength
,
420 res
->Data
.Address16
.Granularity
);
422 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
423 "Address16/IO 0x%x-0x%x/%d\n",
424 res
->Data
.Address16
.Minimum
,
425 res
->Data
.Address16
.Maximum
,
426 res
->Data
.Address16
.AddressLength
));
427 set
->set_iorange(dev
, context
,
428 res
->Data
.Address16
.Minimum
,
429 res
->Data
.Address16
.Maximum
,
430 res
->Data
.Address16
.AddressLength
,
431 res
->Data
.Address16
.Granularity
);
435 case ACPI_RESOURCE_TYPE_ADDRESS64
:
436 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
437 "unimplemented Address64 resource\n"));
439 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
440 if (res
->Data
.ExtendedIrq
.ProducerConsumer
!= ACPI_CONSUMER
) {
441 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
442 "ignored ExtIRQ producer\n"));
445 set
->set_ext_irq(dev
, context
, res
->Data
.ExtendedIrq
.Interrupts
,
446 res
->Data
.ExtendedIrq
.InterruptCount
,
447 res
->Data
.ExtendedIrq
.Triggering
,
448 res
->Data
.ExtendedIrq
.Polarity
);
450 case ACPI_RESOURCE_TYPE_VENDOR
:
451 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES
,
452 "unimplemented VendorSpecific resource\n"));
459 AcpiOsFree(buf
.Pointer
);
460 set
->set_done(dev
, context
);
461 return_ACPI_STATUS (AE_OK
);
465 * Resource-set vectors used to attach _CRS-derived resources
468 static void acpi_res_set_init(device_t dev
, void *arg
, void **context
);
469 static void acpi_res_set_done(device_t dev
, void *context
);
470 static void acpi_res_set_ioport(device_t dev
, void *context
,
471 u_int32_t base
, u_int32_t length
);
472 static void acpi_res_set_iorange(device_t dev
, void *context
,
473 u_int32_t low
, u_int32_t high
,
474 u_int32_t length
, u_int32_t align
);
475 static void acpi_res_set_memory(device_t dev
, void *context
,
476 u_int32_t base
, u_int32_t length
);
477 static void acpi_res_set_memoryrange(device_t dev
, void *context
,
478 u_int32_t low
, u_int32_t high
,
479 u_int32_t length
, u_int32_t align
);
480 static void acpi_res_set_irq(device_t dev
, void *context
, u_int8_t
*irq
,
481 int count
, int trig
, int pol
);
482 static void acpi_res_set_ext_irq(device_t dev
, void *context
,
483 u_int32_t
*irq
, int count
, int trig
, int pol
);
484 static void acpi_res_set_drq(device_t dev
, void *context
, u_int8_t
*drq
,
486 static void acpi_res_set_start_dependent(device_t dev
, void *context
,
488 static void acpi_res_set_end_dependent(device_t dev
, void *context
);
490 struct acpi_parse_resource_set acpi_res_parse_set
= {
494 acpi_res_set_iorange
,
496 acpi_res_set_memoryrange
,
498 acpi_res_set_ext_irq
,
500 acpi_res_set_start_dependent
,
501 acpi_res_set_end_dependent
504 struct acpi_res_context
{
513 acpi_res_set_init(device_t dev
, void *arg
, void **context
)
515 struct acpi_res_context
*cp
;
517 if ((cp
= AcpiOsAllocate(sizeof(*cp
))) != NULL
) {
518 bzero(cp
, sizeof(*cp
));
525 acpi_res_set_done(device_t dev
, void *context
)
527 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
535 acpi_res_set_ioport(device_t dev
, void *context
, u_int32_t base
,
538 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
542 bus_set_resource(dev
, SYS_RES_IOPORT
, cp
->ar_nio
++, base
, length
);
546 acpi_res_set_iorange(device_t dev
, void *context
, u_int32_t low
,
547 u_int32_t high
, u_int32_t length
, u_int32_t align
)
549 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
553 device_printf(dev
, "I/O range not supported\n");
557 acpi_res_set_memory(device_t dev
, void *context
, u_int32_t base
,
560 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
565 bus_set_resource(dev
, SYS_RES_MEMORY
, cp
->ar_nmem
++, base
, length
);
569 acpi_res_set_memoryrange(device_t dev
, void *context
, u_int32_t low
,
570 u_int32_t high
, u_int32_t length
, u_int32_t align
)
572 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
576 device_printf(dev
, "memory range not supported\n");
580 acpi_res_set_irq(device_t dev
, void *context
, u_int8_t
*irq
, int count
,
583 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
585 if (cp
== NULL
|| irq
== NULL
)
588 /* This implements no resource relocation. */
592 bus_set_resource(dev
, SYS_RES_IRQ
, cp
->ar_nirq
++, *irq
, 1);
596 acpi_res_set_ext_irq(device_t dev
, void *context
, u_int32_t
*irq
, int count
,
599 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
601 if (cp
== NULL
|| irq
== NULL
)
604 /* This implements no resource relocation. */
608 bus_set_resource(dev
, SYS_RES_IRQ
, cp
->ar_nirq
++, *irq
, 1);
612 acpi_res_set_drq(device_t dev
, void *context
, u_int8_t
*drq
, int count
)
614 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
616 if (cp
== NULL
|| drq
== NULL
)
619 /* This implements no resource relocation. */
623 bus_set_resource(dev
, SYS_RES_DRQ
, cp
->ar_ndrq
++, *drq
, 1);
627 acpi_res_set_start_dependent(device_t dev
, void *context
, int preference
)
629 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
633 device_printf(dev
, "dependent functions not supported\n");
637 acpi_res_set_end_dependent(device_t dev
, void *context
)
639 struct acpi_res_context
*cp
= (struct acpi_res_context
*)context
;
643 device_printf(dev
, "dependent functions not supported\n");
647 * Resource-owning placeholders for IO and memory pseudo-devices.
649 * This code allocates system resources that will be used by ACPI
650 * child devices. The acpi parent manages these resources through a
654 static int acpi_sysres_rid
= 100;
656 static int acpi_sysres_probe(device_t dev
);
657 static int acpi_sysres_attach(device_t dev
);
659 static device_method_t acpi_sysres_methods
[] = {
660 /* Device interface */
661 DEVMETHOD(device_probe
, acpi_sysres_probe
),
662 DEVMETHOD(device_attach
, acpi_sysres_attach
),
667 static driver_t acpi_sysres_driver
= {
673 static devclass_t acpi_sysres_devclass
;
674 DRIVER_MODULE(acpi_sysresource
, acpi
, acpi_sysres_driver
, acpi_sysres_devclass
,
676 MODULE_DEPEND(acpi_sysresource
, acpi
, 1, 1, 1);
679 acpi_sysres_probe(device_t dev
)
681 static char *sysres_ids
[] = { "PNP0C01", "PNP0C02", NULL
};
683 if (acpi_disabled("sysresource") ||
684 ACPI_ID_PROBE(device_get_parent(dev
), dev
, sysres_ids
) == NULL
)
687 device_set_desc(dev
, "System Resource");
689 return (BUS_PROBE_DEFAULT
);
693 acpi_sysres_attach(device_t dev
)
697 struct resource_list_entry
*bus_rle
, *dev_rle
;
698 struct resource_list
*bus_rl
, *dev_rl
;
700 u_long start
, end
, count
;
702 * Loop through all current resources to see if the new one overlaps
703 * any existing ones. If so, grow the old one up and/or down
704 * accordingly. Discard any that are wholly contained in the old. If
705 * the resource is unique, add it to the parent. It will later go into
708 bus
= device_get_parent(dev
);
709 gparent
= device_get_parent(bus
);
710 dev_rl
= BUS_GET_RESOURCE_LIST(bus
, dev
);
711 bus_rl
= BUS_GET_RESOURCE_LIST(device_get_parent(bus
), bus
);
713 kprintf("busrl is not null!\n");
714 SLIST_FOREACH(dev_rle
, dev_rl
, link
) {
715 if (dev_rle
->type
!= SYS_RES_IOPORT
&& dev_rle
->type
!= SYS_RES_MEMORY
)
718 start
= dev_rle
->start
;
720 count
= dev_rle
->count
;
721 type
= dev_rle
->type
;
724 SLIST_FOREACH(bus_rle
, bus_rl
, link
) {
725 if (bus_rle
->type
!= type
)
728 /* New resource wholly contained in old, discard. */
729 if (start
>= bus_rle
->start
&& end
<= bus_rle
->end
)
732 /* New tail overlaps old head, grow existing resource downward. */
733 if (start
< bus_rle
->start
&& end
>= bus_rle
->start
) {
734 bus_rle
->count
+= bus_rle
->start
- start
;
735 bus_rle
->start
= start
;
739 /* New head overlaps old tail, grow existing resource upward. */
740 if (start
<= bus_rle
->end
&& end
> bus_rle
->end
) {
741 bus_rle
->count
+= end
- bus_rle
->end
;
746 /* If we adjusted the old resource, we're finished. */
750 } else bus_rle
= NULL
;
751 /* If we didn't merge with anything, add this resource. */
752 if (bus_rle
== NULL
) {
753 bus_set_resource(bus
, type
, acpi_sysres_rid
++, start
, count
);
757 /* After merging/moving resources to the parent, free the list. */
758 resource_list_free(dev_rl
);