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