code:
/*	$OpenBSD: mnode.h,v 1.18 2011/04/17 17:44:24 miod Exp $ */

/*
 * Copyright (c) 2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
 *
 * 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	PHYS_TO_XKPHYS(0, CCA_CACHED)

/*
 * IP27 uses XKPHYS space for accessing special objects.
 * Note that IP27_UNCAC_BASE is a linear space without specials.
 */
#define	IP27_HSPEC_BASE	PHYS_TO_XKPHYS_UNCACHED(0, SP_HUB)
#define	IP27_IO_BASE	PHYS_TO_XKPHYS_UNCACHED(0, SP_IO)
#define	IP27_MSPEC_BASE	PHYS_TO_XKPHYS_UNCACHED(0, SP_SPECIAL)
#define	IP27_UNCAC_BASE	PHYS_TO_XKPHYS_UNCACHED(0, SP_NC)

/*
 * Macros used to find the base of each nodes address space.
 * In M mode each node space is 4GB; in N mode each node space is 2GB only.
 */
#define IP27_NODE_BASE(base, node) ((base) + ((uint64_t)(node) << kl_n_shift))
#define	IP27_NODE_SIZE_MASK	   ((1UL << kl_n_shift) - 1)

#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)))

/*
 * Convert a physical (XIO) address to a node number.
 */
#define	IP27_PHYS_TO_NODE(addr)	((addr) >> kl_n_shift)

/*
 * 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;		/* # of entries if array, 1 if not */
	size_t		 stride;	/* Stride if array, 0 if not */
	char		 rsvd[16];	/* Pad entry to 0x40 bytes */
} 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 (widget on IP35) */
	unsigned short	brd_bus_num: 2,	/* PIC bus number (IP35) */
			brd_unused: 14;
	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;

#define	LBOARD	0x01
#define	RBOARD	0x02

/* Definitions of board type and class */
#define	IP27_BC_MASK	0xf0
#define	IP27_BT_MASK	0x0f

#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_BC_IO2	0x80

/* NODE types */
#define	IP27_BRD_CPU		(IP27_BC_NODE | 0x01)
/* IO types */
#define	IP27_BRD_BASEIO		(IP27_BC_IO | 0x01)	/* IO6 */
#define	IP27_BRD_MSCSI		(IP27_BC_IO | 0x02)
#define	IP27_BRD_MENET		(IP27_BC_IO | 0x03)
#define	IP27_BRD_FDDI		(IP27_BC_IO | 0x04)
#define	IP27_BRD_PCI1		(IP27_BC_IO | 0x06)	/* PCI shoebox */
#define	IP27_BRD_VME		(IP27_BC_IO | 0x07)
#define	IP27_BRD_MIO		(IP27_BC_IO | 0x08)
#define	IP27_BRD_FC		(IP27_BC_IO | 0x09)
#define	IP27_BRD_LINC		(IP27_BC_IO | 0x0a)
/* MPLANE types */
#define	IP27_BRD_MPLANE8	(IP27_BC_MPLANE | 0x01)
#define	IP27_BRD_IOBRICK_XBOW	(IP27_BC_MPLANE | 0x02)
/* GRAF types */
#define	IP27_BRD_KONA		(IP27_BC_GRAF | 0x01)
#define	IP27_BRD_MGRAS		(IP27_BC_GRAF | 0x03)
#define	IP27_BRD_ODSY		(IP27_BC_GRAF | 0x04)
/* BRICK types */
#define	IP27_BRD_IOBRICK	(IP27_BC_BRICK | 0x00)
#define	IP27_BRD_IBRICK		(IP27_BC_BRICK | 0x01)
#define	IP27_BRD_PBRICK		(IP27_BC_BRICK | 0x02)
#define	IP27_BRD_XBRICK		(IP27_BC_BRICK | 0x03)
#define	IP27_BRD_NBRICK		(IP27_BC_BRICK | 0x04)
#define	IP27_BRD_PEBRICK	(IP27_BC_BRICK | 0x05)
#define	IP27_BRD_PXBRICK	(IP27_BC_BRICK | 0x06)
#define	IP27_BRD_IXBRICK	(IP27_BC_BRICK | 0x07)
#define	IP27_BRD_CGBRICK	(IP27_BC_BRICK | 0x08)
/* IO2 types */
#define	IP27_BRD_DIVO		(IP27_BC_IO2 | 0x01)
#define	IP27_BRD_TPU		(IP27_BC_IO2 | 0x02)
#define	IP27_BRD_GSN		(IP27_BC_IO2 | 0x03)
#define	IP27_BRD_GSN_AUX	(IP27_BC_IO2 | 0x04)
#define	IP27_BRD_PCI3		(IP27_BC_IO2 | 0x05)	/* PCI shoehorn */
#define	IP27_BRD_HIPPI		(IP27_BC_IO2 | 0x06)
#define	IP27_BRD_ATM		(IP27_BC_IO2 | 0x07)

/* 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 */
	unsigned short	port: 2,	/* (IP35) port on dual port controller */
			pci_bus_num: 2,	/* (IP35) PCI bus number if on PIC */
			pci_multifunc: 1,
			pci_func_num: 3,/* (IP35) PCI function number */
			pci_unused: 8;
	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	KLINFO_PHYSID_PIC_BUS1		0x10	/* set if on PIC bus 1 */
#define	KLINFO_PHYSID_WIDGET_MASK	0x0f

#define	KLINFO_ENABLED	0x01
#define	KLINFO_FAILED	0x02

/*
 * Component structure types.
 */
#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_IOC3PCKM	21
#define	KLSTRUCT_RAD		22
#define	KLSTRUCT_HUB_TTY	23
#define	KLSTRUCT_IOC3_TTY	24
/* new IP35 values */
#define	KLSTRUCT_FIBERCHANNEL	25
#define	KLSTRUCT_MOD_SERIAL_NUM	26
#define	KLSTRUCT_IOC3MS		27
#define	KLSTRUCT_TPU		28
#define	KLSTRUCT_GSN		29
#define	KLSTRUCT_GSN_AUX	30
#define	KLSTRUCT_XTHD		31
#define	KLSTRUCT_QLFIBRE	32
#define	KLSTRUCT_FIREWIRE	33
#define	KLSTRUCT_USB		34
#define	KLSTRUCT_USBKBD		35
#define	KLSTRUCT_USBMS		36
#define	KLSTRUCT_SCSI2		37
#define	KLSTRUCT_PEBRICK	38
#define	KLSTRUCT_GIGENET	39
#define	KLSTRUCT_IDE		40
/* new IP53 values */
#define	KLSTRUCT_IOC4		41
#define	KLSTRUCT_IOC4UART	42
#define	KLSTRUCT_IOC4_TTY	43
#define	KLSTRUCT_IOC4PCKM	44
#define	KLSTRUCT_IOC4MS		45
#define	KLSTRUCT_IOC4_ATA	46
#define	KLSTRUCT_VGAGFX		47

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;	/* IP27: FPU IRR value */
					/* IP35: mode information (?) */
	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;		/* directory memory, per bank */
} 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;		/* directory memory, per bank */
} klmembnk_n_t;

/* KLSTRUCT_XBOW: Xbow */
#define	MAX_XBOW_LINKS	16
typedef struct klxbow_s {
	klinfo_t	xbow_info;
	klport_t	xbow_port_info[MAX_XBOW_LINKS];	/* Module number */
	int		xbow_hub_master_link;
} klxbow_t;

/* xbow_port_info.port_flag bits */
#define	XBOW_PORT_IO		0x01
#define	XBOW_PORT_HUB		0x02
#define	XBOW_PORT_ENABLE	0x04

/* KLSTRUCT_SCSI: SCSI Bus, or single-bus SCSI Controller */
#define	MAX_SCSI_DEVS	16
typedef struct klscsi_s {
	klinfo_t	scsi_info;
	uint64_t	scsi_specific;
	uint8_t		scsi_numdevs;
	klconf_off_t	scsi_devinfo[MAX_SCSI_DEVS];
} klscsi_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 */
	klconf_off_t	ioc3_tty_off;
	klconf_off_t	ioc3_kbd_off;
	klinfo_t	ioc3_superio;	/* Info about superio */
	klinfo_t	ioc3_enet;
	klconf_off_t	ioc3_enet_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;

/* KLSTRUCT_SCSI2: SCSI Controller */
typedef struct klscctl_s {
	klinfo_t	scsi_info;
	uint		type;
	uint		scsi_buscnt;
	uint64_t	scsi_bus[2];
} klscctl_t;

/* ========== */

#define IP27_NMI(n) \
	IP27_UNCAC_ADDR(nmi_t *, n, IP27_KLD_NMI(n)->offset)

#define	NMI_MAGIC	0x0048414d4d455201	/* \x00HAMMER\x01 */

typedef struct nmi {
	uint64_t	magic;			/* NMI_MAGIC */
	uint64_t	flags;
	uint64_t	cb;			/* callback function */
	uint64_t	cb_complement;		/* two's complement of above */
	uint64_t	cb_arg;			/* callback arg */
	uint64_t	master;			/* nonzero if master node */
} nmi_t;

/* ========== */

#define IP27_GDA(n)		(gda_t *)(IP27_KLD_GDA(n)->pointer)
#define IP27_GDA_SIZE(n)	(IP27_KLD_GDA(n)->size)

#define	GDA_MAGIC	0x58464552		/* XFER */

#define	GDA_MAXNODES	128

typedef struct gda {
	uint32_t	 magic;			/* GDA_MAGIC */
	uint16_t	 ver;
	uint16_t	 masternasid;		/* NASID of the master cpu */
	uint32_t	 promop;		/* Request to pass to PROM */
	uint32_t	 switches;
	void		*tlb_handlers[3];
	uint		 partid;
	uint		 symcnt;
	void		*symtab;
	char		*symnames;
	void		*replication_mask;
	uint32_t	 pad[14];
	int16_t		 nasid[GDA_MAXNODES];	/* NASID of connected nodes */
} gda_t;

#define	GDA_PROMOP_MAGIC	0x0ead0000
/* commands */
#define	GDA_PROMOP_HALT		0x00000010
#define	GDA_PROMOP_POWERDOWN	0x00000020
#define	GDA_PROMOP_RESTART	0x00000030
#define	GDA_PROMOP_REBOOT	0x00000040
#define	GDA_PROMOP_EIM		0x00000050
/* options */
#define	GDA_PROMOP_NO_DIAGS	0x00000100	/* don't run diagnostics */
#define	GDA_PROMOP_NO_MEMINIT	0x00000200	/* don't initialize memory */
#define	GDA_PROMOP_NO_DEVINIT	0x00000400	/* don't initialize devices */

/* ========== */

/*
 * Functions.
 */

console_t *kl_get_console(void);
void	kl_init(int);
int	kl_scan_all_nodes(uint, int (*)(lboard_t *, void *), void *);
int	kl_scan_node(int, uint, int (*)(lboard_t *, void *), void *);
#define	KLBRD_ANY	0
int	kl_scan_board(lboard_t *, uint, int (*)(klinfo_t *, void *), void *);
#define	KLSTRUCT_ANY	((uint)~0)
void	kl_get_location(klinfo_t *, struct sgi_device_location *);
void	kl_get_console_location(console_t *, struct sgi_device_location *);

