acpi_resource.c revision 69744
1153838Sdfr/*-
2153838Sdfr * Copyright (c) 2000 Michael Smith
3153838Sdfr * Copyright (c) 2000 BSDi
4153838Sdfr * All rights reserved.
5153838Sdfr *
6153838Sdfr * Redistribution and use in source and binary forms, with or without
7153838Sdfr * modification, are permitted provided that the following conditions
8153838Sdfr * are met:
9153838Sdfr * 1. Redistributions of source code must retain the above copyright
10153838Sdfr *    notice, this list of conditions and the following disclaimer.
11153838Sdfr * 2. Redistributions in binary form must reproduce the above copyright
12153838Sdfr *    notice, this list of conditions and the following disclaimer in the
13153838Sdfr *    documentation and/or other materials provided with the distribution.
14153838Sdfr *
15153838Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16153838Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17153838Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18153838Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19153838Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20153838Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21153838Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22153838Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23153838Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24153838Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25153838Sdfr * SUCH DAMAGE.
26153838Sdfr *
27153838Sdfr *	$FreeBSD: head/sys/dev/acpica/acpi_resource.c 69744 2000-12-08 09:16:20Z msmith $
28153838Sdfr */
29153838Sdfr
30153838Sdfr#include "opt_acpi.h"
31168340Skan#include <sys/param.h>
32153838Sdfr#include <sys/kernel.h>
33153838Sdfr#include <sys/bus.h>
34153838Sdfr#include <machine/bus.h>
35153838Sdfr#include <machine/resource.h>
36153838Sdfr
37153838Sdfr#include "acpi.h"
38153838Sdfr
39153838Sdfr#include <dev/acpica/acpivar.h>
40153838Sdfr
41153838Sdfr/*
42153838Sdfr * Hooks for the ACPI CA debugging infrastructure
43153838Sdfr */
44153838Sdfr#define _COMPONENT	BUS_MANAGER
45153838SdfrMODULE_NAME("RESOURCE")
46153838Sdfr
47153838Sdfr/*
48153838Sdfr * Fetch a device's resources and associate them with the device.
49153838Sdfr *
50153838Sdfr * Note that it might be nice to also locate ACPI-specific resource items, such
51153838Sdfr * as GPE bits.
52153838Sdfr */
53153838SdfrACPI_STATUS
54153838Sdfracpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set)
55153838Sdfr{
56153838Sdfr    ACPI_BUFFER		buf;
57153838Sdfr    RESOURCE		*res;
58153838Sdfr    char		*curr, *last;
59153838Sdfr    ACPI_STATUS		status;
60153838Sdfr    int			i;
61153838Sdfr    void		*context;
62153838Sdfr
63153838Sdfr    FUNCTION_TRACE(__FUNCTION__);
64153838Sdfr
65153838Sdfr    /*
66153838Sdfr     * Fetch the device resources
67153838Sdfr     */
68153838Sdfr    if (((status = acpi_GetIntoBuffer(handle, AcpiGetPossibleResources, &buf)) != AE_OK) &&
69153838Sdfr	((status = acpi_GetIntoBuffer(handle, AcpiGetCurrentResources, &buf)) != AE_OK)) {
70153838Sdfr	device_printf(dev, "can't fetch ACPI resources - %s\n", acpi_strerror(status));
71153838Sdfr	return_ACPI_STATUS(status);
72153838Sdfr    }
73153838Sdfr    DEBUG_PRINT(TRACE_RESOURCES, ("got %d bytes of resources\n", buf.Length));
74153838Sdfr    set->set_init(dev, &context);
75153838Sdfr
76153838Sdfr    /*
77153838Sdfr     * Iterate through the resources
78153838Sdfr     */
79    curr = buf.Pointer;
80    last = (char *)buf.Pointer + buf.Length;
81    while (curr < last) {
82	res = (RESOURCE *)curr;
83	curr += res->Length;
84
85	/*
86	 * Handle the individual resource types
87	 */
88	switch(res->Id) {
89	case EndTag:
90	    DEBUG_PRINT(TRACE_RESOURCES, ("EndTag\n"));
91	    curr = last;
92	    break;
93
94	case FixedIo:
95	    DEBUG_PRINT(TRACE_RESOURCES, ("FixedIo 0x%x/%d\n", res->Data.FixedIo.BaseAddress, res->Data.FixedIo.RangeLength));
96	    set->set_ioport(dev, context, res->Data.FixedIo.BaseAddress, res->Data.FixedIo.RangeLength);
97	    break;
98
99	case Io:
100	    if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
101		DEBUG_PRINT(TRACE_RESOURCES, ("Io 0x%x/%d\n", res->Data.Io.MinBaseAddress, res->Data.Io.RangeLength));
102		set->set_ioport(dev, context, res->Data.Io.MinBaseAddress, res->Data.Io.RangeLength);
103	    } else {
104		DEBUG_PRINT(TRACE_RESOURCES, ("Io 0x%x-0x%x/%d\n", res->Data.Io.MinBaseAddress, res->Data.Io.MaxBaseAddress,
105					      res->Data.Io.RangeLength));
106		set->set_iorange(dev, context, res->Data.Io.MinBaseAddress, res->Data.Io.MaxBaseAddress,
107				 res->Data.Io.RangeLength, res->Data.Io.Alignment);
108	    }
109	    break;
110
111	case FixedMemory32:
112	    DEBUG_PRINT(TRACE_RESOURCES, ("FixedMemory32 0x%x/%d\n", res->Data.FixedMemory32.RangeBaseAddress,
113					  res->Data.FixedMemory32.RangeLength));
114	    set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress,
115			    res->Data.FixedMemory32.RangeLength);
116	    break;
117
118	case Memory32:
119	    if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) {
120		DEBUG_PRINT(TRACE_RESOURCES, ("Memory32 0x%x/%d\n", res->Data.Memory32.MinBaseAddress,
121					      res->Data.Memory32.RangeLength));
122		set->set_memory(dev, context, res->Data.Memory32.MinBaseAddress, res->Data.Memory32.RangeLength);
123	    } else {
124		DEBUG_PRINT(TRACE_RESOURCES, ("Memory32 0x%x-0x%x/%d\n", res->Data.Memory32.MinBaseAddress,
125					      res->Data.Memory32.MaxBaseAddress, res->Data.Memory32.RangeLength));
126		set->set_memoryrange(dev, context, res->Data.Memory32.MinBaseAddress, res->Data.Memory32.MaxBaseAddress,
127				     res->Data.Memory32.RangeLength, res->Data.Memory32.Alignment);
128	    }
129	    break;
130
131	case Memory24:
132	    if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) {
133		DEBUG_PRINT(TRACE_RESOURCES, ("Memory24 0x%x/%d\n", res->Data.Memory24.MinBaseAddress,
134					      res->Data.Memory24.RangeLength));
135		set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress, res->Data.Memory24.RangeLength);
136	    } else {
137		DEBUG_PRINT(TRACE_RESOURCES, ("Memory24 0x%x-0x%x/%d\n", res->Data.Memory24.MinBaseAddress,
138					      res->Data.Memory24.MaxBaseAddress, res->Data.Memory24.RangeLength));
139		set->set_memoryrange(dev, context, res->Data.Memory24.MinBaseAddress, res->Data.Memory24.MaxBaseAddress,
140				     res->Data.Memory24.RangeLength, res->Data.Memory24.Alignment);
141	    }
142	    break;
143
144	case Irq:
145	    for (i = 0; i < res->Data.Irq.NumberOfInterrupts; i++) {
146		DEBUG_PRINT(TRACE_RESOURCES, ("Irq %d\n", res->Data.Irq.Interrupts[i]));
147		set->set_irq(dev, context, res->Data.Irq.Interrupts[i]);
148	    }
149	    break;
150
151	case Dma:
152	    for (i = 0; i < res->Data.Dma.NumberOfChannels; i++) {
153		DEBUG_PRINT(TRACE_RESOURCES, ("Drq %d\n", res->Data.Dma.Channels[i]));
154		set->set_drq(dev, context, res->Data.Dma.Channels[i]);
155	    }
156	    break;
157
158	case StartDependentFunctions:
159	    DEBUG_PRINT(TRACE_RESOURCES, ("start dependant functions"));
160	    set->set_start_dependant(dev, context, res->Data.StartDependentFunctions.CompatibilityPriority);
161	    break;
162
163	case EndDependentFunctions:
164	    DEBUG_PRINT(TRACE_RESOURCES, ("end dependant functions"));
165	    set->set_end_dependant(dev, context);
166	    break;
167
168	case Address32:
169	    DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented Address32 resource\n"));
170	    break;
171
172	case Address16:
173	    DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented Address16 resource\n"));
174	    break;
175
176	case ExtendedIrq:
177	    DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented ExtendedIrq resource\n"));
178	    break;
179
180	case VendorSpecific:
181	    DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented VendorSpecific resource\n"));
182	    break;
183	default:
184	    break;
185	}
186    }
187    AcpiOsFree(buf.Pointer);
188    set->set_done(dev, context);
189    return_ACPI_STATUS(AE_OK);
190}
191
192static void	acpi_res_set_init(device_t dev, void **context);
193static void	acpi_res_set_done(device_t dev, void *context);
194static void	acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
195static void	acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
196				     u_int32_t length, u_int32_t align);
197static void	acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
198static void	acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
199					 u_int32_t length, u_int32_t align);
200static void	acpi_res_set_irq(device_t dev, void *context, u_int32_t irq);
201static void	acpi_res_set_drq(device_t dev, void *context, u_int32_t drq);
202static void	acpi_res_set_start_dependant(device_t dev, void *context, int preference);
203static void	acpi_res_set_end_dependant(device_t dev, void *context);
204
205struct acpi_parse_resource_set acpi_res_parse_set = {
206    acpi_res_set_init,
207    acpi_res_set_done,
208    acpi_res_set_ioport,
209    acpi_res_set_iorange,
210    acpi_res_set_memory,
211    acpi_res_set_memoryrange,
212    acpi_res_set_irq,
213    acpi_res_set_drq,
214    acpi_res_set_start_dependant,
215    acpi_res_set_end_dependant
216};
217
218struct acpi_res_context {
219    int		ar_nio;
220    int		ar_nmem;
221    int		ar_nirq;
222};
223
224static void
225acpi_res_set_init(device_t dev, void **context)
226{
227    struct acpi_res_context	*cp;
228
229    if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
230	bzero(cp, sizeof(*cp));
231	*context = cp;
232    }
233}
234
235static void
236acpi_res_set_done(device_t dev, void *context)
237{
238    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
239
240    if (cp == NULL)
241	return;
242    AcpiOsFree(cp);
243}
244
245static void
246acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length)
247{
248    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
249
250    if (cp == NULL)
251	return;
252    bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
253}
254
255static void
256acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
257{
258    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
259
260    if (cp == NULL)
261	return;
262    device_printf(dev, "I/O range not supported\n");
263}
264
265static void
266acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length)
267{
268    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
269
270    if (cp == NULL)
271	return;
272    bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
273}
274
275static void
276acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
277{
278    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
279
280    if (cp == NULL)
281	return;
282    device_printf(dev, "memory range not supported\n");
283}
284
285static void
286acpi_res_set_irq(device_t dev, void *context, u_int32_t irq)
287{
288    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
289
290    if (cp == NULL)
291	return;
292    bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq, 1);
293}
294
295static void
296acpi_res_set_drq(device_t dev, void *context, u_int32_t drq)
297{
298    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
299
300    if (cp == NULL)
301	return;
302    device_printf(dev, "DRQ not supported\n");
303}
304
305static void
306acpi_res_set_start_dependant(device_t dev, void *context, int preference)
307{
308    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
309
310    if (cp == NULL)
311	return;
312    device_printf(dev, "dependant functions not supported");
313}
314
315static void
316acpi_res_set_end_dependant(device_t dev, void *context)
317{
318    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
319
320    if (cp == NULL)
321	return;
322}
323