svn commit: r220119 - in projects/altix/sys/ia64: include sgisn
Marcel Moolenaar
marcel at FreeBSD.org
Tue Mar 29 00:36:37 UTC 2011
Author: marcel
Date: Tue Mar 29 00:36:36 2011
New Revision: 220119
URL: http://svn.freebsd.org/changeset/base/220119
Log:
o Fleshed-out shub driver that creates pcib children.
o Modified pcib driver that attaches to shub.
o Slightly tweaked PROM-defined structures.
Modified:
projects/altix/sys/ia64/include/sgisn.h
projects/altix/sys/ia64/sgisn/sgisn_pcib.c
projects/altix/sys/ia64/sgisn/sgisn_shub.c
Modified: projects/altix/sys/ia64/include/sgisn.h
==============================================================================
--- projects/altix/sys/ia64/include/sgisn.h Tue Mar 29 00:33:02 2011 (r220118)
+++ projects/altix/sys/ia64/include/sgisn.h Tue Mar 29 00:36:36 2011 (r220119)
@@ -29,6 +29,7 @@
#define _MACHINE_SGISN_H_
/* SAL functions */
+#define SAL_SGISN_KLCONFIG_ADDR 0x02000005
#define SAL_SGISN_SAPIC_INFO 0x0200001d
#define SAL_SGISN_SN_INFO 0x0200001e
#define SAL_SGISN_PUTC 0x02000021
@@ -38,6 +39,8 @@
#define SAL_SGISN_IOHUB_INFO 0x02000055
#define SAL_SGISN_IOBUS_INFO 0x02000056
#define SAL_SGISN_IODEV_INFO 0x02000057
+#define SAL_SGISN_FEATURE_GET_PROM 0x02000065
+#define SAL_SGISN_FEATURE_SET_OS 0x02000066
#define SGISN_GEOID_MODULE(id) (((id) >> 0) & 0xffffffffu)
#define SGISN_GEOID_TYPE(id) (((id) >> 32) & 0xff)
@@ -61,23 +64,39 @@
#define SGISN_HUB_NITTES 8
#define SGISN_HUB_NWIDGETS 16
+#define SHUB_IVAR_PCIBUS 1
+#define SHUB_IVAR_PCISEG 2
+
+struct sgisn_fwhub;
+
struct sgisn_widget {
uint32_t wgt_hwmfg;
uint32_t wgt_hwrev;
uint32_t wgt_hwpn;
uint8_t wgt_port;
- char _pad[3];
- uint64_t wgt_private;
- uint64_t wgt_provider;
+ uint8_t _pad[3];
+ struct sgisn_fwhub *wgt_hub;
+ uint64_t wgt_funcs;
uint64_t wgt_vertex;
};
-struct sgisn_hub {
+struct sgisn_fwbus {
+ uint32_t bus_asic;
+ uint32_t bus_xid;
+ uint32_t bus_busnr;
+ uint32_t bus_segment;
+ uint64_t bus_ioport_addr;
+ uint64_t bus_memio_addr;
+ uint64_t bus_base;
+ struct sgisn_widget *bus_wgt_info;
+};
+
+struct sgisn_fwhub {
uint64_t hub_geoid;
uint16_t hub_nasid;
uint16_t hub_peer_nasid;
- char _pad[4];
- uint64_t hub_pointer;
+ uint32_t _pad;
+ void *hub_widgets;
uint64_t hub_dma_itte[SGISN_HUB_NITTES];
struct sgisn_widget hub_widget[SGISN_HUB_NWIDGETS];
@@ -88,29 +107,33 @@ struct sgisn_hub {
uint32_t hub_pci_maxbus;
};
-struct sgisn_irq {
- uint64_t irq_unused;
- uint16_t irq_nasid;
- char _pad1[2];
- u_int irq_slice;
- u_int irq_cpuid;
- u_int irq_no;
- u_int irq_pin;
- uint64_t irq_xtaddr;
- u_int irq_br_type;
- char _pad2[4];
- uint64_t irq_bridge;
- uint64_t irq_io_info;
- u_int irq_last;
- u_int irq_cookie;
- u_int irq_flags;
- u_int irq_refcnt;
+struct sgisn_fwirq {
+ uint64_t _obsolete;
+ uint16_t irq_tgt_nasid;
+ uint16_t _pad1;
+ uint32_t irq_tgt_slice;
+ uint32_t irq_cpuid;
+ uint32_t irq_nr;
+ uint32_t irq_pin;
+ uint64_t irq_tgt_xtaddr;
+ uint32_t irq_br_type;
+ uint32_t _pad2;
+ void *irq_bridge; /* Originating */
+ void *irq_io_info;
+ uint32_t irq_last;
+ uint32_t irq_cookie;
+ uint32_t irq_flags;
+ uint32_t irq_refcnt;
};
-struct sgisn_dev {
+struct sgisn_fwdev {
uint64_t dev_bar[6];
- uint64_t dev_rom;
+ uint64_t dev_romaddr;
uint64_t dev_handle;
+ struct sgisn_fwbus *dev_bus_softc;
+ struct sgisn_fwdev *dev_parent;
+ void *dev_os_devptr;
+ struct sgisn_fwirq *dev_irq;
};
#endif /* !_MACHINE_SGISN_H_ */
Modified: projects/altix/sys/ia64/sgisn/sgisn_pcib.c
==============================================================================
--- projects/altix/sys/ia64/sgisn/sgisn_pcib.c Tue Mar 29 00:33:02 2011 (r220118)
+++ projects/altix/sys/ia64/sgisn/sgisn_pcib.c Tue Mar 29 00:36:36 2011 (r220119)
@@ -50,9 +50,8 @@ __FBSDID("$FreeBSD$");
#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;
+static struct sgisn_fwdev sgisn_dev;
+static struct sgisn_fwirq sgisn_irq;
struct sgisn_pcib_softc {
device_t sc_dev;
@@ -62,7 +61,6 @@ struct sgisn_pcib_softc {
};
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,
@@ -84,7 +82,6 @@ static int sgisn_pcib_scan(struct sgisn_
*/
static device_method_t sgisn_pcib_methods[] = {
/* Device interface */
- DEVMETHOD(device_identify, sgisn_pcib_identify),
DEVMETHOD(device_probe, sgisn_pcib_probe),
DEVMETHOD(device_attach, sgisn_pcib_attach),
@@ -116,7 +113,7 @@ static driver_t sgisn_pcib_driver = {
devclass_t pcib_devclass;
-DRIVER_MODULE(pcib, nexus, sgisn_pcib_driver, pcib_devclass, 0, 0);
+DRIVER_MODULE(pcib, shub, sgisn_pcib_driver, pcib_devclass, 0, 0);
static int
sgisn_pcib_maxslots(device_t dev)
@@ -184,9 +181,30 @@ sgisn_pcib_activate_resource(device_t de
if (type == SYS_RES_IRQ) {
/* For now, only warn when there's a mismatch. */
- if (paddr != sgisn_irq.irq_no)
+ if (paddr != sgisn_irq.irq_nr)
device_printf(dev, "interrupt mismatch: (actual=%u)\n",
- sgisn_irq.irq_no);
+ sgisn_irq.irq_nr);
+
+ printf("XXX: %s: %u, %u, %u, %u, %u, %#lx\n", __func__,
+ sgisn_irq.irq_tgt_nasid, sgisn_irq.irq_tgt_slice,
+ sgisn_irq.irq_cpuid, sgisn_irq.irq_nr, sgisn_irq.irq_pin,
+ sgisn_irq.irq_tgt_xtaddr);
+ printf("\t%u, %p, %p, %u, %#x, %#x, %u\n", sgisn_irq.irq_br_type,
+ sgisn_irq.irq_bridge, sgisn_irq.irq_io_info, sgisn_irq.irq_last,
+ sgisn_irq.irq_cookie, sgisn_irq.irq_flags, sgisn_irq.irq_refcnt);
+
+#if 0
+ r = ia64_sal_entry(SAL_SGISN_INTERRUPT, 1 /*alloc*/,
+ sgisn_irq.irq_tgt_nasid,
+ (sgisn_irq.irq_bridge >> 24) & 15
+ ia64_tpa((uintptr_t)&sgisn_irq),
+ paddr,
+ sgisn_irq.irq_tgt_nasid,
+ sgisn_irq.irq_tgt_slice);
+ if (r.status != 0)
+ return (ENXIO);
+#endif
+
goto out;
}
@@ -209,44 +227,19 @@ sgisn_pcib_activate_resource(device_t de
return (rman_activate_resource(res));
}
-static void
-sgisn_pcib_identify(driver_t *drv, device_t bus)
-{
- struct ia64_sal_result r;
- device_t dev;
- struct sgisn_pcib_softc *sc;
- void *addr;
- u_int busno, segno;
-
- sgisn_hub.hub_pci_maxseg = 0xffffffff;
- sgisn_hub.hub_pci_maxbus = 0xff;
- r = ia64_sal_entry(SAL_SGISN_IOHUB_INFO, PCPU_GET(md.sgisn_nasid),
- ia64_tpa((uintptr_t)&sgisn_hub), 0, 0, 0, 0, 0);
- if (r.sal_status != 0)
- return;
-
- for (segno = 0; segno <= sgisn_hub.hub_pci_maxseg; segno++) {
- for (busno = 0; busno <= sgisn_hub.hub_pci_maxbus; busno++) {
- r = ia64_sal_entry(SAL_SGISN_IOBUS_INFO, segno, busno,
- ia64_tpa((uintptr_t)&addr), 0, 0, 0, 0);
-
- if (r.sal_status == 0 && addr != NULL) {
- dev = BUS_ADD_CHILD(bus, 0, drv->name, -1);
- if (dev == NULL)
- continue;
- device_set_driver(dev, drv);
- sc = device_get_softc(dev);
- sc->sc_promaddr = addr;
- sc->sc_domain = segno;
- sc->sc_busnr = busno;
- }
- }
- }
-}
-
static int
sgisn_pcib_probe(device_t dev)
{
+ device_t parent;
+ uintptr_t bus, seg;
+
+ parent = device_get_parent(dev);
+ if (parent == NULL)
+ return (ENXIO);
+
+ if (BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCISEG, &seg) ||
+ BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCIBUS, &bus))
+ return (ENXIO);
device_set_desc(dev, "SGI PCI-X host controller");
return (BUS_PROBE_DEFAULT);
@@ -256,10 +249,18 @@ static int
sgisn_pcib_attach(device_t dev)
{
struct sgisn_pcib_softc *sc;
+ device_t parent;
+ uintptr_t bus, seg;
sc = device_get_softc(dev);
sc->sc_dev = dev;
+ parent = device_get_parent(dev);
+ BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCIBUS, &bus);
+ sc->sc_busnr = bus;
+ BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCISEG, &seg);
+ sc->sc_domain = seg;
+
#if 0
sgisn_pcib_scan(sc, sc->sc_busnr, sgisn_pcib_maxslots(dev));
#endif
@@ -301,8 +302,8 @@ sgisn_pcib_write_ivar(device_t dev, devi
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;
+ static struct sgisn_fwdev dev;
+ static struct sgisn_fwirq irq;
struct ia64_sal_result r;
u_int devfn, func, maxfunc, slot;
uint8_t hdrtype;
Modified: projects/altix/sys/ia64/sgisn/sgisn_shub.c
==============================================================================
--- projects/altix/sys/ia64/sgisn/sgisn_shub.c Tue Mar 29 00:33:02 2011 (r220118)
+++ projects/altix/sys/ia64/sgisn/sgisn_shub.c Tue Mar 29 00:36:36 2011 (r220119)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/rman.h>
@@ -48,14 +49,16 @@ __FBSDID("$FreeBSD$");
#include <contrib/dev/acpica/include/actables.h>
#include <dev/acpica/acpivar.h>
-// XXX static struct sgisn_hub sgisn_hub;
-
struct sgisn_shub_softc {
- struct sgisn_hub sc_prom_hub;
+ struct sgisn_fwhub *sc_fwhub;
device_t sc_dev;
- void *sc_promaddr;
+ vm_paddr_t sc_membase;
+ vm_size_t sc_memsize;
u_int sc_domain;
- u_int sc_busnr;
+ u_int sc_hubtype; /* SHub type (0=SHub1, 1=SHub2) */
+ u_int sc_nasid_mask;
+ u_int sc_nasid_shft;
+ u_int sc_nasid;
};
static int sgisn_shub_attach(device_t);
@@ -204,7 +207,7 @@ sgisn_shub_dump_sn_info(struct ia64_sal_
}
static void
-sgisn_shub_srat_parse(ACPI_SUBTABLE_HEADER *entry, void *arg)
+sgisn_shub_identify_srat_cb(ACPI_SUBTABLE_HEADER *entry, void *arg)
{
ACPI_SRAT_CPU_AFFINITY *cpu;
ACPI_SRAT_MEM_AFFINITY *mem;
@@ -215,7 +218,7 @@ sgisn_shub_srat_parse(ACPI_SUBTABLE_HEAD
/*
* Use all possible entry types for learning about domains.
- * This probably is highly redundant and could possible be
+ * This probably is highly redundant and could possibly be
* wrong, but it seems more harmful to miss a domain than
* anything else.
*/
@@ -244,7 +247,7 @@ sgisn_shub_srat_parse(ACPI_SUBTABLE_HEAD
return;
if (bootverbose)
- printf("%s: found now domain %u\n", sgisn_shub_name, domain);
+ printf("%s: new domain %u\n", sgisn_shub_name, domain);
/*
* First encounter of this domain. Add a SHub device with a unit
@@ -285,37 +288,175 @@ sgisn_shub_identify(driver_t *drv, devic
}
acpi_walk_subtables((uint8_t *)ptr + sizeof(ACPI_TABLE_SRAT),
- (uint8_t *)ptr + tbl->Length, sgisn_shub_srat_parse, bus);
+ (uint8_t *)ptr + tbl->Length, sgisn_shub_identify_srat_cb, bus);
}
static int
sgisn_shub_probe(device_t dev)
{
+ struct ia64_sal_result r;
+ char desc[80];
+ u_int v;
+
+ /*
+ * NOTICE: This can only be done on a CPU that's connected to the
+ * FSB of the SHub ASIC. As such, the BSP can only validly probe
+ * the SHub it's connected to.
+ *
+ * In order to probe and attach SHubs in other domains, we need to
+ * defer to some CPU connected to that SHub.
+ *
+ * XXX For now, we assume that SHub types are the same across the
+ * system, so we simply query the SHub in our domain and pretend
+ * we queried the one corresponding to the domain this instance
+ * refers to.
+ */
+ r = ia64_sal_entry(SAL_SGISN_SN_INFO, 0, 0, 0, 0, 0, 0, 0);
+ if (r.sal_status != 0)
+ return (ENXIO);
+
+ v = (r.sal_result[0] & 0xff) + 1;;
+ snprintf(desc, sizeof(desc), "SGI SHub%u ASIC", v);
+ device_set_desc_copy(dev, desc);
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+sgisn_shub_attach_srat_cb(ACPI_SUBTABLE_HEADER *entry, void *arg)
+{
+ device_t dev = arg;
+ ACPI_SRAT_MEM_AFFINITY *mem;
struct sgisn_shub_softc *sc;
+
+ if (entry->Type != ACPI_SRAT_TYPE_MEMORY_AFFINITY)
+ return;
sc = device_get_softc(dev);
- device_set_desc(dev, "SGI SHub ASIC ");
- return (BUS_PROBE_DEFAULT);
+ mem = (ACPI_SRAT_MEM_AFFINITY *)(void *)entry;
+ if (mem->ProximityDomain != sc->sc_domain)
+ return;
+ if ((mem->Flags & ACPI_SRAT_MEM_ENABLED) == 0)
+ return;
+
+ sc->sc_membase = mem->BaseAddress;
+ sc->sc_memsize = mem->Length;
}
static int
sgisn_shub_attach(device_t dev)
{
+ struct ia64_sal_result r;
struct sgisn_shub_softc *sc;
+ ACPI_TABLE_HEADER *tbl;
+ device_t child;
+ void *ptr;
+ u_long addr;
+ u_int bus, seg, wdgt;
sc = device_get_softc(dev);
sc->sc_dev = dev;
+ sc->sc_domain = device_get_unit(dev);
+
+ /*
+ * Get the physical memory region that is connected to the MD I/F
+ * of this SHub. It allows us to allocate memory that's close to
+ * this SHub. Fail the attach if we don't have local memory, as
+ * we really depend on it.
+ */
+ tbl = ptr = acpi_find_table(ACPI_SIG_SRAT);
+ acpi_walk_subtables((uint8_t *)ptr + sizeof(ACPI_TABLE_SRAT),
+ (uint8_t *)ptr + tbl->Length, sgisn_shub_attach_srat_cb, dev);
+ if (sc->sc_memsize == 0)
+ return (ENXIO);
+
+ if (bootverbose)
+ device_printf(dev, "%#lx bytes of attached memory at %#lx\n",
+ sc->sc_memsize, sc->sc_membase);
+
+ /*
+ * Obtain our NASID.
+ */
+ r = ia64_sal_entry(SAL_SGISN_SN_INFO, 0, 0, 0, 0, 0, 0, 0);
+ if (r.sal_status != 0)
+ return (ENXIO);
+
+ sc->sc_hubtype = r.sal_result[0] & 0xff;
+ sc->sc_nasid_mask = r.sal_result[1] & 0xffff;
+ sc->sc_nasid_shft = (r.sal_result[1] >> 16) & 0xff;
+ sc->sc_nasid = (sc->sc_membase >> sc->sc_nasid_shft) &
+ sc->sc_nasid_mask;
+
+ if (bootverbose)
+ device_printf(dev, "NASID=%#x\n", sc->sc_nasid);
+
+ /*
+ * Allocate contiguous memory, local to the SHub, for collecting
+ * SHub information from the PROM and for discovering the PCI
+ * host controllers connected to the SHub.
+ */
+ sc->sc_fwhub = contigmalloc(sizeof(struct sgisn_fwhub), M_DEVBUF,
+ M_ZERO, sc->sc_membase, sc->sc_membase + sc->sc_memsize, 16, 0);
+
+ sc->sc_fwhub->hub_pci_maxseg = 0xffffffff;
+ sc->sc_fwhub->hub_pci_maxbus = 0xff;
+ r = ia64_sal_entry(SAL_SGISN_IOHUB_INFO, sc->sc_nasid,
+ ia64_tpa((uintptr_t)sc->sc_fwhub), 0, 0, 0, 0, 0);
+ if (r.sal_status != 0) {
+ contigfree(sc->sc_fwhub, sizeof(struct sgisn_fwhub), M_DEVBUF);
+ return (ENXIO);
+ }
+
+ for (wdgt = 0; wdgt < SGISN_HUB_NWIDGETS; wdgt++)
+ sc->sc_fwhub->hub_widget[wdgt].wgt_hub = sc->sc_fwhub;
+
+ r = ia64_sal_entry(SAL_SGISN_KLCONFIG_ADDR, sc->sc_nasid,
+ 0, 0, 0, 0, 0, 0);
+ device_printf(dev, "KLCONFIG: status=%#lx, addr=%#lx\n",
+ r.sal_status, r.sal_result[0]);
+
+ /*
+ * XXX Hack to avoid having the same PCI busses as children of any
+ * SHub we have. The problem is that we can't pass the nasid to the
+ * the SAL function. So either we get all the busses, irrespective
+ * of the node in which they live or we always get the busses local
+ * to the CPU. I can't tell the difference, because I don't have
+ * busses on the other brick right now.
+ * In any case: we don't have a good way yet to figure out if the
+ * bus connects to the SHub in question.
+ */
+ if (sc->sc_nasid != 0)
+ return (0);
+
+ for (seg = 0; seg <= sc->sc_fwhub->hub_pci_maxseg; seg++) {
+ for (bus = 0; bus <= sc->sc_fwhub->hub_pci_maxbus; bus++) {
+ r = ia64_sal_entry(SAL_SGISN_IOBUS_INFO, seg, bus,
+ ia64_tpa((uintptr_t)&addr), 0, 0, 0, 0);
+ if (r.sal_status == 0 && addr != 0) {
+ child = device_add_child(dev, "pcib", -1);
+ device_set_ivars(child, (void *)(uintptr_t)
+ ((seg << 8) | (bus & 0xff)));
+ }
+ }
+ }
- device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
static int
sgisn_shub_read_ivar(device_t dev, device_t child, int which, uintptr_t *res)
{
-// XXX struct sgisn_shub_softc *sc = device_get_softc(dev);
+ uintptr_t ivars;
+ ivars = (uintptr_t)device_get_ivars(child);
+ switch (which) {
+ case SHUB_IVAR_PCIBUS:
+ *res = ivars & 0xff;
+ return (0);
+ case SHUB_IVAR_PCISEG:
+ *res = ivars >> 8;
+ return (0);
+ }
return (ENOENT);
}
More information about the svn-src-projects
mailing list