Home | History | Annotate | Line # | Download | only in acpi
      1 /*	$NetBSD: acpi_pci_link.c,v 1.29 2021/12/20 12:01:01 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2002 Mitsuru IWASAKI <iwasaki (at) jp.freebsd.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.29 2021/12/20 12:01:01 skrll Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/malloc.h>
     34 #include <sys/queue.h>
     35 #include <sys/reboot.h>
     36 #include <sys/systm.h>
     37 
     38 #include <dev/acpi/acpireg.h>
     39 #include <dev/acpi/acpivar.h>
     40 
     41 #include <dev/pci/pcireg.h>
     42 
     43 #include "opt_acpi.h"
     44 
     45 
     46 #define _COMPONENT          ACPI_BUS_COMPONENT
     47 ACPI_MODULE_NAME            ("acpi_pci_link")
     48 
     49 MALLOC_DECLARE(M_ACPI);
     50 
     51 #define NUM_ISA_INTERRUPTS	16
     52 #define NUM_ACPI_INTERRUPTS	256
     53 
     54 #define PCI_INVALID_IRQ	255
     55 #define PCI_INTERRUPT_VALID(x) ((x) != PCI_INVALID_IRQ && (x) != 0)
     56 
     57 #define ACPI_SERIAL_BEGIN(x)
     58 #define ACPI_SERIAL_END(x)
     59 
     60 /*
     61  * An ACPI PCI link device may contain multiple links.  Each link has its
     62  * own ACPI resource.  _PRT entries specify which link is being used via
     63  * the Source Index.
     64  *
     65  * XXX: A note about Source Indices and DPFs:  Currently we assume that
     66  * the DPF start and end tags are not counted towards the index that
     67  * Source Index corresponds to.  Also, we assume that when DPFs are in use
     68  * they various sets overlap in terms of Indices.  Here's an example
     69  * resource list indicating these assumptions:
     70  *
     71  * Resource		Index
     72  * --------		-----
     73  * I/O Port		0
     74  * Start DPF		-
     75  * IRQ			1
     76  * MemIO		2
     77  * Start DPF		-
     78  * IRQ			1
     79  * MemIO		2
     80  * End DPF		-
     81  * DMA Channel		3
     82  *
     83  * The XXX is because I'm not sure if this is a valid assumption to make.
     84  */
     85 
     86 /* States during DPF processing. */
     87 #define	DPF_OUTSIDE	0
     88 #define	DPF_FIRST	1
     89 #define	DPF_IGNORE	2
     90 
     91 struct link;
     92 
     93 struct acpi_pci_link_softc {
     94 	int	pl_num_links;
     95 	int	pl_crs_bad;
     96 	struct link *pl_links;
     97 	char pl_name[32];
     98 	ACPI_HANDLE pl_handle;
     99 	TAILQ_ENTRY(acpi_pci_link_softc) pl_list;
    100 };
    101 
    102 static TAILQ_HEAD(, acpi_pci_link_softc) acpi_pci_linkdevs =
    103     TAILQ_HEAD_INITIALIZER(acpi_pci_linkdevs);
    104 
    105 
    106 struct link {
    107 	struct acpi_pci_link_softc *l_sc;
    108 	uint8_t	l_bios_irq;
    109 	uint8_t	l_irq;
    110 	uint8_t l_trig;
    111 	uint8_t l_pol;
    112 	uint8_t	l_initial_irq;
    113 	int	l_res_index;
    114 	int	l_num_irqs;
    115 	int	*l_irqs;
    116 	int	l_references;
    117 	int	l_dev_count;
    118 	pcitag_t *l_devices;
    119 	u_int	l_routed:1;
    120 	u_int	l_isa_irq:1;
    121 	ACPI_RESOURCE l_prs_template;
    122 };
    123 
    124 struct link_count_request {
    125 	int	in_dpf;
    126 	int	count;
    127 };
    128 
    129 struct link_res_request {
    130 	struct acpi_pci_link_softc *sc;
    131 	int	in_dpf;
    132 	int	res_index;
    133 	int	link_index;
    134 };
    135 
    136 static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS];
    137 static int pci_link_bios_isa_irqs;
    138 
    139 static ACPI_STATUS acpi_count_irq_resources(ACPI_RESOURCE *, void *);
    140 static ACPI_STATUS link_add_crs(ACPI_RESOURCE *, void *);
    141 static ACPI_STATUS link_add_prs(ACPI_RESOURCE *, void *);
    142 static int link_valid_irq(struct link *, int);
    143 static void acpi_pci_link_dump(struct acpi_pci_link_softc *);
    144 static int acpi_pci_link_attach(struct acpi_pci_link_softc *);
    145 static uint8_t acpi_pci_link_search_irq(struct acpi_pci_link_softc *,
    146 					pci_chipset_tag_t, int, int, int);
    147 static struct link *acpi_pci_link_lookup(struct acpi_pci_link_softc *, int);
    148 static ACPI_STATUS acpi_pci_link_srs(struct acpi_pci_link_softc *,
    149 				     ACPI_BUFFER *);
    150 static ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *, ACPI_RESOURCE *);
    151 
    152 static ACPI_STATUS
    153 acpi_count_irq_resources(ACPI_RESOURCE *res, void *context)
    154 {
    155 	struct link_count_request *req;
    156 
    157 	req = (struct link_count_request *)context;
    158 	switch (res->Type) {
    159 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
    160 		switch (req->in_dpf) {
    161 		case DPF_OUTSIDE:
    162 			/* We've started the first DPF. */
    163 			req->in_dpf = DPF_FIRST;
    164 			break;
    165 		case DPF_FIRST:
    166 			/* We've started the second DPF. */
    167 			req->in_dpf = DPF_IGNORE;
    168 			break;
    169 		}
    170 		break;
    171 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
    172 		/* We are finished with DPF parsing. */
    173 		KASSERT(req->in_dpf != DPF_OUTSIDE);
    174 		req->in_dpf = DPF_OUTSIDE;
    175 		break;
    176 	case ACPI_RESOURCE_TYPE_IRQ:
    177 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
    178 		/*
    179 		 * Don't count resources if we are in a DPF set that we are
    180 		 * ignoring.
    181 		 */
    182 		if (req->in_dpf != DPF_IGNORE)
    183 			req->count++;
    184 	}
    185 	return AE_OK;
    186 }
    187 
    188 static ACPI_STATUS
    189 link_add_crs(ACPI_RESOURCE *res, void *context)
    190 {
    191 	struct link_res_request *req;
    192 	struct link *link;
    193 
    194 	req = (struct link_res_request *)context;
    195 	switch (res->Type) {
    196 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
    197 		switch (req->in_dpf) {
    198 		case DPF_OUTSIDE:
    199 			/* We've started the first DPF. */
    200 			req->in_dpf = DPF_FIRST;
    201 			break;
    202 		case DPF_FIRST:
    203 			/* We've started the second DPF. */
    204 			panic(
    205 		"%s: Multiple dependent functions within a current resource",
    206 			    __func__);
    207 			break;
    208 		}
    209 		break;
    210 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
    211 		/* We are finished with DPF parsing. */
    212 		KASSERT(req->in_dpf != DPF_OUTSIDE);
    213 		req->in_dpf = DPF_OUTSIDE;
    214 		break;
    215 	case ACPI_RESOURCE_TYPE_IRQ:
    216 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
    217 		KASSERT(req->link_index < req->sc->pl_num_links);
    218 		link = &req->sc->pl_links[req->link_index];
    219 		link->l_res_index = req->res_index;
    220 		req->link_index++;
    221 		req->res_index++;
    222 
    223 		/*
    224 		 * Only use the current value if there's one IRQ.  Some
    225 		 * systems return multiple IRQs (which is nonsense for _CRS)
    226 		 * when the link hasn't been programmed.
    227 		 */
    228 		if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
    229 			if (res->Data.Irq.InterruptCount == 1) {
    230 				link->l_irq = res->Data.Irq.Interrupts[0];
    231 				link->l_trig = res->Data.Irq.Triggering;
    232 				link->l_pol = res->Data.Irq.Polarity;
    233 			}
    234 		} else if (res->Data.ExtendedIrq.InterruptCount == 1) {
    235 			link->l_irq = res->Data.ExtendedIrq.Interrupts[0];
    236 			link->l_trig = res->Data.ExtendedIrq.Triggering;
    237 			link->l_pol = res->Data.ExtendedIrq.Polarity;
    238 		}
    239 
    240 		/*
    241 		 * An IRQ of zero means that the link isn't routed.
    242 		 */
    243 		if (link->l_irq == 0)
    244 			link->l_irq = PCI_INVALID_IRQ;
    245 		break;
    246 	default:
    247 		req->res_index++;
    248 	}
    249 	return AE_OK;
    250 }
    251 
    252 /*
    253  * Populate the set of possible IRQs for each device.
    254  */
    255 static ACPI_STATUS
    256 link_add_prs(ACPI_RESOURCE *res, void *context)
    257 {
    258 	ACPI_RESOURCE *tmp;
    259 	struct link_res_request *req;
    260 	struct link *link;
    261 	uint8_t *irqs = NULL;
    262 	uint32_t *ext_irqs = NULL;
    263 	int i, is_ext_irq = 1;
    264 
    265 	req = (struct link_res_request *)context;
    266 	switch (res->Type) {
    267 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
    268 		switch (req->in_dpf) {
    269 		case DPF_OUTSIDE:
    270 			/* We've started the first DPF. */
    271 			req->in_dpf = DPF_FIRST;
    272 			break;
    273 		case DPF_FIRST:
    274 			/* We've started the second DPF. */
    275 			req->in_dpf = DPF_IGNORE;
    276 			break;
    277 		}
    278 		break;
    279 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
    280 		/* We are finished with DPF parsing. */
    281 		KASSERT(req->in_dpf != DPF_OUTSIDE);
    282 		req->in_dpf = DPF_OUTSIDE;
    283 		break;
    284 	case ACPI_RESOURCE_TYPE_IRQ:
    285 		is_ext_irq = 0;
    286 		/* fall through */
    287 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
    288 		/*
    289 		 * Don't parse resources if we are in a DPF set that we are
    290 		 * ignoring.
    291 		 */
    292 		if (req->in_dpf == DPF_IGNORE)
    293 			break;
    294 
    295 		KASSERT(req->link_index < req->sc->pl_num_links);
    296 		link = &req->sc->pl_links[req->link_index];
    297 		if (link->l_res_index == -1) {
    298 			KASSERT(req->sc->pl_crs_bad);
    299 			link->l_res_index = req->res_index;
    300 		}
    301 		req->link_index++;
    302 		req->res_index++;
    303 
    304 		/*
    305 		 * Stash a copy of the resource for later use when doing
    306 		 * _SRS.
    307 		 */
    308 		tmp = &link->l_prs_template;
    309 		if (is_ext_irq) {
    310 			memcpy(tmp, res, ACPI_RS_SIZE(tmp->Data.ExtendedIrq));
    311 
    312 			/*
    313 			 * XXX acpi_AppendBufferResource() cannot handle
    314 			 * optional data.
    315 			 */
    316 			memset(&tmp->Data.ExtendedIrq.ResourceSource, 0,
    317 			    sizeof(tmp->Data.ExtendedIrq.ResourceSource));
    318 			tmp->Length = ACPI_RS_SIZE(tmp->Data.ExtendedIrq);
    319 
    320 			link->l_num_irqs =
    321 			    res->Data.ExtendedIrq.InterruptCount;
    322 			link->l_trig = res->Data.ExtendedIrq.Triggering;
    323 			link->l_pol = res->Data.ExtendedIrq.Polarity;
    324 			ext_irqs = res->Data.ExtendedIrq.Interrupts;
    325 		} else {
    326 			memcpy(tmp, res, ACPI_RS_SIZE(tmp->Data.Irq));
    327 			link->l_num_irqs = res->Data.Irq.InterruptCount;
    328 			link->l_trig = res->Data.Irq.Triggering;
    329 			link->l_pol = res->Data.Irq.Polarity;
    330 			irqs = res->Data.Irq.Interrupts;
    331 		}
    332 		if (link->l_num_irqs == 0)
    333 			break;
    334 
    335 		/*
    336 		 * Save a list of the valid IRQs.  Also, if all of the
    337 		 * valid IRQs are ISA IRQs, then mark this link as
    338 		 * routed via an ISA interrupt.
    339 		 */
    340 		link->l_isa_irq = TRUE;
    341 		link->l_irqs = malloc(sizeof(int) * link->l_num_irqs,
    342 		    M_ACPI, M_WAITOK | M_ZERO);
    343 		for (i = 0; i < link->l_num_irqs; i++) {
    344 			if (is_ext_irq) {
    345 				link->l_irqs[i] = ext_irqs[i];
    346 				if (ext_irqs[i] >= NUM_ISA_INTERRUPTS)
    347 					link->l_isa_irq = FALSE;
    348 			} else {
    349 				link->l_irqs[i] = irqs[i];
    350 				if (irqs[i] >= NUM_ISA_INTERRUPTS)
    351 					link->l_isa_irq = FALSE;
    352 			}
    353 		}
    354 		break;
    355 	default:
    356 		if (req->in_dpf == DPF_IGNORE)
    357 			break;
    358 		if (req->sc->pl_crs_bad)
    359 			aprint_normal("%s: Warning: possible resource %d "
    360 			       "will be lost during _SRS\n", req->sc->pl_name,
    361 			       req->res_index);
    362 		req->res_index++;
    363 	}
    364 	return AE_OK;
    365 }
    366 
    367 static int
    368 link_valid_irq(struct link *link, int irq)
    369 {
    370 	int i;
    371 
    372 	/* Invalid interrupts are never valid. */
    373 	if (!PCI_INTERRUPT_VALID(irq))
    374 		return FALSE;
    375 
    376 	/* Any interrupt in the list of possible interrupts is valid. */
    377 	for (i = 0; i < link->l_num_irqs; i++)
    378 		if (link->l_irqs[i] == irq)
    379 			 return TRUE;
    380 
    381 	/*
    382 	 * For links routed via an ISA interrupt, if the SCI is routed via
    383 	 * an ISA interrupt, the SCI is always treated as a valid IRQ.
    384 	 */
    385 	if (link->l_isa_irq && AcpiGbl_FADT.SciInterrupt == irq &&
    386 	    irq < NUM_ISA_INTERRUPTS)
    387 		return TRUE;
    388 
    389 	/* If the interrupt wasn't found in the list it is not valid. */
    390 	return FALSE;
    391 }
    392 
    393 void
    394 acpi_pci_link_state(void)
    395 {
    396 	struct acpi_pci_link_softc *sc;
    397 
    398 	TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) {
    399 		acpi_pci_link_dump(sc);
    400 	}
    401 }
    402 
    403 static void
    404 acpi_pci_link_dump(struct acpi_pci_link_softc *sc)
    405 {
    406 	struct link *link;
    407 	int i, j;
    408 
    409 	printf("Link Device %s:\n", sc->pl_name);
    410 	printf("Index  IRQ  Rtd  Ref  IRQs\n");
    411 	for (i = 0; i < sc->pl_num_links; i++) {
    412 		link = &sc->pl_links[i];
    413 		printf("%5d  %3d   %c   %3d ", i, link->l_irq,
    414 		    link->l_routed ? 'Y' : 'N',  link->l_references);
    415 		if (link->l_num_irqs == 0)
    416 			printf(" none");
    417 		else for (j = 0; j < link->l_num_irqs; j++)
    418 			printf(" %d", link->l_irqs[j]);
    419 		printf(" polarity %u trigger %u\n", link->l_pol, link->l_trig);
    420 	}
    421 	printf("\n");
    422 }
    423 
    424 static int
    425 acpi_pci_link_attach(struct acpi_pci_link_softc *sc)
    426 {
    427 	struct link_count_request creq;
    428 	struct link_res_request rreq;
    429 	ACPI_STATUS status;
    430 	int i;
    431 
    432 	ACPI_SERIAL_BEGIN(pci_link);
    433 
    434 	/*
    435 	 * Count the number of current resources so we know how big of
    436 	 * a link array to allocate.  On some systems, _CRS is broken,
    437 	 * so for those systems try to derive the count from _PRS instead.
    438 	 */
    439 	creq.in_dpf = DPF_OUTSIDE;
    440 	creq.count = 0;
    441 	status = AcpiWalkResources(sc->pl_handle, "_CRS",
    442 	    acpi_count_irq_resources, &creq);
    443 	sc->pl_crs_bad = ACPI_FAILURE(status);
    444 	if (sc->pl_crs_bad) {
    445 		creq.in_dpf = DPF_OUTSIDE;
    446 		creq.count = 0;
    447 		status = AcpiWalkResources(sc->pl_handle, "_PRS",
    448 		    acpi_count_irq_resources, &creq);
    449 		if (ACPI_FAILURE(status)) {
    450 			aprint_error("%s: Unable to parse _CRS or _PRS: %s\n",
    451 			    sc->pl_name, AcpiFormatException(status));
    452 			ACPI_SERIAL_END(pci_link);
    453 			return ENXIO;
    454 		}
    455 	}
    456 	sc->pl_num_links = creq.count;
    457 	if (creq.count == 0) {
    458 		ACPI_SERIAL_END(pci_link);
    459 		return 0;
    460 	}
    461 	sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links,
    462 	    M_ACPI, M_WAITOK | M_ZERO);
    463 
    464 	/* Initialize the child links. */
    465 	for (i = 0; i < sc->pl_num_links; i++) {
    466 		sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
    467 		sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ;
    468 		sc->pl_links[i].l_sc = sc;
    469 		sc->pl_links[i].l_isa_irq = FALSE;
    470 		sc->pl_links[i].l_res_index = -1;
    471 		sc->pl_links[i].l_dev_count = 0;
    472 		sc->pl_links[i].l_devices = NULL;
    473 	}
    474 
    475 	/* Try to read the current settings from _CRS if it is valid. */
    476 	if (!sc->pl_crs_bad) {
    477 		rreq.in_dpf = DPF_OUTSIDE;
    478 		rreq.link_index = 0;
    479 		rreq.res_index = 0;
    480 		rreq.sc = sc;
    481 		status = AcpiWalkResources(sc->pl_handle, "_CRS",
    482 		    link_add_crs, &rreq);
    483 		if (ACPI_FAILURE(status)) {
    484 			aprint_error("%s: Unable to parse _CRS: %s\n",
    485 			    sc->pl_name, AcpiFormatException(status));
    486 			goto fail;
    487 		}
    488 	}
    489 
    490 	/*
    491 	 * Try to read the possible settings from _PRS.  Note that if the
    492 	 * _CRS is toast, we depend on having a working _PRS.  However, if
    493 	 * _CRS works, then it is ok for _PRS to be missing.
    494 	 */
    495 	rreq.in_dpf = DPF_OUTSIDE;
    496 	rreq.link_index = 0;
    497 	rreq.res_index = 0;
    498 	rreq.sc = sc;
    499 	status = AcpiWalkResources(sc->pl_handle, "_PRS",
    500 	    link_add_prs, &rreq);
    501 	if (ACPI_FAILURE(status) &&
    502 	    (status != AE_NOT_FOUND || sc->pl_crs_bad)) {
    503 		aprint_error("%s: Unable to parse _PRS: %s\n",
    504 		    sc->pl_name, AcpiFormatException(status));
    505 		goto fail;
    506 	}
    507 	if (boothowto & AB_VERBOSE) {
    508 		aprint_normal("%s: Links after initial probe:\n", sc->pl_name);
    509 		acpi_pci_link_dump(sc);
    510 	}
    511 
    512 	/* Verify initial IRQs if we have _PRS. */
    513 	if (status != AE_NOT_FOUND)
    514 		for (i = 0; i < sc->pl_num_links; i++)
    515 			if (!link_valid_irq(&sc->pl_links[i],
    516 			    sc->pl_links[i].l_irq))
    517 				sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
    518 	if (boothowto & AB_VERBOSE) {
    519 		printf("%s: Links after initial validation:\n", sc->pl_name);
    520 		acpi_pci_link_dump(sc);
    521 	}
    522 
    523 	/* Save initial IRQs. */
    524 	for (i = 0; i < sc->pl_num_links; i++)
    525 		sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq;
    526 
    527 	/*
    528 	 * Try to disable this link.  If successful, set the current IRQ to
    529 	 * zero and flags to indicate this link is not routed.  If we can't
    530 	 * run _DIS (i.e., the method doesn't exist), assume the initial
    531 	 * IRQ was routed by the BIOS.
    532 	 */
    533 #ifndef ACPI__DIS_IS_BROKEN
    534 	if (ACPI_SUCCESS(AcpiEvaluateObject(sc->pl_handle, "_DIS", NULL,
    535 	    NULL)))
    536 		for (i = 0; i < sc->pl_num_links; i++)
    537 			sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
    538 	else
    539 #endif
    540 		for (i = 0; i < sc->pl_num_links; i++)
    541 			if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq))
    542 				sc->pl_links[i].l_routed = TRUE;
    543 	if (boothowto & AB_VERBOSE) {
    544 		printf("%s: Links after disable:\n", sc->pl_name);
    545 		acpi_pci_link_dump(sc);
    546 	}
    547 	ACPI_SERIAL_END(pci_link);
    548 	return 0;
    549 fail:
    550 	ACPI_SERIAL_END(pci_link);
    551 	for (i = 0; i < sc->pl_num_links; i++) {
    552 		if (sc->pl_links[i].l_irqs != NULL)
    553 			free(sc->pl_links[i].l_irqs, M_ACPI);
    554 		if (sc->pl_links[i].l_devices != NULL)
    555 			free(sc->pl_links[i].l_devices, M_ACPI);
    556 	}
    557 	free(sc->pl_links, M_ACPI);
    558 	return ENXIO;
    559 }
    560 
    561 static void
    562 acpi_pci_link_add_functions(struct acpi_pci_link_softc *sc, struct link *link,
    563     pci_chipset_tag_t pc, int bus, int device, int pin)
    564 {
    565 	uint32_t value;
    566 	uint8_t func, maxfunc, ipin;
    567 	pcitag_t tag;
    568 
    569 	tag = pci_make_tag(pc, bus, device, 0);
    570 	/* See if we have a valid device at function 0. */
    571 	value = pci_conf_read(pc, tag,  PCI_BHLC_REG);
    572 	if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB)
    573 		return;
    574 	if (PCI_HDRTYPE_MULTIFN(value))
    575 		maxfunc = 7;
    576 	else
    577 		maxfunc = 0;
    578 
    579 	/* Scan all possible functions at this device. */
    580 	for (func = 0; func <= maxfunc; func++) {
    581 		tag = pci_make_tag(pc, bus, device, func);
    582 		value = pci_conf_read(pc, tag, PCI_ID_REG);
    583 		if (PCI_VENDOR(value) == 0xffff)
    584 			continue;
    585 		value = pci_conf_read(pc, tag,
    586 		    PCI_INTERRUPT_REG);
    587 		ipin = PCI_INTERRUPT_PIN(value);
    588 		/*
    589 		 * See if it uses the pin in question.  Note that the passed
    590 		 * in pin uses 0 for A, .. 3 for D whereas the intpin
    591 		 * register uses 0 for no interrupt, 1 for A, .. 4 for D.
    592 		 */
    593 		if (ipin != pin + 1)
    594 			continue;
    595 
    596 		link->l_devices = realloc(link->l_devices,
    597 		    sizeof(pcitag_t) * (link->l_dev_count + 1),
    598 		    M_ACPI, M_WAITOK);
    599 		link->l_devices[link->l_dev_count] = tag;
    600 		++link->l_dev_count;
    601 	}
    602 }
    603 
    604 static uint8_t
    605 acpi_pci_link_search_irq(struct acpi_pci_link_softc *sc, pci_chipset_tag_t pc,
    606     int bus, int device, int pin)
    607 {
    608 	uint32_t value;
    609 	uint8_t func, maxfunc, ipin, iline;
    610 	pcitag_t tag;
    611 
    612 	tag = pci_make_tag(pc, bus, device, 0);
    613 	/* See if we have a valid device at function 0. */
    614 	value = pci_conf_read(pc, tag,  PCI_BHLC_REG);
    615 	if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB)
    616 		return PCI_INVALID_IRQ;
    617 	if (PCI_HDRTYPE_MULTIFN(value))
    618 		maxfunc = 7;
    619 	else
    620 		maxfunc = 0;
    621 
    622 	/* Scan all possible functions at this device. */
    623 	for (func = 0; func <= maxfunc; func++) {
    624 		tag = pci_make_tag(pc, bus, device, func);
    625 		value = pci_conf_read(pc, tag, PCI_ID_REG);
    626 		if (PCI_VENDOR(value) == 0xffff)
    627 			continue;
    628 		value = pci_conf_read(pc, tag,
    629 		    PCI_INTERRUPT_REG);
    630 		ipin = PCI_INTERRUPT_PIN(value);
    631 		iline = PCI_INTERRUPT_LINE(value);
    632 
    633 		/*
    634 		 * See if it uses the pin in question.  Note that the passed
    635 		 * in pin uses 0 for A, .. 3 for D whereas the intpin
    636 		 * register uses 0 for no interrupt, 1 for A, .. 4 for D.
    637 		 */
    638 		if (ipin != pin + 1)
    639 			continue;
    640 		aprint_verbose(
    641 		    "%s: ACPI: Found matching pin for %d.%d.INT%c"
    642 	            " at func %d: %d\n",
    643 			    sc->pl_name, bus, device, pin + 'A', func, iline);
    644 		if (PCI_INTERRUPT_VALID(iline))
    645 			return iline;
    646 	}
    647 	return PCI_INVALID_IRQ;
    648 }
    649 
    650 /*
    651  * Find the link structure that corresponds to the resource index passed in
    652  * via 'source_index'.
    653  */
    654 static struct link *
    655 acpi_pci_link_lookup(struct acpi_pci_link_softc *sc, int source_index)
    656 {
    657 	int i;
    658 
    659 	for (i = 0; i < sc->pl_num_links; i++)
    660 		if (sc->pl_links[i].l_res_index == source_index)
    661 			return &sc->pl_links[i];
    662 	return NULL;
    663 }
    664 
    665 void
    666 acpi_pci_link_add_reference(void *v, pci_chipset_tag_t pc, int index,
    667     int bus, int slot, int pin)
    668 {
    669 	struct acpi_pci_link_softc *sc = v;
    670 	struct link *link;
    671 	uint8_t bios_irq;
    672 
    673 	/* Bump the reference count. */
    674 	ACPI_SERIAL_BEGIN(pci_link);
    675 	link = acpi_pci_link_lookup(sc, index);
    676 	if (link == NULL) {
    677 		printf("%s: apparently invalid index %d\n", sc->pl_name, index);
    678 		ACPI_SERIAL_END(pci_link);
    679 		return;
    680 	}
    681 	link->l_references++;
    682 	acpi_pci_link_add_functions(sc, link, pc, bus, slot, pin);
    683 	if (link->l_routed)
    684 		pci_link_interrupt_weights[link->l_irq]++;
    685 
    686 	/*
    687 	 * The BIOS only routes interrupts via ISA IRQs using the ATPICs
    688 	 * (8259As).  Thus, if this link is routed via an ISA IRQ, go
    689 	 * look to see if the BIOS routed an IRQ for this link at the
    690 	 * indicated (bus, slot, pin).  If so, we prefer that IRQ for
    691 	 * this link and add that IRQ to our list of known-good IRQs.
    692 	 * This provides a good work-around for link devices whose _CRS
    693 	 * method is either broken or bogus.  We only use the value
    694 	 * returned by _CRS if we can't find a valid IRQ via this method
    695 	 * in fact.
    696 	 *
    697 	 * If this link is not routed via an ISA IRQ (because we are using
    698 	 * APIC for example), then don't bother looking up the BIOS IRQ
    699 	 * as if we find one it won't be valid anyway.
    700 	 */
    701 	if (!link->l_isa_irq) {
    702 		ACPI_SERIAL_END(pci_link);
    703 		return;
    704 	}
    705 
    706 	/* Try to find a BIOS IRQ setting from any matching devices. */
    707 	bios_irq = acpi_pci_link_search_irq(sc, pc, bus, slot, pin);
    708 	if (!PCI_INTERRUPT_VALID(bios_irq)) {
    709 		ACPI_SERIAL_END(pci_link);
    710 		return;
    711 	}
    712 
    713 	/* Validate the BIOS IRQ. */
    714 	if (!link_valid_irq(link, bios_irq)) {
    715 		printf("%s: BIOS IRQ %u for %d.%d.INT%c is invalid\n",
    716 		    sc->pl_name, bios_irq, (int)bus, slot, pin + 'A');
    717 	} else if (!PCI_INTERRUPT_VALID(link->l_bios_irq)) {
    718 		link->l_bios_irq = bios_irq;
    719 		if (bios_irq < NUM_ISA_INTERRUPTS)
    720 			pci_link_bios_isa_irqs |= (1 << bios_irq);
    721 		if (bios_irq != link->l_initial_irq &&
    722 		    PCI_INTERRUPT_VALID(link->l_initial_irq))
    723 			printf(
    724 			    "%s: BIOS IRQ %u does not match initial IRQ %u\n",
    725 			    sc->pl_name, bios_irq, link->l_initial_irq);
    726 	} else if (bios_irq != link->l_bios_irq)
    727 		printf(
    728 	    "%s: BIOS IRQ %u for %d.%d.INT%c does not match "
    729 	    "previous BIOS IRQ %u\n",
    730 		    sc->pl_name, bios_irq, (int)bus, slot, pin + 'A',
    731 		    link->l_bios_irq);
    732 	ACPI_SERIAL_END(pci_link);
    733 }
    734 
    735 static ACPI_STATUS
    736 acpi_pci_link_srs_from_crs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf)
    737 {
    738 	ACPI_RESOURCE *end, *res;
    739 	ACPI_STATUS status;
    740 	struct link *link;
    741 	int i, in_dpf;
    742 
    743 	/* Fetch the _CRS. */
    744 	srsbuf->Pointer = NULL;
    745 	srsbuf->Length = ACPI_ALLOCATE_BUFFER;
    746 	status = AcpiGetCurrentResources(sc->pl_handle, srsbuf);
    747 	if (ACPI_SUCCESS(status) && srsbuf->Pointer == NULL)
    748 		status = AE_NO_MEMORY;
    749 	if (ACPI_FAILURE(status)) {
    750 		aprint_verbose("%s: Unable to fetch current resources: %s\n",
    751 		    sc->pl_name, AcpiFormatException(status));
    752 		return status;
    753 	}
    754 
    755 	/* Fill in IRQ resources via link structures. */
    756 	link = sc->pl_links;
    757 	i = 0;
    758 	in_dpf = DPF_OUTSIDE;
    759 	res = (ACPI_RESOURCE *)srsbuf->Pointer;
    760 	end = (ACPI_RESOURCE *)((char *)srsbuf->Pointer + srsbuf->Length);
    761 	for (;;) {
    762 		switch (res->Type) {
    763 		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
    764 			switch (in_dpf) {
    765 			case DPF_OUTSIDE:
    766 				/* We've started the first DPF. */
    767 				in_dpf = DPF_FIRST;
    768 				break;
    769 			case DPF_FIRST:
    770 				/* We've started the second DPF. */
    771 				panic(
    772 		"%s: Multiple dependent functions within a current resource",
    773 				    __func__);
    774 				break;
    775 			}
    776 			break;
    777 		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
    778 			/* We are finished with DPF parsing. */
    779 			KASSERT(in_dpf != DPF_OUTSIDE);
    780 			in_dpf = DPF_OUTSIDE;
    781 			break;
    782 		case ACPI_RESOURCE_TYPE_IRQ:
    783 			res->Data.Irq.InterruptCount = 1;
    784 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
    785 				KASSERT(link->l_irq < NUM_ISA_INTERRUPTS);
    786 				res->Data.Irq.Interrupts[0] = link->l_irq;
    787 				res->Data.Irq.Triggering = link->l_trig;
    788 				res->Data.Irq.Polarity = link->l_pol;
    789 			} else
    790 				res->Data.Irq.Interrupts[0] = 0;
    791 			link++;
    792 			i++;
    793 			break;
    794 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
    795 			res->Data.ExtendedIrq.InterruptCount = 1;
    796 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
    797 				res->Data.ExtendedIrq.Interrupts[0] =
    798 				    link->l_irq;
    799 				res->Data.ExtendedIrq.Triggering =
    800 				    link->l_trig;
    801 				res->Data.ExtendedIrq.Polarity = link->l_pol;
    802 			} else
    803 				res->Data.ExtendedIrq.Interrupts[0] = 0;
    804 			link++;
    805 			i++;
    806 			break;
    807 		}
    808 		if (res->Type == ACPI_RESOURCE_TYPE_END_TAG)
    809 			break;
    810 		res = ACPI_NEXT_RESOURCE(res);
    811 		if (res >= end)
    812 			break;
    813 	}
    814 	return AE_OK;
    815 }
    816 
    817 static ACPI_STATUS
    818 acpi_pci_link_srs_from_links(struct acpi_pci_link_softc *sc,
    819     ACPI_BUFFER *srsbuf)
    820 {
    821 	ACPI_RESOURCE newres;
    822 	ACPI_STATUS status;
    823 	struct link *link;
    824 	int i;
    825 
    826 	/* Start off with an empty buffer. */
    827 	srsbuf->Pointer = NULL;
    828 	link = sc->pl_links;
    829 	for (i = 0; i < sc->pl_num_links; i++) {
    830 
    831 		/* Add a new IRQ resource from each link. */
    832 		link = &sc->pl_links[i];
    833 		if (link->l_prs_template.Type == ACPI_RESOURCE_TYPE_IRQ) {
    834 
    835 			/* Build an IRQ resource. */
    836 			bcopy(&link->l_prs_template, &newres,
    837 			    ACPI_RS_SIZE(newres.Data.Irq));
    838 			newres.Data.Irq.InterruptCount = 1;
    839 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
    840 				KASSERT(link->l_irq < NUM_ISA_INTERRUPTS);
    841 				newres.Data.Irq.Interrupts[0] = link->l_irq;
    842 				newres.Data.Irq.Triggering = link->l_trig;
    843 				newres.Data.Irq.Polarity = link->l_pol;
    844 			} else
    845 				newres.Data.Irq.Interrupts[0] = 0;
    846 		} else {
    847 
    848 			/* Build an ExtIRQ resuorce. */
    849 			bcopy(&link->l_prs_template, &newres,
    850 			    ACPI_RS_SIZE(newres.Data.ExtendedIrq));
    851 			newres.Data.ExtendedIrq.InterruptCount = 1;
    852 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
    853 				newres.Data.ExtendedIrq.Interrupts[0] =
    854 				    link->l_irq;
    855 				newres.Data.ExtendedIrq.Triggering =
    856 				    link->l_trig;
    857 				newres.Data.ExtendedIrq.Polarity =
    858 				    link->l_pol;
    859 			} else {
    860 				newres.Data.ExtendedIrq.Interrupts[0] = 0;
    861 			}
    862 		}
    863 
    864 		/* Add the new resource to the end of the _SRS buffer. */
    865 		status = acpi_AppendBufferResource(srsbuf, &newres);
    866 		if (ACPI_FAILURE(status)) {
    867 			printf("%s: Unable to build resources: %s\n",
    868 			    sc->pl_name, AcpiFormatException(status));
    869 			if (srsbuf->Pointer != NULL)
    870 				ACPI_FREE(srsbuf->Pointer);
    871 			return status;
    872 		}
    873 	}
    874 	return AE_OK;
    875 }
    876 
    877 static ACPI_STATUS
    878 acpi_pci_link_srs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf)
    879 {
    880 	ACPI_STATUS status;
    881 
    882 	if (sc->pl_crs_bad)
    883 		status = acpi_pci_link_srs_from_links(sc, srsbuf);
    884 	else
    885 		status = acpi_pci_link_srs_from_crs(sc, srsbuf);
    886 
    887 	if (ACPI_FAILURE(status))
    888 		printf("%s: Unable to find link srs : %s\n",
    889 		    sc->pl_name, AcpiFormatException(status));
    890 
    891 	/* Write out new resources via _SRS. */
    892 	return AcpiSetCurrentResources(sc->pl_handle, srsbuf);
    893 }
    894 
    895 static ACPI_STATUS
    896 acpi_pci_link_route_irqs(struct acpi_pci_link_softc *sc, int *irq, int *pol,
    897 			 int *trig)
    898 {
    899 	ACPI_RESOURCE *resource, *end;
    900 	ACPI_BUFFER srsbuf;
    901 	ACPI_STATUS status;
    902 	struct link *link;
    903 	int i, is_ext = 0;
    904 
    905 	status = acpi_pci_link_srs(sc, &srsbuf);
    906 	if (ACPI_FAILURE(status)) {
    907 		printf("%s: _SRS failed: %s\n",
    908 		    sc->pl_name, AcpiFormatException(status));
    909 		return status;
    910 	}
    911 	/*
    912 	 * Perform acpi_config_intr() on each IRQ resource if it was just
    913 	 * routed for the first time.
    914 	 */
    915 	link = sc->pl_links;
    916 	i = 0;
    917 	resource = (ACPI_RESOURCE *)srsbuf.Pointer;
    918 	end = (ACPI_RESOURCE *)((char *)srsbuf.Pointer + srsbuf.Length);
    919 	for (;;) {
    920 		if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG)
    921 			break;
    922 		switch (resource->Type) {
    923 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
    924 			is_ext = 1;
    925 			/* FALLTHROUGH */
    926 		case ACPI_RESOURCE_TYPE_IRQ:
    927 			/*
    928 			 * Only configure the interrupt and update the
    929 			 * weights if this link has a valid IRQ and was
    930 			 * previously unrouted.
    931 			 */
    932 			if (!link->l_routed &&
    933 			    PCI_INTERRUPT_VALID(link->l_irq)) {
    934 				*trig = is_ext ?
    935 				    resource->Data.ExtendedIrq.Triggering :
    936 				    resource->Data.Irq.Triggering;
    937 				*pol = is_ext ?
    938 				    resource->Data.ExtendedIrq.Polarity :
    939 				    resource->Data.Irq.Polarity;
    940 				*irq = is_ext ?
    941 				    resource->Data.ExtendedIrq.Interrupts[0] :
    942 				    resource->Data.Irq.Interrupts[0];
    943 				link->l_routed = TRUE;
    944 				pci_link_interrupt_weights[link->l_irq] +=
    945 				    link->l_references;
    946 			}
    947 			link++;
    948 			i++;
    949 			break;
    950 		}
    951 		resource = ACPI_NEXT_RESOURCE(resource);
    952 		if (resource >= end)
    953 			break;
    954 	}
    955 	ACPI_FREE(srsbuf.Pointer);
    956 	return AE_OK;
    957 }
    958 
    959 /*
    960  * Pick an IRQ to use for this unrouted link.
    961  */
    962 static uint8_t
    963 acpi_pci_link_choose_irq(struct acpi_pci_link_softc *sc, struct link *link)
    964 {
    965 	u_int8_t best_irq, pos_irq;
    966 	int best_weight, pos_weight, i;
    967 
    968 	KASSERT(!link->l_routed);
    969 	KASSERT(!PCI_INTERRUPT_VALID(link->l_irq));
    970 
    971 	/*
    972 	 * If we have a valid BIOS IRQ, use that.  We trust what the BIOS
    973 	 * says it routed over what _CRS says the link thinks is routed.
    974 	 */
    975 	if (PCI_INTERRUPT_VALID(link->l_bios_irq))
    976 		return link->l_bios_irq;
    977 
    978 	/*
    979 	 * If we don't have a BIOS IRQ but do have a valid IRQ from _CRS,
    980 	 * then use that.
    981 	 */
    982 	if (PCI_INTERRUPT_VALID(link->l_initial_irq))
    983 		return link->l_initial_irq;
    984 
    985 	/*
    986 	 * Ok, we have no useful hints, so we have to pick from the
    987 	 * possible IRQs.  For ISA IRQs we only use interrupts that
    988 	 * have already been used by the BIOS.
    989 	 */
    990 	best_irq = PCI_INVALID_IRQ;
    991 	best_weight = INT_MAX;
    992 	for (i = 0; i < link->l_num_irqs; i++) {
    993 		pos_irq = link->l_irqs[i];
    994 		if (pos_irq < NUM_ISA_INTERRUPTS &&
    995 		    (pci_link_bios_isa_irqs & 1 << pos_irq) == 0)
    996 			continue;
    997 		pos_weight = pci_link_interrupt_weights[pos_irq];
    998 		if (pos_weight < best_weight) {
    999 			best_weight = pos_weight;
   1000 			best_irq = pos_irq;
   1001 		}
   1002 	}
   1003 
   1004 	/*
   1005 	 * If this is an ISA IRQ, try using the SCI if it is also an ISA
   1006 	 * interrupt as a fallback.
   1007 	 */
   1008 	if (link->l_isa_irq && !PCI_INTERRUPT_VALID(best_irq)) {
   1009 		pos_irq = AcpiGbl_FADT.SciInterrupt;
   1010 		pos_weight = pci_link_interrupt_weights[pos_irq];
   1011 		if (pos_weight < best_weight) {
   1012 			best_weight = pos_weight;
   1013 			best_irq = pos_irq;
   1014 		}
   1015 	}
   1016 
   1017 	if (PCI_INTERRUPT_VALID(best_irq)) {
   1018 		aprint_verbose("%s: Picked IRQ %u with weight %d\n",
   1019 		    sc->pl_name, best_irq, best_weight);
   1020 	} else
   1021 		printf("%s: Unable to choose an IRQ\n", sc->pl_name);
   1022 	return best_irq;
   1023 }
   1024 
   1025 int
   1026 acpi_pci_link_route_interrupt(void *v, pci_chipset_tag_t pc, int index,
   1027     int *irq, int *pol, int *trig)
   1028 {
   1029 	struct acpi_pci_link_softc *sc = v;
   1030 	struct link *link;
   1031 	int i;
   1032 	pcireg_t reg;
   1033 
   1034 	ACPI_SERIAL_BEGIN(pci_link);
   1035 	link = acpi_pci_link_lookup(sc, index);
   1036 	if (link == NULL)
   1037 		panic("%s: apparently invalid index %d", __func__, index);
   1038 
   1039 	/*
   1040 	 * If this link device is already routed to an interrupt, just return
   1041 	 * the interrupt it is routed to.
   1042 	 */
   1043 	if (link->l_routed) {
   1044 		KASSERT(PCI_INTERRUPT_VALID(link->l_irq));
   1045 		ACPI_SERIAL_END(pci_link);
   1046 		*irq = link->l_irq;
   1047 		*pol = link->l_pol;
   1048 		*trig = link->l_trig;
   1049 		return link->l_irq;
   1050 	}
   1051 
   1052 	if (PCI_INTERRUPT_VALID(link->l_irq)) {
   1053 		*irq = link->l_irq;
   1054 		*pol = link->l_pol;
   1055 		*trig = link->l_trig;
   1056 		goto done;
   1057 	}
   1058 
   1059 	/* The link device doesn't have an interrupt, so try to choose one. */
   1060 	link->l_irq = acpi_pci_link_choose_irq(sc, link);
   1061 	if (!PCI_INTERRUPT_VALID(link->l_irq))
   1062 		goto done;
   1063 
   1064 	/*
   1065 	 * Try to route the interrupt we picked.  If it fails, then
   1066 	 * assume the interrupt is not routed.
   1067 	 */
   1068 	acpi_pci_link_route_irqs(sc, irq, pol, trig);
   1069 	if (!link->l_routed) {
   1070 		link->l_irq = PCI_INVALID_IRQ;
   1071 		goto done;
   1072 	}
   1073 
   1074 	link->l_pol = *pol;
   1075 	link->l_trig = *trig;
   1076 	for (i = 0; i < link->l_dev_count; ++i) {
   1077 		reg = pci_conf_read(pc, link->l_devices[i],
   1078 		    PCI_INTERRUPT_REG);
   1079 		reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
   1080 		reg |= link->l_irq << PCI_INTERRUPT_LINE_SHIFT;
   1081 		pci_conf_write(pc, link->l_devices[i],
   1082 		    PCI_INTERRUPT_REG, reg);
   1083 	}
   1084 
   1085 done:
   1086 	ACPI_SERIAL_END(pci_link);
   1087 
   1088 	return link->l_irq;
   1089 }
   1090 
   1091 /*
   1092  * This is gross, but we abuse the identify routine to perform one-time
   1093  * SYSINIT() style initialization for the driver.
   1094  */
   1095 static void
   1096 acpi_pci_link_init(struct acpi_pci_link_softc *sc)
   1097 {
   1098 	ACPI_BUFFER buf;
   1099 
   1100 	/*
   1101 	 * If the SCI is an ISA IRQ, add it to the bitmask of known good
   1102 	 * ISA IRQs.
   1103 	 *
   1104 	 * XXX: If we are using the APIC, the SCI might have been
   1105 	 * rerouted to an APIC pin in which case this is invalid.  However,
   1106 	 * if we are using the APIC, we also shouldn't be having any PCI
   1107 	 * interrupts routed via ISA IRQs, so this is probably ok.
   1108 	 */
   1109 	if (AcpiGbl_FADT.SciInterrupt < NUM_ISA_INTERRUPTS)
   1110 		pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT.SciInterrupt);
   1111 
   1112 	buf.Length = sizeof (sc->pl_name);
   1113 	buf.Pointer = sc->pl_name;
   1114 
   1115 	if (ACPI_FAILURE(AcpiGetName(sc->pl_handle, ACPI_SINGLE_NAME, &buf)))
   1116 		snprintf(sc->pl_name, sizeof (sc->pl_name), "%s",
   1117 		    "ACPI link device");
   1118 
   1119 	acpi_pci_link_attach(sc);
   1120 }
   1121 
   1122 void *
   1123 acpi_pci_link_devbyhandle(ACPI_HANDLE handle)
   1124 {
   1125 	struct acpi_pci_link_softc *sc;
   1126 
   1127 	TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) {
   1128 		if (sc->pl_handle == handle)
   1129 			return sc;
   1130 	}
   1131 
   1132 	sc = malloc(sizeof (*sc), M_ACPI, M_WAITOK | M_ZERO);
   1133 	sc->pl_handle = handle;
   1134 
   1135 	acpi_pci_link_init(sc);
   1136 
   1137 	TAILQ_INSERT_TAIL(&acpi_pci_linkdevs, sc, pl_list);
   1138 
   1139 	return (void *)sc;
   1140 }
   1141 
   1142 void
   1143 acpi_pci_link_resume(void)
   1144 {
   1145 	struct acpi_pci_link_softc *sc;
   1146 	ACPI_BUFFER srsbuf;
   1147 
   1148 	TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) {
   1149 		ACPI_SERIAL_BEGIN(pci_link);
   1150 		if (ACPI_SUCCESS(acpi_pci_link_srs(sc, &srsbuf)))
   1151 			ACPI_FREE(srsbuf.Pointer);
   1152 		ACPI_SERIAL_END(pci_link);
   1153 	}
   1154 }
   1155 
   1156 ACPI_HANDLE
   1157 acpi_pci_link_handle(void *v)
   1158 {
   1159 	struct acpi_pci_link_softc *sc = v;
   1160 
   1161 	return sc->pl_handle;
   1162 }
   1163 
   1164 char *
   1165 acpi_pci_link_name(void *v)
   1166 {
   1167 	struct acpi_pci_link_softc *sc = v;
   1168 
   1169 	return sc->pl_name;
   1170 }
   1171 
   1172 
   1173 /*
   1174  * Append an ACPI_RESOURCE to an ACPI_BUFFER.
   1175  *
   1176  * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
   1177  * provided to contain it.  If the ACPI_BUFFER is empty, allocate a sensible
   1178  * backing block.  If the ACPI_RESOURCE is NULL, return an empty set of
   1179  * resources.
   1180  */
   1181 #define ACPI_INITIAL_RESOURCE_BUFFER_SIZE	512
   1182 
   1183 static ACPI_STATUS
   1184 acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
   1185 {
   1186 	ACPI_RESOURCE	*rp;
   1187 	void		*newp;
   1188 
   1189 	/* Initialise the buffer if necessary. */
   1190 	if (buf->Pointer == NULL) {
   1191 	buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
   1192 	if ((buf->Pointer = ACPI_ALLOCATE(buf->Length)) == NULL)
   1193 		return (AE_NO_MEMORY);
   1194 	rp = (ACPI_RESOURCE *)buf->Pointer;
   1195 	rp->Type =  ACPI_RESOURCE_TYPE_END_TAG;
   1196 	rp->Length = 0;
   1197 	}
   1198 
   1199 	if (res == NULL)
   1200 		return AE_OK;
   1201 
   1202 	/*
   1203 	 * Scan the current buffer looking for the terminator.
   1204 	 * This will either find the terminator or hit the end
   1205 	 * of the buffer and return an error.
   1206 	 */
   1207 	rp = (ACPI_RESOURCE *)buf->Pointer;
   1208 	for (;;) {
   1209 		/* Range check, don't go outside the buffer */
   1210 		if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer +
   1211 		    buf->Length))
   1212 			return AE_BAD_PARAMETER;
   1213 		if (rp->Type ==  ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0)
   1214 			break;
   1215 		rp = ACPI_NEXT_RESOURCE(rp);
   1216 	}
   1217 
   1218 	/*
   1219 	 * Check the size of the buffer and expand if required.
   1220 	 *
   1221 	 * Required size is:
   1222 	 *	size of existing resources before terminator +
   1223 	 *	size of new resource and header +
   1224 	 * 	size of terminator.
   1225 	 *
   1226 	 * Note that this loop should really only run once, unless
   1227 	 * for some reason we are stuffing a *really* huge resource.
   1228 	 */
   1229 	while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +
   1230 	    res->Length + ACPI_RS_SIZE_NO_DATA +
   1231 	    ACPI_RS_SIZE_MIN) >= buf->Length) {
   1232 		if ((newp = ACPI_ALLOCATE(buf->Length * 2)) == NULL)
   1233 			return AE_NO_MEMORY;
   1234 		memcpy(newp, buf->Pointer, buf->Length);
   1235 		rp = (ACPI_RESOURCE *)((u_int8_t *)newp +
   1236 		   ((u_int8_t *)rp - (u_int8_t *)buf->Pointer));
   1237 		ACPI_FREE(buf->Pointer);
   1238 		buf->Pointer = newp;
   1239 		buf->Length += buf->Length;
   1240 	}
   1241 
   1242 	/* Insert the new resource. */
   1243 	memcpy(rp, res, res->Length);
   1244 
   1245 	/* And add the terminator. */
   1246 	rp = ACPI_NEXT_RESOURCE(rp);
   1247 	rp->Type =  ACPI_RESOURCE_TYPE_END_TAG;
   1248 	rp->Length = 0;
   1249 
   1250 	return AE_OK;
   1251 }
   1252