Home | History | Annotate | Line # | Download | only in acpi
acpi_resource.c revision 1.17
      1 /*	$NetBSD: acpi_resource.c,v 1.17 2005/05/29 20:56:02 christos Exp $	*/
      2 
      3 /*
      4  * Copyright 2001 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed for the NetBSD Project by
     20  *	Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*-
     39  * Copyright (c) 2000 Michael Smith
     40  * Copyright (c) 2000 BSDi
     41  * All rights reserved.
     42  *
     43  * Redistribution and use in source and binary forms, with or without
     44  * modification, are permitted provided that the following conditions
     45  * are met:
     46  * 1. Redistributions of source code must retain the above copyright
     47  *    notice, this list of conditions and the following disclaimer.
     48  * 2. Redistributions in binary form must reproduce the above copyright
     49  *    notice, this list of conditions and the following disclaimer in the
     50  *    documentation and/or other materials provided with the distribution.
     51  *
     52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     62  * SUCH DAMAGE.
     63  */
     64 
     65 /*
     66  * ACPI resource parsing.
     67  */
     68 
     69 #include <sys/cdefs.h>
     70 __KERNEL_RCSID(0, "$NetBSD: acpi_resource.c,v 1.17 2005/05/29 20:56:02 christos Exp $");
     71 
     72 #include <sys/param.h>
     73 #include <sys/systm.h>
     74 #include <sys/device.h>
     75 
     76 #include <dev/acpi/acpica.h>
     77 #include <dev/acpi/acpireg.h>
     78 #include <dev/acpi/acpivar.h>
     79 
     80 #define	_COMPONENT	ACPI_RESOURCE_COMPONENT
     81 ACPI_MODULE_NAME("RESOURCE")
     82 
     83 static ACPI_STATUS acpi_resource_parse_callback(ACPI_RESOURCE *, void *);
     84 
     85 struct resource_parse_callback_arg {
     86 	const struct acpi_resource_parse_ops *ops;
     87 	struct device *dev;
     88 	void *context;
     89 };
     90 
     91 static ACPI_STATUS
     92 acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context)
     93 {
     94 	struct resource_parse_callback_arg *arg = context;
     95 	const struct acpi_resource_parse_ops *ops;
     96 	int i;
     97 
     98 	ACPI_FUNCTION_TRACE(__FUNCTION__);
     99 
    100 	ops = arg->ops;
    101 
    102 	switch (res->Id) {
    103 	case ACPI_RSTYPE_FIXED_IO:
    104 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    105 				     "FixedIo 0x%x/%d\n",
    106 				     res->Data.FixedIo.BaseAddress,
    107 				     res->Data.FixedIo.RangeLength));
    108 		if (ops->ioport)
    109 			(*ops->ioport)(arg->dev, arg->context,
    110 			    res->Data.FixedIo.BaseAddress,
    111 			    res->Data.FixedIo.RangeLength);
    112 		break;
    113 
    114 	case ACPI_RSTYPE_IO:
    115 		if (res->Data.Io.MinBaseAddress ==
    116 			    res->Data.Io.MaxBaseAddress) {
    117 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    118 					     "Io 0x%x/%d\n",
    119 					     res->Data.Io.MinBaseAddress,
    120 					     res->Data.Io.RangeLength));
    121 			if (ops->ioport)
    122 				(*ops->ioport)(arg->dev, arg->context,
    123 				    res->Data.Io.MinBaseAddress,
    124 				    res->Data.Io.RangeLength);
    125 		} else {
    126 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    127 					     "Io 0x%x-0x%x/%d\n",
    128 					     res->Data.Io.MinBaseAddress,
    129 					     res->Data.Io.MaxBaseAddress,
    130 					     res->Data.Io.RangeLength));
    131 			if (ops->ioport)
    132 				(*ops->iorange)(arg->dev, arg->context,
    133 				    res->Data.Io.MinBaseAddress,
    134 				    res->Data.Io.MaxBaseAddress,
    135 				    res->Data.Io.RangeLength,
    136 				    res->Data.Io.Alignment);
    137 		}
    138 		break;
    139 
    140 	case ACPI_RSTYPE_FIXED_MEM32:
    141 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    142 				     "FixedMemory32 0x%x/%d\n",
    143 				     res->Data.FixedMemory32.RangeBaseAddress,
    144 				     res->Data.FixedMemory32.RangeLength));
    145 		if (ops->memory)
    146 			(*ops->memory)(arg->dev, arg->context,
    147 			    res->Data.FixedMemory32.RangeBaseAddress,
    148 			    res->Data.FixedMemory32.RangeLength);
    149 		break;
    150 
    151 	case ACPI_RSTYPE_MEM32:
    152 		if (res->Data.Memory32.MinBaseAddress ==
    153 		    res->Data.Memory32.MaxBaseAddress) {
    154 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    155 					     "Memory32 0x%x/%d\n",
    156 					     res->Data.Memory32.MinBaseAddress,
    157 					     res->Data.Memory32.RangeLength));
    158 			if (ops->memory)
    159 				(*ops->memory)(arg->dev, arg->context,
    160 				    res->Data.Memory32.MinBaseAddress,
    161 				    res->Data.Memory32.RangeLength);
    162 		} else {
    163 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    164 					     "Memory32 0x%x-0x%x/%d\n",
    165 					     res->Data.Memory32.MinBaseAddress,
    166 					     res->Data.Memory32.MaxBaseAddress,
    167 					     res->Data.Memory32.RangeLength));
    168 			if (ops->memrange)
    169 				(*ops->memrange)(arg->dev, arg->context,
    170 				    res->Data.Memory32.MinBaseAddress,
    171 				    res->Data.Memory32.MaxBaseAddress,
    172 				    res->Data.Memory32.RangeLength,
    173 				    res->Data.Memory32.Alignment);
    174 		}
    175 		break;
    176 
    177 	case ACPI_RSTYPE_MEM24:
    178 		if (res->Data.Memory24.MinBaseAddress ==
    179 		    res->Data.Memory24.MaxBaseAddress) {
    180 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    181 					     "Memory24 0x%x/%d\n",
    182 					     res->Data.Memory24.MinBaseAddress,
    183 					     res->Data.Memory24.RangeLength));
    184 			if (ops->memory)
    185 				(*ops->memory)(arg->dev, arg->context,
    186 				    res->Data.Memory24.MinBaseAddress,
    187 				    res->Data.Memory24.RangeLength);
    188 		} else {
    189 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    190 					     "Memory24 0x%x-0x%x/%d\n",
    191 					     res->Data.Memory24.MinBaseAddress,
    192 					     res->Data.Memory24.MaxBaseAddress,
    193 					     res->Data.Memory24.RangeLength));
    194 			if (ops->memrange)
    195 				(*ops->memrange)(arg->dev, arg->context,
    196 				    res->Data.Memory24.MinBaseAddress,
    197 				    res->Data.Memory24.MaxBaseAddress,
    198 				    res->Data.Memory24.RangeLength,
    199 				    res->Data.Memory24.Alignment);
    200 		}
    201 		break;
    202 
    203 	case ACPI_RSTYPE_IRQ:
    204 		for (i = 0; i < res->Data.Irq.NumberOfInterrupts; i++) {
    205 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    206 					     "IRQ %d\n",
    207 					     res->Data.Irq.Interrupts[i]));
    208 			if (ops->irq)
    209 				(*ops->irq)(arg->dev, arg->context,
    210 				    res->Data.Irq.Interrupts[i],
    211 				    res->Data.Irq.EdgeLevel);
    212 		}
    213 		break;
    214 
    215 	case ACPI_RSTYPE_DMA:
    216 		for (i = 0; i < res->Data.Dma.NumberOfChannels; i++) {
    217 			ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    218 					     "DRQ %d\n",
    219 					     res->Data.Dma.Channels[i]));
    220 			if (ops->drq)
    221 				(*ops->drq)(arg->dev, arg->context,
    222 				    res->Data.Dma.Channels[i]);
    223 		}
    224 		break;
    225 
    226 	case ACPI_RSTYPE_START_DPF:
    227 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    228 				     "Start dependant functions: %d\n",
    229 				     res->Data.StartDpf.CompatibilityPriority));
    230 		if (ops->start_dep)
    231 			(*ops->start_dep)(arg->dev, arg->context,
    232 			    res->Data.StartDpf.CompatibilityPriority);
    233 		break;
    234 
    235 	case ACPI_RSTYPE_END_DPF:
    236 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    237 				     "End dependant functions\n"));
    238 		if (ops->end_dep)
    239 			(*ops->end_dep)(arg->dev, arg->context);
    240 
    241 	case ACPI_RSTYPE_ADDRESS32:
    242 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    243 				     "Address32 unimplemented\n"));
    244 		break;
    245 
    246 	case ACPI_RSTYPE_ADDRESS16:
    247 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    248 				     "Address16 unimplemented\n"));
    249 		break;
    250 
    251 	case ACPI_RSTYPE_EXT_IRQ:
    252 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    253 				     "ExtendedIrq unimplemented\n"));
    254 		break;
    255 
    256 	case ACPI_RSTYPE_VENDOR:
    257 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    258 				     "VendorSpecific unimplemented\n"));
    259 		break;
    260 
    261 	default:
    262 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
    263 				     "Unknown resource type: %d\n", res->Id));
    264 		break;
    265 	}
    266 
    267 	return_ACPI_STATUS(AE_OK);
    268 }
    269 
    270 
    271 /*
    272  * acpi_resource_parse:
    273  *
    274  *	Parse a device node's resources and fill them in for the
    275  *	client.
    276  *
    277  *	This API supports _CRS (current resources) and
    278  *	_PRS (possible resources).
    279  *
    280  *	Note that it might be nice to also locate ACPI-specific resource
    281  *	items, such as GPE bits.
    282  */
    283 ACPI_STATUS
    284 acpi_resource_parse(struct device *dev, ACPI_HANDLE handle, const char *path,
    285     void *arg, const struct acpi_resource_parse_ops *ops)
    286 {
    287 	struct resource_parse_callback_arg cbarg;
    288 	ACPI_STATUS rv;
    289 
    290 	ACPI_FUNCTION_TRACE(__FUNCTION__);
    291 
    292 	if (ops->init)
    293 		(*ops->init)(dev, arg, &cbarg.context);
    294 	else
    295 		cbarg.context = arg;
    296 	cbarg.ops = ops;
    297 	cbarg.dev = dev;
    298 
    299 	rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback,
    300 	    &cbarg);
    301 	if (ACPI_FAILURE(rv)) {
    302 		printf("%s: ACPI: unable to get %s resources: %s\n",
    303 		    dev->dv_xname, path, AcpiFormatException(rv));
    304 		return_ACPI_STATUS(rv);
    305 	}
    306 
    307 	if (ops->fini)
    308 		(*ops->fini)(dev, cbarg.context);
    309 
    310 	return_ACPI_STATUS(AE_OK);
    311 }
    312 
    313 /*
    314  * acpi_resource_print:
    315  *
    316  *	Print the resources assigned to a device.
    317  */
    318 void
    319 acpi_resource_print(struct device *dev, struct acpi_resources *res)
    320 {
    321 	const char *sep;
    322 
    323 	if (SIMPLEQ_EMPTY(&res->ar_io) &&
    324 	    SIMPLEQ_EMPTY(&res->ar_iorange) &&
    325 	    SIMPLEQ_EMPTY(&res->ar_mem) &&
    326 	    SIMPLEQ_EMPTY(&res->ar_memrange) &&
    327 	    SIMPLEQ_EMPTY(&res->ar_irq) &&
    328 	    SIMPLEQ_EMPTY(&res->ar_drq))
    329 		return;
    330 
    331 	printf("%s:", dev->dv_xname);
    332 
    333 	if (SIMPLEQ_EMPTY(&res->ar_io) == 0) {
    334 		struct acpi_io *ar;
    335 
    336 		sep = "";
    337 		printf(" io ");
    338 		SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
    339 			printf("%s0x%x", sep, ar->ar_base);
    340 			if (ar->ar_length > 1)
    341 				printf("-0x%x", ar->ar_base +
    342 				    ar->ar_length - 1);
    343 			sep = ",";
    344 		}
    345 	}
    346 
    347 	/* XXX iorange */
    348 
    349 	if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) {
    350 		struct acpi_mem *ar;
    351 
    352 		sep = "";
    353 		printf(" mem ");
    354 		SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
    355 			printf("%s0x%x", sep, ar->ar_base);
    356 			if (ar->ar_length > 1)
    357 				printf("-0x%x", ar->ar_base +
    358 				    ar->ar_length - 1);
    359 			sep = ",";
    360 		}
    361 	}
    362 
    363 	/* XXX memrange */
    364 
    365 	if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) {
    366 		struct acpi_irq *ar;
    367 
    368 		sep = "";
    369 		printf(" irq ");
    370 		SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
    371 			printf("%s%d", sep, ar->ar_irq);
    372 			sep = ",";
    373 		}
    374 	}
    375 
    376 	if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) {
    377 		struct acpi_drq *ar;
    378 
    379 		sep = "";
    380 		printf(" drq ");
    381 		SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
    382 			printf("%s%d", sep, ar->ar_drq);
    383 			sep = ",";
    384 		}
    385 	}
    386 
    387 	printf("\n");
    388 }
    389 
    390 /*
    391  * acpi_resource_cleanup:
    392  *
    393  *	Free all allocated buffers
    394  */
    395 void
    396 acpi_resource_cleanup(struct acpi_resources *res)
    397 {
    398 	while (!SIMPLEQ_EMPTY(&res->ar_io)) {
    399 		struct acpi_io *ar;
    400 		ar = SIMPLEQ_FIRST(&res->ar_io);
    401 		SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list);
    402 		AcpiOsFree(ar);
    403 	}
    404 
    405 	while (!SIMPLEQ_EMPTY(&res->ar_iorange)) {
    406 		struct acpi_iorange *ar;
    407 		ar = SIMPLEQ_FIRST(&res->ar_iorange);
    408 		SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list);
    409 		AcpiOsFree(ar);
    410 	}
    411 
    412 	while (!SIMPLEQ_EMPTY(&res->ar_mem)) {
    413 		struct acpi_mem *ar;
    414 		ar = SIMPLEQ_FIRST(&res->ar_mem);
    415 		SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list);
    416 		AcpiOsFree(ar);
    417 	}
    418 
    419 	while (!SIMPLEQ_EMPTY(&res->ar_memrange)) {
    420 		struct acpi_memrange *ar;
    421 		ar = SIMPLEQ_FIRST(&res->ar_memrange);
    422 		SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list);
    423 		AcpiOsFree(ar);
    424 	}
    425 
    426 	while (!SIMPLEQ_EMPTY(&res->ar_irq)) {
    427 		struct acpi_irq *ar;
    428 		ar = SIMPLEQ_FIRST(&res->ar_irq);
    429 		SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list);
    430 		AcpiOsFree(ar);
    431 	}
    432 
    433 	while (!SIMPLEQ_EMPTY(&res->ar_drq)) {
    434 		struct acpi_drq *ar;
    435 		ar = SIMPLEQ_FIRST(&res->ar_drq);
    436 		SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list);
    437 		AcpiOsFree(ar);
    438 	}
    439 
    440 	res->ar_nio = res->ar_niorange = res->ar_nmem =
    441 	    res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0;
    442 }
    443 
    444 struct acpi_io *
    445 acpi_res_io(struct acpi_resources *res, int idx)
    446 {
    447 	struct acpi_io *ar;
    448 
    449 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
    450 		if (ar->ar_index == idx)
    451 			return ar;
    452 	}
    453 	return NULL;
    454 }
    455 
    456 struct acpi_iorange *
    457 acpi_res_iorange(struct acpi_resources *res, int idx)
    458 {
    459 	struct acpi_iorange *ar;
    460 
    461 	SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) {
    462 		if (ar->ar_index == idx)
    463 			return ar;
    464 	}
    465 	return NULL;
    466 }
    467 
    468 struct acpi_mem *
    469 acpi_res_mem(struct acpi_resources *res, int idx)
    470 {
    471 	struct acpi_mem *ar;
    472 
    473 	SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) {
    474 		if (ar->ar_index == idx)
    475 			return ar;
    476 	}
    477 	return NULL;
    478 }
    479 
    480 struct acpi_memrange *
    481 acpi_res_memrange(struct acpi_resources *res, int idx)
    482 {
    483 	struct acpi_memrange *ar;
    484 
    485 	SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) {
    486 		if (ar->ar_index == idx)
    487 			return ar;
    488 	}
    489 	return NULL;
    490 }
    491 
    492 struct acpi_irq *
    493 acpi_res_irq(struct acpi_resources *res, int idx)
    494 {
    495 	struct acpi_irq *ar;
    496 
    497 	SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) {
    498 		if (ar->ar_index == idx)
    499 			return ar;
    500 	}
    501 	return NULL;
    502 }
    503 
    504 struct acpi_drq *
    505 acpi_res_drq(struct acpi_resources *res, int idx)
    506 {
    507 	struct acpi_drq *ar;
    508 
    509 	SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) {
    510 		if (ar->ar_index == idx)
    511 			return ar;
    512 	}
    513 	return NULL;
    514 }
    515 
    516 /*****************************************************************************
    517  * Default ACPI resource parse operations.
    518  *****************************************************************************/
    519 
    520 static void	acpi_res_parse_init(struct device *, void *, void **);
    521 static void	acpi_res_parse_fini(struct device *, void *);
    522 
    523 static void	acpi_res_parse_ioport(struct device *, void *, uint32_t,
    524 		    uint32_t);
    525 static void	acpi_res_parse_iorange(struct device *, void *, uint32_t,
    526 		    uint32_t, uint32_t, uint32_t);
    527 
    528 static void	acpi_res_parse_memory(struct device *, void *, uint32_t,
    529 		    uint32_t);
    530 static void	acpi_res_parse_memrange(struct device *, void *, uint32_t,
    531 		    uint32_t, uint32_t, uint32_t);
    532 
    533 static void	acpi_res_parse_irq(struct device *, void *, uint32_t, uint32_t);
    534 static void	acpi_res_parse_drq(struct device *, void *, uint32_t);
    535 
    536 static void	acpi_res_parse_start_dep(struct device *, void *, int);
    537 static void	acpi_res_parse_end_dep(struct device *, void *);
    538 
    539 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = {
    540 	.init = acpi_res_parse_init,
    541 	.fini = acpi_res_parse_fini,
    542 
    543 	.ioport = acpi_res_parse_ioport,
    544 	.iorange = acpi_res_parse_iorange,
    545 
    546 	.memory = acpi_res_parse_memory,
    547 	.memrange = acpi_res_parse_memrange,
    548 
    549 	.irq = acpi_res_parse_irq,
    550 	.drq = acpi_res_parse_drq,
    551 
    552 	.start_dep = acpi_res_parse_start_dep,
    553 	.end_dep = acpi_res_parse_end_dep,
    554 };
    555 
    556 static void
    557 acpi_res_parse_init(struct device *dev, void *arg, void **contextp)
    558 {
    559 	struct acpi_resources *res = arg;
    560 
    561 	SIMPLEQ_INIT(&res->ar_io);
    562 	res->ar_nio = 0;
    563 
    564 	SIMPLEQ_INIT(&res->ar_iorange);
    565 	res->ar_niorange = 0;
    566 
    567 	SIMPLEQ_INIT(&res->ar_mem);
    568 	res->ar_nmem = 0;
    569 
    570 	SIMPLEQ_INIT(&res->ar_memrange);
    571 	res->ar_nmemrange = 0;
    572 
    573 	SIMPLEQ_INIT(&res->ar_irq);
    574 	res->ar_nirq = 0;
    575 
    576 	SIMPLEQ_INIT(&res->ar_drq);
    577 	res->ar_ndrq = 0;
    578 
    579 	*contextp = res;
    580 }
    581 
    582 static void
    583 acpi_res_parse_fini(struct device *dev, void *context)
    584 {
    585 	struct acpi_resources *res = context;
    586 
    587 	/* Print the resources we're using. */
    588 	acpi_resource_print(dev, res);
    589 }
    590 
    591 static void
    592 acpi_res_parse_ioport(struct device *dev, void *context, uint32_t base,
    593     uint32_t length)
    594 {
    595 	struct acpi_resources *res = context;
    596 	struct acpi_io *ar;
    597 
    598 	/*
    599 	 * Check if there is another I/O port directly below/under
    600 	 * this one.
    601 	 */
    602 	SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) {
    603 		if (ar->ar_base == base + length ) {
    604 			/*
    605 			 * Entry just below existing entry - adjust
    606 			 * the entry and return.
    607 			 */
    608 			ar->ar_base = base;
    609 			ar->ar_length += length;
    610 			return;
    611 		} else if (ar->ar_base + ar->ar_length == base) {
    612 			/*
    613 			 * Entry just above existing entry - adjust
    614 			 * the entry and return.
    615 			 */
    616 			ar->ar_length += length;
    617 			return;
    618 		}
    619 	}
    620 
    621 	ar = AcpiOsAllocate(sizeof(*ar));
    622 	if (ar == NULL) {
    623 		printf("%s: ACPI: unable to allocate I/O resource %d\n",
    624 		    dev->dv_xname, res->ar_nio);
    625 		res->ar_nio++;
    626 		return;
    627 	}
    628 
    629 	ar->ar_index = res->ar_nio++;
    630 	ar->ar_base = base;
    631 	ar->ar_length = length;
    632 
    633 	SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list);
    634 }
    635 
    636 static void
    637 acpi_res_parse_iorange(struct device *dev, void *context, uint32_t low,
    638     uint32_t high, uint32_t length, uint32_t align)
    639 {
    640 	struct acpi_resources *res = context;
    641 	struct acpi_iorange *ar;
    642 
    643 	ar = AcpiOsAllocate(sizeof(*ar));
    644 	if (ar == NULL) {
    645 		printf("%s: ACPI: unable to allocate I/O range resource %d\n",
    646 		    dev->dv_xname, res->ar_niorange);
    647 		res->ar_niorange++;
    648 		return;
    649 	}
    650 
    651 	ar->ar_index = res->ar_niorange++;
    652 	ar->ar_low = low;
    653 	ar->ar_high = high;
    654 	ar->ar_length = length;
    655 	ar->ar_align = align;
    656 
    657 	SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list);
    658 }
    659 
    660 static void
    661 acpi_res_parse_memory(struct device *dev, void *context, uint32_t base,
    662     uint32_t length)
    663 {
    664 	struct acpi_resources *res = context;
    665 	struct acpi_mem *ar;
    666 
    667 	ar = AcpiOsAllocate(sizeof(*ar));
    668 	if (ar == NULL) {
    669 		printf("%s: ACPI: unable to allocate Memory resource %d\n",
    670 		    dev->dv_xname, res->ar_nmem);
    671 		res->ar_nmem++;
    672 		return;
    673 	}
    674 
    675 	ar->ar_index = res->ar_nmem++;
    676 	ar->ar_base = base;
    677 	ar->ar_length = length;
    678 
    679 	SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list);
    680 }
    681 
    682 static void
    683 acpi_res_parse_memrange(struct device *dev, void *context, uint32_t low,
    684     uint32_t high, uint32_t length, uint32_t align)
    685 {
    686 	struct acpi_resources *res = context;
    687 	struct acpi_memrange *ar;
    688 
    689 	ar = AcpiOsAllocate(sizeof(*ar));
    690 	if (ar == NULL) {
    691 		printf("%s: ACPI: unable to allocate Memory range resource "
    692 		    "%d\n", dev->dv_xname, res->ar_nmemrange);
    693 		res->ar_nmemrange++;
    694 		return;
    695 	}
    696 
    697 	ar->ar_index = res->ar_nmemrange++;
    698 	ar->ar_low = low;
    699 	ar->ar_high = high;
    700 	ar->ar_length = length;
    701 	ar->ar_align = align;
    702 
    703 	SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list);
    704 }
    705 
    706 static void
    707 acpi_res_parse_irq(struct device *dev, void *context, uint32_t irq, uint32_t type)
    708 {
    709 	struct acpi_resources *res = context;
    710 	struct acpi_irq *ar;
    711 
    712 	ar = AcpiOsAllocate(sizeof(*ar));
    713 	if (ar == NULL) {
    714 		printf("%s: ACPI: unable to allocate IRQ resource %d\n",
    715 		    dev->dv_xname, res->ar_nirq);
    716 		res->ar_nirq++;
    717 		return;
    718 	}
    719 
    720 	ar->ar_index = res->ar_nirq++;
    721 	ar->ar_irq = irq;
    722 	ar->ar_type = type;
    723 
    724 	SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list);
    725 }
    726 
    727 static void
    728 acpi_res_parse_drq(struct device *dev, void *context, uint32_t drq)
    729 {
    730 	struct acpi_resources *res = context;
    731 	struct acpi_drq *ar;
    732 
    733 	ar = AcpiOsAllocate(sizeof(*ar));
    734 	if (ar == NULL) {
    735 		printf("%s: ACPI: unable to allocate DRQ resource %d\n",
    736 		    dev->dv_xname, res->ar_ndrq);
    737 		res->ar_ndrq++;
    738 		return;
    739 	}
    740 
    741 	ar->ar_index = res->ar_ndrq++;
    742 	ar->ar_drq = drq;
    743 
    744 	SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list);
    745 }
    746 
    747 static void
    748 acpi_res_parse_start_dep(struct device *dev, void *context, int preference)
    749 {
    750 
    751 	printf("%s: ACPI: dependant functions not supported\n",
    752 	    dev->dv_xname);
    753 }
    754 
    755 static void
    756 acpi_res_parse_end_dep(struct device *dev, void *context)
    757 {
    758 
    759 	/* Nothing to do. */
    760 }
    761