svn commit: r219964 - projects/altix/sys/ia64/sgisn
Marcel Moolenaar
marcel at FreeBSD.org
Thu Mar 24 16:56:34 UTC 2011
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 <sys/module.h>
#include <sys/bus.h>
#include <sys/pcpu.h>
+#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -40,11 +41,18 @@ __FBSDID("$FreeBSD$");
#include "pcib_if.h"
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
#include <machine/pci_cfgreg.h>
+#include <machine/resource.h>
#include <machine/sal.h>
#include <machine/sgisn.h>
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
More information about the svn-src-projects
mailing list