diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index aefca024124f..763c1130b581 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -227,6 +227,7 @@ powerpc/pseries/phyp_llan.c optional llan powerpc/pseries/phyp_vscsi.c optional pseries powerpc64 scbus powerpc/pseries/platform_chrp.c optional pseries powerpc/pseries/plpar_iommu.c optional pseries powerpc64 +powerpc/pseries/plpar_pcibus.c optional pseries powerpc64 pci powerpc/pseries/rtas_dev.c optional pseries powerpc/pseries/rtas_pci.c optional pseries pci powerpc/pseries/vdevice.c optional pseries powerpc64 diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c index 63c327c2efa9..f1063a1f41af 100644 --- a/sys/powerpc/ofw/ofw_pcibus.c +++ b/sys/powerpc/ofw/ofw_pcibus.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include "ofw_pcibus.h" #include "pcib_if.h" #include "pci_if.h" @@ -85,12 +86,7 @@ static device_method_t ofw_pcibus_methods[] = { DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), - { 0, 0 } -}; - -struct ofw_pcibus_devinfo { - struct pci_devinfo opd_dinfo; - struct ofw_bus_devinfo opd_obdinfo; + DEVMETHOD_END }; static devclass_t pci_devclass; @@ -195,6 +191,7 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) pci_freecfg((struct pci_devinfo *)dinfo); continue; } + dinfo->opd_dma_tag = NULL; pci_add_child(dev, (struct pci_devinfo *)dinfo); /* @@ -272,6 +269,7 @@ ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno) if (dinfo == NULL) continue; + dinfo->opd_dma_tag = NULL; dinfo->opd_obdinfo.obd_node = -1; dinfo->opd_obdinfo.obd_name = NULL; diff --git a/sys/powerpc/ofw/ofw_pcibus.h b/sys/powerpc/ofw/ofw_pcibus.h new file mode 100644 index 000000000000..c7b82d7ebdd2 --- /dev/null +++ b/sys/powerpc/ofw/ofw_pcibus.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2011 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef POWERPC_OFW_OFW_PCIBUS_H +#define POWERPC_OFW_OFW_PCIBUS_H + +#include +#include + +#include +#include +#include + +/* + * Export class definition for inheritance purposes + */ +DECLARE_CLASS(ofw_pcibus_driver); /* PCI Bus Enumerators */ + +struct ofw_pcibus_devinfo { + struct pci_devinfo opd_dinfo; + struct ofw_bus_devinfo opd_obdinfo; + bus_dma_tag_t opd_dma_tag; +}; + +#endif // POWERPC_OFW_OFW_PCIBUS_H + diff --git a/sys/powerpc/pseries/plpar_pcibus.c b/sys/powerpc/pseries/plpar_pcibus.c new file mode 100644 index 000000000000..640212f53f1a --- /dev/null +++ b/sys/powerpc/pseries/plpar_pcibus.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2011 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include "pci_if.h" +#include "iommu_if.h" + +static int plpar_pcibus_probe(device_t); +static bus_dma_tag_t plpar_pcibus_get_dma_tag(device_t dev, device_t child); + +/* + * Driver methods. + */ +static device_method_t plpar_pcibus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, plpar_pcibus_probe), + + /* IOMMU functions */ + DEVMETHOD(bus_get_dma_tag, plpar_pcibus_get_dma_tag), + DEVMETHOD(iommu_map, phyp_iommu_map), + DEVMETHOD(iommu_unmap, phyp_iommu_unmap), + + DEVMETHOD_END +}; + +static devclass_t pci_devclass; +DEFINE_CLASS_1(pci, plpar_pcibus_driver, plpar_pcibus_methods, + sizeof(struct pci_softc), ofw_pcibus_driver); +DRIVER_MODULE(plpar_pcibus, pcib, plpar_pcibus_driver, pci_devclass, 0, 0); + +static int +plpar_pcibus_probe(device_t dev) +{ + phandle_t rtas; + + if (ofw_bus_get_node(dev) == -1 || !rtas_exists()) + return (ENXIO); + + rtas = OF_finddevice("/rtas"); + if (!OF_hasprop(rtas, "ibm,hypertas-functions")) + return (ENXIO); + + device_set_desc(dev, "POWER Hypervisor PCI bus"); + + return (BUS_PROBE_SPECIFIC); +} + +static bus_dma_tag_t +plpar_pcibus_get_dma_tag(device_t dev, device_t child) +{ + struct ofw_pcibus_devinfo *dinfo; + + while (device_get_parent(child) != dev) + child = device_get_parent(child); + + dinfo = device_get_ivars(child); + + if (dinfo->opd_dma_tag != NULL) + return (dinfo->opd_dma_tag); + + bus_dma_tag_create(bus_get_dma_tag(dev), + 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, + BUS_SPACE_MAXSIZE, 0, NULL, NULL, &dinfo->opd_dma_tag); + phyp_iommu_set_dma_tag(dev, child, dinfo->opd_dma_tag); + + return (dinfo->opd_dma_tag); +} + diff --git a/sys/powerpc/pseries/rtas_pci.c b/sys/powerpc/pseries/rtas_pci.c index f3e9a29a655b..0835a279e75f 100644 --- a/sys/powerpc/pseries/rtas_pci.c +++ b/sys/powerpc/pseries/rtas_pci.c @@ -73,11 +73,6 @@ static u_int32_t rtaspci_read_config(device_t, u_int, u_int, u_int, static void rtaspci_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t, int); -/* - * IOMMU LPAR interface - */ -static bus_dma_tag_t rtaspci_get_dma_tag(device_t dev, device_t child); - /* * Driver methods. */ @@ -90,19 +85,11 @@ static device_method_t rtaspci_methods[] = { DEVMETHOD(pcib_read_config, rtaspci_read_config), DEVMETHOD(pcib_write_config, rtaspci_write_config), - /* IOMMU functions */ - DEVMETHOD(bus_get_dma_tag, rtaspci_get_dma_tag), -#ifdef __powerpc64__ - DEVMETHOD(iommu_map, phyp_iommu_map), - DEVMETHOD(iommu_unmap, phyp_iommu_unmap), -#endif - DEVMETHOD_END }; struct rtaspci_softc { struct ofw_pci_softc pci_sc; - bus_dma_tag_t dma_tag; cell_t read_pci_config, write_pci_config; cell_t ex_read_pci_config, ex_write_pci_config; @@ -149,15 +136,6 @@ rtaspci_attach(device_t dev) OF_getprop(ofw_bus_get_node(dev), "ibm,pci-config-space-type", &sc->sc_extended_config, sizeof(sc->sc_extended_config)); - bus_dma_tag_create(bus_get_dma_tag(dev), - 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, - BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->dma_tag); -#ifdef __powerpc64__ - if (!(mfmsr() & PSL_HV)) - phyp_iommu_set_dma_tag(dev, dev, sc->dma_tag); -#endif - return (ofw_pci_attach(dev)); } @@ -225,12 +203,3 @@ rtaspci_write_config(device_t dev, u_int bus, u_int slot, u_int func, width, val, &pcierror); } -static bus_dma_tag_t -rtaspci_get_dma_tag(device_t dev, device_t child) -{ - struct rtaspci_softc *sc; - - sc = device_get_softc(dev); - return (sc->dma_tag); -} -