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