diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-27 19:06:21 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-27 19:06:21 +0000 |
commit | e2eb4d39e6917a4a14ec459a1a8df7a4f74c5526 (patch) | |
tree | c9bc8a644d9183d0a771b5fc573594bba8f89157 /sys/arch/sgi/xbow | |
parent | fdfd6841927b99237cc814cfc3f85745ad56bffa (diff) |
Use the KL enumeration functions to try and figure out what kind of XBow
we have, in order to pick a widget enumeration order matching the PROM.
This is especially important when the boot path is in dksc() syntax.
Diffstat (limited to 'sys/arch/sgi/xbow')
-rw-r--r-- | sys/arch/sgi/xbow/xbow.c | 267 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xheart.c | 11 |
2 files changed, 178 insertions, 100 deletions
diff --git a/sys/arch/sgi/xbow/xbow.c b/sys/arch/sgi/xbow/xbow.c index 72a00042e01..35119ec9f16 100644 --- a/sys/arch/sgi/xbow/xbow.c +++ b/sys/arch/sgi/xbow/xbow.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xbow.c,v 1.6 2009/05/02 21:30:13 miod Exp $ */ +/* $OpenBSD: xbow.c,v 1.7 2009/05/27 19:06:20 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. @@ -75,14 +75,13 @@ int xbowmatch(struct device *, void *, void *); void xbowattach(struct device *, struct device *, void *); -int xbowprint_pass1(void *, const char *); -int xbowprint_pass2(void *, const char *); -int xbowsubmatch_pass1(struct device *, void *, void *); -int xbowsubmatch_pass2(struct device *, void *, void *); +int xbowprint(void *, const char *); +int xbowsubmatch(struct device *, void *, void *); int xbow_attach_widget(struct device *, int16_t, int, int (*)(struct device *, void *, void *), cfprint_t); -void xbow_enumerate(struct device *, int16_t, int, - int (*)(struct device *, void *, void *), cfprint_t); + +int xbow_kl_search_brd(lboard_t *, void *); +int xbow_kl_search_mplane(klinfo_t *, void *); uint32_t xbow_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); uint64_t xbow_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); @@ -210,24 +209,7 @@ xbow_identify(uint32_t vendor, uint32_t product) } int -xbowprint_pass1(void *aux, const char *pnp) -{ - struct xbow_attach_args *xaa = aux; - const struct xbow_product *p; - - p = xbow_identify(xaa->xaa_vendor, xaa->xaa_product); - - if (pnp == NULL) { - printf(" widget %d", xaa->xaa_widget); - if (p != NULL) - printf(": %s", p->productname); - } - - return (QUIET); -} - -int -xbowprint_pass2(void *aux, const char *pnp) +xbowprint(void *aux, const char *pnp) { struct xbow_attach_args *xaa = aux; const struct xbow_product *p; @@ -253,22 +235,7 @@ xbowprint_pass2(void *aux, const char *pnp) } int -xbowsubmatch_pass1(struct device *parent, void *vcf, void *aux) -{ - int rc; - - if (xbow_intr_widget != 0) - return 0; - - rc = xbowsubmatch_pass2(parent, vcf, aux); - if (rc < 20) - rc = 0; - - return rc; -} - -int -xbowsubmatch_pass2(struct device *parent, void *vcf, void *aux) +xbowsubmatch(struct device *parent, void *vcf, void *aux) { struct xbow_attach_args *xaa = aux; struct cfdata *cf = vcf; @@ -281,12 +248,53 @@ xbowsubmatch_pass2(struct device *parent, void *vcf, void *aux) return (*cf->cf_attach->ca_match)(parent, vcf, aux); } +/* + * Widget probe order for various components + */ + +/* Octane: probe Heart first, then onboard devices, then other slots */ +const uint8_t xbow_probe_octane[] = + { 0x08, 0x0f, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0 }; +/* Origin 200: probe onboard devices, and there is nothing more */ +const uint8_t xbow_probe_singlebridge[] = + { 0x08 }; +/* Base I/O board: probe in ascending order */ +const uint8_t xbow_probe_baseio[] = + { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0 }; +/* I-Brick: probe PCI buses first (starting with the onboard devices) */ +const uint8_t xbow_probe_ibrick[] = + { 0x0f, 0x0e, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0 }; +/* P-Brick: all widgets are PCI buses, probe in recommended order */ +const uint8_t xbow_probe_pbrick[] = + { 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x0a, 0x0b, 0 }; +/* X-Brick: all widgets are XIO devices, probe in recommended order */ +const uint8_t xbow_probe_xbrick[] = + { 0x08, 0x09, 0x0c, 0x0d, 0x0a, 0x0b, 0x0e, 0x0f, 0 }; + +/* + * Structures used to carry information between KL and atatchment code. + */ + +struct xbow_config { + int valid; + int master; + int widgets[WIDGET_MAX + 1 - WIDGET_MIN]; +}; + +struct xbow_kl_config { + const uint8_t *probe_order; + struct xbow_config *cfg; +}; + void xbowattach(struct device *parent, struct device *self, void *aux) { int16_t nasid = 0; /* XXX for now... */ uint32_t wid, vendor, product; const struct xbow_product *p; + struct xbow_config cfg; + struct xbow_kl_config klcfg; + uint widget; /* * This assumes widget 0 is the XBow itself (or an XXBow). @@ -301,66 +309,66 @@ xbowattach(struct device *parent, struct device *self, void *aux) p != NULL ? p->productname : "unknown xbow", (wid & WIDGET_ID_REV_MASK) >> WIDGET_ID_REV_SHIFT); - /* - * Default value for the interrupt register. If this system - * has a Heart widget, the Heart code will take care of changing it. - */ - xbow_intr_widget_register = (1UL << 47) /* XIO I/O space */ | - ((paddr_t)IP27_RHUB_ADDR(nasid, HUB_IR_CHANGE) - - IP27_NODE_IO_BASE(0)) /* HUB register offset */; - - /* - * If widget 0 reports itself as a bridge, this is not a - * complete XBow, but only a limited topology. This is - * found on at least the Origin 200. - */ - if (vendor == XBOW_VENDOR_SGI4 && product == XBOW_PRODUCT_SGI4_BRIDGE) { + memset(&cfg, 0, sizeof cfg); + switch (sys_config.system_type) { + case SGI_OCTANE: + klcfg.probe_order = xbow_probe_octane; + break; +#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000) + default: /* - * Interrupt widget is hardwired to #a (this is another - * facet of this bridge). + * Default value for the interrupt register. */ - xbow_intr_widget = 0x0a; + xbow_intr_widget_register = (1UL << 47) /* XIO I/O space */ | + ((paddr_t)IP27_RHUB_ADDR(nasid, HUB_IR_CHANGE) - + IP27_NODE_IO_BASE(0)) /* HUB register offset */; - xbow_attach_widget(self, nasid, WIDGET_MIN, - xbowsubmatch_pass2, xbowprint_pass2); - } else { - /* - * XXX This widget number is actually the Hub part of the - * XXX crossbow, and is where memory and interrupt logic - * XXX resources are connected to. - * XXX The exact widget number ought to be computed from - * XXX the KL configuration graph; I'm hardcoding it for - * XXX now because I am lazy and we only care about the - * XXX first node at the moment. -- miod - */ - if (sys_config.system_type != SGI_OCTANE) - xbow_intr_widget = 0x0a; + klcfg.cfg = &cfg; + klcfg.probe_order = NULL; /* - * Enumerate the other widgets. - * We'll do two passes - one to give the first Heart or a Hub a - * chance to setup interrupt routing, and one to attach all - * other widgets. + * If widget 0 reports itself as a bridge, this is not a + * complete XBow, but only a limited topology. This is + * found on at least the Origin 200. */ - if (xbow_intr_widget == 0) - xbow_enumerate(self, nasid, 0, - xbowsubmatch_pass1, xbowprint_pass1); - xbow_enumerate(self, nasid, xbow_intr_widget, - xbowsubmatch_pass2, xbowprint_pass2); + if (vendor == XBOW_VENDOR_SGI4 && + product == XBOW_PRODUCT_SGI4_BRIDGE) { + /* + * Interrupt widget is hardwired to #a (this is another + * facet of this bridge). + */ + xbow_intr_widget = 0x0a; + klcfg.probe_order = xbow_probe_singlebridge; + } else { + /* + * Get crossbow information from the KL configuration. + */ + kl_scan_node(nasid, KLBRD_ANY, xbow_kl_search_brd, + &klcfg); + + if (cfg.valid == 0) + panic("no hub"); + + /* + * This widget number is actually the Hub part of the + * crossbow, and is where memory and interrupt logic + * resources are connected to. + */ + xbow_intr_widget = cfg.master; + } + break; +#endif } -} -void -xbow_enumerate(struct device *self, int16_t nasid, int skip, - int (*sm)(struct device *, void *, void *), cfprint_t print) -{ - int widget; - - for (widget = WIDGET_MIN; widget <= WIDGET_MAX; widget++) { - if (widget == skip) + if (klcfg.probe_order == NULL) + klcfg.probe_order = xbow_probe_baseio; + for (; *klcfg.probe_order != 0; klcfg.probe_order++) { + widget = *klcfg.probe_order; + if (cfg.valid != 0 && + !ISSET(cfg.widgets[widget - WIDGET_MIN], XBOW_PORT_ENABLE)) continue; - - (void)xbow_attach_widget(self, nasid, widget, sm, print); + (void)xbow_attach_widget(self, nasid, widget, xbowsubmatch, + xbowprint); } } @@ -411,6 +419,81 @@ xbow_attach_widget(struct device *self, int16_t nasid, int widget, return 0; } +#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000) + +/* + * These two functions try to figure out the configuration of the XBow + * on this node. + * + * We are looking for two pieces of information: + * - the Hub widget, to which memory is attached and interrupts are routed. + * - what kind of Brick we are. + * + * The first information can be obtained easily by looking for a MPLANE type + * board. However there is no easy way to figure the second part, except for + * checking what kind of boards are reported. + * + * A BaseIO board will report itself once, as a single widget. Bricks, on the + * other hand, appear for each of the widgets they provide. + */ + +int +xbow_kl_search_brd(lboard_t *brd, void *arg) +{ + struct xbow_kl_config *cfg = arg; + + switch (brd->brd_type & IP27_BC_MASK) { + case IP27_BC_MPLANE: + if (cfg->cfg->valid == 0) + kl_scan_board(brd, KLSTRUCT_XBOW, xbow_kl_search_mplane, + cfg->cfg); + break; + case IP27_BC_IO: + if (cfg->probe_order == NULL) + cfg->probe_order = xbow_probe_baseio; + break; + case IP27_BC_BRICK: + if (cfg->probe_order == NULL) + switch (brd->brd_type) { + case IP27_BRD_IBRICK: + cfg->probe_order = xbow_probe_ibrick; + break; + case IP27_BRD_PBRICK: + cfg->probe_order = xbow_probe_pbrick; + break; + case IP27_BRD_XBRICK: + cfg->probe_order = xbow_probe_xbrick; + break; + default: + /* unknown brick */ + break; + } + break; + } + + if (cfg->cfg->valid != 0 && cfg->probe_order != NULL) + return 1; /* stop enumeration */ + + return 0; +} + +int +xbow_kl_search_mplane(klinfo_t *c, void *arg) +{ + klxbow_t *xbow = (klxbow_t *)c; + struct xbow_config *cfg = arg; + uint w; + + cfg->valid = 1; + cfg->master = xbow->xbow_hub_master_link; + for (w = WIDGET_MIN; w <= WIDGET_MAX; w++) + cfg->widgets[w - WIDGET_MIN] = + xbow->xbow_port_info[w - WIDGET_MIN].port_flag; + + return 1; +} + +#endif /* * Bus access primitives. diff --git a/sys/arch/sgi/xbow/xheart.c b/sys/arch/sgi/xbow/xheart.c index 3d1ee8b2f56..11edb90eec9 100644 --- a/sys/arch/sgi/xbow/xheart.c +++ b/sys/arch/sgi/xbow/xheart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xheart.c,v 1.7 2009/05/08 18:42:07 miod Exp $ */ +/* $OpenBSD: xheart.c,v 1.8 2009/05/27 19:06:20 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -78,13 +78,8 @@ xheart_match(struct device *parent, void *match, void *aux) struct xbow_attach_args *xaa = aux; if (xaa->xaa_vendor == XBOW_VENDOR_SGI4 && - xaa->xaa_product == XBOW_PRODUCT_SGI4_HEART) { - /* - * Only match if no interrupt widget has registered yet. - * There should be only one Heart in a system anyway. - */ - return xbow_intr_widget == 0 ? 20 : 0; - } + xaa->xaa_product == XBOW_PRODUCT_SGI4_HEART) + return 1; return 0; } |