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
28 #include <sys/cdefs.h>
29 #include "opt_acpi.h"
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/bus.h>
33 #include <sys/limits.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36
37 #if defined(__i386__) || defined(__amd64__)
38 #include <machine/pci_cfgreg.h>
39 #endif
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/rman.h>
43
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46
47 #include <dev/acpica/acpivar.h>
48
49 #ifdef INTRNG
50 #include "acpi_bus_if.h"
51 #endif
52
53 /* Hooks for the ACPI CA debugging infrastructure */
54 #define _COMPONENT ACPI_BUS
55 ACPI_MODULE_NAME("RESOURCE")
56
57 struct lookup_irq_request {
58 ACPI_RESOURCE *acpi_res;
59 u_int irq;
60 int counter;
61 int rid;
62 int found;
63 int checkrid;
64 int trig;
65 int pol;
66 };
67
68 static char *pcilink_ids[] = { "PNP0C0F", NULL };
69
70 static ACPI_STATUS
acpi_lookup_irq_handler(ACPI_RESOURCE * res,void * context)71 acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
72 {
73 struct lookup_irq_request *req;
74 size_t len;
75 u_int irqnum, irq, trig, pol;
76
77 switch (res->Type) {
78 case ACPI_RESOURCE_TYPE_IRQ:
79 irqnum = res->Data.Irq.InterruptCount;
80 irq = res->Data.Irq.Interrupts[0];
81 len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
82 trig = res->Data.Irq.Triggering;
83 pol = res->Data.Irq.Polarity;
84 break;
85 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
86 irqnum = res->Data.ExtendedIrq.InterruptCount;
87 irq = res->Data.ExtendedIrq.Interrupts[0];
88 len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
89 trig = res->Data.ExtendedIrq.Triggering;
90 pol = res->Data.ExtendedIrq.Polarity;
91 break;
92 default:
93 return (AE_OK);
94 }
95 if (irqnum != 1)
96 return (AE_OK);
97 req = (struct lookup_irq_request *)context;
98 if (req->checkrid) {
99 if (req->counter != req->rid) {
100 req->counter++;
101 return (AE_OK);
102 }
103 KASSERT(irq == req->irq, ("IRQ resources do not match"));
104 } else {
105 if (req->irq != irq)
106 return (AE_OK);
107 }
108 req->found = 1;
109 req->pol = pol;
110 req->trig = trig;
111 if (req->acpi_res != NULL)
112 bcopy(res, req->acpi_res, len);
113 return (AE_CTRL_TERMINATE);
114 }
115
116 ACPI_STATUS
acpi_lookup_irq_resource(device_t dev,int rid,struct resource * res,ACPI_RESOURCE * acpi_res)117 acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res,
118 ACPI_RESOURCE *acpi_res)
119 {
120 struct lookup_irq_request req;
121 ACPI_STATUS status;
122
123 req.acpi_res = acpi_res;
124 req.irq = rman_get_start(res);
125 req.counter = 0;
126 req.rid = rid;
127 req.found = 0;
128 req.checkrid = 1;
129 status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
130 acpi_lookup_irq_handler, &req);
131 if (ACPI_SUCCESS(status) && req.found == 0)
132 status = AE_NOT_FOUND;
133 return (status);
134 }
135
136 void
acpi_config_intr(device_t dev,ACPI_RESOURCE * res)137 acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
138 {
139 u_int irq;
140 int pol, trig;
141
142 switch (res->Type) {
143 case ACPI_RESOURCE_TYPE_IRQ:
144 KASSERT(res->Data.Irq.InterruptCount == 1,
145 ("%s: multiple interrupts", __func__));
146 irq = res->Data.Irq.Interrupts[0];
147 trig = res->Data.Irq.Triggering;
148 pol = res->Data.Irq.Polarity;
149 break;
150 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
151 KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
152 ("%s: multiple interrupts", __func__));
153 irq = res->Data.ExtendedIrq.Interrupts[0];
154 trig = res->Data.ExtendedIrq.Triggering;
155 pol = res->Data.ExtendedIrq.Polarity;
156 break;
157 default:
158 panic("%s: bad resource type %u", __func__, res->Type);
159 }
160
161 #if defined(__amd64__) || defined(__i386__)
162 /*
163 * XXX: Certain BIOSes have buggy AML that specify an IRQ that is
164 * edge-sensitive and active-lo. However, edge-sensitive IRQs
165 * should be active-hi. Force IRQs with an ISA IRQ value to be
166 * active-hi instead.
167 */
168 if (irq < 16 && trig == ACPI_EDGE_SENSITIVE && pol == ACPI_ACTIVE_LOW)
169 pol = ACPI_ACTIVE_HIGH;
170 #endif
171 BUS_CONFIG_INTR(dev, irq, (trig == ACPI_EDGE_SENSITIVE) ?
172 INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
173 INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
174 }
175
176 #ifdef INTRNG
177 int
acpi_map_intr(device_t dev,u_int irq,ACPI_HANDLE handle)178 acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle)
179 {
180 struct lookup_irq_request req;
181 int trig, pol;
182
183 trig = ACPI_LEVEL_SENSITIVE;
184 pol = ACPI_ACTIVE_HIGH;
185 if (handle != NULL) {
186 req.found = 0;
187 req.acpi_res = NULL;
188 req.irq = irq;
189 req.counter = 0;
190 req.rid = 0;
191 req.checkrid = 0;
192 AcpiWalkResources(handle, "_CRS", acpi_lookup_irq_handler, &req);
193 if (req.found != 0) {
194 trig = req.trig;
195 pol = req.pol;
196 }
197 }
198 return ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, irq,
199 (trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
200 (pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
201 }
202 #endif
203
204 struct acpi_resource_context {
205 struct acpi_parse_resource_set *set;
206 device_t dev;
207 void *context;
208 bool ignore_producer_flag;
209 };
210
211 #ifdef ACPI_DEBUG_OUTPUT
212 static const char *
acpi_address_range_name(UINT8 ResourceType)213 acpi_address_range_name(UINT8 ResourceType)
214 {
215 static char buf[16];
216
217 switch (ResourceType) {
218 case ACPI_MEMORY_RANGE:
219 return ("Memory");
220 case ACPI_IO_RANGE:
221 return ("IO");
222 case ACPI_BUS_NUMBER_RANGE:
223 return ("Bus Number");
224 default:
225 snprintf(buf, sizeof(buf), "type %u", ResourceType);
226 return (buf);
227 }
228 }
229 #endif
230
231 static ACPI_STATUS
acpi_parse_resource(ACPI_RESOURCE * res,void * context)232 acpi_parse_resource(ACPI_RESOURCE *res, void *context)
233 {
234 struct acpi_parse_resource_set *set;
235 struct acpi_resource_context *arc;
236 UINT64 min, max, length, gran;
237 #ifdef ACPI_DEBUG
238 const char *name;
239 #endif
240 device_t dev;
241
242 arc = context;
243 dev = arc->dev;
244 set = arc->set;
245
246 switch (res->Type) {
247 case ACPI_RESOURCE_TYPE_END_TAG:
248 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
249 break;
250 case ACPI_RESOURCE_TYPE_FIXED_IO:
251 if (res->Data.FixedIo.AddressLength <= 0)
252 break;
253 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
254 res->Data.FixedIo.Address, res->Data.FixedIo.AddressLength));
255 set->set_ioport(dev, arc->context, res->Data.FixedIo.Address,
256 res->Data.FixedIo.AddressLength);
257 break;
258 case ACPI_RESOURCE_TYPE_IO:
259 if (res->Data.Io.AddressLength <= 0)
260 break;
261 if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
262 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
263 res->Data.Io.Minimum, res->Data.Io.AddressLength));
264 set->set_ioport(dev, arc->context, res->Data.Io.Minimum,
265 res->Data.Io.AddressLength);
266 } else {
267 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
268 res->Data.Io.Minimum, res->Data.Io.Maximum,
269 res->Data.Io.AddressLength));
270 set->set_iorange(dev, arc->context, res->Data.Io.Minimum,
271 res->Data.Io.Maximum, res->Data.Io.AddressLength,
272 res->Data.Io.Alignment);
273 }
274 break;
275 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
276 if (res->Data.FixedMemory32.AddressLength <= 0)
277 break;
278 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
279 res->Data.FixedMemory32.Address,
280 res->Data.FixedMemory32.AddressLength));
281 set->set_memory(dev, arc->context, res->Data.FixedMemory32.Address,
282 res->Data.FixedMemory32.AddressLength);
283 break;
284 case ACPI_RESOURCE_TYPE_MEMORY32:
285 if (res->Data.Memory32.AddressLength <= 0)
286 break;
287 if (res->Data.Memory32.Minimum == res->Data.Memory32.Maximum) {
288 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
289 res->Data.Memory32.Minimum, res->Data.Memory32.AddressLength));
290 set->set_memory(dev, arc->context, res->Data.Memory32.Minimum,
291 res->Data.Memory32.AddressLength);
292 } else {
293 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
294 res->Data.Memory32.Minimum, res->Data.Memory32.Maximum,
295 res->Data.Memory32.AddressLength));
296 set->set_memoryrange(dev, arc->context, res->Data.Memory32.Minimum,
297 res->Data.Memory32.Maximum, res->Data.Memory32.AddressLength,
298 res->Data.Memory32.Alignment);
299 }
300 break;
301 case ACPI_RESOURCE_TYPE_MEMORY24:
302 if (res->Data.Memory24.AddressLength <= 0)
303 break;
304 if (res->Data.Memory24.Minimum == res->Data.Memory24.Maximum) {
305 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
306 res->Data.Memory24.Minimum, res->Data.Memory24.AddressLength));
307 set->set_memory(dev, arc->context, res->Data.Memory24.Minimum,
308 res->Data.Memory24.AddressLength);
309 } else {
310 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
311 res->Data.Memory24.Minimum, res->Data.Memory24.Maximum,
312 res->Data.Memory24.AddressLength));
313 set->set_memoryrange(dev, arc->context, res->Data.Memory24.Minimum,
314 res->Data.Memory24.Maximum, res->Data.Memory24.AddressLength,
315 res->Data.Memory24.Alignment);
316 }
317 break;
318 case ACPI_RESOURCE_TYPE_IRQ:
319 /*
320 * from 1.0b 6.4.2
321 * "This structure is repeated for each separate interrupt
322 * required"
323 */
324 set->set_irq(dev, arc->context, res->Data.Irq.Interrupts,
325 res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
326 res->Data.Irq.Polarity);
327 break;
328 case ACPI_RESOURCE_TYPE_DMA:
329 /*
330 * from 1.0b 6.4.3
331 * "This structure is repeated for each separate DMA channel
332 * required"
333 */
334 set->set_drq(dev, arc->context, res->Data.Dma.Channels,
335 res->Data.Dma.ChannelCount);
336 break;
337 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
338 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
339 set->set_start_dependent(dev, arc->context,
340 res->Data.StartDpf.CompatibilityPriority);
341 break;
342 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
343 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
344 set->set_end_dependent(dev, arc->context);
345 break;
346 case ACPI_RESOURCE_TYPE_ADDRESS16:
347 case ACPI_RESOURCE_TYPE_ADDRESS32:
348 case ACPI_RESOURCE_TYPE_ADDRESS64:
349 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
350 switch (res->Type) {
351 case ACPI_RESOURCE_TYPE_ADDRESS16:
352 gran = res->Data.Address16.Address.Granularity;
353 min = res->Data.Address16.Address.Minimum;
354 max = res->Data.Address16.Address.Maximum;
355 length = res->Data.Address16.Address.AddressLength;
356 #ifdef ACPI_DEBUG
357 name = "Address16";
358 #endif
359 break;
360 case ACPI_RESOURCE_TYPE_ADDRESS32:
361 gran = res->Data.Address32.Address.Granularity;
362 min = res->Data.Address32.Address.Minimum;
363 max = res->Data.Address32.Address.Maximum;
364 length = res->Data.Address32.Address.AddressLength;
365 #ifdef ACPI_DEBUG
366 name = "Address32";
367 #endif
368 break;
369 case ACPI_RESOURCE_TYPE_ADDRESS64:
370 gran = res->Data.Address64.Address.Granularity;
371 min = res->Data.Address64.Address.Minimum;
372 max = res->Data.Address64.Address.Maximum;
373 length = res->Data.Address64.Address.AddressLength;
374 #ifdef ACPI_DEBUG
375 name = "Address64";
376 #endif
377 break;
378 default:
379 KASSERT(res->Type == ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
380 ("should never happen"));
381 gran = res->Data.ExtAddress64.Address.Granularity;
382 min = res->Data.ExtAddress64.Address.Minimum;
383 max = res->Data.ExtAddress64.Address.Maximum;
384 length = res->Data.ExtAddress64.Address.AddressLength;
385 #ifdef ACPI_DEBUG
386 name = "ExtAddress64";
387 #endif
388 break;
389 }
390 if (length <= 0)
391 break;
392 if (!arc->ignore_producer_flag &&
393 res->Data.Address.ProducerConsumer != ACPI_CONSUMER) {
394 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
395 "ignored %s %s producer\n", name,
396 acpi_address_range_name(res->Data.Address.ResourceType)));
397 break;
398 }
399 if (res->Data.Address.ResourceType != ACPI_MEMORY_RANGE &&
400 res->Data.Address.ResourceType != ACPI_IO_RANGE) {
401 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
402 "ignored %s for non-memory, non-I/O\n", name));
403 break;
404 }
405
406 #ifdef __i386__
407 if (min > ULONG_MAX || (res->Data.Address.MaxAddressFixed && max >
408 ULONG_MAX)) {
409 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored %s above 4G\n",
410 name));
411 break;
412 }
413 if (max > ULONG_MAX)
414 max = ULONG_MAX;
415 #endif
416 if (res->Data.Address.MinAddressFixed == ACPI_ADDRESS_FIXED &&
417 res->Data.Address.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
418 if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) {
419 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%jx/%ju\n",
420 name, (uintmax_t)min, (uintmax_t)length));
421 set->set_memory(dev, arc->context, min, length);
422 } else {
423 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx/%ju\n", name,
424 (uintmax_t)min, (uintmax_t)length));
425 set->set_ioport(dev, arc->context, min, length);
426 }
427 } else if (res->Data.Address.MinAddressFixed != ACPI_ADDRESS_FIXED &&
428 res->Data.Address.MaxAddressFixed != ACPI_ADDRESS_FIXED) {
429 /* Fixed size, variable location resource descriptor */
430 min = roundup(min, gran + 1);
431 if ((min + length - 1) > max) {
432 device_printf(dev,
433 "invalid memory range: start: %jx end: %jx max: %jx\n",
434 (uintmax_t)min, (uintmax_t)(min + length - 1),
435 (uintmax_t)max);
436 } else {
437 if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) {
438 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
439 "%s/Memory 0x%jx/%ju\n", name, (uintmax_t)min,
440 (uintmax_t)length));
441 set->set_memory(dev, arc->context, min, length);
442 } else {
443 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx/%ju\n",
444 name, (uintmax_t)min, (uintmax_t)length));
445 set->set_ioport(dev, arc->context, min, length);
446 }
447 }
448 } else {
449 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
450 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
451 "%s/Memory 0x%jx-0x%jx/%ju\n", name, (uintmax_t)min,
452 (uintmax_t)max, (uintmax_t)length));
453 set->set_memoryrange(dev, arc->context, min, max, length, gran);
454 } else {
455 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx-0x%jx/%ju\n",
456 name, (uintmax_t)min, (uintmax_t)max, (uintmax_t)length));
457 set->set_iorange(dev, arc->context, min, max, length, gran);
458 }
459 }
460 break;
461 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
462 if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
463 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored ExtIRQ producer\n"));
464 break;
465 }
466 set->set_ext_irq(dev, arc->context, res->Data.ExtendedIrq.Interrupts,
467 res->Data.ExtendedIrq.InterruptCount,
468 res->Data.ExtendedIrq.Triggering, res->Data.ExtendedIrq.Polarity);
469 break;
470 case ACPI_RESOURCE_TYPE_VENDOR:
471 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
472 "unimplemented VendorSpecific resource\n"));
473 break;
474 default:
475 break;
476 }
477 return (AE_OK);
478 }
479
480 /*
481 * Fetch a device's resources and associate them with the device.
482 *
483 * Note that it might be nice to also locate ACPI-specific resource items, such
484 * as GPE bits.
485 *
486 * We really need to split the resource-fetching code out from the
487 * resource-parsing code, since we may want to use the parsing
488 * code for _PRS someday.
489 */
490 ACPI_STATUS
acpi_parse_resources(device_t dev,ACPI_HANDLE handle,struct acpi_parse_resource_set * set,void * arg)491 acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
492 struct acpi_parse_resource_set *set, void *arg)
493 {
494 struct acpi_resource_context arc;
495 ACPI_STATUS status;
496
497 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
498
499 set->set_init(dev, arg, &arc.context);
500 arc.set = set;
501 arc.dev = dev;
502 arc.ignore_producer_flag = false;
503
504 /*
505 * UARTs on ThunderX2 set ResourceProducer on memory resources, with
506 * 7.2 firmware.
507 */
508 if (acpi_MatchHid(handle, "ARMH0011") != ACPI_MATCHHID_NOMATCH)
509 arc.ignore_producer_flag = true;
510
511 /*
512 * ARM Coresight on N1SDP set ResourceProducer on memory resources.
513 * Coresight devices: ETM, STM, TPIU, ETF/ETR, REP, FUN.
514 */
515 if (acpi_MatchHid(handle, "ARMHC500") != ACPI_MATCHHID_NOMATCH ||
516 acpi_MatchHid(handle, "ARMHC502") != ACPI_MATCHHID_NOMATCH ||
517 acpi_MatchHid(handle, "ARMHC600") != ACPI_MATCHHID_NOMATCH ||
518 acpi_MatchHid(handle, "ARMHC979") != ACPI_MATCHHID_NOMATCH ||
519 acpi_MatchHid(handle, "ARMHC97C") != ACPI_MATCHHID_NOMATCH ||
520 acpi_MatchHid(handle, "ARMHC98D") != ACPI_MATCHHID_NOMATCH ||
521 acpi_MatchHid(handle, "ARMHC9FF") != ACPI_MATCHHID_NOMATCH ||
522 acpi_MatchHid(handle, "ARMHD620") != ACPI_MATCHHID_NOMATCH)
523 arc.ignore_producer_flag = true;
524
525 /*
526 * The DesignWare I2C Controller on Ampere Altra sets ResourceProducer on
527 * memory resources.
528 */
529 if (acpi_MatchHid(handle, "APMC0D0F") != ACPI_MATCHHID_NOMATCH)
530 arc.ignore_producer_flag = true;
531
532 status = AcpiWalkResources(handle, "_CRS", acpi_parse_resource, &arc);
533 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
534 printf("can't fetch resources for %s - %s\n",
535 acpi_name(handle), AcpiFormatException(status));
536 return_ACPI_STATUS (status);
537 }
538 set->set_done(dev, arc.context);
539 return_ACPI_STATUS (AE_OK);
540 }
541
542 /*
543 * Resource-set vectors used to attach _CRS-derived resources
544 * to an ACPI device.
545 */
546 static void acpi_res_set_init(device_t dev, void *arg, void **context);
547 static void acpi_res_set_done(device_t dev, void *context);
548 static void acpi_res_set_ioport(device_t dev, void *context,
549 uint64_t base, uint64_t length);
550 static void acpi_res_set_iorange(device_t dev, void *context,
551 uint64_t low, uint64_t high,
552 uint64_t length, uint64_t align);
553 static void acpi_res_set_memory(device_t dev, void *context,
554 uint64_t base, uint64_t length);
555 static void acpi_res_set_memoryrange(device_t dev, void *context,
556 uint64_t low, uint64_t high,
557 uint64_t length, uint64_t align);
558 static void acpi_res_set_irq(device_t dev, void *context, uint8_t *irq,
559 int count, int trig, int pol);
560 static void acpi_res_set_ext_irq(device_t dev, void *context,
561 uint32_t *irq, int count, int trig, int pol);
562 static void acpi_res_set_drq(device_t dev, void *context, uint8_t *drq,
563 int count);
564 static void acpi_res_set_start_dependent(device_t dev, void *context,
565 int preference);
566 static void acpi_res_set_end_dependent(device_t dev, void *context);
567
568 struct acpi_parse_resource_set acpi_res_parse_set = {
569 acpi_res_set_init,
570 acpi_res_set_done,
571 acpi_res_set_ioport,
572 acpi_res_set_iorange,
573 acpi_res_set_memory,
574 acpi_res_set_memoryrange,
575 acpi_res_set_irq,
576 acpi_res_set_ext_irq,
577 acpi_res_set_drq,
578 acpi_res_set_start_dependent,
579 acpi_res_set_end_dependent
580 };
581
582 struct acpi_res_context {
583 int ar_nio;
584 int ar_nmem;
585 int ar_nirq;
586 int ar_ndrq;
587 void *ar_parent;
588 };
589
590 /*
591 * Some resources reported via _CRS should not be added as bus
592 * resources. This function returns true if a resource reported via
593 * _CRS should be ignored.
594 */
595 static bool
acpi_res_ignore(device_t dev,int type,rman_res_t start,rman_res_t count)596 acpi_res_ignore(device_t dev, int type, rman_res_t start, rman_res_t count)
597 {
598 struct acpi_device *ad = device_get_ivars(dev);
599 ACPI_DEVICE_INFO *devinfo;
600 bool allow;
601
602 /* Ignore IRQ resources for PCI link devices. */
603 if (type == SYS_RES_IRQ &&
604 ACPI_ID_PROBE(device_get_parent(dev), dev, pcilink_ids, NULL) <= 0)
605 return (true);
606
607 /*
608 * Ignore most resources for PCI root bridges. Some BIOSes
609 * incorrectly enumerate the memory ranges they decode as plain
610 * memory resources instead of as ResourceProducer ranges. Other
611 * BIOSes incorrectly list system resource entries for I/O ranges
612 * under the PCI bridge. Do allow the one known-correct case on
613 * x86 of a PCI bridge claiming the I/O ports used for PCI config
614 * access.
615 */
616 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
617 if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) {
618 if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) {
619 #if defined(__i386__) || defined(__amd64__)
620 allow = (type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT);
621 #else
622 allow = false;
623 #endif
624 if (!allow) {
625 AcpiOsFree(devinfo);
626 return (true);
627 }
628 }
629 AcpiOsFree(devinfo);
630 }
631 }
632
633 return (false);
634 }
635
636 static void
acpi_res_set_init(device_t dev,void * arg,void ** context)637 acpi_res_set_init(device_t dev, void *arg, void **context)
638 {
639 struct acpi_res_context *cp;
640
641 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
642 bzero(cp, sizeof(*cp));
643 cp->ar_parent = arg;
644 *context = cp;
645 }
646 }
647
648 static void
acpi_res_set_done(device_t dev,void * context)649 acpi_res_set_done(device_t dev, void *context)
650 {
651 struct acpi_res_context *cp = (struct acpi_res_context *)context;
652
653 if (cp == NULL)
654 return;
655 AcpiOsFree(cp);
656 }
657
658 static void
acpi_res_set_ioport(device_t dev,void * context,uint64_t base,uint64_t length)659 acpi_res_set_ioport(device_t dev, void *context, uint64_t base,
660 uint64_t length)
661 {
662 struct acpi_res_context *cp = (struct acpi_res_context *)context;
663
664 if (cp == NULL)
665 return;
666 if (acpi_res_ignore(dev, SYS_RES_IOPORT, base, length))
667 return;
668 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
669 }
670
671 static void
acpi_res_set_iorange(device_t dev,void * context,uint64_t low,uint64_t high,uint64_t length,uint64_t align)672 acpi_res_set_iorange(device_t dev, void *context, uint64_t low,
673 uint64_t high, uint64_t length, uint64_t align)
674 {
675 struct acpi_res_context *cp = (struct acpi_res_context *)context;
676
677 if (cp == NULL)
678 return;
679
680 /*
681 * XXX: Some BIOSes contain buggy _CRS entries where fixed I/O
682 * ranges have the maximum base address (_MAX) to the end of the
683 * I/O range instead of the start. These are then treated as a
684 * relocatable I/O range rather than a fixed I/O resource. As a
685 * workaround, treat I/O resources encoded this way as fixed I/O
686 * ports.
687 */
688 if (high == (low + length)) {
689 if (bootverbose)
690 device_printf(dev,
691 "_CRS has fixed I/O port range defined as relocatable\n");
692
693 if (acpi_res_ignore(dev, SYS_RES_IOPORT, low, length))
694 return;
695 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, low, length);
696 return;
697 }
698
699 device_printf(dev, "I/O range not supported\n");
700 }
701
702 static void
acpi_res_set_memory(device_t dev,void * context,uint64_t base,uint64_t length)703 acpi_res_set_memory(device_t dev, void *context, uint64_t base,
704 uint64_t length)
705 {
706 struct acpi_res_context *cp = (struct acpi_res_context *)context;
707
708 if (cp == NULL)
709 return;
710 if (acpi_res_ignore(dev, SYS_RES_MEMORY, base, length))
711 return;
712 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
713 }
714
715 static void
acpi_res_set_memoryrange(device_t dev,void * context,uint64_t low,uint64_t high,uint64_t length,uint64_t align)716 acpi_res_set_memoryrange(device_t dev, void *context, uint64_t low,
717 uint64_t high, uint64_t length, uint64_t align)
718 {
719 struct acpi_res_context *cp = (struct acpi_res_context *)context;
720
721 if (cp == NULL)
722 return;
723 device_printf(dev, "memory range not supported\n");
724 }
725
726 static void
acpi_res_set_irq(device_t dev,void * context,uint8_t * irq,int count,int trig,int pol)727 acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count,
728 int trig, int pol)
729 {
730 struct acpi_res_context *cp = (struct acpi_res_context *)context;
731 int i;
732
733 if (cp == NULL || irq == NULL)
734 return;
735
736 for (i = 0; i < count; i++) {
737 if (acpi_res_ignore(dev, SYS_RES_IRQ, irq[i], 1))
738 continue;
739 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq[i], 1);
740 }
741 }
742
743 static void
acpi_res_set_ext_irq(device_t dev,void * context,uint32_t * irq,int count,int trig,int pol)744 acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count,
745 int trig, int pol)
746 {
747 struct acpi_res_context *cp = (struct acpi_res_context *)context;
748 int i;
749
750 if (cp == NULL || irq == NULL)
751 return;
752
753 for (i = 0; i < count; i++) {
754 if (acpi_res_ignore(dev, SYS_RES_IRQ, irq[i], 1))
755 continue;
756 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq[i], 1);
757 }
758 }
759
760 static void
acpi_res_set_drq(device_t dev,void * context,uint8_t * drq,int count)761 acpi_res_set_drq(device_t dev, void *context, uint8_t *drq, int count)
762 {
763 struct acpi_res_context *cp = (struct acpi_res_context *)context;
764
765 if (cp == NULL || drq == NULL)
766 return;
767
768 /* This implements no resource relocation. */
769 if (count != 1)
770 return;
771
772 if (acpi_res_ignore(dev, SYS_RES_DRQ, *drq, 1))
773 return;
774 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
775 }
776
777 static void
acpi_res_set_start_dependent(device_t dev,void * context,int preference)778 acpi_res_set_start_dependent(device_t dev, void *context, int preference)
779 {
780 struct acpi_res_context *cp = (struct acpi_res_context *)context;
781
782 if (cp == NULL)
783 return;
784 device_printf(dev, "dependent functions not supported\n");
785 }
786
787 static void
acpi_res_set_end_dependent(device_t dev,void * context)788 acpi_res_set_end_dependent(device_t dev, void *context)
789 {
790 struct acpi_res_context *cp = (struct acpi_res_context *)context;
791
792 if (cp == NULL)
793 return;
794 device_printf(dev, "dependent functions not supported\n");
795 }
796
797 /*
798 * Resource-owning placeholders for IO and memory pseudo-devices.
799 *
800 * This code allocates system resources that will be used by ACPI
801 * child devices. The acpi parent manages these resources through a
802 * private rman.
803 */
804
805 static int acpi_sysres_probe(device_t dev);
806 static int acpi_sysres_attach(device_t dev);
807
808 static device_method_t acpi_sysres_methods[] = {
809 /* Device interface */
810 DEVMETHOD(device_probe, acpi_sysres_probe),
811 DEVMETHOD(device_attach, acpi_sysres_attach),
812
813 DEVMETHOD_END
814 };
815
816 static driver_t acpi_sysres_driver = {
817 "acpi_sysresource",
818 acpi_sysres_methods,
819 0,
820 };
821
822 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, 0, 0);
823 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
824
825 static int
acpi_sysres_probe(device_t dev)826 acpi_sysres_probe(device_t dev)
827 {
828 static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL };
829 int rv;
830
831 if (acpi_disabled("sysresource"))
832 return (ENXIO);
833 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, sysres_ids, NULL);
834 if (rv > 0){
835 return (rv);
836 }
837 device_set_desc(dev, "System Resource");
838 device_quiet(dev);
839 return (rv);
840 }
841
842 static int
acpi_sysres_attach(device_t dev)843 acpi_sysres_attach(device_t dev)
844 {
845 device_t bus;
846 struct acpi_softc *bus_sc;
847 struct resource_list_entry *bus_rle, *dev_rle;
848 struct resource_list *bus_rl, *dev_rl;
849 int done, type;
850 rman_res_t start, end, count;
851
852 /*
853 * Loop through all current resources to see if the new one overlaps
854 * any existing ones. If so, grow the old one up and/or down
855 * accordingly. Discard any that are wholly contained in the old. If
856 * the resource is unique, add it to the parent. It will later go into
857 * the rman pool.
858 */
859 bus = device_get_parent(dev);
860 dev_rl = BUS_GET_RESOURCE_LIST(bus, dev);
861 bus_sc = acpi_device_get_parent_softc(dev);
862 bus_rl = &bus_sc->sysres_rl;
863 STAILQ_FOREACH(dev_rle, dev_rl, link) {
864 if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY)
865 continue;
866
867 start = dev_rle->start;
868 end = dev_rle->end;
869 count = dev_rle->count;
870 type = dev_rle->type;
871 done = FALSE;
872
873 STAILQ_FOREACH(bus_rle, bus_rl, link) {
874 if (bus_rle->type != type)
875 continue;
876
877 /* New resource wholly contained in old, discard. */
878 if (start >= bus_rle->start && end <= bus_rle->end)
879 break;
880
881 /* New tail overlaps old head, grow existing resource downward. */
882 if (start < bus_rle->start && end >= bus_rle->start) {
883 bus_rle->count += bus_rle->start - start;
884 bus_rle->start = start;
885 done = TRUE;
886 }
887
888 /* New head overlaps old tail, grow existing resource upward. */
889 if (start <= bus_rle->end && end > bus_rle->end) {
890 bus_rle->count += end - bus_rle->end;
891 bus_rle->end = end;
892 done = TRUE;
893 }
894
895 /* If we adjusted the old resource, we're finished. */
896 if (done)
897 break;
898 }
899
900 /* If we didn't merge with anything, add this resource. */
901 if (bus_rle == NULL)
902 resource_list_add_next(bus_rl, type, start, end, count);
903 }
904
905 /* After merging/moving resources to the parent, free the list. */
906 resource_list_free(dev_rl);
907
908 return (0);
909 }
910