xref: /netbsd/sys/dev/acpi/acpi_resource.c (revision 4b739352)
1 /*	$NetBSD: acpi_resource.c,v 1.42 2021/08/07 18:39:40 jmcneill Exp $	*/
2 
3 /*
4  * Copyright 2001 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed for the NetBSD Project by
20  *	Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*-
39  * Copyright (c) 2000 Michael Smith
40  * Copyright (c) 2000 BSDi
41  * All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  */
64 
65 /*
66  * ACPI resource parsing.
67  */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: acpi_resource.c,v 1.42 2021/08/07 18:39:40 jmcneill Exp $");
71 
72 #include <sys/param.h>
73 #include <sys/device.h>
74 #include <sys/systm.h>
75 
76 #include <dev/acpi/acpireg.h>
77 #include <dev/acpi/acpivar.h>
78 
79 #define	_COMPONENT	ACPI_RESOURCE_COMPONENT
80 ACPI_MODULE_NAME("RESOURCE")
81 
82 static ACPI_STATUS acpi_resource_parse_callback(ACPI_RESOURCE *, void *);
83 
84 struct resource_parse_callback_arg {
85 	const struct acpi_resource_parse_ops *ops;
86 	bool include_producer;
87 	device_t dev;
88 	void *context;
89 };
90 
91 static ACPI_STATUS
acpi_resource_parse_callback(ACPI_RESOURCE * res,void * context)92 acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context)
93 {
94 	struct resource_parse_callback_arg *arg = context;
95 	const struct acpi_resource_parse_ops *ops;
96 	int i;
97 
98 	ACPI_FUNCTION_TRACE(__func__);
99 
100 	ops = arg->ops;
101 
102 	switch (res->Type) {
103 	case ACPI_RESOURCE_TYPE_END_TAG:
104 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
105 		break;
106 	case ACPI_RESOURCE_TYPE_FIXED_IO:
107 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
108 				     "FixedIo 0x%x/%u\n",
109 				     res->Data.FixedIo.Address,
110 				     res->Data.FixedIo.AddressLength));
111 		if (ops->ioport)
112 			(*ops->ioport)(arg->dev, arg->context,
113 			    res->Data.FixedIo.Address,
114 			    res->Data.FixedIo.AddressLength);
115 		break;
116 
117 	case ACPI_RESOURCE_TYPE_IO:
118 		if (res->Data.Io.Minimum ==
119 		    res->Data.Io.Maximum) {
120 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
121 					     "Io 0x%x/%u\n",
122 					     res->Data.Io.Minimum,
123 					     res->Data.Io.AddressLength));
124 			if (ops->ioport)
125 				(*ops->ioport)(arg->dev, arg->context,
126 				    res->Data.Io.Minimum,
127 				    res->Data.Io.AddressLength);
128 		} else {
129 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
130 					     "Io 0x%x-0x%x/%u\n",
131 					     res->Data.Io.Minimum,
132 					     res->Data.Io.Maximum,
133 					     res->Data.Io.AddressLength));
134 			if (ops->iorange)
135 				(*ops->iorange)(arg->dev, arg->context,
136 				    res->Data.Io.Minimum,
137 				    res->Data.Io.Maximum,
138 				    res->Data.Io.AddressLength,
139 				    res->Data.Io.Alignment);
140 		}
141 		break;
142 
143 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
144 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
145 				     "FixedMemory32 0x%x/%u\n",
146 				     res->Data.FixedMemory32.Address,
147 				     res->Data.FixedMemory32.AddressLength));
148 		if (ops->memory)
149 			(*ops->memory)(arg->dev, arg->context,
150 			    res->Data.FixedMemory32.Address,
151 			    res->Data.FixedMemory32.AddressLength,
152 			    res->Data.FixedMemory32.Address);
153 		break;
154 
155 	case ACPI_RESOURCE_TYPE_MEMORY32:
156 		if (res->Data.Memory32.Minimum ==
157 		    res->Data.Memory32.Maximum) {
158 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
159 					     "Memory32 0x%x/%u\n",
160 					     res->Data.Memory32.Minimum,
161 					     res->Data.Memory32.AddressLength));
162 			if (ops->memory)
163 				(*ops->memory)(arg->dev, arg->context,
164 				    res->Data.Memory32.Minimum,
165 				    res->Data.Memory32.AddressLength,
166 				    res->Data.Memory32.Minimum);
167 		} else {
168 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
169 					     "Memory32 0x%x-0x%x/%u\n",
170 					     res->Data.Memory32.Minimum,
171 					     res->Data.Memory32.Maximum,
172 					     res->Data.Memory32.AddressLength));
173 			if (ops->memrange)
174 				(*ops->memrange)(arg->dev, arg->context,
175 				    res->Data.Memory32.Minimum,
176 				    res->Data.Memory32.Maximum,
177 				    res->Data.Memory32.AddressLength,
178 				    res->Data.Memory32.Alignment);
179 		}
180 		break;
181 
182 	case ACPI_RESOURCE_TYPE_MEMORY24:
183 		if (res->Data.Memory24.Minimum ==
184 		    res->Data.Memory24.Maximum) {
185 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
186 					     "Memory24 0x%x/%u\n",
187 					     res->Data.Memory24.Minimum,
188 					     res->Data.Memory24.AddressLength));
189 			if (ops->memory)
190 				(*ops->memory)(arg->dev, arg->context,
191 				    res->Data.Memory24.Minimum,
192 				    res->Data.Memory24.AddressLength,
193 				    res->Data.Memory24.Minimum);
194 		} else {
195 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
196 					     "Memory24 0x%x-0x%x/%u\n",
197 					     res->Data.Memory24.Minimum,
198 					     res->Data.Memory24.Maximum,
199 					     res->Data.Memory24.AddressLength));
200 			if (ops->memrange)
201 				(*ops->memrange)(arg->dev, arg->context,
202 				    res->Data.Memory24.Minimum,
203 				    res->Data.Memory24.Maximum,
204 				    res->Data.Memory24.AddressLength,
205 				    res->Data.Memory24.Alignment);
206 		}
207 		break;
208 
209 	case ACPI_RESOURCE_TYPE_IRQ:
210 		for (i = 0; i < res->Data.Irq.InterruptCount; i++) {
211 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
212 					     "IRQ %u\n",
213 					     res->Data.Irq.Interrupts[i]));
214 			if (ops->irq)
215 				(*ops->irq)(arg->dev, arg->context,
216 				    res->Data.Irq.Interrupts[i],
217 				    res->Data.Irq.Triggering);
218 		}
219 		break;
220 
221 	case ACPI_RESOURCE_TYPE_DMA:
222 		for (i = 0; i < res->Data.Dma.ChannelCount; i++) {
223 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
224 					     "DRQ %u\n",
225 					     res->Data.Dma.Channels[i]));
226 			if (ops->drq)
227 				(*ops->drq)(arg->dev, arg->context,
228 				    res->Data.Dma.Channels[i]);
229 		}
230 		break;
231 
232 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
233 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
234 				     "Start dependent functions: %u\n",
235 				     res->Data.StartDpf.CompatibilityPriority));
236 		if (ops->start_dep)
237 			(*ops->start_dep)(arg->dev, arg->context,
238 			    res->Data.StartDpf.CompatibilityPriority);
239 		break;
240 
241 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
242 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
243 				     "End dependent functions\n"));
244 		if (ops->end_dep)
245 			(*ops->end_dep)(arg->dev, arg->context);
246 		break;
247 
248 	case ACPI_RESOURCE_TYPE_ADDRESS32:
249 		/* XXX Only fixed size supported for now */
250 		if (res->Data.Address32.Address.AddressLength == 0 ||
251 		    (!arg->include_producer &&
252 		     res->Data.Address32.ProducerConsumer != ACPI_CONSUMER))
253 			break;
254 #define ADDRESS32_FIXED2(r)						\
255 	((r)->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&	\
256 	 (r)->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)
257 		switch (res->Data.Address32.ResourceType) {
258 		case ACPI_MEMORY_RANGE:
259 			if (ADDRESS32_FIXED2(res)) {
260 				if (ops->memory)
261 					(*ops->memory)(arg->dev, arg->context,
262 					    res->Data.Address32.Address.Minimum,
263 					    res->Data.Address32.Address.AddressLength,
264 					    res->Data.Address32.Address.Minimum +
265 					        res->Data.Address32.Address.TranslationOffset);
266 			} else {
267 				if (ops->memrange)
268 					(*ops->memrange)(arg->dev, arg->context,
269 					    res->Data.Address32.Address.Minimum,
270 					    res->Data.Address32.Address.Maximum,
271 					    res->Data.Address32.Address.AddressLength,
272 					    res->Data.Address32.Address.Granularity);
273 			}
274 			break;
275 		case ACPI_IO_RANGE:
276 			if (ADDRESS32_FIXED2(res)) {
277 				if (ops->ioport)
278 					(*ops->ioport)(arg->dev, arg->context,
279 					    res->Data.Address32.Address.Minimum,
280 					    res->Data.Address32.Address.AddressLength);
281 			} else {
282 				if (ops->iorange)
283 					(*ops->iorange)(arg->dev, arg->context,
284 					    res->Data.Address32.Address.Minimum,
285 					    res->Data.Address32.Address.Maximum,
286 					    res->Data.Address32.Address.AddressLength,
287 					    res->Data.Address32.Address.Granularity);
288 			}
289 			break;
290 		case ACPI_BUS_NUMBER_RANGE:
291 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
292 				      "Address32/BusNumber unimplemented\n"));
293 			break;
294 		}
295 #undef ADDRESS32_FIXED2
296 		break;
297 
298 	case ACPI_RESOURCE_TYPE_ADDRESS16:
299 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
300 				     "Address16 unimplemented\n"));
301 		break;
302 
303 	case ACPI_RESOURCE_TYPE_ADDRESS64:
304 #ifdef _LP64
305 		/* XXX Only fixed size supported for now */
306 		if (res->Data.Address64.Address.AddressLength == 0 ||
307 		    (!arg->include_producer &&
308 		     res->Data.Address64.ProducerConsumer != ACPI_CONSUMER))
309 			break;
310 #define ADDRESS64_FIXED2(r)						\
311 	((r)->Data.Address64.MinAddressFixed == ACPI_ADDRESS_FIXED &&	\
312 	 (r)->Data.Address64.MaxAddressFixed == ACPI_ADDRESS_FIXED)
313 		switch (res->Data.Address64.ResourceType) {
314 		case ACPI_MEMORY_RANGE:
315 			if (ADDRESS64_FIXED2(res)) {
316 				if (ops->memory)
317 					(*ops->memory)(arg->dev, arg->context,
318 					    res->Data.Address64.Address.Minimum,
319 					    res->Data.Address64.Address.AddressLength,
320 					    res->Data.Address64.Address.Minimum +
321 					        res->Data.Address64.Address.TranslationOffset);
322 			} else {
323 				if (ops->memrange)
324 					(*ops->memrange)(arg->dev, arg->context,
325 					    res->Data.Address64.Address.Minimum,
326 					    res->Data.Address64.Address.Maximum,
327 					    res->Data.Address64.Address.AddressLength,
328 					    res->Data.Address64.Address.Granularity);
329 			}
330 			break;
331 		case ACPI_IO_RANGE:
332 			if (ADDRESS64_FIXED2(res)) {
333 				if (ops->ioport)
334 					(*ops->ioport)(arg->dev, arg->context,
335 					    res->Data.Address64.Address.Minimum,
336 					    res->Data.Address64.Address.AddressLength);
337 			} else {
338 				if (ops->iorange)
339 					(*ops->iorange)(arg->dev, arg->context,
340 					    res->Data.Address64.Address.Minimum,
341 					    res->Data.Address64.Address.Maximum,
342 					    res->Data.Address64.Address.AddressLength,
343 					    res->Data.Address64.Address.Granularity);
344 			}
345 			break;
346 		case ACPI_BUS_NUMBER_RANGE:
347 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
348 				      "Address64/BusNumber unimplemented\n"));
349 			break;
350 		}
351 #undef ADDRESS64_FIXED2
352 #else
353 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
354 				     "Address64 unimplemented\n"));
355 #endif
356 		break;
357 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
358 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
359 				     "Extended address64 unimplemented\n"));
360 		break;
361 
362 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
363 		if (!arg->include_producer &&
364 		    res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
365 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
366 			    "ignored ExtIRQ producer\n"));
367 			break;
368 		}
369 		for (i = 0; i < res->Data.ExtendedIrq.InterruptCount; i++) {
370 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
371 				     "ExtIRQ %u\n",
372 				     res->Data.ExtendedIrq.Interrupts[i]));
373 			if (ops->irq)
374 				(*ops->irq)(arg->dev, arg->context,
375 				    res->Data.ExtendedIrq.Interrupts[i],
376 				    res->Data.ExtendedIrq.Triggering);
377 		}
378 		break;
379 
380 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
381 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
382 				     "GenericRegister unimplemented\n"));
383 		break;
384 
385 	case ACPI_RESOURCE_TYPE_VENDOR:
386 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
387 				     "VendorSpecific unimplemented\n"));
388 		break;
389 
390 	default:
391 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
392 				     "Unknown resource type: %u\n", res->Type));
393 		break;
394 	}
395 
396 	return_ACPI_STATUS(AE_OK);
397 }
398 
399 
400 /*
401  * acpi_resource_parse:
402  *
403  *	Parse a device node's resources and fill them in for the
404  *	client.
405  *
406  *	This API supports _CRS (current resources) and
407  *	_PRS (possible resources).
408  *
409  *	Note that it might be nice to also locate ACPI-specific resource
410  *	items, such as GPE bits.
411  */
412 ACPI_STATUS
acpi_resource_parse(device_t dev,ACPI_HANDLE handle,const char * path,void * arg,const struct acpi_resource_parse_ops * ops)413 acpi_resource_parse(device_t dev, ACPI_HANDLE handle, const char *path,
414     void *arg, const struct acpi_resource_parse_ops *ops)
415 {
416 	struct resource_parse_callback_arg cbarg;
417 	ACPI_STATUS rv;
418 
419 	ACPI_FUNCTION_TRACE(__func__);
420 
421 	if (ops->init)
422 		(*ops->init)(dev, arg, &cbarg.context);
423 	else
424 		cbarg.context = arg;
425 	cbarg.ops = ops;
426 	cbarg.dev = dev;
427 	cbarg.include_producer = false;
428 
429 	rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
430 	    &cbarg);
431 	if (ACPI_FAILURE(rv)) {
432 		aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n",
433 		    path, AcpiFormatException(rv));
434 		return_ACPI_STATUS(rv);
435 	}
436 
437 	if (ops->fini)
438 		(*ops->fini)(dev, cbarg.context);
439 
440 	return_ACPI_STATUS(AE_OK);
441 }
442 
443 /*
444  * acpi_resource_parse_any:
445  *
446  *	Parse a device node's resources and fill them in for the
447  *	client. Like acpi_resource_parse, but doesn't skip ResourceProducer
448  *	type resources.
449  */
450 ACPI_STATUS
acpi_resource_parse_any(device_t dev,ACPI_HANDLE handle,const char * path,void * arg,const struct acpi_resource_parse_ops * ops)451 acpi_resource_parse_any(device_t dev, ACPI_HANDLE handle, const char *path,
452     void *arg, const struct acpi_resource_parse_ops *ops)
453 {
454 	struct resource_parse_callback_arg cbarg;
455 	ACPI_STATUS rv;
456 
457 	ACPI_FUNCTION_TRACE(__func__);
458 
459 	if (ops->init)
460 		(*ops->init)(dev, arg, &cbarg.context);
461 	else
462 		cbarg.context = arg;
463 	cbarg.ops = ops;
464 	cbarg.dev = dev;
465 	cbarg.include_producer = true;
466 
467 	rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
468 	    &cbarg);
469 	if (ACPI_FAILURE(rv)) {
470 		aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n",
471 		    path, AcpiFormatException(rv));
472 		return_ACPI_STATUS(rv);
473 	}
474 
475 	if (ops->fini)
476 		(*ops->fini)(dev, cbarg.context);
477 
478 	return_ACPI_STATUS(AE_OK);
479 }
480 
481 
482 /*
483  * acpi_resource_print:
484  *
485  *	Print the resources assigned to a device.
486  */
487 void
acpi_resource_print(device_t dev,struct acpi_resources * res)488 acpi_resource_print(device_t dev, struct acpi_resources *res)
489 {
490 	const char *sep;
491 
492 	if (SIMPLEQ_EMPTY(&res->ar_io) &&
493 	    SIMPLEQ_EMPTY(&res->ar_iorange) &&
494 	    SIMPLEQ_EMPTY(&res->ar_mem) &&
495 	    SIMPLEQ_EMPTY(&res->ar_memrange) &&
496 	    SIMPLEQ_EMPTY(&res->ar_irq) &&
497 	    SIMPLEQ_EMPTY(&res->ar_drq))
498 		return;
499 
500 	aprint_normal(":");
501 
502 	if (SIMPLEQ_EMPTY(&res->ar_io) == 0) {
503 		struct acpi_io *ar;
504 
505 		sep = "";
506 		aprint_normal(" io ");
507 		SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
508 			aprint_normal("%s0x%x", sep, ar->ar_base);
509 			if (ar->ar_length > 1)
510 				aprint_normal("-0x%x", ar->ar_base +
511 				    ar->ar_length - 1);
512 			sep = ",";
513 		}
514 	}
515 
516 	/* XXX iorange */
517 
518 	if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) {
519 		struct acpi_mem *ar;
520 
521 		sep = "";
522 		aprint_normal(" mem ");
523 		SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
524 			aprint_normal("%s0x%" PRIx64, sep,
525 			    (uint64_t)ar->ar_base);
526 			if (ar->ar_length > 1)
527 				aprint_normal("-0x%" PRIx64,
528 				    (uint64_t)ar->ar_base +
529 				    ar->ar_length - 1);
530 			sep = ",";
531 		}
532 	}
533 
534 	/* XXX memrange */
535 
536 	if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) {
537 		struct acpi_irq *ar;
538 
539 		sep = "";
540 		aprint_normal(" irq ");
541 		SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
542 			aprint_normal("%s%d", sep, ar->ar_irq);
543 			sep = ",";
544 		}
545 	}
546 
547 	if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) {
548 		struct acpi_drq *ar;
549 
550 		sep = "";
551 		aprint_normal(" drq ");
552 		SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
553 			aprint_normal("%s%d", sep, ar->ar_drq);
554 			sep = ",";
555 		}
556 	}
557 
558 	aprint_normal("\n");
559 	aprint_naive("\n");
560 }
561 
562 /*
563  * acpi_resource_cleanup:
564  *
565  *	Free all allocated buffers
566  */
567 void
acpi_resource_cleanup(struct acpi_resources * res)568 acpi_resource_cleanup(struct acpi_resources *res)
569 {
570 	while (!SIMPLEQ_EMPTY(&res->ar_io)) {
571 		struct acpi_io *ar;
572 		ar = SIMPLEQ_FIRST(&res->ar_io);
573 		SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list);
574 		ACPI_FREE(ar);
575 	}
576 
577 	while (!SIMPLEQ_EMPTY(&res->ar_iorange)) {
578 		struct acpi_iorange *ar;
579 		ar = SIMPLEQ_FIRST(&res->ar_iorange);
580 		SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list);
581 		ACPI_FREE(ar);
582 	}
583 
584 	while (!SIMPLEQ_EMPTY(&res->ar_mem)) {
585 		struct acpi_mem *ar;
586 		ar = SIMPLEQ_FIRST(&res->ar_mem);
587 		SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list);
588 		ACPI_FREE(ar);
589 	}
590 
591 	while (!SIMPLEQ_EMPTY(&res->ar_memrange)) {
592 		struct acpi_memrange *ar;
593 		ar = SIMPLEQ_FIRST(&res->ar_memrange);
594 		SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list);
595 		ACPI_FREE(ar);
596 	}
597 
598 	while (!SIMPLEQ_EMPTY(&res->ar_irq)) {
599 		struct acpi_irq *ar;
600 		ar = SIMPLEQ_FIRST(&res->ar_irq);
601 		SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list);
602 		ACPI_FREE(ar);
603 	}
604 
605 	while (!SIMPLEQ_EMPTY(&res->ar_drq)) {
606 		struct acpi_drq *ar;
607 		ar = SIMPLEQ_FIRST(&res->ar_drq);
608 		SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list);
609 		ACPI_FREE(ar);
610 	}
611 
612 	res->ar_nio = res->ar_niorange = res->ar_nmem =
613 	    res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0;
614 }
615 
616 struct acpi_io *
acpi_res_io(struct acpi_resources * res,int idx)617 acpi_res_io(struct acpi_resources *res, int idx)
618 {
619 	struct acpi_io *ar;
620 
621 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
622 		if (ar->ar_index == idx)
623 			return ar;
624 	}
625 	return NULL;
626 }
627 
628 struct acpi_iorange *
acpi_res_iorange(struct acpi_resources * res,int idx)629 acpi_res_iorange(struct acpi_resources *res, int idx)
630 {
631 	struct acpi_iorange *ar;
632 
633 	SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) {
634 		if (ar->ar_index == idx)
635 			return ar;
636 	}
637 	return NULL;
638 }
639 
640 struct acpi_mem *
acpi_res_mem(struct acpi_resources * res,int idx)641 acpi_res_mem(struct acpi_resources *res, int idx)
642 {
643 	struct acpi_mem *ar;
644 
645 	SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
646 		if (ar->ar_index == idx)
647 			return ar;
648 	}
649 	return NULL;
650 }
651 
652 struct acpi_memrange *
acpi_res_memrange(struct acpi_resources * res,int idx)653 acpi_res_memrange(struct acpi_resources *res, int idx)
654 {
655 	struct acpi_memrange *ar;
656 
657 	SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) {
658 		if (ar->ar_index == idx)
659 			return ar;
660 	}
661 	return NULL;
662 }
663 
664 struct acpi_irq *
acpi_res_irq(struct acpi_resources * res,int idx)665 acpi_res_irq(struct acpi_resources *res, int idx)
666 {
667 	struct acpi_irq *ar;
668 
669 	SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
670 		if (ar->ar_index == idx)
671 			return ar;
672 	}
673 	return NULL;
674 }
675 
676 struct acpi_drq *
acpi_res_drq(struct acpi_resources * res,int idx)677 acpi_res_drq(struct acpi_resources *res, int idx)
678 {
679 	struct acpi_drq *ar;
680 
681 	SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
682 		if (ar->ar_index == idx)
683 			return ar;
684 	}
685 	return NULL;
686 }
687 
688 /*****************************************************************************
689  * Default ACPI resource parse operations.
690  *****************************************************************************/
691 
692 static void	acpi_res_parse_init(device_t, void *, void **);
693 static void	acpi_res_parse_fini(device_t, void *);
694 
695 static void	acpi_res_parse_ioport(device_t, void *, uint32_t,
696 		    uint32_t);
697 static void	acpi_res_parse_iorange(device_t, void *, uint32_t,
698 		    uint32_t, uint32_t, uint32_t);
699 
700 static void	acpi_res_parse_memory(device_t, void *, uint64_t,
701 		    uint64_t, uint64_t);
702 static void	acpi_res_parse_memrange(device_t, void *, uint64_t,
703 		    uint64_t, uint64_t, uint64_t);
704 
705 static void	acpi_res_parse_irq(device_t, void *, uint32_t, uint32_t);
706 static void	acpi_res_parse_drq(device_t, void *, uint32_t);
707 
708 static void	acpi_res_parse_start_dep(device_t, void *, int);
709 static void	acpi_res_parse_end_dep(device_t, void *);
710 
711 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = {
712 	.init = acpi_res_parse_init,
713 	.fini = acpi_res_parse_fini,
714 
715 	.ioport = acpi_res_parse_ioport,
716 	.iorange = acpi_res_parse_iorange,
717 
718 	.memory = acpi_res_parse_memory,
719 	.memrange = acpi_res_parse_memrange,
720 
721 	.irq = acpi_res_parse_irq,
722 	.drq = acpi_res_parse_drq,
723 
724 	.start_dep = acpi_res_parse_start_dep,
725 	.end_dep = acpi_res_parse_end_dep,
726 };
727 
728 const struct acpi_resource_parse_ops acpi_resource_parse_ops_quiet = {
729 	.init = acpi_res_parse_init,
730 	.fini = NULL,
731 
732 	.ioport = acpi_res_parse_ioport,
733 	.iorange = acpi_res_parse_iorange,
734 
735 	.memory = acpi_res_parse_memory,
736 	.memrange = acpi_res_parse_memrange,
737 
738 	.irq = acpi_res_parse_irq,
739 	.drq = acpi_res_parse_drq,
740 
741 	.start_dep = acpi_res_parse_start_dep,
742 	.end_dep = acpi_res_parse_end_dep,
743 };
744 
745 static void
acpi_res_parse_init(device_t dev,void * arg,void ** contextp)746 acpi_res_parse_init(device_t dev, void *arg, void **contextp)
747 {
748 	struct acpi_resources *res = arg;
749 
750 	SIMPLEQ_INIT(&res->ar_io);
751 	res->ar_nio = 0;
752 
753 	SIMPLEQ_INIT(&res->ar_iorange);
754 	res->ar_niorange = 0;
755 
756 	SIMPLEQ_INIT(&res->ar_mem);
757 	res->ar_nmem = 0;
758 
759 	SIMPLEQ_INIT(&res->ar_memrange);
760 	res->ar_nmemrange = 0;
761 
762 	SIMPLEQ_INIT(&res->ar_irq);
763 	res->ar_nirq = 0;
764 
765 	SIMPLEQ_INIT(&res->ar_drq);
766 	res->ar_ndrq = 0;
767 
768 	*contextp = res;
769 }
770 
771 static void
acpi_res_parse_fini(device_t dev,void * context)772 acpi_res_parse_fini(device_t dev, void *context)
773 {
774 	struct acpi_resources *res = context;
775 
776 	/* Print the resources we're using. */
777 	acpi_resource_print(dev, res);
778 }
779 
780 static void
acpi_res_parse_ioport(device_t dev,void * context,uint32_t base,uint32_t length)781 acpi_res_parse_ioport(device_t dev, void *context, uint32_t base,
782     uint32_t length)
783 {
784 	struct acpi_resources *res = context;
785 	struct acpi_io *ar;
786 
787 	/*
788 	 * Check if there is another I/O port directly below/under
789 	 * this one.
790 	 */
791 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
792 		if (ar->ar_base == base + length ) {
793 			/*
794 			 * Entry just below existing entry - adjust
795 			 * the entry and return.
796 			 */
797 			ar->ar_base = base;
798 			ar->ar_length += length;
799 			return;
800 		} else if (ar->ar_base + ar->ar_length == base) {
801 			/*
802 			 * Entry just above existing entry - adjust
803 			 * the entry and return.
804 			 */
805 			ar->ar_length += length;
806 			return;
807 		}
808 	}
809 
810 	ar = ACPI_ALLOCATE(sizeof(*ar));
811 	if (ar == NULL) {
812 		aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n",
813 		    res->ar_nio);
814 		res->ar_nio++;
815 		return;
816 	}
817 
818 	ar->ar_index = res->ar_nio++;
819 	ar->ar_base = base;
820 	ar->ar_length = length;
821 
822 	SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list);
823 }
824 
825 static void
acpi_res_parse_iorange(device_t dev,void * context,uint32_t low,uint32_t high,uint32_t length,uint32_t align)826 acpi_res_parse_iorange(device_t dev, void *context, uint32_t low,
827     uint32_t high, uint32_t length, uint32_t align)
828 {
829 	struct acpi_resources *res = context;
830 	struct acpi_iorange *ar;
831 
832 	ar = ACPI_ALLOCATE(sizeof(*ar));
833 	if (ar == NULL) {
834 		aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n",
835 		    res->ar_niorange);
836 		res->ar_niorange++;
837 		return;
838 	}
839 
840 	ar->ar_index = res->ar_niorange++;
841 	ar->ar_low = low;
842 	ar->ar_high = high;
843 	ar->ar_length = length;
844 	ar->ar_align = align;
845 
846 	SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list);
847 }
848 
849 static void
acpi_res_parse_memory(device_t dev,void * context,uint64_t base,uint64_t length,uint64_t xbase)850 acpi_res_parse_memory(device_t dev, void *context, uint64_t base,
851     uint64_t length, uint64_t xbase)
852 {
853 	struct acpi_resources *res = context;
854 	struct acpi_mem *ar;
855 
856 	ar = ACPI_ALLOCATE(sizeof(*ar));
857 	if (ar == NULL) {
858 		aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n",
859 		    res->ar_nmem);
860 		res->ar_nmem++;
861 		return;
862 	}
863 
864 	ar->ar_index = res->ar_nmem++;
865 	ar->ar_base = base;
866 	ar->ar_length = length;
867 	ar->ar_xbase = xbase;
868 
869 	SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list);
870 }
871 
872 static void
acpi_res_parse_memrange(device_t dev,void * context,uint64_t low,uint64_t high,uint64_t length,uint64_t align)873 acpi_res_parse_memrange(device_t dev, void *context, uint64_t low,
874     uint64_t high, uint64_t length, uint64_t align)
875 {
876 	struct acpi_resources *res = context;
877 	struct acpi_memrange *ar;
878 
879 	ar = ACPI_ALLOCATE(sizeof(*ar));
880 	if (ar == NULL) {
881 		aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n",
882 		    res->ar_nmemrange);
883 		res->ar_nmemrange++;
884 		return;
885 	}
886 
887 	ar->ar_index = res->ar_nmemrange++;
888 	ar->ar_low = low;
889 	ar->ar_high = high;
890 	ar->ar_length = length;
891 	ar->ar_align = align;
892 
893 	SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list);
894 }
895 
896 static void
acpi_res_parse_irq(device_t dev,void * context,uint32_t irq,uint32_t type)897 acpi_res_parse_irq(device_t dev, void *context, uint32_t irq, uint32_t type)
898 {
899 	struct acpi_resources *res = context;
900 	struct acpi_irq *ar;
901 
902 	ar = ACPI_ALLOCATE(sizeof(*ar));
903 	if (ar == NULL) {
904 		aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n",
905 		    res->ar_nirq);
906 		res->ar_nirq++;
907 		return;
908 	}
909 
910 	ar->ar_index = res->ar_nirq++;
911 	ar->ar_irq = irq;
912 	ar->ar_type = type;
913 
914 	SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list);
915 }
916 
917 static void
acpi_res_parse_drq(device_t dev,void * context,uint32_t drq)918 acpi_res_parse_drq(device_t dev, void *context, uint32_t drq)
919 {
920 	struct acpi_resources *res = context;
921 	struct acpi_drq *ar;
922 
923 	ar = ACPI_ALLOCATE(sizeof(*ar));
924 	if (ar == NULL) {
925 		aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n",
926 		    res->ar_ndrq);
927 		res->ar_ndrq++;
928 		return;
929 	}
930 
931 	ar->ar_index = res->ar_ndrq++;
932 	ar->ar_drq = drq;
933 
934 	SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list);
935 }
936 
937 static void
acpi_res_parse_start_dep(device_t dev,void * context,int preference)938 acpi_res_parse_start_dep(device_t dev, void *context,
939     int preference)
940 {
941 
942 	aprint_error_dev(dev, "ACPI: dependent functions not supported\n");
943 }
944 
945 static void
acpi_res_parse_end_dep(device_t dev,void * context)946 acpi_res_parse_end_dep(device_t dev, void *context)
947 {
948 
949 	/* Nothing to do. */
950 }
951