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