/* widget number of the XBow `hub', for each node */
extern int kl_hub_widget[GDA_MAXNODES];

extern int kl_n_mode;
extern u_int kl_n_shift;
extern klinfo_t *kl_glass_console;
extern gda_t *gda;
extern uint maxnodes;

#endif /* _MACHINE_MNODE_H_ */


code:
/*	$OpenBSD: mplock.h,v 1.1 2009/11/21 23:28:14 syuu Exp $	*/

/*
 * Copyright (c) 2004 Niklas Hallqvist.  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 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_MPLOCK_H_
#define _MACHINE_MPLOCK_H_

/*
 * Really simple spinlock implementation with recursive capabilities.
 * Correctness is paramount, no fancyness allowed.
 */

struct __mp_lock {
	volatile struct cpu_info *mpl_cpu;
	volatile long		mpl_count;
};

#ifndef _LOCORE

void __mp_lock_init(struct __mp_lock *);
void __mp_lock(struct __mp_lock *);
void __mp_unlock(struct __mp_lock *);
int __mp_release_all(struct __mp_lock *);
int __mp_release_all_but_one(struct __mp_lock *);
void __mp_acquire_count(struct __mp_lock *, int);
int __mp_lock_held(struct __mp_lock *);

#endif

#endif /* !_MACHINE_MPLOCK_H */

license: unknown


code:
/*	$OpenBSD: mutex.h,v 1.9 2015/07/08 13:37:31 dlg Exp $	*/

#include <mips64/mutex.h>


code:
/*	$OpenBSD: param.h,v 1.7 2013/03/23 16:12:26 deraadt Exp $ */

/*
 * Copyright (c) 2003 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_PARAM_H_
#define	_MACHINE_PARAM_H_

#define	MACHINE		"sgi"
#define	_MACHINE	sgi
#define	MACHINE_ARCH	"mips64"
#define	_MACHINE_ARCH	mips64
#define	MID_MACHINE	MID_MIPS64	/* None but has to be defined */

#ifdef _KERNEL
#ifndef PAGE_SHIFT
#if defined(CPU_R5000) || defined(CPU_RM7000)
#define	PAGE_SHIFT	12
#else
#define	PAGE_SHIFT	14
#endif
#endif
#endif	/* _KERNEL */

#include <mips64/param.h>

#endif /* _MACHINE_PARAM_H_ */


code:
/*	$OpenBSD: pcb.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/pcb.h>


code:
/*	$OpenBSD: pmap.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/pmap.h>


code:
/*	$OpenBSD: proc.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/proc.h>


code:
/*	$OpenBSD: profile.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/profile.h>


code:
/*	$OpenBSD: ptrace.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/ptrace.h>


code:
/*	$OpenBSD: rbus_machdep.h,v 1.2 2011/03/23 16:54:36 pirofti Exp $	*/

/*
 * Copyright (c) 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.
 */

#ifndef	_MACHINE_RBUS_MACHDEP_H_
#define	_MACHINE_RBUS_MACHDEP_H_

/*
 * RBUS mapping routines
 */

struct rb_md_fnptr {
	int	(*rbus_md_space_map)(bus_space_tag_t, bus_addr_t, bus_size_t,
		    int, bus_space_handle_t *);
	void	(*rbus_md_space_unmap)(bus_space_tag_t, bus_space_handle_t,
		    bus_size_t, bus_addr_t *);
};

static __inline__ int
md_space_map(rbus_tag_t rbt, u_long addr, bus_size_t size, int flags,
    bus_space_handle_t *bshp)
{
	struct rb_md_fnptr *fn = (struct rb_md_fnptr *)rbt->rb_md;

	return (*fn->rbus_md_space_map)(rbt->rb_bt, (bus_addr_t)addr, size,
	    flags, bshp);
}

static __inline__ void
md_space_unmap(rbus_tag_t rbt, bus_space_handle_t h, bus_size_t size,
    bus_addr_t *addrp)
{
	struct rb_md_fnptr *fn = (struct rb_md_fnptr *)rbt->rb_md;

	(*fn->rbus_md_space_unmap)(rbt->rb_bt, h, size, addrp);
}

/*
 * PCCBB RBUS allocation routines (rbus_pccbb_parent_io, rbus_pccbb_parent_mem)
 * are implemented in pci_machdep.h.
 */

#define	pccbb_attach_hook(parent, self, paa)	\
	do { /* nothing */} while (/*CONSTCOND*/0)

#endif	/* _MACHINE_RBUS_MACHDEP_H_ */


code:
/*	$OpenBSD: reg.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/reg.h>


code:
/*	$OpenBSD: regdef.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/regdef.h>


code:
/*	$OpenBSD: regnum.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/regnum.h>


code:
/*	$OpenBSD: setjmp.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/setjmp.h>


code:
/*	$OpenBSD: signal.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/signal.h>


code:
/*	$OpenBSD: spinlock.h,v 1.1 2004/08/06 21:12:19 pefo Exp $	*/

#include <mips64/spinlock.h>


code:
/*	$OpenBSD: stdarg.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/stdarg.h>


code:
/*	$OpenBSD: sysarch.h,v 1.1 2009/09/27 18:20:13 miod Exp $	*/
/* public domain */
#include <mips64/sysarch.h>


code:
/*	$OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $	*/
/* public domain */
#include <mips64/tcb.h>


code:
/*	$OpenBSD: trap.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/trap.h>


code:
/*	$OpenBSD: varargs.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */

/* Use Mips generic include file */

#include <mips64/varargs.h>


code:
/*	$OpenBSD: vmparam.h,v 1.10 2014/07/13 15:48:32 miod Exp $ */
/* public domain */
#ifndef _MACHINE_VMPARAM_H_
#define _MACHINE_VMPARAM_H_

#define	VM_PHYSSEG_MAX	32	/* Max number of physical memory segments */

#include <mips64/vmparam.h>

#endif	/* _MACHINE_VMPARAM_H_ */


code:
/*	$OpenBSD: z8530var.h,v 1.4 2013/04/21 14:44:16 sebastia Exp $	*/
/*	$NetBSD: z8530var.h,v 1.10 2011/07/01 21:00:21 dyoung Exp $	*/

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * 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.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * 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.
 *
 *	@(#)zsvar.h	8.1 (Berkeley) 6/11/93
 */

/*
 * Copyright (c) 1994 Gordon W. Ross
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * 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.
 *
 *	@(#)zsvar.h	8.1 (Berkeley) 6/11/93
 */

#include <machine/bus.h>
#include <dev/ic/z8530sc.h>

struct zs_channel {
	struct zs_chanstate	cs_zscs; 	/* Required: soft state */
	bus_space_tag_t		cs_bustag;	/* Machine-dependent */
	bus_space_handle_t	cs_regs;
	int			cs_flags;
#define	ZSCFL_INVERT_WIRING		0x01
};

struct zsc_softc {
	struct device		zsc_dev;	/* required: base device */
	struct	zs_chanstate   *zsc_cs[2];	/* channel soft state */
	struct	zs_channel	zsc_cs_store[2];
	/* Machine-dependent part follows... */
	bus_space_tag_t		zsc_bustag;	/* Bus type */
	bus_space_handle_t	zsc_base; 	/* Device base address */
	void		       *sc_si;		/* Softinterrupt handle */
};

/*
 * Functions to read and write individual registers in a channel.
 * The SCC chip requires 3-4 PCLK cycles recovery time between accesses
 */

uint8_t zs_read_reg(struct zs_chanstate *, uint8_t);
uint8_t zs_read_csr(struct zs_chanstate *);
uint8_t zs_read_data(struct zs_chanstate *);

void  zs_write_reg(struct zs_chanstate *, uint8_t, uint8_t);
void  zs_write_csr(struct zs_chanstate *, uint8_t);
void  zs_write_data(struct zs_chanstate *, uint8_t);

/* Zilog Serial hardware interrupts (level 0) */
#define splzs()		spltty()
#define	IPL_ZS		IPL_TTY


path: sys/arch/sgi/localbus/CVS/Entries


code: src/sys/arch/sgi/localbus

path: sys/arch/sgi/localbus/CVS/Repository


code:
/*	$OpenBSD: com_lbus.c,v 1.12 2012/10/03 22:46:09 miod Exp $ */

/*
 * Copyright (c) 2001-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.
 *
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/tty.h>

#include <machine/bus.h>
#include <machine/intr.h>

#include <dev/ic/comreg.h>
#include <dev/ic/comvar.h>
#include <dev/ic/ns16550reg.h>

#include <sgi/localbus/macebusvar.h>

int	com_macebus_probe(struct device *, void *, void *);
void	com_macebus_attach(struct device *, struct device *, void *);

struct cfattach com_macebus_ca = {
	sizeof(struct com_softc), com_macebus_probe, com_macebus_attach
};

int
com_macebus_probe(struct device *parent, void *match, void *aux)
{
	struct macebus_attach_args *maa = aux;
	bus_space_handle_t ioh;
	int rv;

	/* If it's in use as the console, then it's there. */
	if (maa->maa_baseaddr == comconsaddr && !comconsattached)
		return (1);

	if (bus_space_map(maa->maa_iot, maa->maa_baseaddr, COM_NPORTS, 0, &ioh))
		return (0);

	rv = comprobe1(maa->maa_iot, ioh);
	bus_space_unmap(maa->maa_iot, ioh, COM_NPORTS);

	return rv;
}

