1/*-
2 * Copyright (c) 1999, 2000 Matthew R. Green
3 * Copyright (c) 2009 by Marius Strobl <marius@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	from: NetBSD: ebus.c,v 1.52 2008/05/29 14:51:26 mrg Exp
30 */
31/*-
32 * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org>
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. The name of the author may not be used to endorse or promote products
44 *    derived from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
51 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
53 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 */
58
59#include <sys/cdefs.h>
60__FBSDID("$FreeBSD$");
61
62/*
63 * Driver for JBus to EBus and PCI to EBus bridges
64 */
65
66#include <sys/param.h>
67#include <sys/systm.h>
68#include <sys/bus.h>
69#include <sys/kernel.h>
70#include <sys/malloc.h>
71#include <sys/module.h>
72
73#include <sys/rman.h>
74
75#include <dev/ofw/ofw_bus.h>
76#include <dev/ofw/ofw_bus_subr.h>
77#include <dev/ofw/openfirm.h>
78
79#include <machine/bus.h>
80#ifndef SUN4V
81#include <machine/bus_common.h>
82#endif
83#include <machine/intr_machdep.h>
84#include <machine/resource.h>
85
86#include <dev/pci/pcireg.h>
87#include <dev/pci/pcivar.h>
88
89#include <sparc64/pci/ofw_pci.h>
90
91/*
92 * The register, interrupt map and for the PCI variant also the ranges
93 * properties are identical to the ISA ones.
94 */
95#include <sparc64/isa/ofw_isa.h>
96
97struct ebus_nexus_ranges {
98	uint32_t	child_hi;
99	uint32_t	child_lo;
100	uint32_t	phys_hi;
101	uint32_t	phys_lo;
102	uint32_t	size;
103};
104
105struct ebus_devinfo {
106	struct ofw_bus_devinfo	edi_obdinfo;
107	struct resource_list	edi_rl;
108};
109
110struct ebus_rinfo {
111	int			eri_rtype;
112	struct rman		eri_rman;
113	struct resource		*eri_res;
114};
115
116struct ebus_softc {
117	void			*sc_range;
118	struct ebus_rinfo	*sc_rinfo;
119
120	u_int			sc_flags;
121#define	EBUS_PCI		(1 << 0)
122
123	int			sc_nrange;
124
125	struct ofw_bus_iinfo	sc_iinfo;
126
127#ifndef SUN4V
128	uint32_t		sc_ign;
129#endif
130};
131
132static device_probe_t ebus_nexus_probe;
133static device_attach_t ebus_nexus_attach;
134static device_probe_t ebus_pci_probe;
135static device_attach_t ebus_pci_attach;
136static bus_print_child_t ebus_print_child;
137static bus_probe_nomatch_t ebus_probe_nomatch;
138static bus_alloc_resource_t ebus_alloc_resource;
139static bus_activate_resource_t ebus_activate_resource;
140static bus_adjust_resource_t ebus_adjust_resource;
141static bus_release_resource_t ebus_release_resource;
142static bus_setup_intr_t ebus_setup_intr;
143static bus_get_resource_list_t ebus_get_resource_list;
144static ofw_bus_get_devinfo_t ebus_get_devinfo;
145
146static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node);
147static struct ebus_devinfo *ebus_setup_dinfo(device_t dev,
148    struct ebus_softc *sc, phandle_t node);
149static void ebus_destroy_dinfo(struct ebus_devinfo *edi);
150static int ebus_print_res(struct ebus_devinfo *edi);
151
152static devclass_t ebus_devclass;
153
154static device_method_t ebus_nexus_methods[] = {
155	/* Device interface */
156	DEVMETHOD(device_probe,		ebus_nexus_probe),
157	DEVMETHOD(device_attach,	ebus_nexus_attach),
158	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
159	DEVMETHOD(device_suspend,	bus_generic_suspend),
160	DEVMETHOD(device_resume,	bus_generic_resume),
161
162	/* Bus interface */
163	DEVMETHOD(bus_print_child,	ebus_print_child),
164	DEVMETHOD(bus_probe_nomatch,	ebus_probe_nomatch),
165	DEVMETHOD(bus_alloc_resource,	ebus_alloc_resource),
166	DEVMETHOD(bus_activate_resource, ebus_activate_resource),
167	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
168	DEVMETHOD(bus_adjust_resource,	ebus_adjust_resource),
169	DEVMETHOD(bus_release_resource,	ebus_release_resource),
170	DEVMETHOD(bus_setup_intr,	ebus_setup_intr),
171	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
172	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
173	DEVMETHOD(bus_get_resource_list, ebus_get_resource_list),
174	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
175
176	/* ofw_bus interface */
177	DEVMETHOD(ofw_bus_get_devinfo,	ebus_get_devinfo),
178	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
179	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
180	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
181	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
182	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
183
184	DEVMETHOD_END
185};
186
187static driver_t ebus_nexus_driver = {
188	"ebus",
189	ebus_nexus_methods,
190	sizeof(struct ebus_softc),
191};
192
193/*
194 * NB: we rely on the interrupt controllers of the accompanying PCI-Express
195 * bridge to be registered as the nexus variant of the EBus bridges doesn't
196 * employ its own one.
197 */
198EARLY_DRIVER_MODULE(ebus, nexus, ebus_nexus_driver, ebus_devclass, 0, 0,
199    BUS_PASS_BUS + 1);
200MODULE_DEPEND(ebus, nexus, 1, 1, 1);
201
202static device_method_t ebus_pci_methods[] = {
203	/* Device interface */
204	DEVMETHOD(device_probe,		ebus_pci_probe),
205	DEVMETHOD(device_attach,	ebus_pci_attach),
206	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
207	DEVMETHOD(device_suspend,	bus_generic_suspend),
208	DEVMETHOD(device_resume,	bus_generic_resume),
209
210	/* Bus interface */
211	DEVMETHOD(bus_print_child,	ebus_print_child),
212	DEVMETHOD(bus_probe_nomatch,	ebus_probe_nomatch),
213	DEVMETHOD(bus_alloc_resource,	ebus_alloc_resource),
214	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
215	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
216	DEVMETHOD(bus_release_resource,	ebus_release_resource),
217	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
218	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
219	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
220	DEVMETHOD(bus_get_resource_list, ebus_get_resource_list),
221	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
222
223	/* ofw_bus interface */
224	DEVMETHOD(ofw_bus_get_devinfo,	ebus_get_devinfo),
225	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
226	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
227	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
228	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
229	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
230
231	DEVMETHOD_END
232};
233
234static driver_t ebus_pci_driver = {
235	"ebus",
236	ebus_pci_methods,
237	sizeof(struct ebus_softc),
238};
239
240EARLY_DRIVER_MODULE(ebus, pci, ebus_pci_driver, ebus_devclass, 0, 0,
241    BUS_PASS_BUS);
242MODULE_DEPEND(ebus, pci, 1, 1, 1);
243MODULE_VERSION(ebus, 1);
244
245static int
246ebus_nexus_probe(device_t dev)
247{
248	const char* compat;
249
250	compat = ofw_bus_get_compat(dev);
251	if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ebus") == 0 &&
252	    strcmp(compat, "jbus-ebus") == 0) {
253		device_set_desc(dev, "JBus-EBus bridge");
254		return (BUS_PROBE_GENERIC);
255	}
256	return (ENXIO);
257}
258
259static int
260ebus_pci_probe(device_t dev)
261{
262
263	if (pci_get_class(dev) != PCIC_BRIDGE ||
264	    pci_get_vendor(dev) != 0x108e ||
265	    strcmp(ofw_bus_get_name(dev), "ebus") != 0)
266		return (ENXIO);
267
268	if (pci_get_device(dev) == 0x1000)
269		device_set_desc(dev, "PCI-EBus2 bridge");
270	else if (pci_get_device(dev) == 0x1100)
271		device_set_desc(dev, "PCI-EBus3 bridge");
272	else
273		return (ENXIO);
274	return (BUS_PROBE_GENERIC);
275}
276
277static int
278ebus_nexus_attach(device_t dev)
279{
280	struct ebus_softc *sc;
281	phandle_t node;
282
283	sc = device_get_softc(dev);
284	node = ofw_bus_get_node(dev);
285
286#ifndef SUN4V
287	if (OF_getprop(node, "portid", &sc->sc_ign,
288	    sizeof(sc->sc_ign)) == -1) {
289		device_printf(dev, "could not determine IGN");
290		return (ENXIO);
291	}
292#endif
293
294	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
295	    sizeof(struct ebus_nexus_ranges), &sc->sc_range);
296	if (sc->sc_nrange == -1) {
297		printf("%s: could not get ranges property\n", __func__);
298		return (ENXIO);
299	}
300	return (ebus_attach(dev, sc, node));
301}
302
303static int
304ebus_pci_attach(device_t dev)
305{
306	struct ebus_softc *sc;
307	struct ebus_rinfo *eri;
308	struct resource *res;
309	phandle_t node;
310	int i, rnum, rid;
311
312	sc = device_get_softc(dev);
313	sc->sc_flags |= EBUS_PCI;
314
315	pci_write_config(dev, PCIR_COMMAND,
316	    pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_SERRESPEN |
317	    PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 2);
318	pci_write_config(dev, PCIR_CACHELNSZ, 16 /* 64 bytes */, 1);
319	pci_write_config(dev, PCIR_LATTIMER, 64 /* 64 PCI cycles */, 1);
320
321	node = ofw_bus_get_node(dev);
322	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
323	    sizeof(struct isa_ranges), &sc->sc_range);
324	if (sc->sc_nrange == -1) {
325		printf("%s: could not get ranges property\n", __func__);
326		return (ENXIO);
327	}
328
329	sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF,
330	    M_WAITOK | M_ZERO);
331
332	/* For every range, there must be a matching resource. */
333	for (rnum = 0; rnum < sc->sc_nrange; rnum++) {
334		eri = &sc->sc_rinfo[rnum];
335		eri->eri_rtype = ofw_isa_range_restype(
336		    &((struct isa_ranges *)sc->sc_range)[rnum]);
337		rid = PCIR_BAR(rnum);
338		res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid,
339		    RF_ACTIVE);
340		if (res == NULL) {
341			printf("%s: failed to allocate range resource!\n",
342			    __func__);
343			goto fail;
344		}
345		eri->eri_res = res;
346		eri->eri_rman.rm_type = RMAN_ARRAY;
347		eri->eri_rman.rm_descr = "EBus range";
348		if (rman_init_from_resource(&eri->eri_rman, res) != 0) {
349			printf("%s: failed to initialize rman!", __func__);
350			goto fail;
351		}
352	}
353	return (ebus_attach(dev, sc, node));
354
355 fail:
356	for (i = rnum; i >= 0; i--) {
357		eri = &sc->sc_rinfo[i];
358		if (i < rnum)
359			rman_fini(&eri->eri_rman);
360		if (eri->eri_res != 0) {
361			bus_release_resource(dev, eri->eri_rtype,
362			    PCIR_BAR(rnum), eri->eri_res);
363		}
364	}
365	free(sc->sc_rinfo, M_DEVBUF);
366	free(sc->sc_range, M_OFWPROP);
367	return (ENXIO);
368}
369
370static int
371ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node)
372{
373	struct ebus_devinfo *edi;
374	device_t cdev;
375
376	ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t));
377
378	/*
379	 * Now attach our children.
380	 */
381	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
382		if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL)
383			continue;
384		if ((cdev = device_add_child(dev, NULL, -1)) == NULL) {
385			device_printf(dev, "<%s>: device_add_child failed\n",
386			    edi->edi_obdinfo.obd_name);
387			ebus_destroy_dinfo(edi);
388			continue;
389		}
390		device_set_ivars(cdev, edi);
391	}
392	return (bus_generic_attach(dev));
393}
394
395static int
396ebus_print_child(device_t dev, device_t child)
397{
398	int retval;
399
400	retval = bus_print_child_header(dev, child);
401	retval += ebus_print_res(device_get_ivars(child));
402	retval += bus_print_child_footer(dev, child);
403	return (retval);
404}
405
406static void
407ebus_probe_nomatch(device_t dev, device_t child)
408{
409
410	device_printf(dev, "<%s>", ofw_bus_get_name(child));
411	ebus_print_res(device_get_ivars(child));
412	printf(" (no driver attached)\n");
413}
414
415static struct resource *
416ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
417    u_long start, u_long end, u_long count, u_int flags)
418{
419	struct ebus_softc *sc;
420	struct resource_list *rl;
421	struct resource_list_entry *rle = NULL;
422	struct resource *res;
423	struct ebus_rinfo *eri;
424	struct ebus_nexus_ranges *enr;
425	uint64_t cend, cstart, offset;
426	int i, isdefault, passthrough, ridx;
427
428	isdefault = (start == 0UL && end == ~0UL);
429	passthrough = (device_get_parent(child) != bus);
430	sc = device_get_softc(bus);
431	rl = BUS_GET_RESOURCE_LIST(bus, child);
432	switch (type) {
433	case SYS_RES_MEMORY:
434		KASSERT(!(isdefault && passthrough),
435		    ("%s: passthrough of default allocation", __func__));
436		if (!passthrough) {
437			rle = resource_list_find(rl, type, *rid);
438			if (rle == NULL)
439				return (NULL);
440			KASSERT(rle->res == NULL,
441			    ("%s: resource entry is busy", __func__));
442			if (isdefault) {
443				start = rle->start;
444				count = ulmax(count, rle->count);
445				end = ulmax(rle->end, start + count - 1);
446			}
447		}
448
449		res = NULL;
450		if ((sc->sc_flags & EBUS_PCI) != 0) {
451			/*
452			 * Map EBus ranges to PCI ranges.  This may include
453			 * changing the allocation type.
454			 */
455			(void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
456			    &start, &end, &ridx);
457			eri = &sc->sc_rinfo[ridx];
458			res = rman_reserve_resource(&eri->eri_rman, start,
459			    end, count, flags & ~RF_ACTIVE, child);
460			if (res == NULL)
461				return (NULL);
462			rman_set_rid(res, *rid);
463			if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(
464			    child, type, *rid, res) != 0) {
465				rman_release_resource(res);
466				return (NULL);
467			}
468		} else {
469			/* Map EBus ranges to nexus ranges. */
470			for (i = 0; i < sc->sc_nrange; i++) {
471				enr = &((struct ebus_nexus_ranges *)
472				    sc->sc_range)[i];
473				cstart = (((uint64_t)enr->child_hi) << 32) |
474				    enr->child_lo;
475				cend = cstart + enr->size - 1;
476				if (start >= cstart && end <= cend) {
477					offset =
478					    (((uint64_t)enr->phys_hi) << 32) |
479					    enr->phys_lo;
480					start += offset - cstart;
481					end += offset - cstart;
482					res = bus_generic_alloc_resource(bus,
483					    child, type, rid, start, end,
484					    count, flags);
485					break;
486				}
487			}
488		}
489		if (!passthrough)
490			rle->res = res;
491		return (res);
492	case SYS_RES_IRQ:
493		return (resource_list_alloc(rl, bus, child, type, rid, start,
494		    end, count, flags));
495	}
496	return (NULL);
497}
498
499static int
500ebus_activate_resource(device_t bus, device_t child, int type, int rid,
501    struct resource *res)
502{
503	struct ebus_softc *sc;
504	struct ebus_rinfo *eri;
505	bus_space_tag_t bt;
506	bus_space_handle_t bh;
507	int i, rv;
508
509	sc = device_get_softc(bus);
510	if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
511		for (i = 0; i < sc->sc_nrange; i++) {
512			eri = &sc->sc_rinfo[i];
513			if (rman_is_region_manager(res, &eri->eri_rman) != 0) {
514				bt = rman_get_bustag(eri->eri_res);
515				rv = bus_space_subregion(bt,
516				    rman_get_bushandle(eri->eri_res),
517				    rman_get_start(res) -
518				    rman_get_start(eri->eri_res),
519				    rman_get_size(res), &bh);
520				if (rv != 0)
521					return (rv);
522				rman_set_bustag(res, bt);
523				rman_set_bushandle(res, bh);
524				return (rman_activate_resource(res));
525			}
526		}
527		return (EINVAL);
528	}
529	return (bus_generic_activate_resource(bus, child, type, rid, res));
530}
531
532static int
533ebus_adjust_resource(device_t bus __unused, device_t child __unused,
534    int type __unused, struct resource *res __unused, u_long start __unused,
535    u_long end __unused)
536{
537
538	return (ENXIO);
539}
540
541static int
542ebus_release_resource(device_t bus, device_t child, int type, int rid,
543    struct resource *res)
544{
545	struct ebus_softc *sc;
546	struct resource_list *rl;
547	struct resource_list_entry *rle;
548	int passthrough, rv;
549
550	passthrough = (device_get_parent(child) != bus);
551	rl = BUS_GET_RESOURCE_LIST(bus, child);
552	sc = device_get_softc(bus);
553	if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
554		if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){
555			rv = bus_deactivate_resource(child, type, rid, res);
556			if (rv != 0)
557				return (rv);
558		}
559		rv = rman_release_resource(res);
560		if (rv != 0)
561			return (rv);
562		if (!passthrough) {
563			rle = resource_list_find(rl, type, rid);
564			KASSERT(rle != NULL,
565			    ("%s: resource entry not found!", __func__));
566			KASSERT(rle->res != NULL,
567			   ("%s: resource entry is not busy", __func__));
568			rle->res = NULL;
569		}
570		return (0);
571	}
572	return (resource_list_release(rl, bus, child, type, rid, res));
573}
574
575static int
576ebus_setup_intr(device_t dev, device_t child, struct resource *ires,
577    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
578    void **cookiep)
579{
580#ifndef SUN4V
581	struct ebus_softc *sc;
582	u_long vec;
583
584	sc = device_get_softc(dev);
585	if ((sc->sc_flags & EBUS_PCI) == 0) {
586		/*
587		 * Make sure the vector is fully specified.  This isn't
588		 * necessarily the case with the PCI variant.
589		 */
590		vec = rman_get_start(ires);
591		if (INTIGN(vec) != sc->sc_ign) {
592			device_printf(dev,
593			    "invalid interrupt vector 0x%lx\n", vec);
594			return (EINVAL);
595		}
596
597		/*
598		 * As we rely on the interrupt controllers of the
599		 * accompanying PCI-Express bridge ensure at least
600		 * something is registered for this vector.
601		 */
602		if (intr_vectors[vec].iv_ic == NULL) {
603			device_printf(dev,
604			    "invalid interrupt controller for vector 0x%lx\n",
605			    vec);
606			return (EINVAL);
607		}
608	}
609#endif
610	return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
611	    arg, cookiep));
612}
613
614static struct resource_list *
615ebus_get_resource_list(device_t dev, device_t child)
616{
617	struct ebus_devinfo *edi;
618
619	edi = device_get_ivars(child);
620	return (&edi->edi_rl);
621}
622
623static const struct ofw_bus_devinfo *
624ebus_get_devinfo(device_t bus, device_t dev)
625{
626	struct ebus_devinfo *edi;
627
628	edi = device_get_ivars(dev);
629	return (&edi->edi_obdinfo);
630}
631
632static struct ebus_devinfo *
633ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node)
634{
635	struct isa_regs reg, *regs;
636	ofw_isa_intr_t intr, *intrs;
637	struct ebus_devinfo *edi;
638	uint64_t start;
639	uint32_t rintr;
640	int i, nintr, nreg, rv;
641
642	edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK);
643	if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) {
644		free(edi, M_DEVBUF);
645		return (NULL);
646	}
647	resource_list_init(&edi->edi_rl);
648	nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)&regs);
649	if (nreg == -1) {
650		device_printf(dev, "<%s>: incomplete\n",
651		    edi->edi_obdinfo.obd_name);
652		ebus_destroy_dinfo(edi);
653		return (NULL);
654	}
655	for (i = 0; i < nreg; i++) {
656		start = ISA_REG_PHYS(regs + i);
657		(void)resource_list_add(&edi->edi_rl, SYS_RES_MEMORY, i,
658		    start, start + regs[i].size - 1, regs[i].size);
659	}
660	free(regs, M_OFWPROP);
661
662	nintr = OF_getprop_alloc(node, "interrupts",  sizeof(*intrs),
663	    (void **)&intrs);
664	if (nintr == -1)
665		return (edi);
666	for (i = 0; i < nintr; i++) {
667		rv = 0;
668		if ((sc->sc_flags & EBUS_PCI) != 0) {
669			rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo,
670			    intrs[i]);
671		} else {
672			intr = intrs[i];
673			rv = ofw_bus_lookup_imap(node, &sc->sc_iinfo, &reg,
674			    sizeof(reg), &intr, sizeof(intr), &rintr,
675			    sizeof(rintr), NULL);
676#ifndef SUN4V
677			if (rv != 0)
678				rintr = INTMAP_VEC(sc->sc_ign, rintr);
679#endif
680		}
681		if ((sc->sc_flags & EBUS_PCI) == 0 ? rv == 0 :
682		    rintr == PCI_INVALID_IRQ) {
683			device_printf(dev,
684			    "<%s>: could not map EBus interrupt %d\n",
685			    edi->edi_obdinfo.obd_name, intrs[i]);
686			continue;
687		}
688		(void)resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, rintr,
689		    rintr, 1);
690	}
691	free(intrs, M_OFWPROP);
692	return (edi);
693}
694
695static void
696ebus_destroy_dinfo(struct ebus_devinfo *edi)
697{
698
699	resource_list_free(&edi->edi_rl);
700	ofw_bus_gen_destroy_devinfo(&edi->edi_obdinfo);
701	free(edi, M_DEVBUF);
702}
703
704static int
705ebus_print_res(struct ebus_devinfo *edi)
706{
707	int retval;
708
709	retval = 0;
710	retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_MEMORY,
711	    "%#lx");
712	retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ,
713	    "%ld");
714	return (retval);
715}
716