acpi_resource.c revision 69744
1153838Sdfr/*- 2153838Sdfr * Copyright (c) 2000 Michael Smith 3153838Sdfr * Copyright (c) 2000 BSDi 4153838Sdfr * All rights reserved. 5153838Sdfr * 6153838Sdfr * Redistribution and use in source and binary forms, with or without 7153838Sdfr * modification, are permitted provided that the following conditions 8153838Sdfr * are met: 9153838Sdfr * 1. Redistributions of source code must retain the above copyright 10153838Sdfr * notice, this list of conditions and the following disclaimer. 11153838Sdfr * 2. Redistributions in binary form must reproduce the above copyright 12153838Sdfr * notice, this list of conditions and the following disclaimer in the 13153838Sdfr * documentation and/or other materials provided with the distribution. 14153838Sdfr * 15153838Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16153838Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17153838Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18153838Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19153838Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20153838Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21153838Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22153838Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23153838Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24153838Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25153838Sdfr * SUCH DAMAGE. 26153838Sdfr * 27153838Sdfr * $FreeBSD: head/sys/dev/acpica/acpi_resource.c 69744 2000-12-08 09:16:20Z msmith $ 28153838Sdfr */ 29153838Sdfr 30153838Sdfr#include "opt_acpi.h" 31168340Skan#include <sys/param.h> 32153838Sdfr#include <sys/kernel.h> 33153838Sdfr#include <sys/bus.h> 34153838Sdfr#include <machine/bus.h> 35153838Sdfr#include <machine/resource.h> 36153838Sdfr 37153838Sdfr#include "acpi.h" 38153838Sdfr 39153838Sdfr#include <dev/acpica/acpivar.h> 40153838Sdfr 41153838Sdfr/* 42153838Sdfr * Hooks for the ACPI CA debugging infrastructure 43153838Sdfr */ 44153838Sdfr#define _COMPONENT BUS_MANAGER 45153838SdfrMODULE_NAME("RESOURCE") 46153838Sdfr 47153838Sdfr/* 48153838Sdfr * Fetch a device's resources and associate them with the device. 49153838Sdfr * 50153838Sdfr * Note that it might be nice to also locate ACPI-specific resource items, such 51153838Sdfr * as GPE bits. 52153838Sdfr */ 53153838SdfrACPI_STATUS 54153838Sdfracpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set) 55153838Sdfr{ 56153838Sdfr ACPI_BUFFER buf; 57153838Sdfr RESOURCE *res; 58153838Sdfr char *curr, *last; 59153838Sdfr ACPI_STATUS status; 60153838Sdfr int i; 61153838Sdfr void *context; 62153838Sdfr 63153838Sdfr FUNCTION_TRACE(__FUNCTION__); 64153838Sdfr 65153838Sdfr /* 66153838Sdfr * Fetch the device resources 67153838Sdfr */ 68153838Sdfr if (((status = acpi_GetIntoBuffer(handle, AcpiGetPossibleResources, &buf)) != AE_OK) && 69153838Sdfr ((status = acpi_GetIntoBuffer(handle, AcpiGetCurrentResources, &buf)) != AE_OK)) { 70153838Sdfr device_printf(dev, "can't fetch ACPI resources - %s\n", acpi_strerror(status)); 71153838Sdfr return_ACPI_STATUS(status); 72153838Sdfr } 73153838Sdfr DEBUG_PRINT(TRACE_RESOURCES, ("got %d bytes of resources\n", buf.Length)); 74153838Sdfr set->set_init(dev, &context); 75153838Sdfr 76153838Sdfr /* 77153838Sdfr * Iterate through the resources 78153838Sdfr */ 79 curr = buf.Pointer; 80 last = (char *)buf.Pointer + buf.Length; 81 while (curr < last) { 82 res = (RESOURCE *)curr; 83 curr += res->Length; 84 85 /* 86 * Handle the individual resource types 87 */ 88 switch(res->Id) { 89 case EndTag: 90 DEBUG_PRINT(TRACE_RESOURCES, ("EndTag\n")); 91 curr = last; 92 break; 93 94 case FixedIo: 95 DEBUG_PRINT(TRACE_RESOURCES, ("FixedIo 0x%x/%d\n", res->Data.FixedIo.BaseAddress, res->Data.FixedIo.RangeLength)); 96 set->set_ioport(dev, context, res->Data.FixedIo.BaseAddress, res->Data.FixedIo.RangeLength); 97 break; 98 99 case Io: 100 if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) { 101 DEBUG_PRINT(TRACE_RESOURCES, ("Io 0x%x/%d\n", res->Data.Io.MinBaseAddress, res->Data.Io.RangeLength)); 102 set->set_ioport(dev, context, res->Data.Io.MinBaseAddress, res->Data.Io.RangeLength); 103 } else { 104 DEBUG_PRINT(TRACE_RESOURCES, ("Io 0x%x-0x%x/%d\n", res->Data.Io.MinBaseAddress, res->Data.Io.MaxBaseAddress, 105 res->Data.Io.RangeLength)); 106 set->set_iorange(dev, context, res->Data.Io.MinBaseAddress, res->Data.Io.MaxBaseAddress, 107 res->Data.Io.RangeLength, res->Data.Io.Alignment); 108 } 109 break; 110 111 case FixedMemory32: 112 DEBUG_PRINT(TRACE_RESOURCES, ("FixedMemory32 0x%x/%d\n", res->Data.FixedMemory32.RangeBaseAddress, 113 res->Data.FixedMemory32.RangeLength)); 114 set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress, 115 res->Data.FixedMemory32.RangeLength); 116 break; 117 118 case Memory32: 119 if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) { 120 DEBUG_PRINT(TRACE_RESOURCES, ("Memory32 0x%x/%d\n", res->Data.Memory32.MinBaseAddress, 121 res->Data.Memory32.RangeLength)); 122 set->set_memory(dev, context, res->Data.Memory32.MinBaseAddress, res->Data.Memory32.RangeLength); 123 } else { 124 DEBUG_PRINT(TRACE_RESOURCES, ("Memory32 0x%x-0x%x/%d\n", res->Data.Memory32.MinBaseAddress, 125 res->Data.Memory32.MaxBaseAddress, res->Data.Memory32.RangeLength)); 126 set->set_memoryrange(dev, context, res->Data.Memory32.MinBaseAddress, res->Data.Memory32.MaxBaseAddress, 127 res->Data.Memory32.RangeLength, res->Data.Memory32.Alignment); 128 } 129 break; 130 131 case Memory24: 132 if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) { 133 DEBUG_PRINT(TRACE_RESOURCES, ("Memory24 0x%x/%d\n", res->Data.Memory24.MinBaseAddress, 134 res->Data.Memory24.RangeLength)); 135 set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress, res->Data.Memory24.RangeLength); 136 } else { 137 DEBUG_PRINT(TRACE_RESOURCES, ("Memory24 0x%x-0x%x/%d\n", res->Data.Memory24.MinBaseAddress, 138 res->Data.Memory24.MaxBaseAddress, res->Data.Memory24.RangeLength)); 139 set->set_memoryrange(dev, context, res->Data.Memory24.MinBaseAddress, res->Data.Memory24.MaxBaseAddress, 140 res->Data.Memory24.RangeLength, res->Data.Memory24.Alignment); 141 } 142 break; 143 144 case Irq: 145 for (i = 0; i < res->Data.Irq.NumberOfInterrupts; i++) { 146 DEBUG_PRINT(TRACE_RESOURCES, ("Irq %d\n", res->Data.Irq.Interrupts[i])); 147 set->set_irq(dev, context, res->Data.Irq.Interrupts[i]); 148 } 149 break; 150 151 case Dma: 152 for (i = 0; i < res->Data.Dma.NumberOfChannels; i++) { 153 DEBUG_PRINT(TRACE_RESOURCES, ("Drq %d\n", res->Data.Dma.Channels[i])); 154 set->set_drq(dev, context, res->Data.Dma.Channels[i]); 155 } 156 break; 157 158 case StartDependentFunctions: 159 DEBUG_PRINT(TRACE_RESOURCES, ("start dependant functions")); 160 set->set_start_dependant(dev, context, res->Data.StartDependentFunctions.CompatibilityPriority); 161 break; 162 163 case EndDependentFunctions: 164 DEBUG_PRINT(TRACE_RESOURCES, ("end dependant functions")); 165 set->set_end_dependant(dev, context); 166 break; 167 168 case Address32: 169 DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented Address32 resource\n")); 170 break; 171 172 case Address16: 173 DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented Address16 resource\n")); 174 break; 175 176 case ExtendedIrq: 177 DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented ExtendedIrq resource\n")); 178 break; 179 180 case VendorSpecific: 181 DEBUG_PRINT(TRACE_RESOURCES, ("unimplemented VendorSpecific resource\n")); 182 break; 183 default: 184 break; 185 } 186 } 187 AcpiOsFree(buf.Pointer); 188 set->set_done(dev, context); 189 return_ACPI_STATUS(AE_OK); 190} 191 192static void acpi_res_set_init(device_t dev, void **context); 193static void acpi_res_set_done(device_t dev, void *context); 194static void acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length); 195static void acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, 196 u_int32_t length, u_int32_t align); 197static void acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length); 198static void acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, 199 u_int32_t length, u_int32_t align); 200static void acpi_res_set_irq(device_t dev, void *context, u_int32_t irq); 201static void acpi_res_set_drq(device_t dev, void *context, u_int32_t drq); 202static void acpi_res_set_start_dependant(device_t dev, void *context, int preference); 203static void acpi_res_set_end_dependant(device_t dev, void *context); 204 205struct acpi_parse_resource_set acpi_res_parse_set = { 206 acpi_res_set_init, 207 acpi_res_set_done, 208 acpi_res_set_ioport, 209 acpi_res_set_iorange, 210 acpi_res_set_memory, 211 acpi_res_set_memoryrange, 212 acpi_res_set_irq, 213 acpi_res_set_drq, 214 acpi_res_set_start_dependant, 215 acpi_res_set_end_dependant 216}; 217 218struct acpi_res_context { 219 int ar_nio; 220 int ar_nmem; 221 int ar_nirq; 222}; 223 224static void 225acpi_res_set_init(device_t dev, void **context) 226{ 227 struct acpi_res_context *cp; 228 229 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) { 230 bzero(cp, sizeof(*cp)); 231 *context = cp; 232 } 233} 234 235static void 236acpi_res_set_done(device_t dev, void *context) 237{ 238 struct acpi_res_context *cp = (struct acpi_res_context *)context; 239 240 if (cp == NULL) 241 return; 242 AcpiOsFree(cp); 243} 244 245static void 246acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length) 247{ 248 struct acpi_res_context *cp = (struct acpi_res_context *)context; 249 250 if (cp == NULL) 251 return; 252 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length); 253} 254 255static void 256acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align) 257{ 258 struct acpi_res_context *cp = (struct acpi_res_context *)context; 259 260 if (cp == NULL) 261 return; 262 device_printf(dev, "I/O range not supported\n"); 263} 264 265static void 266acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length) 267{ 268 struct acpi_res_context *cp = (struct acpi_res_context *)context; 269 270 if (cp == NULL) 271 return; 272 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length); 273} 274 275static void 276acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align) 277{ 278 struct acpi_res_context *cp = (struct acpi_res_context *)context; 279 280 if (cp == NULL) 281 return; 282 device_printf(dev, "memory range not supported\n"); 283} 284 285static void 286acpi_res_set_irq(device_t dev, void *context, u_int32_t irq) 287{ 288 struct acpi_res_context *cp = (struct acpi_res_context *)context; 289 290 if (cp == NULL) 291 return; 292 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq, 1); 293} 294 295static void 296acpi_res_set_drq(device_t dev, void *context, u_int32_t drq) 297{ 298 struct acpi_res_context *cp = (struct acpi_res_context *)context; 299 300 if (cp == NULL) 301 return; 302 device_printf(dev, "DRQ not supported\n"); 303} 304 305static void 306acpi_res_set_start_dependant(device_t dev, void *context, int preference) 307{ 308 struct acpi_res_context *cp = (struct acpi_res_context *)context; 309 310 if (cp == NULL) 311 return; 312 device_printf(dev, "dependant functions not supported"); 313} 314 315static void 316acpi_res_set_end_dependant(device_t dev, void *context) 317{ 318 struct acpi_res_context *cp = (struct acpi_res_context *)context; 319 320 if (cp == NULL) 321 return; 322} 323