ebus.c revision 292785
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: stable/10/sys/sparc64/ebus/ebus.c 292785 2015-12-27 17:51:10Z marius $");
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#include <sys/rman.h>
73
74#include <dev/ofw/ofw_bus.h>
75#include <dev/ofw/ofw_bus_subr.h>
76#include <dev/ofw/openfirm.h>
77
78#include <machine/bus.h>
79#ifndef SUN4V
80#include <machine/bus_common.h>
81#endif
82#include <machine/intr_machdep.h>
83#include <machine/resource.h>
84
85#include <dev/pci/pcireg.h>
86#include <dev/pci/pcivar.h>
87
88#include <sparc64/pci/ofw_pci.h>
89
90/*
91 * The register, interrupt map and for the PCI variant also the ranges
92 * properties are identical to the ISA ones.
93 */
94#include <sparc64/isa/ofw_isa.h>
95
96struct ebus_nexus_ranges {
97	uint32_t	child_hi;
98	uint32_t	child_lo;
99	uint32_t	phys_hi;
100	uint32_t	phys_lo;
101	uint32_t	size;
102};
103
104struct ebus_devinfo {
105	struct ofw_bus_devinfo	edi_obdinfo;
106	struct resource_list	edi_rl;
107};
108
109struct ebus_rinfo {
110	int			eri_rtype;
111	struct rman		eri_rman;
112	struct resource		*eri_res;
113};
114
115struct ebus_softc {
116	void			*sc_range;
117	struct ebus_rinfo	*sc_rinfo;
118
119	u_int			sc_flags;
120#define	EBUS_PCI		(1 << 0)
121
122	int			sc_nrange;
123
124	struct ofw_bus_iinfo	sc_iinfo;
125
126#ifndef SUN4V
127	uint32_t		sc_ign;
128#endif
129};
130
131static device_probe_t ebus_nexus_probe;
132static device_attach_t ebus_nexus_attach;
133static device_probe_t ebus_pci_probe;
134static device_attach_t ebus_pci_attach;
135static bus_print_child_t ebus_print_child;
136static bus_probe_nomatch_t ebus_probe_nomatch;
137static bus_alloc_resource_t ebus_alloc_resource;
138static bus_activate_resource_t ebus_activate_resource;
139static bus_adjust_resource_t ebus_adjust_resource;
140static bus_release_resource_t ebus_release_resource;
141static bus_setup_intr_t ebus_setup_intr;
142static bus_get_resource_list_t ebus_get_resource_list;
143static ofw_bus_get_devinfo_t ebus_get_devinfo;
144
145static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node);
146static struct ebus_devinfo *ebus_setup_dinfo(device_t dev,
147    struct ebus_softc *sc, phandle_t node);
148static void ebus_destroy_dinfo(struct ebus_devinfo *edi);
149static int ebus_print_res(struct ebus_devinfo *edi);
150
151static devclass_t ebus_devclass;
152
153static device_method_t ebus_nexus_methods[] = {
154	/* Device interface */
155	DEVMETHOD(device_probe,		ebus_nexus_probe),
156	DEVMETHOD(device_attach,	ebus_nexus_attach),
157	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
158	DEVMETHOD(device_suspend,	bus_generic_suspend),
159	DEVMETHOD(device_resume,	bus_generic_resume),
160
161	/* Bus interface */
162	DEVMETHOD(bus_print_child,	ebus_print_child),
163	DEVMETHOD(bus_probe_nomatch,	ebus_probe_nomatch),
164	DEVMETHOD(bus_alloc_resource,	ebus_alloc_resource),
165	DEVMETHOD(bus_activate_resource, ebus_activate_resource),
166	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
167	DEVMETHOD(bus_adjust_resource,	ebus_adjust_resource),
168	DEVMETHOD(bus_release_resource,	ebus_release_resource),
169	DEVMETHOD(bus_setup_intr,	ebus_setup_intr),
170	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
171	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
172	DEVMETHOD(bus_get_resource_list, ebus_get_resource_list),
173	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
174
175	/* ofw_bus interface */
176	DEVMETHOD(ofw_bus_get_devinfo,	ebus_get_devinfo),
177	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
178	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
179	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
180	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
181	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
182
183	DEVMETHOD_END
184};
185
186static driver_t ebus_nexus_driver = {
187	"ebus",
188	ebus_nexus_methods,
189	sizeof(struct ebus_softc),
190};
191
192/*
193 * NB: we rely on the interrupt controllers of the accompanying PCI-Express
194 * bridge to be registered as the nexus variant of the EBus bridges doesn't
195 * employ its own one.
196 */
197EARLY_DRIVER_MODULE(ebus, nexus, ebus_nexus_driver, ebus_devclass, 0, 0,
198    BUS_PASS_BUS + 1);
199MODULE_DEPEND(ebus, nexus, 1, 1, 1);
200
201static device_method_t ebus_pci_methods[] = {
202	/* Device interface */
203	DEVMETHOD(device_probe,		ebus_pci_probe),
204	DEVMETHOD(device_attach,	ebus_pci_attach),
205	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
206	DEVMETHOD(device_suspend,	bus_generic_suspend),
207	DEVMETHOD(device_resume,	bus_generic_resume),
208
209	/* Bus interface */
210	DEVMETHOD(bus_print_child,	ebus_print_child),
211	DEVMETHOD(bus_probe_nomatch,	ebus_probe_nomatch),
212	DEVMETHOD(bus_alloc_resource,	ebus_alloc_resource),
213	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
214	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
215	DEVMETHOD(bus_release_resource,	ebus_release_resource),
216	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
217	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
218	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
219	DEVMETHOD(bus_get_resource_list, ebus_get_resource_list),
220	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
221
222	/* ofw_bus interface */
223	DEVMETHOD(ofw_bus_get_devinfo,	ebus_get_devinfo),
224	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
225	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
226	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
227	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
228	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
229
230	DEVMETHOD_END
231};
232
233static driver_t ebus_pci_driver = {
234	"ebus",
235	ebus_pci_methods,
236	sizeof(struct ebus_softc),
237};
238
239EARLY_DRIVER_MODULE(ebus, pci, ebus_pci_driver, ebus_devclass, 0, 0,
240    BUS_PASS_BUS);
241MODULE_DEPEND(ebus, pci, 1, 1, 1);
242MODULE_VERSION(ebus, 1);
243
244static int
245ebus_nexus_probe(device_t dev)
246{
247	const char* compat;
248
249	compat = ofw_bus_get_compat(dev);
250	if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ebus") == 0 &&
251	    strcmp(compat, "jbus-ebus") == 0) {
252		device_set_desc(dev, "JBus-EBus bridge");
253		return (BUS_PROBE_GENERIC);
254	}
255	return (ENXIO);
256}
257
258static int
259ebus_pci_probe(device_t dev)
260{
261
262	if (pci_get_class(dev) != PCIC_BRIDGE ||
263	    pci_get_vendor(dev) != 0x108e ||
264	    strcmp(ofw_bus_get_name(dev), "ebus") != 0)
265		return (ENXIO);
266
267	if (pci_get_device(dev) == 0x1000)
268		device_set_desc(dev, "PCI-EBus2 bridge");
269	else if (pci_get_device(dev) == 0x1100)
270		device_set_desc(dev, "PCI-EBus3 bridge");
271	else
272		return (ENXIO);
273	return (BUS_PROBE_GENERIC);
274}
275
276static int
277ebus_nexus_attach(device_t dev)
278{
279	struct ebus_softc *sc;
280	phandle_t node;
281
282	sc = device_get_softc(dev);
283	node = ofw_bus_get_node(dev);
284
285#ifndef SUN4V
286	if (OF_getprop(node, "portid", &sc->sc_ign,
287	    sizeof(sc->sc_ign)) == -1) {
288		device_printf(dev, "could not determine IGN");
289		return (ENXIO);
290	}
291#endif
292
293	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
294	    sizeof(struct ebus_nexus_ranges), &sc->sc_range);
295	if (sc->sc_nrange == -1) {
296		device_printf(dev, "could not get ranges property\n");
297		return (ENXIO);
298	}
299	return (ebus_attach(dev, sc, node));
300}
301
302static int
303ebus_pci_attach(device_t dev)
304{
305	struct ebus_softc *sc;
306	struct ebus_rinfo *eri;
307	struct resource *res;
308	struct isa_ranges *range;
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		device_printf(dev, "could not get ranges property\n");
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		range = &((struct isa_ranges *)sc->sc_range)[rnum];
336		eri->eri_rtype = ofw_isa_range_restype(range);
337		rid = PCIR_BAR(rnum);
338		res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid,
339		    RF_ACTIVE);
340		if (res == NULL) {
341			device_printf(dev,
342			    "could not allocate range resource %d\n", rnum);
343			goto fail;
344		}
345		if (rman_get_start(res) != ISA_RANGE_PHYS(range)) {
346			device_printf(dev,
347			    "mismatch in start of range %d (0x%lx/0x%lx)\n",
348			    rnum, rman_get_start(res), ISA_RANGE_PHYS(range));
349			goto fail;
350		}
351		if (rman_get_size(res) != range->size) {
352			device_printf(dev,
353			    "mismatch in size of range %d (0x%lx/0x%x)\n",
354			    rnum, rman_get_size(res), range->size);
355			goto fail;
356		}
357		eri->eri_res = res;
358		eri->eri_rman.rm_type = RMAN_ARRAY;
359		eri->eri_rman.rm_descr = "EBus range";
360		if (rman_init_from_resource(&eri->eri_rman, res) != 0) {
361			device_printf(dev,
362			    "could not initialize rman for range %d", rnum);
363			goto fail;
364		}
365	}
366	return (ebus_attach(dev, sc, node));
367
368 fail:
369	for (i = rnum; i >= 0; i--) {
370		eri = &sc->sc_rinfo[i];
371		if (i < rnum)
372			rman_fini(&eri->eri_rman);
373		if (eri->eri_res != 0) {
374			bus_release_resource(dev, eri->eri_rtype,
375			    PCIR_BAR(rnum), eri->eri_res);
376		}
377	}
378	free(sc->sc_rinfo, M_DEVBUF);
379	free(sc->sc_range, M_OFWPROP);
380	return (ENXIO);
381}
382
383static int
384ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node)
385{
386	struct ebus_devinfo *edi;
387	device_t cdev;
388
389	ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t));
390
391	/*
392	 * Now attach our children.
393	 */
394	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
395		if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL)
396			continue;
397		if ((cdev = device_add_child(dev, NULL, -1)) == NULL) {
398			device_printf(dev, "<%s>: device_add_child failed\n",
399			    edi->edi_obdinfo.obd_name);
400			ebus_destroy_dinfo(edi);
401			continue;
402		}
403		device_set_ivars(cdev, edi);
404	}
405	return (bus_generic_attach(dev));
406}
407
408static int
409ebus_print_child(device_t dev, device_t child)
410{
411	int retval;
412
413	retval = bus_print_child_header(dev, child);
414	retval += ebus_print_res(device_get_ivars(child));
415	retval += bus_print_child_footer(dev, child);
416	return (retval);
417}
418
419static void
420ebus_probe_nomatch(device_t dev, device_t child)
421{
422
423	device_printf(dev, "<%s>", ofw_bus_get_name(child));
424	ebus_print_res(device_get_ivars(child));
425	printf(" (no driver attached)\n");
426}
427
428static struct resource *
429ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
430    u_long start, u_long end, u_long count, u_int flags)
431{
432	struct ebus_softc *sc;
433	struct resource_list *rl;
434	struct resource_list_entry *rle = NULL;
435	struct resource *res;
436	struct ebus_rinfo *eri;
437	struct ebus_nexus_ranges *enr;
438	uint64_t cend, cstart, offset;
439	int i, isdefault, passthrough, ridx;
440
441	isdefault = (start == 0UL && end == ~0UL);
442	passthrough = (device_get_parent(child) != bus);
443	sc = device_get_softc(bus);
444	rl = BUS_GET_RESOURCE_LIST(bus, child);
445	switch (type) {
446	case SYS_RES_MEMORY:
447		KASSERT(!(isdefault && passthrough),
448		    ("%s: passthrough of default allocation", __func__));
449		if (!passthrough) {
450			rle = resource_list_find(rl, type, *rid);
451			if (rle == NULL)
452				return (NULL);
453			KASSERT(rle->res == NULL,
454			    ("%s: resource entry is busy", __func__));
455			if (isdefault) {
456				start = rle->start;
457				count = ulmax(count, rle->count);
458				end = ulmax(rle->end, start + count - 1);
459			}
460		}
461
462		res = NULL;
463		if ((sc->sc_flags & EBUS_PCI) != 0) {
464			/*
465			 * Map EBus ranges to PCI ranges.  This may include
466			 * changing the allocation type.
467			 */
468			type = ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
469			    &start, &end, &ridx);
470			eri = &sc->sc_rinfo[ridx];
471			res = rman_reserve_resource(&eri->eri_rman, start,
472			    end, count, flags & ~RF_ACTIVE, child);
473			if (res == NULL)
474				return (NULL);
475			rman_set_rid(res, *rid);
476			if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(
477			    child, type, *rid, res) != 0) {
478				rman_release_resource(res);
479				return (NULL);
480			}
481		} else {
482			/* Map EBus ranges to nexus ranges. */
483			for (i = 0; i < sc->sc_nrange; i++) {
484				enr = &((struct ebus_nexus_ranges *)
485				    sc->sc_range)[i];
486				cstart = (((uint64_t)enr->child_hi) << 32) |
487				    enr->child_lo;
488				cend = cstart + enr->size - 1;
489				if (start >= cstart && end <= cend) {
490					offset =
491					    (((uint64_t)enr->phys_hi) << 32) |
492					    enr->phys_lo;
493					start += offset - cstart;
494					end += offset - cstart;
495					res = bus_generic_alloc_resource(bus,
496					    child, type, rid, start, end,
497					    count, flags);
498					break;
499				}
500			}
501		}
502		if (!passthrough)
503			rle->res = res;
504		return (res);
505	case SYS_RES_IRQ:
506		return (resource_list_alloc(rl, bus, child, type, rid, start,
507		    end, count, flags));
508	}
509	return (NULL);
510}
511
512static int
513ebus_activate_resource(device_t bus, device_t child, int type, int rid,
514    struct resource *res)
515{
516	struct ebus_softc *sc;
517	struct ebus_rinfo *eri;
518	bus_space_tag_t bt;
519	bus_space_handle_t bh;
520	int i, rv;
521
522	sc = device_get_softc(bus);
523	if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) {
524		for (i = 0; i < sc->sc_nrange; i++) {
525			eri = &sc->sc_rinfo[i];
526			if (rman_is_region_manager(res, &eri->eri_rman) != 0) {
527				bt = rman_get_bustag(eri->eri_res);
528				rv = bus_space_subregion(bt,
529				    rman_get_bushandle(eri->eri_res),
530				    rman_get_start(res) -
531				    rman_get_start(eri->eri_res),
532				    rman_get_size(res), &bh);
533				if (rv != 0)
534					return (rv);
535				rman_set_bustag(res, bt);
536				rman_set_bushandle(res, bh);
537				return (rman_activate_resource(res));
538			}
539		}
540		return (EINVAL);
541	}
542	return (bus_generic_activate_resource(bus, child, type, rid, res));
543}
544
545static int
546ebus_adjust_resource(device_t bus __unused, device_t child __unused,
547    int type __unused, struct resource *res __unused, u_long start __unused,
548    u_long end __unused)
549{
550
551	return (ENXIO);
552}
553
554static int
555ebus_release_resource(device_t bus, device_t child, int type, int rid,
556    struct resource *res)
557{
558	struct ebus_softc *sc;
559	struct resource_list *rl;
560	struct resource_list_entry *rle;
561	int passthrough, rv;
562
563	passthrough = (device_get_parent(child) != bus);
564	rl = BUS_GET_RESOURCE_LIST(bus, child);
565	sc = device_get_softc(bus);
566	if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) {
567		if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){
568			rv = bus_deactivate_resource(child, type, rid, res);
569			if (rv != 0)
570				return (rv);
571		}
572		rv = rman_release_resource(res);
573		if (rv != 0)
574			return (rv);
575		if (!passthrough) {
576			rle = resource_list_find(rl, type, rid);
577			KASSERT(rle != NULL,
578			    ("%s: resource entry not found!", __func__));
579			KASSERT(rle->res != NULL,
580			   ("%s: resource entry is not busy", __func__));
581			rle->res = NULL;
582		}
583		return (0);
584	}
585	return (resource_list_release(rl, bus, child, type, rid, res));
586}
587
588static int
589ebus_setup_intr(device_t dev, device_t child, struct resource *ires,
590    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
591    void **cookiep)
592{
593#ifndef SUN4V
594	struct ebus_softc *sc;
595	u_long vec;
596
597	sc = device_get_softc(dev);
598	if ((sc->sc_flags & EBUS_PCI) == 0) {
599		/*
600		 * Make sure the vector is fully specified.  This isn't
601		 * necessarily the case with the PCI variant.
602		 */
603		vec = rman_get_start(ires);
604		if (INTIGN(vec) != sc->sc_ign) {
605			device_printf(dev,
606			    "invalid interrupt vector 0x%lx\n", vec);
607			return (EINVAL);
608		}
609
610		/*
611		 * As we rely on the interrupt controllers of the
612		 * accompanying PCI-Express bridge ensure at least
613		 * something is registered for this vector.
614		 */
615		if (intr_vectors[vec].iv_ic == NULL) {
616			device_printf(dev,
617			    "invalid interrupt controller for vector 0x%lx\n",
618			    vec);
619			return (EINVAL);
620		}
621	}
622#endif
623	return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
624	    arg, cookiep));
625}
626
627static struct resource_list *
628ebus_get_resource_list(device_t dev, device_t child)
629{
630	struct ebus_devinfo *edi;
631
632	edi = device_get_ivars(child);
633	return (&edi->edi_rl);
634}
635
636static const struct ofw_bus_devinfo *
637ebus_get_devinfo(device_t bus, device_t dev)
638{
639	struct ebus_devinfo *edi;
640
641	edi = device_get_ivars(dev);
642	return (&edi->edi_obdinfo);
643}
644
645static struct ebus_devinfo *
646ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node)
647{
648	struct isa_regs reg, *regs;
649	ofw_isa_intr_t intr, *intrs;
650	struct ebus_devinfo *edi;
651	uint64_t start;
652	uint32_t rintr;
653	int i, nintr, nreg, rv;
654
655	edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK);
656	if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) {
657		free(edi, M_DEVBUF);
658		return (NULL);
659	}
660	resource_list_init(&edi->edi_rl);
661	nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)&regs);
662	if (nreg == -1) {
663		device_printf(dev, "<%s>: incomplete\n",
664		    edi->edi_obdinfo.obd_name);
665		ebus_destroy_dinfo(edi);
666		return (NULL);
667	}
668	for (i = 0; i < nreg; i++) {
669		start = ISA_REG_PHYS(regs + i);
670		(void)resource_list_add(&edi->edi_rl, SYS_RES_MEMORY, i,
671		    start, start + regs[i].size - 1, regs[i].size);
672	}
673	free(regs, M_OFWPROP);
674
675	nintr = OF_getprop_alloc(node, "interrupts",  sizeof(*intrs),
676	    (void **)&intrs);
677	if (nintr == -1)
678		return (edi);
679	for (i = 0; i < nintr; i++) {
680		rv = 0;
681		if ((sc->sc_flags & EBUS_PCI) != 0) {
682			rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo,
683			    intrs[i]);
684		} else {
685			intr = intrs[i];
686			rv = ofw_bus_lookup_imap(node, &sc->sc_iinfo, &reg,
687			    sizeof(reg), &intr, sizeof(intr), &rintr,
688			    sizeof(rintr), NULL);
689#ifndef SUN4V
690			if (rv != 0)
691				rintr = INTMAP_VEC(sc->sc_ign, rintr);
692#endif
693		}
694		if ((sc->sc_flags & EBUS_PCI) == 0 ? rv == 0 :
695		    rintr == PCI_INVALID_IRQ) {
696			device_printf(dev,
697			    "<%s>: could not map EBus interrupt %d\n",
698			    edi->edi_obdinfo.obd_name, intrs[i]);
699			continue;
700		}
701		(void)resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, rintr,
702		    rintr, 1);
703	}
704	free(intrs, M_OFWPROP);
705	return (edi);
706}
707
708static void
709ebus_destroy_dinfo(struct ebus_devinfo *edi)
710{
711
712	resource_list_free(&edi->edi_rl);
713	ofw_bus_gen_destroy_devinfo(&edi->edi_obdinfo);
714	free(edi, M_DEVBUF);
715}
716
717static int
718ebus_print_res(struct ebus_devinfo *edi)
719{
720	int retval;
721
722	retval = 0;
723	retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_MEMORY,
724	    "%#lx");
725	retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ,
726	    "%ld");
727	return (retval);
728}
729