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