From 55c8e0faf57734b99ad8cfe033022058c61bca18 Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Sun, 17 Apr 2011 17:44:25 +0000 Subject: On IP27 systems, fill the array of node hub widget numbers early, so that all hubs are known during autoconf. Then, pick the most populated 2GB window as our DMA memory window. xbridge(4) can thus program the correct settings regardless of the order in which the xbow(4) attach. --- sys/arch/sgi/include/mnode.h | 5 +- sys/arch/sgi/sgi/sginode.c | 108 +++++++++++++++++++++++++++++++++++-------- sys/arch/sgi/xbow/xbow.c | 52 ++++++++++----------- sys/arch/sgi/xbow/xbow.h | 10 +--- sys/arch/sgi/xbow/xbridge.c | 24 +++++++--- sys/arch/sgi/xbow/xheart.c | 3 +- 6 files changed, 138 insertions(+), 64 deletions(-) (limited to 'sys') diff --git a/sys/arch/sgi/include/mnode.h b/sys/arch/sgi/include/mnode.h index 960f76a7bf7..dc7365b98f1 100644 --- a/sys/arch/sgi/include/mnode.h +++ b/sys/arch/sgi/include/mnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mnode.h,v 1.17 2011/04/05 14:43:10 miod Exp $ */ +/* $OpenBSD: mnode.h,v 1.18 2011/04/17 17:44:24 miod Exp $ */ /* * Copyright (c) 2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -481,6 +481,9 @@ int kl_scan_board(lboard_t *, uint, int (*)(klinfo_t *, void *), void *); void kl_get_location(klinfo_t *, struct sgi_device_location *); void kl_get_console_location(console_t *, struct sgi_device_location *); +/* widget number of the XBow `hub', for each node */ +extern int kl_hub_widget[GDA_MAXNODES]; + extern int kl_n_mode; extern u_int kl_n_shift; extern klinfo_t *kl_glass_console; diff --git a/sys/arch/sgi/sgi/sginode.c b/sys/arch/sgi/sgi/sginode.c index 0d5fe0cb4b6..76cf0304e7b 100644 --- a/sys/arch/sgi/sgi/sginode.c +++ b/sys/arch/sgi/sgi/sginode.c @@ -1,6 +1,6 @@ -/* $OpenBSD: sginode.c,v 1.22 2011/04/07 15:30:16 miod Exp $ */ +/* $OpenBSD: sginode.c,v 1.23 2011/04/17 17:44:24 miod Exp $ */ /* - * Copyright (c) 2008, 2009 Miodrag Vallat. + * Copyright (c) 2008, 2009, 2011 Miodrag Vallat. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -42,7 +42,8 @@ #include #include #include -#include + +#include #include #include @@ -63,6 +64,8 @@ void kl_add_memory_ip27(int16_t, int16_t *, unsigned int); void kl_add_memory_ip35(int16_t, int16_t *, unsigned int); +void kl_dma_select(paddr_t, psize_t); + int kl_first_pass_board(lboard_t *, void *); int kl_first_pass_comp(klinfo_t *, void *); @@ -72,6 +75,9 @@ int kl_first_pass_comp(klinfo_t *, void *); #define DB_PRF(x) #endif +/* widget number of the XBow `hub', for each node */ +int kl_hub_widget[GDA_MAXNODES]; + int kl_n_mode = 0; u_int kl_n_shift = 32; klinfo_t *kl_glass_console = NULL; @@ -143,7 +149,19 @@ kl_first_pass_board(lboard_t *boardinfo, void *arg) boardinfo->brd_nasid, boardinfo->brd_nic, boardinfo->brd_numcompts)); + /* + * Assume the worst case of a restricted XBow, as found on + * Origin 200 systems. This value will be overridden should a + * full-blown XBow be found during component enumeration. + * + * On Origin 200, widget 0 reports itself as a Bridge, and + * interrupt widget is hardwired to #a (which is another facet + * of the bridge). + */ + kl_hub_widget[boardinfo->brd_nasid] = 0x0a; + kl_scan_board(boardinfo, KLSTRUCT_ANY, kl_first_pass_comp, arg); + return 0; } @@ -326,6 +344,7 @@ kl_first_pass_comp(klinfo_t *comp, void *arg) xbowcomp = (klxbow_t *)comp; DB_PRF(("\t hub master link %d\n", xbowcomp->xbow_hub_master_link)); + kl_hub_widget[comp->nasid] = xbowcomp->xbow_hub_master_link; for (i = 0; i < MAX_XBOW_LINKS; i++) { if (!ISSET(xbowcomp->xbow_port_info[i].port_flag, XBOW_PORT_ENABLE)) @@ -456,29 +475,63 @@ kl_get_console() return &cfghdr->cons_info; } +/* + * Pick the given window as the DMAable memory window, if it contains more + * memory than our former choice. Expects the base address to be aligned on + * a 2GB boundary. + */ +void +kl_dma_select(paddr_t base, psize_t size) +{ + static psize_t maxsize = 0; + + if (size > maxsize) { + maxsize = size; + dma_constraint.ucr_low = base; + dma_constraint.ucr_high = base | ((1UL << 31) - 1); + } +} + /* * Process memory bank information. * There are two different routines, because IP27 and IP35 do not * layout memory the same way. + * + * This is the opportunity to pick the largest populated 2GB window on a + * 2GB boundary, as our DMA window. */ +/* + * On IP27, access to each DIMM is interleaved, which cause it to map to + * four banks on 128MB boundaries. + * DIMMs of 128MB or smaller map everything in the first bank, though -- + * interleaving would be horribly non-optimal. + */ void kl_add_memory_ip27(int16_t nasid, int16_t *sizes, unsigned int cnt) { paddr_t basepa; uint64_t fp, lp, np; unsigned int seg, nmeg; + paddr_t twogseg; + psize_t twogcnt; - /* - * On IP27, access to each DIMM is interleaved, which cause it to - * map to four banks on 128MB boundaries. - * DIMMs of 128MB or smaller map everything in the first bank, - * though. - */ basepa = (paddr_t)nasid << kl_n_shift; + + /* note we know kl_n_shift >> 31, so 2GB windows can not span nodes */ + twogseg = basepa >> 31; + twogcnt = 0; + while (cnt-- != 0) { nmeg = *sizes++; for (seg = 0; seg < 4; basepa += (1 << 27), seg++) { + /* did we cross a 2GB boundary? */ + if ((basepa >> 31) != twogseg) { + kl_dma_select(twogseg << 31, twogcnt); + twogseg = basepa >> 31; + twogcnt = 0; + } + if (nmeg <= 128) np = seg == 0 ? nmeg : 0; else @@ -505,10 +558,11 @@ kl_add_memory_ip27(int16_t nasid, int16_t *sizes, unsigned int cnt) physmem += atop(32 << 20); } + twogcnt += ptoa(lp - fp); + if (memrange_register(fp, lp, ~(atop(1UL << kl_n_shift) - 1), - lp <= atop(2UL << 30) ? - VM_FREELIST_DEFAULT : VM_FREELIST_DMA32) != 0) { + VM_FREELIST_DEFAULT) != 0) { /* * We could hijack the smallest segment here. * But is it really worth doing? @@ -519,21 +573,36 @@ kl_add_memory_ip27(int16_t nasid, int16_t *sizes, unsigned int cnt) } } } + + kl_dma_select(twogseg << 31, twogcnt); } +/* + * On IP35, the smallest memory DIMMs are 256MB, and the largest is 1GB. + * Memory is reported at 1GB intervals. + */ void kl_add_memory_ip35(int16_t nasid, int16_t *sizes, unsigned int cnt) { paddr_t basepa; uint32_t fp, lp, np; - - /* - * On IP35, the smallest memory DIMMs are 256MB, and the - * largest is 1GB. Memory is reported at 1GB intervals. - */ + paddr_t twogseg; + psize_t twogcnt; basepa = (paddr_t)nasid << kl_n_shift; + + /* note we know kl_n_shift >> 31, so 2GB windows can not span nodes */ + twogseg = basepa >> 31; + twogcnt = 0; + while (cnt-- != 0) { + /* did we cross a 2GB boundary? */ + if ((basepa >> 31) != twogseg) { + kl_dma_select(twogseg << 31, twogcnt); + twogseg = basepa >> 31; + twogcnt = 0; + } + np = *sizes++; if (np != 0) { DB_PRF(("IP35 memory from %p to %p (%u MB)\n", @@ -555,10 +624,11 @@ kl_add_memory_ip35(int16_t nasid, int16_t *sizes, unsigned int cnt) physmem += atop(64 << 20); } + twogcnt += ptoa(lp - fp); + if (memrange_register(fp, lp, ~(atop(1UL << kl_n_shift) - 1), - lp <= atop(2UL << 30) ? - VM_FREELIST_DEFAULT : VM_FREELIST_DMA32) != 0) { + VM_FREELIST_DEFAULT) != 0) { /* * We could hijack the smallest segment here. * But is it really worth doing? @@ -570,6 +640,8 @@ kl_add_memory_ip35(int16_t nasid, int16_t *sizes, unsigned int cnt) } basepa += 1UL << 30; /* 1 GB */ } + + kl_dma_select(twogseg << 31, twogcnt); } /* diff --git a/sys/arch/sgi/xbow/xbow.c b/sys/arch/sgi/xbow/xbow.c index fbea53e8d5f..681b84c1d2f 100644 --- a/sys/arch/sgi/xbow/xbow.c +++ b/sys/arch/sgi/xbow/xbow.c @@ -1,7 +1,7 @@ -/* $OpenBSD: xbow.c,v 1.31 2011/04/05 14:43:11 miod Exp $ */ +/* $OpenBSD: xbow.c,v 1.32 2011/04/17 17:44:24 miod Exp $ */ /* - * Copyright (c) 2008, 2009 Miodrag Vallat. + * Copyright (c) 2008, 2009, 2011 Miodrag Vallat. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -231,9 +231,12 @@ xbowsubmatch(struct device *parent, void *vcf, void *aux) * Widget probe order for various components */ +#ifdef TGT_OCTANE /* 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 }; +#endif +#ifdef TGT_ORIGIN /* Origin 200: probe onboard devices, and there is nothing more */ const uint8_t xbow_probe_singlebridge[] = { 0x08, 0 }; @@ -249,6 +252,7 @@ const uint8_t xbow_probe_pbrick[] = /* 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 }; +#endif /* * Structures used to carry information between KL and attachment code. @@ -256,7 +260,6 @@ const uint8_t xbow_probe_xbrick[] = struct xbow_config { int valid; - int master; int widgets[WIDGET_MAX + 1 - WIDGET_MIN]; }; @@ -273,7 +276,9 @@ xbowattach(struct device *parent, struct device *self, void *aux) int16_t nasid = maa->maa_nasid; uint32_t wid, vendor, product; const struct xbow_product *p; +#ifdef TGT_ORIGIN struct xbow_config cfg; +#endif struct xbow_kl_config klcfg; uint widget; @@ -295,15 +300,11 @@ xbowattach(struct device *parent, struct device *self, void *aux) printf(": %s", p->productname); printf(" revision %d\n", WIDGET_ID_REV(wid)); - memset(&cfg, 0, sizeof cfg); switch (sys_config.system_type) { - case SGI_OCTANE: - klcfg.probe_order = xbow_probe_octane; - break; -#ifdef TGT_ORIGIN default: +#ifdef TGT_ORIGIN + memset(&cfg, 0, sizeof cfg); klcfg.cfg = &cfg; - klcfg.probe_order = NULL; /* * If widget 0 reports itself as a bridge, this is not a @@ -312,40 +313,39 @@ xbowattach(struct device *parent, struct device *self, void *aux) */ if (vendor == XBOW_VENDOR_SGI4 && product == XBOW_PRODUCT_SGI4_BRIDGE) { - /* - * Interrupt widget is hardwired to #a (this is another - * facet of this bridge). - */ - xbow_node_hub_widget[nasid] = 0x0a; klcfg.probe_order = xbow_probe_singlebridge; } else { /* * Get crossbow information from the KL configuration. */ + klcfg.probe_order = NULL; kl_scan_node(nasid, KLBRD_ANY, xbow_kl_search_brd, &klcfg); + if (klcfg.probe_order == NULL) + klcfg.probe_order = xbow_probe_baseio; - 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_node_hub_widget[nasid] = cfg.master; + /* should not happen, but I can't help being paranoid */ + if (cfg.valid == 0) { + printf("%s: no hub\n", self->dv_xname); + return; + } } break; +#endif +#ifdef TGT_OCTANE + case SGI_OCTANE: + klcfg.probe_order = xbow_probe_octane; + break; #endif } - if (klcfg.probe_order == NULL) - klcfg.probe_order = xbow_probe_baseio; for (; *klcfg.probe_order != 0; klcfg.probe_order++) { widget = *klcfg.probe_order; +#ifdef TGT_ORIGIN if (cfg.valid != 0 && !ISSET(cfg.widgets[widget - WIDGET_MIN], XBOW_PORT_ENABLE)) continue; +#endif (void)xbow_attach_widget(self, nasid, widget, xbowsubmatch, xbowprint); } @@ -449,7 +449,6 @@ xbow_kl_search_mplane(klinfo_t *c, void *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; @@ -646,7 +645,6 @@ xbow_space_vaddr(bus_space_tag_t t, bus_space_handle_t h) * the master nasid; other nodes do not handle interrupts. */ -int xbow_node_hub_widget[XBOW_MAX]; uint64_t xbow_intr_address; int (*xbow_intr_widget_intr_register)(int, int, int *) = NULL; diff --git a/sys/arch/sgi/xbow/xbow.h b/sys/arch/sgi/xbow/xbow.h index 4d763dbfb75..6d921cb2d3b 100644 --- a/sys/arch/sgi/xbow/xbow.h +++ b/sys/arch/sgi/xbow/xbow.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xbow.h,v 1.11 2011/04/05 14:43:11 miod Exp $ */ +/* $OpenBSD: xbow.h,v 1.12 2011/04/17 17:44:24 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -61,14 +61,6 @@ extern void (*xbow_intr_widget_intr_clear)(int); #define WIDGET_MIN 8 #define WIDGET_MAX 15 -#ifdef TGT_OCTANE -#define XBOW_MAX 1 -#else -#define XBOW_MAX GDA_MAXNODES -#endif - -/* widget number of the XBow `hub', for each node */ -extern int xbow_node_hub_widget[/*XBOW_MAX*/]; /* interrupt register address on the master hub */ extern uint64_t xbow_intr_address; diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c index e7a51c25fc9..c7192ef6df6 100644 --- a/sys/arch/sgi/xbow/xbridge.c +++ b/sys/arch/sgi/xbow/xbridge.c @@ -1,7 +1,7 @@ -/* $OpenBSD: xbridge.c,v 1.81 2011/04/05 14:43:11 miod Exp $ */ +/* $OpenBSD: xbridge.c,v 1.82 2011/04/17 17:44:24 miod Exp $ */ /* - * Copyright (c) 2008, 2009 Miodrag Vallat. + * Copyright (c) 2008, 2009, 2011 Miodrag Vallat. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1898,15 +1898,14 @@ xbridge_setup(struct xbpci_softc *xb) switch (sys_config.system_type) { default: #ifdef TGT_ORIGIN - dirmap |= xbow_node_hub_widget[ + dirmap |= kl_hub_widget[ IP27_PHYS_TO_NODE(dma_constraint.ucr_low)] << BRIDGE_DIRMAP_WIDGET_SHIFT; break; #endif #ifdef TGT_OCTANE case SGI_OCTANE: - dirmap |= xbow_node_hub_widget[0/*masternasid*/] << - BRIDGE_DIRMAP_WIDGET_SHIFT; + dirmap |= IP30_HEART_WIDGET << BRIDGE_DIRMAP_WIDGET_SHIFT; break; #endif } @@ -1994,8 +1993,19 @@ xbridge_setup(struct xbpci_softc *xb) xbridge_write_reg(xb, BRIDGE_IER, 0); xbridge_write_reg(xb, BRIDGE_INT_MODE, 0); xbridge_write_reg(xb, BRIDGE_INT_DEV, 0); - int_addr = ((uint64_t)xbow_node_hub_widget[masternasid] << 48) | - (xbow_intr_address & ((1UL << 48) - 1)); + int_addr = xbow_intr_address & ((1UL << 48) - 1); + switch (sys_config.system_type) { + default: +#ifdef TGT_ORIGIN + int_addr |= (uint64_t)kl_hub_widget[masternasid] << 48; + break; +#endif +#ifdef TGT_OCTANE + case SGI_OCTANE: + int_addr |= (uint64_t)IP30_HEART_WIDGET << 48; + break; +#endif + } xbridge_write_reg(xb, WIDGET_INTDEST_ADDR_LOWER, int_addr); xbridge_write_reg(xb, WIDGET_INTDEST_ADDR_UPPER, int_addr >> 32); diff --git a/sys/arch/sgi/xbow/xheart.c b/sys/arch/sgi/xbow/xheart.c index 6212ba0102f..5cf2916462a 100644 --- a/sys/arch/sgi/xbow/xheart.c +++ b/sys/arch/sgi/xbow/xheart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xheart.c,v 1.21 2011/04/05 14:43:11 miod Exp $ */ +/* $OpenBSD: xheart.c,v 1.22 2011/04/17 17:44:24 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -134,7 +134,6 @@ xheart_attach(struct device *parent, struct device *self, void *aux) oba.oba_flags = ONEWIRE_SCAN_NOW | ONEWIRE_NO_PERIODIC_SCAN; config_found(self, &oba, onewirebus_print); - xbow_node_hub_widget[0/*xaa->xaa_nasid*/] = xaa->xaa_widget; xbow_intr_address = 0x80; xbow_intr_widget_intr_register = xheart_intr_register; xbow_intr_widget_intr_establish = xheart_intr_establish; -- cgit v1.2.3