void
com_macebus_attach(struct device *parent, struct device *self, void *aux)
{
	struct com_softc *sc = (void *)self;
	struct macebus_attach_args *maa = aux;

	sc->sc_iot = maa->maa_iot;
	sc->sc_hwflags = 0;
	sc->sc_swflags = 0;
	sc->sc_iobase = maa->maa_baseaddr;
	sc->sc_frequency = 1843200;

	/* If it's in use as the console, then it's there. */
	if (maa->maa_baseaddr == comconsaddr && !comconsattached) {
		if (comcnattach(sc->sc_iot, sc->sc_iobase, comconsrate,
		    sc->sc_frequency, (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8))
			panic("failed to setup serial console!");
		sc->sc_ioh = comconsioh;
	} else {
		if (bus_space_map(sc->sc_iot, maa->maa_baseaddr, COM_NPORTS, 0,
		    &sc->sc_ioh)) {
			printf(": can't map i/o space\n");
			return;
		}
	}

	com_attach_subr(sc);

	macebus_intr_establish(maa->maa_intr, maa->maa_mace_intr,
	    IST_EDGE, IPL_TTY, comintr, (void *)sc, sc->sc_dev.dv_xname);
}


code:
/*	$OpenBSD: crimebus.h,v 1.9 2012/04/21 19:17:50 miod Exp $	*/

/*
 * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se).
 *
 * 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	_CRIMEBUS_H_
#define	_CRIMEBUS_H_

#include <machine/bus.h>

#define	CRIMEBUS_BASE		0x14000000

#define	CRIME_REVISION		 0x0000

#define	CRIME_CONTROL		 0x0008
#define	CRIME_CTRL_TRITON_SYSADC   0x2000
#define	CRIME_CTRL_CRIME_SYSADC    0x1000
#define	CRIME_CTRL_HARD_RESET      0x0800
#define	CRIME_CTRL_SOFT_RESET      0x0400
#define	CRIME_CTRL_DOG_ENABLE      0x0200
#define	CRIME_CTRL_ENDIAN_BIG      0x0100

#define	CRIME_INT_STAT		 0x0010
#define	CRIME_INT_MASK		 0x0018
#define	CRIME_INT_SOFT		 0x0020
#define	CRIME_INT_HARD		 0x0028

/*
 * CRIME_INT_STAT and CRIME_INT_MASK mapping.
 */
#define	CRIME_INT_VIDEO_IN_1	0x00000001	/* Video in 1 */
#define	CRIME_INT_VIDEO_IN_2	0x00000002	/* Video in 2 */
#define	CRIME_INT_VIDEO_OUT	0x00000004	/* Video out */
#define	CRIME_INT_MACE_ETHER	0x00000008	/* Mace Ethernet NIC */
#define	CRIME_INT_SUPER_IO	0x00000010	/* Super I/O sub interrupt */
#define	CRIME_INT_SUB_MISC	0x00000020	/* Miscellaneous sub interrupt */
#define	CRIME_INT_SUB_AUDIO	0x00000040	/* Audio sub interrupt */
#define	CRIME_INT_PCI_BRIDGE	0x00000080	/* PCI bridge errors */
#define	CRIME_INT_PCI_SCSI_0	0x00000100	/* AIC SCSI controller 0 */
#define	CRIME_INT_PCI_SCSI_1	0x00000200	/* AIC SCSI controller 1 */
#define	CRIME_INT_PCI_SLOT_0	0x00000400	/* PCI expansion slot 0 */
#define	CRIME_INT_PCI_SLOT_1	0x00000800	/* PCI expansion slot 1 */
#define	CRIME_INT_PCI_SLOT_2	0x00001000	/* PCI expansion slot 2 */
#define	CRIME_INT_PCI_SHARE_0	0x00002000	/* PCI shared 0 */
#define	CRIME_INT_PCI_SHARE_1	0x00004000	/* PCI shared 1 */
#define	CRIME_INT_PCI_SHARE_2	0x00008000	/* PCI shared 2 */
#define	CRIME_INT_GBE_0		0x00010000	/* GBE0 (E) */
#define	CRIME_INT_GBE_1		0x00020000	/* GBE1 (E) */
#define	CRIME_INT_GBE_2		0x00040000	/* GBE2 (E) */
#define	CRIME_INT_GBE_3		0x00080000	/* GBE3 (E) */
#define	CRIME_INT_CPU_ERR	0x00100000	/* CPU Errors */
#define	CRIME_INT_MEM_ERR	0x00200000	/* Memory Errors */
#define	CRIME_INT_RE_EDGE_EMPTY	0x00400000	/* RE */
#define	CRIME_INT_RE_EDGE_FULL	0x00800000	/* RE */
#define	CRIME_INT_RE_EDGE_IDLE	0x01000000	/* RE */
#define	CRIME_INT_RE_LEVL_EMPTY	0x02000000	/* RE */
#define	CRIME_INT_RE_LEVL_FULL	0x04000000	/* RE */
#define	CRIME_INT_RE_LEVL_IDLE	0x08000000	/* RE */
#define	CRIME_INT_SOFT_0	0x10000000	/* ??? */
#define	CRIME_INT_SOFT_1	0x20000000	/* ??? */
#define	CRIME_INT_SOFT_2	0x40000000	/* ??? */
#define	CRIME_INT_VICE		0x80000000	/* Video Image Compression Engine */

#define	CRIME_NINTS		32

/*
 *  Watchdog?
 */
#define	CRIME_KICK_DOG		 0x0030
#define	CRIME_TIMER		 0x0038

#define	CRIME_CPU_ERROR_ADDR	 0x0040
#define	CRIME_CPU_ERROR_STAT	 0x0048
#define	CRIME_CPU_ERROR_ENAB	 0x0050

#define CRIME_MEM_BANK0_CONTROL	 0x0208
#define  CRIME_MEM_BANK_ADDR	   0x01f
#define  CRIME_MEM_BANK_128MB	   0x100
#define CRIME_MAX_BANKS		 8

#define	CRIME_MEMORY_OFFSET	0x40000000	/* 1GB */
#define	CRIME_MEMORY_MASK	0x3fffffff

#define	CRIME_MEM_ERROR_STAT	 0x0250
#define	CRIME_MEM_ERROR_ADDR	 0x0258

extern bus_space_t crimebus_tag;

#endif	/* _CRIMEBUS_H_ */


code:
/*	$OpenBSD: imc.c,v 1.19 2014/12/10 12:27:56 mikeb Exp $	*/
/*	$NetBSD: imc.c,v 1.32 2011/07/01 18:53:46 dyoung Exp $	*/

/*
 * Copyright (c) 2012 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) 2001 Rafal K. Boni
 * 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * 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.
 */

/*
 * Indigo/Indigo2/Indy on-board Memory Controller support code.
 */

#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>

#include <mips64/archtype.h>

#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <mips64/mips_cpu.h>

#include <sgi/sgi/ip22.h>
#include <sgi/localbus/imcreg.h>
#include <sgi/localbus/imcvar.h>
#include <sgi/localbus/intreg.h>

#include <sgi/hpc/hpcreg.h>
#include <sgi/gio/gioreg.h>
#include <sgi/gio/giovar.h>

#include "eisa.h"

#if NEISA > 0
#include <dev/eisa/eisavar.h>
#endif

int	imc_match(struct device *, void *, void *);
void	imc_attach(struct device *, struct device *, void *);
int	imc_activate(struct device *, int);
int	imc_print(void *, const char *);

const struct cfattach imc_ca = {
	sizeof(struct device), imc_match, imc_attach, NULL, imc_activate
};

struct cfdriver imc_cd = {
	NULL, "imc", DV_DULL
};

uint32_t imc_bus_error(uint32_t, struct trap_frame *);
int	 imc_watchdog_cb(void *, int);

void	 imc_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    bus_size_t, int);

/* can't be static for gio_cnattach() */
bus_space_t imcbus_tag = {
	PHYS_TO_XKPHYS(0, CCA_NC),
	NULL,
	imc_read_1, imc_write_1,
	imc_read_2, imc_write_2,
	imc_read_4, imc_write_4,
	imc_read_8, imc_write_8,
	imc_read_raw_2, imc_write_raw_2,
	imc_read_raw_4, imc_write_raw_4,
	imc_read_raw_8, imc_write_raw_8,
	imc_space_map, imc_space_unmap, imc_space_region,
	imc_space_vaddr, imc_space_barrier
};

#if NEISA > 0
void	 imc_eisa_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    uint8_t *, bus_size_t);
void	 imc_eisa_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    const uint8_t *, bus_size_t);
void	 imc_eisa_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    uint8_t *, bus_size_t);
void	 imc_eisa_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    const uint8_t *, bus_size_t);
void	 imc_eisa_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    uint8_t *, bus_size_t);
void	 imc_eisa_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    const uint8_t *, bus_size_t);
int	 imc_eisa_io_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
	    bus_space_handle_t *);
int	 imc_eisa_io_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    bus_size_t, bus_space_handle_t *);
int	 imc_eisa_mem_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
	    bus_space_handle_t *);
int	 imc_eisa_mem_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    bus_size_t, bus_space_handle_t *);

static bus_space_t imcbus_eisa_io_tag = {
	PHYS_TO_XKPHYS(EISA_IO_BASE, CCA_NC),
	NULL,
	imc_read_1, imc_write_1,
	imc_read_2, imc_write_2,
	imc_read_4, imc_write_4,
	imc_read_8, imc_write_8,
	imc_eisa_read_raw_2, imc_eisa_write_raw_2,
	imc_eisa_read_raw_4, imc_eisa_write_raw_4,
	imc_eisa_read_raw_8, imc_eisa_write_raw_8,
	imc_eisa_io_map, imc_space_unmap, imc_eisa_io_region,
	imc_space_vaddr, imc_space_barrier
};
static bus_space_t imcbus_eisa_mem_tag = {
	PHYS_TO_XKPHYS(0, CCA_NC),
	NULL,
	imc_read_1, imc_write_1,
	imc_read_2, imc_write_2,
	imc_read_4, imc_write_4,
	imc_read_8, imc_write_8,
	imc_read_raw_2, imc_write_raw_2,
	imc_read_raw_4, imc_write_raw_4,
	imc_read_raw_8, imc_write_raw_8,
	imc_eisa_mem_map, imc_space_unmap, imc_eisa_mem_region,
	imc_space_vaddr, imc_space_barrier
};
#endif

bus_addr_t imc_pa_to_device(paddr_t);
paddr_t	 imc_device_to_pa(bus_addr_t);

/* can't be static for gio_cnattach() */
struct machine_bus_dma_tag imc_bus_dma_tag = {
	NULL,			/* _cookie */
	_dmamap_create,
	_dmamap_destroy,
	_dmamap_load,
	_dmamap_load_mbuf,
	_dmamap_load_uio,
	_dmamap_load_raw,
	_dmamap_load_buffer,
	_dmamap_unload,
	_dmamap_sync,
	_dmamem_alloc,
	_dmamem_free,
	_dmamem_map,
	_dmamem_unmap,
	_dmamem_mmap,
	imc_pa_to_device,
	imc_device_to_pa,
	0
};

/*
 * Bus access primitives.
 */

uint8_t
imc_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
{
	return *(volatile uint8_t *)(h + o);
}

uint16_t
imc_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
{
	return *(volatile uint16_t *)(h + o);
}

uint32_t
imc_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
{
	return *(volatile uint32_t *)(h + o);
}

uint64_t
imc_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
{
	return *(volatile uint64_t *)(h + o);
}

void
imc_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t v)
{
	*(volatile uint8_t *)(h + o) = v;
}

void
imc_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v)
{
	*(volatile uint16_t *)(h + o) = v;
}

void
imc_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v)
{
	*(volatile uint32_t *)(h + o) = v;
}

void
imc_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t v)
{
	*(volatile uint64_t *)(h + o) = v;
}

void
imc_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    uint8_t *buf, bus_size_t len)
{
	volatile uint16_t *addr = (volatile uint16_t *)(h + o);
	len >>= 1;
	while (len-- != 0) {
		*(uint16_t *)buf = *addr;
		buf += 2;
	}
}

void
imc_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    const uint8_t *buf, bus_size_t len)
{
	volatile uint16_t *addr = (volatile uint16_t *)(h + o);
	len >>= 1;
	while (len-- != 0) {
		*addr = *(uint16_t *)buf;
		buf += 2;
	}
}

void
imc_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    uint8_t *buf, bus_size_t len)
{
	volatile uint32_t *addr = (volatile uint32_t *)(h + o);
	len >>= 2;
	while (len-- != 0) {
		*(uint32_t *)buf = *addr;
		buf += 4;
	}
}

