Deleted Added
full compact
acpi_resource.c (90014) acpi_resource.c (91125)
1/*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
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.
14 *
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.
26 *
1/*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
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.
14 *
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.
26 *
27 * $FreeBSD: head/sys/dev/acpica/acpi_resource.c 90014 2002-01-31 09:18:27Z takawata $
27 * $FreeBSD: head/sys/dev/acpica/acpi_resource.c 91125 2002-02-23 05:28:22Z msmith $
28 */
29
30#include "opt_acpi.h"
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/bus.h>
34
35#include <machine/bus.h>
36#include <machine/resource.h>
37#include <sys/rman.h>
38
39#include "acpi.h"
40
41#include <dev/acpica/acpivar.h>
42
43/*
44 * Hooks for the ACPI CA debugging infrastructure
45 */
46#define _COMPONENT ACPI_BUS
28 */
29
30#include "opt_acpi.h"
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/bus.h>
34
35#include <machine/bus.h>
36#include <machine/resource.h>
37#include <sys/rman.h>
38
39#include "acpi.h"
40
41#include <dev/acpica/acpivar.h>
42
43/*
44 * Hooks for the ACPI CA debugging infrastructure
45 */
46#define _COMPONENT ACPI_BUS
47MODULE_NAME("RESOURCE")
47ACPI_MODULE_NAME("RESOURCE")
48
49/*
50 * Fetch a device's resources and associate them with the device.
51 *
52 * Note that it might be nice to also locate ACPI-specific resource items, such
53 * as GPE bits.
54 *
55 * We really need to split the resource-fetching code out from the
56 * resource-parsing code, since we may want to use the parsing
57 * code for _PRS someday.
58 */
59ACPI_STATUS
60acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set)
61{
62 ACPI_BUFFER buf;
63 ACPI_RESOURCE *res;
64 char *curr, *last;
65 ACPI_STATUS status;
66 void *context;
67
48
49/*
50 * Fetch a device's resources and associate them with the device.
51 *
52 * Note that it might be nice to also locate ACPI-specific resource items, such
53 * as GPE bits.
54 *
55 * We really need to split the resource-fetching code out from the
56 * resource-parsing code, since we may want to use the parsing
57 * code for _PRS someday.
58 */
59ACPI_STATUS
60acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set)
61{
62 ACPI_BUFFER buf;
63 ACPI_RESOURCE *res;
64 char *curr, *last;
65 ACPI_STATUS status;
66 void *context;
67
68 FUNCTION_TRACE(__func__);
68 ACPI_FUNCTION_TRACE(__func__);
69
70 /*
71 * Special-case some devices that abuse _PRS/_CRS to mean
72 * something other than "I consume this resource".
73 *
74 * XXX do we really need this? It's only relevant once
75 * we start always-allocating these resources, and even
76 * then, the only special-cased device is likely to be
77 * the PCI interrupt link.
78 */
79
80 /*
81 * Fetch the device's current resources.
82 */
69
70 /*
71 * Special-case some devices that abuse _PRS/_CRS to mean
72 * something other than "I consume this resource".
73 *
74 * XXX do we really need this? It's only relevant once
75 * we start always-allocating these resources, and even
76 * then, the only special-cased device is likely to be
77 * the PCI interrupt link.
78 */
79
80 /*
81 * Fetch the device's current resources.
82 */
83 if (((status = acpi_GetIntoBuffer(handle, AcpiGetCurrentResources, &buf)) != AE_OK)) {
83 buf.Length = ACPI_ALLOCATE_BUFFER;
84 if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
84 if (status != AE_NOT_FOUND)
85 printf("can't fetch resources for %s - %s\n",
86 acpi_name(handle), AcpiFormatException(status));
87 return_ACPI_STATUS(status);
88 }
89 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %d bytes of resources\n",
90 acpi_name(handle), buf.Length));
91 set->set_init(dev, &context);
92
93 /*
94 * Iterate through the resources
95 */
96 curr = buf.Pointer;
97 last = (char *)buf.Pointer + buf.Length;
98 while (curr < last) {
99 res = (ACPI_RESOURCE *)curr;
100 curr += res->Length;
101
102 /*
103 * Handle the individual resource types
104 */
105 switch(res->Id) {
106 case ACPI_RSTYPE_END_TAG:
107 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
108 curr = last;
109 break;
110
111 case ACPI_RSTYPE_FIXED_IO:
112 if (res->Data.FixedIo.RangeLength <= 0)
113 break;
114 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
115 res->Data.FixedIo.BaseAddress,
116 res->Data.FixedIo.RangeLength));
117 set->set_ioport(dev, context,
118 res->Data.FixedIo.BaseAddress,
119 res->Data.FixedIo.RangeLength);
120 break;
121
122 case ACPI_RSTYPE_IO:
123 if (res->Data.Io.RangeLength <= 0)
124 break;
125 if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
126 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
127 res->Data.Io.MinBaseAddress,
128 res->Data.Io.RangeLength));
129 set->set_ioport(dev, context,
130 res->Data.Io.MinBaseAddress,
131 res->Data.Io.RangeLength);
132 } else {
133 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
134 res->Data.Io.MinBaseAddress,
135 res->Data.Io.MaxBaseAddress,
136 res->Data.Io.RangeLength));
137 set->set_iorange(dev, context,
138 res->Data.Io.MinBaseAddress,
139 res->Data.Io.MaxBaseAddress,
140 res->Data.Io.RangeLength, res->Data.Io.Alignment);
141 }
142 break;
143
144 case ACPI_RSTYPE_FIXED_MEM32:
145 if (res->Data.FixedMemory32.RangeLength <= 0)
146 break;
147 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
148 res->Data.FixedMemory32.RangeBaseAddress,
149 res->Data.FixedMemory32.RangeLength));
150 set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress,
151 res->Data.FixedMemory32.RangeLength);
152 break;
153
154 case ACPI_RSTYPE_MEM32:
155 if (res->Data.Memory32.RangeLength <= 0)
156 break;
157 if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) {
158 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
159 res->Data.Memory32.MinBaseAddress,
160 res->Data.Memory32.RangeLength));
161 set->set_memory(dev, context,
162 res->Data.Memory32.MinBaseAddress,
163 res->Data.Memory32.RangeLength);
164 } else {
165 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
166 res->Data.Memory32.MinBaseAddress,
167 res->Data.Memory32.MaxBaseAddress,
168 res->Data.Memory32.RangeLength));
169 set->set_memoryrange(dev, context,
170 res->Data.Memory32.MinBaseAddress,
171 res->Data.Memory32.MaxBaseAddress,
172 res->Data.Memory32.RangeLength,
173 res->Data.Memory32.Alignment);
174 }
175 break;
176
177 case ACPI_RSTYPE_MEM24:
178 if (res->Data.Memory24.RangeLength <= 0)
179 break;
180 if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) {
181 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
182 res->Data.Memory24.MinBaseAddress,
183 res->Data.Memory24.RangeLength));
184 set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
185 res->Data.Memory24.RangeLength);
186 } else {
187 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
188 res->Data.Memory24.MinBaseAddress,
189 res->Data.Memory24.MaxBaseAddress,
190 res->Data.Memory24.RangeLength));
191 set->set_memoryrange(dev, context,
192 res->Data.Memory24.MinBaseAddress,
193 res->Data.Memory24.MaxBaseAddress,
194 res->Data.Memory24.RangeLength,
195 res->Data.Memory24.Alignment);
196 }
197 break;
198
199 case ACPI_RSTYPE_IRQ:
200 /*
201 * from 1.0b 6.4.2
202 * "This structure is repeated for each separate interrupt
203 * required"
204 */
205 set->set_irq(dev, context, res->Data.Irq.Interrupts,
206 res->Data.Irq.NumberOfInterrupts);
207 break;
208
209 case ACPI_RSTYPE_DMA:
210 /*
211 * from 1.0b 6.4.3
212 * "This structure is repeated for each separate dma channel
213 * required"
214 */
215
216 set->set_drq(dev, context, res->Data.Dma.Channels,
217 res->Data.Dma.NumberOfChannels);
218 break;
219
220 case ACPI_RSTYPE_START_DPF:
221 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
222 set->set_start_dependant(dev, context,
223 res->Data.StartDpf.CompatibilityPriority);
224 break;
225
226 case ACPI_RSTYPE_END_DPF:
227 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
228 set->set_end_dependant(dev, context);
229 break;
230
231 case ACPI_RSTYPE_ADDRESS32:
232 if (res->Data.Address32.AddressLength <= 0)
233 break;
85 if (status != AE_NOT_FOUND)
86 printf("can't fetch resources for %s - %s\n",
87 acpi_name(handle), AcpiFormatException(status));
88 return_ACPI_STATUS(status);
89 }
90 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %d bytes of resources\n",
91 acpi_name(handle), buf.Length));
92 set->set_init(dev, &context);
93
94 /*
95 * Iterate through the resources
96 */
97 curr = buf.Pointer;
98 last = (char *)buf.Pointer + buf.Length;
99 while (curr < last) {
100 res = (ACPI_RESOURCE *)curr;
101 curr += res->Length;
102
103 /*
104 * Handle the individual resource types
105 */
106 switch(res->Id) {
107 case ACPI_RSTYPE_END_TAG:
108 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
109 curr = last;
110 break;
111
112 case ACPI_RSTYPE_FIXED_IO:
113 if (res->Data.FixedIo.RangeLength <= 0)
114 break;
115 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
116 res->Data.FixedIo.BaseAddress,
117 res->Data.FixedIo.RangeLength));
118 set->set_ioport(dev, context,
119 res->Data.FixedIo.BaseAddress,
120 res->Data.FixedIo.RangeLength);
121 break;
122
123 case ACPI_RSTYPE_IO:
124 if (res->Data.Io.RangeLength <= 0)
125 break;
126 if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
127 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
128 res->Data.Io.MinBaseAddress,
129 res->Data.Io.RangeLength));
130 set->set_ioport(dev, context,
131 res->Data.Io.MinBaseAddress,
132 res->Data.Io.RangeLength);
133 } else {
134 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
135 res->Data.Io.MinBaseAddress,
136 res->Data.Io.MaxBaseAddress,
137 res->Data.Io.RangeLength));
138 set->set_iorange(dev, context,
139 res->Data.Io.MinBaseAddress,
140 res->Data.Io.MaxBaseAddress,
141 res->Data.Io.RangeLength, res->Data.Io.Alignment);
142 }
143 break;
144
145 case ACPI_RSTYPE_FIXED_MEM32:
146 if (res->Data.FixedMemory32.RangeLength <= 0)
147 break;
148 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
149 res->Data.FixedMemory32.RangeBaseAddress,
150 res->Data.FixedMemory32.RangeLength));
151 set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress,
152 res->Data.FixedMemory32.RangeLength);
153 break;
154
155 case ACPI_RSTYPE_MEM32:
156 if (res->Data.Memory32.RangeLength <= 0)
157 break;
158 if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) {
159 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
160 res->Data.Memory32.MinBaseAddress,
161 res->Data.Memory32.RangeLength));
162 set->set_memory(dev, context,
163 res->Data.Memory32.MinBaseAddress,
164 res->Data.Memory32.RangeLength);
165 } else {
166 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
167 res->Data.Memory32.MinBaseAddress,
168 res->Data.Memory32.MaxBaseAddress,
169 res->Data.Memory32.RangeLength));
170 set->set_memoryrange(dev, context,
171 res->Data.Memory32.MinBaseAddress,
172 res->Data.Memory32.MaxBaseAddress,
173 res->Data.Memory32.RangeLength,
174 res->Data.Memory32.Alignment);
175 }
176 break;
177
178 case ACPI_RSTYPE_MEM24:
179 if (res->Data.Memory24.RangeLength <= 0)
180 break;
181 if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) {
182 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
183 res->Data.Memory24.MinBaseAddress,
184 res->Data.Memory24.RangeLength));
185 set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
186 res->Data.Memory24.RangeLength);
187 } else {
188 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
189 res->Data.Memory24.MinBaseAddress,
190 res->Data.Memory24.MaxBaseAddress,
191 res->Data.Memory24.RangeLength));
192 set->set_memoryrange(dev, context,
193 res->Data.Memory24.MinBaseAddress,
194 res->Data.Memory24.MaxBaseAddress,
195 res->Data.Memory24.RangeLength,
196 res->Data.Memory24.Alignment);
197 }
198 break;
199
200 case ACPI_RSTYPE_IRQ:
201 /*
202 * from 1.0b 6.4.2
203 * "This structure is repeated for each separate interrupt
204 * required"
205 */
206 set->set_irq(dev, context, res->Data.Irq.Interrupts,
207 res->Data.Irq.NumberOfInterrupts);
208 break;
209
210 case ACPI_RSTYPE_DMA:
211 /*
212 * from 1.0b 6.4.3
213 * "This structure is repeated for each separate dma channel
214 * required"
215 */
216
217 set->set_drq(dev, context, res->Data.Dma.Channels,
218 res->Data.Dma.NumberOfChannels);
219 break;
220
221 case ACPI_RSTYPE_START_DPF:
222 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
223 set->set_start_dependant(dev, context,
224 res->Data.StartDpf.CompatibilityPriority);
225 break;
226
227 case ACPI_RSTYPE_END_DPF:
228 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
229 set->set_end_dependant(dev, context);
230 break;
231
232 case ACPI_RSTYPE_ADDRESS32:
233 if (res->Data.Address32.AddressLength <= 0)
234 break;
234 if (res->Data.Address32.ProducerConsumer != CONSUMER) {
235 if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
235 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n",
236 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n",
236 (res->Data.Address32.ResourceType == IO_RANGE) ?
237 (res->Data.Address32.ResourceType == ACPI_IO_RANGE) ?
237 "IO" : "Memory"));
238 break;
239 }
238 "IO" : "Memory"));
239 break;
240 }
240 if ((res->Data.Address32.ResourceType != MEMORY_RANGE) ||
241 (res->Data.Address32.ResourceType != IO_RANGE)) {
241 if ((res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE) ||
242 (res->Data.Address32.ResourceType != ACPI_IO_RANGE)) {
242 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
243 "ignored Address32 for non-memory, non-I/O\n"));
244 break;
245 }
246
243 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
244 "ignored Address32 for non-memory, non-I/O\n"));
245 break;
246 }
247
247 if ((res->Data.Address32.MinAddressFixed == ADDRESS_FIXED) &&
248 (res->Data.Address32.MaxAddressFixed == ADDRESS_FIXED)) {
249 if (res->Data.Address32.ResourceType == MEMORY_RANGE) {
248 if ((res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED) &&
249 (res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)) {
250 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
250 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n",
251 res->Data.Address32.MinAddressRange,
252 res->Data.Address32.AddressLength));
253 set->set_memory(dev, context,
254 res->Data.Address32.MinAddressRange,
255 res->Data.Address32.AddressLength);
256 } else {
257 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n",
258 res->Data.Address32.MinAddressRange,
259 res->Data.Address32.AddressLength));
260 set->set_ioport(dev, context,
261 res->Data.Address32.MinAddressRange,
262 res->Data.Address32.AddressLength);
263 }
264 } else {
251 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n",
252 res->Data.Address32.MinAddressRange,
253 res->Data.Address32.AddressLength));
254 set->set_memory(dev, context,
255 res->Data.Address32.MinAddressRange,
256 res->Data.Address32.AddressLength);
257 } else {
258 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n",
259 res->Data.Address32.MinAddressRange,
260 res->Data.Address32.AddressLength));
261 set->set_ioport(dev, context,
262 res->Data.Address32.MinAddressRange,
263 res->Data.Address32.AddressLength);
264 }
265 } else {
265 if (res->Data.Address32.ResourceType == MEMORY_RANGE) {
266 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
266 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n",
267 res->Data.Address32.MinAddressRange,
268 res->Data.Address32.MaxAddressRange,
269 res->Data.Address32.AddressLength));
270 set->set_memoryrange(dev, context,
271 res->Data.Address32.MinAddressRange,
272 res->Data.Address32.MaxAddressRange,
273 res->Data.Address32.AddressLength,
274 res->Data.Address32.Granularity);
275 } else {
276 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n",
277 res->Data.Address32.MinAddressRange,
278 res->Data.Address32.MaxAddressRange,
279 res->Data.Address32.AddressLength));
280 set->set_iorange(dev, context,
281 res->Data.Address32.MinAddressRange,
282 res->Data.Address32.MaxAddressRange,
283 res->Data.Address32.AddressLength,
284 res->Data.Address32.Granularity);
285 }
286 }
287 break;
288
289 case ACPI_RSTYPE_ADDRESS16:
290 if (res->Data.Address16.AddressLength <= 0)
291 break;
267 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n",
268 res->Data.Address32.MinAddressRange,
269 res->Data.Address32.MaxAddressRange,
270 res->Data.Address32.AddressLength));
271 set->set_memoryrange(dev, context,
272 res->Data.Address32.MinAddressRange,
273 res->Data.Address32.MaxAddressRange,
274 res->Data.Address32.AddressLength,
275 res->Data.Address32.Granularity);
276 } else {
277 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n",
278 res->Data.Address32.MinAddressRange,
279 res->Data.Address32.MaxAddressRange,
280 res->Data.Address32.AddressLength));
281 set->set_iorange(dev, context,
282 res->Data.Address32.MinAddressRange,
283 res->Data.Address32.MaxAddressRange,
284 res->Data.Address32.AddressLength,
285 res->Data.Address32.Granularity);
286 }
287 }
288 break;
289
290 case ACPI_RSTYPE_ADDRESS16:
291 if (res->Data.Address16.AddressLength <= 0)
292 break;
292 if (res->Data.Address16.ProducerConsumer != CONSUMER) {
293 if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
293 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n",
294 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n",
294 (res->Data.Address16.ResourceType == IO_RANGE) ?
295 (res->Data.Address16.ResourceType == ACPI_IO_RANGE) ?
295 "IO" : "Memory"));
296 break;
297 }
296 "IO" : "Memory"));
297 break;
298 }
298 if ((res->Data.Address16.ResourceType != MEMORY_RANGE) ||
299 (res->Data.Address16.ResourceType != IO_RANGE)) {
299 if ((res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE) ||
300 (res->Data.Address16.ResourceType != ACPI_IO_RANGE)) {
300 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
301 "ignored Address16 for non-memory, non-I/O\n"));
302 break;
303 }
304
301 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
302 "ignored Address16 for non-memory, non-I/O\n"));
303 break;
304 }
305
305 if ((res->Data.Address16.MinAddressFixed == ADDRESS_FIXED) &&
306 (res->Data.Address16.MaxAddressFixed == ADDRESS_FIXED)) {
307 if (res->Data.Address16.ResourceType == MEMORY_RANGE) {
306 if ((res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED) &&
307 (res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED)) {
308 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
308 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x/%d\n",
309 res->Data.Address16.MinAddressRange,
310 res->Data.Address16.AddressLength));
311 set->set_memory(dev, context,
312 res->Data.Address16.MinAddressRange,
313 res->Data.Address16.AddressLength);
314 } else {
315 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x/%d\n",
316 res->Data.Address16.MinAddressRange,
317 res->Data.Address16.AddressLength));
318 set->set_ioport(dev, context,
319 res->Data.Address16.MinAddressRange,
320 res->Data.Address16.AddressLength);
321 }
322 } else {
309 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x/%d\n",
310 res->Data.Address16.MinAddressRange,
311 res->Data.Address16.AddressLength));
312 set->set_memory(dev, context,
313 res->Data.Address16.MinAddressRange,
314 res->Data.Address16.AddressLength);
315 } else {
316 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x/%d\n",
317 res->Data.Address16.MinAddressRange,
318 res->Data.Address16.AddressLength));
319 set->set_ioport(dev, context,
320 res->Data.Address16.MinAddressRange,
321 res->Data.Address16.AddressLength);
322 }
323 } else {
323 if (res->Data.Address16.ResourceType == MEMORY_RANGE) {
324 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
324 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x-0x%x/%d\n",
325 res->Data.Address16.MinAddressRange,
326 res->Data.Address16.MaxAddressRange,
327 res->Data.Address16.AddressLength));
328 set->set_memoryrange(dev, context,
329 res->Data.Address16.MinAddressRange,
330 res->Data.Address16.MaxAddressRange,
331 res->Data.Address16.AddressLength,
332 res->Data.Address16.Granularity);
333 } else {
334 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x-0x%x/%d\n",
335 res->Data.Address16.MinAddressRange,
336 res->Data.Address16.MaxAddressRange,
337 res->Data.Address16.AddressLength));
338 set->set_iorange(dev, context,
339 res->Data.Address16.MinAddressRange,
340 res->Data.Address16.MaxAddressRange,
341 res->Data.Address16.AddressLength,
342 res->Data.Address16.Granularity);
343 }
344 }
345 break;
346
347 case ACPI_RSTYPE_ADDRESS64:
348 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n"));
349 break;
350
351 case ACPI_RSTYPE_EXT_IRQ:
352 /* XXX special handling? */
353 set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
354 res->Data.ExtendedIrq.NumberOfInterrupts);
355 break;
356
357 case ACPI_RSTYPE_VENDOR:
358 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n"));
359 break;
360 default:
361 break;
362 }
363 }
364 AcpiOsFree(buf.Pointer);
365 set->set_done(dev, context);
366 return_ACPI_STATUS(AE_OK);
367}
368
369/*
370 * Resource-set vectors used to attach _CRS-derived resources
371 * to an ACPI device.
372 */
373static void acpi_res_set_init(device_t dev, void **context);
374static void acpi_res_set_done(device_t dev, void *context);
375static void acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
376static void acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
377 u_int32_t length, u_int32_t align);
378static void acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
379static void acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
380 u_int32_t length, u_int32_t align);
381static void acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
382 int count);
383static void acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
384 int count);
385static void acpi_res_set_start_dependant(device_t dev, void *context, int preference);
386static void acpi_res_set_end_dependant(device_t dev, void *context);
387
388struct acpi_parse_resource_set acpi_res_parse_set = {
389 acpi_res_set_init,
390 acpi_res_set_done,
391 acpi_res_set_ioport,
392 acpi_res_set_iorange,
393 acpi_res_set_memory,
394 acpi_res_set_memoryrange,
395 acpi_res_set_irq,
396 acpi_res_set_drq,
397 acpi_res_set_start_dependant,
398 acpi_res_set_end_dependant
399};
400
401struct acpi_res_context {
402 int ar_nio;
403 int ar_nmem;
404 int ar_nirq;
405 int ar_ndrq;
406};
407
408static void
409acpi_res_set_init(device_t dev, void **context)
410{
411 struct acpi_res_context *cp;
412
413 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
414 bzero(cp, sizeof(*cp));
415 *context = cp;
416 }
417}
418
419static void
420acpi_res_set_done(device_t dev, void *context)
421{
422 struct acpi_res_context *cp = (struct acpi_res_context *)context;
423
424 if (cp == NULL)
425 return;
426 AcpiOsFree(cp);
427}
428
429static void
430acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length)
431{
432 struct acpi_res_context *cp = (struct acpi_res_context *)context;
433
434 if (cp == NULL)
435 return;
436 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
437}
438
439static void
440acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
441{
442 struct acpi_res_context *cp = (struct acpi_res_context *)context;
443
444 if (cp == NULL)
445 return;
446 device_printf(dev, "I/O range not supported\n");
447}
448
449static void
450acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length)
451{
452 struct acpi_res_context *cp = (struct acpi_res_context *)context;
453
454 if (cp == NULL)
455 return;
456
457 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
458}
459
460static void
461acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
462{
463 struct acpi_res_context *cp = (struct acpi_res_context *)context;
464
465 if (cp == NULL)
466 return;
467 device_printf(dev, "memory range not supported\n");
468}
469
470static void
471acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count)
472{
473 struct acpi_res_context *cp = (struct acpi_res_context *)context;
474
475 if (cp == NULL)
476 return;
477 if (irq == NULL)
478 return;
479
480 /*This implements no resource relocation.*/
481 if(count != 1)
482 return;
483
484 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
485}
486
487static void
488acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
489{
490 struct acpi_res_context *cp = (struct acpi_res_context *)context;
491
492 if (cp == NULL)
493 return;
494 if (drq == NULL)
495 return;
496
497 /*This implements no resource relocation.*/
498 if(count != 1)
499 return;
500
501 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
502}
503
504static void
505acpi_res_set_start_dependant(device_t dev, void *context, int preference)
506{
507 struct acpi_res_context *cp = (struct acpi_res_context *)context;
508
509 if (cp == NULL)
510 return;
511 device_printf(dev, "dependant functions not supported\n");
512}
513
514static void
515acpi_res_set_end_dependant(device_t dev, void *context)
516{
517 struct acpi_res_context *cp = (struct acpi_res_context *)context;
518
519 if (cp == NULL)
520 return;
521}
522
523/*
524 * Resource-owning placeholders.
525 *
526 * This code "owns" system resource objects that aren't
527 * otherwise useful to devices, and which shouldn't be
528 * considered "free".
529 *
530 * Note that some systems claim *all* of the physical address space
531 * with a PNP0C01 device, so we cannot correctly "own" system memory
532 * here (must be done in the SMAP handler on x86 systems, for
533 * example).
534 */
535
536static int acpi_sysresource_probe(device_t dev);
537static int acpi_sysresource_attach(device_t dev);
538
539static device_method_t acpi_sysresource_methods[] = {
540 /* Device interface */
541 DEVMETHOD(device_probe, acpi_sysresource_probe),
542 DEVMETHOD(device_attach, acpi_sysresource_attach),
543
544 {0, 0}
545};
546
547static driver_t acpi_sysresource_driver = {
548 "acpi_sysresource",
549 acpi_sysresource_methods,
550 0,
551};
552
553static devclass_t acpi_sysresource_devclass;
554DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0);
555
556static int
557acpi_sysresource_probe(device_t dev)
558{
559 if (acpi_disabled("sysresource"))
560 return(ENXIO);
561 if (acpi_MatchHid(dev, "PNP0C02")) {
562 device_set_desc(dev, "system resource");
563 } else {
564 return(ENXIO);
565 }
566 device_quiet(dev);
567 return(-100);
568}
569
570static int
571acpi_sysresource_attach(device_t dev)
572{
573 struct resource *res;
574 int i, rid;
575
576 /*
577 * Suck up all the resources that might have been assigned to us.
578 * Note that it's impossible to tell the difference between a
579 * resource that someone else has claimed, and one that doesn't
580 * exist.
581 */
582 for (i = 0; i < 100; i++) {
583 rid = i;
584 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
585 rid = i;
586 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
587 rid = i;
588 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE);
589 }
590 return(0);
591}
325 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x-0x%x/%d\n",
326 res->Data.Address16.MinAddressRange,
327 res->Data.Address16.MaxAddressRange,
328 res->Data.Address16.AddressLength));
329 set->set_memoryrange(dev, context,
330 res->Data.Address16.MinAddressRange,
331 res->Data.Address16.MaxAddressRange,
332 res->Data.Address16.AddressLength,
333 res->Data.Address16.Granularity);
334 } else {
335 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x-0x%x/%d\n",
336 res->Data.Address16.MinAddressRange,
337 res->Data.Address16.MaxAddressRange,
338 res->Data.Address16.AddressLength));
339 set->set_iorange(dev, context,
340 res->Data.Address16.MinAddressRange,
341 res->Data.Address16.MaxAddressRange,
342 res->Data.Address16.AddressLength,
343 res->Data.Address16.Granularity);
344 }
345 }
346 break;
347
348 case ACPI_RSTYPE_ADDRESS64:
349 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n"));
350 break;
351
352 case ACPI_RSTYPE_EXT_IRQ:
353 /* XXX special handling? */
354 set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
355 res->Data.ExtendedIrq.NumberOfInterrupts);
356 break;
357
358 case ACPI_RSTYPE_VENDOR:
359 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n"));
360 break;
361 default:
362 break;
363 }
364 }
365 AcpiOsFree(buf.Pointer);
366 set->set_done(dev, context);
367 return_ACPI_STATUS(AE_OK);
368}
369
370/*
371 * Resource-set vectors used to attach _CRS-derived resources
372 * to an ACPI device.
373 */
374static void acpi_res_set_init(device_t dev, void **context);
375static void acpi_res_set_done(device_t dev, void *context);
376static void acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
377static void acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
378 u_int32_t length, u_int32_t align);
379static void acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
380static void acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
381 u_int32_t length, u_int32_t align);
382static void acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
383 int count);
384static void acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
385 int count);
386static void acpi_res_set_start_dependant(device_t dev, void *context, int preference);
387static void acpi_res_set_end_dependant(device_t dev, void *context);
388
389struct acpi_parse_resource_set acpi_res_parse_set = {
390 acpi_res_set_init,
391 acpi_res_set_done,
392 acpi_res_set_ioport,
393 acpi_res_set_iorange,
394 acpi_res_set_memory,
395 acpi_res_set_memoryrange,
396 acpi_res_set_irq,
397 acpi_res_set_drq,
398 acpi_res_set_start_dependant,
399 acpi_res_set_end_dependant
400};
401
402struct acpi_res_context {
403 int ar_nio;
404 int ar_nmem;
405 int ar_nirq;
406 int ar_ndrq;
407};
408
409static void
410acpi_res_set_init(device_t dev, void **context)
411{
412 struct acpi_res_context *cp;
413
414 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
415 bzero(cp, sizeof(*cp));
416 *context = cp;
417 }
418}
419
420static void
421acpi_res_set_done(device_t dev, void *context)
422{
423 struct acpi_res_context *cp = (struct acpi_res_context *)context;
424
425 if (cp == NULL)
426 return;
427 AcpiOsFree(cp);
428}
429
430static void
431acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length)
432{
433 struct acpi_res_context *cp = (struct acpi_res_context *)context;
434
435 if (cp == NULL)
436 return;
437 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
438}
439
440static void
441acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
442{
443 struct acpi_res_context *cp = (struct acpi_res_context *)context;
444
445 if (cp == NULL)
446 return;
447 device_printf(dev, "I/O range not supported\n");
448}
449
450static void
451acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length)
452{
453 struct acpi_res_context *cp = (struct acpi_res_context *)context;
454
455 if (cp == NULL)
456 return;
457
458 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
459}
460
461static void
462acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
463{
464 struct acpi_res_context *cp = (struct acpi_res_context *)context;
465
466 if (cp == NULL)
467 return;
468 device_printf(dev, "memory range not supported\n");
469}
470
471static void
472acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count)
473{
474 struct acpi_res_context *cp = (struct acpi_res_context *)context;
475
476 if (cp == NULL)
477 return;
478 if (irq == NULL)
479 return;
480
481 /*This implements no resource relocation.*/
482 if(count != 1)
483 return;
484
485 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
486}
487
488static void
489acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
490{
491 struct acpi_res_context *cp = (struct acpi_res_context *)context;
492
493 if (cp == NULL)
494 return;
495 if (drq == NULL)
496 return;
497
498 /*This implements no resource relocation.*/
499 if(count != 1)
500 return;
501
502 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
503}
504
505static void
506acpi_res_set_start_dependant(device_t dev, void *context, int preference)
507{
508 struct acpi_res_context *cp = (struct acpi_res_context *)context;
509
510 if (cp == NULL)
511 return;
512 device_printf(dev, "dependant functions not supported\n");
513}
514
515static void
516acpi_res_set_end_dependant(device_t dev, void *context)
517{
518 struct acpi_res_context *cp = (struct acpi_res_context *)context;
519
520 if (cp == NULL)
521 return;
522}
523
524/*
525 * Resource-owning placeholders.
526 *
527 * This code "owns" system resource objects that aren't
528 * otherwise useful to devices, and which shouldn't be
529 * considered "free".
530 *
531 * Note that some systems claim *all* of the physical address space
532 * with a PNP0C01 device, so we cannot correctly "own" system memory
533 * here (must be done in the SMAP handler on x86 systems, for
534 * example).
535 */
536
537static int acpi_sysresource_probe(device_t dev);
538static int acpi_sysresource_attach(device_t dev);
539
540static device_method_t acpi_sysresource_methods[] = {
541 /* Device interface */
542 DEVMETHOD(device_probe, acpi_sysresource_probe),
543 DEVMETHOD(device_attach, acpi_sysresource_attach),
544
545 {0, 0}
546};
547
548static driver_t acpi_sysresource_driver = {
549 "acpi_sysresource",
550 acpi_sysresource_methods,
551 0,
552};
553
554static devclass_t acpi_sysresource_devclass;
555DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0);
556
557static int
558acpi_sysresource_probe(device_t dev)
559{
560 if (acpi_disabled("sysresource"))
561 return(ENXIO);
562 if (acpi_MatchHid(dev, "PNP0C02")) {
563 device_set_desc(dev, "system resource");
564 } else {
565 return(ENXIO);
566 }
567 device_quiet(dev);
568 return(-100);
569}
570
571static int
572acpi_sysresource_attach(device_t dev)
573{
574 struct resource *res;
575 int i, rid;
576
577 /*
578 * Suck up all the resources that might have been assigned to us.
579 * Note that it's impossible to tell the difference between a
580 * resource that someone else has claimed, and one that doesn't
581 * exist.
582 */
583 for (i = 0; i < 100; i++) {
584 rid = i;
585 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
586 rid = i;
587 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
588 rid = i;
589 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE);
590 }
591 return(0);
592}