xref: /freebsd/sys/dev/acpica/acpi_pci_link.c (revision 6af83ee0d2941d18880b6aaa2b4facd1d30c6106)
1 /*-
2  * Copyright (c) 2002 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_acpi.h"
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/limits.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 
38 #include "acpi.h"
39 #include <dev/acpica/acpivar.h>
40 #include <dev/acpica/acpi_pcibvar.h>
41 
42 #include <machine/pci_cfgreg.h>
43 #include <dev/pci/pcireg.h>
44 #include <dev/pci/pcivar.h>
45 #include "pcib_if.h"
46 
47 /* Hooks for the ACPI CA debugging infrastructure. */
48 #define _COMPONENT	ACPI_BUS
49 ACPI_MODULE_NAME("PCI_LINK")
50 
51 ACPI_SERIAL_DECL(pci_link, "ACPI PCI link");
52 
53 #define NUM_ISA_INTERRUPTS	16
54 #define NUM_ACPI_INTERRUPTS	256
55 
56 /*
57  * An ACPI PCI link device may contain multiple links.  Each link has its
58  * own ACPI resource.  _PRT entries specify which link is being used via
59  * the Source Index.
60  *
61  * XXX: A note about Source Indices and DPFs:  Currently we assume that
62  * the DPF start and end tags are not counted towards the index that
63  * Source Index corresponds to.  Also, we assume that when DPFs are in use
64  * they various sets overlap in terms of Indices.  Here's an example
65  * resource list indicating these assumptions:
66  *
67  * Resource		Index
68  * --------		-----
69  * I/O Port		0
70  * Start DPF		-
71  * IRQ			1
72  * MemIO		2
73  * Start DPF		-
74  * IRQ			1
75  * MemIO		2
76  * End DPF		-
77  * DMA Channel		3
78  *
79  * The XXX is because I'm not sure if this is a valid assumption to make.
80  */
81 
82 /* States during DPF processing. */
83 #define	DPF_OUTSIDE	0
84 #define	DPF_FIRST	1
85 #define	DPF_IGNORE	2
86 
87 struct link;
88 
89 struct acpi_pci_link_softc {
90 	int	pl_num_links;
91 	int	pl_crs_bad;
92 	struct link *pl_links;
93 	device_t pl_dev;
94 };
95 
96 struct link {
97 	struct acpi_pci_link_softc *l_sc;
98 	uint8_t	l_bios_irq;
99 	uint8_t	l_irq;
100 	uint8_t	l_initial_irq;
101 	int	l_res_index;
102 	int	l_num_irqs;
103 	int	*l_irqs;
104 	int	l_references;
105 	int	l_routed:1;
106 	int	l_isa_irq:1;
107 	ACPI_RESOURCE l_prs_template;
108 };
109 
110 struct link_count_request {
111 	int	in_dpf;
112 	int	count;
113 };
114 
115 struct link_res_request {
116 	struct acpi_pci_link_softc *sc;
117 	int	in_dpf;
118 	int	res_index;
119 	int	link_index;
120 };
121 
122 MALLOC_DEFINE(M_PCI_LINK, "PCI Link", "ACPI PCI Link structures");
123 
124 static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS];
125 static int pci_link_bios_isa_irqs;
126 
127 static char *pci_link_ids[] = { "PNP0C0F", NULL };
128 
129 /*
130  * Fetch the short name associated with an ACPI handle and save it in the
131  * passed in buffer.
132  */
133 static ACPI_STATUS
134 acpi_short_name(ACPI_HANDLE handle, char *buffer, size_t buflen)
135 {
136 	ACPI_BUFFER buf;
137 
138 	buf.Length = buflen;
139 	buf.Pointer = buffer;
140 	return (AcpiGetName(handle, ACPI_SINGLE_NAME, &buf));
141 }
142 
143 static int
144 acpi_pci_link_probe(device_t dev)
145 {
146 	char descr[28], name[12];
147 
148 	/*
149 	 * We explicitly do not check _STA since not all systems set it to
150 	 * sensible values.
151 	 */
152 	if (acpi_disabled("pci_link") ||
153 	    ACPI_ID_PROBE(device_get_parent(dev), dev, pci_link_ids) == NULL)
154 		return (ENXIO);
155 
156 	if (ACPI_SUCCESS(acpi_short_name(acpi_get_handle(dev), name,
157 	    sizeof(name)))) {
158 		snprintf(descr, sizeof(descr), "ACPI PCI Link %s", name);
159 		device_set_desc_copy(dev, descr);
160 	} else
161 		device_set_desc(dev, "ACPI PCI Link");
162 	return (0);
163 }
164 
165 static ACPI_STATUS
166 acpi_count_irq_resources(ACPI_RESOURCE *res, void *context)
167 {
168 	struct link_count_request *req;
169 
170 	req = (struct link_count_request *)context;
171 	switch (res->Id) {
172 	case ACPI_RSTYPE_START_DPF:
173 		switch (req->in_dpf) {
174 		case DPF_OUTSIDE:
175 			/* We've started the first DPF. */
176 			req->in_dpf = DPF_FIRST;
177 			break;
178 		case DPF_FIRST:
179 			/* We've started the second DPF. */
180 			req->in_dpf = DPF_IGNORE;
181 			break;
182 		}
183 		break;
184 	case ACPI_RSTYPE_END_DPF:
185 		/* We are finished with DPF parsing. */
186 		KASSERT(req->in_dpf != DPF_OUTSIDE,
187 		    ("%s: end dpf when not parsing a dpf", __func__));
188 		req->in_dpf = DPF_OUTSIDE;
189 		break;
190 	case ACPI_RSTYPE_IRQ:
191 	case ACPI_RSTYPE_EXT_IRQ:
192 		/*
193 		 * Don't count resources if we are in a DPF set that we are
194 		 * ignoring.
195 		 */
196 		if (req->in_dpf != DPF_IGNORE)
197 			req->count++;
198 	}
199 	return (AE_OK);
200 }
201 
202 static ACPI_STATUS
203 link_add_crs(ACPI_RESOURCE *res, void *context)
204 {
205 	struct link_res_request *req;
206 	struct link *link;
207 
208 	ACPI_SERIAL_ASSERT(pci_link);
209 	req = (struct link_res_request *)context;
210 	switch (res->Id) {
211 	case ACPI_RSTYPE_START_DPF:
212 		switch (req->in_dpf) {
213 		case DPF_OUTSIDE:
214 			/* We've started the first DPF. */
215 			req->in_dpf = DPF_FIRST;
216 			break;
217 		case DPF_FIRST:
218 			/* We've started the second DPF. */
219 			panic(
220 		"%s: Multiple dependent functions within a current resource",
221 			    __func__);
222 			break;
223 		}
224 		break;
225 	case ACPI_RSTYPE_END_DPF:
226 		/* We are finished with DPF parsing. */
227 		KASSERT(req->in_dpf != DPF_OUTSIDE,
228 		    ("%s: end dpf when not parsing a dpf", __func__));
229 		req->in_dpf = DPF_OUTSIDE;
230 		break;
231 	case ACPI_RSTYPE_IRQ:
232 	case ACPI_RSTYPE_EXT_IRQ:
233 		KASSERT(req->link_index < req->sc->pl_num_links,
234 		    ("%s: array boundary violation", __func__));
235 		link = &req->sc->pl_links[req->link_index];
236 		link->l_res_index = req->res_index;
237 		req->link_index++;
238 		req->res_index++;
239 
240 		/*
241 		 * Only use the current value if there's one IRQ.  Some
242 		 * systems return multiple IRQs (which is nonsense for _CRS)
243 		 * when the link hasn't been programmed.
244 		 */
245 		if (res->Id == ACPI_RSTYPE_IRQ) {
246 			if (res->Data.Irq.NumberOfInterrupts == 1)
247 				link->l_irq = res->Data.Irq.Interrupts[0];
248 		} else if (res->Data.ExtendedIrq.NumberOfInterrupts == 1)
249 			link->l_irq = res->Data.ExtendedIrq.Interrupts[0];
250 
251 		/*
252 		 * An IRQ of zero means that the link isn't routed.
253 		 */
254 		if (link->l_irq == 0)
255 			link->l_irq = PCI_INVALID_IRQ;
256 		break;
257 	default:
258 		req->res_index++;
259 	}
260 	return (AE_OK);
261 }
262 
263 /*
264  * Populate the set of possible IRQs for each device.
265  */
266 static ACPI_STATUS
267 link_add_prs(ACPI_RESOURCE *res, void *context)
268 {
269 	struct link_res_request *req;
270 	struct link *link;
271 	UINT32 *irqs;
272 	int i;
273 
274 	ACPI_SERIAL_ASSERT(pci_link);
275 	req = (struct link_res_request *)context;
276 	switch (res->Id) {
277 	case ACPI_RSTYPE_START_DPF:
278 		switch (req->in_dpf) {
279 		case DPF_OUTSIDE:
280 			/* We've started the first DPF. */
281 			req->in_dpf = DPF_FIRST;
282 			break;
283 		case DPF_FIRST:
284 			/* We've started the second DPF. */
285 			req->in_dpf = DPF_IGNORE;
286 			break;
287 		}
288 		break;
289 	case ACPI_RSTYPE_END_DPF:
290 		/* We are finished with DPF parsing. */
291 		KASSERT(req->in_dpf != DPF_OUTSIDE,
292 		    ("%s: end dpf when not parsing a dpf", __func__));
293 		req->in_dpf = DPF_OUTSIDE;
294 		break;
295 	case ACPI_RSTYPE_IRQ:
296 	case ACPI_RSTYPE_EXT_IRQ:
297 		/*
298 		 * Don't parse resources if we are in a DPF set that we are
299 		 * ignoring.
300 		 */
301 		if (req->in_dpf == DPF_IGNORE)
302 			break;
303 
304 		KASSERT(req->link_index < req->sc->pl_num_links,
305 		    ("%s: array boundary violation", __func__));
306 		link = &req->sc->pl_links[req->link_index];
307 		if (link->l_res_index == -1) {
308 			KASSERT(req->sc->pl_crs_bad,
309 			    ("res_index should be set"));
310 			link->l_res_index = req->res_index;
311 		}
312 		req->link_index++;
313 		req->res_index++;
314 
315 		/*
316 		 * Stash a copy of the resource for later use when doing
317 		 * _SRS.
318 		 */
319 		bcopy(res, &link->l_prs_template, sizeof(ACPI_RESOURCE));
320 		if (res->Id == ACPI_RSTYPE_IRQ) {
321 			link->l_num_irqs = res->Data.Irq.NumberOfInterrupts;
322 			irqs = res->Data.Irq.Interrupts;
323 		} else {
324 			link->l_num_irqs =
325 			    res->Data.ExtendedIrq.NumberOfInterrupts;
326 			irqs = res->Data.ExtendedIrq.Interrupts;
327 		}
328 		if (link->l_num_irqs == 0)
329 			break;
330 
331 		/*
332 		 * Save a list of the valid IRQs.  Also, if all of the
333 		 * valid IRQs are ISA IRQs, then mark this link as
334 		 * routed via an ISA interrupt.
335 		 */
336 		link->l_isa_irq = TRUE;
337 		link->l_irqs = malloc(sizeof(int) * link->l_num_irqs,
338 		    M_PCI_LINK, M_WAITOK | M_ZERO);
339 		for (i = 0; i < link->l_num_irqs; i++) {
340 			link->l_irqs[i] = irqs[i];
341 			if (irqs[i] >= NUM_ISA_INTERRUPTS)
342 				link->l_isa_irq = FALSE;
343 		}
344 		break;
345 	default:
346 		if (req->in_dpf == DPF_IGNORE)
347 			break;
348 		if (req->sc->pl_crs_bad)
349 			device_printf(req->sc->pl_dev,
350 		    "Warning: possible resource %d will be lost during _SRS\n",
351 			    req->res_index);
352 		req->res_index++;
353 	}
354 	return (AE_OK);
355 }
356 
357 static int
358 link_valid_irq(struct link *link, int irq)
359 {
360 	int i;
361 
362 	ACPI_SERIAL_ASSERT(pci_link);
363 
364 	/* Invalid interrupts are never valid. */
365 	if (!PCI_INTERRUPT_VALID(irq))
366 		return (FALSE);
367 
368 	/* Any interrupt in the list of possible interrupts is valid. */
369 	for (i = 0; i < link->l_num_irqs; i++)
370 		if (link->l_irqs[i] == irq)
371 			 return (TRUE);
372 
373 	/*
374 	 * For links routed via an ISA interrupt, if the SCI is routed via
375 	 * an ISA interrupt, the SCI is always treated as a valid IRQ.
376 	 */
377 	if (link->l_isa_irq && AcpiGbl_FADT->SciInt == irq &&
378 	    irq < NUM_ISA_INTERRUPTS)
379 		return (TRUE);
380 
381 	/* If the interrupt wasn't found in the list it is not valid. */
382 	return (FALSE);
383 }
384 
385 static void
386 acpi_pci_link_dump(struct acpi_pci_link_softc *sc)
387 {
388 	struct link *link;
389 	int i, j;
390 
391 	ACPI_SERIAL_ASSERT(pci_link);
392 	printf("Index  IRQ  Rtd  Ref  IRQs\n");
393 	for (i = 0; i < sc->pl_num_links; i++) {
394 		link = &sc->pl_links[i];
395 		printf("%5d  %3d   %c   %3d ", i, link->l_irq,
396 		    link->l_routed ? 'Y' : 'N',  link->l_references);
397 		if (link->l_num_irqs == 0)
398 			printf(" none");
399 		else for (j = 0; j < link->l_num_irqs; j++)
400 			printf(" %d", link->l_irqs[j]);
401 		printf("\n");
402 	}
403 }
404 
405 static int
406 acpi_pci_link_attach(device_t dev)
407 {
408 	struct acpi_pci_link_softc *sc;
409 	struct link_count_request creq;
410 	struct link_res_request rreq;
411 	ACPI_STATUS status;
412 	int i;
413 
414 	sc = device_get_softc(dev);
415 	sc->pl_dev = dev;
416 	ACPI_SERIAL_BEGIN(pci_link);
417 
418 	/*
419 	 * Count the number of current resources so we know how big of
420 	 * a link array to allocate.  On some systems, _CRS is broken,
421 	 * so for those systems try to derive the count from _PRS instead.
422 	 */
423 	creq.in_dpf = DPF_OUTSIDE;
424 	creq.count = 0;
425 	status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
426 	    acpi_count_irq_resources, &creq);
427 	sc->pl_crs_bad = ACPI_FAILURE(status);
428 	if (sc->pl_crs_bad) {
429 		creq.in_dpf = DPF_OUTSIDE;
430 		creq.count = 0;
431 		status = AcpiWalkResources(acpi_get_handle(dev), "_PRS",
432 		    acpi_count_irq_resources, &creq);
433 		if (ACPI_FAILURE(status)) {
434 			device_printf(dev,
435 			    "Unable to parse _CRS or _PRS: %s\n",
436 			    AcpiFormatException(status));
437 			ACPI_SERIAL_END(pci_link);
438 			return (ENXIO);
439 		}
440 	}
441 	sc->pl_num_links = creq.count;
442 	if (creq.count == 0)
443 		return (0);
444 	sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links,
445 	    M_PCI_LINK, M_WAITOK | M_ZERO);
446 
447 	/* Initialize the child links. */
448 	for (i = 0; i < sc->pl_num_links; i++) {
449 		sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
450 		sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ;
451 		sc->pl_links[i].l_sc = sc;
452 		sc->pl_links[i].l_isa_irq = FALSE;
453 		sc->pl_links[i].l_res_index = -1;
454 	}
455 
456 	/* Try to read the current settings from _CRS if it is valid. */
457 	if (!sc->pl_crs_bad) {
458 		rreq.in_dpf = DPF_OUTSIDE;
459 		rreq.link_index = 0;
460 		rreq.res_index = 0;
461 		rreq.sc = sc;
462 		status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
463 		    link_add_crs, &rreq);
464 		if (ACPI_FAILURE(status)) {
465 			device_printf(dev, "Unable to parse _CRS: %s\n",
466 			    AcpiFormatException(status));
467 			goto fail;
468 		}
469 	}
470 
471 	/*
472 	 * Try to read the possible settings from _PRS.  Note that if the
473 	 * _CRS is toast, we depend on having a working _PRS.  However, if
474 	 * _CRS works, then it is ok for _PRS to be missing.
475 	 */
476 	rreq.in_dpf = DPF_OUTSIDE;
477 	rreq.link_index = 0;
478 	rreq.res_index = 0;
479 	rreq.sc = sc;
480 	status = AcpiWalkResources(acpi_get_handle(dev), "_PRS",
481 	    link_add_prs, &rreq);
482 	if (ACPI_FAILURE(status) &&
483 	    (status != AE_NOT_FOUND || sc->pl_crs_bad)) {
484 		device_printf(dev, "Unable to parse _PRS: %s\n",
485 		    AcpiFormatException(status));
486 		goto fail;
487 	}
488 	if (bootverbose) {
489 		device_printf(dev, "Links after initial probe:\n");
490 		acpi_pci_link_dump(sc);
491 	}
492 
493 	/* Verify initial IRQs if we have _PRS. */
494 	if (status != AE_NOT_FOUND)
495 		for (i = 0; i < sc->pl_num_links; i++)
496 			if (!link_valid_irq(&sc->pl_links[i],
497 			    sc->pl_links[i].l_irq))
498 				sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
499 	if (bootverbose) {
500 		device_printf(dev, "Links after initial validation:\n");
501 		acpi_pci_link_dump(sc);
502 	}
503 
504 	/* Save initial IRQs. */
505 	for (i = 0; i < sc->pl_num_links; i++)
506 		sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq;
507 
508 	/*
509 	 * Try to disable this link.  If successful, set the current IRQ to
510 	 * zero and flags to indicate this link is not routed.  If we can't
511 	 * run _DIS (i.e., the method doesn't exist), assume the initial
512 	 * IRQ was routed by the BIOS.
513 	 */
514 	if (ACPI_SUCCESS(AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL,
515 	    NULL)))
516 		for (i = 0; i < sc->pl_num_links; i++)
517 			sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
518 	else
519 		for (i = 0; i < sc->pl_num_links; i++)
520 			if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq))
521 				sc->pl_links[i].l_routed = TRUE;
522 	if (bootverbose) {
523 		device_printf(dev, "Links after disable:\n");
524 		acpi_pci_link_dump(sc);
525 	}
526 	ACPI_SERIAL_END(pci_link);
527 	return (0);
528 fail:
529 	ACPI_SERIAL_END(pci_link);
530 	for (i = 0; i < sc->pl_num_links; i++)
531 		if (sc->pl_links[i].l_irqs != NULL)
532 			free(sc->pl_links[i].l_irqs, M_PCI_LINK);
533 	free(sc->pl_links, M_PCI_LINK);
534 	return (ENXIO);
535 }
536 
537 /* XXX: Note that this is identical to pci_pir_search_irq(). */
538 static uint8_t
539 acpi_pci_link_search_irq(int bus, int device, int pin)
540 {
541 	uint32_t value;
542 	uint8_t func, maxfunc;
543 
544 	/* See if we have a valid device at function 0. */
545 	value = pci_cfgregread(bus, device, 0, PCIR_HDRTYPE, 1);
546 	if ((value & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
547 		return (PCI_INVALID_IRQ);
548 	if (value & PCIM_MFDEV)
549 		maxfunc = PCI_FUNCMAX;
550 	else
551 		maxfunc = 0;
552 
553 	/* Scan all possible functions at this device. */
554 	for (func = 0; func <= maxfunc; func++) {
555 		value = pci_cfgregread(bus, device, func, PCIR_DEVVENDOR, 4);
556 		if (value == 0xffffffff)
557 			continue;
558 		value = pci_cfgregread(bus, device, func, PCIR_INTPIN, 1);
559 
560 		/*
561 		 * See if it uses the pin in question.  Note that the passed
562 		 * in pin uses 0 for A, .. 3 for D whereas the intpin
563 		 * register uses 0 for no interrupt, 1 for A, .. 4 for D.
564 		 */
565 		if (value != pin + 1)
566 			continue;
567 		value = pci_cfgregread(bus, device, func, PCIR_INTLINE, 1);
568 		if (bootverbose)
569 			printf(
570 		"ACPI: Found matching pin for %d.%d.INT%c at func %d: %d\n",
571 			    bus, device, pin + 'A', func, value);
572 		if (value != PCI_INVALID_IRQ)
573 			return (value);
574 	}
575 	return (PCI_INVALID_IRQ);
576 }
577 
578 /*
579  * Find the link structure that corresponds to the resource index passed in
580  * via 'source_index'.
581  */
582 static struct link *
583 acpi_pci_link_lookup(device_t dev, int source_index)
584 {
585 	struct acpi_pci_link_softc *sc;
586 	int i;
587 
588 	ACPI_SERIAL_ASSERT(pci_link);
589 	sc = device_get_softc(dev);
590 	for (i = 0; i < sc->pl_num_links; i++)
591 		if (sc->pl_links[i].l_res_index == source_index)
592 			return (&sc->pl_links[i]);
593 	return (NULL);
594 }
595 
596 void
597 acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot,
598     int pin)
599 {
600 	struct link *link;
601 	uint8_t bios_irq;
602 
603 	/* Bump the reference count. */
604 	ACPI_SERIAL_BEGIN(pci_link);
605 	link = acpi_pci_link_lookup(dev, index);
606 	if (link == NULL)
607 		panic("%s: apparently invalid index %d", __func__, index);
608 	link->l_references++;
609 	if (link->l_routed)
610 		pci_link_interrupt_weights[link->l_irq]++;
611 
612 	/* Try to find a BIOS IRQ setting from any matching devices. */
613 	bios_irq = acpi_pci_link_search_irq(pcib_get_bus(pcib), slot, pin);
614 	if (!PCI_INTERRUPT_VALID(bios_irq)) {
615 		ACPI_SERIAL_END(pci_link);
616 		return;
617 	}
618 
619 	/* Validate the BIOS IRQ. */
620 	if (!link_valid_irq(link, bios_irq)) {
621 		device_printf(dev, "BIOS IRQ %u for %d.%d.INT%c is invalid\n",
622 		    bios_irq, pcib_get_bus(pcib), slot, pin + 'A');
623 	} else if (!PCI_INTERRUPT_VALID(link->l_bios_irq)) {
624 		link->l_bios_irq = bios_irq;
625 		if (bios_irq < NUM_ISA_INTERRUPTS)
626 			pci_link_bios_isa_irqs |= (1 << bios_irq);
627 		if (bios_irq != link->l_initial_irq &&
628 		    PCI_INTERRUPT_VALID(link->l_initial_irq))
629 			device_printf(dev,
630 			    "BIOS IRQ %u does not match initial IRQ %u\n",
631 			    bios_irq, link->l_initial_irq);
632 	} else if (bios_irq != link->l_bios_irq)
633 		device_printf(dev,
634 	    "BIOS IRQ %u for %d.%d.INT%c does not match previous BIOS IRQ %u\n",
635 		    bios_irq, pcib_get_bus(pcib), slot, pin + 'A',
636 		    link->l_bios_irq);
637 	ACPI_SERIAL_END(pci_link);
638 }
639 
640 static ACPI_STATUS
641 acpi_pci_link_srs_from_crs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf)
642 {
643 	ACPI_RESOURCE *resource, *end, newres, *resptr;
644 	ACPI_BUFFER crsbuf;
645 	ACPI_STATUS status;
646 	struct link *link;
647 	int i, in_dpf;
648 
649 	/* Fetch the _CRS. */
650 	ACPI_SERIAL_ASSERT(pci_link);
651 	crsbuf.Pointer = NULL;
652 	crsbuf.Length = ACPI_ALLOCATE_BUFFER;
653 	status = AcpiGetCurrentResources(acpi_get_handle(sc->pl_dev), &crsbuf);
654 	if (ACPI_SUCCESS(status) && crsbuf.Pointer == NULL)
655 		status = AE_NO_MEMORY;
656 	if (ACPI_FAILURE(status)) {
657 		if (bootverbose)
658 			device_printf(sc->pl_dev,
659 			    "Unable to fetch current resources: %s\n",
660 			    AcpiFormatException(status));
661 		return (status);
662 	}
663 
664 	/* Fill in IRQ resources via link structures. */
665 	srsbuf->Pointer = NULL;
666 	link = sc->pl_links;
667 	i = 0;
668 	in_dpf = DPF_OUTSIDE;
669 	resource = (ACPI_RESOURCE *)crsbuf.Pointer;
670 	end = (ACPI_RESOURCE *)((char *)crsbuf.Pointer + crsbuf.Length);
671 	for (;;) {
672 		switch (resource->Id) {
673 		case ACPI_RSTYPE_START_DPF:
674 			switch (in_dpf) {
675 			case DPF_OUTSIDE:
676 				/* We've started the first DPF. */
677 				in_dpf = DPF_FIRST;
678 				break;
679 			case DPF_FIRST:
680 				/* We've started the second DPF. */
681 				panic(
682 		"%s: Multiple dependent functions within a current resource",
683 				    __func__);
684 				break;
685 			}
686 			resptr = NULL;
687 			break;
688 		case ACPI_RSTYPE_END_DPF:
689 			/* We are finished with DPF parsing. */
690 			KASSERT(in_dpf != DPF_OUTSIDE,
691 			    ("%s: end dpf when not parsing a dpf", __func__));
692 			in_dpf = DPF_OUTSIDE;
693 			resptr = NULL;
694 			break;
695 		case ACPI_RSTYPE_IRQ:
696 			MPASS(i < sc->pl_num_links);
697 			MPASS(link->l_prs_template.Id == ACPI_RSTYPE_IRQ);
698 			newres = link->l_prs_template;
699 			resptr = &newres;
700 			resptr->Data.Irq.NumberOfInterrupts = 1;
701 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
702 				KASSERT(link->l_irq < NUM_ISA_INTERRUPTS,
703 		("%s: can't put non-ISA IRQ %d in legacy IRQ resource type",
704 				    __func__, link->l_irq));
705 				resptr->Data.Irq.Interrupts[0] = link->l_irq;
706 			} else
707 				resptr->Data.Irq.Interrupts[0] = 0;
708 			link++;
709 			i++;
710 			break;
711 		case ACPI_RSTYPE_EXT_IRQ:
712 			MPASS(i < sc->pl_num_links);
713 			MPASS(link->l_prs_template.Id == ACPI_RSTYPE_EXT_IRQ);
714 			newres = link->l_prs_template;
715 			resptr = &newres;
716 			resptr->Data.ExtendedIrq.NumberOfInterrupts = 1;
717 			if (PCI_INTERRUPT_VALID(link->l_irq))
718 				resptr->Data.ExtendedIrq.Interrupts[0] =
719 				    link->l_irq;
720 			else
721 				resptr->Data.ExtendedIrq.Interrupts[0] = 0;
722 			link++;
723 			i++;
724 			break;
725 		default:
726 			resptr = resource;
727 		}
728 		if (resptr != NULL) {
729 			status = acpi_AppendBufferResource(srsbuf, resptr);
730 			if (ACPI_FAILURE(status)) {
731 				device_printf(sc->pl_dev,
732 				    "Unable to build resources: %s\n",
733 				    AcpiFormatException(status));
734 				if (srsbuf->Pointer != NULL)
735 					AcpiOsFree(srsbuf->Pointer);
736 				AcpiOsFree(crsbuf.Pointer);
737 				return (status);
738 			}
739 		}
740 		if (resource->Id == ACPI_RSTYPE_END_TAG)
741 			break;
742 		resource = ACPI_NEXT_RESOURCE(resource);
743 		if (resource >= end)
744 			break;
745 	}
746 	AcpiOsFree(crsbuf.Pointer);
747 	return (AE_OK);
748 }
749 
750 static ACPI_STATUS
751 acpi_pci_link_srs_from_links(struct acpi_pci_link_softc *sc,
752     ACPI_BUFFER *srsbuf)
753 {
754 	ACPI_RESOURCE newres;
755 	ACPI_STATUS status;
756 	struct link *link;
757 	int i;
758 
759 	/* Start off with an empty buffer. */
760 	srsbuf->Pointer = NULL;
761 	link = sc->pl_links;
762 	for (i = 0; i < sc->pl_num_links; i++) {
763 
764 		/* Add a new IRQ resource from each link. */
765 		link = &sc->pl_links[i];
766 		newres = link->l_prs_template;
767 		if (newres.Id == ACPI_RSTYPE_IRQ) {
768 
769 			/* Build an IRQ resource. */
770 			newres.Data.Irq.NumberOfInterrupts = 1;
771 			if (PCI_INTERRUPT_VALID(link->l_irq)) {
772 				KASSERT(link->l_irq < NUM_ISA_INTERRUPTS,
773 		("%s: can't put non-ISA IRQ %d in legacy IRQ resource type",
774 				    __func__, link->l_irq));
775 				newres.Data.Irq.Interrupts[0] = link->l_irq;
776 			} else
777 				newres.Data.Irq.Interrupts[0] = 0;
778 		} else {
779 
780 			/* Build an ExtIRQ resuorce. */
781 			newres.Data.ExtendedIrq.NumberOfInterrupts = 1;
782 			if (PCI_INTERRUPT_VALID(link->l_irq))
783 				newres.Data.ExtendedIrq.Interrupts[0] =
784 				    link->l_irq;
785 			else
786 				newres.Data.ExtendedIrq.Interrupts[0] = 0;
787 		}
788 
789 		/* Add the new resource to the end of the _SRS buffer. */
790 		status = acpi_AppendBufferResource(srsbuf, &newres);
791 		if (ACPI_FAILURE(status)) {
792 			device_printf(sc->pl_dev,
793 			    "Unable to build resources: %s\n",
794 			    AcpiFormatException(status));
795 			if (srsbuf->Pointer != NULL)
796 				AcpiOsFree(srsbuf->Pointer);
797 			return (status);
798 		}
799 	}
800 	return (AE_OK);
801 }
802 
803 static ACPI_STATUS
804 acpi_pci_link_route_irqs(device_t dev)
805 {
806 	struct acpi_pci_link_softc *sc;
807 	ACPI_RESOURCE *resource, *end;
808 	ACPI_BUFFER srsbuf;
809 	ACPI_STATUS status;
810 	struct link *link;
811 	int i;
812 
813 	ACPI_SERIAL_ASSERT(pci_link);
814 	sc = device_get_softc(dev);
815 	if (sc->pl_crs_bad)
816 		status = acpi_pci_link_srs_from_links(sc, &srsbuf);
817 	else
818 		status = acpi_pci_link_srs_from_crs(sc, &srsbuf);
819 
820 	/* Write out new resources via _SRS. */
821 	status = AcpiSetCurrentResources(acpi_get_handle(dev), &srsbuf);
822 	if (ACPI_FAILURE(status)) {
823 		device_printf(dev, "Unable to route IRQs: %s\n",
824 		    AcpiFormatException(status));
825 		AcpiOsFree(srsbuf.Pointer);
826 		return (status);
827 	}
828 
829 	/*
830 	 * Perform acpi_config_intr() on each IRQ resource if it was just
831 	 * routed for the first time.
832 	 */
833 	link = sc->pl_links;
834 	i = 0;
835 	resource = (ACPI_RESOURCE *)srsbuf.Pointer;
836 	end = (ACPI_RESOURCE *)((char *)srsbuf.Pointer + srsbuf.Length);
837 	for (;;) {
838 		if (resource->Id == ACPI_RSTYPE_END_TAG)
839 			break;
840 		switch (resource->Id) {
841 		case ACPI_RSTYPE_IRQ:
842 		case ACPI_RSTYPE_EXT_IRQ:
843 			MPASS(i < sc->pl_num_links);
844 
845 			/*
846 			 * Only configure the interrupt and update the
847 			 * weights if this link has a valid IRQ and was
848 			 * previously unrouted.
849 			 */
850 			if (!link->l_routed &&
851 			    PCI_INTERRUPT_VALID(link->l_irq)) {
852 				link->l_routed = TRUE;
853 				acpi_config_intr(dev, resource);
854 				pci_link_interrupt_weights[link->l_irq] +=
855 				    link->l_references;
856 			}
857 			link++;
858 			i++;
859 			break;
860 		}
861 		resource = ACPI_NEXT_RESOURCE(resource);
862 		if (resource >= end)
863 			break;
864 	}
865 	AcpiOsFree(srsbuf.Pointer);
866 	return (AE_OK);
867 }
868 
869 static int
870 acpi_pci_link_resume(device_t dev)
871 {
872 	ACPI_STATUS status;
873 
874 	ACPI_SERIAL_BEGIN(pci_link);
875 	status = acpi_pci_link_route_irqs(dev);
876 	ACPI_SERIAL_END(pci_link);
877 	if (ACPI_FAILURE(status))
878 		return (ENXIO);
879 	else
880 		return (0);
881 }
882 
883 /*
884  * Pick an IRQ to use for this unrouted link.
885  */
886 static uint8_t
887 acpi_pci_link_choose_irq(device_t dev, struct link *link)
888 {
889 	char tunable_buffer[64], link_name[5];
890 	u_int8_t best_irq, pos_irq;
891 	int best_weight, pos_weight, i;
892 
893 	KASSERT(!link->l_routed, ("%s: link already routed", __func__));
894 	KASSERT(!PCI_INTERRUPT_VALID(link->l_irq),
895 	    ("%s: link already has an IRQ", __func__));
896 
897 	/* Check for a tunable override and use it if it is valid. */
898 	if (ACPI_SUCCESS(acpi_short_name(acpi_get_handle(dev), link_name,
899 	    sizeof(link_name)))) {
900 		snprintf(tunable_buffer, sizeof(tunable_buffer),
901 		    "hw.pci.link.%s.%d.irq", link_name, link->l_res_index);
902 		if (getenv_int(tunable_buffer, &i) &&
903 		    PCI_INTERRUPT_VALID(i) && link_valid_irq(link, i))
904 			return (i);
905 		snprintf(tunable_buffer, sizeof(tunable_buffer),
906 		    "hw.pci.link.%s.irq", link_name);
907 		if (getenv_int(tunable_buffer, &i) &&
908 		    PCI_INTERRUPT_VALID(i) && link_valid_irq(link, i))
909 			return (i);
910 	}
911 
912 	/*
913 	 * If we have a valid BIOS IRQ, use that.  We trust what the BIOS
914 	 * says it routed over what _CRS says the link thinks is routed.
915 	 */
916 	if (PCI_INTERRUPT_VALID(link->l_bios_irq))
917 		return (link->l_bios_irq);
918 
919 	/*
920 	 * If we don't have a BIOS IRQ but do have a valid IRQ from _CRS,
921 	 * then use that.
922 	 */
923 	if (PCI_INTERRUPT_VALID(link->l_initial_irq))
924 		return (link->l_initial_irq);
925 
926 	/*
927 	 * Ok, we have no useful hints, so we have to pick from the
928 	 * possible IRQs.  For ISA IRQs we only use interrupts that
929 	 * have already been used by the BIOS.
930 	 */
931 	best_irq = PCI_INVALID_IRQ;
932 	best_weight = INT_MAX;
933 	for (i = 0; i < link->l_num_irqs; i++) {
934 		pos_irq = link->l_irqs[i];
935 		if (pos_irq < NUM_ISA_INTERRUPTS &&
936 		    (pci_link_bios_isa_irqs & 1 << pos_irq) == 0)
937 			continue;
938 		pos_weight = pci_link_interrupt_weights[pos_irq];
939 		if (pos_weight < best_weight) {
940 			best_weight = pos_weight;
941 			best_irq = pos_irq;
942 		}
943 	}
944 
945 	/*
946 	 * If this is an ISA IRQ, try using the SCI if it is also an ISA
947 	 * interrupt as a fallback.
948 	 */
949 	if (link->l_isa_irq) {
950 		pos_irq = AcpiGbl_FADT->SciInt;
951 		pos_weight = pci_link_interrupt_weights[pos_irq];
952 		if (pos_weight < best_weight) {
953 			best_weight = pos_weight;
954 			best_irq = pos_irq;
955 		}
956 	}
957 
958 	if (bootverbose) {
959 		if (PCI_INTERRUPT_VALID(best_irq))
960 			device_printf(dev, "Picked IRQ %u with weight %d\n",
961 			    best_irq, best_weight);
962 	} else
963 		device_printf(dev, "Unable to choose an IRQ\n");
964 	return (best_irq);
965 }
966 
967 int
968 acpi_pci_link_route_interrupt(device_t dev, int index)
969 {
970 	struct link *link;
971 
972 	ACPI_SERIAL_BEGIN(pci_link);
973 	link = acpi_pci_link_lookup(dev, index);
974 	if (link == NULL)
975 		panic("%s: apparently invalid index %d", __func__, index);
976 
977 	/*
978 	 * If this link device is already routed to an interrupt, just return
979 	 * the interrupt it is routed to.
980 	 */
981 	if (link->l_routed) {
982 		KASSERT(PCI_INTERRUPT_VALID(link->l_irq),
983 		    ("%s: link is routed but has an invalid IRQ", __func__));
984 		ACPI_SERIAL_END(pci_link);
985 		return (link->l_irq);
986 	}
987 
988 	/* Choose an IRQ if we need one. */
989 	if (!PCI_INTERRUPT_VALID(link->l_irq)) {
990 		link->l_irq = acpi_pci_link_choose_irq(dev, link);
991 
992 		/*
993 		 * Try to route the interrupt we picked.  If it fails, then
994 		 * assume the interrupt is not routed.
995 		 */
996 		if (PCI_INTERRUPT_VALID(link->l_irq)) {
997 			acpi_pci_link_route_irqs(dev);
998 			if (!link->l_routed)
999 				link->l_irq = PCI_INVALID_IRQ;
1000 		}
1001 	}
1002 	ACPI_SERIAL_END(pci_link);
1003 
1004 	return (link->l_irq);
1005 }
1006 
1007 /*
1008  * This is gross, but we abuse the identify routine to perform one-time
1009  * SYSINIT() style initialization for the driver.
1010  */
1011 static void
1012 acpi_pci_link_identify(driver_t *driver, device_t parent)
1013 {
1014 
1015 	/*
1016 	 * If the SCI is an ISA IRQ, add it to the bitmask of known good
1017 	 * ISA IRQs.
1018 	 *
1019 	 * XXX: If we are using the APIC, the SCI might have been
1020 	 * rerouted to an APIC pin in which case this is invalid.  However,
1021 	 * if we are using the APIC, we also shouldn't be having any PCI
1022 	 * interrupts routed via ISA IRQs, so this is probably ok.
1023 	 */
1024 	if (AcpiGbl_FADT->SciInt < NUM_ISA_INTERRUPTS)
1025 		pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT->SciInt);
1026 }
1027 
1028 static device_method_t acpi_pci_link_methods[] = {
1029 	/* Device interface */
1030 	DEVMETHOD(device_identify,	acpi_pci_link_identify),
1031 	DEVMETHOD(device_probe,		acpi_pci_link_probe),
1032 	DEVMETHOD(device_attach,	acpi_pci_link_attach),
1033 	DEVMETHOD(device_resume,	acpi_pci_link_resume),
1034 
1035 	{0, 0}
1036 };
1037 
1038 static driver_t acpi_pci_link_driver = {
1039 	"pci_link",
1040 	acpi_pci_link_methods,
1041 	sizeof(struct acpi_pci_link_softc),
1042 };
1043 
1044 static devclass_t pci_link_devclass;
1045 
1046 DRIVER_MODULE(acpi_pci_link, acpi, acpi_pci_link_driver, pci_link_devclass, 0,
1047     0);
1048 MODULE_DEPEND(acpi_pci_link, acpi, 1, 1, 1);
1049