void
imc_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    const uint8_t *buf, bus_size_t len)
{
	volatile uint32_t *addr = (volatile uint32_t *)(h + o);
	len >>= 2;
	while (len-- != 0) {
		*addr = *(uint32_t *)buf;
		buf += 4;
	}
}

void
imc_read_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    uint8_t *buf, bus_size_t len)
{
	volatile uint64_t *addr = (volatile uint64_t *)(h + o);
	len >>= 3;
	while (len-- != 0) {
		*(uint64_t *)buf = *addr;
		buf += 8;
	}
}

void
imc_write_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    const uint8_t *buf, bus_size_t len)
{
	volatile uint64_t *addr = (volatile uint64_t *)(h + o);
	len >>= 3;
	while (len-- != 0) {
		*addr = *(uint64_t *)buf;
		buf += 8;
	}
}

int
imc_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
    int flags, bus_space_handle_t *bshp)
{
	*bshp = t->bus_base + offs;
	return 0;
}

void
imc_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
{
}

int
imc_space_region(bus_space_tag_t t, bus_space_handle_t bsh,
    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
{
	*nbshp = bsh + offset;
	return 0;
}

void *
imc_space_vaddr(bus_space_tag_t t, bus_space_handle_t h)
{
	return (void *)h;
}

void
imc_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offs,
    bus_size_t len, int flags)
{
	mips_sync();
}

#if NEISA > 0
void
imc_eisa_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    uint8_t *buf, bus_size_t len)
{
	volatile uint16_t *addr = (volatile uint16_t *)(h + o);
	len >>= 1;
	while (len-- != 0) {
		*(uint16_t *)buf = swap16(*addr);
		buf += 2;
	}
}

void
imc_eisa_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    const uint8_t *buf, bus_size_t len)
{
	volatile uint16_t *addr = (volatile uint16_t *)(h + o);
	len >>= 1;
	while (len-- != 0) {
		*addr = swap16(*(uint16_t *)buf);
		buf += 2;
	}
}

void
imc_eisa_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    uint8_t *buf, bus_size_t len)
{
	volatile uint32_t *addr = (volatile uint32_t *)(h + o);
	len >>= 2;
	while (len-- != 0) {
		*(uint32_t *)buf = swap32(*addr);
		buf += 4;
	}
}

void
imc_eisa_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    const uint8_t *buf, bus_size_t len)
{
	volatile uint32_t *addr = (volatile uint32_t *)(h + o);
	len >>= 2;
	while (len-- != 0) {
		*addr = swap32(*(uint32_t *)buf);
		buf += 4;
	}
}

void
imc_eisa_read_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    uint8_t *buf, bus_size_t len)
{
	volatile uint64_t *addr = (volatile uint64_t *)(h + o);
	len >>= 3;
	while (len-- != 0) {
		*(uint64_t *)buf = swap64(*addr);
		buf += 8;
	}
}

void
imc_eisa_write_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
    const uint8_t *buf, bus_size_t len)
{
	volatile uint64_t *addr = (volatile uint64_t *)(h + o);
	len >>= 3;
	while (len-- != 0) {
		*addr = swap64(*(uint64_t *)buf);
		buf += 8;
	}
}

int
imc_eisa_io_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
    bus_space_handle_t *bshp)
{
	if (offs + size > EISA_IO_END - EISA_IO_BASE)
		return EINVAL;

	*bshp = t->bus_base + offs;
	return 0;
}

int
imc_eisa_io_region(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
    bus_size_t size, bus_space_handle_t *nbshp)
{
	if ((bsh - t->bus_base) + offset + size > EISA_IO_END - EISA_IO_BASE)
		return EINVAL;

	*nbshp = bsh + offset;
	return 0;
}

int
imc_eisa_mem_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
    bus_space_handle_t *bshp)
{
	if ((offs >= EISA_MEM0_BASE && offs + size <= EISA_MEM0_END) ||
	    (offs >= EISA_MEM1_BASE && offs + size <= EISA_MEM1_END)) {
		*bshp = t->bus_base + offs;
		return 0;
	}

	return EINVAL;
}

