1*5db2f26eSSascha Wildner /*- 2*5db2f26eSSascha Wildner * Copyright (c) 2000 Michael Smith 3*5db2f26eSSascha Wildner * Copyright (c) 2000 BSDi 4*5db2f26eSSascha Wildner * All rights reserved. 5*5db2f26eSSascha Wildner * 6*5db2f26eSSascha Wildner * Redistribution and use in source and binary forms, with or without 7*5db2f26eSSascha Wildner * modification, are permitted provided that the following conditions 8*5db2f26eSSascha Wildner * are met: 9*5db2f26eSSascha Wildner * 1. Redistributions of source code must retain the above copyright 10*5db2f26eSSascha Wildner * notice, this list of conditions and the following disclaimer. 11*5db2f26eSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 12*5db2f26eSSascha Wildner * notice, this list of conditions and the following disclaimer in the 13*5db2f26eSSascha Wildner * documentation and/or other materials provided with the distribution. 14*5db2f26eSSascha Wildner * 15*5db2f26eSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*5db2f26eSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*5db2f26eSSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*5db2f26eSSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*5db2f26eSSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*5db2f26eSSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*5db2f26eSSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*5db2f26eSSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*5db2f26eSSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*5db2f26eSSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*5db2f26eSSascha Wildner * SUCH DAMAGE. 26*5db2f26eSSascha Wildner * 27*5db2f26eSSascha Wildner * $FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.40.8.1 2009/04/15 03:14:26 kensmith Exp $ 28*5db2f26eSSascha Wildner */ 29*5db2f26eSSascha Wildner 30*5db2f26eSSascha Wildner #include "opt_acpi.h" 31*5db2f26eSSascha Wildner #include <sys/param.h> 32*5db2f26eSSascha Wildner #include <sys/kernel.h> 33*5db2f26eSSascha Wildner #include <sys/bus.h> 34*5db2f26eSSascha Wildner #include <sys/malloc.h> 35*5db2f26eSSascha Wildner #include <sys/module.h> 36*5db2f26eSSascha Wildner #include <sys/resource.h> 37*5db2f26eSSascha Wildner #include <sys/machintr.h> 38*5db2f26eSSascha Wildner 39*5db2f26eSSascha Wildner #include <sys/rman.h> 40*5db2f26eSSascha Wildner 41*5db2f26eSSascha Wildner #include "acpi.h" 42*5db2f26eSSascha Wildner #include <dev/acpica/acpivar.h> 43*5db2f26eSSascha Wildner 44*5db2f26eSSascha Wildner /* Hooks for the ACPI CA debugging infrastructure */ 45*5db2f26eSSascha Wildner #define _COMPONENT ACPI_BUS 46*5db2f26eSSascha Wildner ACPI_MODULE_NAME("RESOURCE") 47*5db2f26eSSascha Wildner 48*5db2f26eSSascha Wildner struct lookup_irq_request { 49*5db2f26eSSascha Wildner ACPI_RESOURCE *acpi_res; 50*5db2f26eSSascha Wildner struct resource *res; 51*5db2f26eSSascha Wildner int counter; 52*5db2f26eSSascha Wildner int rid; 53*5db2f26eSSascha Wildner int found; 54*5db2f26eSSascha Wildner }; 55*5db2f26eSSascha Wildner 56*5db2f26eSSascha Wildner static ACPI_STATUS 57*5db2f26eSSascha Wildner acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context) 58*5db2f26eSSascha Wildner { 59*5db2f26eSSascha Wildner struct lookup_irq_request *req; 60*5db2f26eSSascha Wildner size_t len; 61*5db2f26eSSascha Wildner u_int irqnum, irq; 62*5db2f26eSSascha Wildner 63*5db2f26eSSascha Wildner switch (res->Type) { 64*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_IRQ: 65*5db2f26eSSascha Wildner irqnum = res->Data.Irq.InterruptCount; 66*5db2f26eSSascha Wildner irq = res->Data.Irq.Interrupts[0]; 67*5db2f26eSSascha Wildner len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ); 68*5db2f26eSSascha Wildner break; 69*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 70*5db2f26eSSascha Wildner irqnum = res->Data.ExtendedIrq.InterruptCount; 71*5db2f26eSSascha Wildner irq = res->Data.ExtendedIrq.Interrupts[0]; 72*5db2f26eSSascha Wildner len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ); 73*5db2f26eSSascha Wildner break; 74*5db2f26eSSascha Wildner default: 75*5db2f26eSSascha Wildner return (AE_OK); 76*5db2f26eSSascha Wildner } 77*5db2f26eSSascha Wildner if (irqnum != 1) 78*5db2f26eSSascha Wildner return (AE_OK); 79*5db2f26eSSascha Wildner req = (struct lookup_irq_request *)context; 80*5db2f26eSSascha Wildner if (req->counter != req->rid) { 81*5db2f26eSSascha Wildner req->counter++; 82*5db2f26eSSascha Wildner return (AE_OK); 83*5db2f26eSSascha Wildner } 84*5db2f26eSSascha Wildner req->found = 1; 85*5db2f26eSSascha Wildner KASSERT(irq == rman_get_start(req->res), 86*5db2f26eSSascha Wildner ("IRQ resources do not match")); 87*5db2f26eSSascha Wildner bcopy(res, req->acpi_res, len); 88*5db2f26eSSascha Wildner return (AE_CTRL_TERMINATE); 89*5db2f26eSSascha Wildner } 90*5db2f26eSSascha Wildner 91*5db2f26eSSascha Wildner ACPI_STATUS 92*5db2f26eSSascha Wildner acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res, 93*5db2f26eSSascha Wildner ACPI_RESOURCE *acpi_res) 94*5db2f26eSSascha Wildner { 95*5db2f26eSSascha Wildner struct lookup_irq_request req; 96*5db2f26eSSascha Wildner ACPI_STATUS status; 97*5db2f26eSSascha Wildner 98*5db2f26eSSascha Wildner req.acpi_res = acpi_res; 99*5db2f26eSSascha Wildner req.res = res; 100*5db2f26eSSascha Wildner req.counter = 0; 101*5db2f26eSSascha Wildner req.rid = rid; 102*5db2f26eSSascha Wildner req.found = 0; 103*5db2f26eSSascha Wildner status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", 104*5db2f26eSSascha Wildner acpi_lookup_irq_handler, &req); 105*5db2f26eSSascha Wildner if (ACPI_SUCCESS(status) && req.found == 0) 106*5db2f26eSSascha Wildner status = AE_NOT_FOUND; 107*5db2f26eSSascha Wildner return (status); 108*5db2f26eSSascha Wildner } 109*5db2f26eSSascha Wildner 110*5db2f26eSSascha Wildner void 111*5db2f26eSSascha Wildner acpi_config_intr(device_t dev, ACPI_RESOURCE *res) 112*5db2f26eSSascha Wildner { 113*5db2f26eSSascha Wildner u_int irq; 114*5db2f26eSSascha Wildner int pol, trig; 115*5db2f26eSSascha Wildner enum intr_trigger trigger; 116*5db2f26eSSascha Wildner enum intr_polarity polarity; 117*5db2f26eSSascha Wildner 118*5db2f26eSSascha Wildner switch (res->Type) { 119*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_IRQ: 120*5db2f26eSSascha Wildner KASSERT(res->Data.Irq.InterruptCount == 1, 121*5db2f26eSSascha Wildner ("%s: multiple interrupts", __func__)); 122*5db2f26eSSascha Wildner irq = res->Data.Irq.Interrupts[0]; 123*5db2f26eSSascha Wildner trig = res->Data.Irq.Triggering; 124*5db2f26eSSascha Wildner pol = res->Data.Irq.Polarity; 125*5db2f26eSSascha Wildner break; 126*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 127*5db2f26eSSascha Wildner KASSERT(res->Data.ExtendedIrq.InterruptCount == 1, 128*5db2f26eSSascha Wildner ("%s: multiple interrupts", __func__)); 129*5db2f26eSSascha Wildner irq = res->Data.ExtendedIrq.Interrupts[0]; 130*5db2f26eSSascha Wildner trig = res->Data.ExtendedIrq.Triggering; 131*5db2f26eSSascha Wildner pol = res->Data.ExtendedIrq.Polarity; 132*5db2f26eSSascha Wildner break; 133*5db2f26eSSascha Wildner default: 134*5db2f26eSSascha Wildner panic("%s: bad resource type %u", __func__, res->Type); 135*5db2f26eSSascha Wildner } 136*5db2f26eSSascha Wildner 137*5db2f26eSSascha Wildner if (trig == ACPI_EDGE_SENSITIVE) 138*5db2f26eSSascha Wildner trigger = INTR_TRIGGER_EDGE; 139*5db2f26eSSascha Wildner else 140*5db2f26eSSascha Wildner trigger = INTR_TRIGGER_LEVEL; 141*5db2f26eSSascha Wildner 142*5db2f26eSSascha Wildner if (pol == ACPI_ACTIVE_HIGH) 143*5db2f26eSSascha Wildner polarity = INTR_POLARITY_HIGH; 144*5db2f26eSSascha Wildner else 145*5db2f26eSSascha Wildner polarity = INTR_POLARITY_LOW; 146*5db2f26eSSascha Wildner 147*5db2f26eSSascha Wildner if (machintr_legacy_intr_find(irq, trigger, polarity) < 0) 148*5db2f26eSSascha Wildner kprintf("acpi_config_intr: Skip irq %d config\n", irq); 149*5db2f26eSSascha Wildner else 150*5db2f26eSSascha Wildner BUS_CONFIG_INTR(dev, dev, irq, trigger, polarity); 151*5db2f26eSSascha Wildner } 152*5db2f26eSSascha Wildner 153*5db2f26eSSascha Wildner /* 154*5db2f26eSSascha Wildner * Fetch a device's resources and associate them with the device. 155*5db2f26eSSascha Wildner * 156*5db2f26eSSascha Wildner * Note that it might be nice to also locate ACPI-specific resource items, such 157*5db2f26eSSascha Wildner * as GPE bits. 158*5db2f26eSSascha Wildner * 159*5db2f26eSSascha Wildner * We really need to split the resource-fetching code out from the 160*5db2f26eSSascha Wildner * resource-parsing code, since we may want to use the parsing 161*5db2f26eSSascha Wildner * code for _PRS someday. 162*5db2f26eSSascha Wildner */ 163*5db2f26eSSascha Wildner ACPI_STATUS 164*5db2f26eSSascha Wildner acpi_parse_resources(device_t dev, ACPI_HANDLE handle, 165*5db2f26eSSascha Wildner struct acpi_parse_resource_set *set, void *arg) 166*5db2f26eSSascha Wildner { 167*5db2f26eSSascha Wildner ACPI_BUFFER buf; 168*5db2f26eSSascha Wildner ACPI_RESOURCE *res; 169*5db2f26eSSascha Wildner char *curr, *last; 170*5db2f26eSSascha Wildner ACPI_STATUS status; 171*5db2f26eSSascha Wildner void *context; 172*5db2f26eSSascha Wildner 173*5db2f26eSSascha Wildner ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 174*5db2f26eSSascha Wildner 175*5db2f26eSSascha Wildner /* 176*5db2f26eSSascha Wildner * Special-case some devices that abuse _PRS/_CRS to mean 177*5db2f26eSSascha Wildner * something other than "I consume this resource". 178*5db2f26eSSascha Wildner * 179*5db2f26eSSascha Wildner * XXX do we really need this? It's only relevant once 180*5db2f26eSSascha Wildner * we start always-allocating these resources, and even 181*5db2f26eSSascha Wildner * then, the only special-cased device is likely to be 182*5db2f26eSSascha Wildner * the PCI interrupt link. 183*5db2f26eSSascha Wildner */ 184*5db2f26eSSascha Wildner 185*5db2f26eSSascha Wildner /* Fetch the device's current resources. */ 186*5db2f26eSSascha Wildner buf.Length = ACPI_ALLOCATE_BUFFER; 187*5db2f26eSSascha Wildner if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) { 188*5db2f26eSSascha Wildner if (status != AE_NOT_FOUND && status != AE_TYPE) 189*5db2f26eSSascha Wildner kprintf("can't fetch resources for %s - %s\n", 190*5db2f26eSSascha Wildner acpi_name(handle), AcpiFormatException(status)); 191*5db2f26eSSascha Wildner return_ACPI_STATUS (status); 192*5db2f26eSSascha Wildner } 193*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n", 194*5db2f26eSSascha Wildner acpi_name(handle), (long)buf.Length)); 195*5db2f26eSSascha Wildner set->set_init(dev, arg, &context); 196*5db2f26eSSascha Wildner 197*5db2f26eSSascha Wildner /* Iterate through the resources */ 198*5db2f26eSSascha Wildner curr = buf.Pointer; 199*5db2f26eSSascha Wildner last = (char *)buf.Pointer + buf.Length; 200*5db2f26eSSascha Wildner while (curr < last) { 201*5db2f26eSSascha Wildner res = (ACPI_RESOURCE *)curr; 202*5db2f26eSSascha Wildner curr += res->Length; 203*5db2f26eSSascha Wildner 204*5db2f26eSSascha Wildner /* Handle the individual resource types */ 205*5db2f26eSSascha Wildner switch(res->Type) { 206*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_END_TAG: 207*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); 208*5db2f26eSSascha Wildner curr = last; 209*5db2f26eSSascha Wildner break; 210*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_FIXED_IO: 211*5db2f26eSSascha Wildner if (res->Data.FixedIo.AddressLength <= 0) 212*5db2f26eSSascha Wildner break; 213*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n", 214*5db2f26eSSascha Wildner res->Data.FixedIo.Address, 215*5db2f26eSSascha Wildner res->Data.FixedIo.AddressLength)); 216*5db2f26eSSascha Wildner set->set_ioport(dev, context, 217*5db2f26eSSascha Wildner res->Data.FixedIo.Address, 218*5db2f26eSSascha Wildner res->Data.FixedIo.AddressLength); 219*5db2f26eSSascha Wildner break; 220*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_IO: 221*5db2f26eSSascha Wildner if (res->Data.Io.AddressLength <= 0) 222*5db2f26eSSascha Wildner break; 223*5db2f26eSSascha Wildner if (res->Data.Io.Minimum == res->Data.Io.Maximum) { 224*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n", 225*5db2f26eSSascha Wildner res->Data.Io.Minimum, 226*5db2f26eSSascha Wildner res->Data.Io.AddressLength)); 227*5db2f26eSSascha Wildner set->set_ioport(dev, context, 228*5db2f26eSSascha Wildner res->Data.Io.Minimum, 229*5db2f26eSSascha Wildner res->Data.Io.AddressLength); 230*5db2f26eSSascha Wildner } else { 231*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n", 232*5db2f26eSSascha Wildner res->Data.Io.Minimum, 233*5db2f26eSSascha Wildner res->Data.Io.Maximum, 234*5db2f26eSSascha Wildner res->Data.Io.AddressLength)); 235*5db2f26eSSascha Wildner set->set_iorange(dev, context, 236*5db2f26eSSascha Wildner res->Data.Io.Minimum, 237*5db2f26eSSascha Wildner res->Data.Io.Maximum, 238*5db2f26eSSascha Wildner res->Data.Io.AddressLength, 239*5db2f26eSSascha Wildner res->Data.Io.Alignment); 240*5db2f26eSSascha Wildner } 241*5db2f26eSSascha Wildner break; 242*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 243*5db2f26eSSascha Wildner if (res->Data.FixedMemory32.AddressLength <= 0) 244*5db2f26eSSascha Wildner break; 245*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n", 246*5db2f26eSSascha Wildner res->Data.FixedMemory32.Address, 247*5db2f26eSSascha Wildner res->Data.FixedMemory32.AddressLength)); 248*5db2f26eSSascha Wildner set->set_memory(dev, context, 249*5db2f26eSSascha Wildner res->Data.FixedMemory32.Address, 250*5db2f26eSSascha Wildner res->Data.FixedMemory32.AddressLength); 251*5db2f26eSSascha Wildner break; 252*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_MEMORY32: 253*5db2f26eSSascha Wildner if (res->Data.Memory32.AddressLength <= 0) 254*5db2f26eSSascha Wildner break; 255*5db2f26eSSascha Wildner if (res->Data.Memory32.Minimum == 256*5db2f26eSSascha Wildner res->Data.Memory32.Maximum) { 257*5db2f26eSSascha Wildner 258*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n", 259*5db2f26eSSascha Wildner res->Data.Memory32.Minimum, 260*5db2f26eSSascha Wildner res->Data.Memory32.AddressLength)); 261*5db2f26eSSascha Wildner set->set_memory(dev, context, 262*5db2f26eSSascha Wildner res->Data.Memory32.Minimum, 263*5db2f26eSSascha Wildner res->Data.Memory32.AddressLength); 264*5db2f26eSSascha Wildner } else { 265*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n", 266*5db2f26eSSascha Wildner res->Data.Memory32.Minimum, 267*5db2f26eSSascha Wildner res->Data.Memory32.Maximum, 268*5db2f26eSSascha Wildner res->Data.Memory32.AddressLength)); 269*5db2f26eSSascha Wildner set->set_memoryrange(dev, context, 270*5db2f26eSSascha Wildner res->Data.Memory32.Minimum, 271*5db2f26eSSascha Wildner res->Data.Memory32.Maximum, 272*5db2f26eSSascha Wildner res->Data.Memory32.AddressLength, 273*5db2f26eSSascha Wildner res->Data.Memory32.Alignment); 274*5db2f26eSSascha Wildner } 275*5db2f26eSSascha Wildner break; 276*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_MEMORY24: 277*5db2f26eSSascha Wildner if (res->Data.Memory24.AddressLength <= 0) 278*5db2f26eSSascha Wildner break; 279*5db2f26eSSascha Wildner if (res->Data.Memory24.Minimum == 280*5db2f26eSSascha Wildner res->Data.Memory24.Maximum) { 281*5db2f26eSSascha Wildner 282*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n", 283*5db2f26eSSascha Wildner res->Data.Memory24.Minimum, 284*5db2f26eSSascha Wildner res->Data.Memory24.AddressLength)); 285*5db2f26eSSascha Wildner set->set_memory(dev, context, res->Data.Memory24.Minimum, 286*5db2f26eSSascha Wildner res->Data.Memory24.AddressLength); 287*5db2f26eSSascha Wildner } else { 288*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n", 289*5db2f26eSSascha Wildner res->Data.Memory24.Minimum, 290*5db2f26eSSascha Wildner res->Data.Memory24.Maximum, 291*5db2f26eSSascha Wildner res->Data.Memory24.AddressLength)); 292*5db2f26eSSascha Wildner set->set_memoryrange(dev, context, 293*5db2f26eSSascha Wildner res->Data.Memory24.Minimum, 294*5db2f26eSSascha Wildner res->Data.Memory24.Maximum, 295*5db2f26eSSascha Wildner res->Data.Memory24.AddressLength, 296*5db2f26eSSascha Wildner res->Data.Memory24.Alignment); 297*5db2f26eSSascha Wildner } 298*5db2f26eSSascha Wildner break; 299*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_IRQ: 300*5db2f26eSSascha Wildner /* 301*5db2f26eSSascha Wildner * from 1.0b 6.4.2 302*5db2f26eSSascha Wildner * "This structure is repeated for each separate interrupt 303*5db2f26eSSascha Wildner * required" 304*5db2f26eSSascha Wildner */ 305*5db2f26eSSascha Wildner set->set_irq(dev, context, res->Data.Irq.Interrupts, 306*5db2f26eSSascha Wildner res->Data.Irq.InterruptCount, res->Data.Irq.Triggering, 307*5db2f26eSSascha Wildner res->Data.Irq.Polarity); 308*5db2f26eSSascha Wildner break; 309*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_DMA: 310*5db2f26eSSascha Wildner /* 311*5db2f26eSSascha Wildner * from 1.0b 6.4.3 312*5db2f26eSSascha Wildner * "This structure is repeated for each separate dma channel 313*5db2f26eSSascha Wildner * required" 314*5db2f26eSSascha Wildner */ 315*5db2f26eSSascha Wildner set->set_drq(dev, context, res->Data.Dma.Channels, 316*5db2f26eSSascha Wildner res->Data.Dma.ChannelCount); 317*5db2f26eSSascha Wildner break; 318*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_START_DEPENDENT: 319*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n")); 320*5db2f26eSSascha Wildner set->set_start_dependent(dev, context, 321*5db2f26eSSascha Wildner res->Data.StartDpf.CompatibilityPriority); 322*5db2f26eSSascha Wildner break; 323*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_END_DEPENDENT: 324*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n")); 325*5db2f26eSSascha Wildner set->set_end_dependent(dev, context); 326*5db2f26eSSascha Wildner break; 327*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_ADDRESS32: 328*5db2f26eSSascha Wildner if (res->Data.Address32.AddressLength <= 0) 329*5db2f26eSSascha Wildner break; 330*5db2f26eSSascha Wildner if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) { 331*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 332*5db2f26eSSascha Wildner "ignored Address32 %s producer\n", 333*5db2f26eSSascha Wildner res->Data.Address32.ResourceType == ACPI_IO_RANGE ? 334*5db2f26eSSascha Wildner "IO" : "Memory")); 335*5db2f26eSSascha Wildner break; 336*5db2f26eSSascha Wildner } 337*5db2f26eSSascha Wildner if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE && 338*5db2f26eSSascha Wildner res->Data.Address32.ResourceType != ACPI_IO_RANGE) { 339*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 340*5db2f26eSSascha Wildner "ignored Address32 for non-memory, non-I/O\n")); 341*5db2f26eSSascha Wildner break; 342*5db2f26eSSascha Wildner } 343*5db2f26eSSascha Wildner 344*5db2f26eSSascha Wildner if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED && 345*5db2f26eSSascha Wildner res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) { 346*5db2f26eSSascha Wildner 347*5db2f26eSSascha Wildner if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { 348*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 349*5db2f26eSSascha Wildner "Address32/Memory 0x%x/%d\n", 350*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 351*5db2f26eSSascha Wildner res->Data.Address32.AddressLength)); 352*5db2f26eSSascha Wildner set->set_memory(dev, context, 353*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 354*5db2f26eSSascha Wildner res->Data.Address32.AddressLength); 355*5db2f26eSSascha Wildner } else { 356*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 357*5db2f26eSSascha Wildner "Address32/IO 0x%x/%d\n", 358*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 359*5db2f26eSSascha Wildner res->Data.Address32.AddressLength)); 360*5db2f26eSSascha Wildner set->set_ioport(dev, context, 361*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 362*5db2f26eSSascha Wildner res->Data.Address32.AddressLength); 363*5db2f26eSSascha Wildner } 364*5db2f26eSSascha Wildner } else { 365*5db2f26eSSascha Wildner if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { 366*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 367*5db2f26eSSascha Wildner "Address32/Memory 0x%x-0x%x/%d\n", 368*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 369*5db2f26eSSascha Wildner res->Data.Address32.Maximum, 370*5db2f26eSSascha Wildner res->Data.Address32.AddressLength)); 371*5db2f26eSSascha Wildner set->set_memoryrange(dev, context, 372*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 373*5db2f26eSSascha Wildner res->Data.Address32.Maximum, 374*5db2f26eSSascha Wildner res->Data.Address32.AddressLength, 375*5db2f26eSSascha Wildner res->Data.Address32.Granularity); 376*5db2f26eSSascha Wildner } else { 377*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 378*5db2f26eSSascha Wildner "Address32/IO 0x%x-0x%x/%d\n", 379*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 380*5db2f26eSSascha Wildner res->Data.Address32.Maximum, 381*5db2f26eSSascha Wildner res->Data.Address32.AddressLength)); 382*5db2f26eSSascha Wildner set->set_iorange(dev, context, 383*5db2f26eSSascha Wildner res->Data.Address32.Minimum, 384*5db2f26eSSascha Wildner res->Data.Address32.Maximum, 385*5db2f26eSSascha Wildner res->Data.Address32.AddressLength, 386*5db2f26eSSascha Wildner res->Data.Address32.Granularity); 387*5db2f26eSSascha Wildner } 388*5db2f26eSSascha Wildner } 389*5db2f26eSSascha Wildner break; 390*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_ADDRESS16: 391*5db2f26eSSascha Wildner if (res->Data.Address16.AddressLength <= 0) 392*5db2f26eSSascha Wildner break; 393*5db2f26eSSascha Wildner if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) { 394*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 395*5db2f26eSSascha Wildner "ignored Address16 %s producer\n", 396*5db2f26eSSascha Wildner res->Data.Address16.ResourceType == ACPI_IO_RANGE ? 397*5db2f26eSSascha Wildner "IO" : "Memory")); 398*5db2f26eSSascha Wildner break; 399*5db2f26eSSascha Wildner } 400*5db2f26eSSascha Wildner if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE && 401*5db2f26eSSascha Wildner res->Data.Address16.ResourceType != ACPI_IO_RANGE) { 402*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 403*5db2f26eSSascha Wildner "ignored Address16 for non-memory, non-I/O\n")); 404*5db2f26eSSascha Wildner break; 405*5db2f26eSSascha Wildner } 406*5db2f26eSSascha Wildner 407*5db2f26eSSascha Wildner if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED && 408*5db2f26eSSascha Wildner res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) { 409*5db2f26eSSascha Wildner 410*5db2f26eSSascha Wildner if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { 411*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 412*5db2f26eSSascha Wildner "Address16/Memory 0x%x/%d\n", 413*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 414*5db2f26eSSascha Wildner res->Data.Address16.AddressLength)); 415*5db2f26eSSascha Wildner set->set_memory(dev, context, 416*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 417*5db2f26eSSascha Wildner res->Data.Address16.AddressLength); 418*5db2f26eSSascha Wildner } else { 419*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 420*5db2f26eSSascha Wildner "Address16/IO 0x%x/%d\n", 421*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 422*5db2f26eSSascha Wildner res->Data.Address16.AddressLength)); 423*5db2f26eSSascha Wildner set->set_ioport(dev, context, 424*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 425*5db2f26eSSascha Wildner res->Data.Address16.AddressLength); 426*5db2f26eSSascha Wildner } 427*5db2f26eSSascha Wildner } else { 428*5db2f26eSSascha Wildner if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { 429*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 430*5db2f26eSSascha Wildner "Address16/Memory 0x%x-0x%x/%d\n", 431*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 432*5db2f26eSSascha Wildner res->Data.Address16.Maximum, 433*5db2f26eSSascha Wildner res->Data.Address16.AddressLength)); 434*5db2f26eSSascha Wildner set->set_memoryrange(dev, context, 435*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 436*5db2f26eSSascha Wildner res->Data.Address16.Maximum, 437*5db2f26eSSascha Wildner res->Data.Address16.AddressLength, 438*5db2f26eSSascha Wildner res->Data.Address16.Granularity); 439*5db2f26eSSascha Wildner } else { 440*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 441*5db2f26eSSascha Wildner "Address16/IO 0x%x-0x%x/%d\n", 442*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 443*5db2f26eSSascha Wildner res->Data.Address16.Maximum, 444*5db2f26eSSascha Wildner res->Data.Address16.AddressLength)); 445*5db2f26eSSascha Wildner set->set_iorange(dev, context, 446*5db2f26eSSascha Wildner res->Data.Address16.Minimum, 447*5db2f26eSSascha Wildner res->Data.Address16.Maximum, 448*5db2f26eSSascha Wildner res->Data.Address16.AddressLength, 449*5db2f26eSSascha Wildner res->Data.Address16.Granularity); 450*5db2f26eSSascha Wildner } 451*5db2f26eSSascha Wildner } 452*5db2f26eSSascha Wildner break; 453*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_ADDRESS64: 454*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 455*5db2f26eSSascha Wildner "unimplemented Address64 resource\n")); 456*5db2f26eSSascha Wildner break; 457*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 458*5db2f26eSSascha Wildner if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) { 459*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 460*5db2f26eSSascha Wildner "ignored ExtIRQ producer\n")); 461*5db2f26eSSascha Wildner break; 462*5db2f26eSSascha Wildner } 463*5db2f26eSSascha Wildner set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts, 464*5db2f26eSSascha Wildner res->Data.ExtendedIrq.InterruptCount, 465*5db2f26eSSascha Wildner res->Data.ExtendedIrq.Triggering, 466*5db2f26eSSascha Wildner res->Data.ExtendedIrq.Polarity); 467*5db2f26eSSascha Wildner break; 468*5db2f26eSSascha Wildner case ACPI_RESOURCE_TYPE_VENDOR: 469*5db2f26eSSascha Wildner ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 470*5db2f26eSSascha Wildner "unimplemented VendorSpecific resource\n")); 471*5db2f26eSSascha Wildner break; 472*5db2f26eSSascha Wildner default: 473*5db2f26eSSascha Wildner break; 474*5db2f26eSSascha Wildner } 475*5db2f26eSSascha Wildner } 476*5db2f26eSSascha Wildner 477*5db2f26eSSascha Wildner AcpiOsFree(buf.Pointer); 478*5db2f26eSSascha Wildner set->set_done(dev, context); 479*5db2f26eSSascha Wildner return_ACPI_STATUS (AE_OK); 480*5db2f26eSSascha Wildner } 481*5db2f26eSSascha Wildner 482*5db2f26eSSascha Wildner /* 483*5db2f26eSSascha Wildner * Resource-set vectors used to attach _CRS-derived resources 484*5db2f26eSSascha Wildner * to an ACPI device. 485*5db2f26eSSascha Wildner */ 486*5db2f26eSSascha Wildner static void acpi_res_set_init(device_t dev, void *arg, void **context); 487*5db2f26eSSascha Wildner static void acpi_res_set_done(device_t dev, void *context); 488*5db2f26eSSascha Wildner static void acpi_res_set_ioport(device_t dev, void *context, 489*5db2f26eSSascha Wildner u_int32_t base, u_int32_t length); 490*5db2f26eSSascha Wildner static void acpi_res_set_iorange(device_t dev, void *context, 491*5db2f26eSSascha Wildner u_int32_t low, u_int32_t high, 492*5db2f26eSSascha Wildner u_int32_t length, u_int32_t align); 493*5db2f26eSSascha Wildner static void acpi_res_set_memory(device_t dev, void *context, 494*5db2f26eSSascha Wildner u_int32_t base, u_int32_t length); 495*5db2f26eSSascha Wildner static void acpi_res_set_memoryrange(device_t dev, void *context, 496*5db2f26eSSascha Wildner u_int32_t low, u_int32_t high, 497*5db2f26eSSascha Wildner u_int32_t length, u_int32_t align); 498*5db2f26eSSascha Wildner static void acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, 499*5db2f26eSSascha Wildner int count, int trig, int pol); 500*5db2f26eSSascha Wildner static void acpi_res_set_ext_irq(device_t dev, void *context, 501*5db2f26eSSascha Wildner u_int32_t *irq, int count, int trig, int pol); 502*5db2f26eSSascha Wildner static void acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, 503*5db2f26eSSascha Wildner int count); 504*5db2f26eSSascha Wildner static void acpi_res_set_start_dependent(device_t dev, void *context, 505*5db2f26eSSascha Wildner int preference); 506*5db2f26eSSascha Wildner static void acpi_res_set_end_dependent(device_t dev, void *context); 507*5db2f26eSSascha Wildner 508*5db2f26eSSascha Wildner struct acpi_parse_resource_set acpi_res_parse_set = { 509*5db2f26eSSascha Wildner acpi_res_set_init, 510*5db2f26eSSascha Wildner acpi_res_set_done, 511*5db2f26eSSascha Wildner acpi_res_set_ioport, 512*5db2f26eSSascha Wildner acpi_res_set_iorange, 513*5db2f26eSSascha Wildner acpi_res_set_memory, 514*5db2f26eSSascha Wildner acpi_res_set_memoryrange, 515*5db2f26eSSascha Wildner acpi_res_set_irq, 516*5db2f26eSSascha Wildner acpi_res_set_ext_irq, 517*5db2f26eSSascha Wildner acpi_res_set_drq, 518*5db2f26eSSascha Wildner acpi_res_set_start_dependent, 519*5db2f26eSSascha Wildner acpi_res_set_end_dependent 520*5db2f26eSSascha Wildner }; 521*5db2f26eSSascha Wildner 522*5db2f26eSSascha Wildner struct acpi_res_context { 523*5db2f26eSSascha Wildner int ar_nio; 524*5db2f26eSSascha Wildner int ar_nmem; 525*5db2f26eSSascha Wildner int ar_nirq; 526*5db2f26eSSascha Wildner int ar_ndrq; 527*5db2f26eSSascha Wildner void *ar_parent; 528*5db2f26eSSascha Wildner }; 529*5db2f26eSSascha Wildner 530*5db2f26eSSascha Wildner static void 531*5db2f26eSSascha Wildner acpi_res_set_init(device_t dev, void *arg, void **context) 532*5db2f26eSSascha Wildner { 533*5db2f26eSSascha Wildner struct acpi_res_context *cp; 534*5db2f26eSSascha Wildner 535*5db2f26eSSascha Wildner if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) { 536*5db2f26eSSascha Wildner bzero(cp, sizeof(*cp)); 537*5db2f26eSSascha Wildner cp->ar_parent = arg; 538*5db2f26eSSascha Wildner *context = cp; 539*5db2f26eSSascha Wildner } 540*5db2f26eSSascha Wildner } 541*5db2f26eSSascha Wildner 542*5db2f26eSSascha Wildner static void 543*5db2f26eSSascha Wildner acpi_res_set_done(device_t dev, void *context) 544*5db2f26eSSascha Wildner { 545*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 546*5db2f26eSSascha Wildner 547*5db2f26eSSascha Wildner if (cp == NULL) 548*5db2f26eSSascha Wildner return; 549*5db2f26eSSascha Wildner AcpiOsFree(cp); 550*5db2f26eSSascha Wildner } 551*5db2f26eSSascha Wildner 552*5db2f26eSSascha Wildner static void 553*5db2f26eSSascha Wildner acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, 554*5db2f26eSSascha Wildner u_int32_t length) 555*5db2f26eSSascha Wildner { 556*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 557*5db2f26eSSascha Wildner 558*5db2f26eSSascha Wildner if (cp == NULL) 559*5db2f26eSSascha Wildner return; 560*5db2f26eSSascha Wildner bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length, -1); 561*5db2f26eSSascha Wildner } 562*5db2f26eSSascha Wildner 563*5db2f26eSSascha Wildner static void 564*5db2f26eSSascha Wildner acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, 565*5db2f26eSSascha Wildner u_int32_t high, u_int32_t length, u_int32_t align) 566*5db2f26eSSascha Wildner { 567*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 568*5db2f26eSSascha Wildner 569*5db2f26eSSascha Wildner if (cp == NULL) 570*5db2f26eSSascha Wildner return; 571*5db2f26eSSascha Wildner device_printf(dev, "I/O range not supported\n"); 572*5db2f26eSSascha Wildner } 573*5db2f26eSSascha Wildner 574*5db2f26eSSascha Wildner static void 575*5db2f26eSSascha Wildner acpi_res_set_memory(device_t dev, void *context, u_int32_t base, 576*5db2f26eSSascha Wildner u_int32_t length) 577*5db2f26eSSascha Wildner { 578*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 579*5db2f26eSSascha Wildner 580*5db2f26eSSascha Wildner if (cp == NULL) 581*5db2f26eSSascha Wildner return; 582*5db2f26eSSascha Wildner 583*5db2f26eSSascha Wildner bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length, -1); 584*5db2f26eSSascha Wildner } 585*5db2f26eSSascha Wildner 586*5db2f26eSSascha Wildner static void 587*5db2f26eSSascha Wildner acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, 588*5db2f26eSSascha Wildner u_int32_t high, u_int32_t length, u_int32_t align) 589*5db2f26eSSascha Wildner { 590*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 591*5db2f26eSSascha Wildner 592*5db2f26eSSascha Wildner if (cp == NULL) 593*5db2f26eSSascha Wildner return; 594*5db2f26eSSascha Wildner device_printf(dev, "memory range not supported\n"); 595*5db2f26eSSascha Wildner } 596*5db2f26eSSascha Wildner 597*5db2f26eSSascha Wildner static void 598*5db2f26eSSascha Wildner acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count, 599*5db2f26eSSascha Wildner int trig, int pol) 600*5db2f26eSSascha Wildner { 601*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 602*5db2f26eSSascha Wildner 603*5db2f26eSSascha Wildner if (cp == NULL || irq == NULL) 604*5db2f26eSSascha Wildner return; 605*5db2f26eSSascha Wildner 606*5db2f26eSSascha Wildner /* This implements no resource relocation. */ 607*5db2f26eSSascha Wildner if (count != 1) 608*5db2f26eSSascha Wildner return; 609*5db2f26eSSascha Wildner 610*5db2f26eSSascha Wildner bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1, 611*5db2f26eSSascha Wildner machintr_legacy_intr_cpuid(*irq)); 612*5db2f26eSSascha Wildner } 613*5db2f26eSSascha Wildner 614*5db2f26eSSascha Wildner static void 615*5db2f26eSSascha Wildner acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count, 616*5db2f26eSSascha Wildner int trig, int pol) 617*5db2f26eSSascha Wildner { 618*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 619*5db2f26eSSascha Wildner 620*5db2f26eSSascha Wildner if (cp == NULL || irq == NULL) 621*5db2f26eSSascha Wildner return; 622*5db2f26eSSascha Wildner 623*5db2f26eSSascha Wildner /* This implements no resource relocation. */ 624*5db2f26eSSascha Wildner if (count != 1) 625*5db2f26eSSascha Wildner return; 626*5db2f26eSSascha Wildner 627*5db2f26eSSascha Wildner bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1, 628*5db2f26eSSascha Wildner machintr_legacy_intr_cpuid(*irq)); 629*5db2f26eSSascha Wildner } 630*5db2f26eSSascha Wildner 631*5db2f26eSSascha Wildner static void 632*5db2f26eSSascha Wildner acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count) 633*5db2f26eSSascha Wildner { 634*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 635*5db2f26eSSascha Wildner 636*5db2f26eSSascha Wildner if (cp == NULL || drq == NULL) 637*5db2f26eSSascha Wildner return; 638*5db2f26eSSascha Wildner 639*5db2f26eSSascha Wildner /* This implements no resource relocation. */ 640*5db2f26eSSascha Wildner if (count != 1) 641*5db2f26eSSascha Wildner return; 642*5db2f26eSSascha Wildner 643*5db2f26eSSascha Wildner bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1, -1); 644*5db2f26eSSascha Wildner } 645*5db2f26eSSascha Wildner 646*5db2f26eSSascha Wildner static void 647*5db2f26eSSascha Wildner acpi_res_set_start_dependent(device_t dev, void *context, int preference) 648*5db2f26eSSascha Wildner { 649*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 650*5db2f26eSSascha Wildner 651*5db2f26eSSascha Wildner if (cp == NULL) 652*5db2f26eSSascha Wildner return; 653*5db2f26eSSascha Wildner device_printf(dev, "dependent functions not supported\n"); 654*5db2f26eSSascha Wildner } 655*5db2f26eSSascha Wildner 656*5db2f26eSSascha Wildner static void 657*5db2f26eSSascha Wildner acpi_res_set_end_dependent(device_t dev, void *context) 658*5db2f26eSSascha Wildner { 659*5db2f26eSSascha Wildner struct acpi_res_context *cp = (struct acpi_res_context *)context; 660*5db2f26eSSascha Wildner 661*5db2f26eSSascha Wildner if (cp == NULL) 662*5db2f26eSSascha Wildner return; 663*5db2f26eSSascha Wildner device_printf(dev, "dependent functions not supported\n"); 664*5db2f26eSSascha Wildner } 665*5db2f26eSSascha Wildner 666*5db2f26eSSascha Wildner /* 667*5db2f26eSSascha Wildner * Resource-owning placeholders for IO and memory pseudo-devices. 668*5db2f26eSSascha Wildner * 669*5db2f26eSSascha Wildner * This code allocates system resources that will be used by ACPI 670*5db2f26eSSascha Wildner * child devices. The acpi parent manages these resources through a 671*5db2f26eSSascha Wildner * private rman. 672*5db2f26eSSascha Wildner */ 673*5db2f26eSSascha Wildner 674*5db2f26eSSascha Wildner static int acpi_sysres_rid = 100; 675*5db2f26eSSascha Wildner 676*5db2f26eSSascha Wildner static int acpi_sysres_probe(device_t dev); 677*5db2f26eSSascha Wildner static int acpi_sysres_attach(device_t dev); 678*5db2f26eSSascha Wildner 679*5db2f26eSSascha Wildner static device_method_t acpi_sysres_methods[] = { 680*5db2f26eSSascha Wildner /* Device interface */ 681*5db2f26eSSascha Wildner DEVMETHOD(device_probe, acpi_sysres_probe), 682*5db2f26eSSascha Wildner DEVMETHOD(device_attach, acpi_sysres_attach), 683*5db2f26eSSascha Wildner 684*5db2f26eSSascha Wildner {0, 0} 685*5db2f26eSSascha Wildner }; 686*5db2f26eSSascha Wildner 687*5db2f26eSSascha Wildner static driver_t acpi_sysres_driver = { 688*5db2f26eSSascha Wildner "acpi_sysresource", 689*5db2f26eSSascha Wildner acpi_sysres_methods, 690*5db2f26eSSascha Wildner 0, 691*5db2f26eSSascha Wildner }; 692*5db2f26eSSascha Wildner 693*5db2f26eSSascha Wildner static devclass_t acpi_sysres_devclass; 694*5db2f26eSSascha Wildner DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, acpi_sysres_devclass, 695*5db2f26eSSascha Wildner 0, 0); 696*5db2f26eSSascha Wildner MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1); 697*5db2f26eSSascha Wildner 698*5db2f26eSSascha Wildner static int 699*5db2f26eSSascha Wildner acpi_sysres_probe(device_t dev) 700*5db2f26eSSascha Wildner { 701*5db2f26eSSascha Wildner static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; 702*5db2f26eSSascha Wildner 703*5db2f26eSSascha Wildner if (acpi_disabled("sysresource") || 704*5db2f26eSSascha Wildner ACPI_ID_PROBE(device_get_parent(dev), dev, sysres_ids) == NULL) 705*5db2f26eSSascha Wildner return (ENXIO); 706*5db2f26eSSascha Wildner 707*5db2f26eSSascha Wildner device_set_desc(dev, "System Resource"); 708*5db2f26eSSascha Wildner device_quiet(dev); 709*5db2f26eSSascha Wildner return (BUS_PROBE_DEFAULT); 710*5db2f26eSSascha Wildner } 711*5db2f26eSSascha Wildner 712*5db2f26eSSascha Wildner static int 713*5db2f26eSSascha Wildner acpi_sysres_attach(device_t dev) 714*5db2f26eSSascha Wildner { 715*5db2f26eSSascha Wildner device_t bus; 716*5db2f26eSSascha Wildner struct resource_list_entry *bus_rle, *dev_rle; 717*5db2f26eSSascha Wildner struct resource_list *bus_rl, *dev_rl; 718*5db2f26eSSascha Wildner int done, type; 719*5db2f26eSSascha Wildner u_long start, end, count; 720*5db2f26eSSascha Wildner /* 721*5db2f26eSSascha Wildner * Loop through all current resources to see if the new one overlaps 722*5db2f26eSSascha Wildner * any existing ones. If so, grow the old one up and/or down 723*5db2f26eSSascha Wildner * accordingly. Discard any that are wholly contained in the old. If 724*5db2f26eSSascha Wildner * the resource is unique, add it to the parent. It will later go into 725*5db2f26eSSascha Wildner * the rman pool. 726*5db2f26eSSascha Wildner */ 727*5db2f26eSSascha Wildner bus = device_get_parent(dev); 728*5db2f26eSSascha Wildner dev_rl = BUS_GET_RESOURCE_LIST(bus, dev); 729*5db2f26eSSascha Wildner bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus); 730*5db2f26eSSascha Wildner if(bus_rl) 731*5db2f26eSSascha Wildner kprintf("busrl is not null!\n"); 732*5db2f26eSSascha Wildner SLIST_FOREACH(dev_rle, dev_rl, link) { 733*5db2f26eSSascha Wildner if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY) 734*5db2f26eSSascha Wildner continue; 735*5db2f26eSSascha Wildner 736*5db2f26eSSascha Wildner start = dev_rle->start; 737*5db2f26eSSascha Wildner end = dev_rle->end; 738*5db2f26eSSascha Wildner count = dev_rle->count; 739*5db2f26eSSascha Wildner type = dev_rle->type; 740*5db2f26eSSascha Wildner done = FALSE; 741*5db2f26eSSascha Wildner if(bus_rl) { 742*5db2f26eSSascha Wildner SLIST_FOREACH(bus_rle, bus_rl, link) { 743*5db2f26eSSascha Wildner if (bus_rle->type != type) 744*5db2f26eSSascha Wildner continue; 745*5db2f26eSSascha Wildner 746*5db2f26eSSascha Wildner /* New resource wholly contained in old, discard. */ 747*5db2f26eSSascha Wildner if (start >= bus_rle->start && end <= bus_rle->end) 748*5db2f26eSSascha Wildner break; 749*5db2f26eSSascha Wildner 750*5db2f26eSSascha Wildner /* New tail overlaps old head, grow existing resource downward. */ 751*5db2f26eSSascha Wildner if (start < bus_rle->start && end >= bus_rle->start) { 752*5db2f26eSSascha Wildner bus_rle->count += bus_rle->start - start; 753*5db2f26eSSascha Wildner bus_rle->start = start; 754*5db2f26eSSascha Wildner done = TRUE; 755*5db2f26eSSascha Wildner } 756*5db2f26eSSascha Wildner 757*5db2f26eSSascha Wildner /* New head overlaps old tail, grow existing resource upward. */ 758*5db2f26eSSascha Wildner if (start <= bus_rle->end && end > bus_rle->end) { 759*5db2f26eSSascha Wildner bus_rle->count += end - bus_rle->end; 760*5db2f26eSSascha Wildner bus_rle->end = end; 761*5db2f26eSSascha Wildner done = TRUE; 762*5db2f26eSSascha Wildner } 763*5db2f26eSSascha Wildner 764*5db2f26eSSascha Wildner /* If we adjusted the old resource, we're finished. */ 765*5db2f26eSSascha Wildner if (done) 766*5db2f26eSSascha Wildner break; 767*5db2f26eSSascha Wildner } 768*5db2f26eSSascha Wildner } else bus_rle = NULL; 769*5db2f26eSSascha Wildner /* If we didn't merge with anything, add this resource. */ 770*5db2f26eSSascha Wildner if (bus_rle == NULL) { 771*5db2f26eSSascha Wildner bus_set_resource(bus, type, acpi_sysres_rid++, start, count, -1); 772*5db2f26eSSascha Wildner } 773*5db2f26eSSascha Wildner } 774*5db2f26eSSascha Wildner 775*5db2f26eSSascha Wildner /* After merging/moving resources to the parent, free the list. */ 776*5db2f26eSSascha Wildner resource_list_free(dev_rl); 777*5db2f26eSSascha Wildner 778*5db2f26eSSascha Wildner return (0); 779*5db2f26eSSascha Wildner } 780