xref: /netbsd-src/sys/dev/acpi/acpi_resource.c (revision b0bb4503535f46d986306941621a58cbe2316831)
1*b0bb4503Sandvar /*	$NetBSD: acpi_resource.c,v 1.44 2025/01/02 16:32:34 andvar Exp $	*/
26179b9baSthorpej 
36179b9baSthorpej /*
46179b9baSthorpej  * Copyright 2001 Wasabi Systems, Inc.
56179b9baSthorpej  * All rights reserved.
66179b9baSthorpej  *
76179b9baSthorpej  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
86179b9baSthorpej  *
96179b9baSthorpej  * Redistribution and use in source and binary forms, with or without
106179b9baSthorpej  * modification, are permitted provided that the following conditions
116179b9baSthorpej  * are met:
126179b9baSthorpej  * 1. Redistributions of source code must retain the above copyright
136179b9baSthorpej  *    notice, this list of conditions and the following disclaimer.
146179b9baSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
156179b9baSthorpej  *    notice, this list of conditions and the following disclaimer in the
166179b9baSthorpej  *    documentation and/or other materials provided with the distribution.
176179b9baSthorpej  * 3. All advertising materials mentioning features or use of this software
186179b9baSthorpej  *    must display the following acknowledgement:
196179b9baSthorpej  *	This product includes software developed for the NetBSD Project by
206179b9baSthorpej  *	Wasabi Systems, Inc.
216179b9baSthorpej  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
226179b9baSthorpej  *    or promote products derived from this software without specific prior
236179b9baSthorpej  *    written permission.
246179b9baSthorpej  *
256179b9baSthorpej  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
266179b9baSthorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
276179b9baSthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
286179b9baSthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
296179b9baSthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
306179b9baSthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
316179b9baSthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
326179b9baSthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
336179b9baSthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
346179b9baSthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
356179b9baSthorpej  * POSSIBILITY OF SUCH DAMAGE.
366179b9baSthorpej  */
376179b9baSthorpej 
386179b9baSthorpej /*-
396179b9baSthorpej  * Copyright (c) 2000 Michael Smith
406179b9baSthorpej  * Copyright (c) 2000 BSDi
416179b9baSthorpej  * All rights reserved.
426179b9baSthorpej  *
436179b9baSthorpej  * Redistribution and use in source and binary forms, with or without
446179b9baSthorpej  * modification, are permitted provided that the following conditions
456179b9baSthorpej  * are met:
466179b9baSthorpej  * 1. Redistributions of source code must retain the above copyright
476179b9baSthorpej  *    notice, this list of conditions and the following disclaimer.
486179b9baSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
496179b9baSthorpej  *    notice, this list of conditions and the following disclaimer in the
506179b9baSthorpej  *    documentation and/or other materials provided with the distribution.
516179b9baSthorpej  *
526179b9baSthorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
536179b9baSthorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
546179b9baSthorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
556179b9baSthorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
566179b9baSthorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
576179b9baSthorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
586179b9baSthorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
596179b9baSthorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
606179b9baSthorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
616179b9baSthorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
626179b9baSthorpej  * SUCH DAMAGE.
636179b9baSthorpej  */
646179b9baSthorpej 
656179b9baSthorpej /*
666179b9baSthorpej  * ACPI resource parsing.
676179b9baSthorpej  */
686179b9baSthorpej 
6913ac4302Slukem #include <sys/cdefs.h>
70*b0bb4503Sandvar __KERNEL_RCSID(0, "$NetBSD: acpi_resource.c,v 1.44 2025/01/02 16:32:34 andvar Exp $");
7113ac4302Slukem 
726179b9baSthorpej #include <sys/param.h>
736179b9baSthorpej #include <sys/device.h>
745a425210Sjruoho #include <sys/systm.h>
756179b9baSthorpej 
766179b9baSthorpej #include <dev/acpi/acpireg.h>
776179b9baSthorpej #include <dev/acpi/acpivar.h>
786179b9baSthorpej 
7917848b05Sthorpej #define	_COMPONENT	ACPI_RESOURCE_COMPONENT
8017848b05Sthorpej ACPI_MODULE_NAME("RESOURCE")
816179b9baSthorpej 
820dd2fcbaSkochi static ACPI_STATUS acpi_resource_parse_callback(ACPI_RESOURCE *, void *);
830dd2fcbaSkochi 
84b547a6d2Skochi struct resource_parse_callback_arg {
85b547a6d2Skochi 	const struct acpi_resource_parse_ops *ops;
86d3b539ecSjmcneill 	bool include_producer;
8793dfc06dScegger 	device_t dev;
886179b9baSthorpej 	void *context;
89b547a6d2Skochi };
90b547a6d2Skochi 
91b547a6d2Skochi static ACPI_STATUS
92b547a6d2Skochi acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context)
93b547a6d2Skochi {
94b547a6d2Skochi 	struct resource_parse_callback_arg *arg = context;
95b547a6d2Skochi 	const struct acpi_resource_parse_ops *ops;
966179b9baSthorpej 	int i;
976179b9baSthorpej 
989b2b412cSperry 	ACPI_FUNCTION_TRACE(__func__);
9901e95b11Skochi 
100b547a6d2Skochi 	ops = arg->ops;
1016179b9baSthorpej 
1029e72fe1eSkochi 	switch (res->Type) {
10353b3110fSmsaitoh 	case ACPI_RESOURCE_TYPE_END_TAG:
10453b3110fSmsaitoh 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
10553b3110fSmsaitoh 		break;
1069e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_FIXED_IO:
1076179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1084fcde464Sjruoho 				     "FixedIo 0x%x/%u\n",
1099e72fe1eSkochi 				     res->Data.FixedIo.Address,
1109e72fe1eSkochi 				     res->Data.FixedIo.AddressLength));
1110dd2fcbaSkochi 		if (ops->ioport)
112b547a6d2Skochi 			(*ops->ioport)(arg->dev, arg->context,
1139e72fe1eSkochi 			    res->Data.FixedIo.Address,
1149e72fe1eSkochi 			    res->Data.FixedIo.AddressLength);
1156179b9baSthorpej 		break;
1166179b9baSthorpej 
1179e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_IO:
1189e72fe1eSkochi 		if (res->Data.Io.Minimum ==
1199e72fe1eSkochi 		    res->Data.Io.Maximum) {
1206179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1214fcde464Sjruoho 					     "Io 0x%x/%u\n",
1229e72fe1eSkochi 					     res->Data.Io.Minimum,
1239e72fe1eSkochi 					     res->Data.Io.AddressLength));
1240dd2fcbaSkochi 			if (ops->ioport)
125b547a6d2Skochi 				(*ops->ioport)(arg->dev, arg->context,
1269e72fe1eSkochi 				    res->Data.Io.Minimum,
1279e72fe1eSkochi 				    res->Data.Io.AddressLength);
1286179b9baSthorpej 		} else {
1296179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1304fcde464Sjruoho 					     "Io 0x%x-0x%x/%u\n",
1319e72fe1eSkochi 					     res->Data.Io.Minimum,
1329e72fe1eSkochi 					     res->Data.Io.Maximum,
1339e72fe1eSkochi 					     res->Data.Io.AddressLength));
13469b70bfeSnjoly 			if (ops->iorange)
135b547a6d2Skochi 				(*ops->iorange)(arg->dev, arg->context,
1369e72fe1eSkochi 				    res->Data.Io.Minimum,
1379e72fe1eSkochi 				    res->Data.Io.Maximum,
1389e72fe1eSkochi 				    res->Data.Io.AddressLength,
1396179b9baSthorpej 				    res->Data.Io.Alignment);
1406179b9baSthorpej 		}
1416179b9baSthorpej 		break;
1426179b9baSthorpej 
1439e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1446179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1454fcde464Sjruoho 				     "FixedMemory32 0x%x/%u\n",
1469e72fe1eSkochi 				     res->Data.FixedMemory32.Address,
1479e72fe1eSkochi 				     res->Data.FixedMemory32.AddressLength));
1480dd2fcbaSkochi 		if (ops->memory)
149b547a6d2Skochi 			(*ops->memory)(arg->dev, arg->context,
1509e72fe1eSkochi 			    res->Data.FixedMemory32.Address,
151439fe919Sjmcneill 			    res->Data.FixedMemory32.AddressLength,
1520dc1816eSjmcneill 			    res->Data.FixedMemory32.Address);
1536179b9baSthorpej 		break;
1546179b9baSthorpej 
1559e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_MEMORY32:
1569e72fe1eSkochi 		if (res->Data.Memory32.Minimum ==
1579e72fe1eSkochi 		    res->Data.Memory32.Maximum) {
1586179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1594fcde464Sjruoho 					     "Memory32 0x%x/%u\n",
1609e72fe1eSkochi 					     res->Data.Memory32.Minimum,
1619e72fe1eSkochi 					     res->Data.Memory32.AddressLength));
1620dd2fcbaSkochi 			if (ops->memory)
163b547a6d2Skochi 				(*ops->memory)(arg->dev, arg->context,
1649e72fe1eSkochi 				    res->Data.Memory32.Minimum,
165439fe919Sjmcneill 				    res->Data.Memory32.AddressLength,
1660dc1816eSjmcneill 				    res->Data.Memory32.Minimum);
1676179b9baSthorpej 		} else {
1686179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1694fcde464Sjruoho 					     "Memory32 0x%x-0x%x/%u\n",
1709e72fe1eSkochi 					     res->Data.Memory32.Minimum,
1719e72fe1eSkochi 					     res->Data.Memory32.Maximum,
1729e72fe1eSkochi 					     res->Data.Memory32.AddressLength));
1730dd2fcbaSkochi 			if (ops->memrange)
174b547a6d2Skochi 				(*ops->memrange)(arg->dev, arg->context,
1759e72fe1eSkochi 				    res->Data.Memory32.Minimum,
1769e72fe1eSkochi 				    res->Data.Memory32.Maximum,
1779e72fe1eSkochi 				    res->Data.Memory32.AddressLength,
1786179b9baSthorpej 				    res->Data.Memory32.Alignment);
1796179b9baSthorpej 		}
1806179b9baSthorpej 		break;
1816179b9baSthorpej 
1829e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_MEMORY24:
1839e72fe1eSkochi 		if (res->Data.Memory24.Minimum ==
1849e72fe1eSkochi 		    res->Data.Memory24.Maximum) {
1856179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1864fcde464Sjruoho 					     "Memory24 0x%x/%u\n",
1879e72fe1eSkochi 					     res->Data.Memory24.Minimum,
1889e72fe1eSkochi 					     res->Data.Memory24.AddressLength));
1890dd2fcbaSkochi 			if (ops->memory)
190b547a6d2Skochi 				(*ops->memory)(arg->dev, arg->context,
1919e72fe1eSkochi 				    res->Data.Memory24.Minimum,
192439fe919Sjmcneill 				    res->Data.Memory24.AddressLength,
1930dc1816eSjmcneill 				    res->Data.Memory24.Minimum);
1946179b9baSthorpej 		} else {
1956179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
1964fcde464Sjruoho 					     "Memory24 0x%x-0x%x/%u\n",
1979e72fe1eSkochi 					     res->Data.Memory24.Minimum,
1989e72fe1eSkochi 					     res->Data.Memory24.Maximum,
1999e72fe1eSkochi 					     res->Data.Memory24.AddressLength));
2000dd2fcbaSkochi 			if (ops->memrange)
201b547a6d2Skochi 				(*ops->memrange)(arg->dev, arg->context,
2029e72fe1eSkochi 				    res->Data.Memory24.Minimum,
2039e72fe1eSkochi 				    res->Data.Memory24.Maximum,
2049e72fe1eSkochi 				    res->Data.Memory24.AddressLength,
2056179b9baSthorpej 				    res->Data.Memory24.Alignment);
2066179b9baSthorpej 		}
2076179b9baSthorpej 		break;
2086179b9baSthorpej 
2099e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_IRQ:
2109e72fe1eSkochi 		for (i = 0; i < res->Data.Irq.InterruptCount; i++) {
2116179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
2124fcde464Sjruoho 					     "IRQ %u\n",
213b547a6d2Skochi 					     res->Data.Irq.Interrupts[i]));
2140dd2fcbaSkochi 			if (ops->irq)
215b547a6d2Skochi 				(*ops->irq)(arg->dev, arg->context,
216da1df3d5Smatt 				    res->Data.Irq.Interrupts[i],
2179e72fe1eSkochi 				    res->Data.Irq.Triggering);
2186179b9baSthorpej 		}
2196179b9baSthorpej 		break;
2206179b9baSthorpej 
2219e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_DMA:
2229e72fe1eSkochi 		for (i = 0; i < res->Data.Dma.ChannelCount; i++) {
2236179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
2244fcde464Sjruoho 					     "DRQ %u\n",
225b547a6d2Skochi 					     res->Data.Dma.Channels[i]));
2260dd2fcbaSkochi 			if (ops->drq)
227b547a6d2Skochi 				(*ops->drq)(arg->dev, arg->context,
2286179b9baSthorpej 				    res->Data.Dma.Channels[i]);
2296179b9baSthorpej 		}
2306179b9baSthorpej 		break;
2316179b9baSthorpej 
2329e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
2336179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
2344cbd24b2Swiz 				     "Start dependent functions: %u\n",
2356179b9baSthorpej 				     res->Data.StartDpf.CompatibilityPriority));
2360dd2fcbaSkochi 		if (ops->start_dep)
237b547a6d2Skochi 			(*ops->start_dep)(arg->dev, arg->context,
2386179b9baSthorpej 			    res->Data.StartDpf.CompatibilityPriority);
2396179b9baSthorpej 		break;
2406179b9baSthorpej 
2419e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
2426179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
2434cbd24b2Swiz 				     "End dependent functions\n"));
2440dd2fcbaSkochi 		if (ops->end_dep)
245b547a6d2Skochi 			(*ops->end_dep)(arg->dev, arg->context);
24669b70bfeSnjoly 		break;
2476179b9baSthorpej 
2489e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_ADDRESS32:
24969b70bfeSnjoly 		/* XXX Only fixed size supported for now */
250e9c4d788Sjmcneill 		if (res->Data.Address32.Address.AddressLength == 0)
25169b70bfeSnjoly 			break;
252b7635a00Sjmcneill #define ADDRESS32_FIXED2(r)						\
25369b70bfeSnjoly 	((r)->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&	\
25469b70bfeSnjoly 	 (r)->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)
25569b70bfeSnjoly 		switch (res->Data.Address32.ResourceType) {
25669b70bfeSnjoly 		case ACPI_MEMORY_RANGE:
257b7635a00Sjmcneill 			if (ADDRESS32_FIXED2(res)) {
25869b70bfeSnjoly 				if (ops->memory)
25969b70bfeSnjoly 					(*ops->memory)(arg->dev, arg->context,
2606252065cSchristos 					    res->Data.Address32.Address.Minimum,
261439fe919Sjmcneill 					    res->Data.Address32.Address.AddressLength,
2620dc1816eSjmcneill 					    res->Data.Address32.Address.Minimum +
2630dc1816eSjmcneill 					        res->Data.Address32.Address.TranslationOffset);
26469b70bfeSnjoly 			} else {
26569b70bfeSnjoly 				if (ops->memrange)
26669b70bfeSnjoly 					(*ops->memrange)(arg->dev, arg->context,
2676252065cSchristos 					    res->Data.Address32.Address.Minimum,
2686252065cSchristos 					    res->Data.Address32.Address.Maximum,
2696252065cSchristos 					    res->Data.Address32.Address.AddressLength,
2706252065cSchristos 					    res->Data.Address32.Address.Granularity);
27169b70bfeSnjoly 			}
27269b70bfeSnjoly 			break;
27369b70bfeSnjoly 		case ACPI_IO_RANGE:
274b7635a00Sjmcneill 			if (ADDRESS32_FIXED2(res)) {
27569b70bfeSnjoly 				if (ops->ioport)
27669b70bfeSnjoly 					(*ops->ioport)(arg->dev, arg->context,
2776252065cSchristos 					    res->Data.Address32.Address.Minimum,
2786252065cSchristos 					    res->Data.Address32.Address.AddressLength);
27969b70bfeSnjoly 			} else {
28069b70bfeSnjoly 				if (ops->iorange)
28169b70bfeSnjoly 					(*ops->iorange)(arg->dev, arg->context,
2826252065cSchristos 					    res->Data.Address32.Address.Minimum,
2836252065cSchristos 					    res->Data.Address32.Address.Maximum,
2846252065cSchristos 					    res->Data.Address32.Address.AddressLength,
2856252065cSchristos 					    res->Data.Address32.Address.Granularity);
28669b70bfeSnjoly 			}
28769b70bfeSnjoly 			break;
28869b70bfeSnjoly 		case ACPI_BUS_NUMBER_RANGE:
2896179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
29069b70bfeSnjoly 				      "Address32/BusNumber unimplemented\n"));
29169b70bfeSnjoly 			break;
29269b70bfeSnjoly 		}
293b7635a00Sjmcneill #undef ADDRESS32_FIXED2
2946179b9baSthorpej 		break;
2956179b9baSthorpej 
2969e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_ADDRESS16:
2976179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
2986179b9baSthorpej 				     "Address16 unimplemented\n"));
2996179b9baSthorpej 		break;
3006179b9baSthorpej 
30153b3110fSmsaitoh 	case ACPI_RESOURCE_TYPE_ADDRESS64:
302b7635a00Sjmcneill #ifdef _LP64
303b7635a00Sjmcneill 		/* XXX Only fixed size supported for now */
304e9c4d788Sjmcneill 		if (res->Data.Address64.Address.AddressLength == 0)
305b7635a00Sjmcneill 			break;
306b7635a00Sjmcneill #define ADDRESS64_FIXED2(r)						\
307b7635a00Sjmcneill 	((r)->Data.Address64.MinAddressFixed == ACPI_ADDRESS_FIXED &&	\
308b7635a00Sjmcneill 	 (r)->Data.Address64.MaxAddressFixed == ACPI_ADDRESS_FIXED)
309b7635a00Sjmcneill 		switch (res->Data.Address64.ResourceType) {
310b7635a00Sjmcneill 		case ACPI_MEMORY_RANGE:
311b7635a00Sjmcneill 			if (ADDRESS64_FIXED2(res)) {
312b7635a00Sjmcneill 				if (ops->memory)
313b7635a00Sjmcneill 					(*ops->memory)(arg->dev, arg->context,
314b7635a00Sjmcneill 					    res->Data.Address64.Address.Minimum,
315439fe919Sjmcneill 					    res->Data.Address64.Address.AddressLength,
3160dc1816eSjmcneill 					    res->Data.Address64.Address.Minimum +
3170dc1816eSjmcneill 					        res->Data.Address64.Address.TranslationOffset);
318b7635a00Sjmcneill 			} else {
319b7635a00Sjmcneill 				if (ops->memrange)
320b7635a00Sjmcneill 					(*ops->memrange)(arg->dev, arg->context,
321b7635a00Sjmcneill 					    res->Data.Address64.Address.Minimum,
322b7635a00Sjmcneill 					    res->Data.Address64.Address.Maximum,
323b7635a00Sjmcneill 					    res->Data.Address64.Address.AddressLength,
324b7635a00Sjmcneill 					    res->Data.Address64.Address.Granularity);
325b7635a00Sjmcneill 			}
326b7635a00Sjmcneill 			break;
327b7635a00Sjmcneill 		case ACPI_IO_RANGE:
328b7635a00Sjmcneill 			if (ADDRESS64_FIXED2(res)) {
329b7635a00Sjmcneill 				if (ops->ioport)
330b7635a00Sjmcneill 					(*ops->ioport)(arg->dev, arg->context,
331b7635a00Sjmcneill 					    res->Data.Address64.Address.Minimum,
332b7635a00Sjmcneill 					    res->Data.Address64.Address.AddressLength);
333b7635a00Sjmcneill 			} else {
334b7635a00Sjmcneill 				if (ops->iorange)
335b7635a00Sjmcneill 					(*ops->iorange)(arg->dev, arg->context,
336b7635a00Sjmcneill 					    res->Data.Address64.Address.Minimum,
337b7635a00Sjmcneill 					    res->Data.Address64.Address.Maximum,
338b7635a00Sjmcneill 					    res->Data.Address64.Address.AddressLength,
339b7635a00Sjmcneill 					    res->Data.Address64.Address.Granularity);
340b7635a00Sjmcneill 			}
341b7635a00Sjmcneill 			break;
342b7635a00Sjmcneill 		case ACPI_BUS_NUMBER_RANGE:
343b7635a00Sjmcneill 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
344b7635a00Sjmcneill 				      "Address64/BusNumber unimplemented\n"));
345b7635a00Sjmcneill 			break;
346b7635a00Sjmcneill 		}
347b7635a00Sjmcneill #undef ADDRESS64_FIXED2
348b7635a00Sjmcneill #else
34953b3110fSmsaitoh 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
35053b3110fSmsaitoh 				     "Address64 unimplemented\n"));
351b7635a00Sjmcneill #endif
35253b3110fSmsaitoh 		break;
3539e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
3549e72fe1eSkochi 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
3559e72fe1eSkochi 				     "Extended address64 unimplemented\n"));
3569e72fe1eSkochi 		break;
3579e72fe1eSkochi 
3589e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
359d3b539ecSjmcneill 		if (!arg->include_producer &&
360d3b539ecSjmcneill 		    res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
3616179b9baSthorpej 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
362e14284f1Skiyohara 			    "ignored ExtIRQ producer\n"));
363e14284f1Skiyohara 			break;
364e14284f1Skiyohara 		}
365e14284f1Skiyohara 		for (i = 0; i < res->Data.ExtendedIrq.InterruptCount; i++) {
366e14284f1Skiyohara 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
3674fcde464Sjruoho 				     "ExtIRQ %u\n",
368e14284f1Skiyohara 				     res->Data.ExtendedIrq.Interrupts[i]));
369e14284f1Skiyohara 			if (ops->irq)
370e14284f1Skiyohara 				(*ops->irq)(arg->dev, arg->context,
371e14284f1Skiyohara 				    res->Data.ExtendedIrq.Interrupts[i],
372e14284f1Skiyohara 				    res->Data.ExtendedIrq.Triggering);
373e14284f1Skiyohara 		}
3746179b9baSthorpej 		break;
3756179b9baSthorpej 
3769e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
3779e72fe1eSkochi 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
37869b70bfeSnjoly 				     "GenericRegister unimplemented\n"));
3799e72fe1eSkochi 		break;
3809e72fe1eSkochi 
3819e72fe1eSkochi 	case ACPI_RESOURCE_TYPE_VENDOR:
3826179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
3836179b9baSthorpej 				     "VendorSpecific unimplemented\n"));
3846179b9baSthorpej 		break;
3856179b9baSthorpej 
3866179b9baSthorpej 	default:
3876179b9baSthorpej 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
3884fcde464Sjruoho 				     "Unknown resource type: %u\n", res->Type));
3896179b9baSthorpej 		break;
3906179b9baSthorpej 	}
391b547a6d2Skochi 
39201e95b11Skochi 	return_ACPI_STATUS(AE_OK);
3936179b9baSthorpej }
3946179b9baSthorpej 
395b547a6d2Skochi 
396b547a6d2Skochi /*
397b547a6d2Skochi  * acpi_resource_parse:
398b547a6d2Skochi  *
399b547a6d2Skochi  *	Parse a device node's resources and fill them in for the
400b547a6d2Skochi  *	client.
401b547a6d2Skochi  *
402b547a6d2Skochi  *	This API supports _CRS (current resources) and
403b547a6d2Skochi  *	_PRS (possible resources).
404b547a6d2Skochi  *
405b547a6d2Skochi  *	Note that it might be nice to also locate ACPI-specific resource
406b547a6d2Skochi  *	items, such as GPE bits.
407b547a6d2Skochi  */
408b547a6d2Skochi ACPI_STATUS
40993dfc06dScegger acpi_resource_parse(device_t dev, ACPI_HANDLE handle, const char *path,
410b547a6d2Skochi     void *arg, const struct acpi_resource_parse_ops *ops)
411b547a6d2Skochi {
412b547a6d2Skochi 	struct resource_parse_callback_arg cbarg;
413b547a6d2Skochi 	ACPI_STATUS rv;
414b547a6d2Skochi 
4159b2b412cSperry 	ACPI_FUNCTION_TRACE(__func__);
416b547a6d2Skochi 
4170dd2fcbaSkochi 	if (ops->init)
418b547a6d2Skochi 		(*ops->init)(dev, arg, &cbarg.context);
4190dd2fcbaSkochi 	else
4200dd2fcbaSkochi 		cbarg.context = arg;
421b547a6d2Skochi 	cbarg.ops = ops;
422b547a6d2Skochi 	cbarg.dev = dev;
423d3b539ecSjmcneill 	cbarg.include_producer = false;
424b547a6d2Skochi 
425b547a6d2Skochi 	rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
426b547a6d2Skochi 	    &cbarg);
427b547a6d2Skochi 	if (ACPI_FAILURE(rv)) {
4284fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n",
4294fbe23fdSjmcneill 		    path, AcpiFormatException(rv));
430b547a6d2Skochi 		return_ACPI_STATUS(rv);
431b547a6d2Skochi 	}
432b547a6d2Skochi 
4330dd2fcbaSkochi 	if (ops->fini)
434b547a6d2Skochi 		(*ops->fini)(dev, cbarg.context);
4356179b9baSthorpej 
4366179b9baSthorpej 	return_ACPI_STATUS(AE_OK);
4376179b9baSthorpej }
4386179b9baSthorpej 
4396179b9baSthorpej /*
440d3b539ecSjmcneill  * acpi_resource_parse_any:
441d3b539ecSjmcneill  *
442d3b539ecSjmcneill  *	Parse a device node's resources and fill them in for the
443d3b539ecSjmcneill  *	client. Like acpi_resource_parse, but doesn't skip ResourceProducer
444d3b539ecSjmcneill  *	type resources.
445d3b539ecSjmcneill  */
446d3b539ecSjmcneill ACPI_STATUS
447d3b539ecSjmcneill acpi_resource_parse_any(device_t dev, ACPI_HANDLE handle, const char *path,
448d3b539ecSjmcneill     void *arg, const struct acpi_resource_parse_ops *ops)
449d3b539ecSjmcneill {
450d3b539ecSjmcneill 	struct resource_parse_callback_arg cbarg;
451d3b539ecSjmcneill 	ACPI_STATUS rv;
452d3b539ecSjmcneill 
453d3b539ecSjmcneill 	ACPI_FUNCTION_TRACE(__func__);
454d3b539ecSjmcneill 
455d3b539ecSjmcneill 	if (ops->init)
456d3b539ecSjmcneill 		(*ops->init)(dev, arg, &cbarg.context);
457d3b539ecSjmcneill 	else
458d3b539ecSjmcneill 		cbarg.context = arg;
459d3b539ecSjmcneill 	cbarg.ops = ops;
460d3b539ecSjmcneill 	cbarg.dev = dev;
461d3b539ecSjmcneill 	cbarg.include_producer = true;
462d3b539ecSjmcneill 
463d3b539ecSjmcneill 	rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
464d3b539ecSjmcneill 	    &cbarg);
465d3b539ecSjmcneill 	if (ACPI_FAILURE(rv)) {
466d3b539ecSjmcneill 		aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n",
467d3b539ecSjmcneill 		    path, AcpiFormatException(rv));
468d3b539ecSjmcneill 		return_ACPI_STATUS(rv);
469d3b539ecSjmcneill 	}
470d3b539ecSjmcneill 
471d3b539ecSjmcneill 	if (ops->fini)
472d3b539ecSjmcneill 		(*ops->fini)(dev, cbarg.context);
473d3b539ecSjmcneill 
474d3b539ecSjmcneill 	return_ACPI_STATUS(AE_OK);
475d3b539ecSjmcneill }
476d3b539ecSjmcneill 
477d3b539ecSjmcneill 
478d3b539ecSjmcneill /*
4796179b9baSthorpej  * acpi_resource_print:
4806179b9baSthorpej  *
4816179b9baSthorpej  *	Print the resources assigned to a device.
4826179b9baSthorpej  */
4836179b9baSthorpej void
48493dfc06dScegger acpi_resource_print(device_t dev, struct acpi_resources *res)
4856179b9baSthorpej {
4866179b9baSthorpej 	const char *sep;
4876179b9baSthorpej 
4886179b9baSthorpej 	if (SIMPLEQ_EMPTY(&res->ar_io) &&
4896179b9baSthorpej 	    SIMPLEQ_EMPTY(&res->ar_iorange) &&
4906179b9baSthorpej 	    SIMPLEQ_EMPTY(&res->ar_mem) &&
4916179b9baSthorpej 	    SIMPLEQ_EMPTY(&res->ar_memrange) &&
4926179b9baSthorpej 	    SIMPLEQ_EMPTY(&res->ar_irq) &&
4936179b9baSthorpej 	    SIMPLEQ_EMPTY(&res->ar_drq))
4946179b9baSthorpej 		return;
4956179b9baSthorpej 
496c315121aSjmcneill 	aprint_normal(":");
4976179b9baSthorpej 
4986179b9baSthorpej 	if (SIMPLEQ_EMPTY(&res->ar_io) == 0) {
4996179b9baSthorpej 		struct acpi_io *ar;
5006179b9baSthorpej 
5016179b9baSthorpej 		sep = "";
5024fbe23fdSjmcneill 		aprint_normal(" io ");
50306de4264Slukem 		SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
5044fbe23fdSjmcneill 			aprint_normal("%s0x%x", sep, ar->ar_base);
5056179b9baSthorpej 			if (ar->ar_length > 1)
5064fbe23fdSjmcneill 				aprint_normal("-0x%x", ar->ar_base +
5076179b9baSthorpej 				    ar->ar_length - 1);
5086179b9baSthorpej 			sep = ",";
5096179b9baSthorpej 		}
5106179b9baSthorpej 	}
5116179b9baSthorpej 
5126179b9baSthorpej 	/* XXX iorange */
5136179b9baSthorpej 
5146179b9baSthorpej 	if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) {
5156179b9baSthorpej 		struct acpi_mem *ar;
5166179b9baSthorpej 
5176179b9baSthorpej 		sep = "";
5184fbe23fdSjmcneill 		aprint_normal(" mem ");
51906de4264Slukem 		SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
520b7635a00Sjmcneill 			aprint_normal("%s0x%" PRIx64, sep,
521b7635a00Sjmcneill 			    (uint64_t)ar->ar_base);
5226179b9baSthorpej 			if (ar->ar_length > 1)
523b7635a00Sjmcneill 				aprint_normal("-0x%" PRIx64,
524b7635a00Sjmcneill 				    (uint64_t)ar->ar_base +
5256179b9baSthorpej 				    ar->ar_length - 1);
5266179b9baSthorpej 			sep = ",";
5276179b9baSthorpej 		}
5286179b9baSthorpej 	}
5296179b9baSthorpej 
5306179b9baSthorpej 	/* XXX memrange */
5316179b9baSthorpej 
5326179b9baSthorpej 	if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) {
5336179b9baSthorpej 		struct acpi_irq *ar;
5346179b9baSthorpej 
5356179b9baSthorpej 		sep = "";
5364fbe23fdSjmcneill 		aprint_normal(" irq ");
53706de4264Slukem 		SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
5384fbe23fdSjmcneill 			aprint_normal("%s%d", sep, ar->ar_irq);
5396179b9baSthorpej 			sep = ",";
5406179b9baSthorpej 		}
5416179b9baSthorpej 	}
5426179b9baSthorpej 
5436179b9baSthorpej 	if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) {
5446179b9baSthorpej 		struct acpi_drq *ar;
5456179b9baSthorpej 
5466179b9baSthorpej 		sep = "";
5474fbe23fdSjmcneill 		aprint_normal(" drq ");
54806de4264Slukem 		SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
5494fbe23fdSjmcneill 			aprint_normal("%s%d", sep, ar->ar_drq);
5506179b9baSthorpej 			sep = ",";
5516179b9baSthorpej 		}
5526179b9baSthorpej 	}
5536179b9baSthorpej 
5544fbe23fdSjmcneill 	aprint_normal("\n");
555c315121aSjmcneill 	aprint_naive("\n");
5566179b9baSthorpej }
5576179b9baSthorpej 
558193c08b3Skochi /*
559193c08b3Skochi  * acpi_resource_cleanup:
560193c08b3Skochi  *
561193c08b3Skochi  *	Free all allocated buffers
562193c08b3Skochi  */
563193c08b3Skochi void
564193c08b3Skochi acpi_resource_cleanup(struct acpi_resources *res)
565193c08b3Skochi {
566193c08b3Skochi 	while (!SIMPLEQ_EMPTY(&res->ar_io)) {
567193c08b3Skochi 		struct acpi_io *ar;
568193c08b3Skochi 		ar = SIMPLEQ_FIRST(&res->ar_io);
569193c08b3Skochi 		SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list);
57023ab96a3Smlelstv 		ACPI_FREE(ar);
571193c08b3Skochi 	}
572193c08b3Skochi 
573193c08b3Skochi 	while (!SIMPLEQ_EMPTY(&res->ar_iorange)) {
574193c08b3Skochi 		struct acpi_iorange *ar;
575193c08b3Skochi 		ar = SIMPLEQ_FIRST(&res->ar_iorange);
576193c08b3Skochi 		SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list);
57723ab96a3Smlelstv 		ACPI_FREE(ar);
578193c08b3Skochi 	}
579193c08b3Skochi 
580193c08b3Skochi 	while (!SIMPLEQ_EMPTY(&res->ar_mem)) {
581193c08b3Skochi 		struct acpi_mem *ar;
582193c08b3Skochi 		ar = SIMPLEQ_FIRST(&res->ar_mem);
583193c08b3Skochi 		SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list);
58423ab96a3Smlelstv 		ACPI_FREE(ar);
585193c08b3Skochi 	}
586193c08b3Skochi 
587193c08b3Skochi 	while (!SIMPLEQ_EMPTY(&res->ar_memrange)) {
588193c08b3Skochi 		struct acpi_memrange *ar;
589193c08b3Skochi 		ar = SIMPLEQ_FIRST(&res->ar_memrange);
590193c08b3Skochi 		SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list);
59123ab96a3Smlelstv 		ACPI_FREE(ar);
592193c08b3Skochi 	}
593193c08b3Skochi 
594193c08b3Skochi 	while (!SIMPLEQ_EMPTY(&res->ar_irq)) {
595193c08b3Skochi 		struct acpi_irq *ar;
596193c08b3Skochi 		ar = SIMPLEQ_FIRST(&res->ar_irq);
597193c08b3Skochi 		SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list);
59823ab96a3Smlelstv 		ACPI_FREE(ar);
599193c08b3Skochi 	}
600193c08b3Skochi 
601193c08b3Skochi 	while (!SIMPLEQ_EMPTY(&res->ar_drq)) {
602193c08b3Skochi 		struct acpi_drq *ar;
603193c08b3Skochi 		ar = SIMPLEQ_FIRST(&res->ar_drq);
604193c08b3Skochi 		SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list);
60523ab96a3Smlelstv 		ACPI_FREE(ar);
606193c08b3Skochi 	}
607193c08b3Skochi 
608193c08b3Skochi 	res->ar_nio = res->ar_niorange = res->ar_nmem =
609193c08b3Skochi 	    res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0;
610193c08b3Skochi }
611193c08b3Skochi 
6126179b9baSthorpej struct acpi_io *
6136179b9baSthorpej acpi_res_io(struct acpi_resources *res, int idx)
6146179b9baSthorpej {
6156179b9baSthorpej 	struct acpi_io *ar;
6166179b9baSthorpej 
6176179b9baSthorpej 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
6186179b9baSthorpej 		if (ar->ar_index == idx)
6192bde9b60Skochi 			return ar;
6206179b9baSthorpej 	}
6212bde9b60Skochi 	return NULL;
6226179b9baSthorpej }
6236179b9baSthorpej 
6246179b9baSthorpej struct acpi_iorange *
6256179b9baSthorpej acpi_res_iorange(struct acpi_resources *res, int idx)
6266179b9baSthorpej {
6276179b9baSthorpej 	struct acpi_iorange *ar;
6286179b9baSthorpej 
6296179b9baSthorpej 	SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) {
6306179b9baSthorpej 		if (ar->ar_index == idx)
6312bde9b60Skochi 			return ar;
6326179b9baSthorpej 	}
6332bde9b60Skochi 	return NULL;
6346179b9baSthorpej }
6356179b9baSthorpej 
6366179b9baSthorpej struct acpi_mem *
6376179b9baSthorpej acpi_res_mem(struct acpi_resources *res, int idx)
6386179b9baSthorpej {
6396179b9baSthorpej 	struct acpi_mem *ar;
6406179b9baSthorpej 
6416179b9baSthorpej 	SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
6426179b9baSthorpej 		if (ar->ar_index == idx)
6432bde9b60Skochi 			return ar;
6446179b9baSthorpej 	}
6452bde9b60Skochi 	return NULL;
6466179b9baSthorpej }
6476179b9baSthorpej 
6486179b9baSthorpej struct acpi_memrange *
6496179b9baSthorpej acpi_res_memrange(struct acpi_resources *res, int idx)
6506179b9baSthorpej {
6516179b9baSthorpej 	struct acpi_memrange *ar;
6526179b9baSthorpej 
6536179b9baSthorpej 	SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) {
6546179b9baSthorpej 		if (ar->ar_index == idx)
6552bde9b60Skochi 			return ar;
6566179b9baSthorpej 	}
6572bde9b60Skochi 	return NULL;
6586179b9baSthorpej }
6596179b9baSthorpej 
6606179b9baSthorpej struct acpi_irq *
6616179b9baSthorpej acpi_res_irq(struct acpi_resources *res, int idx)
6626179b9baSthorpej {
6636179b9baSthorpej 	struct acpi_irq *ar;
6646179b9baSthorpej 
6656179b9baSthorpej 	SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
6666179b9baSthorpej 		if (ar->ar_index == idx)
6672bde9b60Skochi 			return ar;
6686179b9baSthorpej 	}
6692bde9b60Skochi 	return NULL;
6706179b9baSthorpej }
6716179b9baSthorpej 
6726179b9baSthorpej struct acpi_drq *
6736179b9baSthorpej acpi_res_drq(struct acpi_resources *res, int idx)
6746179b9baSthorpej {
6756179b9baSthorpej 	struct acpi_drq *ar;
6766179b9baSthorpej 
6776179b9baSthorpej 	SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
6786179b9baSthorpej 		if (ar->ar_index == idx)
6792bde9b60Skochi 			return ar;
6806179b9baSthorpej 	}
6812bde9b60Skochi 	return NULL;
6826179b9baSthorpej }
6836179b9baSthorpej 
6846179b9baSthorpej /*****************************************************************************
6856179b9baSthorpej  * Default ACPI resource parse operations.
6866179b9baSthorpej  *****************************************************************************/
6876179b9baSthorpej 
68893dfc06dScegger static void	acpi_res_parse_init(device_t, void *, void **);
68993dfc06dScegger static void	acpi_res_parse_fini(device_t, void *);
6906179b9baSthorpej 
69193dfc06dScegger static void	acpi_res_parse_ioport(device_t, void *, uint32_t,
6926179b9baSthorpej 		    uint32_t);
69393dfc06dScegger static void	acpi_res_parse_iorange(device_t, void *, uint32_t,
6946179b9baSthorpej 		    uint32_t, uint32_t, uint32_t);
6956179b9baSthorpej 
696b7635a00Sjmcneill static void	acpi_res_parse_memory(device_t, void *, uint64_t,
6970dc1816eSjmcneill 		    uint64_t, uint64_t);
698b7635a00Sjmcneill static void	acpi_res_parse_memrange(device_t, void *, uint64_t,
699b7635a00Sjmcneill 		    uint64_t, uint64_t, uint64_t);
7006179b9baSthorpej 
70193dfc06dScegger static void	acpi_res_parse_irq(device_t, void *, uint32_t, uint32_t);
70293dfc06dScegger static void	acpi_res_parse_drq(device_t, void *, uint32_t);
7036179b9baSthorpej 
70493dfc06dScegger static void	acpi_res_parse_start_dep(device_t, void *, int);
70593dfc06dScegger static void	acpi_res_parse_end_dep(device_t, void *);
7066179b9baSthorpej 
7076179b9baSthorpej const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = {
7080dd2fcbaSkochi 	.init = acpi_res_parse_init,
7090dd2fcbaSkochi 	.fini = acpi_res_parse_fini,
7106179b9baSthorpej 
7110dd2fcbaSkochi 	.ioport = acpi_res_parse_ioport,
7120dd2fcbaSkochi 	.iorange = acpi_res_parse_iorange,
7136179b9baSthorpej 
7140dd2fcbaSkochi 	.memory = acpi_res_parse_memory,
7150dd2fcbaSkochi 	.memrange = acpi_res_parse_memrange,
7166179b9baSthorpej 
7170dd2fcbaSkochi 	.irq = acpi_res_parse_irq,
7180dd2fcbaSkochi 	.drq = acpi_res_parse_drq,
7196179b9baSthorpej 
7200dd2fcbaSkochi 	.start_dep = acpi_res_parse_start_dep,
7210dd2fcbaSkochi 	.end_dep = acpi_res_parse_end_dep,
7226179b9baSthorpej };
7236179b9baSthorpej 
724d67c24f0Sjruoho const struct acpi_resource_parse_ops acpi_resource_parse_ops_quiet = {
725d67c24f0Sjruoho 	.init = acpi_res_parse_init,
726d67c24f0Sjruoho 	.fini = NULL,
727d67c24f0Sjruoho 
728d67c24f0Sjruoho 	.ioport = acpi_res_parse_ioport,
729d67c24f0Sjruoho 	.iorange = acpi_res_parse_iorange,
730d67c24f0Sjruoho 
731d67c24f0Sjruoho 	.memory = acpi_res_parse_memory,
732d67c24f0Sjruoho 	.memrange = acpi_res_parse_memrange,
733d67c24f0Sjruoho 
734d67c24f0Sjruoho 	.irq = acpi_res_parse_irq,
735d67c24f0Sjruoho 	.drq = acpi_res_parse_drq,
736d67c24f0Sjruoho 
737d67c24f0Sjruoho 	.start_dep = acpi_res_parse_start_dep,
738d67c24f0Sjruoho 	.end_dep = acpi_res_parse_end_dep,
739d67c24f0Sjruoho };
740d67c24f0Sjruoho 
7416179b9baSthorpej static void
74293dfc06dScegger acpi_res_parse_init(device_t dev, void *arg, void **contextp)
7436179b9baSthorpej {
7446179b9baSthorpej 	struct acpi_resources *res = arg;
7456179b9baSthorpej 
7466179b9baSthorpej 	SIMPLEQ_INIT(&res->ar_io);
7476179b9baSthorpej 	res->ar_nio = 0;
7486179b9baSthorpej 
7496179b9baSthorpej 	SIMPLEQ_INIT(&res->ar_iorange);
7506179b9baSthorpej 	res->ar_niorange = 0;
7516179b9baSthorpej 
7526179b9baSthorpej 	SIMPLEQ_INIT(&res->ar_mem);
7536179b9baSthorpej 	res->ar_nmem = 0;
7546179b9baSthorpej 
7556179b9baSthorpej 	SIMPLEQ_INIT(&res->ar_memrange);
7566179b9baSthorpej 	res->ar_nmemrange = 0;
7576179b9baSthorpej 
7586179b9baSthorpej 	SIMPLEQ_INIT(&res->ar_irq);
7596179b9baSthorpej 	res->ar_nirq = 0;
7606179b9baSthorpej 
7616179b9baSthorpej 	SIMPLEQ_INIT(&res->ar_drq);
7626179b9baSthorpej 	res->ar_ndrq = 0;
7636179b9baSthorpej 
7646179b9baSthorpej 	*contextp = res;
7656179b9baSthorpej }
7666179b9baSthorpej 
7676179b9baSthorpej static void
76893dfc06dScegger acpi_res_parse_fini(device_t dev, void *context)
7696179b9baSthorpej {
7706179b9baSthorpej 	struct acpi_resources *res = context;
7716179b9baSthorpej 
7726179b9baSthorpej 	/* Print the resources we're using. */
7736179b9baSthorpej 	acpi_resource_print(dev, res);
7746179b9baSthorpej }
7756179b9baSthorpej 
7766179b9baSthorpej static void
77793dfc06dScegger acpi_res_parse_ioport(device_t dev, void *context, uint32_t base,
7786179b9baSthorpej     uint32_t length)
7796179b9baSthorpej {
7806179b9baSthorpej 	struct acpi_resources *res = context;
7816179b9baSthorpej 	struct acpi_io *ar;
7826179b9baSthorpej 
783076f4674Sjdolecek 	/*
784076f4674Sjdolecek 	 * Check if there is another I/O port directly below/under
785076f4674Sjdolecek 	 * this one.
786076f4674Sjdolecek 	 */
787076f4674Sjdolecek 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
788076f4674Sjdolecek 		if (ar->ar_base == base + length ) {
789076f4674Sjdolecek 			/*
790076f4674Sjdolecek 			 * Entry just below existing entry - adjust
791076f4674Sjdolecek 			 * the entry and return.
792076f4674Sjdolecek 			 */
793076f4674Sjdolecek 			ar->ar_base = base;
794076f4674Sjdolecek 			ar->ar_length += length;
795076f4674Sjdolecek 			return;
796076f4674Sjdolecek 		} else if (ar->ar_base + ar->ar_length == base) {
797076f4674Sjdolecek 			/*
798076f4674Sjdolecek 			 * Entry just above existing entry - adjust
799076f4674Sjdolecek 			 * the entry and return.
800076f4674Sjdolecek 			 */
801076f4674Sjdolecek 			ar->ar_length += length;
802076f4674Sjdolecek 			return;
803076f4674Sjdolecek 		}
804076f4674Sjdolecek 	}
805076f4674Sjdolecek 
806*b0bb4503Sandvar 	/* IO and FixedIO I/O resource addresses are limited to 10/16-bit. */
807*b0bb4503Sandvar 	if (base + length - 1 > UINT16_MAX) {
808*b0bb4503Sandvar 		aprint_error_dev(dev, "ACPI: invalid I/O register resource %d,"
809*b0bb4503Sandvar 		    " base 0x%x, length %d\n",
810*b0bb4503Sandvar 		    res->ar_nio, base, length);
811*b0bb4503Sandvar 		res->ar_nio++;
812*b0bb4503Sandvar 		return;
813*b0bb4503Sandvar 	}
814*b0bb4503Sandvar 
81523ab96a3Smlelstv 	ar = ACPI_ALLOCATE(sizeof(*ar));
8166179b9baSthorpej 	if (ar == NULL) {
8174fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n",
8184fbe23fdSjmcneill 		    res->ar_nio);
8196179b9baSthorpej 		res->ar_nio++;
8206179b9baSthorpej 		return;
8216179b9baSthorpej 	}
8226179b9baSthorpej 
8236179b9baSthorpej 	ar->ar_index = res->ar_nio++;
8246179b9baSthorpej 	ar->ar_base = base;
8256179b9baSthorpej 	ar->ar_length = length;
8266179b9baSthorpej 
8276179b9baSthorpej 	SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list);
8286179b9baSthorpej }
8296179b9baSthorpej 
8306179b9baSthorpej static void
83193dfc06dScegger acpi_res_parse_iorange(device_t dev, void *context, uint32_t low,
8326179b9baSthorpej     uint32_t high, uint32_t length, uint32_t align)
8336179b9baSthorpej {
8346179b9baSthorpej 	struct acpi_resources *res = context;
8356179b9baSthorpej 	struct acpi_iorange *ar;
8366179b9baSthorpej 
83723ab96a3Smlelstv 	ar = ACPI_ALLOCATE(sizeof(*ar));
8386179b9baSthorpej 	if (ar == NULL) {
8394fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n",
8404fbe23fdSjmcneill 		    res->ar_niorange);
8416179b9baSthorpej 		res->ar_niorange++;
8426179b9baSthorpej 		return;
8436179b9baSthorpej 	}
8446179b9baSthorpej 
8456179b9baSthorpej 	ar->ar_index = res->ar_niorange++;
8466179b9baSthorpej 	ar->ar_low = low;
8476179b9baSthorpej 	ar->ar_high = high;
8486179b9baSthorpej 	ar->ar_length = length;
8496179b9baSthorpej 	ar->ar_align = align;
8506179b9baSthorpej 
8516179b9baSthorpej 	SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list);
8526179b9baSthorpej }
8536179b9baSthorpej 
8546179b9baSthorpej static void
855b7635a00Sjmcneill acpi_res_parse_memory(device_t dev, void *context, uint64_t base,
8560dc1816eSjmcneill     uint64_t length, uint64_t xbase)
8576179b9baSthorpej {
8586179b9baSthorpej 	struct acpi_resources *res = context;
8596179b9baSthorpej 	struct acpi_mem *ar;
8606179b9baSthorpej 
86123ab96a3Smlelstv 	ar = ACPI_ALLOCATE(sizeof(*ar));
8626179b9baSthorpej 	if (ar == NULL) {
8634fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n",
8644fbe23fdSjmcneill 		    res->ar_nmem);
8656179b9baSthorpej 		res->ar_nmem++;
8666179b9baSthorpej 		return;
8676179b9baSthorpej 	}
8686179b9baSthorpej 
8696179b9baSthorpej 	ar->ar_index = res->ar_nmem++;
8706179b9baSthorpej 	ar->ar_base = base;
8716179b9baSthorpej 	ar->ar_length = length;
8720dc1816eSjmcneill 	ar->ar_xbase = xbase;
8736179b9baSthorpej 
8746179b9baSthorpej 	SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list);
8756179b9baSthorpej }
8766179b9baSthorpej 
8776179b9baSthorpej static void
878b7635a00Sjmcneill acpi_res_parse_memrange(device_t dev, void *context, uint64_t low,
879b7635a00Sjmcneill     uint64_t high, uint64_t length, uint64_t align)
8806179b9baSthorpej {
8816179b9baSthorpej 	struct acpi_resources *res = context;
8826179b9baSthorpej 	struct acpi_memrange *ar;
8836179b9baSthorpej 
88423ab96a3Smlelstv 	ar = ACPI_ALLOCATE(sizeof(*ar));
8856179b9baSthorpej 	if (ar == NULL) {
8864fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n",
8874fbe23fdSjmcneill 		    res->ar_nmemrange);
8886179b9baSthorpej 		res->ar_nmemrange++;
8896179b9baSthorpej 		return;
8906179b9baSthorpej 	}
8916179b9baSthorpej 
8926179b9baSthorpej 	ar->ar_index = res->ar_nmemrange++;
8936179b9baSthorpej 	ar->ar_low = low;
8946179b9baSthorpej 	ar->ar_high = high;
8956179b9baSthorpej 	ar->ar_length = length;
8966179b9baSthorpej 	ar->ar_align = align;
8976179b9baSthorpej 
8986179b9baSthorpej 	SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list);
8996179b9baSthorpej }
9006179b9baSthorpej 
9016179b9baSthorpej static void
90293dfc06dScegger acpi_res_parse_irq(device_t dev, void *context, uint32_t irq, uint32_t type)
9036179b9baSthorpej {
9046179b9baSthorpej 	struct acpi_resources *res = context;
9056179b9baSthorpej 	struct acpi_irq *ar;
9066179b9baSthorpej 
90723ab96a3Smlelstv 	ar = ACPI_ALLOCATE(sizeof(*ar));
9086179b9baSthorpej 	if (ar == NULL) {
9094fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n",
9104fbe23fdSjmcneill 		    res->ar_nirq);
9116179b9baSthorpej 		res->ar_nirq++;
9126179b9baSthorpej 		return;
9136179b9baSthorpej 	}
9146179b9baSthorpej 
9156179b9baSthorpej 	ar->ar_index = res->ar_nirq++;
9166179b9baSthorpej 	ar->ar_irq = irq;
917da1df3d5Smatt 	ar->ar_type = type;
9186179b9baSthorpej 
9196179b9baSthorpej 	SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list);
9206179b9baSthorpej }
9216179b9baSthorpej 
9226179b9baSthorpej static void
92393dfc06dScegger acpi_res_parse_drq(device_t dev, void *context, uint32_t drq)
9246179b9baSthorpej {
9256179b9baSthorpej 	struct acpi_resources *res = context;
9266179b9baSthorpej 	struct acpi_drq *ar;
9276179b9baSthorpej 
92823ab96a3Smlelstv 	ar = ACPI_ALLOCATE(sizeof(*ar));
9296179b9baSthorpej 	if (ar == NULL) {
9304fbe23fdSjmcneill 		aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n",
9314fbe23fdSjmcneill 		    res->ar_ndrq);
9326179b9baSthorpej 		res->ar_ndrq++;
9336179b9baSthorpej 		return;
9346179b9baSthorpej 	}
9356179b9baSthorpej 
9366179b9baSthorpej 	ar->ar_index = res->ar_ndrq++;
9376179b9baSthorpej 	ar->ar_drq = drq;
9386179b9baSthorpej 
9396179b9baSthorpej 	SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list);
9406179b9baSthorpej }
9416179b9baSthorpej 
9426179b9baSthorpej static void
94393dfc06dScegger acpi_res_parse_start_dep(device_t dev, void *context,
944168cd830Schristos     int preference)
9456179b9baSthorpej {
9466179b9baSthorpej 
9474cbd24b2Swiz 	aprint_error_dev(dev, "ACPI: dependent functions not supported\n");
9486179b9baSthorpej }
9496179b9baSthorpej 
9506179b9baSthorpej static void
95193dfc06dScegger acpi_res_parse_end_dep(device_t dev, void *context)
9526179b9baSthorpej {
9536179b9baSthorpej 
9546179b9baSthorpej 	/* Nothing to do. */
9556179b9baSthorpej }
956