int
imc_eisa_mem_region(bus_space_tag_t t, bus_space_handle_t bsh,
    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
{
	bus_addr_t orig = bsh - t->bus_base;

	if ((orig >= EISA_MEM0_BASE && orig + offset + size <= EISA_MEM0_END) ||
	    (orig >= EISA_MEM1_BASE && orig + offset + size <= EISA_MEM1_END)) {
		*nbshp = t->bus_base + offset;
		return 0;
	}

	return EINVAL;
}
#endif

bus_addr_t
imc_pa_to_device(paddr_t pa)
{
	return (bus_addr_t)pa;
}

paddr_t
imc_device_to_pa(bus_addr_t addr)
{
	return (paddr_t)addr;
}

/*
 * For some reason, reading the arbitration register sometimes returns
 * wrong values, at least on IP20 (where the usual value is 0x400, but
 * nonsense values such as 0x34f have been witnessed).
 * Because of this, we'll treat the register as write-only, once we have
 * been able to read a supposedly safe value.
 * This variable contains the last known value written to this register.
 */
uint32_t imc_arb_value;

/*
 * Autoconf glue.
 */

int
imc_match(struct device *parent, void *match, void *aux)
{
	struct mainbus_attach_args *maa = (void *)aux;

	switch (sys_config.system_type) {
	case SGI_IP20:
	case SGI_IP22:
	case SGI_IP26:
	case SGI_IP28:
		break;
	default:
		return 0;
	}

	return strcmp(maa->maa_name, imc_cd.cd_name) == 0;
}

void
imc_attach(struct device *parent, struct device *self, void *aux)
{
	struct imc_attach_args iaa;
#if NEISA > 0
	struct eisabus_attach_args eba;
#endif
	uint32_t reg, lastreg;
	uint32_t id, rev;
	int have_eisa;

	id = imc_read(IMC_SYSID);
	rev = id & IMC_SYSID_REVMASK;

	/* EISA exists on Indigo2 only */
	if (sys_config.system_type != SGI_IP20 &&
	    sys_config.system_subtype == IP22_INDIGO2)
		have_eisa = (id & IMC_SYSID_HAVEISA) != 0;
	else
		have_eisa = 0;

	printf(": revision %d\n", rev);

	/* Clear CPU/GIO error status registers to clear any leftover bits. */
	imc_bus_reset();

	/* Disable watchdog if leftover from previous reboot */
	imc_watchdog_cb(self, 0);

	/* Hook the bus error handler into the ISR */
	set_intr(INTPRI_BUSERR, CR_INT_4, imc_bus_error);

	/*
	 * Enable parity reporting on GIO/main memory transactions, except
	 * on systems with the ECC memory controller, where enabling parity
	 * interferes with regular operation and causes sticky false errors.
	 *
	 * Disable parity checking on CPU bus transactions (as turning
	 * it on seems to cause spurious bus errors), but enable parity
	 * checking on CPU reads from main memory (note that this bit
	 * has the opposite sense... Turning it on turns the checks off!).
	 *
	 * Finally, turn on interrupt writes to the CPU from the MC.
	 */
	reg = imc_read(IMC_CPUCTRL0);
	if (ip22_ecc)
		reg &= ~(IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR);
	else
		reg |= IMC_CPUCTRL0_GPR | IMC_CPUCTRL0_MPR;
	reg &= ~IMC_CPUCTRL0_NCHKMEMPAR;
	reg |= IMC_CPUCTRL0_INTENA;
	imc_write(IMC_CPUCTRL0, reg);

	/* Setup the MC write buffer depth */
	/*
	 * XXX This hardcoded value is not documented anywhere, and can be
	 * XXX traced back to DaveM's internship at SGI in 1996, so it can
	 * XXX be considered correct at least for IP24 (and, to a lesser
	 * XXX extent, IP22). IP20 and IP28 systems seem to run happy with
	 * XXX this value as well.
	 */
	reg = imc_read(IMC_CPUCTRL1);
	reg = (reg & ~IMC_CPUCTRL1_MCHWMSK) | 13;

	/*
	 * Force endianness on the onboard HPC and both slots.
	 * This should be safe for Fullhouse, but leave it conditional
	 * for now.
	 */
	switch (sys_config.system_type) {
	case SGI_IP22:
		if (sys_config.system_subtype == IP22_INDIGO2)
			break;
		/* FALLTHROUGH */
	case SGI_IP20:
		reg |= IMC_CPUCTRL1_HPCFX;
		reg |= IMC_CPUCTRL1_EXP0FX;
		reg |= IMC_CPUCTRL1_EXP1FX;
		reg &= ~IMC_CPUCTRL1_HPCLITTLE;
		reg &= ~IMC_CPUCTRL1_EXP0LITTLE;
		reg &= ~IMC_CPUCTRL1_EXP1LITTLE;
		break;
	}
	imc_write(IMC_CPUCTRL1, reg);

	/*
	 * Try and read the GIO64 arbitrator configuration register value.
	 * See comments above the declaration of imc_arb_value for why we
	 * are doing this.
	 */
	reg = 0; lastreg = ~reg;
	while (reg != lastreg || (reg & ~0xffff) != 0) {
		lastreg = reg;
		reg = imc_read(IMC_GIO64ARB);
		/* read another harmless register */
		(void)imc_read(IMC_CPUCTRL0);
	}

	/*
	 * Set GIO64 arbitrator configuration register:
	 *
	 * Preserve PROM-set graphics-related bits, as they seem to depend
	 * on the graphics variant present and I'm not sure how to figure
	 * that out or 100% sure what the correct settings are for each.
	 */
	reg &= (IMC_GIO64ARB_GRX64 | IMC_GIO64ARB_GRXRT | IMC_GIO64ARB_GRXMST);

	/*
	 * Rest of settings are machine/board dependent
	 */
	switch (sys_config.system_type) {
	case SGI_IP20:
		reg |= IMC_GIO64ARB_ONEGIO;
		reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT;
		reg |= IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST;
		reg &= ~(IMC_GIO64ARB_HPC64 |
		     IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EISA64 |
		     IMC_GIO64ARB_EXP064 | IMC_GIO64ARB_EXP164 |
		     IMC_GIO64ARB_EXP0PIPE | IMC_GIO64ARB_EXP1PIPE);
		break;
	default:
		/*
		 * GIO64 invariant for all IP22 platforms: one GIO bus,
		 * HPC1 @ 64
		 */
		reg |= IMC_GIO64ARB_ONEGIO | IMC_GIO64ARB_HPC64;

		switch (sys_config.system_subtype) {
		default:
		case IP22_INDY:
		case IP22_CHALLS:
			/* XXX is MST mutually exclusive? */
			reg |= IMC_GIO64ARB_EXP0RT | IMC_GIO64ARB_EXP1RT;
			reg |= IMC_GIO64ARB_EXP0MST | IMC_GIO64ARB_EXP1MST;

			/* EISA (VINO, really) can bus-master, is 64-bit */
			reg |= IMC_GIO64ARB_EISAMST | IMC_GIO64ARB_EISA64;
			break;

		case IP22_INDIGO2:
			/*
			 * All Fullhouse boards have a 64-bit HPC2 and pipelined
			 * EXP0 slot.
			 */
			reg |= IMC_GIO64ARB_HPCEXP64 | IMC_GIO64ARB_EXP0PIPE;

			/*
			 * The EISA bus is the real thing, and is a 32-bit bus.
			 */
			reg &= ~IMC_GIO64ARB_EISA64;

			if (rev < 2) {
				/* EXP0 realtime, EXP1 can master */
				reg |= IMC_GIO64ARB_EXP0RT |
				    IMC_GIO64ARB_EXP1MST;
			} else {
				/* EXP1 pipelined as well, EISA masters */
				reg |= IMC_GIO64ARB_EXP1PIPE |
				    IMC_GIO64ARB_EISAMST;
			}
			break;
		}
	}

	imc_write(IMC_GIO64ARB, reg);
	imc_arb_value = reg;

	memset(&iaa, 0, sizeof(iaa));
	iaa.iaa_name = "gio";
	iaa.iaa_st = &imcbus_tag;
	iaa.iaa_dmat = &imc_bus_dma_tag;
	config_found(self, &iaa, imc_print);

#if NEISA > 0
	if (have_eisa) {
		memset(&eba, 0, sizeof(eba));
		eba.eba_busname = "eisa";
		eba.eba_iot = &imcbus_eisa_io_tag;
		eba.eba_memt = &imcbus_eisa_mem_tag;
		eba.eba_dmat = &imc_bus_dma_tag;
		eba.eba_ec = NULL;
		config_found(self, &eba, imc_print);
	}
#endif

#ifndef SMALL_KERNEL
	/* Register watchdog */
	wdog_register(imc_watchdog_cb, self);
#endif
}

int
imc_activate(struct device *self, int act)
{
	int rv = 0;

	switch (act) {
	case DVACT_POWERDOWN:
#ifndef SMALL_KERNEL
		wdog_shutdown(self);
#endif
		rv = config_activate_children(self, act);
		break;
	}

	return (rv);
}

int
imc_print(void *aux, const char *name)
{
	struct imc_attach_args *iaa = aux;

	if (name != NULL)
		printf("%s at %s", iaa->iaa_name, name);

	return UNCONF;
}

void
imc_bus_reset()
{
	imc_write(IMC_CPU_ERRSTAT, 0);
	imc_write(IMC_GIO_ERRSTAT, 0);
}

uint32_t
imc_bus_error(uint32_t hwpend, struct trap_frame *tf)
{
	uint32_t cpustat, giostat;
	paddr_t cpuaddr, gioaddr;
	int cpuquiet = 0, gioquiet = 0;

	cpustat = imc_read(IMC_CPU_ERRSTAT);
	cpuaddr = imc_read(IMC_CPU_ERRADDR);
	giostat = imc_read(IMC_GIO_ERRSTAT);
	gioaddr = imc_read(IMC_GIO_ERRADDR);

	switch (sys_config.system_type) {
	case SGI_IP28:
		/*
		 * R10000 speculative execution may attempt to access
		 * non-existing memory when in the kernel. We do not
		 * want to flood the console about those.
		 */
		if (cpustat & IMC_CPU_ERRSTAT_ADDR) {
			if (IS_XKPHYS((vaddr_t)tf->pc))
				cpuquiet = 1;
		}
		if (giostat != 0) {
			/*
			 * Ignore speculative writes to interrupt controller
			 * registers.
			 */
			if ((giostat & IMC_ECC_ERRSTAT_FUW) &&
			    (gioaddr & ~0x3f) == INT2_IP22)
				gioquiet = 1;
			/* XXX is it wise to hide these? */
			if ((giostat & IMC_GIO_ERRSTAT_TMO) &&
			    !IS_GIO_ADDRESS(gioaddr))
				gioquiet = 1;
		}
		break;
	}

	if (cpustat != 0 && cpuquiet == 0) {
		vaddr_t pc = tf->pc;
		uint32_t insn = 0xffffffff;

		if (tf->pc < 0)
			guarded_read_4(pc, &insn);
		else
			copyin((void *)pc, &insn, sizeof insn);

		printf("bus error: cpu_stat %08x addr %08lx pc %p insn %08x\n",
		    cpustat, cpuaddr, (void *)pc, insn);
	}
	if (giostat != 0 && gioquiet == 0) {
		printf("bus error: gio_stat %08x addr %08lx\n",
		    giostat, gioaddr);
	}

	if (cpustat != 0)
		imc_write(IMC_CPU_ERRSTAT, 0);
	if (giostat != 0)
		imc_write(IMC_GIO_ERRSTAT, 0);

	return hwpend;
}

int
imc_watchdog_cb(void *v, int period)
{
	uint32_t reg;

	if (period == 0) {
		/* reset... */
		imc_write(IMC_WDOG, 0);
		/* ...and disable */
		reg = imc_read(IMC_CPUCTRL0);
		reg &= ~(IMC_CPUCTRL0_WDOG);
		imc_write(IMC_CPUCTRL0, reg);

		return 0;
	} else {
		/* enable... */
		reg = imc_read(IMC_CPUCTRL0);
		reg |= IMC_CPUCTRL0_WDOG;
		imc_write(IMC_CPUCTRL0, reg);
		/* ...and reset */
		imc_write(IMC_WDOG, 0);

		/*
		 * The watchdog period is not controllable; it will fire
		 * when the 20 bit counter, running on a 64 usec clock,
		 * overflows.
		 */
		return (64 << 20) / 1000000;
	}
}

/* intended to be called from gio/gio.c only */
int
imc_gio64_arb_config(int slot, uint32_t flags)
{
	uint32_t reg;

	if (sys_config.system_type == SGI_IP20 ||
	    sys_config.system_subtype != IP22_INDIGO2) {
		/* GIO_SLOT_GFX is only usable on Fullhouse */
		if (slot == GIO_SLOT_GFX)
			return EINVAL;
	} else {
		/* GIO_SLOT_EXP1 is unusable on Fullhouse */
		if (slot == GIO_SLOT_EXP1)
			return EINVAL;
	}

	/* GIO_SLOT_GFX is always pipelined */
	if (slot == GIO_SLOT_GFX && (flags & GIO_ARB_NOPIPE))
		return EINVAL;

	/* IP20 does not support pipelining (XXX what about Indy?) */
	if (((flags & GIO_ARB_PIPE) || (flags & GIO_ARB_NOPIPE)) &&
	    sys_config.system_type == SGI_IP20)
		return EINVAL;

	reg = imc_arb_value;

	if (flags & GIO_ARB_RT) {
		if (slot == GIO_SLOT_EXP0)
			reg |= IMC_GIO64ARB_EXP0RT;
		else if (slot == GIO_SLOT_EXP1)
			reg |= IMC_GIO64ARB_EXP1RT;
		else if (slot == GIO_SLOT_GFX)
			reg |= IMC_GIO64ARB_GRXRT;
	}

	if (flags & GIO_ARB_MST) {
		if (slot == GIO_SLOT_EXP0)
			reg |= IMC_GIO64ARB_EXP0MST;
		else if (slot == GIO_SLOT_EXP1)
			reg |= IMC_GIO64ARB_EXP1MST;
		else if (slot == GIO_SLOT_GFX)
			reg |= IMC_GIO64ARB_GRXMST;
	}

	if (flags & GIO_ARB_PIPE) {
		if (slot == GIO_SLOT_EXP0)
			reg |= IMC_GIO64ARB_EXP0PIPE;
		else if (slot == GIO_SLOT_EXP1)
			reg |= IMC_GIO64ARB_EXP1PIPE;
	}

	if (flags & GIO_ARB_LB) {
		if (slot == GIO_SLOT_EXP0)
			reg &= ~IMC_GIO64ARB_EXP0RT;
		else if (slot == GIO_SLOT_EXP1)
			reg &= ~IMC_GIO64ARB_EXP1RT;
		else if (slot == GIO_SLOT_GFX)
			reg &= ~IMC_GIO64ARB_GRXRT;
	}

	if (flags & GIO_ARB_SLV) {
		if (slot == GIO_SLOT_EXP0)
			reg &= ~IMC_GIO64ARB_EXP0MST;
		else if (slot == GIO_SLOT_EXP1)
			reg &= ~IMC_GIO64ARB_EXP1MST;
		else if (slot == GIO_SLOT_GFX)
			reg &= ~IMC_GIO64ARB_GRXMST;
	}

	if (flags & GIO_ARB_NOPIPE) {
		if (slot == GIO_SLOT_EXP0)
			reg &= ~IMC_GIO64ARB_EXP0PIPE;
		else if (slot == GIO_SLOT_EXP1)
			reg &= ~IMC_GIO64ARB_EXP1PIPE;
	}

	if (flags & GIO_ARB_32BIT) {
		if (slot == GIO_SLOT_EXP0)
			reg &= ~IMC_GIO64ARB_EXP064;
		else if (slot == GIO_SLOT_EXP1)
			reg &= ~IMC_GIO64ARB_EXP164;
	}

	if (flags & GIO_ARB_64BIT) {
		if (slot == GIO_SLOT_EXP0)
			reg |= IMC_GIO64ARB_EXP064;
		else if (slot == GIO_SLOT_EXP1)
			reg |= IMC_GIO64ARB_EXP164;
	}

	if (flags & GIO_ARB_HPC2_32BIT)
		reg &= ~IMC_GIO64ARB_HPCEXP64;

	if (flags & GIO_ARB_HPC2_64BIT)
		reg |= IMC_GIO64ARB_HPCEXP64;

	imc_write(IMC_GIO64ARB, reg);
	imc_arb_value = reg;

	return 0;
}

/*
 * According to chapter 19 of the "IRIX Device Driver Programmer's Guide",
 * some GIO devices, which do not drive all data lines, may cause false
 * memory read parity errors on the SysAD bus. The workaround is to disable
 * parity checking.
 */
void
imc_disable_sysad_parity(void)
{
	uint32_t reg;

	if (ip22_ecc)
		return;

	reg = imc_read(IMC_CPUCTRL0);
	reg |= IMC_CPUCTRL0_NCHKMEMPAR;
	imc_write(IMC_CPUCTRL0, reg);
}

void
imc_enable_sysad_parity(void)
{
	uint32_t reg;

	if (ip22_ecc)
		return;

	reg = imc_read(IMC_CPUCTRL0);
	reg &= ~IMC_CPUCTRL0_NCHKMEMPAR;
	imc_write(IMC_CPUCTRL0, reg);
}

#if 0
int
imc_is_sysad_parity_enabled(void)
{
	uint32_t reg;

	if (ip22_ecc)
		return 0;

	reg = imc_read(IMC_CPUCTRL0);
	return ~reg & IMC_CPUCTRL0_NCHKMEMPAR;
}
#endif


code:
/*	$OpenBSD: imcreg.h,v 1.5 2014/07/02 17:44:35 miod Exp $	*/
/*	$NetBSD: imcreg.h,v 1.4 2005/12/11 12:18:52 christos Exp $	*/

/*
 * Copyright (c) 2001 Rafal K. Boni
 * 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * 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.
 */

#define	IMC_BASE		0x1fa00000

#define IMC_CPUCTRL0		0x04	/* CPU control, register 0 */

#define IMC_CPUCTRL0_REFMASK	0x0000000f	/* # lines to refresh */
#define IMC_CPUCTRL0_RFE	0x00000010	/* refresh enable */
#define IMC_CPUCTRL0_GPR	0x00000020	/* GIO parity enable */
#define IMC_CPUCTRL0_MPR	0x00000040	/* memory parity enable */
#define IMC_CPUCTRL0_CPR	0x00000080	/* cpu bus parity enable */
#define IMC_CPUCTRL0_WDOG	0x00000100	/* watchdog enable */
#define IMC_CPUCTRL0_SIN	0x00000200	/* reset system */
#define IMC_CPUCTRL0_GRR	0x00000400	/* graphics reset */
#define IMC_CPUCTRL0_ENLOCK	0x00000800	/* enable EISA memory lock */
#define IMC_CPUCTRL0_CMDPAR	0x00001000	/* SysCmd parity enable */
#define IMC_CPUCTRL0_INTENA	0x00002000	/* enable CPU interrupts */
#define IMC_CPUCTRL0_SNOOPENA	0x00004000	/* enable gfx DMA snoop */
#define IMC_CPUCTRL0_PROM_WRENA	0x00008000	/* disable buserr on PROM
						 * writes */
#define IMC_CPUCTRL0_WRST	0x00010000	/* warm restart (reset cpu) */
/* Bit 17 reserved		0x00020000	*/
#define IMC_CPUCTRL0_LITTLE	0x00040000	/* MC little-endian toggle */
#define IMC_CPUCTRL0_WRRST	0x00080000	/* cpu warm reset */
#define IMC_CPUCTRL0_MUXHWMSK	0x01f00000	/* MUX fifo high-water mask */
#define IMC_CPUCTRL0_BADPAR	0x02000000	/* generate bad parity on
						 * CPU->memory writes */
#define IMC_CPUCTRL0_NCHKMEMPAR	0x04000000	/* disable CPU parity check
						 * on memory reads. */
#define IMC_CPUCTRL0_BACK2	0x08000000	/* enable back2back GIO wrt */
#define IMC_CPUCTRL0_BUSRTMSK	0xf0000000	/* stall cycle for berr data */

#define IMC_CPUCTRL1		0x0c	/* CPU control, register 1 */
#define IMC_CPUCTRL1_MCHWMSK	0x0000000f	/* MC FIFO high water mask */
#define IMC_CPUCTRL1_ABORTEN	0x00000010	/* Enable GIO bus timeouts */
/* Bits 5 - 11 reserved		0x00000fe0	*/
#define IMC_CPUCTRL1_HPCFX	0x00001000	/* HPC endian fix */
#define IMC_CPUCTRL1_HPCLITTLE	0x00002000	/* HPC DMA is little-endian */
#define IMC_CPUCTRL1_EXP0FX	0x00004000	/* EXP0 endian fix */
#define IMC_CPUCTRL1_EXP0LITTLE	0x00008000	/* EXP0 DMA is little-endian */
#define IMC_CPUCTRL1_EXP1FX	0x00010000	/* EXP1 endian fix */
#define IMC_CPUCTRL1_EXP1LITTLE	0x00020000	/* EXP1 DMA is little-endian */

#define IMC_WDOG		0x14	/* Watchdog counter */
#define IMC_WDOG_MASK		0x001fffff	/* counter mask */

#define IMC_SYSID		0x1c	/* MC revision register */
#define IMC_SYSID_REVMASK	0x0000000f	/* MC revision mask */
#define IMC_SYSID_HAVEISA	0x00000010	/* EISA present */

#define IMC_RPSSDIV		0x2c	/* RPSS divider */
#define IMC_RPSSDIV_DIVMSK	0x000000ff	/* RPC divider mask */
#define IMC_RPSSDIV_INCMSK	0x0000ff00	/* RPC increment mask */

#define IMC_EEPROM		0x34	/* EEPROM serial interface */
/* Bit 1 is reserved		0x00000001	*/
#define IMC_EEPROM_CS		0x00000002	/* EEPROM chip select */
#define IMC_EEPROM_SCK		0x00000004	/* EEPROM serial clock */
#define IMC_EEPROM_SO		0x00000008	/* Serial data to EEPROM */
#define IMC_EEPROM_SI		0x00000010	/* Serial data from EEPROM */

#define IMC_CTRLD		0x44	/* Refresh counter preload */
#define IMC_CTRLD_MSK		0x000000ff	/* Counter preload mask */

#define IMC_REFCTR		0x4c	/* Refresh counter */
#define IMC_REFCTR_MSK		0x000000ff	/* Refresh counter mask */

#define IMC_GIO64ARB		0x84	/* GIO64 arbitration params */
#define IMC_GIO64ARB_HPC64	0x00000001	/* HPC addr size (32/64bit) */
#define IMC_GIO64ARB_GRX64	0x00000002	/* Gfx addr size (32/64bit) */
#define IMC_GIO64ARB_EXP064	0x00000004	/* EXP0 addr size (32/64bit) */
#define IMC_GIO64ARB_EXP164	0x00000008	/* EXP1 addr size (32/64bit) */
#define IMC_GIO64ARB_EISA64	0x00000010	/* EISA addr size (32/64bit) */
#define IMC_GIO64ARB_HPCEXP64	0x00000020	/* HPC2 addr size (32/64bit) */
#define IMC_GIO64ARB_GRXRT	0x00000040	/* Gfx is realtime device */
#define IMC_GIO64ARB_EXP0RT	0x00000080	/* EXP0 is realtime device */
#define IMC_GIO64ARB_EXP1RT	0x00000100	/* EXP1 is realtime device */
#define IMC_GIO64ARB_EISAMST	0x00000200	/* EISA can be busmaster */
#define IMC_GIO64ARB_ONEGIO	0x00000400	/* Only one GIO64 bus */
#define IMC_GIO64ARB_GRXMST	0x00000800	/* Gfx can be busmaster */
#define IMC_GIO64ARB_EXP0MST	0x00001000	/* EXP0 can be busmaster */
#define IMC_GIO64ARB_EXP1MST	0x00002000	/* EXP1 can be busmaster */
#define IMC_GIO64ARB_EXP0PIPE	0x00004000	/* EXP0 is pipelined */
#define IMC_GIO64ARB_EXP1PIPE	0x00008000	/* EXP1 is pipelined */

#define IMC_CPUTIME		0x8c	/* Arbiter CPU time period */

#define IMC_LBTIME		0x9c	/* Arbiter long-burst time */

#define IMC_MEMCFG0		0xc4	/* Mem config, register 0 */
#define IMC_MEMCFG1		0xcc	/* Mem config, register 1 */
#define	IMC_MEMC_BANK_MASK	0x0000ffff
#define	IMC_MEMC_BANK_SHIFT	16
#define	IMC_MEMC_ADDR_MASK	0x00ff
#define	IMC_MEMC_ADDR_SHIFT	0
#define	IMC_MEMC_SIZE_MASK	0x1f00
#define	IMC_MEMC_SIZE_SHIFT	8
#define	IMC_MEMC_LSHIFT		22	/* 4MB units */
#define	IMC_MEMC_LSHIFT_HUGE	24	/* 16MB units */
#define	IMC_MEMC_VALID		0x2000
#define	IMC_MEMC_SUBBANKS	0x4000

#define IMC_CPU_MEMACC		0xd4	/* CPU mem access config */

#define IMC_GIO_MEMACC		0xdc	/* GIO mem access config */

#define IMC_CPU_ERRADDR		0xe4	/* CPU error address */
#define IMC_CPU_ERRSTAT		0xec	/* CPU error status */
#define	IMC_CPU_ERRSTAT_RD	0x00000100	/* memory parity error */
#define	IMC_CPU_ERRSTAT_PAR	0x00000200	/* CPU parity error */
#define	IMC_CPU_ERRSTAT_ADDR	0x00000400	/* memory bus error */
#define	IMC_CPU_ERRSTAT_SYSAD	0x00000800	/* SysAD parity error */
#define	IMC_CPU_ERRSTAT_SYSCMD	0x00001000	/* syscmd parity error */

#define IMC_GIO_ERRADDR		0xf4	/* GIO error address */
#define IMC_GIO_ERRSTAT		0xfc	/* GIO error status */
#define	IMC_GIO_ERRSTAT_RD	0x00000100	/* read parity error */
#define	IMC_GIO_ERRSTAT_WR	0x00000200	/* write parity error */
#define	IMC_GIO_ERRSTAT_TMO	0x00000400	/* bus timeout */
#define	IMC_GIO_ERRSTAT_PROM	0x00000800	/* PROM write while disabled */
#define	IMC_GIO_ERRSTAT_ADDR	0x00001000	/* parity error during */
						/* address cycle */
#define	IMC_GIO_ERRSTAT_BC	0x00002000	/* parity error during */
						/* byte count cycle */
#define	IMC_GIO_ERRSTAT_PIO_RD	0x00004000	/* data parity error during */
						/* PIO read */
#define	IMC_GIO_ERRSTAT_PIO_WR	0x00008000	/* data parity error during */
						/* PIO write */
/* {CPU,GIO}_ERRSTAT bits in ECC mode */
#define	IMC_ECC_ERRSTAT_FUW	0x00000001	/* fast mode uncached write */
#define	IMC_ECC_ERRSTAT_MULTI	0x00000002	/* multi bit error */

#define IMC_RPSS		0x1004	/* RPSS counter */

/*
 * IP26/IP28 ECC Controller defines
 */

#define	ECC_BASE		0x60000000
/* control register */
#define	ECC_CTRL		0x00
#define	ECC_CTRL_ENABLE		0x00000000	/* fast mode */
#define	ECC_CTRL_DISABLE	0x00010000	/* slow mode */
#define	ECC_CTRL_WRITE		0x00020000	/* write low bits to chip */
#define	ECC_CTRL_INT_CLR	0x00030000	/* clear pending interrupts */
#define	ECC_CTRL_CHK_ENABLE	0x00050000	/* enable ECC err generation */
#define	ECC_CTRL_CHK_DISABLE	0x00060000	/* disable ECC err generation */

/* ecc control chip modes */
#define	ECC_MODE_PASSTHROUGH	0x0002	/* error detection only */
#define	ECC_MODE_NORMAL		0x0003	/* error detection and correction */


code:
/*	$OpenBSD: imcvar.h,v 1.3 2012/09/29 21:46:02 miod Exp $	*/
/*	$NetBSD: imcvar.h,v 1.1 2006/08/30 23:44:52 rumble Exp $	*/

/*
 * Copyright (c) 2006 Stephen M. Rumble
 * 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. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * 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.
 */

struct imc_attach_args {
	const char	*iaa_name;
	bus_space_tag_t	 iaa_st;
	bus_dma_tag_t	 iaa_dmat;
};

void	imc_bus_reset(void);
int	imc_gio64_arb_config(int, uint32_t);
void	imc_disable_sysad_parity(void);
void	imc_enable_sysad_parity(void);
int	imc_is_sysad_parity_enabled(void);

#define	imc_read(o) \
	*(volatile uint32_t *)PHYS_TO_XKPHYS(IMC_BASE + (o), CCA_NC)
#define	imc_write(o,v) \
	*(volatile uint32_t *)PHYS_TO_XKPHYS(IMC_BASE + (o), CCA_NC) = (v)

uint8_t  imc_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
uint16_t imc_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
void	 imc_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    uint8_t *, bus_size_t);
void	 imc_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint8_t);
void	 imc_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint16_t);
void	 imc_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    const uint8_t *, bus_size_t);
uint32_t imc_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
uint64_t imc_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t);
void	 imc_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint32_t);
void	 imc_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint64_t);
void	 imc_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    uint8_t *, bus_size_t);
void	 imc_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    const uint8_t *, bus_size_t);
void	 imc_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    uint8_t *, bus_size_t);
void	 imc_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
	    const uint8_t *, bus_size_t);
