xref: /dflybsd-src/sys/dev/acpica/acpi_resource.c (revision 5db2f26edd92ab4befeb61802687554b3ee6769a)
1*5db2f26eSSascha Wildner /*-
2*5db2f26eSSascha Wildner  * Copyright (c) 2000 Michael Smith
3*5db2f26eSSascha Wildner  * Copyright (c) 2000 BSDi
4*5db2f26eSSascha Wildner  * All rights reserved.
5*5db2f26eSSascha Wildner  *
6*5db2f26eSSascha Wildner  * Redistribution and use in source and binary forms, with or without
7*5db2f26eSSascha Wildner  * modification, are permitted provided that the following conditions
8*5db2f26eSSascha Wildner  * are met:
9*5db2f26eSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
10*5db2f26eSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
11*5db2f26eSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
12*5db2f26eSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
13*5db2f26eSSascha Wildner  *    documentation and/or other materials provided with the distribution.
14*5db2f26eSSascha Wildner  *
15*5db2f26eSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*5db2f26eSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*5db2f26eSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*5db2f26eSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*5db2f26eSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*5db2f26eSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*5db2f26eSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*5db2f26eSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*5db2f26eSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*5db2f26eSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*5db2f26eSSascha Wildner  * SUCH DAMAGE.
26*5db2f26eSSascha Wildner  *
27*5db2f26eSSascha Wildner  * $FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.40.8.1 2009/04/15 03:14:26 kensmith Exp $
28*5db2f26eSSascha Wildner  */
29*5db2f26eSSascha Wildner 
30*5db2f26eSSascha Wildner #include "opt_acpi.h"
31*5db2f26eSSascha Wildner #include <sys/param.h>
32*5db2f26eSSascha Wildner #include <sys/kernel.h>
33*5db2f26eSSascha Wildner #include <sys/bus.h>
34*5db2f26eSSascha Wildner #include <sys/malloc.h>
35*5db2f26eSSascha Wildner #include <sys/module.h>
36*5db2f26eSSascha Wildner #include <sys/resource.h>
37*5db2f26eSSascha Wildner #include <sys/machintr.h>
38*5db2f26eSSascha Wildner 
39*5db2f26eSSascha Wildner #include <sys/rman.h>
40*5db2f26eSSascha Wildner 
41*5db2f26eSSascha Wildner #include "acpi.h"
42*5db2f26eSSascha Wildner #include <dev/acpica/acpivar.h>
43*5db2f26eSSascha Wildner 
44*5db2f26eSSascha Wildner /* Hooks for the ACPI CA debugging infrastructure */
45*5db2f26eSSascha Wildner #define _COMPONENT	ACPI_BUS
46*5db2f26eSSascha Wildner ACPI_MODULE_NAME("RESOURCE")
47*5db2f26eSSascha Wildner 
48*5db2f26eSSascha Wildner struct lookup_irq_request {
49*5db2f26eSSascha Wildner     ACPI_RESOURCE *acpi_res;
50*5db2f26eSSascha Wildner     struct resource *res;
51*5db2f26eSSascha Wildner     int		counter;
52*5db2f26eSSascha Wildner     int		rid;
53*5db2f26eSSascha Wildner     int		found;
54*5db2f26eSSascha Wildner };
55*5db2f26eSSascha Wildner 
56*5db2f26eSSascha Wildner static ACPI_STATUS
57*5db2f26eSSascha Wildner acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
58*5db2f26eSSascha Wildner {
59*5db2f26eSSascha Wildner     struct lookup_irq_request *req;
60*5db2f26eSSascha Wildner     size_t len;
61*5db2f26eSSascha Wildner     u_int irqnum, irq;
62*5db2f26eSSascha Wildner 
63*5db2f26eSSascha Wildner     switch (res->Type) {
64*5db2f26eSSascha Wildner     case ACPI_RESOURCE_TYPE_IRQ:
65*5db2f26eSSascha Wildner 	irqnum = res->Data.Irq.InterruptCount;
66*5db2f26eSSascha Wildner 	irq = res->Data.Irq.Interrupts[0];
67*5db2f26eSSascha Wildner 	len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
68*5db2f26eSSascha Wildner 	break;
69*5db2f26eSSascha Wildner     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
70*5db2f26eSSascha Wildner 	irqnum = res->Data.ExtendedIrq.InterruptCount;
71*5db2f26eSSascha Wildner 	irq = res->Data.ExtendedIrq.Interrupts[0];
72*5db2f26eSSascha Wildner 	len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
73*5db2f26eSSascha Wildner 	break;
74*5db2f26eSSascha Wildner     default:
75*5db2f26eSSascha Wildner 	return (AE_OK);
76*5db2f26eSSascha Wildner     }
77*5db2f26eSSascha Wildner     if (irqnum != 1)
78*5db2f26eSSascha Wildner 	return (AE_OK);
79*5db2f26eSSascha Wildner     req = (struct lookup_irq_request *)context;
80*5db2f26eSSascha Wildner     if (req->counter != req->rid) {
81*5db2f26eSSascha Wildner 	req->counter++;
82*5db2f26eSSascha Wildner 	return (AE_OK);
83*5db2f26eSSascha Wildner     }
84*5db2f26eSSascha Wildner     req->found = 1;
85*5db2f26eSSascha Wildner     KASSERT(irq == rman_get_start(req->res),
86*5db2f26eSSascha Wildner 	("IRQ resources do not match"));
87*5db2f26eSSascha Wildner     bcopy(res, req->acpi_res, len);
88*5db2f26eSSascha Wildner     return (AE_CTRL_TERMINATE);
89*5db2f26eSSascha Wildner }
90*5db2f26eSSascha Wildner 
91*5db2f26eSSascha Wildner ACPI_STATUS
92*5db2f26eSSascha Wildner acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res,
93*5db2f26eSSascha Wildner     ACPI_RESOURCE *acpi_res)
94*5db2f26eSSascha Wildner {
95*5db2f26eSSascha Wildner     struct lookup_irq_request req;
96*5db2f26eSSascha Wildner     ACPI_STATUS status;
97*5db2f26eSSascha Wildner 
98*5db2f26eSSascha Wildner     req.acpi_res = acpi_res;
99*5db2f26eSSascha Wildner     req.res = res;
100*5db2f26eSSascha Wildner     req.counter = 0;
101*5db2f26eSSascha Wildner     req.rid = rid;
102*5db2f26eSSascha Wildner     req.found = 0;
103*5db2f26eSSascha Wildner     status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
104*5db2f26eSSascha Wildner 	acpi_lookup_irq_handler, &req);
105*5db2f26eSSascha Wildner     if (ACPI_SUCCESS(status) && req.found == 0)
106*5db2f26eSSascha Wildner 	status = AE_NOT_FOUND;
107*5db2f26eSSascha Wildner     return (status);
108*5db2f26eSSascha Wildner }
109*5db2f26eSSascha Wildner 
110*5db2f26eSSascha Wildner void
111*5db2f26eSSascha Wildner acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
112*5db2f26eSSascha Wildner {
113*5db2f26eSSascha Wildner     u_int irq;
114*5db2f26eSSascha Wildner     int pol, trig;
115*5db2f26eSSascha Wildner     enum intr_trigger trigger;
116*5db2f26eSSascha Wildner     enum intr_polarity polarity;
117*5db2f26eSSascha Wildner 
118*5db2f26eSSascha Wildner     switch (res->Type) {
119*5db2f26eSSascha Wildner     case ACPI_RESOURCE_TYPE_IRQ:
120*5db2f26eSSascha Wildner 	KASSERT(res->Data.Irq.InterruptCount == 1,
121*5db2f26eSSascha Wildner 	    ("%s: multiple interrupts", __func__));
122*5db2f26eSSascha Wildner 	irq = res->Data.Irq.Interrupts[0];
123*5db2f26eSSascha Wildner 	trig = res->Data.Irq.Triggering;
124*5db2f26eSSascha Wildner 	pol = res->Data.Irq.Polarity;
125*5db2f26eSSascha Wildner 	break;
126*5db2f26eSSascha Wildner     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
127*5db2f26eSSascha Wildner 	KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
128*5db2f26eSSascha Wildner 	    ("%s: multiple interrupts", __func__));
129*5db2f26eSSascha Wildner 	irq = res->Data.ExtendedIrq.Interrupts[0];
130*5db2f26eSSascha Wildner 	trig = res->Data.ExtendedIrq.Triggering;
131*5db2f26eSSascha Wildner 	pol = res->Data.ExtendedIrq.Polarity;
132*5db2f26eSSascha Wildner 	break;
133*5db2f26eSSascha Wildner     default:
134*5db2f26eSSascha Wildner 	panic("%s: bad resource type %u", __func__, res->Type);
135*5db2f26eSSascha Wildner     }
136*5db2f26eSSascha Wildner 
137*5db2f26eSSascha Wildner     if (trig == ACPI_EDGE_SENSITIVE)
138*5db2f26eSSascha Wildner     	trigger = INTR_TRIGGER_EDGE;
139*5db2f26eSSascha Wildner     else
140*5db2f26eSSascha Wildner     	trigger = INTR_TRIGGER_LEVEL;
141*5db2f26eSSascha Wildner 
142*5db2f26eSSascha Wildner     if (pol == ACPI_ACTIVE_HIGH)
143*5db2f26eSSascha Wildner 	polarity = INTR_POLARITY_HIGH;
144*5db2f26eSSascha Wildner     else
145*5db2f26eSSascha Wildner     	polarity = INTR_POLARITY_LOW;
146*5db2f26eSSascha Wildner 
147*5db2f26eSSascha Wildner     if (machintr_legacy_intr_find(irq, trigger, polarity) < 0)
148*5db2f26eSSascha Wildner 	kprintf("acpi_config_intr: Skip irq %d config\n", irq);
149*5db2f26eSSascha Wildner     else
150*5db2f26eSSascha Wildner 	BUS_CONFIG_INTR(dev, dev, irq, trigger, polarity);
151*5db2f26eSSascha Wildner }
152*5db2f26eSSascha Wildner 
153*5db2f26eSSascha Wildner /*
154*5db2f26eSSascha Wildner  * Fetch a device's resources and associate them with the device.
155*5db2f26eSSascha Wildner  *
156*5db2f26eSSascha Wildner  * Note that it might be nice to also locate ACPI-specific resource items, such
157*5db2f26eSSascha Wildner  * as GPE bits.
158*5db2f26eSSascha Wildner  *
159*5db2f26eSSascha Wildner  * We really need to split the resource-fetching code out from the
160*5db2f26eSSascha Wildner  * resource-parsing code, since we may want to use the parsing
161*5db2f26eSSascha Wildner  * code for _PRS someday.
162*5db2f26eSSascha Wildner  */
163*5db2f26eSSascha Wildner ACPI_STATUS
164*5db2f26eSSascha Wildner acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
165*5db2f26eSSascha Wildner 		     struct acpi_parse_resource_set *set, void *arg)
166*5db2f26eSSascha Wildner {
167*5db2f26eSSascha Wildner     ACPI_BUFFER		buf;
168*5db2f26eSSascha Wildner     ACPI_RESOURCE	*res;
169*5db2f26eSSascha Wildner     char		*curr, *last;
170*5db2f26eSSascha Wildner     ACPI_STATUS		status;
171*5db2f26eSSascha Wildner     void		*context;
172*5db2f26eSSascha Wildner 
173*5db2f26eSSascha Wildner     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
174*5db2f26eSSascha Wildner 
175*5db2f26eSSascha Wildner     /*
176*5db2f26eSSascha Wildner      * Special-case some devices that abuse _PRS/_CRS to mean
177*5db2f26eSSascha Wildner      * something other than "I consume this resource".
178*5db2f26eSSascha Wildner      *
179*5db2f26eSSascha Wildner      * XXX do we really need this?  It's only relevant once
180*5db2f26eSSascha Wildner      *     we start always-allocating these resources, and even
181*5db2f26eSSascha Wildner      *     then, the only special-cased device is likely to be
182*5db2f26eSSascha Wildner      *     the PCI interrupt link.
183*5db2f26eSSascha Wildner      */
184*5db2f26eSSascha Wildner 
185*5db2f26eSSascha Wildner     /* Fetch the device's current resources. */
186*5db2f26eSSascha Wildner     buf.Length = ACPI_ALLOCATE_BUFFER;
187*5db2f26eSSascha Wildner     if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
188*5db2f26eSSascha Wildner 	if (status != AE_NOT_FOUND && status != AE_TYPE)
189*5db2f26eSSascha Wildner 	    kprintf("can't fetch resources for %s - %s\n",
190*5db2f26eSSascha Wildner 		   acpi_name(handle), AcpiFormatException(status));
191*5db2f26eSSascha Wildner 	return_ACPI_STATUS (status);
192*5db2f26eSSascha Wildner     }
193*5db2f26eSSascha Wildner     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
194*5db2f26eSSascha Wildner 		     acpi_name(handle), (long)buf.Length));
195*5db2f26eSSascha Wildner     set->set_init(dev, arg, &context);
196*5db2f26eSSascha Wildner 
197*5db2f26eSSascha Wildner     /* Iterate through the resources */
198*5db2f26eSSascha Wildner     curr = buf.Pointer;
199*5db2f26eSSascha Wildner     last = (char *)buf.Pointer + buf.Length;
200*5db2f26eSSascha Wildner     while (curr < last) {
201*5db2f26eSSascha Wildner 	res = (ACPI_RESOURCE *)curr;
202*5db2f26eSSascha Wildner 	curr += res->Length;
203*5db2f26eSSascha Wildner 
204*5db2f26eSSascha Wildner 	/* Handle the individual resource types */
205*5db2f26eSSascha Wildner 	switch(res->Type) {
206*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_END_TAG:
207*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
208*5db2f26eSSascha Wildner 	    curr = last;
209*5db2f26eSSascha Wildner 	    break;
210*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_FIXED_IO:
211*5db2f26eSSascha Wildner 	    if (res->Data.FixedIo.AddressLength <= 0)
212*5db2f26eSSascha Wildner 		break;
213*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
214*5db2f26eSSascha Wildner 			     res->Data.FixedIo.Address,
215*5db2f26eSSascha Wildner 			     res->Data.FixedIo.AddressLength));
216*5db2f26eSSascha Wildner 	    set->set_ioport(dev, context,
217*5db2f26eSSascha Wildner 			    res->Data.FixedIo.Address,
218*5db2f26eSSascha Wildner 			    res->Data.FixedIo.AddressLength);
219*5db2f26eSSascha Wildner 	    break;
220*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_IO:
221*5db2f26eSSascha Wildner 	    if (res->Data.Io.AddressLength <= 0)
222*5db2f26eSSascha Wildner 		break;
223*5db2f26eSSascha Wildner 	    if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
224*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
225*5db2f26eSSascha Wildner 				 res->Data.Io.Minimum,
226*5db2f26eSSascha Wildner 				 res->Data.Io.AddressLength));
227*5db2f26eSSascha Wildner 		set->set_ioport(dev, context,
228*5db2f26eSSascha Wildner 				res->Data.Io.Minimum,
229*5db2f26eSSascha Wildner 				res->Data.Io.AddressLength);
230*5db2f26eSSascha Wildner 	    } else {
231*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
232*5db2f26eSSascha Wildner 				 res->Data.Io.Minimum,
233*5db2f26eSSascha Wildner 				 res->Data.Io.Maximum,
234*5db2f26eSSascha Wildner 				 res->Data.Io.AddressLength));
235*5db2f26eSSascha Wildner 		set->set_iorange(dev, context,
236*5db2f26eSSascha Wildner 				 res->Data.Io.Minimum,
237*5db2f26eSSascha Wildner 				 res->Data.Io.Maximum,
238*5db2f26eSSascha Wildner 				 res->Data.Io.AddressLength,
239*5db2f26eSSascha Wildner 				 res->Data.Io.Alignment);
240*5db2f26eSSascha Wildner 	    }
241*5db2f26eSSascha Wildner 	    break;
242*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
243*5db2f26eSSascha Wildner 	    if (res->Data.FixedMemory32.AddressLength <= 0)
244*5db2f26eSSascha Wildner 		break;
245*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
246*5db2f26eSSascha Wildner 			      res->Data.FixedMemory32.Address,
247*5db2f26eSSascha Wildner 			      res->Data.FixedMemory32.AddressLength));
248*5db2f26eSSascha Wildner 	    set->set_memory(dev, context,
249*5db2f26eSSascha Wildner 			    res->Data.FixedMemory32.Address,
250*5db2f26eSSascha Wildner 			    res->Data.FixedMemory32.AddressLength);
251*5db2f26eSSascha Wildner 	    break;
252*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_MEMORY32:
253*5db2f26eSSascha Wildner 	    if (res->Data.Memory32.AddressLength <= 0)
254*5db2f26eSSascha Wildner 		break;
255*5db2f26eSSascha Wildner 	    if (res->Data.Memory32.Minimum ==
256*5db2f26eSSascha Wildner 		res->Data.Memory32.Maximum) {
257*5db2f26eSSascha Wildner 
258*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
259*5db2f26eSSascha Wildner 				  res->Data.Memory32.Minimum,
260*5db2f26eSSascha Wildner 				  res->Data.Memory32.AddressLength));
261*5db2f26eSSascha Wildner 		set->set_memory(dev, context,
262*5db2f26eSSascha Wildner 				res->Data.Memory32.Minimum,
263*5db2f26eSSascha Wildner 				res->Data.Memory32.AddressLength);
264*5db2f26eSSascha Wildner 	    } else {
265*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
266*5db2f26eSSascha Wildner 				 res->Data.Memory32.Minimum,
267*5db2f26eSSascha Wildner 				 res->Data.Memory32.Maximum,
268*5db2f26eSSascha Wildner 				 res->Data.Memory32.AddressLength));
269*5db2f26eSSascha Wildner 		set->set_memoryrange(dev, context,
270*5db2f26eSSascha Wildner 				     res->Data.Memory32.Minimum,
271*5db2f26eSSascha Wildner 				     res->Data.Memory32.Maximum,
272*5db2f26eSSascha Wildner 				     res->Data.Memory32.AddressLength,
273*5db2f26eSSascha Wildner 				     res->Data.Memory32.Alignment);
274*5db2f26eSSascha Wildner 	    }
275*5db2f26eSSascha Wildner 	    break;
276*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_MEMORY24:
277*5db2f26eSSascha Wildner 	    if (res->Data.Memory24.AddressLength <= 0)
278*5db2f26eSSascha Wildner 		break;
279*5db2f26eSSascha Wildner 	    if (res->Data.Memory24.Minimum ==
280*5db2f26eSSascha Wildner 		res->Data.Memory24.Maximum) {
281*5db2f26eSSascha Wildner 
282*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
283*5db2f26eSSascha Wildner 				 res->Data.Memory24.Minimum,
284*5db2f26eSSascha Wildner 				 res->Data.Memory24.AddressLength));
285*5db2f26eSSascha Wildner 		set->set_memory(dev, context, res->Data.Memory24.Minimum,
286*5db2f26eSSascha Wildner 				res->Data.Memory24.AddressLength);
287*5db2f26eSSascha Wildner 	    } else {
288*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
289*5db2f26eSSascha Wildner 				 res->Data.Memory24.Minimum,
290*5db2f26eSSascha Wildner 				 res->Data.Memory24.Maximum,
291*5db2f26eSSascha Wildner 				 res->Data.Memory24.AddressLength));
292*5db2f26eSSascha Wildner 		set->set_memoryrange(dev, context,
293*5db2f26eSSascha Wildner 				     res->Data.Memory24.Minimum,
294*5db2f26eSSascha Wildner 				     res->Data.Memory24.Maximum,
295*5db2f26eSSascha Wildner 				     res->Data.Memory24.AddressLength,
296*5db2f26eSSascha Wildner 				     res->Data.Memory24.Alignment);
297*5db2f26eSSascha Wildner 	    }
298*5db2f26eSSascha Wildner 	    break;
299*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_IRQ:
300*5db2f26eSSascha Wildner 	    /*
301*5db2f26eSSascha Wildner 	     * from 1.0b 6.4.2
302*5db2f26eSSascha Wildner 	     * "This structure is repeated for each separate interrupt
303*5db2f26eSSascha Wildner 	     * required"
304*5db2f26eSSascha Wildner 	     */
305*5db2f26eSSascha Wildner 	    set->set_irq(dev, context, res->Data.Irq.Interrupts,
306*5db2f26eSSascha Wildner 		res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
307*5db2f26eSSascha Wildner 		res->Data.Irq.Polarity);
308*5db2f26eSSascha Wildner 	    break;
309*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_DMA:
310*5db2f26eSSascha Wildner 	    /*
311*5db2f26eSSascha Wildner 	     * from 1.0b 6.4.3
312*5db2f26eSSascha Wildner 	     * "This structure is repeated for each separate dma channel
313*5db2f26eSSascha Wildner 	     * required"
314*5db2f26eSSascha Wildner 	     */
315*5db2f26eSSascha Wildner 	    set->set_drq(dev, context, res->Data.Dma.Channels,
316*5db2f26eSSascha Wildner 			 res->Data.Dma.ChannelCount);
317*5db2f26eSSascha Wildner 	    break;
318*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
319*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
320*5db2f26eSSascha Wildner 	    set->set_start_dependent(dev, context,
321*5db2f26eSSascha Wildner 				     res->Data.StartDpf.CompatibilityPriority);
322*5db2f26eSSascha Wildner 	    break;
323*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
324*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
325*5db2f26eSSascha Wildner 	    set->set_end_dependent(dev, context);
326*5db2f26eSSascha Wildner 	    break;
327*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_ADDRESS32:
328*5db2f26eSSascha Wildner 	    if (res->Data.Address32.AddressLength <= 0)
329*5db2f26eSSascha Wildner 		break;
330*5db2f26eSSascha Wildner 	    if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
331*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
332*5db2f26eSSascha Wildner 		    "ignored Address32 %s producer\n",
333*5db2f26eSSascha Wildner 		    res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
334*5db2f26eSSascha Wildner 		    "IO" : "Memory"));
335*5db2f26eSSascha Wildner 		break;
336*5db2f26eSSascha Wildner 	    }
337*5db2f26eSSascha Wildner 	    if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
338*5db2f26eSSascha Wildner 		res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
339*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
340*5db2f26eSSascha Wildner 		    "ignored Address32 for non-memory, non-I/O\n"));
341*5db2f26eSSascha Wildner 		break;
342*5db2f26eSSascha Wildner 	    }
343*5db2f26eSSascha Wildner 
344*5db2f26eSSascha Wildner 	    if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
345*5db2f26eSSascha Wildner 		res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
346*5db2f26eSSascha Wildner 
347*5db2f26eSSascha Wildner 		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
348*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
349*5db2f26eSSascha Wildner 				     "Address32/Memory 0x%x/%d\n",
350*5db2f26eSSascha Wildner 				     res->Data.Address32.Minimum,
351*5db2f26eSSascha Wildner 				     res->Data.Address32.AddressLength));
352*5db2f26eSSascha Wildner 		    set->set_memory(dev, context,
353*5db2f26eSSascha Wildner 				    res->Data.Address32.Minimum,
354*5db2f26eSSascha Wildner 				    res->Data.Address32.AddressLength);
355*5db2f26eSSascha Wildner 		} else {
356*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
357*5db2f26eSSascha Wildner 				     "Address32/IO 0x%x/%d\n",
358*5db2f26eSSascha Wildner 				     res->Data.Address32.Minimum,
359*5db2f26eSSascha Wildner 				     res->Data.Address32.AddressLength));
360*5db2f26eSSascha Wildner 		    set->set_ioport(dev, context,
361*5db2f26eSSascha Wildner 				    res->Data.Address32.Minimum,
362*5db2f26eSSascha Wildner 				    res->Data.Address32.AddressLength);
363*5db2f26eSSascha Wildner 		}
364*5db2f26eSSascha Wildner 	    } else {
365*5db2f26eSSascha Wildner 		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
366*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
367*5db2f26eSSascha Wildner 				     "Address32/Memory 0x%x-0x%x/%d\n",
368*5db2f26eSSascha Wildner 				     res->Data.Address32.Minimum,
369*5db2f26eSSascha Wildner 				     res->Data.Address32.Maximum,
370*5db2f26eSSascha Wildner 				     res->Data.Address32.AddressLength));
371*5db2f26eSSascha Wildner 		    set->set_memoryrange(dev, context,
372*5db2f26eSSascha Wildner 					  res->Data.Address32.Minimum,
373*5db2f26eSSascha Wildner 					  res->Data.Address32.Maximum,
374*5db2f26eSSascha Wildner 					  res->Data.Address32.AddressLength,
375*5db2f26eSSascha Wildner 					  res->Data.Address32.Granularity);
376*5db2f26eSSascha Wildner 		} else {
377*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
378*5db2f26eSSascha Wildner 				     "Address32/IO 0x%x-0x%x/%d\n",
379*5db2f26eSSascha Wildner 				     res->Data.Address32.Minimum,
380*5db2f26eSSascha Wildner 				     res->Data.Address32.Maximum,
381*5db2f26eSSascha Wildner 				     res->Data.Address32.AddressLength));
382*5db2f26eSSascha Wildner 		    set->set_iorange(dev, context,
383*5db2f26eSSascha Wildner 				     res->Data.Address32.Minimum,
384*5db2f26eSSascha Wildner 				     res->Data.Address32.Maximum,
385*5db2f26eSSascha Wildner 				     res->Data.Address32.AddressLength,
386*5db2f26eSSascha Wildner 				     res->Data.Address32.Granularity);
387*5db2f26eSSascha Wildner 		}
388*5db2f26eSSascha Wildner 	    }
389*5db2f26eSSascha Wildner 	    break;
390*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_ADDRESS16:
391*5db2f26eSSascha Wildner 	    if (res->Data.Address16.AddressLength <= 0)
392*5db2f26eSSascha Wildner 		break;
393*5db2f26eSSascha Wildner 	    if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
394*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
395*5db2f26eSSascha Wildner 		    "ignored Address16 %s producer\n",
396*5db2f26eSSascha Wildner 		    res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
397*5db2f26eSSascha Wildner 		    "IO" : "Memory"));
398*5db2f26eSSascha Wildner 		break;
399*5db2f26eSSascha Wildner 	    }
400*5db2f26eSSascha Wildner 	    if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
401*5db2f26eSSascha Wildner 		res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
402*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
403*5db2f26eSSascha Wildner 			"ignored Address16 for non-memory, non-I/O\n"));
404*5db2f26eSSascha Wildner 		break;
405*5db2f26eSSascha Wildner 	    }
406*5db2f26eSSascha Wildner 
407*5db2f26eSSascha Wildner 	    if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
408*5db2f26eSSascha Wildner 		res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
409*5db2f26eSSascha Wildner 
410*5db2f26eSSascha Wildner 		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
411*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
412*5db2f26eSSascha Wildner 				     "Address16/Memory 0x%x/%d\n",
413*5db2f26eSSascha Wildner 				     res->Data.Address16.Minimum,
414*5db2f26eSSascha Wildner 				     res->Data.Address16.AddressLength));
415*5db2f26eSSascha Wildner 		    set->set_memory(dev, context,
416*5db2f26eSSascha Wildner 				    res->Data.Address16.Minimum,
417*5db2f26eSSascha Wildner 				    res->Data.Address16.AddressLength);
418*5db2f26eSSascha Wildner 		} else {
419*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
420*5db2f26eSSascha Wildner 				     "Address16/IO 0x%x/%d\n",
421*5db2f26eSSascha Wildner 				     res->Data.Address16.Minimum,
422*5db2f26eSSascha Wildner 				     res->Data.Address16.AddressLength));
423*5db2f26eSSascha Wildner 		    set->set_ioport(dev, context,
424*5db2f26eSSascha Wildner 				    res->Data.Address16.Minimum,
425*5db2f26eSSascha Wildner 				    res->Data.Address16.AddressLength);
426*5db2f26eSSascha Wildner 		}
427*5db2f26eSSascha Wildner 	    } else {
428*5db2f26eSSascha Wildner 		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
429*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
430*5db2f26eSSascha Wildner 				     "Address16/Memory 0x%x-0x%x/%d\n",
431*5db2f26eSSascha Wildner 				     res->Data.Address16.Minimum,
432*5db2f26eSSascha Wildner 				     res->Data.Address16.Maximum,
433*5db2f26eSSascha Wildner 				     res->Data.Address16.AddressLength));
434*5db2f26eSSascha Wildner 		    set->set_memoryrange(dev, context,
435*5db2f26eSSascha Wildner 					  res->Data.Address16.Minimum,
436*5db2f26eSSascha Wildner 					  res->Data.Address16.Maximum,
437*5db2f26eSSascha Wildner 					  res->Data.Address16.AddressLength,
438*5db2f26eSSascha Wildner 					  res->Data.Address16.Granularity);
439*5db2f26eSSascha Wildner 		} else {
440*5db2f26eSSascha Wildner 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
441*5db2f26eSSascha Wildner 				     "Address16/IO 0x%x-0x%x/%d\n",
442*5db2f26eSSascha Wildner 				     res->Data.Address16.Minimum,
443*5db2f26eSSascha Wildner 				     res->Data.Address16.Maximum,
444*5db2f26eSSascha Wildner 				     res->Data.Address16.AddressLength));
445*5db2f26eSSascha Wildner 		    set->set_iorange(dev, context,
446*5db2f26eSSascha Wildner 				     res->Data.Address16.Minimum,
447*5db2f26eSSascha Wildner 				     res->Data.Address16.Maximum,
448*5db2f26eSSascha Wildner 				     res->Data.Address16.AddressLength,
449*5db2f26eSSascha Wildner 				     res->Data.Address16.Granularity);
450*5db2f26eSSascha Wildner 		}
451*5db2f26eSSascha Wildner 	    }
452*5db2f26eSSascha Wildner 	    break;
453*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_ADDRESS64:
454*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
455*5db2f26eSSascha Wildner 			     "unimplemented Address64 resource\n"));
456*5db2f26eSSascha Wildner 	    break;
457*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
458*5db2f26eSSascha Wildner 	    if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
459*5db2f26eSSascha Wildner 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
460*5db2f26eSSascha Wildner 		    "ignored ExtIRQ producer\n"));
461*5db2f26eSSascha Wildner 		break;
462*5db2f26eSSascha Wildner 	    }
463*5db2f26eSSascha Wildner 	    set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
464*5db2f26eSSascha Wildner 		res->Data.ExtendedIrq.InterruptCount,
465*5db2f26eSSascha Wildner 		res->Data.ExtendedIrq.Triggering,
466*5db2f26eSSascha Wildner 		res->Data.ExtendedIrq.Polarity);
467*5db2f26eSSascha Wildner 	    break;
468*5db2f26eSSascha Wildner 	case ACPI_RESOURCE_TYPE_VENDOR:
469*5db2f26eSSascha Wildner 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
470*5db2f26eSSascha Wildner 			     "unimplemented VendorSpecific resource\n"));
471*5db2f26eSSascha Wildner 	    break;
472*5db2f26eSSascha Wildner 	default:
473*5db2f26eSSascha Wildner 	    break;
474*5db2f26eSSascha Wildner 	}
475*5db2f26eSSascha Wildner     }
476*5db2f26eSSascha Wildner 
477*5db2f26eSSascha Wildner     AcpiOsFree(buf.Pointer);
478*5db2f26eSSascha Wildner     set->set_done(dev, context);
479*5db2f26eSSascha Wildner     return_ACPI_STATUS (AE_OK);
480*5db2f26eSSascha Wildner }
481*5db2f26eSSascha Wildner 
482*5db2f26eSSascha Wildner /*
483*5db2f26eSSascha Wildner  * Resource-set vectors used to attach _CRS-derived resources
484*5db2f26eSSascha Wildner  * to an ACPI device.
485*5db2f26eSSascha Wildner  */
486*5db2f26eSSascha Wildner static void	acpi_res_set_init(device_t dev, void *arg, void **context);
487*5db2f26eSSascha Wildner static void	acpi_res_set_done(device_t dev, void *context);
488*5db2f26eSSascha Wildner static void	acpi_res_set_ioport(device_t dev, void *context,
489*5db2f26eSSascha Wildner 				    u_int32_t base, u_int32_t length);
490*5db2f26eSSascha Wildner static void	acpi_res_set_iorange(device_t dev, void *context,
491*5db2f26eSSascha Wildner 				     u_int32_t low, u_int32_t high,
492*5db2f26eSSascha Wildner 				     u_int32_t length, u_int32_t align);
493*5db2f26eSSascha Wildner static void	acpi_res_set_memory(device_t dev, void *context,
494*5db2f26eSSascha Wildner 				    u_int32_t base, u_int32_t length);
495*5db2f26eSSascha Wildner static void	acpi_res_set_memoryrange(device_t dev, void *context,
496*5db2f26eSSascha Wildner 					 u_int32_t low, u_int32_t high,
497*5db2f26eSSascha Wildner 					 u_int32_t length, u_int32_t align);
498*5db2f26eSSascha Wildner static void	acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq,
499*5db2f26eSSascha Wildner 				 int count, int trig, int pol);
500*5db2f26eSSascha Wildner static void	acpi_res_set_ext_irq(device_t dev, void *context,
501*5db2f26eSSascha Wildner 				 u_int32_t *irq, int count, int trig, int pol);
502*5db2f26eSSascha Wildner static void	acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq,
503*5db2f26eSSascha Wildner 				 int count);
504*5db2f26eSSascha Wildner static void	acpi_res_set_start_dependent(device_t dev, void *context,
505*5db2f26eSSascha Wildner 					     int preference);
506*5db2f26eSSascha Wildner static void	acpi_res_set_end_dependent(device_t dev, void *context);
507*5db2f26eSSascha Wildner 
508*5db2f26eSSascha Wildner struct acpi_parse_resource_set acpi_res_parse_set = {
509*5db2f26eSSascha Wildner     acpi_res_set_init,
510*5db2f26eSSascha Wildner     acpi_res_set_done,
511*5db2f26eSSascha Wildner     acpi_res_set_ioport,
512*5db2f26eSSascha Wildner     acpi_res_set_iorange,
513*5db2f26eSSascha Wildner     acpi_res_set_memory,
514*5db2f26eSSascha Wildner     acpi_res_set_memoryrange,
515*5db2f26eSSascha Wildner     acpi_res_set_irq,
516*5db2f26eSSascha Wildner     acpi_res_set_ext_irq,
517*5db2f26eSSascha Wildner     acpi_res_set_drq,
518*5db2f26eSSascha Wildner     acpi_res_set_start_dependent,
519*5db2f26eSSascha Wildner     acpi_res_set_end_dependent
520*5db2f26eSSascha Wildner };
521*5db2f26eSSascha Wildner 
522*5db2f26eSSascha Wildner struct acpi_res_context {
523*5db2f26eSSascha Wildner     int		ar_nio;
524*5db2f26eSSascha Wildner     int		ar_nmem;
525*5db2f26eSSascha Wildner     int		ar_nirq;
526*5db2f26eSSascha Wildner     int		ar_ndrq;
527*5db2f26eSSascha Wildner     void 	*ar_parent;
528*5db2f26eSSascha Wildner };
529*5db2f26eSSascha Wildner 
530*5db2f26eSSascha Wildner static void
531*5db2f26eSSascha Wildner acpi_res_set_init(device_t dev, void *arg, void **context)
532*5db2f26eSSascha Wildner {
533*5db2f26eSSascha Wildner     struct acpi_res_context	*cp;
534*5db2f26eSSascha Wildner 
535*5db2f26eSSascha Wildner     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
536*5db2f26eSSascha Wildner 	bzero(cp, sizeof(*cp));
537*5db2f26eSSascha Wildner 	cp->ar_parent = arg;
538*5db2f26eSSascha Wildner 	*context = cp;
539*5db2f26eSSascha Wildner     }
540*5db2f26eSSascha Wildner }
541*5db2f26eSSascha Wildner 
542*5db2f26eSSascha Wildner static void
543*5db2f26eSSascha Wildner acpi_res_set_done(device_t dev, void *context)
544*5db2f26eSSascha Wildner {
545*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
546*5db2f26eSSascha Wildner 
547*5db2f26eSSascha Wildner     if (cp == NULL)
548*5db2f26eSSascha Wildner 	return;
549*5db2f26eSSascha Wildner     AcpiOsFree(cp);
550*5db2f26eSSascha Wildner }
551*5db2f26eSSascha Wildner 
552*5db2f26eSSascha Wildner static void
553*5db2f26eSSascha Wildner acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
554*5db2f26eSSascha Wildner 		    u_int32_t length)
555*5db2f26eSSascha Wildner {
556*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
557*5db2f26eSSascha Wildner 
558*5db2f26eSSascha Wildner     if (cp == NULL)
559*5db2f26eSSascha Wildner 	return;
560*5db2f26eSSascha Wildner     bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length, -1);
561*5db2f26eSSascha Wildner }
562*5db2f26eSSascha Wildner 
563*5db2f26eSSascha Wildner static void
564*5db2f26eSSascha Wildner acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
565*5db2f26eSSascha Wildner 		     u_int32_t high, u_int32_t length, u_int32_t align)
566*5db2f26eSSascha Wildner {
567*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
568*5db2f26eSSascha Wildner 
569*5db2f26eSSascha Wildner     if (cp == NULL)
570*5db2f26eSSascha Wildner 	return;
571*5db2f26eSSascha Wildner     device_printf(dev, "I/O range not supported\n");
572*5db2f26eSSascha Wildner }
573*5db2f26eSSascha Wildner 
574*5db2f26eSSascha Wildner static void
575*5db2f26eSSascha Wildner acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
576*5db2f26eSSascha Wildner 		    u_int32_t length)
577*5db2f26eSSascha Wildner {
578*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
579*5db2f26eSSascha Wildner 
580*5db2f26eSSascha Wildner     if (cp == NULL)
581*5db2f26eSSascha Wildner 	return;
582*5db2f26eSSascha Wildner 
583*5db2f26eSSascha Wildner     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length, -1);
584*5db2f26eSSascha Wildner }
585*5db2f26eSSascha Wildner 
586*5db2f26eSSascha Wildner static void
587*5db2f26eSSascha Wildner acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
588*5db2f26eSSascha Wildner 			 u_int32_t high, u_int32_t length, u_int32_t align)
589*5db2f26eSSascha Wildner {
590*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
591*5db2f26eSSascha Wildner 
592*5db2f26eSSascha Wildner     if (cp == NULL)
593*5db2f26eSSascha Wildner 	return;
594*5db2f26eSSascha Wildner     device_printf(dev, "memory range not supported\n");
595*5db2f26eSSascha Wildner }
596*5db2f26eSSascha Wildner 
597*5db2f26eSSascha Wildner static void
598*5db2f26eSSascha Wildner acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count,
599*5db2f26eSSascha Wildner     int trig, int pol)
600*5db2f26eSSascha Wildner {
601*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
602*5db2f26eSSascha Wildner 
603*5db2f26eSSascha Wildner     if (cp == NULL || irq == NULL)
604*5db2f26eSSascha Wildner 	return;
605*5db2f26eSSascha Wildner 
606*5db2f26eSSascha Wildner     /* This implements no resource relocation. */
607*5db2f26eSSascha Wildner     if (count != 1)
608*5db2f26eSSascha Wildner 	return;
609*5db2f26eSSascha Wildner 
610*5db2f26eSSascha Wildner     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1,
611*5db2f26eSSascha Wildner         machintr_legacy_intr_cpuid(*irq));
612*5db2f26eSSascha Wildner }
613*5db2f26eSSascha Wildner 
614*5db2f26eSSascha Wildner static void
615*5db2f26eSSascha Wildner acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count,
616*5db2f26eSSascha Wildner     int trig, int pol)
617*5db2f26eSSascha Wildner {
618*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
619*5db2f26eSSascha Wildner 
620*5db2f26eSSascha Wildner     if (cp == NULL || irq == NULL)
621*5db2f26eSSascha Wildner 	return;
622*5db2f26eSSascha Wildner 
623*5db2f26eSSascha Wildner     /* This implements no resource relocation. */
624*5db2f26eSSascha Wildner     if (count != 1)
625*5db2f26eSSascha Wildner 	return;
626*5db2f26eSSascha Wildner 
627*5db2f26eSSascha Wildner     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1,
628*5db2f26eSSascha Wildner         machintr_legacy_intr_cpuid(*irq));
629*5db2f26eSSascha Wildner }
630*5db2f26eSSascha Wildner 
631*5db2f26eSSascha Wildner static void
632*5db2f26eSSascha Wildner acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count)
633*5db2f26eSSascha Wildner {
634*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
635*5db2f26eSSascha Wildner 
636*5db2f26eSSascha Wildner     if (cp == NULL || drq == NULL)
637*5db2f26eSSascha Wildner 	return;
638*5db2f26eSSascha Wildner 
639*5db2f26eSSascha Wildner     /* This implements no resource relocation. */
640*5db2f26eSSascha Wildner     if (count != 1)
641*5db2f26eSSascha Wildner 	return;
642*5db2f26eSSascha Wildner 
643*5db2f26eSSascha Wildner     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1, -1);
644*5db2f26eSSascha Wildner }
645*5db2f26eSSascha Wildner 
646*5db2f26eSSascha Wildner static void
647*5db2f26eSSascha Wildner acpi_res_set_start_dependent(device_t dev, void *context, int preference)
648*5db2f26eSSascha Wildner {
649*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
650*5db2f26eSSascha Wildner 
651*5db2f26eSSascha Wildner     if (cp == NULL)
652*5db2f26eSSascha Wildner 	return;
653*5db2f26eSSascha Wildner     device_printf(dev, "dependent functions not supported\n");
654*5db2f26eSSascha Wildner }
655*5db2f26eSSascha Wildner 
656*5db2f26eSSascha Wildner static void
657*5db2f26eSSascha Wildner acpi_res_set_end_dependent(device_t dev, void *context)
658*5db2f26eSSascha Wildner {
659*5db2f26eSSascha Wildner     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
660*5db2f26eSSascha Wildner 
661*5db2f26eSSascha Wildner     if (cp == NULL)
662*5db2f26eSSascha Wildner 	return;
663*5db2f26eSSascha Wildner     device_printf(dev, "dependent functions not supported\n");
664*5db2f26eSSascha Wildner }
665*5db2f26eSSascha Wildner 
666*5db2f26eSSascha Wildner /*
667*5db2f26eSSascha Wildner  * Resource-owning placeholders for IO and memory pseudo-devices.
668*5db2f26eSSascha Wildner  *
669*5db2f26eSSascha Wildner  * This code allocates system resources that will be used by ACPI
670*5db2f26eSSascha Wildner  * child devices.  The acpi parent manages these resources through a
671*5db2f26eSSascha Wildner  * private rman.
672*5db2f26eSSascha Wildner  */
673*5db2f26eSSascha Wildner 
674*5db2f26eSSascha Wildner static int	acpi_sysres_rid = 100;
675*5db2f26eSSascha Wildner 
676*5db2f26eSSascha Wildner static int	acpi_sysres_probe(device_t dev);
677*5db2f26eSSascha Wildner static int	acpi_sysres_attach(device_t dev);
678*5db2f26eSSascha Wildner 
679*5db2f26eSSascha Wildner static device_method_t acpi_sysres_methods[] = {
680*5db2f26eSSascha Wildner     /* Device interface */
681*5db2f26eSSascha Wildner     DEVMETHOD(device_probe,	acpi_sysres_probe),
682*5db2f26eSSascha Wildner     DEVMETHOD(device_attach,	acpi_sysres_attach),
683*5db2f26eSSascha Wildner 
684*5db2f26eSSascha Wildner     {0, 0}
685*5db2f26eSSascha Wildner };
686*5db2f26eSSascha Wildner 
687*5db2f26eSSascha Wildner static driver_t acpi_sysres_driver = {
688*5db2f26eSSascha Wildner     "acpi_sysresource",
689*5db2f26eSSascha Wildner     acpi_sysres_methods,
690*5db2f26eSSascha Wildner     0,
691*5db2f26eSSascha Wildner };
692*5db2f26eSSascha Wildner 
693*5db2f26eSSascha Wildner static devclass_t acpi_sysres_devclass;
694*5db2f26eSSascha Wildner DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, acpi_sysres_devclass,
695*5db2f26eSSascha Wildner     0, 0);
696*5db2f26eSSascha Wildner MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
697*5db2f26eSSascha Wildner 
698*5db2f26eSSascha Wildner static int
699*5db2f26eSSascha Wildner acpi_sysres_probe(device_t dev)
700*5db2f26eSSascha Wildner {
701*5db2f26eSSascha Wildner     static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL };
702*5db2f26eSSascha Wildner 
703*5db2f26eSSascha Wildner     if (acpi_disabled("sysresource") ||
704*5db2f26eSSascha Wildner 	ACPI_ID_PROBE(device_get_parent(dev), dev, sysres_ids) == NULL)
705*5db2f26eSSascha Wildner 	return (ENXIO);
706*5db2f26eSSascha Wildner 
707*5db2f26eSSascha Wildner     device_set_desc(dev, "System Resource");
708*5db2f26eSSascha Wildner     device_quiet(dev);
709*5db2f26eSSascha Wildner     return (BUS_PROBE_DEFAULT);
710*5db2f26eSSascha Wildner }
711*5db2f26eSSascha Wildner 
712*5db2f26eSSascha Wildner static int
713*5db2f26eSSascha Wildner acpi_sysres_attach(device_t dev)
714*5db2f26eSSascha Wildner {
715*5db2f26eSSascha Wildner     device_t bus;
716*5db2f26eSSascha Wildner     struct resource_list_entry *bus_rle, *dev_rle;
717*5db2f26eSSascha Wildner     struct resource_list *bus_rl, *dev_rl;
718*5db2f26eSSascha Wildner     int done, type;
719*5db2f26eSSascha Wildner     u_long start, end, count;
720*5db2f26eSSascha Wildner     /*
721*5db2f26eSSascha Wildner      * Loop through all current resources to see if the new one overlaps
722*5db2f26eSSascha Wildner      * any existing ones.  If so, grow the old one up and/or down
723*5db2f26eSSascha Wildner      * accordingly.  Discard any that are wholly contained in the old.  If
724*5db2f26eSSascha Wildner      * the resource is unique, add it to the parent.  It will later go into
725*5db2f26eSSascha Wildner      * the rman pool.
726*5db2f26eSSascha Wildner      */
727*5db2f26eSSascha Wildner     bus = device_get_parent(dev);
728*5db2f26eSSascha Wildner     dev_rl = BUS_GET_RESOURCE_LIST(bus, dev);
729*5db2f26eSSascha Wildner     bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus);
730*5db2f26eSSascha Wildner     if(bus_rl)
731*5db2f26eSSascha Wildner 	kprintf("busrl is not null!\n");
732*5db2f26eSSascha Wildner 	SLIST_FOREACH(dev_rle, dev_rl, link) {
733*5db2f26eSSascha Wildner 	if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY)
734*5db2f26eSSascha Wildner 	    continue;
735*5db2f26eSSascha Wildner 
736*5db2f26eSSascha Wildner 	start = dev_rle->start;
737*5db2f26eSSascha Wildner 	end = dev_rle->end;
738*5db2f26eSSascha Wildner 	count = dev_rle->count;
739*5db2f26eSSascha Wildner 	type = dev_rle->type;
740*5db2f26eSSascha Wildner 	done = FALSE;
741*5db2f26eSSascha Wildner 	if(bus_rl) {
742*5db2f26eSSascha Wildner 	SLIST_FOREACH(bus_rle, bus_rl, link) {
743*5db2f26eSSascha Wildner 	    if (bus_rle->type != type)
744*5db2f26eSSascha Wildner 		continue;
745*5db2f26eSSascha Wildner 
746*5db2f26eSSascha Wildner 	    /* New resource wholly contained in old, discard. */
747*5db2f26eSSascha Wildner 	    if (start >= bus_rle->start && end <= bus_rle->end)
748*5db2f26eSSascha Wildner 		break;
749*5db2f26eSSascha Wildner 
750*5db2f26eSSascha Wildner 	    /* New tail overlaps old head, grow existing resource downward. */
751*5db2f26eSSascha Wildner 	    if (start < bus_rle->start && end >= bus_rle->start) {
752*5db2f26eSSascha Wildner 		bus_rle->count += bus_rle->start - start;
753*5db2f26eSSascha Wildner 		bus_rle->start = start;
754*5db2f26eSSascha Wildner 		done = TRUE;
755*5db2f26eSSascha Wildner 	    }
756*5db2f26eSSascha Wildner 
757*5db2f26eSSascha Wildner 	    /* New head overlaps old tail, grow existing resource upward. */
758*5db2f26eSSascha Wildner 	    if (start <= bus_rle->end && end > bus_rle->end) {
759*5db2f26eSSascha Wildner 		bus_rle->count += end - bus_rle->end;
760*5db2f26eSSascha Wildner 		bus_rle->end = end;
761*5db2f26eSSascha Wildner 		done = TRUE;
762*5db2f26eSSascha Wildner 	    }
763*5db2f26eSSascha Wildner 
764*5db2f26eSSascha Wildner 	    /* If we adjusted the old resource, we're finished. */
765*5db2f26eSSascha Wildner 	    if (done)
766*5db2f26eSSascha Wildner 		break;
767*5db2f26eSSascha Wildner 	}
768*5db2f26eSSascha Wildner 	} else bus_rle = NULL;
769*5db2f26eSSascha Wildner 	/* If we didn't merge with anything, add this resource. */
770*5db2f26eSSascha Wildner 	if (bus_rle == NULL) {
771*5db2f26eSSascha Wildner 	    bus_set_resource(bus, type, acpi_sysres_rid++, start, count, -1);
772*5db2f26eSSascha Wildner 	}
773*5db2f26eSSascha Wildner     }
774*5db2f26eSSascha Wildner 
775*5db2f26eSSascha Wildner     /* After merging/moving resources to the parent, free the list. */
776*5db2f26eSSascha Wildner     resource_list_free(dev_rl);
777*5db2f26eSSascha Wildner 
778*5db2f26eSSascha Wildner     return (0);
779*5db2f26eSSascha Wildner }
780