From owner-svn-src-projects@FreeBSD.ORG Thu Mar 24 16:56:34 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4492910656D7; Thu, 24 Mar 2011 16:56:34 +0000 (UTC) (envelope-from marcel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 33AA58FC15; Thu, 24 Mar 2011 16:56:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2OGuYlP051708; Thu, 24 Mar 2011 16:56:34 GMT (envelope-from marcel@svn.freebsd.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2OGuY6k051706; Thu, 24 Mar 2011 16:56:34 GMT (envelope-from marcel@svn.freebsd.org) Message-Id: <201103241656.p2OGuY6k051706@svn.freebsd.org> From: Marcel Moolenaar Date: Thu, 24 Mar 2011 16:56:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r219964 - projects/altix/sys/ia64/sgisn X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Mar 2011 16:56:34 -0000 Author: marcel Date: Thu Mar 24 16:56:33 2011 New Revision: 219964 URL: http://svn.freebsd.org/changeset/base/219964 Log: Add necessary address space mapping. The Altix architecture has distinct address spaces for PCI devices and CPUs. That is, the S-Hub translates addresses on the FSB and coming from CPUs to addresses valid on the PCI bus. This is abstracted and implemented in FreeBSD by having the handle contain the CPU address, while the resource itself describes the PCI bus address. Since devices are mapped when resources are activated and the bus handle is derived from that, have the SGI PCI bus driver handle the activation of resources instead of passing it up to the nexus. Note that the Altix architecture allows for IRQ values larger than 255 even though the intline register in the PCI configuration space does not. FreeBSD also doesn't support it by virtue of having an IRQ resource space that's limited. On my machines the IRQ values are within bounds so I'm not going to worry about this detail. It may very well be theoretical. With this change the bge(4) driver attaches properly. The one thing stopping us from netbooting is... interrupts... Modified: projects/altix/sys/ia64/sgisn/sgisn_pcib.c Modified: projects/altix/sys/ia64/sgisn/sgisn_pcib.c ============================================================================== --- projects/altix/sys/ia64/sgisn/sgisn_pcib.c Thu Mar 24 16:06:57 2011 (r219963) +++ projects/altix/sys/ia64/sgisn/sgisn_pcib.c Thu Mar 24 16:56:33 2011 (r219964) @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -40,11 +41,18 @@ __FBSDID("$FreeBSD$"); #include "pcib_if.h" +#include +#include + +#include #include +#include #include #include static struct sgisn_hub sgisn_hub; +static struct sgisn_dev sgisn_dev; +static struct sgisn_irq sgisn_irq; struct sgisn_pcib_softc { device_t sc_dev; @@ -57,6 +65,8 @@ static int sgisn_pcib_attach(device_t); static void sgisn_pcib_identify(driver_t *, device_t); static int sgisn_pcib_probe(device_t); +static int sgisn_pcib_activate_resource(device_t, device_t, int, int, + struct resource *); static int sgisn_pcib_read_ivar(device_t, device_t, int, uintptr_t *); static int sgisn_pcib_write_ivar(device_t, device_t, int, uintptr_t); @@ -65,6 +75,10 @@ static uint32_t sgisn_pcib_cfgread(devic static void sgisn_pcib_cfgwrite(device_t, u_int, u_int, u_int, u_int, uint32_t, int); +#if 0 +static int sgisn_pcib_scan(struct sgisn_pcib_softc *, u_int, u_int); +#endif + /* * Bus interface definitions. */ @@ -80,7 +94,7 @@ static device_method_t sgisn_pcib_method DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_activate_resource, sgisn_pcib_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), @@ -108,7 +122,7 @@ static int sgisn_pcib_maxslots(device_t dev) { - return (31); + return (PCI_SLOTMAX); } static uint32_t @@ -137,6 +151,64 @@ sgisn_pcib_cfgwrite(device_t dev, u_int bytes); } +static int +sgisn_pcib_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *res) +{ + struct ia64_sal_result r; + struct sgisn_pcib_softc *sc; + device_t parent; + void *vaddr; + uintptr_t func, slot; + vm_paddr_t paddr; + u_long base; + int bar, error; + + parent = device_get_parent(child); + + error = BUS_READ_IVAR(parent, child, PCI_IVAR_SLOT, &slot); + if (!error) + error = BUS_READ_IVAR(parent, child, PCI_IVAR_FUNCTION, &func); + if (error) + return (error); + + sc = device_get_softc(dev); + + r = ia64_sal_entry(SAL_SGISN_IODEV_INFO, sc->sc_domain, sc->sc_busnr, + (slot << 3) | func, ia64_tpa((uintptr_t)&sgisn_dev), + ia64_tpa((uintptr_t)&sgisn_irq), 0, 0); + if (r.sal_status != 0) + return (ENXIO); + + paddr = rman_get_start(res); + + if (type == SYS_RES_IRQ) { + /* For now, only warn when there's a mismatch. */ + if (paddr != sgisn_irq.irq_no) + device_printf(dev, "interrupt mismatch: (actual=%u)\n", + sgisn_irq.irq_no); + goto out; + } + + bar = PCI_RID2BAR(rid); + if (bar < 0 || bar > PCIR_MAX_BAR_0) + return (EINVAL); + base = sgisn_dev.dev_bar[bar]; + if (base != paddr) + device_printf(dev, "PCI bus address %#lx mapped to CPU " + "address %#lx\n", paddr, base); + + /* I/O port space is presented as memory mapped I/O. */ + rman_set_bustag(res, IA64_BUS_SPACE_MEM); + vaddr = pmap_mapdev(base, rman_get_size(res)); + rman_set_bushandle(res, (bus_space_handle_t) vaddr); + if (type == SYS_RES_MEMORY) + rman_set_virtual(res, vaddr); + + out: + return (rman_activate_resource(res)); +} + static void sgisn_pcib_identify(driver_t *drv, device_t bus) { @@ -188,6 +260,10 @@ sgisn_pcib_attach(device_t dev) sc = device_get_softc(dev); sc->sc_dev = dev; +#if 0 + sgisn_pcib_scan(sc, sc->sc_busnr, sgisn_pcib_maxslots(dev)); +#endif + device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } @@ -220,3 +296,55 @@ sgisn_pcib_write_ivar(device_t dev, devi } return (ENOENT); } + +#if 0 +static int +sgisn_pcib_scan(struct sgisn_pcib_softc *sc, u_int bus, u_int maxslot) +{ + static struct sgisn_dev dev; + static struct sgisn_irq irq; + struct ia64_sal_result r; + u_int devfn, func, maxfunc, slot; + uint8_t hdrtype; + + for (slot = 0; slot <= maxslot; slot++) { + maxfunc = 0; + for (func = 0; func <= maxfunc; func++) { + hdrtype = sgisn_pcib_cfgread(sc->sc_dev, bus, slot, + func, PCIR_HDRTYPE, 1); + + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + + if (func == 0 && (hdrtype & PCIM_MFDEV)) + maxfunc = PCI_FUNCMAX; + + printf("XXX: %s: %u:%u:%u:%u: ", __func__, + sc->sc_domain, bus, slot, func); + + devfn = (slot << 3) | func; + r = ia64_sal_entry(SAL_SGISN_IODEV_INFO, sc->sc_domain, + bus, devfn, ia64_tpa((uintptr_t)&dev), + ia64_tpa((uintptr_t)&irq), 0, 0); + + if (r.sal_status != 0) { + printf("status %#lx\n", r.sal_status); + continue; + } + + printf("handle=%#lx\n", dev.dev_handle); + printf(" BAR: %#lx, %#lx, %#lx, %#lx, %#lx, %#lx\n", + dev.dev_bar[0], dev.dev_bar[1], dev.dev_bar[2], + dev.dev_bar[3], dev.dev_bar[4], dev.dev_bar[5]); + printf(" ROM: %#lx\n", dev.dev_rom); + + printf(" IRT: nodeid=%#x, slice=%#x, cpuid=%#x\n", + irq.irq_nasid, irq.irq_slice, irq.irq_cpuid); + printf(" IRQ: nr=%#x, pin=%#x, xtaddr=%#lx\n", + irq.irq_no, irq.irq_pin, irq.irq_xtaddr); + } + } + + return (0); +} +#endif