int	 imc_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
	    bus_space_handle_t *);
void	 imc_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
int	 imc_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    bus_size_t, bus_space_handle_t *);
void	*imc_space_vaddr(bus_space_tag_t, bus_space_handle_t);

extern struct machine_bus_dma_tag imc_bus_dma_tag;
extern bus_space_t imcbus_tag;


code:
/*	$OpenBSD: int.c,v 1.11 2014/09/30 06:51:58 jmatthew Exp $	*/
/*	$NetBSD: int.c,v 1.24 2011/07/01 18:53:46 dyoung Exp $	*/

/*
 * Copyright (c) 2009 Stephen M. Rumble
 * Copyright (c) 2004 Christopher SEKIYA
 * 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * 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.
 */

/*
 * INT2 (IP20, IP22) / INT3 (IP24) interrupt controllers
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/atomic.h>

#include <mips64/archtype.h>

#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <mips64/mips_cpu.h>
#include <machine/intr.h>

#include <dev/ic/i8253reg.h>

#include <sgi/localbus/intreg.h>
#include <sgi/localbus/intvar.h>
#include <sgi/sgi/ip22.h>

int	int2_match(struct device *, void *, void *);
void	int2_attach(struct device *, struct device *, void *);
int 	int2_mappable_intr(void *);

const struct cfattach int_ca = {
	sizeof(struct device), int2_match, int2_attach
};

struct cfdriver int_cd = {
	NULL, "int", DV_DULL
};

paddr_t	int2_base;
paddr_t	int2_get_base(void);

#define	int2_read(r)		*(volatile uint8_t *)(int2_base + (r))
#define	int2_write(r, v)	*(volatile uint8_t *)(int2_base + (r)) = (v)

void	int_8254_cal(void);
void	int_8254_startclock(struct cpu_info *);
uint32_t int_8254_intr0(uint32_t, struct trap_frame *);

/*
 * INT2 Interrupt handling declarations: 16 local sources on 2 levels.
 *
 * In addition to this, INT3 provides 8 so-called mappable interrupts, which
 * are cascaded to either one of the unused two INT2 VME interrupts.
 * To make things easier from a software viewpoint, we pretend there are
 * 16 of them - one set of 8 per cascaded interrupt. This allows for
 * faster recognition on where to connect these interrupts - as long as
 * interrupt vector assignment makes sure no mappable interrupt is
 * registered on both cascaded interrupts.
 */

