summaryrefslogtreecommitdiff
path: root/sys/arch/sgi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r--sys/arch/sgi/conf/files.sgi10
-rw-r--r--sys/arch/sgi/dev/dsrtc.c11
-rw-r--r--sys/arch/sgi/include/bus.h4
-rw-r--r--sys/arch/sgi/include/mnode.h377
-rw-r--r--sys/arch/sgi/pci/ioc.c13
-rw-r--r--sys/arch/sgi/sgi/ip27_machdep.c374
-rw-r--r--sys/arch/sgi/sgi/ip30_machdep.c15
-rw-r--r--sys/arch/sgi/sgi/sginode.c299
-rw-r--r--sys/arch/sgi/xbow/files.xbow8
-rw-r--r--sys/arch/sgi/xbow/xbow.c131
-rw-r--r--sys/arch/sgi/xbow/xbow.h11
-rw-r--r--sys/arch/sgi/xbow/xbridge.c64
12 files changed, 1235 insertions, 82 deletions
diff --git a/sys/arch/sgi/conf/files.sgi b/sys/arch/sgi/conf/files.sgi
index edb7841f249..065be6a3cf4 100644
--- a/sys/arch/sgi/conf/files.sgi
+++ b/sys/arch/sgi/conf/files.sgi
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sgi,v 1.23 2009/04/12 17:56:56 miod Exp $
+# $OpenBSD: files.sgi,v 1.24 2009/04/13 21:17:52 miod Exp $
#
# maxpartitions must be first item in files.${ARCH}
#
@@ -57,13 +57,9 @@ file arch/sgi/localbus/macebus.c macebus
file arch/sgi/localbus/macectrl.S macebus
#
-# Origin200/Origin2000 XBOW mux bridge
+# Origin200/Origin2000 node configuration enumerator, and
+# Octane XBOW mux bridge
#
-define xbow {[vendor = -1], [product = -1]}
-device xbow
-attach xbow at mainbus
-file arch/sgi/xbow/xbow.c xbow
-
include "arch/sgi/xbow/files.xbow"
include "dev/onewire/files.onewire"
diff --git a/sys/arch/sgi/dev/dsrtc.c b/sys/arch/sgi/dev/dsrtc.c
index a739a04c3b9..f33889e7afb 100644
--- a/sys/arch/sgi/dev/dsrtc.c
+++ b/sys/arch/sgi/dev/dsrtc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsrtc.c,v 1.1 2008/04/07 22:36:26 miod Exp $ */
+/* $OpenBSD: dsrtc.c,v 1.2 2009/04/13 21:17:54 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -95,10 +95,13 @@ tobcd(int x)
int
dsrtc_match_ioc(struct device *parent, void *match, void *aux)
{
- if (sys_config.system_type != SGI_OCTANE)
+ switch (sys_config.system_type) {
+ case SGI_OCTANE:
+ case SGI_O200:
+ return 1;
+ default:
return 0;
-
- return 1;
+ }
}
void
diff --git a/sys/arch/sgi/include/bus.h b/sys/arch/sgi/include/bus.h
index dfd9a7f615f..41fae205c06 100644
--- a/sys/arch/sgi/include/bus.h
+++ b/sys/arch/sgi/include/bus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus.h,v 1.11 2008/08/25 14:05:51 jsing Exp $ */
+/* $OpenBSD: bus.h,v 1.12 2009/04/13 21:17:54 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved.
@@ -48,7 +48,7 @@ typedef struct mips_bus_space bus_space_t;
struct mips_bus_space {
struct extent *bus_extent;
bus_addr_t bus_base;
- bus_addr_t bus_base_dma;
+ void *bus_private;
int32_t bus_reverse;
u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t,
bus_size_t);
diff --git a/sys/arch/sgi/include/mnode.h b/sys/arch/sgi/include/mnode.h
new file mode 100644
index 00000000000..e0ed9a39329
--- /dev/null
+++ b/sys/arch/sgi/include/mnode.h
@@ -0,0 +1,377 @@
+/* $OpenBSD: mnode.h,v 1.1 2009/04/13 21:17:54 miod Exp $ */
+
+/*
+ * Copyright (c) 2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MACHINE_MNODE_H__
+#define __MACHINE_MNODE_H__
+
+/*
+ * Definitions for Nodes set up in M-Mode. Some stuff here
+ * inspired by information gathered from Linux source code.
+ */
+
+/*
+ * IP27 uses XKSSEG to access the 1TB memory area.
+ */
+#define IP27_CAC_BASE 0xa800000000000000 /* Cached space */
+
+/*
+ * IP27 uses XKPHYS space for accessing special objects.
+ * Note that IP27_UNCAC_BASE is a linear space without specials.
+ */
+#define IP27_HSPEC_BASE 0x9000000000000000 /* Hub Special space */
+#define IP27_IO_BASE 0x9200000000000000 /* I/O space */
+#define IP27_MSPEC_BASE 0x9400000000000000 /* Memory Special space */
+#define IP27_UNCAC_BASE 0x9600000000000000 /* Uncached space */
+
+/*
+ * Macros used to find the base of each nodes address space.
+ * In M mode each node space is 4GB.
+ */
+#define IP27_NODE_BASE(space, node) (space + ((long)(node) << 32))
+#define OP27_NODE_SIZE 0x00000000100000000ULL
+#define IP27_NODE_SIZE_MASK 0x000000000ffffffffULL
+
+#define IP27_NODE_CAC_BASE(node) (IP27_NODE_BASE(IP27_CAC_BASE, node))
+#define IP27_NODE_HSPEC_BASE(node) (IP27_NODE_BASE(IP27_HSPEC_BASE, node))
+#define IP27_NODE_IO_BASE(node) (IP27_NODE_BASE(IP27_IO_BASE, node))
+#define IP27_NODE_MSPEC_BASE(node) (IP27_NODE_BASE(IP27_MSPEC_BASE, node))
+#define IP27_NODE_UNCAC_BASE(node) (IP27_NODE_BASE(IP27_UNCAC_BASE, node))
+
+/* Get typed address to nodes uncached space */
+#define IP27_UNCAC_ADDR(type, node, offs) \
+ ((type)(IP27_NODE_UNCAC_BASE(node) + ((offs) & IP27_NODE_SIZE_MASK)))
+
+/*
+ * IP27 platforms uses something called kldir to describe each
+ * nodes configuration. Directory entries looks like:
+ */
+#define IP27_KLDIR_MAGIC 0x434d5f53505f5357
+
+typedef struct kldir_entry {
+ uint64_t magic;
+ off_t offset; /* Offset from start of node space */
+ void *pointer;
+ size_t size; /* Size in bytes */
+ uint64_t count; /* Number of entries if array, 1 if not */
+ size_t stride; /* Stride if array, 0 if not */
+ char rsvd[16]; /* Pad entry to 0x40 bytes */
+ /* NOTE: These 16 bytes are used in the Partition KLDIR
+ entry to store partition info. Refer to klpart.h for this. */
+} kldir_entry_t;
+
+/* Get address to a specific directory entry */
+#define IP27_KLD_BASE(node) IP27_UNCAC_ADDR(kldir_entry_t *, node, 0x2000)
+#define IP27_KLD_LAUNCH(node) (IP27_KLD_BASE(node) + 0)
+#define IP27_KLD_KLCONFIG(node) (IP27_KLD_BASE(node) + 1)
+#define IP27_KLD_NMI(node) (IP27_KLD_BASE(node) + 2)
+#define IP27_KLD_GDA(node) (IP27_KLD_BASE(node) + 3)
+#define IP27_KLD_FREEMEM(node) (IP27_KLD_BASE(node) + 4)
+#define IP27_KLD_SYMMON_STK(node) (IP27_KLD_BASE(node) + 5)
+#define IP27_KLD_PI_ERROR(node) (IP27_KLD_BASE(node) + 6)
+#define IP27_KLD_KERN_VARS(node) (IP27_KLD_BASE(node) + 7)
+#define IP27_KLD_KERN_XP(node) (IP27_KLD_BASE(node) + 8)
+#define IP27_KLD_KERN_PARTID(node) (IP27_KLD_BASE(node) + 9)
+
+/*
+ * KLCONFIG is a linked list of data structures describing the
+ * system configuration.
+ */
+typedef uint32_t klconf_off_t;
+typedef char confidence_t;
+
+typedef struct console_s {
+ unsigned long uart_base;
+ unsigned long config_base;
+ unsigned long memory_base;
+ short baud;
+ short flag;
+ int type;
+ int16_t nasid;
+ char wid;
+ char npci;
+ uint64_t baseio_nic;
+} console_t;
+
+typedef struct klc_malloc_hdr {
+ klconf_off_t km_base;
+ klconf_off_t km_limit;
+ klconf_off_t km_current;
+} klc_malloc_hdr_t;
+
+/* KLCONFIG header addressed by IP27_KLCONFIG_HDR(node) */
+#define IP27_KLCONFIG_HDR(n) \
+ IP27_UNCAC_ADDR(kl_config_hdr_t *, n, IP27_KLD_KLCONFIG(n)->offset)
+
+typedef struct kl_config_hdr {
+ uint64_t magic; /* set this to KLCFGINFO_MAGIC */
+ uint32_t version; /* structure version number */
+ klconf_off_t malloc_hdr_off; /* offset of ch_malloc_hdr */
+ klconf_off_t cons_off; /* offset of ch_cons */
+ klconf_off_t board_info; /* the link list of boards */
+ console_t cons_info; /* address info of the console */
+ klc_malloc_hdr_t malloc_hdr[3];
+ confidence_t sw_belief; /* confidence that software is bad*/
+ confidence_t sn0net_belief; /* confidence that sn0net is bad */
+} kl_config_hdr_t;
+
+/* Board info. */
+#define IP27_KLFIRST_BOARD(n) \
+ IP27_UNCAC_ADDR(lboard_t *, n, IP27_KLCONFIG_HDR(n)->board_info)
+#define IP27_KLNEXT_BOARD(n, board) \
+ IP27_UNCAC_ADDR(lboard_t *, n, board->brd_next)
+#define MAX_COMPTS_PER_BRD 24
+typedef struct lboard_s {
+ klconf_off_t brd_next; /* Next BOARD */
+ uint8_t struct_type; /* type, local or remote */
+ unsigned char brd_type; /* type+class */
+ unsigned char brd_sversion; /* version of this structure */
+ unsigned char brd_brevision; /* board revision */
+ unsigned char brd_promver; /* board prom version, if any */
+ unsigned char brd_flags; /* Enabled, Disabled etc */
+ unsigned char brd_slot; /* slot number */
+ unsigned short brd_debugsw; /* Debug switches */
+ short brd_module; /* module to which it belongs */
+ char brd_partition; /* Partition number */
+ unsigned short brd_diagval; /* diagnostic value */
+ unsigned short brd_diagparm; /* diagnostic parameter */
+ unsigned char brd_inventory; /* inventory history */
+ unsigned char brd_numcompts; /* Number of components */
+ uint64_t brd_nic; /* Number in CAN */
+ int16_t brd_nasid; /* passed parameter */
+ klconf_off_t brd_compts[MAX_COMPTS_PER_BRD]; /* COMPONENTS */
+ klconf_off_t brd_errinfo; /* Board's error information */
+ struct lboard_s *brd_parent; /* Logical parent for this brd */
+ uint32_t brd_graph_link; /* vertex hdl to connect extrn compts */
+ confidence_t brd_confidence; /* confidence that the board is bad */
+ int16_t brd_owner; /* who owns this board */
+ uint8_t brd_nic_flags; /* To handle 8 more NICs */
+ char brd_name[32];
+} lboard_t;
+
+/* Definitions of board type and class */
+#define IP27_BC_MASK 0xf0
+#define IP27_BC_NODE 0x10
+#define IP27_BC_IO 0x20
+#define IP27_BC_ROUTER 0x30
+#define IP27_BC_MPLANE 0x40
+#define IP27_BC_GRAF 0x50
+#define IP27_BC_HDTV 0x60
+#define IP27_BC_BRICK 0x70
+
+#define IP27_BT_MASK 0x0f
+#define IP27_BT_CPU 0x01
+#define IP27_BT_BASEIO 0x01
+#define IP27_BT_MPLANE8 0x01
+
+
+/* Component info. Common info about a component. */
+typedef struct klinfo_s { /* Generic info */
+ unsigned char struct_type; /* type of this structure */
+ unsigned char struct_version; /* version of this structure */
+ unsigned char flags; /* Enabled, disabled etc */
+ unsigned char revision; /* component revision */
+ unsigned short diagval; /* result of diagnostics */
+ unsigned short diagparm; /* diagnostic parameter */
+ unsigned char inventory; /* previous inventory status */
+ uint64_t nic; /* Must be aligned properly */
+ unsigned char physid; /* physical id of component */
+ unsigned int virtid; /* virtual id as seen by system */
+ unsigned char widid; /* Widget id - if applicable */
+ int16_t nasid; /* node number - from parent */
+ char pad1; /* pad out structure. */
+ char pad2; /* pad out structure. */
+ void *arcs_compt; /* ptr to the arcs struct for ease*/
+ klconf_off_t errinfo; /* component specific errors */
+ unsigned short pad3; /* pci fields have moved over to */
+ unsigned short pad4; /* klbri_t */
+} klinfo_t;
+
+#define KLCONFIG_INFO_ENABLED(_i) ((_i)->flags & KLINFO_ENABLE)
+/*
+ * Component structures.
+ * Following are the currently identified components:
+ * CPU, HUB, MEM_BANK,
+ * XBOW(consists of 16 WIDGETs, each of which can be HUB or GRAPHICS or BRIDGE)
+ * BRIDGE, IOC3, SuperIO, SCSI, FDDI
+ * ROUTER
+ * GRAPHICS
+ */
+#define KLSTRUCT_UNKNOWN 0
+#define KLSTRUCT_CPU 1
+#define KLSTRUCT_HUB 2
+#define KLSTRUCT_MEMBNK 3
+#define KLSTRUCT_XBOW 4
+#define KLSTRUCT_BRI 5
+#define KLSTRUCT_IOC3 6
+#define KLSTRUCT_PCI 7
+#define KLSTRUCT_VME 8
+#define KLSTRUCT_ROU 9
+#define KLSTRUCT_GFX 10
+#define KLSTRUCT_SCSI 11
+#define KLSTRUCT_FDDI 12
+#define KLSTRUCT_MIO 13
+#define KLSTRUCT_DISK 14
+#define KLSTRUCT_TAPE 15
+#define KLSTRUCT_CDROM 16
+#define KLSTRUCT_HUB_UART 17
+#define KLSTRUCT_IOC3ENET 18
+#define KLSTRUCT_IOC3UART 19
+#define KLSTRUCT_UNUSED 20 /* XXX UNUSED */
+#define KLSTRUCT_IOC3PCKM 21
+#define KLSTRUCT_RAD 22
+#define KLSTRUCT_HUB_TTY 23
+#define KLSTRUCT_IOC3_TTY 24
+
+typedef struct klport_s {
+ int16_t port_nasid;
+ unsigned char port_flag;
+ klconf_off_t port_offset;
+} klport_t;
+
+/* KLSTRUCT_CPU: CPU component info */
+typedef struct klcpu_s {
+ klinfo_t cpu_info;
+ uint16_t cpu_prid; /* Processor PRID value */
+ uint16_t cpu_fpirr; /* FPU IRR value */
+ uint16_t cpu_speed; /* Speed in MHZ */
+ uint16_t cpu_scachesz; /* secondary cache size in MB */
+ uint16_t cpu_scachespeed;/* secondary cache speed in MHz */
+} klcpu_t;
+
+/* KLSTRUCT_HUB: Hub */
+typedef struct klhub_s {
+ klinfo_t hub_info;
+ uint32_t hub_flags; /* PCFG_HUB_xxx flags */
+ klport_t hub_port; /* hub is connected to this */
+ uint64_t hub_box_nic; /* nic of containing box */
+ klconf_off_t hub_mfg_nic; /* MFG NIC string */
+ uint64_t hub_speed; /* Speed of hub in HZ */
+} klhub_t;
+
+/* KLSTRUCT_MEMBNK: Memory bank */
+#define MD_MEM_BANKS_M 8 /* M-Mode */
+typedef struct klmembnk_m_s {
+ klinfo_t membnk_info;
+ int16_t membnk_memsz; /* Total memory in megabytes */
+ int16_t membnk_dimm_select; /* bank to phys addr mapping*/
+ int16_t membnk_bnksz[MD_MEM_BANKS_M]; /* Memory bank sizes */
+ int16_t membnk_attr;
+} klmembnk_m_t;
+
+#define MD_MEM_BANKS_N 4 /* N-Mode */
+typedef struct klmembnk_n_s {
+ klinfo_t membnk_info;
+ int16_t membnk_memsz; /* Total memory in megabytes */
+ int16_t membnk_dimm_select; /* bank to phys addr mapping*/
+ int16_t membnk_bnksz[MD_MEM_BANKS_N]; /* Memory bank sizes */
+ int16_t membnk_attr;
+} klmembnk_n_t;
+
+/* KLSTRUCT_IOC3: Basic I/O Controller */
+typedef struct klioc3_s {
+ klinfo_t ioc3_info;
+ unsigned char ioc3_ssram; /* Info about ssram */
+ unsigned char ioc3_nvram; /* Info about nvram */
+ klinfo_t ioc3_superio; /* Info about superio */
+ klconf_off_t ioc3_tty_off;
+ klinfo_t ioc3_enet;
+ klconf_off_t ioc3_enet_off;
+ klconf_off_t ioc3_kbd_off;
+} klioc3_t;
+
+/* KLSTRUCT_IOC3_TTY: IOC3 attached TTY */
+typedef struct klttydev_s {
+ klinfo_t ttydev_info;
+ struct terminal_data *ttydev_cfg; /* driver fills up this */
+} klttydev_t;
+
+
+/* H U B */
+/* ===== */
+/*
+ * HUB access macros.
+ */
+#define BWIN_SIZE_BITS 29
+#define BWIN_INDEX_BITS 3
+#define BWIN_SIZE (1ULL << BWIN_SIZE_BITS)
+#define BWIN_SIZEMASK (BWIN_SIZE - 1)
+#define BWIN_WIDGET_MASK 0x7
+
+#define LWIN_SIZE_BITS 24
+#define LWIN_SIZE (1ULL << LWIN_SIZE_BITS)
+#define LWIN_SIZEMASK (LWIN_SIZE - 1)
+#define LWIN_WIDGET_MASK 0xF
+
+#define RAW_NODE_LWIN_BASE(nasid, widget) \
+ (IP27_NODE_IO_BASE(nasid) + ((uint64_t)(widget) << LWIN_SIZE_BITS))
+
+#define NODE_BWIN_BASE0(nasid) (IP27_NODE_IO_BASE(nasid) + BWIN_SIZE)
+#define NODE_BWIN_BASE(nasid, bigwin) (NODE_BWIN_BASE0(nasid) + \
+ ((uint64_t)(bigwin) << BWIN_SIZE_BITS))
+
+#define NODE_LWIN_BASE(nasid, widget) \
+ ((widget == 0) ? NODE_BWIN_BASE((nasid), 6) \
+ : RAW_NODE_LWIN_BASE(nasid, widget))
+
+
+#define IP27_LHUB_ADDR(_x) \
+ ((volatile uint64_t *)(NODE_LWIN_BASE(0, 1) + (_x)))
+#define IP27_RHUB_ADDR(_n, _x) \
+ ((volatile uint64_t *)(NODE_LWIN_BASE(_n, 1) + 0x800000 + (_x)))
+#define IP27_RHUB_PI_ADDR(_n, _sn, _x) \
+ ((volatile uint64_t *)(NODE_LWIN_BASE(_n, 1) + 0x800000 + (_x)))
+
+#define IP27_LHUB_L(r) *(IP27_LHUB_ADDR(r))
+#define IP27_LHUB_S(r, d) *(IP27_LHUB_ADDR(r)) = (d)
+#define IP27_RHUB_L(n, r) *(IP27_RHUB_ADDR((n), (r))
+#define IP27_RHUB_S(n, r, d) *(IP27_RHUB_ADDR((n), (r)) = (d)
+#define IP27_RHUB_PI_L(n, s, r) *(IP27_RHUB_PI_ADDR((n), (s), (r))
+#define IP27_RHUB_PI_S(n, s, r, d) *(IP27_RHUB_PI_ADDR((n), (s), (r)) = (d)
+
+
+/* HUB I/O registers */
+#define PI_REGION_PRESENT 0x000018
+#define PI_CALIAS_SIZE 0x000028
+#define PI_CALIAS_SIZE_0 0
+
+
+/* HUB network interface */
+#define NI_STATUS_REV_ID 0x600000
+
+#define NSRI_MORENODES_MASK (1ULL << 18) /* Mnodes */
+
+/*
+ * Functions.
+ */
+
+void kl_scan_config(int);
+vaddr_t kl_get_console_base(void);
+
+int kl_n_mode;
+
+#endif /* __MACHINE_MNODE_H__ */
diff --git a/sys/arch/sgi/pci/ioc.c b/sys/arch/sgi/pci/ioc.c
index e00a3bc59d0..af606dcba64 100644
--- a/sys/arch/sgi/pci/ioc.c
+++ b/sys/arch/sgi/pci/ioc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioc.c,v 1.3 2009/04/12 17:56:58 miod Exp $ */
+/* $OpenBSD: ioc.c,v 1.4 2009/04/13 21:17:54 miod Exp $ */
/*
* Copyright (c) 2008 Joel Sing.
@@ -27,6 +27,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
+#include <mips64/archtype.h>
#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/cpu.h>
@@ -41,7 +42,9 @@
#include <dev/onewire/onewirereg.h>
#include <dev/onewire/onewirevar.h>
+#if 0
#include <sgi/dev/if_efreg.h>
+#endif
#include <sgi/dev/owmacvar.h>
#include <sgi/xbow/xbow.h>
@@ -228,6 +231,10 @@ ioc_attach(struct device *parent, struct device *self, void *aux)
sc->sc_mem_bus_space->_space_write_1 = xbow_write_1;
sc->sc_mem_bus_space->_space_write_2 = xbow_write_2;
+ /* XXX undo IP27 xbridge weird mapping */
+ if (sys_config.system_type != SGI_OCTANE)
+ sc->sc_mem_bus_space->_space_map = xbow_space_map_short;
+
sc->sc_memt = sc->sc_mem_bus_space;
sc->sc_memh = memh;
@@ -515,6 +522,7 @@ ioc_intr_superio(void *v)
int
ioc_intr_ethernet(void *v)
{
+#if 0
struct ioc_softc *sc = (struct ioc_softc *)v;
uint32_t stat;
@@ -527,6 +535,9 @@ ioc_intr_ethernet(void *v)
bus_space_write_4(sc->sc_memt, sc->sc_memh, EF_INTR_STATUS, stat);
return 1;
+#else
+ return 0;
+#endif
}
void
diff --git a/sys/arch/sgi/sgi/ip27_machdep.c b/sys/arch/sgi/sgi/ip27_machdep.c
new file mode 100644
index 00000000000..1ff7d4eefbe
--- /dev/null
+++ b/sys/arch/sgi/sgi/ip27_machdep.c
@@ -0,0 +1,374 @@
+/* $OpenBSD: ip27_machdep.c,v 1.1 2009/04/13 21:17:54 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Origin 200 / Origin 2000 / Onyx 2 (IP27) specific code.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/tty.h>
+
+#include <mips64/arcbios.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/memconf.h>
+#include <machine/mnode.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <sgi/xbow/xbow.h>
+#include <sgi/xbow/xbridgereg.h>
+
+#include <sgi/pci/iocreg.h>
+
+#include <dev/ic/comvar.h>
+
+paddr_t ip27_widget_short(int16_t, u_int);
+paddr_t ip27_widget_long(int16_t, u_int);
+int ip27_widget_id(int16_t, u_int, uint32_t *);
+
+static paddr_t io_base;
+
+int ip27_hub_intr_register(int, int, int *);
+int ip27_hub_intr_establish(int (*)(void *), void *, int, int, const char *);
+void ip27_hub_intr_disestablish(int);
+intrmask_t ip27_hub_intr_handler(intrmask_t, struct trap_frame *);
+void ip27_hub_intr_makemasks(void);
+void ip27_hub_do_pending_int(int);
+
+void
+ip27_setup()
+{
+ uncached_base = PHYS_TO_XKPHYS_UNCACHED(0, SP_NC);
+ io_base = PHYS_TO_XKPHYS_UNCACHED(0, SP_IO);
+
+ xbow_widget_short = ip27_widget_short;
+ xbow_widget_long = ip27_widget_long;
+ xbow_widget_id = ip27_widget_id;
+
+ /*
+ * Scan this node's configuration to find out CPU and memory
+ * information.
+ */
+ kl_scan_config(0);
+
+ if (kl_n_mode != 0)
+ xbow_long_shift = 28;
+
+ /*
+ * Initialize the early console parameters.
+ * This assumes BRIDGE is on widget 8 and IOC3 is mapped in
+ * memory space at address 0x600000.
+ *
+ * XXX And that 0x600000 should be computed from the first BAR
+ * XXX of the IOC3 in pci configuration space. Joy. I'll get there
+ * XXX eventually.
+ */
+ xbow_build_bus_space(&sys_config.console_io, 0, 8, 0);
+
+ /* Constrain to a short window */
+ sys_config.console_io.bus_base =
+ kl_get_console_base() & 0xffffffffff000000UL;
+
+ comconsaddr = kl_get_console_base() & 0x0000000000ffffffUL;
+ comconsfreq = 22000000 / 3;
+ comconsiot = &sys_config.console_io;
+
+ /*
+ * Force widget interrupts to run through us, unless a
+ * better interrupt master widget is found.
+ */
+ xbow_intr_widget_intr_register = ip27_hub_intr_register;
+ xbow_intr_widget_intr_establish = ip27_hub_intr_establish;
+ xbow_intr_widget_intr_disestablish = ip27_hub_intr_disestablish;
+
+ set_intr(INTPRI_XBOWMUX, CR_INT_0, ip27_hub_intr_handler);
+ register_pending_int_handler(ip27_hub_do_pending_int);
+}
+
+/*
+ * Widget mapping.
+ */
+
+paddr_t
+ip27_widget_short(int16_t nasid, u_int widget)
+{
+ if (widget == 0)
+ return ip27_widget_long(nasid, 6); /* ??? */
+
+ return ((uint64_t)(widget) << 24) | ((uint64_t)(nasid) << 32) | io_base;
+}
+
+paddr_t
+ip27_widget_long(int16_t nasid, u_int widget)
+{
+ return ((uint64_t)(widget + 1) << xbow_long_shift) |
+ ((uint64_t)(nasid) << 32) | io_base;
+}
+
+/*
+ * Widget enumeration
+ */
+
+int
+ip27_widget_id(int16_t nasid, u_int widget, uint32_t *wid)
+{
+ paddr_t wpa;
+ uint32_t id;
+
+ if (widget != 0)
+ {
+ if (widget < WIDGET_MIN || widget > WIDGET_MAX)
+ return EINVAL;
+ }
+
+ wpa = ip27_widget_short(nasid, widget);
+ if (guarded_read_4(wpa + WIDGET_ID, &id) != 0)
+ return ENXIO;
+
+ if (wid != NULL)
+ *wid = id;
+
+ return 0;
+}
+
+/*
+ * Local HUB interrupt handling routines
+ */
+
+uint64_t ip27_hub_intrmask;
+
+/*
+ * Find a suitable interrupt bit for the given interrupt.
+ */
+int
+ip27_hub_intr_register(int widget, int level, int *intrbit)
+{
+ int bit;
+
+ /*
+ * All interrupts will be serviced at hardware level 0,
+ * so the `level' argument can be ignored.
+ * On HUB, the low 63 bits of the interrupt register
+ * are level 0 sources. However, we'll only consider the
+ * lowest 32 bits for now.
+ */
+ for (bit = SPL_CLOCK - 1; bit >= 0; bit--)
+ if ((ip27_hub_intrmask & (1 << bit)) == 0)
+ break;
+
+ if (bit < 0)
+ return EINVAL;
+
+ *intrbit = bit;
+ return 0;
+}
+
+/*
+ * Register an interrupt handler for a given source, and enable it.
+ */
+int
+ip27_hub_intr_establish(int (*func)(void *), void *arg, int intrbit,
+ int level, const char *name)
+{
+ struct intrhand *ih;
+
+#ifdef DIAGNOSTIC
+ if (intrbit < 0 || intrbit >= SPL_CLOCK)
+ return EINVAL;
+#endif
+
+ /*
+ * HEART interrupts are not supposed to be shared - the interrupt
+ * mask is large enough for all widgets.
+ */
+ if (intrhand[intrbit] != NULL)
+ return EEXIST;
+
+ ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
+ if (ih == NULL)
+ return ENOMEM;
+
+ ih->ih_next = NULL;
+ ih->ih_fun = func;
+ ih->ih_arg = arg;
+ ih->ih_level = level;
+ ih->ih_irq = intrbit;
+ evcount_attach(&ih->ih_count, name, &ih->ih_level, &evcount_intr);
+ intrhand[intrbit] = ih;
+
+ ip27_hub_intrmask |= 1UL << intrbit;
+ ip27_hub_intr_makemasks();
+
+ /* TODO frob hardware */
+
+ return 0;
+}
+
+void
+ip27_hub_intr_disestablish(int intrbit)
+{
+ struct intrhand *ih;
+ int s;
+
+#ifdef DIAGNOSTIC
+ if (intrbit < 0 || intrbit >= SPL_CLOCK)
+ return;
+#endif
+
+ s = splhigh();
+
+ if ((ih = intrhand[intrbit]) == NULL) {
+ splx(s);
+ return;
+ }
+
+ /* TODO frob hardware */
+
+ intrhand[intrbit] = NULL;
+
+ ip27_hub_intrmask &= ~(1UL << intrbit);
+ ip27_hub_intr_makemasks();
+
+ free(ih, M_DEVBUF);
+
+ splx(s);
+}
+
+intrmask_t ip27_hub_intem = 0;
+
+/*
+ * Recompute interrupt masks.
+ */
+void
+ip27_hub_intr_makemasks()
+{
+ int irq, level;
+ struct intrhand *q;
+ intrmask_t intrlevel[INTMASKSIZE];
+
+ /* First, figure out which levels each IRQ uses. */
+ for (irq = 0; irq < INTMASKSIZE; irq++) {
+ int levels = 0;
+ for (q = intrhand[irq]; q; q = q->ih_next)
+ levels |= 1 << q->ih_level;
+ intrlevel[irq] = levels;
+ }
+
+ /* Then figure out which IRQs use each level. */
+ for (level = IPL_NONE; level < NIPLS; level++) {
+ int irqs = 0;
+ for (irq = 0; irq < INTMASKSIZE; irq++)
+ if (intrlevel[irq] & (1 << level))
+ irqs |= 1 << irq;
+ if (level != IPL_NONE)
+ irqs |= SINT_ALLMASK;
+ imask[level] = irqs;
+ }
+
+ /*
+ * There are tty, network and disk drivers that use free() at interrupt
+ * time, so vm > (tty | net | bio).
+ *
+ * Enforce a hierarchy that gives slow devices a better chance at not
+ * dropping data.
+ */
+ imask[IPL_NET] |= imask[IPL_BIO];
+ imask[IPL_TTY] |= imask[IPL_NET];
+ imask[IPL_VM] |= imask[IPL_TTY];
+ imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCKMASK;
+
+ /*
+ * These are pseudo-levels.
+ */
+ imask[IPL_NONE] = 0;
+ imask[IPL_HIGH] = -1;
+
+ /* Lastly, determine which IRQs are actually in use. */
+ ip27_hub_intem = ip27_hub_intrmask & 0x00000000ffffffffL;
+ hw_setintrmask(0);
+}
+
+void
+ip27_hub_do_pending_int(int newcpl)
+{
+ /* Update masks to new cpl. Order highly important! */
+ __asm__ (" .set noreorder\n");
+ cpl = newcpl;
+ __asm__ (" sync\n .set reorder\n");
+ hw_setintrmask(newcpl);
+ /* If we still have softints pending trigger processing. */
+ if (ipending & SINT_ALLMASK & ~newcpl)
+ setsoftintr0();
+}
+
+intrmask_t
+ip27_hub_intr_handler(intrmask_t hwpend, struct trap_frame *frame)
+{
+ uint64_t imr, isr;
+ int bit;
+ intrmask_t mask;
+ struct intrhand *ih;
+
+ /* TODO frob hardware */
+ isr = 0;
+ imr = 0;
+
+ isr &= imr;
+ if (isr == 0)
+ return 0; /* not for us */
+
+ /*
+ * If interrupts are spl-masked, mark them as pending and mask
+ * them in hardware.
+ */
+ if ((mask = isr & frame->cpl) != 0) {
+ atomic_setbits_int(&ipending, mask);
+ /* TODO frob hardware */
+ isr &= ~mask;
+ }
+
+ /*
+ * Now process unmasked interrupts.
+ */
+ mask = isr & ~frame->cpl;
+ atomic_clearbits_int(&ipending, mask);
+ for (bit = SPL_CLOCK - 1, mask = 1 << bit; bit >= 0;
+ bit--, mask >>= 1) {
+ if ((isr & mask) == 0)
+ continue;
+
+ for (ih = intrhand[bit]; ih != NULL; ih = ih->ih_next) {
+ if ((*ih->ih_fun)(ih->ih_arg) != 0)
+ ih->ih_count.ec_count++;
+ }
+ }
+
+ return CR_INT_0;
+}
+
+void
+hw_setintrmask(intrmask_t m)
+{
+ /* TODO frob hardware */
+}
diff --git a/sys/arch/sgi/sgi/ip30_machdep.c b/sys/arch/sgi/sgi/ip30_machdep.c
index 2725f4a686e..f9a43f52c92 100644
--- a/sys/arch/sgi/sgi/ip30_machdep.c
+++ b/sys/arch/sgi/sgi/ip30_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip30_machdep.c,v 1.3 2009/04/12 17:53:02 miod Exp $ */
+/* $OpenBSD: ip30_machdep.c,v 1.4 2009/04/13 21:17:54 miod Exp $ */
/*
* Copyright (c) 2008 Miodrag Vallat.
@@ -35,6 +35,7 @@
#include <uvm/uvm_extern.h>
#include <sgi/sgi/ip30.h>
+#include <sgi/xbow/widget.h>
#include <sgi/xbow/xbow.h>
#include <sgi/xbow/xbridgereg.h>
@@ -147,7 +148,7 @@ ip30_widget_id(int16_t nasid, u_int widget, uint32_t *wid)
if (widget != 0)
{
- if (widget < 8 || widget > 15)
+ if (widget < WIDGET_MIN || widget > WIDGET_MAX)
return EINVAL;
linkpa = ip30_widget_short(nasid, 0) + XBOW_WIDGET_LINK(widget);
@@ -162,3 +163,13 @@ ip30_widget_id(int16_t nasid, u_int widget, uint32_t *wid)
return 0;
}
+
+void
+hw_setintrmask(intrmask_t m)
+{
+ extern intrmask_t heart_intem;
+
+ paddr_t heart;
+ heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
+ *(volatile uint64_t *)(heart + HEART_IMR(0)) = heart_intem & ~m;
+}
diff --git a/sys/arch/sgi/sgi/sginode.c b/sys/arch/sgi/sgi/sginode.c
new file mode 100644
index 00000000000..a8d33e9f87e
--- /dev/null
+++ b/sys/arch/sgi/sgi/sginode.c
@@ -0,0 +1,299 @@
+#define DEBUG
+/* $OpenBSD: sginode.c,v 1.1 2009/04/13 21:17:54 miod Exp $ */
+/*
+ * Copyright (c) 2008, 2009 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 2004 Opsycon AB. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/memconf.h>
+#include <machine/param.h>
+#include <machine/autoconf.h>
+#include <mips64/arcbios.h>
+#include <mips64/archtype.h>
+
+#include <machine/mnode.h>
+
+int nextcpu = 0;
+
+void kl_do_boardinfo(lboard_t *);
+void kl_add_memory(int16_t *, unsigned int);
+
+#ifdef DEBUG
+#define DB_PRF(x) bios_printf x
+#else
+#define DB_PRF(x)
+#endif
+
+void
+kl_scan_config(int node)
+{
+ lboard_t *boardinfo;
+ kl_config_hdr_t *cfghdr;
+ u_int64_t val;
+
+ if (node == 0)
+ physmem = 0;
+
+ cfghdr = IP27_KLCONFIG_HDR(0);
+ DB_PRF(("config @%p\n", cfghdr));
+ DB_PRF(("magic %p version %x\n", cfghdr->magic, cfghdr->version));
+ DB_PRF(("console %p baud %d\n", cfghdr->cons_info.uart_base,
+ cfghdr->cons_info.baud));
+
+ val = IP27_LHUB_L(NI_STATUS_REV_ID);
+ kl_n_mode = (val & NSRI_MORENODES_MASK) != 0;
+ bios_printf("Machine is in %c mode.\n", kl_n_mode + 'M');
+
+ val = IP27_LHUB_L(PI_REGION_PRESENT);
+ DB_PRF(("Region present %p.\n", val));
+ val = IP27_LHUB_L(PI_CALIAS_SIZE);
+ DB_PRF(("Calias size %p.\n", val));
+
+ for (boardinfo = IP27_KLFIRST_BOARD(0); boardinfo != NULL;
+ boardinfo = IP27_KLNEXT_BOARD(0, boardinfo)) {
+ kl_do_boardinfo(boardinfo);
+ if (boardinfo->brd_next == NULL)
+ break;
+ }
+
+ if (nextcpu > MAX_CPUS) {
+ bios_printf("%u processors found, increase MAX_CPUS\n",
+ nextcpu);
+ }
+}
+
+void
+kl_do_boardinfo(lboard_t *boardinfo)
+{
+ klinfo_t *comp;
+ klcpu_t *cpucomp;
+ klhub_t *hubcomp;
+ klmembnk_m_t *memcomp_m;
+ klmembnk_n_t *memcomp_n;
+ struct cpuinfo *cpu;
+ int i, j;
+
+ DB_PRF(("board type %x slot %x nasid %x components %d\n",
+ boardinfo->brd_type, boardinfo->brd_slot, boardinfo->brd_nasid,
+ boardinfo->brd_numcompts));
+
+ for (i = 0; i < boardinfo->brd_numcompts; i++) {
+ comp = IP27_UNCAC_ADDR(klinfo_t *, 0, boardinfo->brd_compts[i]);
+
+ switch(comp->struct_type) {
+ case KLSTRUCT_CPU:
+ cpucomp = (klcpu_t *)comp;
+ DB_PRF(("\tcpu type %x %dMhz cache %dMB speed %dMhz\n",
+ cpucomp->cpu_prid, cpucomp->cpu_speed,
+ cpucomp->cpu_scachesz, cpucomp->cpu_scachespeed));
+
+ if (nextcpu < MAX_CPUS) {
+ cpu = &sys_config.cpu[nextcpu];
+ cpu->clock = cpucomp->cpu_speed * 1000000;
+ cpu->type = (cpucomp->cpu_prid >> 8) & 0xff;
+ cpu->vers_maj = (cpucomp->cpu_prid >> 4) & 0x0f;
+ cpu->vers_min = cpucomp->cpu_prid & 0x0f;
+ cpu->fptype = (cpucomp->cpu_fpirr >> 8) & 0xff;
+ cpu->fpvers_maj =
+ (cpucomp->cpu_fpirr >> 4) & 0x0f;
+ cpu->fpvers_min = cpucomp->cpu_fpirr & 0x0f;
+ cpu->tlbsize = 64;
+ }
+ nextcpu++;
+ break;
+
+ case KLSTRUCT_HUB:
+ hubcomp = (klhub_t *)comp;
+ DB_PRF(("\thub widget %d port %d flag %d speed %dMHz\n",
+ hubcomp->hub_info.widid,
+ hubcomp->hub_port.port_nasid,
+ hubcomp->hub_port.port_flag,
+ hubcomp->hub_speed / 1000000));
+ break;
+
+ case KLSTRUCT_MEMBNK:
+ memcomp_m = (klmembnk_m_t *)comp;
+ memcomp_n = (klmembnk_n_t *)comp;
+ DB_PRF(("\tmemory %dMB, select %x\n",
+ memcomp_m->membnk_memsz,
+ memcomp_m->membnk_dimm_select));
+
+ if (kl_n_mode) {
+ for (j = 0; j < MD_MEM_BANKS_N; j++) {
+ if (memcomp_n->membnk_bnksz[j] == 0)
+ continue;
+ DB_PRF(("\t\tbank %d %dMB\n",
+ j + 1,
+ memcomp_n->membnk_bnksz[j]));
+ }
+ } else {
+ for (j = 0; j < MD_MEM_BANKS_M; j++) {
+ if (memcomp_m->membnk_bnksz[j] == 0)
+ continue;
+ DB_PRF(("\t\tbank %d %dMB\n",
+ j + 1,
+ memcomp_m->membnk_bnksz[j]));
+ }
+ }
+
+ kl_add_memory(memcomp_m->membnk_bnksz,
+ kl_n_mode ? MD_MEM_BANKS_N : MD_MEM_BANKS_M);
+
+ break;
+
+ default:
+ DB_PRF(("\tcomponent widget %d type %d\n",
+ comp->widid, comp->struct_type));
+ }
+ }
+
+}
+
+/*
+ * Return the virtual address of the console device.
+ */
+vaddr_t
+kl_get_console_base()
+{
+ kl_config_hdr_t *cfghdr = IP27_KLCONFIG_HDR(0);
+
+ return (vaddr_t)cfghdr->cons_info.uart_base;
+}
+
+/*
+ * Process memory bank information.
+ */
+void
+kl_add_memory(int16_t *sizes, unsigned int cnt)
+{
+ int16_t nasid = 0; /* XXX */
+ paddr_t basepa;
+ uint32_t fp, lp, np;
+ unsigned int seg, descno, nmeg;
+ struct phys_mem_desc *md;
+
+ /*
+ * 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 = nasid << (32 - kl_n_mode);
+ while (cnt-- != 0) {
+ nmeg = *sizes++;
+ for (seg = 0; seg < 4; basepa += (1 << 27), seg++) {
+ if (nmeg <= 128)
+ np = seg == 0 ? nmeg : 0;
+ else
+ np = nmeg / 4;
+ if (np == 0)
+ continue;
+
+ DB_PRF(("memory from %p to %p (%u MB)\n",
+ basepa, basepa + (np << 20), np));
+
+ np = atop(np << 20); /* MB to pages */
+ fp = atop(basepa);
+ lp = fp + np;
+
+ /*
+ * ARCBios provided us with information on the
+ * first 32MB, so skip them here if necessary.
+ */
+ if (fp < atop(32 << 20)) {
+ fp = atop(32 << 20);
+ if (fp >= lp)
+ continue;
+ np = lp - fp;
+ physmem += atop(32 << 20);
+ }
+
+ /*
+ * Walk the existing segment list to find if we
+ * are adjacent to an existing segment, or the
+ * next free segment to use if not.
+ *
+ * Note that since we do not know in which order
+ * we'll find our nodes, we have to check for
+ * both boundaries, despite adding a given node's
+ * memory in increasing pa order.
+ */
+ for (descno = 0, md = mem_layout; descno < MAXMEMSEGS;
+ descno++, md++) {
+ if (md->mem_first_page == 0)
+ break;
+
+ if (md->mem_first_page == lp) {
+ md->mem_first_page = fp;
+ physmem += np;
+ md = NULL;
+ break;
+ }
+
+ if (md->mem_last_page == fp) {
+ md->mem_last_page = lp;
+ physmem += np;
+ md = NULL;
+ break;
+ }
+ }
+ if (descno != MAXMEMSEGS && md != NULL) {
+ md->mem_first_page = fp;
+ md->mem_last_page = lp;
+ physmem += np;
+ md = NULL;
+ }
+
+ if (md != NULL) {
+ /*
+ * We could hijack the smallest segment here.
+ * But is it really worth doing?
+ */
+ bios_printf("%u MB of memory could not be "
+ "managed, increase MAXMEMSEGS\n",
+ atop(np) >> 20);
+ }
+ }
+ }
+}
diff --git a/sys/arch/sgi/xbow/files.xbow b/sys/arch/sgi/xbow/files.xbow
index e350ddd747b..8a113c29c8d 100644
--- a/sys/arch/sgi/xbow/files.xbow
+++ b/sys/arch/sgi/xbow/files.xbow
@@ -1,4 +1,10 @@
-# $OpenBSD: files.xbow,v 1.1 2008/04/07 22:47:40 miod Exp $
+# $OpenBSD: files.xbow,v 1.2 2009/04/13 21:17:54 miod Exp $
+
+# IP30 and IP27 planar XBow bus
+define xbow {[vendor = -1], [product = -1]}
+device xbow
+attach xbow at mainbus
+file arch/sgi/xbow/xbow.c xbow
# IP30 Heart
device xheart {} : onewirebus
diff --git a/sys/arch/sgi/xbow/xbow.c b/sys/arch/sgi/xbow/xbow.c
index 88cc0d729f4..1688e82d57b 100644
--- a/sys/arch/sgi/xbow/xbow.c
+++ b/sys/arch/sgi/xbow/xbow.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: xbow.c,v 1.2 2008/07/30 17:37:46 miod Exp $ */
+/* $OpenBSD: xbow.c,v 1.3 2009/04/13 21:17:54 miod Exp $ */
/*
- * Copyright (c) 2008 Miodrag Vallat.
+ * Copyright (c) 2008, 2009 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
@@ -77,7 +77,9 @@ 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 *);
-void xbow_enumerate(struct device *, int,
+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);
uint32_t xbow_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
@@ -97,8 +99,6 @@ void xbow_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
void xbow_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
const uint8_t *, bus_size_t);
-int xbow_space_map_short(bus_space_tag_t, bus_addr_t, bus_size_t, int,
- bus_space_handle_t *);
int xbow_space_map_long(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
void xbow_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
@@ -299,65 +299,94 @@ xbowattach(struct device *parent, struct device *self, void *aux)
(wid & WIDGET_ID_REV_MASK) >> WIDGET_ID_REV_SHIFT);
/*
- * 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 the Origin 200 (but probably not on the Origin 2000).
*/
- xbow_enumerate(self, 0, xbowsubmatch_pass1, xbowprint_pass1);
- xbow_enumerate(self, xbow_intr_widget, xbowsubmatch_pass2,
- xbowprint_pass2);
+ if (vendor == XBOW_VENDOR_SGI4 &&
+ product == XBOW_PRODUCT_SGI4_BRIDGE) {
+ /*
+ * Interrupt widget is #a (this is another facet of this
+ * bridge).
+ */
+ xbow_intr_widget = 0x0a;
+ xbow_intr_widget_register = 0x90;
+
+ xbow_attach_widget(self, nasid, WIDGET_MIN,
+ xbowsubmatch_pass2, xbowprint_pass2);
+ } else {
+ /*
+ * 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.
+ */
+ xbow_enumerate(self, nasid, 0,
+ xbowsubmatch_pass1, xbowprint_pass1);
+ xbow_enumerate(self, nasid, xbow_intr_widget,
+ xbowsubmatch_pass2, xbowprint_pass2);
+ }
}
void
-xbow_enumerate(struct device *self, int skip,
+xbow_enumerate(struct device *self, int16_t nasid, int skip,
int (*sm)(struct device *, void *, void *), cfprint_t print)
{
- int16_t nasid = 0; /* XXX for now... */
- struct xbow_attach_args xaa;
int widget;
- uint32_t wid;
-
- for (widget = 8; widget <= 15; widget++) {
- struct mips_bus_space *bs, *bl;
+ for (widget = WIDGET_MIN; widget <= WIDGET_MAX; widget++) {
if (widget == skip)
continue;
- if (xbow_widget_id(nasid, widget, &wid) != 0)
- continue;
+ (void)xbow_attach_widget(self, nasid, widget, sm, print);
+ }
+}
- /*
- * Build a pair of bus_space_t suitable for this widget.
- */
- bs = malloc(sizeof (*bs), M_DEVBUF, M_NOWAIT);
- if (bs == NULL)
- continue;
- bl = malloc(sizeof (*bl), M_DEVBUF, M_NOWAIT);
- if (bl == NULL) {
- free(bs, M_DEVBUF);
- continue;
- }
-
- xbow_build_bus_space(bs, nasid, widget, 0);
- xbow_build_bus_space(bl, nasid, widget, 1);
-
- xaa.xaa_widget = widget;
- xaa.xaa_vendor = (wid & WIDGET_ID_VENDOR_MASK) >>
- WIDGET_ID_VENDOR_SHIFT;
- xaa.xaa_product = (wid & WIDGET_ID_PRODUCT_MASK) >>
- WIDGET_ID_PRODUCT_SHIFT;
- xaa.xaa_revision = (wid & WIDGET_ID_REV_MASK) >>
- WIDGET_ID_REV_SHIFT;
- xaa.xaa_short_tag = bs;
- xaa.xaa_long_tag = bl;
-
- if (config_found_sm(self, &xaa, print, sm) == NULL) {
- /* nothing attached, no need to keep the bus_space */
- free(bs, M_DEVBUF);
- free(bl, M_DEVBUF);
- }
+int
+xbow_attach_widget(struct device *self, int16_t nasid, int widget,
+ int (*sm)(struct device *, void *, void *), cfprint_t print)
+{
+ struct xbow_attach_args xaa;
+ uint32_t wid;
+ struct mips_bus_space *bs, *bl;
+ int rc;
+
+ if ((rc = xbow_widget_id(nasid, widget, &wid)) != 0)
+ return rc;
+
+ /*
+ * Build a pair of bus_space_t suitable for this widget.
+ */
+ bs = malloc(sizeof (*bs), M_DEVBUF, M_NOWAIT);
+ if (bs == NULL)
+ return ENOMEM;
+ bl = malloc(sizeof (*bl), M_DEVBUF, M_NOWAIT);
+ if (bl == NULL) {
+ free(bs, M_DEVBUF);
+ return ENOMEM;
}
+
+ xbow_build_bus_space(bs, nasid, widget, 0);
+ xbow_build_bus_space(bl, nasid, widget, 1);
+
+ xaa.xaa_widget = widget;
+ xaa.xaa_vendor = (wid & WIDGET_ID_VENDOR_MASK) >>
+ WIDGET_ID_VENDOR_SHIFT;
+ xaa.xaa_product = (wid & WIDGET_ID_PRODUCT_MASK) >>
+ WIDGET_ID_PRODUCT_SHIFT;
+ xaa.xaa_revision = (wid & WIDGET_ID_REV_MASK) >> WIDGET_ID_REV_SHIFT;
+ xaa.xaa_short_tag = bs;
+ xaa.xaa_long_tag = bl;
+
+ if (config_found_sm(self, &xaa, print, sm) == NULL) {
+ /* nothing attached, no need to keep the bus_space */
+ free(bs, M_DEVBUF);
+ free(bl, M_DEVBUF);
+
+ return ENOENT;
+ }
+
+ return 0;
}
diff --git a/sys/arch/sgi/xbow/xbow.h b/sys/arch/sgi/xbow/xbow.h
index 1a5bed14da6..59f982ee832 100644
--- a/sys/arch/sgi/xbow/xbow.h
+++ b/sys/arch/sgi/xbow/xbow.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbow.h,v 1.1 2008/04/07 22:47:40 miod Exp $ */
+/* $OpenBSD: xbow.h,v 1.2 2009/04/13 21:17:54 miod Exp $ */
/*
* Copyright (c) 2008 Miodrag Vallat.
@@ -99,6 +99,13 @@ extern void (*xbow_intr_widget_intr_disestablish)(int);
#define WIDGET_LINK_RESET 0x0034
#define WIDGET_LINK_AUX_STATUS 0x003c
+/*
+ * Valid widget values
+ */
+
+#define WIDGET_MIN 8
+#define WIDGET_MAX 15
+
struct xbow_attach_args {
int xaa_widget;
@@ -116,6 +123,8 @@ int xbow_intr_register(int, int, int *);
int xbow_intr_establish(int (*)(void *), void *, int, int, const char *);
void xbow_intr_disestablish(int);
+int xbow_space_map_short(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
uint8_t xbow_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
uint16_t xbow_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
void xbow_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint8_t);
diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c
index fb2dee9e403..5543a3bf56f 100644
--- a/sys/arch/sgi/xbow/xbridge.c
+++ b/sys/arch/sgi/xbow/xbridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbridge.c,v 1.6 2009/04/12 17:55:20 miod Exp $ */
+/* $OpenBSD: xbridge.c,v 1.7 2009/04/13 21:17:54 miod Exp $ */
/*
* Copyright (c) 2008 Miodrag Vallat.
@@ -109,6 +109,8 @@ void xbridge_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
uint8_t *, bus_size_t);
void xbridge_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
const uint8_t *, bus_size_t);
+int xbridge_space_map_short(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
bus_addr_t xbridge_pa_to_device(paddr_t);
paddr_t xbridge_device_to_pa(bus_addr_t);
@@ -184,21 +186,35 @@ xbridge_attach(struct device *parent, struct device *self, void *aux)
if (sc->sc_io_bus_space == NULL)
goto fail2;
- bcopy(xaa->xaa_long_tag, sc->sc_mem_bus_space,
- sizeof(*sc->sc_mem_bus_space));
- sc->sc_mem_bus_space->bus_base = xaa->xaa_long_tag->bus_base +
- BRIDGE_PCI_MEM_SPACE_BASE;
-
- if (sc->sc_rev >= 4) {
- /* Unrestricted I/O mappings in the large window */
- bcopy(xaa->xaa_long_tag, sc->sc_io_bus_space,
- sizeof(*sc->sc_io_bus_space));
- sc->sc_io_bus_space->bus_base +=
- BRIDGE_PCI_IO_SPACE_BASE;
+ if (sys_config.system_type == SGI_OCTANE) {
+ bcopy(xaa->xaa_long_tag, sc->sc_mem_bus_space,
+ sizeof(*sc->sc_mem_bus_space));
+ sc->sc_mem_bus_space->bus_base += BRIDGE_PCI_MEM_SPACE_BASE;
+
+ if (sc->sc_rev >= 4) {
+ /* Unrestricted I/O mappings in the large window */
+ bcopy(xaa->xaa_long_tag, sc->sc_io_bus_space,
+ sizeof(*sc->sc_io_bus_space));
+ sc->sc_io_bus_space->bus_base +=
+ BRIDGE_PCI_IO_SPACE_BASE;
+ } else {
+ /* Programmable I/O mappings in the small window */
+ bcopy(xaa->xaa_short_tag, sc->sc_io_bus_space,
+ sizeof(*sc->sc_io_bus_space));
+ }
} else {
- /* Programmable I/O mappings in the small window */
+ /* Limited memory mappings in the small window */
+ bcopy(xaa->xaa_short_tag, sc->sc_mem_bus_space,
+ sizeof(*sc->sc_mem_bus_space));
+ sc->sc_mem_bus_space->bus_private = sc;
+ sc->sc_mem_bus_space->_space_map = xbridge_space_map_short;
+
+ /* Limited I/O mappings in the small window */
bcopy(xaa->xaa_short_tag, sc->sc_io_bus_space,
sizeof(*sc->sc_io_bus_space));
+ sc->sc_io_bus_space->bus_private = sc;
+ sc->sc_io_bus_space->_space_map = xbridge_space_map_short;
+ sc->sc_io_bus_space->bus_base += 0xa00000;
}
sc->sc_io_bus_space->_space_read_1 = xbridge_read_1;
@@ -769,6 +785,28 @@ xbridge_write_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
}
/*
+ * On IP27, we can not use the default xbow space_map_short because
+ * of the games we play with bus addresses.
+ */
+int
+xbridge_space_map_short(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
+ int cacheable, bus_space_handle_t *bshp)
+{
+ struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private;
+ bus_addr_t bpa;
+
+ bpa = t->bus_base - (sc->sc_widget << 24) + offs;
+
+ /* check that this neither underflows nor overflows the window */
+ if (((bpa + size - 1) >> 24) != (t->bus_base >> 24) ||
+ (bpa >> 24) != (t->bus_base >> 24))
+ return (EINVAL);
+
+ *bshp = bpa;
+ return 0;
+}
+
+/*
* bus_dma helpers
*/