acpipci.c revision 1.6
1/*	$OpenBSD: acpipci.c,v 1.6 2018/08/11 22:47:27 kettenis Exp $	*/
2/*
3 * Copyright (c) 2018 Mark Kettenis
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/param.h>
19#include <sys/device.h>
20#include <sys/extent.h>
21#include <sys/malloc.h>
22#include <sys/systm.h>
23
24#include <machine/bus.h>
25
26#include <dev/acpi/acpireg.h>
27#include <dev/acpi/acpivar.h>
28#include <dev/acpi/acpidev.h>
29#include <dev/acpi/amltypes.h>
30#include <dev/acpi/dsdt.h>
31
32#include <dev/pci/pcidevs.h>
33#include <dev/pci/pcireg.h>
34#include <dev/pci/pcivar.h>
35#include <dev/pci/ppbreg.h>
36
37bus_addr_t pci_mcfg_addr;
38int pci_mcfg_min_bus, pci_mcfg_max_bus;
39bus_space_tag_t pci_mcfgt;
40bus_space_handle_t pci_mcfgh;
41
42struct acpipci_trans {
43	struct acpipci_trans *at_next;
44	bus_space_tag_t	at_iot;
45	bus_addr_t	at_base;
46	bus_size_t	at_size;
47	bus_size_t	at_offset;
48};
49
50struct acpipci_softc {
51	struct device	sc_dev;
52	struct acpi_softc *sc_acpi;
53	struct aml_node *sc_node;
54
55	bus_space_tag_t	sc_iot;
56	bus_space_handle_t sc_ioh;
57
58	struct bus_space sc_bus_iot;
59	struct bus_space sc_bus_memt;
60	struct acpipci_trans *sc_io_trans;
61	struct acpipci_trans *sc_mem_trans;
62
63	struct arm64_pci_chipset sc_pc;
64	struct extent	*sc_busex;
65	struct extent	*sc_memex;
66	struct extent	*sc_ioex;
67	char		sc_busex_name[32];
68	char		sc_ioex_name[32];
69	char		sc_memex_name[32];
70	int		sc_bus;
71	uint32_t	sc_seg;
72};
73
74int	acpipci_match(struct device *, void *, void *);
75void	acpipci_attach(struct device *, struct device *, void *);
76
77struct cfattach acpipci_ca = {
78	sizeof(struct acpipci_softc), acpipci_match, acpipci_attach
79};
80
81struct cfdriver acpipci_cd = {
82	NULL, "acpipci", DV_DULL
83};
84
85const char *acpipci_hids[] = {
86	"PNP0A08",
87	NULL
88};
89
90int	acpipci_parse_resources(int, union acpi_resource *, void *);
91int	acpipci_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
92	    bus_space_handle_t *);
93
94void	acpipci_attach_hook(struct device *, struct device *,
95	    struct pcibus_attach_args *);
96int	acpipci_bus_maxdevs(void *, int);
97pcitag_t acpipci_make_tag(void *, int, int, int);
98void	acpipci_decompose_tag(void *, pcitag_t, int *, int *, int *);
99int	acpipci_conf_size(void *, pcitag_t);
100pcireg_t acpipci_conf_read(void *, pcitag_t, int);
101void	acpipci_conf_write(void *, pcitag_t, int, pcireg_t);
102
103int	acpipci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
104int	acpipci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *);
105int	acpipci_intr_map_msix(struct pci_attach_args *, int,
106	    pci_intr_handle_t *);
107const char *acpipci_intr_string(void *, pci_intr_handle_t);
108void	*acpipci_intr_establish(void *, pci_intr_handle_t, int,
109	    int (*)(void *), void *, char *);
110void	acpipci_intr_disestablish(void *, void *);
111
112uint32_t acpipci_iort_map_msi(pci_chipset_tag_t, pcitag_t);
113
114int
115acpipci_match(struct device *parent, void *match, void *aux)
116{
117	struct acpi_attach_args *aaa = aux;
118	struct cfdata *cf = match;
119
120	return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name);
121}
122
123void
124acpipci_attach(struct device *parent, struct device *self, void *aux)
125{
126	struct acpi_attach_args *aaa = aux;
127	struct acpipci_softc *sc = (struct acpipci_softc *)self;
128	struct pcibus_attach_args pba;
129	struct aml_value res;
130	uint64_t bbn = 0;
131	uint64_t seg = 0;
132
133	/* Bail out early if we don't have a valid MCFG table. */
134	if (pci_mcfg_addr == 0 || pci_mcfg_max_bus <= pci_mcfg_min_bus) {
135		printf(": no registers\n");
136		return;
137	}
138
139	sc->sc_acpi = (struct acpi_softc *)parent;
140	sc->sc_node = aaa->aaa_node;
141	printf(" %s", sc->sc_node->name);
142
143	if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
144		printf(": can't find resources\n");
145		return;
146	}
147
148	aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn);
149	sc->sc_bus = bbn;
150
151	aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg);
152	sc->sc_seg = seg;
153
154	sc->sc_iot = pci_mcfgt;
155	sc->sc_ioh = pci_mcfgh;
156
157	printf("\n");
158
159	/* XXX We only support segment 0 for now. */
160	if (seg != 0)
161		return;
162
163	/* Create extents for our address spaces. */
164	snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name),
165	    "%s pcibus", sc->sc_dev.dv_xname);
166	snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
167	    "%s pciio", sc->sc_dev.dv_xname);
168	snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
169	    "%s pcimem", sc->sc_dev.dv_xname);
170	sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255,
171	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
172	sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff,
173	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
174	sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1,
175	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
176
177	aml_parse_resource(&res, acpipci_parse_resources, sc);
178
179	memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot));
180	sc->sc_bus_iot.bus_private = sc->sc_io_trans;
181	sc->sc_bus_iot._space_map = acpipci_bs_map;
182	memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt));
183	sc->sc_bus_memt.bus_private = sc->sc_mem_trans;
184	sc->sc_bus_memt._space_map = acpipci_bs_map;
185
186	sc->sc_pc.pc_conf_v = sc;
187	sc->sc_pc.pc_attach_hook = acpipci_attach_hook;
188	sc->sc_pc.pc_bus_maxdevs = acpipci_bus_maxdevs;
189	sc->sc_pc.pc_make_tag = acpipci_make_tag;
190	sc->sc_pc.pc_decompose_tag = acpipci_decompose_tag;
191	sc->sc_pc.pc_conf_size = acpipci_conf_size;
192	sc->sc_pc.pc_conf_read = acpipci_conf_read;
193	sc->sc_pc.pc_conf_write = acpipci_conf_write;
194
195	sc->sc_pc.pc_intr_v = sc;
196	sc->sc_pc.pc_intr_map = acpipci_intr_map;
197	sc->sc_pc.pc_intr_map_msi = acpipci_intr_map_msi;
198	sc->sc_pc.pc_intr_map_msix = acpipci_intr_map_msix;
199	sc->sc_pc.pc_intr_string = acpipci_intr_string;
200	sc->sc_pc.pc_intr_establish = acpipci_intr_establish;
201	sc->sc_pc.pc_intr_disestablish = acpipci_intr_disestablish;
202
203	memset(&pba, 0, sizeof(pba));
204	pba.pba_busname = "pci";
205	pba.pba_iot = &sc->sc_bus_iot;
206	pba.pba_memt = &sc->sc_bus_memt;
207	pba.pba_dmat = aaa->aaa_dmat;
208	pba.pba_pc = &sc->sc_pc;
209	pba.pba_busex = sc->sc_busex;
210	pba.pba_ioex = sc->sc_ioex;
211	pba.pba_memex = sc->sc_memex;
212	pba.pba_domain = pci_ndomains++;
213	pba.pba_bus = sc->sc_bus;
214	pba.pba_flags |= PCI_FLAGS_MSI_ENABLED;
215
216	config_found(self, &pba, NULL);
217}
218
219int
220acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
221{
222	struct acpipci_softc *sc = arg;
223	struct acpipci_trans *at;
224	int type = AML_CRSTYPE(crs);
225	int restype, tflags;
226	u_long min, len = 0, tra;
227
228	switch (type) {
229	case LR_WORD:
230		restype = crs->lr_word.type;
231		tflags = crs->lr_word.tflags;
232		min = crs->lr_word._min;
233		len = crs->lr_word._len;
234		tra = crs->lr_word._tra;
235		break;
236	case LR_DWORD:
237		restype = crs->lr_dword.type;
238		tflags = crs->lr_dword.tflags;
239		min = crs->lr_dword._min;
240		len = crs->lr_dword._len;
241		tra = crs->lr_dword._tra;
242		break;
243	case LR_QWORD:
244		restype = crs->lr_qword.type;
245		tflags = crs->lr_qword.tflags;
246		min = crs->lr_qword._min;
247		len = crs->lr_qword._len;
248		tra = crs->lr_qword._tra;
249		break;
250	}
251
252	if (len == 0)
253		return 0;
254
255	switch (restype) {
256	case LR_TYPE_MEMORY:
257		if (tflags & LR_MEMORY_TTP)
258			return 0;
259		extent_free(sc->sc_memex, min, len, EX_WAITOK);
260		at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK);
261		at->at_iot = sc->sc_iot;
262		at->at_base = min;
263		at->at_size = len;
264		at->at_offset = tra;
265		at->at_next = sc->sc_mem_trans;
266		sc->sc_mem_trans = at;
267		break;
268	case LR_TYPE_IO:
269		if ((tflags & LR_IO_TTP) == 0)
270			return 0;
271		extent_free(sc->sc_ioex, min, len, EX_WAITOK);
272		at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK);
273		at->at_iot = sc->sc_iot;
274		at->at_base = min;
275		at->at_size = len;
276		at->at_offset = tra;
277		at->at_next = sc->sc_io_trans;
278		sc->sc_io_trans = at;
279		break;
280	case LR_TYPE_BUS:
281		extent_free(sc->sc_busex, min, len, EX_WAITOK);
282		break;
283	}
284
285	return 0;
286}
287
288void
289acpipci_attach_hook(struct device *parent, struct device *self,
290    struct pcibus_attach_args *pba)
291{
292}
293
294int
295acpipci_bus_maxdevs(void *v, int bus)
296{
297	return 32;
298}
299
300pcitag_t
301acpipci_make_tag(void *v, int bus, int device, int function)
302{
303	return ((bus << 20) | (device << 15) | (function << 12));
304}
305
306void
307acpipci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
308{
309	if (bp != NULL)
310		*bp = (tag >> 20) & 0xff;
311	if (dp != NULL)
312		*dp = (tag >> 15) & 0x1f;
313	if (fp != NULL)
314		*fp = (tag >> 12) & 0x7;
315}
316
317int
318acpipci_conf_size(void *v, pcitag_t tag)
319{
320	return PCIE_CONFIG_SPACE_SIZE;
321}
322
323pcireg_t
324acpipci_conf_read(void *v, pcitag_t tag, int reg)
325{
326	struct acpipci_softc *sc = v;
327
328	return bus_space_read_4(sc->sc_iot, sc->sc_ioh, tag | reg);
329}
330
331void
332acpipci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
333{
334	struct acpipci_softc *sc = v;
335
336	bus_space_write_4(sc->sc_iot, sc->sc_ioh, tag | reg, data);
337}
338
339struct acpipci_intr_handle {
340	pci_chipset_tag_t	ih_pc;
341	pcitag_t		ih_tag;
342	int			ih_intrpin;
343	int			ih_msi;
344};
345
346int
347acpipci_intr_swizzle(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
348{
349	struct acpipci_intr_handle *ih;
350	int dev, swizpin;
351
352	if (pa->pa_bridgetag == NULL)
353		return -1;
354
355	pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL);
356	swizpin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev);
357	if ((void *)pa->pa_bridgeih[swizpin - 1] == NULL)
358		return -1;
359
360	ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK);
361	memcpy(ih, (void *)pa->pa_bridgeih[swizpin - 1],
362	    sizeof(struct acpipci_intr_handle));
363	*ihp = (pci_intr_handle_t)ih;
364
365	return 0;
366}
367
368int
369acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
370{
371	struct acpipci_softc *sc = pa->pa_pc->pc_intr_v;
372	struct aml_node *node = sc->sc_node;
373	struct aml_value res;
374	uint64_t addr, pin, source, index;
375	struct acpipci_intr_handle *ih;
376	int i;
377
378	/*
379	 * If we're behind a bridge, we need to look for a _PRT for
380	 * it.  If we don't find a _PRT, we need to swizzle.  If we're
381	 * not behind a bridge we need to look for a _PRT on the host
382	 * bridge node itself.
383	 */
384	if (pa->pa_bridgetag) {
385		node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag);
386		if (node == NULL)
387			return acpipci_intr_swizzle(pa, ihp);
388	}
389
390	if (aml_evalname(sc->sc_acpi, node, "_PRT", 0, NULL, &res))
391		return acpipci_intr_swizzle(pa, ihp);
392
393	if (res.type != AML_OBJTYPE_PACKAGE)
394		return -1;
395
396	for (i = 0; i < res.length; i++) {
397		struct aml_value *val = res.v_package[i];
398
399		if (val->type != AML_OBJTYPE_PACKAGE)
400			continue;
401		if (val->length != 4)
402			continue;
403		if (val->v_package[0]->type != AML_OBJTYPE_INTEGER ||
404		    val->v_package[1]->type != AML_OBJTYPE_INTEGER ||
405		    val->v_package[2]->type != AML_OBJTYPE_INTEGER ||
406		    val->v_package[3]->type != AML_OBJTYPE_INTEGER)
407			continue;
408
409		addr = val->v_package[0]->v_integer;
410		pin = val->v_package[1]->v_integer;
411		source = val->v_package[2]->v_integer;
412		index = val->v_package[3]->v_integer;
413		if (ACPI_ADR_PCIDEV(addr) != pa->pa_device ||
414		    ACPI_ADR_PCIFUN(addr) != 0xffff ||
415		    pin != pa->pa_intrpin - 1 || source != 0)
416			continue;
417
418		ih = malloc(sizeof(struct acpipci_intr_handle),
419		    M_DEVBUF, M_WAITOK);
420		ih->ih_pc = pa->pa_pc;
421		ih->ih_tag = pa->pa_tag;
422		ih->ih_intrpin = index;
423		ih->ih_msi = 0;
424		*ihp = (pci_intr_handle_t)ih;
425
426		return 0;
427	}
428
429	return -1;
430}
431
432int
433acpipci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
434{
435	pci_chipset_tag_t pc = pa->pa_pc;
436	pcitag_t tag = pa->pa_tag;
437	struct acpipci_intr_handle *ih;
438
439	if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 ||
440	    pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0)
441		return -1;
442
443	ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK);
444	ih->ih_pc = pa->pa_pc;
445	ih->ih_tag = pa->pa_tag;
446	ih->ih_intrpin = pa->pa_intrpin;
447	ih->ih_msi = 1;
448	*ihp = (pci_intr_handle_t)ih;
449
450	return 0;
451}
452
453int
454acpipci_intr_map_msix(struct pci_attach_args *pa, int vec,
455    pci_intr_handle_t *ihp)
456{
457	return -1;
458}
459
460const char *
461acpipci_intr_string(void *v, pci_intr_handle_t ihp)
462{
463	struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp;
464	static char irqstr[32];
465
466	if (ih->ih_msi)
467		return "msi";
468
469	snprintf(irqstr, sizeof(irqstr), "irq %d", ih->ih_intrpin);
470	return irqstr;
471}
472
473void *
474acpipci_intr_establish(void *v, pci_intr_handle_t ihp, int level,
475    int (*func)(void *), void *arg, char *name)
476{
477	struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp;
478	struct interrupt_controller *ic;
479	void *cookie;
480
481	extern LIST_HEAD(, interrupt_controller) interrupt_controllers;
482	LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
483		if (ic->ic_establish_msi)
484			break;
485	}
486	if (ic == NULL)
487		return NULL;
488
489	if (ih->ih_msi) {
490		uint64_t addr, data;
491		pcireg_t reg;
492		int off;
493
494		/* Map Requester ID through IORT to get sideband data. */
495		data = acpipci_iort_map_msi(ih->ih_pc, ih->ih_tag);
496		cookie = ic->ic_establish_msi(ic->ic_cookie, &addr,
497		    &data, level, func, arg, name);
498		if (cookie == NULL)
499			return NULL;
500
501		/* TODO: translate address to the PCI device's view */
502
503		if (pci_get_capability(ih->ih_pc, ih->ih_tag, PCI_CAP_MSI,
504		    &off, &reg) == 0)
505			panic("%s: no msi capability", __func__);
506
507		if (reg & PCI_MSI_MC_C64) {
508			pci_conf_write(ih->ih_pc, ih->ih_tag,
509			    off + PCI_MSI_MA, addr);
510			pci_conf_write(ih->ih_pc, ih->ih_tag,
511			    off + PCI_MSI_MAU32, addr >> 32);
512			pci_conf_write(ih->ih_pc, ih->ih_tag,
513			    off + PCI_MSI_MD64, data);
514		} else {
515			pci_conf_write(ih->ih_pc, ih->ih_tag,
516			    off + PCI_MSI_MA, addr);
517			pci_conf_write(ih->ih_pc, ih->ih_tag,
518			    off + PCI_MSI_MD32, data);
519		}
520		pci_conf_write(ih->ih_pc, ih->ih_tag,
521		    off, reg | PCI_MSI_MC_MSIE);
522	} else {
523		cookie = acpi_intr_establish(ih->ih_intrpin, 0, level,
524		    func, arg, name);
525	}
526
527	free(ih, M_DEVBUF, sizeof(struct acpipci_intr_handle));
528	return cookie;
529}
530
531void
532acpipci_intr_disestablish(void *v, void *cookie)
533{
534	panic("%s", __func__);
535}
536
537/*
538 * Translate memory address if needed.
539 */
540int
541acpipci_bs_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
542    int flags, bus_space_handle_t *bshp)
543{
544	struct acpipci_trans *at;
545
546	for (at = t->bus_private; at; at = at->at_next) {
547		if (addr >= at->at_base && addr < at->at_base + at->at_size) {
548			return bus_space_map(at->at_iot,
549			    addr + at->at_offset, size, flags, bshp);
550		}
551	}
552
553	return ENXIO;
554}
555
556struct arm64_pci_chipset pci_mcfg_chipset;
557
558pcireg_t
559pci_mcfg_conf_read(void *v, pcitag_t tag, int reg)
560{
561	return bus_space_read_4(pci_mcfgt, pci_mcfgh, tag | reg);
562}
563
564void
565pci_mcfg_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
566{
567	bus_space_write_4(pci_mcfgt, pci_mcfgh, tag | reg, data);
568}
569
570pci_chipset_tag_t
571pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus)
572{
573	pci_chipset_tag_t pc = &pci_mcfg_chipset;
574
575	pci_mcfgt = iot;
576	pci_mcfg_addr = addr;
577	pci_mcfg_min_bus = min_bus;
578	pci_mcfg_max_bus = max_bus;
579
580	if (bus_space_map(iot, addr, (pci_mcfg_max_bus + 1) << 20, 0,
581	    &pci_mcfgh))
582		panic("%s: can't map config space", __func__);
583
584	memset(pc, 0, sizeof(*pc));
585	pc->pc_bus_maxdevs = acpipci_bus_maxdevs;
586	pc->pc_make_tag = acpipci_make_tag;
587	pc->pc_decompose_tag = acpipci_decompose_tag;
588	pc->pc_conf_size = acpipci_conf_size;
589	pc->pc_conf_read = pci_mcfg_conf_read;
590	pc->pc_conf_write = pci_mcfg_conf_write;
591
592	return pc;
593}
594
595/*
596 * IORT support.
597 */
598
599struct acpi_iort {
600	struct acpi_table_header	hdr;
601#define IORT_SIG	"IORT"
602	uint32_t	number_of_nodes;
603	uint32_t	offset;
604	uint32_t	reserved;
605} __packed;
606
607struct acpi_iort_node {
608	uint8_t		type;
609#define ACPI_IORT_ITS		0
610#define ACPI_IORT_ROOT_COMPLEX	2
611	uint16_t	length;
612	uint8_t		revision;
613	uint32_t	reserved1;
614	uint32_t	number_of_mappings;
615	uint32_t	mapping_offset;
616	uint64_t	memory_access_properties;
617	uint32_t	atf_attributes;
618	uint32_t	segment;
619	uint8_t		memory_address_size_limit;
620	uint8_t		reserved2[3];
621} __packed;
622
623struct acpi_iort_mapping {
624	uint32_t	input_base;
625	uint32_t	length;
626	uint32_t	output_base;
627	uint32_t	output_reference;
628	uint32_t	flags;
629#define ACPI_IORT_MAPPING_SINGLE	0x00000001
630} __packed;
631
632uint32_t
633acpipci_iort_map_node(struct acpi_iort_node *node, uint32_t id, uint32_t reference)
634{
635	struct acpi_iort_mapping *map =
636	    (struct acpi_iort_mapping *)((char *)node + node->mapping_offset);
637	int i;
638
639	for (i = 0; i < node->number_of_mappings; i++) {
640		if (map[i].output_reference != reference)
641			continue;
642
643		if (map[i].flags & ACPI_IORT_MAPPING_SINGLE)
644			return map[i].output_base;
645
646		if (map[i].input_base <= id &&
647		    id < map[i].input_base + map[i].length)
648			return map[i].output_base + (id - map[i].input_base);
649	}
650
651	return id;
652}
653
654uint32_t
655acpipci_iort_map_msi(pci_chipset_tag_t pc, pcitag_t tag)
656{
657	struct acpipci_softc *sc = pc->pc_intr_v;
658	struct acpi_table_header *hdr;
659	struct acpi_iort *iort = NULL;
660	struct acpi_iort_node *node;
661	struct acpi_q *entry;
662	uint32_t rid, its = 0;
663	uint32_t offset;
664	int i;
665
666	rid = pci_requester_id(pc, tag);
667
668	/* Look for IORT table. */
669	SIMPLEQ_FOREACH(entry, &sc->sc_acpi->sc_tables, q_next) {
670		hdr = entry->q_table;
671		if (strncmp(hdr->signature, IORT_SIG,
672		    sizeof(hdr->signature)) == 0) {
673			iort = entry->q_table;
674			break;
675		}
676	}
677	if (iort == NULL)
678		return rid;
679
680	/* Find reference to ITS group. */
681	offset = iort->offset;
682	for (i = 0; i < iort->number_of_nodes; i++) {
683		node = (struct acpi_iort_node *)((char *)iort + offset);
684		switch (node->type) {
685		case ACPI_IORT_ITS:
686			its = offset;
687			break;
688		}
689		offset += node->length;
690	}
691	if (its == 0)
692		return rid;
693
694	/* Find our root complex and map. */
695	offset = iort->offset;
696	for (i = 0; i < iort->number_of_nodes; i++) {
697		node = (struct acpi_iort_node *)((char *)iort + offset);
698		switch (node->type) {
699		case ACPI_IORT_ROOT_COMPLEX:
700			if (node->segment == sc->sc_seg)
701				return acpipci_iort_map_node(node, rid, its);
702			break;
703		}
704		offset += node->length;
705	}
706
707	return rid;
708}
709