struct int2_intrhand {
	struct intrhand	ih;
	uint32_t	flags;
#define	IH_FL_DISABLED	0x01
};

#define	INT2_NINTS	(8 + 8 + 2 * 8)
struct int2_intrhand *int2_intrhand[INT2_NINTS];

uint32_t int2_intem;
uint8_t	int2_l0imask[NIPLS], int2_l1imask[NIPLS];

void	int2_splx(int);
uint32_t int2_l0intr(uint32_t, struct trap_frame *);
void	int2_l0makemasks(void);
uint32_t int2_l1intr(uint32_t, struct trap_frame *);
void	int2_l1makemasks(void);

/*
 * Level 0 interrupt handler.
 */

uint32_t save_l0imr, save_l0isr, save_l0ipl;
#define	INTR_FUNCTIONNAME	int2_l0intr
#define	MASK_FUNCTIONNAME	int2_l0makemasks

#define	INTR_LOCAL_DECLS
#define	MASK_LOCAL_DECLS
#define	INTR_GETMASKS \
do { \
	isr = int2_read(INT2_LOCAL0_STATUS); \
	imr = int2_read(INT2_LOCAL0_MASK); \
	bit = 7; \
save_l0isr = isr; save_l0imr = imr; save_l0ipl = frame->ipl; \
} while (0)
#define	INTR_MASKPENDING \
	int2_write(INT2_LOCAL0_MASK, imr & ~isr)
#define	INTR_IMASK(ipl)		int2_l0imask[ipl]
#define	INTR_HANDLER(bit)	(struct intrhand *)int2_intrhand[bit + 0]
#define	INTR_SPURIOUS(bit) \
do { \
	printf("spurious int2 interrupt %d\n", bit); \
} while (0)
/* explicit masking with int2_intem to cope with handlers disabling themselves */
#define	INTR_MASKRESTORE \
	int2_write(INT2_LOCAL0_MASK, int2_intem & imr)
#define	INTR_MASKSIZE	8

#define	INTR_HANDLER_SKIP(ih) \
	(((struct int2_intrhand *)(ih))->flags /* & IH_FL_DISABLED */)

#include <sgi/sgi/intr_template.c>

/*
 * Level 1 interrupt handler.
 */

uint32_t save_l1imr, save_l1isr, save_l1ipl;
#define	INTR_FUNCTIONNAME	int2_l1intr
#define	MASK_FUNCTIONNAME	int2_l1makemasks

#define	INTR_LOCAL_DECLS
#define	MASK_LOCAL_DECLS
#define	INTR_GETMASKS \
do { \
	isr = int2_read(INT2_LOCAL1_STATUS); \
	imr = int2_read(INT2_LOCAL1_MASK); \
	bit = 7; \
save_l1isr = isr; save_l1imr = imr; save_l1ipl = frame->ipl; \
} while (0)
#define	INTR_MASKPENDING \
	int2_write(INT2_LOCAL1_MASK, imr & ~isr)
#define	INTR_IMASK(ipl)		int2_l1imask[ipl]
#define	INTR_HANDLER(bit)	(struct intrhand *)int2_intrhand[bit + 8]
#define	INTR_SPURIOUS(bit) \
do { \
	printf("spurious int2 interrupt %d\n", bit + 8); \
} while (0)
/* explicit masking with int2_intem to cope with handlers disabling themselves */
#define	INTR_MASKRESTORE \
	int2_write(INT2_LOCAL1_MASK,  (int2_intem >> 8) & imr)
#define	INTR_MASKSIZE	8

#define	INTR_HANDLER_SKIP(ih) \
	(((struct int2_intrhand *)(ih))->flags /* & IH_FL_DISABLED */)

#include <sgi/sgi/intr_template.c>

void *
int2_intr_establish(int irq, int level, int (*ih_fun) (void *),
    void *ih_arg, const char *ih_what)
{
	struct int2_intrhand **p, *q, *ih;
	int s;

#ifdef DIAGNOSTIC
	if (irq < 0 || irq >= INT2_NINTS)
		panic("int2_intr_establish: illegal irq %d", irq);
	/* Mappable interrupts can't be above IPL_TTY */
	if ((irq >> 3) >= 2 && level > IPL_TTY)
		return NULL;
#endif

	ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
	if (ih == NULL)
		return NULL;

	ih->ih.ih_next = NULL;
	ih->ih.ih_fun = ih_fun;
	ih->ih.ih_arg = ih_arg;
	ih->ih.ih_level = level;
	ih->ih.ih_irq = irq;
	if (ih_what != NULL)
		evcount_attach(&ih->ih.ih_count, ih_what, &ih->ih.ih_irq);
	ih->flags = 0;

	s = splhigh();

	for (p = &int2_intrhand[irq]; (q = *p) != NULL;
	    p = (struct int2_intrhand **)&q->ih.ih_next)
		continue;
	*p = ih;

	int2_intem |= 1 << irq;
	switch (irq >> 3) {
	case 0:
		int2_l0makemasks();
		break;
	case 1:
		int2_l1makemasks();
		break;
	/*
	 * We do not maintain masks for mappable interrupts. They are
	 * masked as a whole, by the level 0 or 1 interrupt they cascade to.
	 */
	case 2:
		int2_write(INT2_IP22_MAP_MASK0,
		    int2_read(INT2_IP22_MAP_MASK0) | (1 << (irq & 7)));
		break;
	case 3:
		int2_write(INT2_IP22_MAP_MASK1,
		    int2_read(INT2_IP22_MAP_MASK1) | (1 << (irq & 7)));
		break;
	}

	splx(s);	/* will cause hardware mask update */

	return ih;
}

void
int2_splx(int newipl)
{
	struct cpu_info *ci = curcpu();
	register_t sr;

	__asm__ (".set noreorder");
	ci->ci_ipl = newipl;
	mips_sync();
	__asm__ (".set reorder\n");

	sr = disableintr();	/* XXX overkill? */
	int2_write(INT2_LOCAL1_MASK, (int2_intem >> 8) & ~int2_l1imask[newipl]);
	int2_write(INT2_LOCAL0_MASK, int2_intem & ~int2_l0imask[newipl]);
	setsr(sr);

	if (ci->ci_softpending != 0 && newipl < IPL_SOFTINT)
		setsoftintr0();
}

/*
 * Mappable interrupts handler.
 */

int
int2_mappable_intr(void *arg)
{
	uint which = (unsigned long)arg;
	vaddr_t imrreg;
	uint64_t imr, isr;
	uint i, intnum;
	struct int2_intrhand *ih;
	int rc, ret;

	imrreg = which == 0 ? INT2_IP22_MAP_MASK0 : INT2_IP22_MAP_MASK1;
	isr = int2_read(INT2_IP22_MAP_STATUS);
	imr = int2_read(imrreg);

	isr &= imr;
	if (isr == 0)
		return 0;	/* not for us */

	/*
	 * Don't bother masking sources here - all mappable interrupts are
	 * tied to either a level 1 or level 0 interrupt, and the dispatcher
	 * is registered at IPL_TTY, so we can safely assume we are running
	 * at IPL_TTY now.
	 */
	for (i = 0; i < 8; i++) {
		intnum = i + 16 + (which << 3);
		if (isr & (1 << i)) {
			rc = 0;
			for (ih = int2_intrhand[intnum]; ih != NULL;
			    ih = (struct int2_intrhand *)ih->ih.ih_next) {
				if (ih->flags /* & IH_FL_DISABLED */)
					continue;
				ret = (*ih->ih.ih_fun)(ih->ih.ih_arg);
				if (ret != 0) {
					rc = 1;
					atomic_inc_long((unsigned long *)
					    &ih->ih.ih_count.ec_count);
				}
				if (ret == 1)
					break;
			}
			if (rc == 0)
				printf("spurious int2 mapped interrupt %d\n",
				    i);
		}
	}

	return 1;
}

