diff options
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r-- | sys/arch/sgi/conf/files.sgi | 10 | ||||
-rw-r--r-- | sys/arch/sgi/dev/dsrtc.c | 11 | ||||
-rw-r--r-- | sys/arch/sgi/include/bus.h | 4 | ||||
-rw-r--r-- | sys/arch/sgi/include/mnode.h | 377 | ||||
-rw-r--r-- | sys/arch/sgi/pci/ioc.c | 13 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip27_machdep.c | 374 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip30_machdep.c | 15 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/sginode.c | 299 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/files.xbow | 8 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbow.c | 131 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbow.h | 11 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridge.c | 64 |
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 */ |