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