xref: /freebsd/sys/dev/ofw/ofw_pcib.c (revision 18250ec6c089c0c50cbd9fd87d78e03ff89916df)
124042910SMarcin Wojtas /*-
224042910SMarcin Wojtas  * Copyright (c) 2011 Nathan Whitehorn
324042910SMarcin Wojtas  * All rights reserved.
424042910SMarcin Wojtas  *
524042910SMarcin Wojtas  * Redistribution and use in source and binary forms, with or without
624042910SMarcin Wojtas  * modification, are permitted provided that the following conditions
724042910SMarcin Wojtas  * are met:
824042910SMarcin Wojtas  * 1. Redistributions of source code must retain the above copyright
924042910SMarcin Wojtas  *    notice, this list of conditions and the following disclaimer.
1024042910SMarcin Wojtas  * 2. Redistributions in binary form must reproduce the above copyright
1124042910SMarcin Wojtas  *    notice, this list of conditions and the following disclaimer in the
1224042910SMarcin Wojtas  *    documentation and/or other materials provided with the distribution.
1324042910SMarcin Wojtas  *
1424042910SMarcin Wojtas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1524042910SMarcin Wojtas  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1624042910SMarcin Wojtas  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1724042910SMarcin Wojtas  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1824042910SMarcin Wojtas  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1924042910SMarcin Wojtas  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2024042910SMarcin Wojtas  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2124042910SMarcin Wojtas  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2224042910SMarcin Wojtas  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2324042910SMarcin Wojtas  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2424042910SMarcin Wojtas  * SUCH DAMAGE.
2524042910SMarcin Wojtas  */
2624042910SMarcin Wojtas 
2724042910SMarcin Wojtas #include <sys/param.h>
2824042910SMarcin Wojtas #include <sys/systm.h>
2924042910SMarcin Wojtas #include <sys/module.h>
3024042910SMarcin Wojtas #include <sys/bus.h>
3124042910SMarcin Wojtas #include <sys/conf.h>
3224042910SMarcin Wojtas #include <sys/kernel.h>
3324042910SMarcin Wojtas #include <sys/rman.h>
3424042910SMarcin Wojtas 
3524042910SMarcin Wojtas #include <dev/ofw/openfirm.h>
3624042910SMarcin Wojtas #include <dev/ofw/ofw_pci.h>
3724042910SMarcin Wojtas #include <dev/ofw/ofw_bus.h>
3824042910SMarcin Wojtas #include <dev/ofw/ofw_bus_subr.h>
3924042910SMarcin Wojtas #include <dev/ofw/ofwpci.h>
4024042910SMarcin Wojtas 
4124042910SMarcin Wojtas #include <dev/pci/pcivar.h>
4224042910SMarcin Wojtas #include <dev/pci/pcireg.h>
4324042910SMarcin Wojtas #include <dev/pci/pcib_private.h>
4424042910SMarcin Wojtas 
4524042910SMarcin Wojtas #include <machine/bus.h>
4624042910SMarcin Wojtas #include <machine/md_var.h>
4724042910SMarcin Wojtas #include <machine/resource.h>
4824042910SMarcin Wojtas 
4924042910SMarcin Wojtas #include <vm/vm.h>
5024042910SMarcin Wojtas #include <vm/pmap.h>
5124042910SMarcin Wojtas 
5224042910SMarcin Wojtas #include "pcib_if.h"
5324042910SMarcin Wojtas 
5424042910SMarcin Wojtas /*
5524042910SMarcin Wojtas  * If it is necessary to set another value of this for
5624042910SMarcin Wojtas  * some platforms it should be set at fdt.h file
5724042910SMarcin Wojtas  */
5824042910SMarcin Wojtas #ifndef PCI_MAP_INTR
5924042910SMarcin Wojtas #define	PCI_MAP_INTR	4
6024042910SMarcin Wojtas #endif
6124042910SMarcin Wojtas 
6224042910SMarcin Wojtas #define	PCI_INTR_PINS	4
6324042910SMarcin Wojtas 
6424042910SMarcin Wojtas /*
6524042910SMarcin Wojtas  * bus interface.
6624042910SMarcin Wojtas  */
670b60d7a6SJohn Baldwin static struct rman *ofw_pcib_get_rman(device_t, int, u_int);
6824042910SMarcin Wojtas static struct resource * ofw_pcib_alloc_resource(device_t, device_t,
6924042910SMarcin Wojtas     int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
709dbf5b0eSJohn Baldwin static int ofw_pcib_release_resource(device_t, device_t, struct resource *);
712baed46eSJohn Baldwin static int ofw_pcib_activate_resource(device_t, device_t, struct resource *);
722baed46eSJohn Baldwin static int ofw_pcib_deactivate_resource(device_t, device_t, struct resource *);
73fef01f04SJohn Baldwin static int ofw_pcib_adjust_resource(device_t, device_t,
7424042910SMarcin Wojtas     struct resource *, rman_res_t, rman_res_t);
75d77f2092SJohn Baldwin static int ofw_pcib_map_resource(device_t, device_t, struct resource *,
760b60d7a6SJohn Baldwin     struct resource_map_request *, struct resource_map *);
77d77f2092SJohn Baldwin static int ofw_pcib_unmap_resource(device_t, device_t, struct resource *,
780b60d7a6SJohn Baldwin     struct resource_map *);
7924042910SMarcin Wojtas static int ofw_pcib_translate_resource(device_t bus, int type,
8024042910SMarcin Wojtas 	rman_res_t start, rman_res_t *newstart);
8124042910SMarcin Wojtas 
8224042910SMarcin Wojtas #ifdef __powerpc__
8324042910SMarcin Wojtas static bus_space_tag_t ofw_pcib_bus_get_bus_tag(device_t, device_t);
8424042910SMarcin Wojtas #endif
8524042910SMarcin Wojtas 
8624042910SMarcin Wojtas /*
8724042910SMarcin Wojtas  * pcib interface
8824042910SMarcin Wojtas  */
8924042910SMarcin Wojtas static int ofw_pcib_maxslots(device_t);
9024042910SMarcin Wojtas 
9124042910SMarcin Wojtas /*
9224042910SMarcin Wojtas  * ofw_bus interface
9324042910SMarcin Wojtas  */
9424042910SMarcin Wojtas static phandle_t ofw_pcib_get_node(device_t, device_t);
9524042910SMarcin Wojtas 
9624042910SMarcin Wojtas /*
9724042910SMarcin Wojtas  * local methods
9824042910SMarcin Wojtas  */
9924042910SMarcin Wojtas static int ofw_pcib_fill_ranges(phandle_t, struct ofw_pci_range *);
10024042910SMarcin Wojtas 
10124042910SMarcin Wojtas /*
10224042910SMarcin Wojtas  * Driver methods.
10324042910SMarcin Wojtas  */
10424042910SMarcin Wojtas static device_method_t	ofw_pcib_methods[] = {
10524042910SMarcin Wojtas 	/* Device interface */
10624042910SMarcin Wojtas 	DEVMETHOD(device_attach,	ofw_pcib_attach),
10724042910SMarcin Wojtas 
10824042910SMarcin Wojtas 	/* Bus interface */
10924042910SMarcin Wojtas 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
11024042910SMarcin Wojtas 	DEVMETHOD(bus_read_ivar,	ofw_pcib_read_ivar),
11124042910SMarcin Wojtas 	DEVMETHOD(bus_write_ivar,	ofw_pcib_write_ivar),
11224042910SMarcin Wojtas 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
11324042910SMarcin Wojtas 	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
1140b60d7a6SJohn Baldwin 	DEVMETHOD(bus_get_rman,		ofw_pcib_get_rman),
11524042910SMarcin Wojtas 	DEVMETHOD(bus_alloc_resource,	ofw_pcib_alloc_resource),
11624042910SMarcin Wojtas 	DEVMETHOD(bus_release_resource,	ofw_pcib_release_resource),
11724042910SMarcin Wojtas 	DEVMETHOD(bus_activate_resource,	ofw_pcib_activate_resource),
11824042910SMarcin Wojtas 	DEVMETHOD(bus_deactivate_resource,	ofw_pcib_deactivate_resource),
11924042910SMarcin Wojtas 	DEVMETHOD(bus_adjust_resource,	ofw_pcib_adjust_resource),
1200b60d7a6SJohn Baldwin 	DEVMETHOD(bus_map_resource,	ofw_pcib_map_resource),
1210b60d7a6SJohn Baldwin 	DEVMETHOD(bus_unmap_resource,	ofw_pcib_unmap_resource),
12224042910SMarcin Wojtas 	DEVMETHOD(bus_translate_resource,	ofw_pcib_translate_resource),
12324042910SMarcin Wojtas #ifdef __powerpc__
12424042910SMarcin Wojtas 	DEVMETHOD(bus_get_bus_tag,	ofw_pcib_bus_get_bus_tag),
12524042910SMarcin Wojtas #endif
12624042910SMarcin Wojtas 
12724042910SMarcin Wojtas 	/* pcib interface */
12824042910SMarcin Wojtas 	DEVMETHOD(pcib_maxslots,	ofw_pcib_maxslots),
12924042910SMarcin Wojtas 	DEVMETHOD(pcib_route_interrupt,	ofw_pcib_route_interrupt),
13024042910SMarcin Wojtas 	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
13124042910SMarcin Wojtas 
13224042910SMarcin Wojtas 	/* ofw_bus interface */
13324042910SMarcin Wojtas 	DEVMETHOD(ofw_bus_get_node,	ofw_pcib_get_node),
13424042910SMarcin Wojtas 
13524042910SMarcin Wojtas 	DEVMETHOD_END
13624042910SMarcin Wojtas };
13724042910SMarcin Wojtas 
13824042910SMarcin Wojtas DEFINE_CLASS_0(ofw_pcib, ofw_pcib_driver, ofw_pcib_methods, 0);
13924042910SMarcin Wojtas 
14024042910SMarcin Wojtas int
ofw_pcib_init(device_t dev)14124042910SMarcin Wojtas ofw_pcib_init(device_t dev)
14224042910SMarcin Wojtas {
14324042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
14424042910SMarcin Wojtas 	phandle_t node;
14524042910SMarcin Wojtas 	u_int32_t busrange[2];
14624042910SMarcin Wojtas 	struct ofw_pci_range *rp;
14724042910SMarcin Wojtas 	int i, error;
14824042910SMarcin Wojtas 	struct ofw_pci_cell_info *cell_info;
14924042910SMarcin Wojtas 
15024042910SMarcin Wojtas 	node = ofw_bus_get_node(dev);
15124042910SMarcin Wojtas 	sc = device_get_softc(dev);
15224042910SMarcin Wojtas 	sc->sc_initialized = 1;
15324042910SMarcin Wojtas 	sc->sc_range = NULL;
15424042910SMarcin Wojtas 	sc->sc_pci_domain = device_get_unit(dev);
15524042910SMarcin Wojtas 
15624042910SMarcin Wojtas 	cell_info = (struct ofw_pci_cell_info *)malloc(sizeof(*cell_info),
15724042910SMarcin Wojtas 	    M_DEVBUF, M_WAITOK | M_ZERO);
15824042910SMarcin Wojtas 
15924042910SMarcin Wojtas 	sc->sc_cell_info = cell_info;
16024042910SMarcin Wojtas 
16124042910SMarcin Wojtas 	if (OF_getencprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
16224042910SMarcin Wojtas 		busrange[0] = 0;
16324042910SMarcin Wojtas 
16424042910SMarcin Wojtas 	sc->sc_dev = dev;
16524042910SMarcin Wojtas 	sc->sc_node = node;
16624042910SMarcin Wojtas 	sc->sc_bus = busrange[0];
16724042910SMarcin Wojtas 
16824042910SMarcin Wojtas 	if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) {
16924042910SMarcin Wojtas 		phandle_t c;
17024042910SMarcin Wojtas 		int n, i;
17124042910SMarcin Wojtas 
17224042910SMarcin Wojtas 		sc->sc_nrange = 0;
17324042910SMarcin Wojtas 		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
17424042910SMarcin Wojtas 			n = ofw_pcib_nranges(c, cell_info);
17524042910SMarcin Wojtas 			if (n > 0)
17624042910SMarcin Wojtas 				sc->sc_nrange += n;
17724042910SMarcin Wojtas 		}
17824042910SMarcin Wojtas 		if (sc->sc_nrange == 0) {
17924042910SMarcin Wojtas 			error = ENXIO;
18024042910SMarcin Wojtas 			goto out;
18124042910SMarcin Wojtas 		}
18224042910SMarcin Wojtas 		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
18324042910SMarcin Wojtas 		    M_DEVBUF, M_WAITOK);
18424042910SMarcin Wojtas 		i = 0;
18524042910SMarcin Wojtas 		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
18624042910SMarcin Wojtas 			n = ofw_pcib_fill_ranges(c, &sc->sc_range[i]);
18724042910SMarcin Wojtas 			if (n > 0)
18824042910SMarcin Wojtas 				i += n;
18924042910SMarcin Wojtas 		}
19024042910SMarcin Wojtas 		KASSERT(i == sc->sc_nrange, ("range count mismatch"));
19124042910SMarcin Wojtas 	} else {
19224042910SMarcin Wojtas 		sc->sc_nrange = ofw_pcib_nranges(node, cell_info);
19324042910SMarcin Wojtas 		if (sc->sc_nrange <= 0) {
19424042910SMarcin Wojtas 			device_printf(dev, "could not getranges\n");
19524042910SMarcin Wojtas 			error = ENXIO;
19624042910SMarcin Wojtas 			goto out;
19724042910SMarcin Wojtas 		}
19824042910SMarcin Wojtas 		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
19924042910SMarcin Wojtas 		    M_DEVBUF, M_WAITOK);
20024042910SMarcin Wojtas 		ofw_pcib_fill_ranges(node, sc->sc_range);
20124042910SMarcin Wojtas 	}
20224042910SMarcin Wojtas 
20324042910SMarcin Wojtas 	sc->sc_io_rman.rm_type = RMAN_ARRAY;
20424042910SMarcin Wojtas 	sc->sc_io_rman.rm_descr = "PCI I/O Ports";
20524042910SMarcin Wojtas 	error = rman_init(&sc->sc_io_rman);
20624042910SMarcin Wojtas 	if (error != 0) {
20724042910SMarcin Wojtas 		device_printf(dev, "rman_init() failed. error = %d\n", error);
20824042910SMarcin Wojtas 		goto out;
20924042910SMarcin Wojtas 	}
21024042910SMarcin Wojtas 
21124042910SMarcin Wojtas 	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
21224042910SMarcin Wojtas 	sc->sc_mem_rman.rm_descr = "PCI Non Prefetchable Memory";
21324042910SMarcin Wojtas 	error = rman_init(&sc->sc_mem_rman);
21424042910SMarcin Wojtas 	if (error != 0) {
21524042910SMarcin Wojtas 		device_printf(dev, "rman_init() failed. error = %d\n", error);
216b1e93132SAndrew Turner 		goto out_mem_rman;
21724042910SMarcin Wojtas 	}
21824042910SMarcin Wojtas 
21924042910SMarcin Wojtas 	sc->sc_pmem_rman.rm_type = RMAN_ARRAY;
22024042910SMarcin Wojtas 	sc->sc_pmem_rman.rm_descr = "PCI Prefetchable Memory";
22124042910SMarcin Wojtas 	error = rman_init(&sc->sc_pmem_rman);
22224042910SMarcin Wojtas 	if (error != 0) {
22324042910SMarcin Wojtas 		device_printf(dev, "rman_init() failed. error = %d\n", error);
224b1e93132SAndrew Turner 		goto out_pmem_rman;
22524042910SMarcin Wojtas 	}
22624042910SMarcin Wojtas 
22724042910SMarcin Wojtas 	for (i = 0; i < sc->sc_nrange; i++) {
22824042910SMarcin Wojtas 		error = 0;
22924042910SMarcin Wojtas 		rp = sc->sc_range + i;
23024042910SMarcin Wojtas 
23124042910SMarcin Wojtas 		if (sc->sc_range_mask & ((uint64_t)1 << i))
23224042910SMarcin Wojtas 			continue;
23324042910SMarcin Wojtas 		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
23424042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
23524042910SMarcin Wojtas 			break;
23624042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_IO:
23724042910SMarcin Wojtas 			error = rman_manage_region(&sc->sc_io_rman, rp->pci,
23824042910SMarcin Wojtas 			    rp->pci + rp->size - 1);
23924042910SMarcin Wojtas 			break;
24024042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_MEM32:
24124042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_MEM64:
24224042910SMarcin Wojtas 			if (rp->pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) {
24324042910SMarcin Wojtas 				sc->sc_have_pmem = 1;
24424042910SMarcin Wojtas 				error = rman_manage_region(&sc->sc_pmem_rman,
24524042910SMarcin Wojtas 				    rp->pci, rp->pci + rp->size - 1);
24624042910SMarcin Wojtas 			} else {
24724042910SMarcin Wojtas 				error = rman_manage_region(&sc->sc_mem_rman,
24824042910SMarcin Wojtas 				    rp->pci, rp->pci + rp->size - 1);
24924042910SMarcin Wojtas 			}
25024042910SMarcin Wojtas 			break;
25124042910SMarcin Wojtas 		}
25224042910SMarcin Wojtas 
25324042910SMarcin Wojtas 		if (error != 0) {
25424042910SMarcin Wojtas 			device_printf(dev,
25524042910SMarcin Wojtas 			    "rman_manage_region(%x, %#jx, %#jx) failed. "
25624042910SMarcin Wojtas 			    "error = %d\n", rp->pci_hi &
25724042910SMarcin Wojtas 			    OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
25824042910SMarcin Wojtas 			    rp->pci + rp->size - 1, error);
259b1e93132SAndrew Turner 			goto out_full;
26024042910SMarcin Wojtas 		}
26124042910SMarcin Wojtas 	}
26224042910SMarcin Wojtas 
26324042910SMarcin Wojtas 	ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
26424042910SMarcin Wojtas 	return (0);
26524042910SMarcin Wojtas 
266b1e93132SAndrew Turner out_full:
267b1e93132SAndrew Turner 	rman_fini(&sc->sc_pmem_rman);
268b1e93132SAndrew Turner out_pmem_rman:
269b1e93132SAndrew Turner 	rman_fini(&sc->sc_mem_rman);
270b1e93132SAndrew Turner out_mem_rman:
271b1e93132SAndrew Turner 	rman_fini(&sc->sc_io_rman);
27224042910SMarcin Wojtas out:
273b1e93132SAndrew Turner 	free(sc->sc_cell_info, M_DEVBUF);
274b1e93132SAndrew Turner 	free(sc->sc_range, M_DEVBUF);
275b1e93132SAndrew Turner 
276b1e93132SAndrew Turner 	return (error);
277b1e93132SAndrew Turner }
278b1e93132SAndrew Turner 
279b1e93132SAndrew Turner void
ofw_pcib_fini(device_t dev)280b1e93132SAndrew Turner ofw_pcib_fini(device_t dev)
281b1e93132SAndrew Turner {
282b1e93132SAndrew Turner 	struct ofw_pci_softc *sc;
283b1e93132SAndrew Turner 
284b1e93132SAndrew Turner 	sc = device_get_softc(dev);
285b1e93132SAndrew Turner 	free(sc->sc_cell_info, M_DEVBUF);
28624042910SMarcin Wojtas 	free(sc->sc_range, M_DEVBUF);
28724042910SMarcin Wojtas 	rman_fini(&sc->sc_io_rman);
28824042910SMarcin Wojtas 	rman_fini(&sc->sc_mem_rman);
28924042910SMarcin Wojtas 	rman_fini(&sc->sc_pmem_rman);
29024042910SMarcin Wojtas }
29124042910SMarcin Wojtas 
29224042910SMarcin Wojtas int
ofw_pcib_attach(device_t dev)29324042910SMarcin Wojtas ofw_pcib_attach(device_t dev)
29424042910SMarcin Wojtas {
29524042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
29624042910SMarcin Wojtas 	int error;
29724042910SMarcin Wojtas 
29824042910SMarcin Wojtas 	sc = device_get_softc(dev);
29924042910SMarcin Wojtas 	if (!sc->sc_initialized) {
30024042910SMarcin Wojtas 		error = ofw_pcib_init(dev);
30124042910SMarcin Wojtas 		if (error != 0)
30224042910SMarcin Wojtas 			return (error);
30324042910SMarcin Wojtas 	}
30424042910SMarcin Wojtas 
3055b56413dSWarner Losh 	device_add_child(dev, "pci", DEVICE_UNIT_ANY);
306*18250ec6SJohn Baldwin 	bus_attach_children(dev);
307*18250ec6SJohn Baldwin 	return (0);
30824042910SMarcin Wojtas }
30924042910SMarcin Wojtas 
31024042910SMarcin Wojtas static int
ofw_pcib_maxslots(device_t dev)31124042910SMarcin Wojtas ofw_pcib_maxslots(device_t dev)
31224042910SMarcin Wojtas {
31324042910SMarcin Wojtas 
31424042910SMarcin Wojtas 	return (PCI_SLOTMAX);
31524042910SMarcin Wojtas }
31624042910SMarcin Wojtas 
31724042910SMarcin Wojtas int
ofw_pcib_route_interrupt(device_t bus,device_t dev,int pin)31824042910SMarcin Wojtas ofw_pcib_route_interrupt(device_t bus, device_t dev, int pin)
31924042910SMarcin Wojtas {
32024042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
32124042910SMarcin Wojtas 	struct ofw_pci_register reg;
32224042910SMarcin Wojtas 	uint32_t pintr, mintr[PCI_MAP_INTR];
32324042910SMarcin Wojtas 	int intrcells;
32424042910SMarcin Wojtas 	phandle_t iparent;
32524042910SMarcin Wojtas 
32624042910SMarcin Wojtas 	sc = device_get_softc(bus);
32724042910SMarcin Wojtas 	pintr = pin;
32824042910SMarcin Wojtas 
32924042910SMarcin Wojtas 	/* Fabricate imap information in case this isn't an OFW device */
33024042910SMarcin Wojtas 	bzero(&reg, sizeof(reg));
33124042910SMarcin Wojtas 	reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
33224042910SMarcin Wojtas 	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
33324042910SMarcin Wojtas 	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
33424042910SMarcin Wojtas 
33524042910SMarcin Wojtas 	intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
33624042910SMarcin Wojtas 	    &sc->sc_pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
33724042910SMarcin Wojtas 	    mintr, sizeof(mintr), &iparent);
33824042910SMarcin Wojtas 	if (intrcells != 0) {
33924042910SMarcin Wojtas 		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
34024042910SMarcin Wojtas 		return (pintr);
34124042910SMarcin Wojtas 	}
34224042910SMarcin Wojtas 
34324042910SMarcin Wojtas 	/*
34424042910SMarcin Wojtas 	 * Maybe it's a real interrupt, not an intpin
34524042910SMarcin Wojtas 	 */
34624042910SMarcin Wojtas 	if (pin > PCI_INTR_PINS)
34724042910SMarcin Wojtas 		return (pin);
34824042910SMarcin Wojtas 
34924042910SMarcin Wojtas 	device_printf(bus, "could not route pin %d for device %d.%d\n",
35024042910SMarcin Wojtas 	    pin, pci_get_slot(dev), pci_get_function(dev));
35124042910SMarcin Wojtas 	return (PCI_INVALID_IRQ);
35224042910SMarcin Wojtas }
35324042910SMarcin Wojtas 
35424042910SMarcin Wojtas int
ofw_pcib_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)35524042910SMarcin Wojtas ofw_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
35624042910SMarcin Wojtas {
35724042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
35824042910SMarcin Wojtas 
35924042910SMarcin Wojtas 	sc = device_get_softc(dev);
36024042910SMarcin Wojtas 
36124042910SMarcin Wojtas 	switch (which) {
36224042910SMarcin Wojtas 	case PCIB_IVAR_DOMAIN:
36324042910SMarcin Wojtas 		*result = sc->sc_pci_domain;
36424042910SMarcin Wojtas 		return (0);
36524042910SMarcin Wojtas 	case PCIB_IVAR_BUS:
36624042910SMarcin Wojtas 		*result = sc->sc_bus;
36724042910SMarcin Wojtas 		return (0);
36824042910SMarcin Wojtas 	default:
36924042910SMarcin Wojtas 		break;
37024042910SMarcin Wojtas 	}
37124042910SMarcin Wojtas 
37224042910SMarcin Wojtas 	return (ENOENT);
37324042910SMarcin Wojtas }
37424042910SMarcin Wojtas 
37524042910SMarcin Wojtas int
ofw_pcib_write_ivar(device_t dev,device_t child,int which,uintptr_t value)37624042910SMarcin Wojtas ofw_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
37724042910SMarcin Wojtas {
37824042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
37924042910SMarcin Wojtas 
38024042910SMarcin Wojtas 	sc = device_get_softc(dev);
38124042910SMarcin Wojtas 
38224042910SMarcin Wojtas 	switch (which) {
38324042910SMarcin Wojtas 	case PCIB_IVAR_BUS:
38424042910SMarcin Wojtas 		sc->sc_bus = value;
38524042910SMarcin Wojtas 		return (0);
38624042910SMarcin Wojtas 	default:
38724042910SMarcin Wojtas 		break;
38824042910SMarcin Wojtas 	}
38924042910SMarcin Wojtas 
39024042910SMarcin Wojtas 	return (ENOENT);
39124042910SMarcin Wojtas }
39224042910SMarcin Wojtas 
39324042910SMarcin Wojtas int
ofw_pcib_nranges(phandle_t node,struct ofw_pci_cell_info * info)39424042910SMarcin Wojtas ofw_pcib_nranges(phandle_t node, struct ofw_pci_cell_info *info)
39524042910SMarcin Wojtas {
39624042910SMarcin Wojtas 	ssize_t nbase_ranges;
39724042910SMarcin Wojtas 
39824042910SMarcin Wojtas 	if (info == NULL)
39924042910SMarcin Wojtas 		return (-1);
40024042910SMarcin Wojtas 
40124042910SMarcin Wojtas 	info->host_address_cells = 1;
40224042910SMarcin Wojtas 	info->size_cells = 2;
40324042910SMarcin Wojtas 	info->pci_address_cell = 3;
40424042910SMarcin Wojtas 
40524042910SMarcin Wojtas 	OF_getencprop(OF_parent(node), "#address-cells",
40624042910SMarcin Wojtas 	    &(info->host_address_cells), sizeof(info->host_address_cells));
40724042910SMarcin Wojtas 	OF_getencprop(node, "#address-cells",
40824042910SMarcin Wojtas 	    &(info->pci_address_cell), sizeof(info->pci_address_cell));
40924042910SMarcin Wojtas 	OF_getencprop(node, "#size-cells", &(info->size_cells),
41024042910SMarcin Wojtas 	    sizeof(info->size_cells));
41124042910SMarcin Wojtas 
41224042910SMarcin Wojtas 	nbase_ranges = OF_getproplen(node, "ranges");
41324042910SMarcin Wojtas 	if (nbase_ranges <= 0)
41424042910SMarcin Wojtas 		return (-1);
41524042910SMarcin Wojtas 
41624042910SMarcin Wojtas 	return (nbase_ranges / sizeof(cell_t) /
41724042910SMarcin Wojtas 	    (info->pci_address_cell + info->host_address_cells +
41824042910SMarcin Wojtas 	    info->size_cells));
41924042910SMarcin Wojtas }
42024042910SMarcin Wojtas 
42124042910SMarcin Wojtas static struct resource *
ofw_pcib_alloc_resource(device_t bus,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)42224042910SMarcin Wojtas ofw_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid,
42324042910SMarcin Wojtas     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
42424042910SMarcin Wojtas {
42524042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
42624042910SMarcin Wojtas 
42724042910SMarcin Wojtas 	sc = device_get_softc(bus);
4280b60d7a6SJohn Baldwin 	switch (type) {
4290b60d7a6SJohn Baldwin 	case PCI_RES_BUS:
4300b60d7a6SJohn Baldwin 		return (pci_domain_alloc_bus(sc->sc_pci_domain, child, rid,
4310b60d7a6SJohn Baldwin 		    start, end, count, flags));
4320b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
4330b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
4340b60d7a6SJohn Baldwin 		return (bus_generic_rman_alloc_resource(bus, child, type, rid,
4350b60d7a6SJohn Baldwin 		    start, end, count, flags));
4360b60d7a6SJohn Baldwin 	default:
43724042910SMarcin Wojtas 		return (bus_generic_alloc_resource(bus, child, type, rid,
4380b60d7a6SJohn Baldwin 		    start, end, count, flags));
43924042910SMarcin Wojtas 	}
44024042910SMarcin Wojtas }
44124042910SMarcin Wojtas 
44224042910SMarcin Wojtas static int
ofw_pcib_release_resource(device_t bus,device_t child,struct resource * res)4439dbf5b0eSJohn Baldwin ofw_pcib_release_resource(device_t bus, device_t child, struct resource *res)
44424042910SMarcin Wojtas {
44524042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
44624042910SMarcin Wojtas 
44724042910SMarcin Wojtas 	sc = device_get_softc(bus);
4489dbf5b0eSJohn Baldwin 	switch (rman_get_type(res)) {
4490b60d7a6SJohn Baldwin 	case PCI_RES_BUS:
4509dbf5b0eSJohn Baldwin 		return (pci_domain_release_bus(sc->sc_pci_domain, child, res));
4510b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
4520b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
4539dbf5b0eSJohn Baldwin 		return (bus_generic_rman_release_resource(bus, child, res));
4540b60d7a6SJohn Baldwin 	default:
4559dbf5b0eSJohn Baldwin 		return (bus_generic_release_resource(bus, child, res));
45624042910SMarcin Wojtas 	}
45724042910SMarcin Wojtas }
45824042910SMarcin Wojtas 
45924042910SMarcin Wojtas static int
ofw_pcib_translate_resource(device_t bus,int type,rman_res_t start,rman_res_t * newstart)46024042910SMarcin Wojtas ofw_pcib_translate_resource(device_t bus, int type, rman_res_t start,
46124042910SMarcin Wojtas 	rman_res_t *newstart)
46224042910SMarcin Wojtas {
46324042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
46424042910SMarcin Wojtas 	struct ofw_pci_range *rp;
46524042910SMarcin Wojtas 	int space;
46624042910SMarcin Wojtas 
46724042910SMarcin Wojtas 	sc = device_get_softc(bus);
46824042910SMarcin Wojtas 
46924042910SMarcin Wojtas 	/*
47024042910SMarcin Wojtas 	 * Map this through the ranges list
47124042910SMarcin Wojtas 	 */
47224042910SMarcin Wojtas 	for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
47324042910SMarcin Wojtas 	    rp->pci_hi != 0; rp++) {
47424042910SMarcin Wojtas 		if (start < rp->pci || start >= rp->pci + rp->size)
47524042910SMarcin Wojtas 			continue;
47624042910SMarcin Wojtas 
47724042910SMarcin Wojtas 		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
47824042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_IO:
47924042910SMarcin Wojtas 			space = SYS_RES_IOPORT;
48024042910SMarcin Wojtas 			break;
48124042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_MEM32:
48224042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_MEM64:
48324042910SMarcin Wojtas 			space = SYS_RES_MEMORY;
48424042910SMarcin Wojtas 			break;
48524042910SMarcin Wojtas 		default:
48624042910SMarcin Wojtas 			space = -1;
48724042910SMarcin Wojtas 		}
48824042910SMarcin Wojtas 
48924042910SMarcin Wojtas 		if (type == space) {
49024042910SMarcin Wojtas 			start += (rp->host - rp->pci);
49124042910SMarcin Wojtas 			*newstart = start;
49224042910SMarcin Wojtas 			return (0);
49324042910SMarcin Wojtas 		}
4941fb99e97SMark Johnston 	}
4951fb99e97SMark Johnston 	return (ENOENT);
4961fb99e97SMark Johnston }
49724042910SMarcin Wojtas 
49824042910SMarcin Wojtas static int
ofw_pcib_activate_resource(device_t bus,device_t child,struct resource * res)4992baed46eSJohn Baldwin ofw_pcib_activate_resource(device_t bus, device_t child, struct resource *res)
50024042910SMarcin Wojtas {
50124042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
50224042910SMarcin Wojtas 
50324042910SMarcin Wojtas 	sc = device_get_softc(bus);
5042baed46eSJohn Baldwin 	switch (rman_get_type(res)) {
5050b60d7a6SJohn Baldwin 	case PCI_RES_BUS:
5062baed46eSJohn Baldwin 		return (pci_domain_activate_bus(sc->sc_pci_domain, child, res));
5070b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
5080b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
5092baed46eSJohn Baldwin 		return (bus_generic_rman_activate_resource(bus, child, res));
5100b60d7a6SJohn Baldwin 	default:
5112baed46eSJohn Baldwin 		return (bus_generic_activate_resource(bus, child, res));
51224042910SMarcin Wojtas 	}
5130b60d7a6SJohn Baldwin }
51424042910SMarcin Wojtas 
5150b60d7a6SJohn Baldwin static int
ofw_pcib_map_resource(device_t dev,device_t child,struct resource * r,struct resource_map_request * argsp,struct resource_map * map)516d77f2092SJohn Baldwin ofw_pcib_map_resource(device_t dev, device_t child, struct resource *r,
517d77f2092SJohn Baldwin     struct resource_map_request *argsp, struct resource_map *map)
5180b60d7a6SJohn Baldwin {
5190b60d7a6SJohn Baldwin 	struct resource_map_request args;
5200b60d7a6SJohn Baldwin 	struct ofw_pci_softc *sc;
5210b60d7a6SJohn Baldwin 	struct ofw_pci_range *rp;
5220b60d7a6SJohn Baldwin 	rman_res_t length, start;
5230b60d7a6SJohn Baldwin 	int error, space;
5240b60d7a6SJohn Baldwin 
5250b60d7a6SJohn Baldwin 	/* Resources must be active to be mapped. */
5260b60d7a6SJohn Baldwin 	if (!(rman_get_flags(r) & RF_ACTIVE))
5270b60d7a6SJohn Baldwin 		return (ENXIO);
5280b60d7a6SJohn Baldwin 
529d77f2092SJohn Baldwin 	switch (rman_get_type(r)) {
5300b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
5310b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
5320b60d7a6SJohn Baldwin 		break;
5330b60d7a6SJohn Baldwin 	default:
5340b60d7a6SJohn Baldwin 		return (EINVAL);
5350b60d7a6SJohn Baldwin 	}
5360b60d7a6SJohn Baldwin 
5370b60d7a6SJohn Baldwin 	resource_init_map_request(&args);
5380b60d7a6SJohn Baldwin 	error = resource_validate_map_request(r, argsp, &args, &start, &length);
5390b60d7a6SJohn Baldwin 	if (error)
5400b60d7a6SJohn Baldwin 		return (error);
54124042910SMarcin Wojtas 
54224042910SMarcin Wojtas 	/*
54324042910SMarcin Wojtas 	 * Map this through the ranges list
54424042910SMarcin Wojtas 	 */
5450b60d7a6SJohn Baldwin 	sc = device_get_softc(dev);
54624042910SMarcin Wojtas 	for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
54724042910SMarcin Wojtas 	    rp->pci_hi != 0; rp++) {
54824042910SMarcin Wojtas 		if (start < rp->pci || start >= rp->pci + rp->size)
54924042910SMarcin Wojtas 			continue;
55024042910SMarcin Wojtas 
55124042910SMarcin Wojtas 		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
55224042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_IO:
55324042910SMarcin Wojtas 			space = SYS_RES_IOPORT;
55424042910SMarcin Wojtas 			break;
55524042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_MEM32:
55624042910SMarcin Wojtas 		case OFW_PCI_PHYS_HI_SPACE_MEM64:
55724042910SMarcin Wojtas 			space = SYS_RES_MEMORY;
55824042910SMarcin Wojtas 			break;
55924042910SMarcin Wojtas 		default:
56024042910SMarcin Wojtas 			space = -1;
56124042910SMarcin Wojtas 		}
56224042910SMarcin Wojtas 
563d77f2092SJohn Baldwin 		if (rman_get_type(r) == space) {
56424042910SMarcin Wojtas 			start += (rp->host - rp->pci);
56524042910SMarcin Wojtas 			break;
56624042910SMarcin Wojtas 		}
56724042910SMarcin Wojtas 	}
56824042910SMarcin Wojtas 
56924042910SMarcin Wojtas 	if (bootverbose)
5700b60d7a6SJohn Baldwin 		printf("ofw_pci mapdev: start %jx, len %jd\n", start, length);
57124042910SMarcin Wojtas 
5720b60d7a6SJohn Baldwin 	map->r_bustag = BUS_GET_BUS_TAG(child, child);
5730b60d7a6SJohn Baldwin 	if (map->r_bustag == NULL)
57424042910SMarcin Wojtas 		return (ENOMEM);
57524042910SMarcin Wojtas 
5760b60d7a6SJohn Baldwin 	error = bus_space_map(map->r_bustag, start, length, 0,
5770b60d7a6SJohn Baldwin 	    &map->r_bushandle);
5780b60d7a6SJohn Baldwin 	if (error != 0)
5790b60d7a6SJohn Baldwin 		return (error);
58024042910SMarcin Wojtas 
5810b60d7a6SJohn Baldwin 	/* XXX for powerpc only? */
5820b60d7a6SJohn Baldwin 	map->r_vaddr = (void *)map->r_bushandle;
5830b60d7a6SJohn Baldwin 	map->r_size = length;
5840b60d7a6SJohn Baldwin 	return (0);
5850b60d7a6SJohn Baldwin }
58624042910SMarcin Wojtas 
5870b60d7a6SJohn Baldwin static int
ofw_pcib_unmap_resource(device_t dev,device_t child,struct resource * r,struct resource_map * map)588d77f2092SJohn Baldwin ofw_pcib_unmap_resource(device_t dev, device_t child, struct resource *r,
589d77f2092SJohn Baldwin     struct resource_map *map)
5900b60d7a6SJohn Baldwin {
591d77f2092SJohn Baldwin 	switch (rman_get_type(r)) {
5920b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
5930b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
5940b60d7a6SJohn Baldwin 		bus_space_unmap(map->r_bustag, map->r_bushandle, map->r_size);
5950b60d7a6SJohn Baldwin 		return (0);
5960b60d7a6SJohn Baldwin 	default:
5970b60d7a6SJohn Baldwin 		return (EINVAL);
5980b60d7a6SJohn Baldwin 	}
59924042910SMarcin Wojtas }
60024042910SMarcin Wojtas 
60124042910SMarcin Wojtas #ifdef __powerpc__
60224042910SMarcin Wojtas static bus_space_tag_t
ofw_pcib_bus_get_bus_tag(device_t bus,device_t child)60324042910SMarcin Wojtas ofw_pcib_bus_get_bus_tag(device_t bus, device_t child)
60424042910SMarcin Wojtas {
60524042910SMarcin Wojtas 
60624042910SMarcin Wojtas 	return (&bs_le_tag);
60724042910SMarcin Wojtas }
60824042910SMarcin Wojtas #endif
60924042910SMarcin Wojtas 
61024042910SMarcin Wojtas static int
ofw_pcib_deactivate_resource(device_t bus,device_t child,struct resource * res)6112baed46eSJohn Baldwin ofw_pcib_deactivate_resource(device_t bus, device_t child, struct resource *res)
61224042910SMarcin Wojtas {
6130b60d7a6SJohn Baldwin 	struct ofw_pci_softc *sc;
61424042910SMarcin Wojtas 
6150b60d7a6SJohn Baldwin 	sc = device_get_softc(bus);
6162baed46eSJohn Baldwin 	switch (rman_get_type(res)) {
6170b60d7a6SJohn Baldwin 	case PCI_RES_BUS:
6182baed46eSJohn Baldwin 		return (pci_domain_deactivate_bus(sc->sc_pci_domain, child,
6190b60d7a6SJohn Baldwin 		    res));
6200b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
6210b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
6222baed46eSJohn Baldwin 		return (bus_generic_rman_deactivate_resource(bus, child, res));
6230b60d7a6SJohn Baldwin 	default:
6242baed46eSJohn Baldwin 		return (bus_generic_deactivate_resource(bus, child, res));
62524042910SMarcin Wojtas 	}
62624042910SMarcin Wojtas }
62724042910SMarcin Wojtas 
62824042910SMarcin Wojtas static int
ofw_pcib_adjust_resource(device_t bus,device_t child,struct resource * res,rman_res_t start,rman_res_t end)629fef01f04SJohn Baldwin ofw_pcib_adjust_resource(device_t bus, device_t child,
63024042910SMarcin Wojtas     struct resource *res, rman_res_t start, rman_res_t end)
63124042910SMarcin Wojtas {
63224042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
63324042910SMarcin Wojtas 
63424042910SMarcin Wojtas 	sc = device_get_softc(bus);
635fef01f04SJohn Baldwin 	switch (rman_get_type(res)) {
6360b60d7a6SJohn Baldwin 	case PCI_RES_BUS:
63724042910SMarcin Wojtas 		return (pci_domain_adjust_bus(sc->sc_pci_domain, child, res,
63824042910SMarcin Wojtas 		    start, end));
6390b60d7a6SJohn Baldwin 	case SYS_RES_MEMORY:
6400b60d7a6SJohn Baldwin 	case SYS_RES_IOPORT:
641fef01f04SJohn Baldwin 		return (bus_generic_rman_adjust_resource(bus, child, res,
6420b60d7a6SJohn Baldwin 		    start, end));
6430b60d7a6SJohn Baldwin 	default:
644fef01f04SJohn Baldwin 		return (bus_generic_adjust_resource(bus, child, res, start,
645fef01f04SJohn Baldwin 		    end));
64624042910SMarcin Wojtas 	}
64724042910SMarcin Wojtas }
64824042910SMarcin Wojtas 
64924042910SMarcin Wojtas static phandle_t
ofw_pcib_get_node(device_t bus,device_t dev)65024042910SMarcin Wojtas ofw_pcib_get_node(device_t bus, device_t dev)
65124042910SMarcin Wojtas {
65224042910SMarcin Wojtas 	struct ofw_pci_softc *sc;
65324042910SMarcin Wojtas 
65424042910SMarcin Wojtas 	sc = device_get_softc(bus);
65524042910SMarcin Wojtas 	/* We only have one child, the PCI bus, which needs our own node. */
65624042910SMarcin Wojtas 
65724042910SMarcin Wojtas 	return (sc->sc_node);
65824042910SMarcin Wojtas }
65924042910SMarcin Wojtas 
66024042910SMarcin Wojtas static int
ofw_pcib_fill_ranges(phandle_t node,struct ofw_pci_range * ranges)66124042910SMarcin Wojtas ofw_pcib_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
66224042910SMarcin Wojtas {
66324042910SMarcin Wojtas 	int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
66424042910SMarcin Wojtas 	cell_t *base_ranges;
66524042910SMarcin Wojtas 	ssize_t nbase_ranges;
66624042910SMarcin Wojtas 	int nranges;
66724042910SMarcin Wojtas 	int i, j, k;
66824042910SMarcin Wojtas 
66924042910SMarcin Wojtas 	OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
67024042910SMarcin Wojtas 	    sizeof(host_address_cells));
67124042910SMarcin Wojtas 	OF_getencprop(node, "#address-cells", &pci_address_cells,
67224042910SMarcin Wojtas 	    sizeof(pci_address_cells));
67324042910SMarcin Wojtas 	OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
67424042910SMarcin Wojtas 
67524042910SMarcin Wojtas 	nbase_ranges = OF_getproplen(node, "ranges");
67624042910SMarcin Wojtas 	if (nbase_ranges <= 0)
67724042910SMarcin Wojtas 		return (-1);
67824042910SMarcin Wojtas 	nranges = nbase_ranges / sizeof(cell_t) /
67924042910SMarcin Wojtas 	    (pci_address_cells + host_address_cells + size_cells);
68024042910SMarcin Wojtas 
68124042910SMarcin Wojtas 	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
68224042910SMarcin Wojtas 	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
68324042910SMarcin Wojtas 
68424042910SMarcin Wojtas 	for (i = 0, j = 0; i < nranges; i++) {
68524042910SMarcin Wojtas 		ranges[i].pci_hi = base_ranges[j++];
68624042910SMarcin Wojtas 		ranges[i].pci = 0;
68724042910SMarcin Wojtas 		for (k = 0; k < pci_address_cells - 1; k++) {
68824042910SMarcin Wojtas 			ranges[i].pci <<= 32;
68924042910SMarcin Wojtas 			ranges[i].pci |= base_ranges[j++];
69024042910SMarcin Wojtas 		}
69124042910SMarcin Wojtas 		ranges[i].host = 0;
69224042910SMarcin Wojtas 		for (k = 0; k < host_address_cells; k++) {
69324042910SMarcin Wojtas 			ranges[i].host <<= 32;
69424042910SMarcin Wojtas 			ranges[i].host |= base_ranges[j++];
69524042910SMarcin Wojtas 		}
69624042910SMarcin Wojtas 		ranges[i].size = 0;
69724042910SMarcin Wojtas 		for (k = 0; k < size_cells; k++) {
69824042910SMarcin Wojtas 			ranges[i].size <<= 32;
69924042910SMarcin Wojtas 			ranges[i].size |= base_ranges[j++];
70024042910SMarcin Wojtas 		}
70124042910SMarcin Wojtas 	}
70224042910SMarcin Wojtas 
70324042910SMarcin Wojtas 	free(base_ranges, M_DEVBUF);
70424042910SMarcin Wojtas 	return (nranges);
70524042910SMarcin Wojtas }
70624042910SMarcin Wojtas 
70724042910SMarcin Wojtas static struct rman *
ofw_pcib_get_rman(device_t bus,int type,u_int flags)7080b60d7a6SJohn Baldwin ofw_pcib_get_rman(device_t bus, int type, u_int flags)
70924042910SMarcin Wojtas {
7100b60d7a6SJohn Baldwin 	struct ofw_pci_softc *sc;
71124042910SMarcin Wojtas 
7120b60d7a6SJohn Baldwin 	sc = device_get_softc(bus);
71324042910SMarcin Wojtas 	switch (type) {
71424042910SMarcin Wojtas 	case SYS_RES_IOPORT:
71524042910SMarcin Wojtas 		return (&sc->sc_io_rman);
71624042910SMarcin Wojtas 	case SYS_RES_MEMORY:
71724042910SMarcin Wojtas 		if (sc->sc_have_pmem  && (flags & RF_PREFETCHABLE))
71824042910SMarcin Wojtas 			return (&sc->sc_pmem_rman);
71924042910SMarcin Wojtas 		else
72024042910SMarcin Wojtas 			return (&sc->sc_mem_rman);
72124042910SMarcin Wojtas 	default:
72224042910SMarcin Wojtas 		break;
72324042910SMarcin Wojtas 	}
72424042910SMarcin Wojtas 
72524042910SMarcin Wojtas 	return (NULL);
72624042910SMarcin Wojtas }
727