int
int2_match(struct device *parent, void *match, void *aux)
{
	struct mainbus_attach_args *maa = (void *)aux;

	switch (sys_config.system_type) {
	case SGI_IP20:
	case SGI_IP22:
	case SGI_IP26:
	case SGI_IP28:
		break;
	default:
		return 0;
	}

	return !strcmp(maa->maa_name, int_cd.cd_name);
}

void
int2_attach(struct device *parent, struct device *self, void *aux)
{
	if (int2_base == 0)
		int2_base = int2_get_base();

	printf(" addr 0x%lx\n", XKPHYS_TO_PHYS(int2_base));

	/* Clean out interrupt masks */
	int2_write(INT2_LOCAL0_MASK, 0);
	int2_write(INT2_LOCAL1_MASK, 0);
	int2_write(INT2_IP22_MAP_MASK0, 0);
	int2_write(INT2_IP22_MAP_MASK1, 0);

	/* Reset timer interrupts */
	int2_write(INT2_TIMER_CONTROL,
	    TIMER_SEL0 | TIMER_16BIT | TIMER_SWSTROBE);
	int2_write(INT2_TIMER_CONTROL,
	    TIMER_SEL1 | TIMER_16BIT | TIMER_SWSTROBE);
	int2_write(INT2_TIMER_CONTROL,
	    TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE);
	mips_sync();
	delay(4);
	int2_write(INT2_TIMER_CLEAR, 0x03);

	set_intr(INTPRI_L1, CR_INT_1, int2_l1intr);
	set_intr(INTPRI_L0, CR_INT_0, int2_l0intr);
	register_splx_handler(int2_splx);

	if (sys_config.system_type != SGI_IP20) {
		/* Wire mappable interrupt handlers */
		int2_intr_establish(INT2_L0_INTR(INT2_L0_IP22_MAP0), IPL_TTY,
		    int2_mappable_intr, (void *)0, NULL);
		int2_intr_establish(INT2_L1_INTR(INT2_L1_IP22_MAP1), IPL_TTY,
		    int2_mappable_intr, (void *)1, NULL);
	}

	/*
	 * The 8254 timer does not interrupt on (some?) IP24 systems.
	 */
	if (sys_config.system_type == SGI_IP20 ||
	    sys_config.system_subtype == IP22_INDIGO2)
		int_8254_cal();
}

paddr_t
int2_get_base(void)
{
	uint32_t address;

	switch (sys_config.system_type) {
	case SGI_IP20:
		address = INT2_IP20;
		break;
	default:
	case SGI_IP22:
	case SGI_IP26:
	case SGI_IP28:
		if (sys_config.system_subtype == IP22_INDIGO2)
			address = INT2_IP22;
		else
			address = INT2_IP24;
		break;
	}

	return PHYS_TO_XKPHYS((uint64_t)address, CCA_NC);
}

/*
 * Returns nonzero if the given interrupt source is pending.
 */
int
int2_is_intr_pending(int irq)
{
	paddr_t reg;

	if (int2_base == 0)
		int2_base = int2_get_base();
	switch (irq >> 3) {
	case 0:
		reg = INT2_LOCAL0_STATUS;
		break;
	case 1:
		reg = INT2_LOCAL1_STATUS;
		break;
	case 2:
	case 3:
		reg = INT2_IP22_MAP_STATUS;
		break;
	default:
		return 0;
	}

	return int2_read(reg) & (1 << (irq & 7));
}

/*
 * Temporarily disable an interrupt handler. Note that disable/enable
 * calls can not be stacked.
 *
 * The interrupt source will become masked if it is the only handler.
 * (This is intended for panel(4) which is not supposed to be a shared
 *  interrupt)
 */
void
int2_intr_disable(void *v)
{
	struct int2_intrhand *ih = (struct int2_intrhand *)v;
	int s;

	s = splhigh();
	if ((ih->flags & IH_FL_DISABLED) == 0) {
		ih->flags |= IH_FL_DISABLED;
		if (ih == int2_intrhand[ih->ih.ih_irq] &&
		    ih->ih.ih_next == NULL) {
			/* disable interrupt source */
			int2_intem &= ~(1 << ih->ih.ih_irq);
		}
	}
	splx(s);
}

/*
 * Reenable an interrupt handler.
 */
void
int2_intr_enable(void *v)
{
	struct int2_intrhand *ih = (struct int2_intrhand *)v;
	int s;

	s = splhigh();
	if ((ih->flags & IH_FL_DISABLED) != 0) {
		ih->flags &= ~IH_FL_DISABLED;
		if (ih == int2_intrhand[ih->ih.ih_irq] &&
		    ih->ih.ih_next == NULL) {
			/* reenable interrupt source */
			int2_intem |= 1 << ih->ih.ih_irq;
		}
	}
	splx(s);
}

/*
 * A master clock is wired to TIMER_2, which in turn clocks the two other
 * timers. The master frequency is 1MHz.
 *
 * TIMER_0 and TIMER_1 interrupt on HW_INT_2 and HW_INT_3, respectively.
 *
 * NB: Apparently int2 doesn't like counting down from one, but two works.
 */

static struct evcount int_clock_count;
static int int_clock_irq = 2;

void
int_8254_cal(void)
{
	uint freq = 1000000 / 2 / hz;

	/* Timer0 is our hz. */
	int2_write(INT2_TIMER_CONTROL,
	    TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
	int2_write(INT2_TIMER_0, freq & 0xff);
	mips_sync();
	delay(4);
	int2_write(INT2_TIMER_0, freq >> 8);

	/* Timer2 clocks timer0 and timer1. */
	int2_write(INT2_TIMER_CONTROL,
	    TIMER_SEL2 | TIMER_RATEGEN | TIMER_16BIT);
	int2_write(INT2_TIMER_2, 2);
	mips_sync();
	delay(4);
	int2_write(INT2_TIMER_2, 0);

	set_intr(INTPRI_CLOCK, CR_INT_2, int_8254_intr0);
	evcount_attach(&int_clock_count, "clock", &int_clock_irq);
	md_startclock = int_8254_startclock;
}

uint32_t
int_8254_intr0(uint32_t hwpend, struct trap_frame *tf)
{
	struct cpu_info *ci = curcpu();

	int2_write(INT2_TIMER_CLEAR, 0x01);
	ci->ci_pendingticks++;
	if (ci->ci_clock_started != 0) {
		if (tf->ipl < IPL_CLOCK) {
			while (ci->ci_pendingticks) {
				int_clock_count.ec_count++;
				hardclock(tf);
				ci->ci_pendingticks--;
			}
		}
	}

	return hwpend;
}

void
int_8254_startclock(struct cpu_info *ci)
{
	ci->ci_clock_started++;
}


code:
/*	$OpenBSD: intreg.h,v 1.2 2012/04/15 20:44:52 miod Exp $	*/
/*	$NetBSD: int2reg.h,v 1.5 2009/02/12 06:33:57 rumble Exp $	*/

/*
 * Copyright (c) 2004 Christopher SEKIYA
 * 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * 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.
 */

/* The INT has known locations on all SGI machines */
#define	INT2_IP20		0x1fb801c0
#define	INT2_IP22		0x1fbd9000
#define	INT2_IP24		0x1fbd9880

/* The following registers are all 8 bit. */
#define INT2_LOCAL0_STATUS	0x03
#define INT2_LOCAL0_STATUS_FIFO	0x01
#define INT2_LOCAL0_MASK	0x07
#define INT2_LOCAL1_STATUS	0x0b
#define INT2_LOCAL1_MASK	0x0f
#define INT2_IP22_MAP_STATUS	0x13
#define INT2_IP22_MAP_MASK0	0x17
#define INT2_IP22_MAP_MASK1	0x1b
#define INT2_IP22_MAP_POL	0x1f
#define INT2_IP20_LED		0x1f
#define INT2_TIMER_CLEAR	0x23
#define INT2_ERROR_STATUS	0x27
#define INT2_TIMER_0		0x33
#define	INT2_TIMER_1		0x37
#define	INT2_TIMER_2		0x3b
#define INT2_TIMER_CONTROL	0x3f

/* LOCAL0 bits */
#define	INT2_L0_FIFO		0
#define	INT2_L0_GIO_SLOT0	0	/* IP24 */
#define	INT2_L0_GIO_LVL0	0	/* IP20/IP22 */
#define	INT2_L0_IP20_PARALLEL	1
#define	INT2_L0_IP22_SCSI0	1
#define	INT2_L0_SCSI1		2
#define	INT2_L0_ENET		3
#define	INT2_L0_GFX_DMA		4
#define	INT2_L0_IP20_SERIAL	5
#define	INT2_L0_IP22_PARALLEL	5
#define	INT2_L0_GIO_LVL1	6	/* IP20/IP22 */
#define	INT2_L0_IP20_VME0	7
#define	INT2_L0_IP22_MAP0	7

/* LOCAL1 bits */
#define	INT2_L1_IP24_ISDN_ISAC	0
#define	INT2_L1_IP20_GR1MODE	1	/* not an interrupt but a status bit */
#define	INT2_L1_IP22_PANEL	1
#define	INT2_L1_IP24_ISDN_HSCX	2
#define	INT2_L1_IP20_VME1	3
#define	INT2_L1_IP22_MAP1	3
#define	INT2_L1_IP20_DSP	4
#define	INT2_L1_IP22_HPC_DMA	4
#define	INT2_L1_ACFAIL		5
#define	INT2_L1_VIDEO		6
#define	INT2_L1_RETRACE		7
#define	INT2_L1_GIO_LVL2	7	/* IP20/IP22 */

/* MAP bits */
#define	INT2_MAP_NEWPORT	0	/* IP24 */
#define	INT2_MAP_PASSWD		1
#define	INT2_MAP_ISDN_POWER	2	/* IP24 */
#define	INT2_MAP_EISA		3	/* IP22 */
#define	INT2_MAP_PCKBC		4
#define	INT2_MAP_SERIAL		5
#define	INT2_MAP_GFX0_DRAIN	6	/* IP22 */
#define	INT2_MAP_GIO_SLOT0	6	/* IP24 */
#define	INT2_MAP_GFX1_DRAIN	7	/* IP22 */
#define	INT2_MAP_GIO_SLOT1	7	/* IP24 */

#define	INT2_L0_INTR(x)		((x) + 0)
#define	INT2_L1_INTR(x)		((x) + 8)
#define	INT2_MAP0_INTR(x)	((x) + 16)
#define	INT2_MAP1_INTR(x)	((x) + 24)


code:
/*	$OpenBSD: intvar.h,v 1.3 2012/04/18 11:01:55 miod Exp $	*/
/*	$NetBSD: int2var.h,v 1.3 2008/08/23 17:25:54 tsutsui Exp $	*/

/*
 * Copyright (c) 2004 Christopher SEKIYA
 * 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * 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.
 */

void	*int2_intr_establish(int, int, int (*)(void *),
	    void *, const char *);
int	 int2_is_intr_pending(int);
void	 int2_intr_disable(void *);
void	 int2_intr_enable(void *);