From owner-svn-src-all@freebsd.org Sun Dec 27 19:37:49 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E2668A53B56; Sun, 27 Dec 2015 19:37:49 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 7917D13A0; Sun, 27 Dec 2015 19:37:49 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBRJbm8f067942; Sun, 27 Dec 2015 19:37:48 GMT (envelope-from marius@FreeBSD.org) Received: (from marius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBRJblN0067934; Sun, 27 Dec 2015 19:37:47 GMT (envelope-from marius@FreeBSD.org) Message-Id: <201512271937.tBRJblN0067934@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: marius set sender to marius@FreeBSD.org using -f From: Marius Strobl Date: Sun, 27 Dec 2015 19:37:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r292789 - in stable/10/sys: conf sparc64/pci X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Dec 2015 19:37:50 -0000 Author: marius Date: Sun Dec 27 19:37:47 2015 New Revision: 292789 URL: https://svnweb.freebsd.org/changeset/base/292789 Log: MFC: r287726 - Factor out the common and generic parts of the sparc64 host-PCI-bridge drivers into the revived sys/sparc64/pci/ofw_pci.c, previously already serving a similar purpose. This has been done with sun4v in mind, which explains a) the otherwise not that obvious scheme employed and b) why reusing sys/powerpc/ofw/ofw_pci.c was even lesser an option. - Add a workaround for QEMU once again not emulating real machines, in this case by not providing the OFW_PCI_CS_MEM64 range. [1] Submitted by: jhb [1] Added: stable/10/sys/sparc64/pci/ofw_pci.c - copied, changed from r287726, head/sys/sparc64/pci/ofw_pci.c Modified: stable/10/sys/conf/files.sparc64 stable/10/sys/sparc64/pci/fire.c stable/10/sys/sparc64/pci/firereg.h stable/10/sys/sparc64/pci/firevar.h stable/10/sys/sparc64/pci/ofw_pci.h stable/10/sys/sparc64/pci/psycho.c stable/10/sys/sparc64/pci/psychoreg.h stable/10/sys/sparc64/pci/psychovar.h stable/10/sys/sparc64/pci/schizo.c stable/10/sys/sparc64/pci/schizoreg.h stable/10/sys/sparc64/pci/schizovar.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/conf/files.sparc64 ============================================================================== --- stable/10/sys/conf/files.sparc64 Sun Dec 27 18:12:13 2015 (r292788) +++ stable/10/sys/conf/files.sparc64 Sun Dec 27 19:37:47 2015 (r292789) @@ -81,6 +81,7 @@ sparc64/isa/isa_dma.c optional isa sparc64/isa/ofw_isa.c optional ebus | isa sparc64/pci/apb.c optional pci sparc64/pci/fire.c optional pci +sparc64/pci/ofw_pci.c optional pci sparc64/pci/ofw_pcib.c optional pci sparc64/pci/ofw_pcib_subr.c optional pci sparc64/pci/ofw_pcibus.c optional pci Modified: stable/10/sys/sparc64/pci/fire.c ============================================================================== --- stable/10/sys/sparc64/pci/fire.c Sun Dec 27 18:12:13 2015 (r292788) +++ stable/10/sys/sparc64/pci/fire.c Sun Dec 27 19:37:47 2015 (r292789) @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -68,7 +67,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -111,19 +109,14 @@ static driver_filter_t fire_xcb; /* * Methods */ -static bus_activate_resource_t fire_activate_resource; -static bus_adjust_resource_t fire_adjust_resource; static pcib_alloc_msi_t fire_alloc_msi; static pcib_alloc_msix_t fire_alloc_msix; static bus_alloc_resource_t fire_alloc_resource; static device_attach_t fire_attach; -static bus_get_dma_tag_t fire_get_dma_tag; -static ofw_bus_get_node_t fire_get_node; static pcib_map_msi_t fire_map_msi; static pcib_maxslots_t fire_maxslots; static device_probe_t fire_probe; static pcib_read_config_t fire_read_config; -static bus_read_ivar_t fire_read_ivar; static pcib_release_msi_t fire_release_msi; static pcib_release_msix_t fire_release_msix; static pcib_route_interrupt_t fire_route_interrupt; @@ -140,15 +133,15 @@ static device_method_t fire_methods[] = DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ - DEVMETHOD(bus_read_ivar, fire_read_ivar), + DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar), DEVMETHOD(bus_setup_intr, fire_setup_intr), DEVMETHOD(bus_teardown_intr, fire_teardown_intr), DEVMETHOD(bus_alloc_resource, fire_alloc_resource), - DEVMETHOD(bus_activate_resource, fire_activate_resource), + DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_adjust_resource, fire_adjust_resource), + DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_get_dma_tag, fire_get_dma_tag), + DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag), /* pcib interface */ DEVMETHOD(pcib_maxslots, fire_maxslots), @@ -162,7 +155,7 @@ static device_method_t fire_methods[] = DEVMETHOD(pcib_map_msi, fire_map_msi), /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_node, fire_get_node), + DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node), DEVMETHOD_END }; @@ -296,7 +289,7 @@ fire_attach(device_t dev) struct ofw_pci_msi_eq_to_devino msi_eq_to_devino; struct fire_msiqarg *fmqa; struct timecounter *tc; - struct ofw_pci_ranges *range; + bus_dma_tag_t dmat; uint64_t ino_bitmap, val; phandle_t node; uint32_t prop, prop_array[2]; @@ -310,7 +303,6 @@ fire_attach(device_t dev) mode = desc->fd_mode; sc->sc_dev = dev; - sc->sc_node = node; sc->sc_mode = mode; sc->sc_flags = 0; @@ -715,81 +707,21 @@ fire_attach(device_t dev) sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_mem_res[FIRE_PCI]); sc->sc_is.is_iommu = FO_PCI_MMU; val = FIRE_PCI_READ_8(sc, FO_PCI_MMU + IMR_CTL); - iommu_init(device_get_nameunit(sc->sc_dev), &sc->sc_is, 7, -1, 0); + iommu_init(device_get_nameunit(dev), &sc->sc_is, 7, -1, 0); #ifdef FIRE_DEBUG device_printf(dev, "FO_PCI_MMU + IMR_CTL 0x%016llx -> 0x%016llx\n", (long long unsigned)val, (long long unsigned)sc->sc_is.is_cr); #endif - - /* Initialize memory and I/O rmans. */ - sc->sc_pci_io_rman.rm_type = RMAN_ARRAY; - sc->sc_pci_io_rman.rm_descr = "Fire PCI I/O Ports"; - if (rman_init(&sc->sc_pci_io_rman) != 0 || - rman_manage_region(&sc->sc_pci_io_rman, 0, FO_IO_SIZE) != 0) - panic("%s: failed to set up I/O rman", __func__); - sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_pci_mem_rman.rm_descr = "Fire PCI Memory"; - if (rman_init(&sc->sc_pci_mem_rman) != 0 || - rman_manage_region(&sc->sc_pci_mem_rman, 0, FO_MEM_SIZE) != 0) - panic("%s: failed to set up memory rman", __func__); - - i = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range); - /* - * Make sure that the expected ranges are present. The - * OFW_PCI_CS_MEM64 one is not currently used though. - */ - if (i != FIRE_NRANGE) - panic("%s: unsupported number of ranges", __func__); - /* - * Find the addresses of the various bus spaces. - * There should not be multiple ones of one kind. - * The physical start addresses of the ranges are the configuration, - * memory and I/O handles. - */ - for (i = 0; i < FIRE_NRANGE; i++) { - j = OFW_PCI_RANGE_CS(&range[i]); - if (sc->sc_pci_bh[j] != 0) - panic("%s: duplicate range for space %d", - __func__, j); - sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]); - } - free(range, M_OFWPROP); - - /* Allocate our tags. */ - sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag( - sc->sc_mem_res[FIRE_PCI]), PCI_IO_BUS_SPACE, NULL); - if (sc->sc_pci_iot == NULL) - panic("%s: could not allocate PCI I/O tag", __func__); - sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag( - sc->sc_mem_res[FIRE_PCI]), PCI_CONFIG_BUS_SPACE, NULL); - if (sc->sc_pci_cfgt == NULL) - panic("%s: could not allocate PCI configuration space tag", - __func__); + /* Create our DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0x100000000, sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, - 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0) + 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0) panic("%s: could not create PCI DMA tag", __func__); - /* Customize the tag. */ - sc->sc_pci_dmat->dt_cookie = &sc->sc_is; - sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods; + dmat->dt_cookie = &sc->sc_is; + dmat->dt_mt = &sc->sc_dma_methods; - /* - * Get the bus range from the firmware. - * NB: Neither Fire nor Oberon support PCI bus reenumeration. - */ - i = OF_getprop(node, "bus-range", (void *)prop_array, - sizeof(prop_array)); - if (i == -1) - panic("%s: could not get bus-range", __func__); - if (i != sizeof(prop_array)) - panic("%s: broken bus-range (%d)", __func__, i); - sc->sc_pci_secbus = prop_array[0]; - sc->sc_pci_subbus = prop_array[1]; - if (bootverbose != 0) - device_printf(dev, "bus range %u to %u; PCI bus %d\n", - sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus); - - ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t)); + if (ofw_pci_attach_common(dev, dmat, FO_IO_SIZE, FO_MEM_SIZE) != 0) + panic("%s: ofw_pci_attach_common() failed", __func__); #define FIRE_SYSCTL_ADD_UINT(name, arg, desc) \ SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), \ @@ -1392,136 +1324,44 @@ static uint32_t fire_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { - struct fire_softc *sc; - bus_space_handle_t bh; - u_long offset = 0; - uint32_t r, wrd; - int i; - uint16_t shrt; - uint8_t byte; - - sc = device_get_softc(dev); - if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus || - slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX) - return (-1); - - offset = FO_CONF_OFF(bus, slot, func, reg); - bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG]; - switch (width) { - case 1: - i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte); - r = byte; - break; - case 2: - i = bus_space_peek_2(sc->sc_pci_cfgt, bh, offset, &shrt); - r = shrt; - break; - case 4: - i = bus_space_peek_4(sc->sc_pci_cfgt, bh, offset, &wrd); - r = wrd; - break; - default: - panic("%s: bad width", __func__); - /* NOTREACHED */ - } - if (i) { -#ifdef FIRE_DEBUG - printf("%s: read data error reading: %d.%d.%d: 0x%x\n", - __func__, bus, slot, func, reg); -#endif - r = -1; - } - return (r); + return (ofw_pci_read_config_common(dev, PCIE_REGMAX, FO_CONF_OFF(bus, + slot, func, reg), bus, slot, func, reg, width)); } static void fire_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width) { - struct fire_softc *sc; - bus_space_handle_t bh; - u_long offset = 0; - - sc = device_get_softc(dev); - if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus || - slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX) - return; - offset = FO_CONF_OFF(bus, slot, func, reg); - bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG]; - switch (width) { - case 1: - bus_space_write_1(sc->sc_pci_cfgt, bh, offset, val); - break; - case 2: - bus_space_write_2(sc->sc_pci_cfgt, bh, offset, val); - break; - case 4: - bus_space_write_4(sc->sc_pci_cfgt, bh, offset, val); - break; - default: - panic("%s: bad width", __func__); - /* NOTREACHED */ - } + ofw_pci_write_config_common(dev, PCIE_REGMAX, FO_CONF_OFF(bus, slot, + func, reg), bus, slot, func, reg, val, width); } static int fire_route_interrupt(device_t bridge, device_t dev, int pin) { - struct fire_softc *sc; - struct ofw_pci_register reg; - ofw_pci_intr_t pintr, mintr; - - sc = device_get_softc(bridge); - pintr = pin; - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, - ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - NULL) != 0) - return (mintr); - - device_printf(bridge, "could not route pin %d for device %d.%d\n", - pin, pci_get_slot(dev), pci_get_function(dev)); - return (PCI_INVALID_IRQ); -} - -static int -fire_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct fire_softc *sc; + ofw_pci_intr_t mintr; - sc = device_get_softc(dev); - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = device_get_unit(dev); - return (0); - case PCIB_IVAR_BUS: - *result = sc->sc_pci_secbus; - return (0); - } - return (ENOENT); + mintr = ofw_pci_route_interrupt_common(bridge, dev, pin); + if (!PCI_INTERRUPT_VALID(mintr)) + device_printf(bridge, + "could not route pin %d for device %d.%d\n", + pin, pci_get_slot(dev), pci_get_function(dev)); + return (mintr); } static void fire_dmamap_sync(bus_dma_tag_t dt __unused, bus_dmamap_t map, bus_dmasync_op_t op) { - static u_char buf[VIS_BLOCKSIZE] __aligned(VIS_BLOCKSIZE); - register_t reg, s; if ((map->dm_flags & DMF_LOADED) == 0) return; - if ((op & BUS_DMASYNC_POSTREAD) != 0) { - s = intr_disable(); - reg = rd(fprs); - wr(fprs, reg | FPRS_FEF, 0); - __asm __volatile("stda %%f0, [%0] %1" - : : "r" (buf), "n" (ASI_BLK_COMMIT_S)); - membar(Sync); - wr(fprs, reg, 0); - intr_restore(s); - } else if ((op & BUS_DMASYNC_PREWRITE) != 0) + if ((op & BUS_DMASYNC_POSTREAD) != 0) + ofw_pci_dmamap_sync_stst_order_common(); + else if ((op & BUS_DMASYNC_PREWRITE) != 0) membar(Sync); } @@ -2015,122 +1855,13 @@ fire_alloc_resource(device_t bus, device u_long start, u_long end, u_long count, u_int flags) { struct fire_softc *sc; - struct resource *rv; - struct rman *rm; - sc = device_get_softc(bus); - switch (type) { - case SYS_RES_IRQ: - /* - * XXX: Don't accept blank ranges for now, only single - * interrupts. The other case should not happen with - * the MI PCI code... - * XXX: This may return a resource that is out of the - * range that was specified. Is this correct...? - */ - if (start != end) - panic("%s: XXX: interrupt range", __func__); - if (*rid == 0) - start = end = INTMAP_VEC(sc->sc_ign, end); - return (bus_generic_alloc_resource(bus, child, type, rid, - start, end, count, flags)); - case SYS_RES_MEMORY: - rm = &sc->sc_pci_mem_rman; - break; - case SYS_RES_IOPORT: - rm = &sc->sc_pci_io_rman; - break; - default: - return (NULL); - } - - rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, - child); - if (rv == NULL) - return (NULL); - rman_set_rid(rv, *rid); - - if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, - *rid, rv) != 0) { - rman_release_resource(rv); - return (NULL); + if (type == SYS_RES_IRQ && *rid == 0) { + sc = device_get_softc(bus); + start = end = INTMAP_VEC(sc->sc_ign, end); } - return (rv); -} - -static int -fire_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - struct fire_softc *sc; - struct bus_space_tag *tag; - - sc = device_get_softc(bus); - switch (type) { - case SYS_RES_IRQ: - return (bus_generic_activate_resource(bus, child, type, rid, - r)); - case SYS_RES_MEMORY: - tag = sparc64_alloc_bus_tag(r, rman_get_bustag( - sc->sc_mem_res[FIRE_PCI]), PCI_MEMORY_BUS_SPACE, NULL); - if (tag == NULL) - return (ENOMEM); - rman_set_bustag(r, tag); - rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] + - rman_get_start(r)); - break; - case SYS_RES_IOPORT: - rman_set_bustag(r, sc->sc_pci_iot); - rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] + - rman_get_start(r)); - break; - } - return (rman_activate_resource(r)); -} - -static int -fire_adjust_resource(device_t bus, device_t child, int type, - struct resource *r, u_long start, u_long end) -{ - struct fire_softc *sc; - struct rman *rm; - - sc = device_get_softc(bus); - switch (type) { - case SYS_RES_IRQ: - return (bus_generic_adjust_resource(bus, child, type, r, - start, end)); - case SYS_RES_MEMORY: - rm = &sc->sc_pci_mem_rman; - break; - case SYS_RES_IOPORT: - rm = &sc->sc_pci_io_rman; - break; - default: - return (EINVAL); - } - if (rman_is_region_manager(r, rm) == 0) - return (EINVAL); - return (rman_adjust_resource(r, start, end)); -} - -static bus_dma_tag_t -fire_get_dma_tag(device_t bus, device_t child __unused) -{ - struct fire_softc *sc; - - sc = device_get_softc(bus); - return (sc->sc_pci_dmat); -} - -static phandle_t -fire_get_node(device_t bus, device_t child __unused) -{ - struct fire_softc *sc; - - sc = device_get_softc(bus); - /* We only have one child, the PCI bus, which needs our own node. */ - return (sc->sc_node); + return (ofw_pci_alloc_resource(bus, child, type, rid, start, end, + count, flags)); } static u_int Modified: stable/10/sys/sparc64/pci/firereg.h ============================================================================== --- stable/10/sys/sparc64/pci/firereg.h Sun Dec 27 18:12:13 2015 (r292788) +++ stable/10/sys/sparc64/pci/firereg.h Sun Dec 27 19:37:47 2015 (r292789) @@ -30,7 +30,6 @@ #define _SPARC64_PCI_FIREREG_H_ #define FIRE_NINTR 3 /* 2 OFW + 1 MSIq */ -#define FIRE_NRANGE 4 #define FIRE_NREG 2 #define FIRE_PCI 0 Modified: stable/10/sys/sparc64/pci/firevar.h ============================================================================== --- stable/10/sys/sparc64/pci/firevar.h Sun Dec 27 18:12:13 2015 (r292788) +++ stable/10/sys/sparc64/pci/firevar.h Sun Dec 27 19:37:47 2015 (r292789) @@ -32,6 +32,12 @@ #define _SPARC64_PCI_FIREVAR_H_ struct fire_softc { + /* + * This is here so that we can hook up the common bus interface + * methods in ofw_pci.c directly. + */ + struct ofw_pci_softc sc_ops; + struct iommu_state sc_is; struct bus_dma_methods sc_dma_methods; @@ -42,13 +48,6 @@ struct fire_softc { struct resource *sc_irq_res[FIRE_NINTR]; void *sc_ihand[FIRE_NINTR]; - struct rman sc_pci_mem_rman; - struct rman sc_pci_io_rman; - bus_space_handle_t sc_pci_bh[FIRE_NRANGE]; - bus_space_tag_t sc_pci_cfgt; - bus_space_tag_t sc_pci_iot; - bus_dma_tag_t sc_pci_dmat; - device_t sc_dev; uint64_t *sc_msiq; @@ -66,8 +65,6 @@ struct fire_softc { uint32_t sc_msiq_first; uint32_t sc_msiq_ino_first; - phandle_t sc_node; - u_int sc_mode; #define FIRE_MODE_FIRE 0 #define FIRE_MODE_OBERON 1 @@ -87,11 +84,6 @@ struct fire_softc { uint32_t sc_stats_tlu_oe_rx_err; uint32_t sc_stats_tlu_oe_tx_err; uint32_t sc_stats_ubc_dmardue; - - uint8_t sc_pci_secbus; - uint8_t sc_pci_subbus; - - struct ofw_bus_iinfo sc_pci_iinfo; }; #endif /* !_SPARC64_PCI_FIREVAR_H_ */ Copied and modified: stable/10/sys/sparc64/pci/ofw_pci.c (from r287726, head/sys/sparc64/pci/ofw_pci.c) ============================================================================== --- head/sys/sparc64/pci/ofw_pci.c Sat Sep 12 22:49:32 2015 (r287726, copy source) +++ stable/10/sys/sparc64/pci/ofw_pci.c Sun Dec 27 19:37:47 2015 (r292789) @@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$"); #include +/* XXX */ +extern struct bus_space_tag nexus_bustag; + int ofw_pci_attach_common(device_t dev, bus_dma_tag_t dmat, u_long iosize, u_long memsize) @@ -125,12 +128,14 @@ ofw_pci_attach_common(device_t dev, bus_ } /* Allocate our tags. */ - sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, PCI_IO_BUS_SPACE); + sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, &nexus_bustag, + PCI_IO_BUS_SPACE, NULL); if (sc->sc_pci_iot == NULL) { device_printf(dev, "could not allocate PCI I/O tag\n"); return (ENXIO); } - sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, PCI_CONFIG_BUS_SPACE); + sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, &nexus_bustag, + PCI_CONFIG_BUS_SPACE, NULL); if (sc->sc_pci_cfgt == NULL) { device_printf(dev, "could not allocate PCI configuration space tag\n"); @@ -344,7 +349,8 @@ ofw_pci_activate_resource(device_t bus, return (bus_generic_activate_resource(bus, child, type, rid, r)); case SYS_RES_MEMORY: - tag = sparc64_alloc_bus_tag(r, PCI_MEMORY_BUS_SPACE); + tag = sparc64_alloc_bus_tag(r, &nexus_bustag, + PCI_MEMORY_BUS_SPACE, NULL); if (tag == NULL) return (ENOMEM); rman_set_bustag(r, tag); Modified: stable/10/sys/sparc64/pci/ofw_pci.h ============================================================================== --- stable/10/sys/sparc64/pci/ofw_pci.h Sun Dec 27 18:12:13 2015 (r292788) +++ stable/10/sys/sparc64/pci/ofw_pci.h Sun Dec 27 19:37:47 2015 (r292789) @@ -62,6 +62,8 @@ #ifndef _SPARC64_PCI_OFW_PCI_H_ #define _SPARC64_PCI_OFW_PCI_H_ +#include + #include #include "ofw_pci_if.h" @@ -73,6 +75,7 @@ typedef uint32_t ofw_pci_intr_t; #define OFW_PCI_CS_IO 0x01 #define OFW_PCI_CS_MEM32 0x02 #define OFW_PCI_CS_MEM64 0x03 +#define OFW_PCI_NUM_CS 4 /* OFW device types */ #define OFW_TYPE_PCI "pci" @@ -124,4 +127,44 @@ struct ofw_pci_ranges { /* default values */ #define OFW_PCI_LATENCY 64 +/* + * Common and generic parts of host-PCI-bridge support + */ + +struct ofw_pci_softc { + struct rman sc_pci_mem_rman; + struct rman sc_pci_io_rman; + + bus_space_handle_t sc_pci_bh[OFW_PCI_NUM_CS]; + bus_space_tag_t sc_pci_cfgt; + bus_space_tag_t sc_pci_iot; + bus_dma_tag_t sc_pci_dmat; + + struct ofw_bus_iinfo sc_pci_iinfo; + + phandle_t sc_node; + + uint8_t sc_pci_secbus; + uint8_t sc_pci_subbus; +}; + +int ofw_pci_attach_common(device_t dev, bus_dma_tag_t dmat, u_long iosize, + u_long memsize); +uint32_t ofw_pci_read_config_common(device_t dev, u_int regmax, u_long offset, + u_int bus, u_int slot, u_int func, u_int reg, int width); +void ofw_pci_write_config_common(device_t dev, u_int regmax, u_long offset, + u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width); +ofw_pci_intr_t ofw_pci_route_interrupt_common(device_t bridge, device_t dev, + int pin); + +void ofw_pci_dmamap_sync_stst_order_common(void); + +bus_activate_resource_t ofw_pci_activate_resource; +bus_adjust_resource_t ofw_pci_adjust_resource; +bus_alloc_resource_t ofw_pci_alloc_resource; +bus_get_dma_tag_t ofw_pci_get_dma_tag; +bus_read_ivar_t ofw_pci_read_ivar; + +ofw_bus_get_node_t ofw_pci_get_node; + #endif /* ! _SPARC64_PCI_OFW_PCI_H_ */ Modified: stable/10/sys/sparc64/pci/psycho.c ============================================================================== --- stable/10/sys/sparc64/pci/psycho.c Sun Dec 27 18:12:13 2015 (r292788) +++ stable/10/sys/sparc64/pci/psycho.c Sun Dec 27 19:37:47 2015 (r292789) @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -110,17 +109,12 @@ static void psycho_iommu_init(struct psy */ static device_probe_t psycho_probe; static device_attach_t psycho_attach; -static bus_read_ivar_t psycho_read_ivar; static bus_setup_intr_t psycho_setup_intr; static bus_alloc_resource_t psycho_alloc_resource; -static bus_activate_resource_t psycho_activate_resource; -static bus_adjust_resource_t psycho_adjust_resource; -static bus_get_dma_tag_t psycho_get_dma_tag; static pcib_maxslots_t psycho_maxslots; static pcib_read_config_t psycho_read_config; static pcib_write_config_t psycho_write_config; static pcib_route_interrupt_t psycho_route_interrupt; -static ofw_bus_get_node_t psycho_get_node; static ofw_pci_setup_device_t psycho_setup_device; static device_method_t psycho_methods[] = { @@ -132,15 +126,15 @@ static device_method_t psycho_methods[] DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ - DEVMETHOD(bus_read_ivar, psycho_read_ivar), + DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar), DEVMETHOD(bus_setup_intr, psycho_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, psycho_alloc_resource), - DEVMETHOD(bus_activate_resource, psycho_activate_resource), + DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_adjust_resource, psycho_adjust_resource), + DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_get_dma_tag, psycho_get_dma_tag), + DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag), /* pcib interface */ DEVMETHOD(pcib_maxslots, psycho_maxslots), @@ -149,7 +143,7 @@ static device_method_t psycho_methods[] DEVMETHOD(pcib_route_interrupt, psycho_route_interrupt), /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_node, psycho_get_node), + DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node), /* ofw_pci interface */ DEVMETHOD(ofw_pci_setup_device, psycho_setup_device), @@ -288,12 +282,12 @@ psycho_attach(device_t dev) { struct psycho_icarg *pica; struct psycho_softc *asc, *sc, *osc; - struct ofw_pci_ranges *range; const struct psycho_desc *desc; bus_addr_t intrclr, intrmap; + bus_dma_tag_t dmat; uint64_t csr, dr; phandle_t node; - uint32_t dvmabase, prop, prop_array[2]; + uint32_t dvmabase, prop; u_int rerun, ver; int i, j; @@ -301,7 +295,6 @@ psycho_attach(device_t dev) sc = device_get_softc(dev); desc = psycho_get_desc(dev); - sc->sc_node = node; sc->sc_dev = dev; sc->sc_mode = desc->pd_mode; @@ -367,6 +360,7 @@ psycho_attach(device_t dev) panic("%s: mutex not initialized", __func__); sc->sc_mtx = osc->sc_mtx; } + SLIST_INSERT_HEAD(&psycho_softcs, sc, sc_link); csr = PSYCHO_READ8(sc, PSR_CS); ver = PSYCHO_GCSR_VERS(csr); @@ -435,43 +429,6 @@ psycho_attach(device_t dev) } else dvmabase = -1; - /* Initialize memory and I/O rmans. */ - sc->sc_pci_io_rman.rm_type = RMAN_ARRAY; - sc->sc_pci_io_rman.rm_descr = "Psycho PCI I/O Ports"; - if (rman_init(&sc->sc_pci_io_rman) != 0 || - rman_manage_region(&sc->sc_pci_io_rman, 0, PSYCHO_IO_SIZE) != 0) - panic("%s: failed to set up I/O rman", __func__); - sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_pci_mem_rman.rm_descr = "Psycho PCI Memory"; - if (rman_init(&sc->sc_pci_mem_rman) != 0 || - rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0) - panic("%s: failed to set up memory rman", __func__); - - i = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range); - /* - * Make sure that the expected ranges are present. The - * OFW_PCI_CS_MEM64 one is not currently used though. - */ - if (i != PSYCHO_NRANGE) - panic("%s: unsupported number of ranges", __func__); - /* - * Find the addresses of the various bus spaces. - * There should not be multiple ones of one kind. - * The physical start addresses of the ranges are the configuration, - * memory and I/O handles. - */ - for (i = 0; i < PSYCHO_NRANGE; i++) { - j = OFW_PCI_RANGE_CS(&range[i]); - if (sc->sc_pci_bh[j] != 0) - panic("%s: duplicate range for space %d", - __func__, j); - sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]); - } - free(range, M_OFWPROP); - - /* Register the softc, this is needed for paired Psychos. */ - SLIST_INSERT_HEAD(&psycho_softcs, sc, sc_link); - /* * If we're a Hummingbird/Sabre or the first of a pair of Psychos * to arrive here, do the interrupt setup and start up the IOMMU. @@ -572,39 +529,21 @@ psycho_attach(device_t dev) iommu_reset(sc->sc_is); } - /* Allocate our tags. */ - sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag( - sc->sc_mem_res), PCI_IO_BUS_SPACE, NULL); - if (sc->sc_pci_iot == NULL) - panic("%s: could not allocate PCI I/O tag", __func__); - sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag( - sc->sc_mem_res), PCI_CONFIG_BUS_SPACE, NULL); - if (sc->sc_pci_cfgt == NULL) - panic("%s: could not allocate PCI configuration space tag", - __func__); + /* Create our DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is->is_pmaxaddr, ~0, NULL, NULL, sc->sc_is->is_pmaxaddr, - 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0) + 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0) panic("%s: could not create PCI DMA tag", __func__); - /* Customize the tag. */ - sc->sc_pci_dmat->dt_cookie = sc->sc_is; - sc->sc_pci_dmat->dt_mt = sc->sc_dma_methods; - - i = OF_getprop(node, "bus-range", (void *)prop_array, - sizeof(prop_array)); - if (i == -1) - panic("%s: could not get bus-range", __func__); - if (i != sizeof(prop_array)) - panic("%s: broken bus-range (%d)", __func__, i); - sc->sc_pci_secbus = prop_array[0]; - sc->sc_pci_subbus = prop_array[1]; - if (bootverbose) - device_printf(dev, "bus range %u to %u; PCI bus %d\n", - sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus); + dmat->dt_cookie = sc->sc_is; + dmat->dt_mt = sc->sc_dma_methods; + + if (ofw_pci_attach_common(dev, dmat, PSYCHO_IO_SIZE, + PSYCHO_MEM_SIZE) != 0) + panic("%s: ofw_pci_attach_common() failed", __func__); /* Clear any pending PCI error bits. */ - PCIB_WRITE_CONFIG(dev, sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC, - PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_pci_secbus, + PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, + PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_STATUS, 2), 2); PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS)); PCICTL_WRITE8(sc, PCR_AFS, PCICTL_READ8(sc, PCR_AFS)); @@ -667,20 +606,20 @@ psycho_attach(device_t dev) * Set the latency timer register as this isn't always done by the * firmware. */ - PCIB_WRITE_CONFIG(dev, sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC, + PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_LATTIMER, OFW_PCI_LATENCY, 1); for (i = PCIR_VENDOR; i < PCIR_STATUS; i += sizeof(uint16_t)) - le16enc(&sc->sc_pci_hpbcfg[i], bus_space_read_2( - sc->sc_pci_cfgt, sc->sc_pci_bh[OFW_PCI_CS_CONFIG], - PSYCHO_CONF_OFF(sc->sc_pci_secbus, PCS_DEVICE, + le16enc(&sc->sc_pci_hpbcfg[i], + bus_space_read_2(sc->sc_ops.sc_pci_cfgt, + sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], + PSYCHO_CONF_OFF(sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i))); for (i = PCIR_REVID; i <= PCIR_BIST; i += sizeof(uint8_t)) - sc->sc_pci_hpbcfg[i] = bus_space_read_1(sc->sc_pci_cfgt, - sc->sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF( - sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i)); + sc->sc_pci_hpbcfg[i] = bus_space_read_1(sc->sc_ops.sc_pci_cfgt, + sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF( + sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i)); - ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t)); /* * On E250 the interrupt map entry for the EBus bridge is wrong, * causing incorrect interrupts to be assigned to some devices on @@ -691,9 +630,9 @@ psycho_attach(device_t dev) * EBus devices will be used directly instead. */ if (strcmp(sparc64_model, "SUNW,Ultra-250") == 0 && - sc->sc_pci_iinfo.opi_imapmsk != NULL) - *(ofw_pci_intr_t *)(&sc->sc_pci_iinfo.opi_imapmsk[ - sc->sc_pci_iinfo.opi_addrc]) = INTMAP_INO_MASK; + sc->sc_ops.sc_pci_iinfo.opi_imapmsk != NULL) + *(ofw_pci_intr_t *)(&sc->sc_ops.sc_pci_iinfo.opi_imapmsk[ + sc->sc_ops.sc_pci_iinfo.opi_addrc]) = INTMAP_INO_MASK; device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); @@ -927,20 +866,8 @@ psycho_read_config(device_t dev, u_int b int width) { struct psycho_softc *sc; - bus_space_handle_t bh; - u_long offset = 0; - uint8_t byte; - uint16_t shrt; - uint32_t r, wrd; - int i; sc = device_get_softc(dev); - if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus || - slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCI_REGMAX) - return (-1); - - bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG]; - /* * The Hummingbird and Sabre bridges are picky in that they * only allow their config space to be accessed using the @@ -956,9 +883,9 @@ psycho_read_config(device_t dev, u_int b * The Psycho bridges contain a dupe of their header at 0x80 * which we nullify that way also. */ - if (bus == sc->sc_pci_secbus && slot == PCS_DEVICE && + if (bus == sc->sc_ops.sc_pci_secbus && slot == PCS_DEVICE && func == PCS_FUNC) { - if (offset % width != 0) + if (reg % width != 0) return (-1); if (reg >= sizeof(sc->sc_pci_hpbcfg)) @@ -967,8 +894,9 @@ psycho_read_config(device_t dev, u_int b if ((reg < PCIR_STATUS && reg + width > PCIR_STATUS) || reg == PCIR_STATUS || reg == PCIR_STATUS + 1) le16enc(&sc->sc_pci_hpbcfg[PCIR_STATUS], - bus_space_read_2(sc->sc_pci_cfgt, bh, - PSYCHO_CONF_OFF(sc->sc_pci_secbus, + bus_space_read_2(sc->sc_ops.sc_pci_cfgt, + sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], + PSYCHO_CONF_OFF(sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_STATUS))); switch (width) { @@ -981,79 +909,29 @@ psycho_read_config(device_t dev, u_int b } } - offset = PSYCHO_CONF_OFF(bus, slot, func, reg); - switch (width) { - case 1: - i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte); - r = byte; - break; - case 2: - i = bus_space_peek_2(sc->sc_pci_cfgt, bh, offset, &shrt); - r = shrt; - break; - case 4: - i = bus_space_peek_4(sc->sc_pci_cfgt, bh, offset, &wrd); - r = wrd; - break; - default: - panic("%s: bad width", __func__); - /* NOTREACHED */ - } - - if (i) { -#ifdef PSYCHO_DEBUG - printf("%s: read data error reading: %d.%d.%d: 0x%x\n", - __func__, bus, slot, func, reg); -#endif - r = -1; - } - return (r); + return (ofw_pci_read_config_common(dev, PCI_REGMAX, + PSYCHO_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, + width)); } static void psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width) { - struct psycho_softc *sc; - bus_space_handle_t bh; - u_long offset = 0; - sc = device_get_softc(dev); - if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus || - slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCI_REGMAX) - return; - - offset = PSYCHO_CONF_OFF(bus, slot, func, reg); - bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG]; - switch (width) { - case 1: - bus_space_write_1(sc->sc_pci_cfgt, bh, offset, val); - break; - case 2: - bus_space_write_2(sc->sc_pci_cfgt, bh, offset, val); - break; - case 4: - bus_space_write_4(sc->sc_pci_cfgt, bh, offset, val); - break; - default: - panic("%s: bad width", __func__); - /* NOTREACHED */ - } + ofw_pci_write_config_common(dev, PCI_REGMAX, PSYCHO_CONF_OFF(bus, + slot, func, reg), bus, slot, func, reg, val, width); } static int psycho_route_interrupt(device_t bridge, device_t dev, int pin) { struct psycho_softc *sc; - struct ofw_pci_register reg; bus_addr_t intrmap; - ofw_pci_intr_t pintr, mintr; + ofw_pci_intr_t mintr; - sc = device_get_softc(bridge); - pintr = pin; - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, - ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - NULL)) + mintr = ofw_pci_route_interrupt_common(bridge, dev, pin); + if (PCI_INTERRUPT_VALID(mintr)) return (mintr); /* * If this is outside of the range for an intpin, it's likely a full @@ -1072,6 +950,7 @@ psycho_route_interrupt(device_t bridge, * for bus A are one-based, while those for bus B seemingly have an * offset of 2 (hence the factor of 3 below). */ + sc = device_get_softc(dev); intrmap = PSR_PCIA0_INT_MAP + 8 * (pci_get_slot(dev) - 1 + 3 * sc->sc_half); mintr = INTINO(PSYCHO_READ8(sc, intrmap)) + pin - 1; @@ -1081,23 +960,6 @@ psycho_route_interrupt(device_t bridge, return (mintr); } -static int -psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct psycho_softc *sc; - - sc = device_get_softc(dev); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***