code:
/*	$OpenBSD: ka53.c,v 1.11 2013/07/05 21:11:57 miod Exp $	*/
/*	$NetBSD: ka53.c,v 1.2 2000/06/04 02:19:27 matt Exp $	*/
/*
 * Copyright (c) 2002 Hugh Graham.
 * Copyright (c) 2000 Ludd, University of Lule}, Sweden.
 * 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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *     This product includes software developed at Ludd, University of
 *     Lule}, Sweden and its contributors.
 * 4. 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.
 */

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

#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/scb.h>
#include <machine/sid.h>
#include <machine/mtpr.h>

static void    ka53_conf(void);
static void    ka53_memerr(void);
static int     ka53_mchk(caddr_t);
static void    ka53_softmem(void *);
static void    ka53_hardmem(void *);
static void    ka53_init(void);
static void    ka53_cache_enable(void);

/*
 * Declaration of 680-specific calls.
 */
struct cpu_dep ka53_calls = {
	ka53_init,
	ka53_mchk,
	ka53_memerr,
	ka53_conf,
	generic_clkread,
	generic_clkwrite,
	32,	 /* ~VUPS */
	2,	/* SCB pages */
	generic_halt,
	generic_reboot,
	NULL,
	icr_hardclock
};

void
ka53_conf()
{
	char *cpuname;

	/* This initialises ISP, avoiding interrupt exceptions  */
	{volatile int *hej = (void *)mfpr(PR_ISP); *hej = *hej; hej[-1] = hej[-1];}

	/* This vector (qbus related?) comes out of nowhere, ignore it for now */
	scb_vecalloc(0x0, (void *)nullop, NULL, SCB_ISTACK, NULL);

	cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1);

	switch (vax_cpustype) {
	case VAX_STYP_50:
		cpuname = "KA50";
		break;
	case VAX_STYP_51:
		cpuname = "KA51";
		break;
	case VAX_STYP_52:
		cpuname = "KA52";
		break;
	case VAX_STYP_53:
		cpuname = "KA53";
		break;
	default:
		cpuname = "unknown NVAX";
	}
	printf("cpu0: %s, ucode rev %d\n", cpuname, vax_cpudata & 0xff);
}

/*
 * Why may we get memory errors during startup???
 */

void
ka53_hardmem(void *arg)
{
	if (cold == 0)
		printf("Hard memory error\n");
	splhigh();
}

void
ka53_softmem(void *arg)
{
	if (cold == 0)
		printf("Soft memory error\n");
	splhigh();
}

/*
 * KA53-specific IPRs. KA53 has the funny habit to control all caches
 * via IPRs.
 */
#define PR_CCTL	 0xa0
#define CCTL_ENABLE	0x00000001
#define CCTL_SW_ETM	0x40000000
#define CCTL_HW_ETM	0x80000000

#define PR_BCETSTS	0xa3
#define PR_BCEDSTS	0xa6
#define PR_NESTS	0xae

#define PR_VMAR	 0xd0
#define PR_VTAG	 0xd1
#define PR_ICSR	 0xd3
#define ICSR_ENABLE	0x01

#define PR_PCCTL	0xf8
#define PCCTL_P_EN	0x10
#define PCCTL_I_EN	0x02
#define PCCTL_D_EN	0x01

void
ka53_cache_enable()
{
	int start, slut;

	/*
	 * Turn caches off.
	 */
	mtpr(0, PR_ICSR);
	mtpr(0, PR_PCCTL);
	mtpr(mfpr(PR_CCTL) | CCTL_SW_ETM, PR_CCTL);

	/*
	 * Invalidate caches.
	 */
	mtpr(mfpr(PR_CCTL) | 6, PR_CCTL);	/* Set cache size and speed */
	mtpr(mfpr(PR_BCETSTS), PR_BCETSTS);	/* Clear error bits */
	mtpr(mfpr(PR_BCEDSTS), PR_BCEDSTS);	/* Clear error bits */
	mtpr(mfpr(PR_NESTS), PR_NESTS);	 /* Clear error bits */

	start = 0x01400000;
	slut  = 0x01420000;

	/* Flush cache lines */
	for (; start < slut; start += 0x20)
		mtpr(0, start);

	mtpr((mfpr(PR_CCTL) & ~(CCTL_SW_ETM|CCTL_ENABLE)) | CCTL_HW_ETM,
	    PR_CCTL);

	start = 0x01000000;
	slut  = 0x01020000;

	/* clear tag and valid */
	for (; start < slut; start += 0x20)
		mtpr(0, start);

	mtpr(mfpr(PR_CCTL) | 6 | CCTL_ENABLE, PR_CCTL); /* enab. bcache */

	start = 0x01800000;
	slut  = 0x01802000;

	/* Clear primary cache */
	for (; start < slut; start += 0x20)
		mtpr(0, start);

	/* Flush the pipes (via REI) */
	asm("movpsl -(%sp); movab 1f,-(%sp); rei; 1:;");

	/* Enable primary cache */
	mtpr(PCCTL_P_EN|PCCTL_I_EN|PCCTL_D_EN, PR_PCCTL);

	/* Enable the VIC */
	start = 0;
	slut  = 0x800;
	for (; start < slut; start += 0x20) {
		mtpr(start, PR_VMAR);
		mtpr(0, PR_VTAG);
	}
	mtpr(ICSR_ENABLE, PR_ICSR);
}

void
ka53_memerr()
{
	printf("Memory err!\n");
}

int
ka53_mchk(caddr_t addr)
{
	mtpr(0x00, PR_MCESR);
	printf("Machine Check\n");
	return 0;
}

void
ka53_init()
{

	/*
	 * Get the soft and hard memory error vectors now.
	 */

	scb_vecalloc(0x54, ka53_softmem, NULL, 0, NULL);
	scb_vecalloc(0x60, ka53_hardmem, NULL, 0, NULL);

	/* Turn on caches (to speed up execution a bit) */
	ka53_cache_enable();
}


code:
/*	$OpenBSD: ka60.c,v 1.3 2011/09/15 00:48:24 miod Exp $	*/

/*
 * Copyright (c) 2008 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Copyright (c) 1988 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Mt. Xinu.
 *
 * 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.
 *
 *	@(#)ka650.c	7.7 (Berkeley) 12/16/90
 */

/*
 * VAXstation 3500 (KA60) specific code. Based on the KA650 specific code.
 */

#include <sys/param.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/cvax.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/mtpr.h>
#include <machine/nexus.h>
#include <machine/psl.h>
#include <machine/sid.h>
#include <machine/rpb.h>
#include <machine/cca.h>
#include <machine/scb.h>

#include <vax/mbus/mbusreg.h>
#include <vax/mbus/mbusvar.h>
#include <vax/mbus/fwioreg.h>

int	ka60_clkread(struct timespec *, time_t);
void	ka60_clkwrite(void);
void	ka60_clrf(void);
void	ka60_conf(void);
void	ka60_halt(void);
void	ka60_hardclock(struct clockframe *);
void	ka60_init(void);
int	ka60_mchk(caddr_t);
void	ka60_memerr(void);
void	ka60_reboot(int);

struct	cpu_dep	ka60_calls = {
	ka60_init,
	ka60_mchk,
	ka60_memerr,
	ka60_conf,
	ka60_clkread,
	ka60_clkwrite,
	3,	/* ~VUPS */
	2,	/* SCB pages */
#if 0	/* this ought to work, dammit! */
	cvax_halt,
	cvax_reboot,
#else
	ka60_halt,
	ka60_reboot,
#endif
	ka60_clrf,
	ka60_hardclock
};

void	ka60_memwrtmo(void *);

struct cca *cca;
unsigned int cca_size;

unsigned int ka60cpus = 1;
uint32_t *ka60_iocsr;

/*
 * Early system initialization, while still running physical.
 *
 * The PROM will have enabled the L2 cache, but each individual
 * CPU still has its own L1 cache disabled.
 *
 * L1 cache configuration is similar to KA650, without external
 * configuration registers.
 */
void
ka60_init()
{
	unsigned int mid;
	paddr_t fbicaddr;
	uint32_t modtype, fbicrange;
	int i;

	/*
	 * Enable CPU cache.
	 */
	mtpr(CADR_SEN2 | CADR_SEN1 | CADR_CENI | CADR_CEND, PR_CADR);

	cca = (struct cca *)rpb.cca_addr;	/* physical!!! */
	if (cca == NULL) {
		/*
		 * If things are *that* wrong, stick to 2 cpus and a
		 * monoprocessor kernel, really.  We could try looking
		 * for a CCA signature from the top of memory downwards,
		 * or count CPU boards to get the correct number of
		 * processors, but is it really worth doing? I don't
		 * think we are in Kansas anymore anyway...
		 */
		ka60cpus = 2;
	} else {
		cca_size = vax_atop(cca->cca_size);

		/*
		 * Count the other processors.
		 */
		for (i = 0; i < cca->cca_nproc; i++)
			if (cca->cca_console & (1 << i))
				ka60cpus++;
	}

	snprintf(cpu_model, sizeof cpu_model, "VAXstation 35%d0", ka60cpus);

	/*
	 * Silence memory write timeout errors now.
	 */
	scb_vecalloc(0x60, ka60_memwrtmo, NULL, 0, NULL);

	/*
	 * We need to find out which M-bus slot contains the I/O
	 * module.  This could not have been done before because
	 * we were not able to handle machine check (and thus run
	 * badaddr() on each slot), and this has to be done before
	 * consinit() may try to talk to the serial ports.
	 *
	 * Note that there might be multiple I/O modules in the system.
	 * We do not know which I/O module the PROM will prefer; however
	 * since only one module should be configured to map the SSC at
	 * its preferred address, it is possible to find out which one
	 * has been selected.
	 */

	for (mid = 0; mid < MBUS_SLOT_MAX; mid++) {
		fbicaddr = MBUS_SLOT_BASE(mid) + FBIC_BASE;
		if (badaddr((caddr_t)(fbicaddr + FBIC_MODTYPE), 4) != 0)
			continue;
		modtype = *(uint32_t *)(fbicaddr + FBIC_MODTYPE);
		if ((modtype & MODTYPE_CLASS_MASK) >> MODTYPE_CLASS_SHIFT !=
		    CLASS_IO)
			continue;

		mbus_ioslot = mid;

		fbicrange = *(uint32_t *)(fbicaddr + FBIC_RANGE);
		if (fbicrange ==
		    ((HOST_TO_MBUS(CVAX_SSC) & RANGE_MATCH) | RANGE_ENABLE))
			break;
	}

	if ((int)mbus_ioslot < 0) {
		/*
		 * This shouldn't happen. Try mid #5 (enclosure slot #4) as a
		 * supposedly sane default.
		 */
		mbus_ioslot = 5;
	}
}

/*
 * Early system initialization, while running virtual, and before
 * devices are probed.
 */
void
ka60_conf()
{
	printf("cpu0: KA60\n");

	cvax_ssc_ptr = (void *)vax_map_physmem(CVAX_SSC, 3);

	/*
	 * Remap the CCA now we're running virtual.
	 */
	if (cca != NULL)
		cca = (void *)vax_map_physmem((paddr_t)cca, cca_size);

	/*
	 * Map the IOCSR register of the main I/O module, and enable
	 * CPU clock.  We'll need this mapping for reset as well.
	 */
	ka60_iocsr = (uint32_t *)vax_map_physmem(MBUS_SLOT_BASE(mbus_ioslot) +
	    FWIO_IOCSR_OFFSET, 1);
	if (ka60_iocsr == 0)
		panic("can not map IOCSR");

	*ka60_iocsr |= FWIO_IOCSR_CLKIEN | FWIO_IOCSR_MRUN | FWIO_IOCSR_CNSL;
}

/*
 * Corrected memory error trap.
 */
void
ka60_memerr()
{
	printf("cpu0: corrected memory error\n");
	/*
	 * Need to peek at the M-bus error logs, display anything
	 * interesting, and clear them.
	 */
}

/*
 * Machine check trap.
 */
int
ka60_mchk(caddr_t mcef)
{
	struct cvax_mchk_frame *mcf = (struct cvax_mchk_frame *)mcef;
	u_int type = mcf->cvax_summary;
	const char *descr;

	printf("machine check %x", type);
	descr = cvax_mchk_descr(type);
	if (descr != NULL)
		printf(": %s", descr);
	printf("\n\tvap %x istate1 %x istate2 %x pc %x psl %x\n",
	    mcf->cvax_mrvaddr, mcf->cvax_istate1, mcf->cvax_istate2,
	    mcf->cvax_pc, mcf->cvax_psl);

	return MCHK_PANIC;
}

/*
 * Clock routines.  They need to access the TODR through the SSC.
 */
int
ka60_clkread(struct timespec *ts, time_t base)
{
	unsigned klocka = cvax_ssc_ptr->ssc_todr;

	/*
	 * Sanity check.
	 */
	if (klocka < TODRBASE) {
		if (klocka == 0) {
			printf("TODR stopped");
			cvax_ssc_ptr->ssc_todr = 1;	/* spin it */
		} else
			printf("TODR too small");
		return EINVAL;
	}

	ts->tv_sec = yeartonum(numtoyear(base)) + (klocka - TODRBASE) / 100;
	ts->tv_nsec = 0;
	return 0;
}

void
ka60_clkwrite()
{
	uint32_t tid = time_second, bastid;

	bastid = tid - yeartonum(numtoyear(tid));
	cvax_ssc_ptr->ssc_todr = (bastid * 100) + TODRBASE;
}

void
ka60_halt()
{
	printf("system halted.\n");
	asm("halt");
}

void
ka60_reboot(arg)
	int arg;
{
	printf("resetting system...\n");
	delay(500000);
	*ka60_iocsr |= FWIO_IOCSR_RSTWS;
}

/*
 * Probing empty M-bus slots causes this vector to be triggered.
 *
 * We get one after the first spl0(), if probing for the console
 * slot caused us to look at empty slots, and then one per empty
 * slot during autoconf.
 *
 * There shouldn't be any such error after autoconf, though.
 */
void
ka60_memwrtmo(void *arg)
{
	/* do nothing */
}

void
ka60_clrf(void)
{
	/*
	 * Restore the memory write timeout vector.
	 */
	scb_vecalloc(0x60, scb_stray, (void *)0x60, SCB_ISTACK, NULL);
}

/*
 * SSC clock interrupts come at level 0x16, which is not enough for
 * our needs, so raise the level here before invoking hardclock().
 */
void
ka60_hardclock(struct clockframe *cf)
{
	int s;

	s = splclock();
	icr_hardclock(cf);
	splx(s);
}

license: unknown


code:
/*	$OpenBSD: ka630.c,v 1.12 2011/09/15 00:48:24 miod Exp $	*/
/*	$NetBSD: ka630.c,v 1.17 1999/09/06 19:52:52 ragge Exp $	*/
/*-
 * Copyright (c) 1982, 1988, 1990, 1993
 *	The Regents of the University of California.  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. 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.
 *
 *	@(#)ka630.c	7.8 (Berkeley) 5/9/91
 */

#include <sys/param.h>
#include <sys/types.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/time.h>
#include <sys/systm.h>

#include <uvm/uvm_extern.h>

#include <machine/cpu.h>
#include <machine/pmap.h>
#include <machine/ka630.h>
#include <machine/clock.h>
#include <machine/vsbus.h>

static struct uvaxIIcpu *uvaxIIcpu_ptr;

static void ka630_conf(void);
static void ka630_memerr(void);
static int ka630_mchk(caddr_t);
static void ka630_halt(void);
static void ka630_reboot(int);
static void ka630_clrf(void);

struct	cpu_dep ka630_calls = {
	0,
	ka630_mchk,
	ka630_memerr,
	ka630_conf,
	chip_clkread,
	chip_clkwrite,
	1,      /* ~VUPS */
	2,	/* SCB pages */
	ka630_halt,
	ka630_reboot,
	ka630_clrf,
	icr_hardclock
};

/*
 * uvaxII_conf() is called by cpu_attach to do the cpu_specific setup.
 */
void
ka630_conf()
{
	clk_adrshift = 0;	/* Addressed at short's... */
	clk_tweak = 0;		/* ...and no shifting */
	clk_page = (short *)vax_map_physmem((paddr_t)KA630CLK, 1);

	uvaxIIcpu_ptr = (void *)vax_map_physmem(VS_REGS, 1);

	/*
	 * Enable memory parity error detection and clear error bits.
	 */
	uvaxIIcpu_ptr->uvaxII_mser = (UVAXIIMSER_PEN | UVAXIIMSER_MERR |
	    UVAXIIMSER_LEB);
}

/* log crd errors */
void
ka630_memerr()
{
	printf("memory err!\n");
}

#define NMC78032 10
char *mc78032[] = {
	0,		"immcr (fsd)",	"immcr (ssd)",	"fpu err 0",
	"fpu err 7",	"mmu st(tb)",	"mmu st(m=0)",	"pte in p0",
	"pte in p1",	"un intr id",
};

struct mc78032frame {
	int	mc63_bcnt;		/* byte count == 0xc */
	int	mc63_summary;		/* summary parameter */
	int	mc63_mrvaddr;		/* most recent vad */
	int	mc63_istate;		/* internal state */
	int	mc63_pc;		/* trapped pc */
	int	mc63_psl;		/* trapped psl */
};

int
ka630_mchk(cmcf)
	caddr_t cmcf;
{
	register struct mc78032frame *mcf = (struct mc78032frame *)cmcf;
	register u_int type = mcf->mc63_summary;

	printf("machine check %x", type);
	if (type < NMC78032 && mc78032[type])
		printf(": %s", mc78032[type]);
	printf("\n\tvap %x istate %x pc %x psl %x\n",
	    mcf->mc63_mrvaddr, mcf->mc63_istate,
	    mcf->mc63_pc, mcf->mc63_psl);
	if (uvaxIIcpu_ptr && uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_MERR) {
		printf("\tmser=0x%lx ", uvaxIIcpu_ptr->uvaxII_mser);
		if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_CPUE)
			printf("page=%ld", uvaxIIcpu_ptr->uvaxII_cear);
		if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_DQPE)
			printf("page=%ld", uvaxIIcpu_ptr->uvaxII_dear);
		printf("\n");
	}
	return (-1);
}

static void
ka630_halt()
{
	((struct ka630clock *)clk_page)->cpmbx = KA630CLK_DOTHIS|KA630CLK_HALT;
	asm("halt");
}

static void
ka630_reboot(arg)
	int arg;
{
	((struct ka630clock *)clk_page)->cpmbx =
	    KA630CLK_DOTHIS | KA630CLK_REBOOT;
}

/*
 * Clear restart and boot in progress flags in the CPMBX.
 */
static void
ka630_clrf()
{
	short i = ((struct ka630clock *)clk_page)->cpmbx;

	((struct ka630clock *)clk_page)->cpmbx = i & KA630CLK_LANG;
}


code:
/*	$OpenBSD: ka650.c,v 1.22 2014/05/08 19:06:07 miod Exp $	*/
/*	$NetBSD: ka650.c,v 1.25 2001/04/27 15:02:37 ragge Exp $	*/
/*
 * Copyright (c) 1988 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Mt. Xinu.
 *
 * 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.
 *
 *	@(#)ka650.c	7.7 (Berkeley) 12/16/90
 */

/*
 * vax650-specific code.
 */

#include <sys/param.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/cvax.h>
#include <machine/ka650.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/psl.h>
#include <machine/mtpr.h>
#include <machine/sid.h>
#include <machine/nexus.h>

struct	ka650_merr *ka650merr_ptr;
struct	ka650_cbd *ka650cbd_ptr;
struct	ka650_ipcr *ka650ipcr_ptr;
int	*KA650_CACHE_ptr;

#define	CACHEOFF	0
#define	CACHEON		1

static	void	ka650setcache(int);
static	void    uvaxIII_conf(void);
static	void    uvaxIII_memerr(void);
static	int     uvaxIII_mchk(caddr_t);

struct	cpu_dep	ka650_calls = {
	NULL,
	uvaxIII_mchk,
	uvaxIII_memerr,
	uvaxIII_conf,
	generic_clkread,
	generic_clkwrite,
	4,      /* ~VUPS */
	2,	/* SCB pages */
	cvax_halt,
	cvax_reboot,
	NULL,
	icr_hardclock
};

/*
 * uvaxIII_conf() is called by cpu_attach to do the cpu_specific setup.
 */
void
uvaxIII_conf()
{
	/*
	 * MicroVAX III: We map in memory error registers,
	 * cache control registers, SSC registers,
	 * interprocessor registers and cache diag space.
	 */
	ka650merr_ptr = (void *)vax_map_physmem(KA650_MERR, 1);
	ka650cbd_ptr = (void *)vax_map_physmem(KA650_CBD, 1);
	cvax_ssc_ptr = (void *)vax_map_physmem(CVAX_SSC, 3);
	ka650ipcr_ptr = (void *)vax_map_physmem(KA650_IPCR, 1);
	KA650_CACHE_ptr = (void *)vax_map_physmem(KA650_CACHE,
	    (KA650_CACHESIZE/VAX_NBPG));

	printf("cpu: KA6%d%d, CVAX microcode rev %d Firmware rev %d\n",
	    vax_cpustype == VAX_STYP_640 ? 4 : 5,
	    vax_cpustype == VAX_STYP_655 ? 5 : 0,
	    (vax_cpudata & 0xff), GETFRMREV(vax_siedata));
	ka650setcache(CACHEON);
	if (ptoa(physmem) > ka650merr_ptr->merr_qbmbr) {
		printf("physmem(0x%lx) > qbmbr(0x%lx)\n",
		    ptoa(physmem), ka650merr_ptr->merr_qbmbr);
		panic("qbus map unprotected");
	}
	if (mfpr(PR_TODR) == 0)
		mtpr(1, PR_TODR);
}

void
uvaxIII_memerr()
{
	printf("memory err!\n");
#if 0 /* XXX Fix this */
	register char *cp = (char *)0;
	register int m;
	extern u_int cache2tag;

	if (ka650cbd.cbd_cacr & CACR_CPE) {
		printf("cache 2 tag parity error: ");
		if (time_second - cache2tag < 7) {
			ka650setcache(CACHEOFF);
			printf("caching disabled\n");
		} else {
			cache2tag = time_second;
			printf("flushing cache\n");
			ka650setcache(CACHEON);
		}
	}
	m = ka650merr.merr_errstat;
	ka650merr.merr_errstat = MEM_EMASK;
	if (m & MEM_CDAL) {
		cp = "Bus Parity";
	} else if (m & MEM_RDS) {
		cp = "Hard ECC";
	} else if (m & MEM_CRD) {
		cp = "Soft ECC";
	}
	if (cp) {
		printf("%sMemory %s Error: page 0x%x\n",
			(m & MEM_DMA) ? "DMA " : "", cp,
			(m & MEM_PAGE) >> MEM_PAGESHFT);
	}
#endif
}

u_int	cache1tag;
u_int	cache1data;
u_int	cdalerr;
u_int	cache2tag;

int
uvaxIII_mchk(cmcf)
	caddr_t cmcf;
{
	struct cvax_mchk_frame *mcf = (struct cvax_mchk_frame *)cmcf;
	u_int type = mcf->cvax_summary;
	const char *descr;
	u_int i;

	printf("machine check %x", type);
	descr = cvax_mchk_descr(type);
	if (descr != NULL)
		printf(": %s", descr);
	printf("\n\tvap %x istate1 %x istate2 %x pc %x psl %x\n",
	    mcf->cvax_mrvaddr, mcf->cvax_istate1, mcf->cvax_istate2,
	    mcf->cvax_pc, mcf->cvax_psl);
	printf("dmaser=0x%lb qbear=0x%lx dmaear=0x%lx\n",
	    ka650merr_ptr->merr_dser, DMASER_BITS,
	    ka650merr_ptr->merr_qbear,
	    ka650merr_ptr->merr_dear);
	ka650merr_ptr->merr_dser = DSER_CLEAR;

	i = mfpr(PR_CAER);
	mtpr(CAER_MCC | CAER_DAT | CAER_TAG, PR_CAER);
	if (i & CAER_MCC) {
		printf("cache 1 ");
		if (i & CAER_DAT) {
			printf("data");
			i = cache1data;
			cache1data = time_second;
		}
		if (i & CAER_TAG) {
			printf("tag");
			i = cache1tag;
			cache1tag = time_second;
		}
	} else if ((i & CAER_MCD) || (ka650merr_ptr->merr_errstat & MEM_CDAL)) {
		printf("CDAL");
		i = cdalerr;
		cdalerr = time_second;
	}
	if (time_second - i < 7) {
		ka650setcache(CACHEOFF);
		printf(" parity error:	caching disabled\n");
	} else {
		printf(" parity error:	flushing cache\n");
		ka650setcache(CACHEON);
	}
	/*
	 * May be able to recover if type is 1-4, 0x80 or 0x81, but
	 * only if FPD is set in the saved PSL, or bit VCR in Istate2
	 * is clear.
	 */
	if ((type > 0 && type < 5) || type == 0x80 || type == 0x81) {
		if ((mcf->cvax_psl & PSL_FPD)
		    || !(mcf->cvax_istate2 & IS2_VCR)) {
			uvaxIII_memerr();
			return MCHK_RECOVERED;
		}
	}
	return MCHK_PANIC;
}

/*
 * Make sure both caches are off and not in diagnostic mode.  Clear the
 * 2nd level cache (by writing to each quadword entry), then enable it.
 * Enable 1st level cache too.
 */
void
ka650setcache(int state)
{
	int i;

	/*
	 * Before doing anything, disable the cache.
	 */
	mtpr(0, PR_CADR);
	if (vax_cpustype != VAX_STYP_640)
		ka650cbd_ptr->cbd_cacr = CACR_CPE;

	/*
	 * Check what we want to do, enable or disable.
	 */
	if (state == CACHEON) {
		mtpr(CADR_SEN2 | CADR_SEN1 | CADR_CENI | CADR_CEND, PR_CADR);
		if (vax_cpustype != VAX_STYP_640) {
			for (i = 0;
			    i < (KA650_CACHESIZE / sizeof(KA650_CACHE_ptr[0]));
			    i += 2)
				KA650_CACHE_ptr[i] = 0;
			ka650cbd_ptr->cbd_cacr = CACR_CEN;
		}
	}
}


code:
/*	$OpenBSD: ka660.c,v 1.8 2011/09/15 00:48:24 miod Exp $	*/
/*	$NetBSD: ka660.c,v 1.3 2000/06/29 07:14:27 mrg Exp $	*/
/*
 * Copyright (c) 2000 Ludd, University of Lule}, Sweden.
 * 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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *     This product includes software developed at Ludd, University of
 *     Lule}, Sweden and its contributors.
 * 4. 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/pte.h>
#include <machine/cpu.h>
#include <machine/mtpr.h>
#include <machine/sid.h>
#include <machine/pmap.h>
#include <machine/uvax.h>
#include <machine/ka410.h>
#include <machine/ka420.h>
#include <machine/clock.h>
#include <machine/vsbus.h>

#define KA660_CCR	37	/* Cache Control Register */
#define KA660_CTAG	0x20150000	/* Cache Tags */
#define KA660_CDATA	0x20150400	/* Cache Data */
#define KA660_BEHR	0x20150800	/* Bank Enable/Hit Register */
#define CCR_WWP 8	/* Write Wrong Parity */
#define CCR_ENA 4	/* Cache Enable */
#define CCR_FLU 2	/* Cache Flush */
#define CCR_DIA 1	/* Diagnostic mode */

static void    ka660_conf(void);
static void    ka660_memerr(void);
static int     ka660_mchk(caddr_t);
static void    ka660_cache_enable(void);

/*
 * Declaration of 660-specific calls.
 */
struct cpu_dep ka660_calls = {
	ka660_cache_enable,
	ka660_mchk,
	ka660_memerr,
	ka660_conf,
	generic_clkread,
	generic_clkwrite,
	6,	/* ~VUPS */
	2,	/* SCB pages */
	generic_halt,
	generic_reboot,
	NULL,
	icr_hardclock
};

void
ka660_conf()
{
	printf("cpu0: KA660, microcode Rev. %d\n", vax_cpudata & 0377);

	cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1);
}

void
ka660_cache_enable()
{
	unsigned int *p;
	int cnt, bnk, behrtmp;

	mtpr(0, KA660_CCR);	/* Disable cache */
	mtpr(CCR_DIA, KA660_CCR);	/* Switch to diag mode */
	bnk = 1;
	behrtmp = 0;
	while(bnk <= 0x80)
	{
		*(int *)KA660_BEHR = bnk;
		p = (int *)KA660_CDATA;
		*p = 0x55aaff00L;
		if(*p == 0x55aaff00L) behrtmp |= bnk;
		*p = 0xffaa0055L;
		if(*p != 0xffaa0055L) behrtmp &= ~bnk;
		cnt = 256;
		while(cnt--) *p++ = 0L;
		p = (int *) KA660_CTAG;
		cnt =128;
		while(cnt--) { *p++ = 0x80000000L; p++; }
		bnk <<= 1;
	}
	*(int *)KA660_BEHR = behrtmp;

	mtpr(CCR_DIA|CCR_FLU, KA660_CCR);	/* Flush tags */
	mtpr(CCR_ENA, KA660_CCR);	/* Enable cache */
}

void
ka660_memerr()
{
	printf("Memory err!\n");
}

int
ka660_mchk(addr)
	caddr_t addr;
{
	panic("Machine check");
	return 0;
}


code:
/*	$OpenBSD: ka670.c,v 1.12 2014/05/08 19:06:07 miod Exp $	*/
/*	$NetBSD: ka670.c,v 1.4 2000/03/13 23:52:35 soren Exp $	*/
/*
 * Copyright (c) 1999 Ludd, University of Lule}, Sweden.
 * All rights reserved.
 *
 * This code is derived from software contributed to Ludd by Bertram Barth.
 *
 * 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 at Ludd, University of
 *	Lule}, Sweden and its contributors.
 * 4. 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/pte.h>
#include <machine/cpu.h>
#include <machine/mtpr.h>
#include <machine/sid.h>
#include <machine/pmap.h>
#include <machine/uvax.h>
#include <machine/vsbus.h>
#include <machine/ka670.h>
#include <machine/clock.h>

static	void ka670_conf(void);

static	int ka670_mchk(caddr_t);
static	void ka670_memerr(void);
static	int ka670_cache_init(void);	/* "int mapen" as argument? */

struct	cpu_dep ka670_calls = {
	0,
	ka670_mchk,
	ka670_memerr,
	ka670_conf,
	generic_clkread,
	generic_clkwrite,
	8,	/* 8 VUP */
	2,	/* SCB pages */
	generic_halt,
	generic_reboot,
	NULL,
	icr_hardclock
};

#define KA670_MC_RESTART	0x00008000	/* Restart possible*/
#define KA670_PSL_FPDONE	0x00010000	/* First Part Done */

struct ka670_mcframe {		/* Format of RigelMAX machine check frame: */
	int	mc670_bcnt;	/* byte count, always 24 (0x18) */
	int	mc670_code;	/* machine check type code and restart bit */
	int	mc670_addr;	/* most recent (faulting?) virtual address */
	int	mc670_viba;	/* contents of VIBA register */
	int	mc670_sisr;	/* ICCS bit 6 and SISR bits 15:0 */
	int	mc670_istate;	/* internal state */
	int	mc670_sc;	/* shift count register */
	int	mc670_pc;	/* trapped PC */
	int	mc670_psl;	/* trapped PSL */
};

#if 0

/*
 * This is not the mchk types on KA670.
 */
static char *ka670_mctype[] = {
	"no error (0)",			/* Code 0: No error */
	"FPA: protocol error",		/* Code 1-5: FPA errors */
	"FPA: illegal opcode",
	"FPA: operand parity error",
	"FPA: unknown status",
	"FPA: result parity error",
	"unused (6)",			/* Code 6-7: Unused */
	"unused (7)",
	"MMU error (TLB miss)",		/* Code 8-9: MMU errors */
	"MMU error (TLB hit)",
	"HW interrupt at unused IPL",	/* Code 10: Interrupt error */
	"MOVCx impossible state",	/* Code 11-13: Microcode errors */
	"undefined trap code (i-box)",
	"undefined control store address",
	"unused (14)",			/* Code 14-15: Unused */
	"unused (15)",
	"PC tag or data parity error",	/* Code 16: Cache error */
	"data bus parity error",	/* Code 17: Read error */
	"data bus error (NXM)",		/* Code 18: Write error */
	"undefined data bus state",	/* Code 19: Bus error */
};
#define MC670_MAX	19
#endif

static int ka670_error_count = 0;

int
ka670_mchk(addr)
	caddr_t addr;
{
	register struct ka670_mcframe *mcf = (void *)addr;

	mtpr(0x00, PR_MCESR);	/* Acknowledge the machine check */
	printf("machine check %d (0x%x)\n", mcf->mc670_code, mcf->mc670_code);
	printf("PC %x PSL %x\n", mcf->mc670_pc, mcf->mc670_psl);
	if (++ka670_error_count > 10) {
		printf("error_count exceeded: %d\n", ka670_error_count);
		return (-1);
	}

	/*
	 * If either the Restart flag is set or the First-Part-Done flag
	 * is set, and the TRAP2 (double error) bit is not set, then the
	 * error is recoverable.
	 */
	if (mfpr(PR_PCSTS) & KA670_PCS_TRAP2) {
		printf("TRAP2 (double error) in ka670_mchk.\n");
		panic("unrecoverable state in ka670_mchk.");
		return (-1);
	}
	if ((mcf->mc670_code & KA670_MC_RESTART) ||
	    (mcf->mc670_psl & KA670_PSL_FPDONE)) {
		printf("ka670_mchk: recovering from machine-check.\n");
		ka670_cache_init();	/* reset caches */
		return (0);		/* go on; */
	}

	/*
	 * Unknown error state, panic/halt the machine!
	 */
	printf("ka670_mchk: unknown error state!\n");
	return (-1);
}

void
ka670_memerr()
{
	/*
	 * Don\'t know what to do here. So just print some messages
	 * and try to go on...
	 */
	printf("memory error!\n");
	printf("primary cache status: %lb\n", mfpr(PR_PCSTS), KA670_PCSTS_BITS);
	printf("secondary cache status: %lb\n", mfpr(PR_BCSTS),
	    KA670_BCSTS_BITS);
}

int
ka670_cache_init()
{
	int val;

	mtpr(KA670_PCS_REFRESH, PR_PCSTS);	/* disable primary cache */
	val = mfpr(PR_PCSTS);
	mtpr(val, PR_PCSTS);			/* clear error flags */
	mtpr(8, PR_BCCTL);			/* disable backup cache */
	mtpr(0, PR_BCFBTS);	/* flush backup cache tag store */
	mtpr(0, PR_BCFPTS);	/* flush primary cache tag store */
	mtpr(0x0e, PR_BCCTL);	/* enable backup cache */
	mtpr(KA670_PCS_FLUSH | KA670_PCS_REFRESH, PR_PCSTS);	/* flush primary cache */
	mtpr(KA670_PCS_ENABLE | KA670_PCS_REFRESH, PR_PCSTS);	/* flush primary cache */

#ifdef DEBUG
	printf("primary cache status: %b\n", mfpr(PR_PCSTS), KA670_PCSTS_BITS);
	printf("secondary cache status: %b\n", mfpr(PR_BCSTS), KA670_BCSTS_BITS);
#endif

	return (0);
}
void
ka670_conf()
{
	printf("cpu0: KA670, ucode rev %d\n", vax_cpudata % 0377);

	/*
	 * ka670_conf() gets called with MMU enabled, now it's safe to
	 * init/reset the caches.
	 */
	ka670_cache_init();

	cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1);
}


code:
/*	$OpenBSD: ka680.c,v 1.16 2013/07/05 21:11:57 miod Exp $	*/
/*	$NetBSD: ka680.c,v 1.3 2001/01/28 21:01:53 ragge Exp $	*/
/*
 * Copyright (c) 2002 Hugh Graham.
 * Copyright (c) 2000 Ludd, University of Lule}, Sweden.
 * 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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *     This product includes software developed at Ludd, University of
 *     Lule}, Sweden and its contributors.
 * 4. 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.
 */

/* Done by Michael Kukat (michael@unixiron.org) */
/* minor modifications for KA690 cache support by isildur@vaxpower.org */

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

#include <machine/pte.h>
#include <machine/cpu.h>
#include <machine/mtpr.h>
#include <machine/sid.h>
#include <machine/uvax.h>
#include <machine/ka680.h>
#include <machine/clock.h>
#include <machine/scb.h>

static void	ka680_conf(void);
static void	ka680_cache_enable(void);
static void	ka680_softmem(void *);
static void	ka680_hardmem(void *);
static void	ka680_init(void);
static void	ka680_memerr(void);
static int	ka680_mchk(caddr_t);

/*
 * KA680-specific IPRs. KA680 has the funny habit to control all caches
 * via IPRs.
 */
#define PR_CCTL	 0xa0
#define CCTL_ENABLE	0x00000001
#define CCTL_SW_ETM	0x40000000
#define CCTL_HW_ETM	0x80000000

#define PR_BCETSTS	0xa3
#define PR_BCEDSTS	0xa6
#define PR_NESTS	0xae

#define PR_VMAR	 0xd0
#define PR_VTAG	 0xd1
#define PR_ICSR	 0xd3
#define ICSR_ENABLE	0x01

#define PR_PCCTL	0xf8
#define PCCTL_P_EN	0x10
#define PCCTL_I_EN	0x02
#define PCCTL_D_EN	0x01

/*
 * Declaration of KA680-specific calls.
 */
struct cpu_dep ka680_calls = {
	ka680_init,
	ka680_mchk,
	ka680_memerr,
	ka680_conf,
	generic_clkread,
	generic_clkwrite,
	24,	 /* ~VUPS */
	2,	/* SCB pages */
	generic_halt,
	generic_reboot,
	NULL,
	icr_hardclock
};

void
ka680_conf()
{
	char *cpuname;

	/* Don't ask why, but we seem to need this... */

	volatile int *hej = (void *)mfpr(PR_ISP);
	*hej = *hej;
	hej[-1] = hej[-1];

	cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1);

	switch(vax_boardtype) {
	case VAX_BTYP_1301:
		switch (vax_cpustype) {
		case VAX_STYP_675:
			cpuname = "KA675";
			break;
		case VAX_STYP_680:
			cpuname = "KA680";
			break;
		case VAX_STYP_690:
			cpuname = "KA690";
			break;
		default:
			cpuname = "unknown NVAX 1301";
		}
		break;
	case VAX_BTYP_1305:
		switch (vax_cpustype) {
		case VAX_STYP_681:
			cpuname = "KA681";
			break;
		case VAX_STYP_691:
			cpuname = "KA691";
			break;
		case VAX_STYP_694:
			if (vax_cpudata & 0x1000)
				cpuname = "KA694";
			else
				cpuname = "KA692";
			break;
		default:
			cpuname = "unknown NVAX 1305";
		}
	}
	printf("cpu0: %s, ucode rev %d\n", cpuname, vax_cpudata & 0xff);
}

void
ka680_cache_enable()
{
	int start, pslut, fslut, cslut, havevic;

	/*
	 * Turn caches off.
	 */
	mtpr(0, PR_ICSR);
	mtpr(0, PR_PCCTL);
	mtpr(mfpr(PR_CCTL) | CCTL_SW_ETM, PR_CCTL);

	/*
	 * Invalidate caches.
	 */
	mtpr(mfpr(PR_CCTL) | 6, PR_CCTL);	/* Set cache size and speed */
	mtpr(mfpr(PR_BCETSTS), PR_BCETSTS);	/* Clear error bits */
	mtpr(mfpr(PR_BCEDSTS), PR_BCEDSTS);	/* Clear error bits */
	mtpr(mfpr(PR_NESTS), PR_NESTS);	 /* Clear error bits */

	switch (vax_cpustype) {
	case VAX_STYP_680:
	case VAX_STYP_681:	/* XXX untested */
		fslut = 0x01420000;
		cslut = 0x01020000;
		havevic = 1;
		break;
	case VAX_STYP_690:
		fslut = 0x01440000;
		cslut = 0x01040000;
		havevic = 1;
		break;
	case VAX_STYP_691:	/* XXX untested */
		fslut = 0x01420000;
		cslut = 0x01020000;
		havevic = 1;
		break;
	case VAX_STYP_694:	/* XXX untested */
		fslut = 0x01440000;
		cslut = 0x01040000;
		havevic = 1;
		break;
	case VAX_STYP_675:
	default:		/* unknown cpu; cross fingers */
		fslut = 0x01420000;
		cslut = 0x01020000;
		havevic = 0;
		break;
	}

	start = 0x01400000;

	/* Flush cache lines */
	for (; start < fslut; start += 0x20)
		mtpr(0, start);

	mtpr((mfpr(PR_CCTL) & ~(CCTL_SW_ETM|CCTL_ENABLE)) | CCTL_HW_ETM,
	    PR_CCTL);

	start = 0x01000000;

	/* clear tag and valid */
	for (; start < cslut; start += 0x20)
		mtpr(0, start);

	mtpr(mfpr(PR_CCTL) | 6 | CCTL_ENABLE, PR_CCTL); /* enab. bcache */

	start = 0x01800000;
	pslut = 0x01802000;

	/* Clear primary cache */
	for (; start < pslut; start += 0x20)
		mtpr(0, start);

	/* Flush the pipes (via REI) */
	asm("movpsl -(%sp); movab 1f,-(%sp); rei; 1:;");

	/* Enable primary cache */
	mtpr(PCCTL_P_EN|PCCTL_I_EN|PCCTL_D_EN, PR_PCCTL);

	/* Enable the VIC */
	if (havevic) {
		int slut;

		start = 0;
		slut  = 0x800;
		for (; start < slut; start += 0x20) {
			mtpr(start, PR_VMAR);
			mtpr(0, PR_VTAG);
		}
		mtpr(ICSR_ENABLE, PR_ICSR);
	}
}

/*
 * Why may we get memory errors during startup???
 */

void
ka680_hardmem(void *arg)
{
	if (cold == 0)
		printf("Hard memory error\n");
	splhigh();
}

void
ka680_softmem(void *arg)
{
	if (cold == 0)
		printf("Soft memory error\n");
	splhigh();
}

void
ka680_init()
{
	/*
	 * Get the soft and hard memory error vectors now.
	 */
	scb_vecalloc(0x54, ka680_softmem, NULL, 0, NULL);
	scb_vecalloc(0x60, ka680_hardmem, NULL, 0, NULL);

	/* Turn on caches (to speed up execution a bit) */
	ka680_cache_enable();
}

void
ka680_memerr()
{
	printf("Memory err!\n");
}

int
ka680_mchk(caddr_t addr)
{
	panic("Machine check");
	return 0;
}


code:
/*	$OpenBSD: led.c,v 1.6 2008/08/20 18:50:17 miod Exp $	*/
/*	$NetBSD: leds.c,v 1.4 2005/12/11 12:19:37 christos Exp $	*/

/*
 * Copyright (c) 1998 Jason L. Wright (jason@thought.net)
 * 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.
 */
/*-
 * Copyright (c) 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Gordon W. Ross and der Mouse.
 *
 * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

/*
 * Functions to flash the LEDs with some pattern.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/conf.h>
#include <sys/timeout.h>

#include <machine/cpu.h>
#include <machine/nexus.h>
#include <machine/sid.h>

#if VAX60
#include <arch/vax/mbus/mbusreg.h>
#include <arch/vax/mbus/mbusvar.h>
#endif

struct led_softc {
	struct device	sc_dev;
	struct timeout	sc_tmo;
	volatile u_short *sc_reg;
	const u_int8_t	*sc_pat, *sc_patpos;
};

/*
 * Patterns for 8 and 4 led displays.
 */
static const u_int8_t led_pattern8[] = {
	0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f,
	0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x00
};
static const u_int8_t led_pattern4[] = {
	0x0e, 0x0d, 0x0b, 0x07, 0x0b, 0x0d, 0x00
};

int	ledmatch(struct device *, void *, void *);
void	ledattach(struct device *, struct device *, void *);
void	led_blink(void *);

struct cfattach led_ca = {
	sizeof(struct led_softc), ledmatch, ledattach
};

struct cfdriver led_cd = {
	NULL, "led", DV_DULL
};

int
ledmatch(struct device *parent, void *cf, void *aux)
{
	struct mainbus_attach_args *maa = aux;

	if (maa->maa_bustype != VAX_LEDS)
		return (0);

	switch (vax_boardtype) {
#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60 || VXT
#if VAX46
	case VAX_BTYP_46:
#endif
#if VAX48
	case VAX_BTYP_48:
#endif
#if VAX49
	case VAX_BTYP_49:
#endif
#if VAX53
	case VAX_BTYP_1303:
#endif
#if VAX60
	case VAX_BTYP_60:
#endif
#if VXT
	case VAX_BTYP_VXT:
#endif
		return (1);
#endif
	default:
		return (0);
	}
}

void
ledattach(struct device *parent, struct device *self, void *aux)
{
	struct led_softc *sc = (void *)self;
#if VAX49 || VAX53 || VXT
	vaddr_t pgva;
#endif

	printf("\n");

	switch (vax_boardtype) {
#if VAX46
	case VAX_BTYP_46:
	{
		extern struct vs_cpu *ka46_cpu;
		sc->sc_reg = (volatile u_short *)(&ka46_cpu->vc_diagdsp);
		sc->sc_pat = led_pattern8;
	}
		break;
#endif
#if VAX48
	case VAX_BTYP_48:
	{
		extern struct vs_cpu *ka48_cpu;
		sc->sc_reg = (volatile u_short *)(&ka48_cpu->vc_diagdsp);
		sc->sc_pat = led_pattern8;
	}
		break;
#endif
#if VAX49
	case VAX_BTYP_49:
		pgva = vax_map_physmem(0x25800000, 1);
		sc->sc_reg = (volatile u_short *)(pgva + 4);
		sc->sc_pat = led_pattern8;
		break;
#endif
#if VAX53
	case VAX_BTYP_1303:
		pgva = vax_map_physmem(0x20140000, 1);
		sc->sc_reg = (volatile u_short *)(pgva + 0x30);
		sc->sc_pat = led_pattern4;
		break;
#endif
#if VAX60
	case VAX_BTYP_60:
		pgva = vax_map_physmem(MBUS_SLOT_BASE(mbus_ioslot) + FBIC_BASE,
		    1);
		sc->sc_reg = (volatile u_short *)(pgva + FBIC_CSR);
		sc->sc_pat = NULL;
		break;
#endif
#if VXT
	case VAX_BTYP_VXT:
		pgva = vax_map_physmem(0x200c1000, 1);
		sc->sc_reg = (volatile u_short *)pgva;
		sc->sc_pat = led_pattern8;
		break;
#endif
	}

	sc->sc_patpos = sc->sc_pat;
	timeout_set(&sc->sc_tmo, led_blink, sc);
	led_blink(sc);
}

void
led_blink(void *v)
{
	struct led_softc *sc = v;
	extern int vax_led_blink;

	if (sc == NULL) {
		/* find our softc if we come from cpu_sysctl */
		if (led_cd.cd_ndevs != 0)
			sc = (struct led_softc *)led_cd.cd_devs[0];
		if (sc == NULL)
			return;
	}

	if (sc->sc_pat != NULL) {
		if (vax_led_blink == 0) {
			*sc->sc_reg = 0xff;
			return;
		}

		*sc->sc_reg = *sc->sc_patpos++;
		if (*sc->sc_patpos == 0)
			sc->sc_patpos = sc->sc_pat;
	} else {
#if VAX60
		uint32_t fbicsr, dot, digit;

		fbicsr= *(volatile uint32_t *)sc->sc_reg;
		dot = ((fbicsr & FBICSR_LEDS_MASK) >> FBICSR_LEDS_SHIFT) & 0x10;
		fbicsr &= ~FBICSR_LEDS_MASK;

		if (vax_led_blink == 0) {
			fbicsr |= 0x1f << FBICSR_LEDS_SHIFT;
			*(volatile uint32_t *)sc->sc_reg = fbicsr;
			return;
		}

		/* this is supposed to flip the decimal dot... doesn't work */
		fbicsr |= (dot ^ 0x10) << FBICSR_LEDS_SHIFT;
		/* display the load average in the hex digit */
		digit = averunnable.ldavg[0] >> FSHIFT;
		if (digit > 0x0f)
			digit = 0x0f;
		fbicsr |= (0x0f ^ digit) << FBICSR_LEDS_SHIFT;

		*(volatile uint32_t *)sc->sc_reg = fbicsr;
#endif
	}

	timeout_add(&sc->sc_tmo,
	    (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 3)));
}


code:
/*	$OpenBSD: locore.S,v 1.9 2015/02/01 10:50:01 miod Exp $   */
/*	$NetBSD: intvec.s,v 1.39 1999/06/28 08:20:48 itojun Exp $   */

/*
 * Copyright (c) 1994, 1997 Ludd, University of Lule}, Sweden.
 * 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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *     This product includes software developed at Ludd, University of Lule}.
 * 4. 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.
 */

#include "assym.h"

#include <machine/asm.h>

#define	JSBENTRY(x) \
	.text; \
	_ALIGN_TEXT; \
	.globl x; \
	.type x,@function; \
x:

#define SCBENTRY(x)	JSBENTRY(__CONCAT(X,x))

#define TRAPCALL(namn, typ) \
SCBENTRY(namn)			; \
	pushl $0		; \
	pushl $typ		; \
	jbr trap

#define TRAPARGC(namn, typ) \
SCBENTRY(namn)			; \
	pushl $typ		; \
	jbr trap

#define FASTINTR(namn, rutin) \
SCBENTRY(namn)			; \
	pushr $0x3f		; \
	calls $0,_C_LABEL(rutin); \
	popr $0x3f		; \
	rei

#define	PUSHR	pushr	$0x3f
#define	POPR	popr	$0x3f

#define KSTACK 0
#define ISTACK 1
#define	NOVEC	.long 0
#define INTVEC(label,stack)	\
	.long	__CONCAT(X,label) + stack;

	.text

	.globl	_C_LABEL(kernbase), _C_LABEL(rpb), _C_LABEL(kernel_text)
	.set	_C_LABEL(kernel_text),KERNBASE
_C_LABEL(kernbase):
_C_LABEL(rpb):
/*
 * First page in memory we have rpb; so that we know where
 * (must be on a 64k page boundary, easiest here). We use it
 * to store SCB vectors generated when compiling the kernel,
 * and move the SCB later to somewhere else.
 */

	NOVEC;				# Unused, 0
	INTVEC(mcheck, ISTACK)		# Machine Check., 4
	INTVEC(invkstk, ISTACK) 	# Kernel Stack Invalid., 8
	NOVEC;			 	# Power Failed., C
	INTVEC(privinflt, KSTACK)	# Privileged/Reserved Instruction.
	INTVEC(xfcflt, KSTACK)		# Customer Reserved Instruction, 14
	INTVEC(resopflt, KSTACK)	# Reserved Operand/Boot Vector(?), 18
	INTVEC(resadflt, KSTACK)	# Reserved Address Mode., 1C
	INTVEC(access_v, KSTACK)	# Access Control Violation, 20
	INTVEC(transl_v, KSTACK)	# Translation Invalid, 24
	INTVEC(tracep, KSTACK)		# Trace Pending, 28
	INTVEC(breakp, KSTACK)		# Breakpoint Instruction, 2C
	NOVEC;			 	# Compatibility Exception, 30
	INTVEC(arithflt, KSTACK)	# Arithmetic Fault, 34
	NOVEC;			 	# Unused, 38
	NOVEC;			 	# Unused, 3C
	INTVEC(syscall, KSTACK)		# main syscall trap, chmk, 40
	INTVEC(resopflt, KSTACK)	# chme, 44
	INTVEC(resopflt, KSTACK)	# chms, 48
	INTVEC(resopflt, KSTACK)	# chmu, 4C
	NOVEC;				# System Backplane Exception/BIerror, 50
	INTVEC(cmrerr, ISTACK)		# Corrected Memory Read, 54
	NOVEC;				# System Backplane Alert/RXCD, 58
	INTVEC(sbiflt, ISTACK)		# System Backplane Fault, 5C
	NOVEC;				# Memory Write Timeout, 60
	NOVEC;				# Unused, 64
	NOVEC;				# Unused, 68
	NOVEC;				# Unused, 6C
	NOVEC;				# Unused, 70
	NOVEC;				# Unused, 74
	NOVEC;				# Unused, 78
	NOVEC;				# Unused, 7C
	NOVEC;				# Unused, 80
	NOVEC;				# Unused, 84
	INTVEC(astintr,	KSTACK)		# Asynchronous System Trap, AST
	NOVEC;				# Unused, 8C
	NOVEC;				# Unused, 90
	NOVEC;				# Unused, 94
	NOVEC;				# Unused, 98
	NOVEC;				# Unused, 9C
	INTVEC(softintr,ISTACK)		# Software interrupts (IPL_SOFT)
	INTVEC(softintr,ISTACK)		# Software interrupts (IPL_SOFTCLOCK)
	INTVEC(softintr,ISTACK)		# Software interrupts (IPL_SOFTNET)
	INTVEC(softintr,ISTACK)		# Software interrupts (IPL_SOFTTTY)
	NOVEC;				# Unused, B0
	NOVEC;				# Unused, B4
	NOVEC;				# Unused, B8
	INTVEC(ddbtrap, ISTACK) 	# Kernel debugger trap, BC
	INTVEC(hardclock,ISTACK)	# Interval Timer
	NOVEC;				# Unused, C4
	INTVEC(emulate, KSTACK)		# Subset instruction emulation, C8
	NOVEC;				# Unused, CC
	NOVEC;				# Unused, D0
	NOVEC;				# Unused, D4
	NOVEC;				# Unused, D8
	NOVEC;				# Unused, DC
	NOVEC;				# Unused, E0
	NOVEC;				# Unused, E4
	NOVEC;				# Unused, E8
	NOVEC;				# Unused, EC
	NOVEC;
	NOVEC;
	NOVEC;
	NOVEC;

	/* space for adapter vectors */
	.space 0x100

	.align 2
#
# mcheck is the badaddress trap, also called when referencing
# a invalid address (busserror)
# memtest holds the address to continue execution at when returning
# from a intentional test.
#
SCBENTRY(mcheck)
	tstl	_ASM_LABEL(memtest)	# Are we expecting a machine check?
	bneq	L4		# Yes.

	pushr	$0x7f
	pushab	28(%sp)
	movl	_C_LABEL(dep_call),%r6	# CPU dependent mchk handling
	calls	$1,*MCHK(%r6)
	tstl	%r0		# If not machine check, try memory error
	beql	1f
	calls	$0,*MEMERR(%r6)
	pushab	2f
	calls	$1,_C_LABEL(panic)
2:	.asciz	"mchk"
1:	popr	$0x7f
	addl2	(%sp)+,%sp

	rei

L4:	addl2	(%sp)+,%sp	# remove info pushed on stack
	# Clear the machine check condition by writing to the
	# MCESR register if available.
	cmpl	$VAX_TYP_UV2, _C_LABEL(vax_cputype)
	beql	2f
	cmpl	$VAX_TYP_SOC, _C_LABEL(vax_cputype)
	beql	2f
  	mtpr	$0,$PR_MCESR	# clear the bus error bit
2:	movl	_ASM_LABEL(memtest),(%sp)	# REI to new address
	rei

TRAPCALL(invkstk, T_KSPNOTVAL)

SCBENTRY(privinflt)	# Privileged/unimplemented instruction
#ifdef INSN_EMULATE
	jsb	unimemu	# do not return if insn emulated
#endif
	pushl $0
	pushl $T_PRIVINFLT
	jbr trap

TRAPCALL(xfcflt, T_XFCFLT);
TRAPCALL(resopflt, T_RESOPFLT)
TRAPCALL(resadflt, T_RESADFLT)

/*
 * Translation fault, used only when simulating page reference bit.
 * Therefore it is done a fast revalidation of the page if it is
 * referenced. Trouble here is the hardware bug on KA650 CPUs that
 * put in a need for an extra check when the fault is gotten during
 * PTE reference. Handled in pmap.c.
 */
SCBENTRY(transl_v)		# 20: Translation violation
	PUSHR
	pushl	28(%sp)
	pushl	28(%sp)
	calls	$2,_C_LABEL(pmap_simulref)
	tstl	%r0
	bneq	1f
	POPR
	addl2	$8,%sp
	rei
1:	POPR
	brb	access_v

SCBENTRY(access_v)		# 24: Access cntrl viol fault
access_v:
	blbs	(%sp), ptelen
	pushl	$T_ACCFLT
	bbc	$1,4(%sp),1f
	bisl2	$T_PTEFETCH,(%sp)
1:	bbc	$2,4(%sp),2f
	bisl2	$T_WRITE,(%sp)
2:	movl	(%sp), 4(%sp)
	addl2	$4, %sp
	jbr	trap

ptelen: movl	$T_PTELEN, (%sp)	# PTE must expand (or send segv)
	jbr	trap

TRAPCALL(tracep, T_TRCTRAP)
TRAPCALL(breakp, T_BPTFLT)

TRAPARGC(arithflt, T_ARITHFLT)

SCBENTRY(syscall)			# Main system call
	pushl	$T_SYSCALL
	pushr	$0xfff
	mfpr	$PR_USP, -(%sp)
	pushl	%ap
	pushl	%fp
	pushl	%sp		# pointer to syscall frame; defined in trap.h
	calls	$1, _C_LABEL(syscall)
	movl	(%sp)+, %fp
	movl	(%sp)+, %ap
	mtpr	(%sp)+, $PR_USP
	popr	$0xfff
	addl2	$8, %sp
	mtpr	$0x1f, $PR_IPL	# Be sure we can REI
	rei

SCBENTRY(cmrerr)
	PUSHR
	movl	_C_LABEL(dep_call),%r0
	calls	$0,*MEMERR(%r0)
	POPR
	rei

SCBENTRY(sbiflt)
	pushab	sbifltmsg
	calls	$1,_C_LABEL(panic)

TRAPCALL(astintr, T_ASTFLT)

FASTINTR(softintr,softintr_dispatch)

TRAPCALL(ddbtrap, T_KDBTRAP)

SCBENTRY(hardclock)
	mtpr	$0xc1,$PR_ICCS		# Reset interrupt flag
	PUSHR
	pushl	%sp
	addl2	$24,(%sp)
	movl	_C_LABEL(dep_call),%r0
	calls	$1,*HARDCLOCK(%r0)
	incl	_C_LABEL(clock_intrcnt)+EC_COUNT	# increment low longword
	adwc	$0,_C_LABEL(clock_intrcnt)+EC_COUNT+4	# add any carry to hi
							# longword
	POPR
	rei

/*
 * Main routine for traps; all go through this.
 * Note that we put USP on the frame here, which sometimes should
 * be KSP to be correct, but because we only alters it when we are
 * called from user space it doesn't care.
 * _sret is used in cpu_set_kpc to jump out to user space first time.
 */
trap:	pushr	$0xfff
	mfpr	$PR_USP, -(%sp)
	pushl	%ap
	pushl	%fp
	pushl	%sp
	calls	$1, _C_LABEL(arithflt)
	.globl	_C_LABEL(sret)
_C_LABEL(sret):
	movl	(%sp)+, %fp
	movl	(%sp)+, %ap
	mtpr	(%sp)+, $PR_USP
	popr	$0xfff
	addl2	$8, %sp
	mtpr	$0x1f, $PR_IPL	# Be sure we can REI
	rei

sbifltmsg:
	.asciz	"SBI fault"

#if INSN_EMULATE
/*
 * Table of emulated Microvax instructions supported by emulate.s.
 * Use noemulate to convert unimplemented ones to reserved instruction faults.
 */
	.globl	_C_LABEL(emtable)
_C_LABEL(emtable):
/* f8 */ .long _C_LABEL(EMashp);	.long _C_LABEL(EMcvtlp)
	 .long noemulate;		.long noemulate
/* fc */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 00 */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 04 */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 08 */ .long _C_LABEL(EMcvtps);	.long _C_LABEL(EMcvtsp)
	 .long noemulate;		.long _C_LABEL(EMcrc)
/* 0c */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 10 */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 14 */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 18 */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 1c */ .long noemulate;		.long noemulate
	 .long noemulate;		.long noemulate
/* 20 */ .long _C_LABEL(EMaddp4);	.long _C_LABEL(EMaddp6)
	 .long _C_LABEL(EMsubp4);	.long _C_LABEL(EMsubp6)
/* 24 */ .long _C_LABEL(EMcvtpt);	.long _C_LABEL(EMmulp)
	 .long _C_LABEL(EMcvttp);	.long _C_LABEL(EMdivp)
/* 28 */ .long noemulate;		.long _C_LABEL(EMcmpc3)
	 .long _C_LABEL(EMscanc);	.long _C_LABEL(EMspanc)
/* 2c */ .long noemulate;		.long _C_LABEL(EMcmpc5)
	 .long _C_LABEL(EMmovtc);	.long _C_LABEL(EMmovtuc)
/* 30 */ .long noemulate;		.long noemulate;
	 .long noemulate;		.long noemulate
/* 34 */ .long _C_LABEL(EMmovp);	.long _C_LABEL(EMcmpp3)
	 .long _C_LABEL(EMcvtpl);	.long _C_LABEL(EMcmpp4)
/* 38 */ .long _C_LABEL(EMeditpc);	.long _C_LABEL(EMmatchc);
	 .long _C_LABEL(EMlocc);	.long _C_LABEL(EMskpc)
#endif
/*
 * The following is called with the stack set up as follows:
 *
 *	  (sp): Opcode
 *	 4(sp): Instruction PC
 *	 8(sp): Operand 1
 *	12(sp): Operand 2
 *	16(sp): Operand 3
 *	20(sp): Operand 4
 *	24(sp): Operand 5
 *	28(sp): Operand 6
 *	32(sp): Operand 7 (unused)
 *	36(sp): Operand 8 (unused)
 *	40(sp): Return PC
 *	44(sp): Return PSL
 *	48(sp): TOS before instruction
 *
 * Each individual routine is called with the stack set up as follows:
 *
 *	  (sp): Return address of trap handler
 *	 4(sp): Opcode (will get return PSL)
 *	 8(sp): Instruction PC
 *	12(sp): Operand 1
 *	16(sp): Operand 2
 *	20(sp): Operand 3
 *	24(sp): Operand 4
 *	28(sp): Operand 5
 *	32(sp): Operand 6
 *	36(sp): saved register 11
 *	40(sp): saved register 10
 *	44(sp): Return PC
 *	48(sp): Return PSL
 *	52(sp): TOS before instruction
 *	See the VAX Architecture Reference Manual, Section B-5 for more
 *	information.
 */

SCBENTRY(emulate)
#if INSN_EMULATE
	movl	%r11,32(%sp)		# save register r11 in unused operand
	movl	%r10,36(%sp)		# save register r10 in unused operand
	cvtbl	(%sp),%r10		# get opcode
	addl2	$8,%r10			# shift negative opcodes
	subl3	%r10,$0x43,%r11		# forget it if opcode is out of range
	bcs	noemulate
	movl	_C_LABEL(emtable)[%r10],%r10 # call appropriate emulation routine
	jsb	(%r10)		# routines put return values into regs 0-5
	movl	32(%sp),%r11		# restore register r11
	movl	36(%sp),%r10		# restore register r10
	insv	(%sp),$0,$4,44(%sp)	# and condition codes in Opcode spot
	addl2	$40,%sp			# adjust stack for return
	rei
noemulate:
	addl2	$48,%sp			# adjust stack for
#endif
	.word	0xffff			# "reserved instruction fault"

	.text

/*
 * First entry routine from boot. This should be in a file called locore.
 */
ASENTRY_NOPROFILE(__start, 0)
	bisl3	$0x80000000,%r9,_C_LABEL(esym)	# End of loaded code
	pushl	$0x1f0000			# Push a nice PSL
	pushl	$to				# Address to jump to
	rei					# change to kernel stack
to:	movw	$0xfff,_C_LABEL(panic)		# Save all regs in panic
	moval	_C_LABEL(end), %r0		# Get kernel end address
	addl2	$0x3ff, %r0			# Round it up
	cmpl	_C_LABEL(esym), %r0		# Compare with symbol table end
	bleq	eskip				# Symbol table not present
	addl3	_C_LABEL(esym), $0x3ff, %r0	# Use symbol end and round
eskip:
	bicl3	$0x3ff,%r0,%r1
	movl	%r1,_C_LABEL(proc0paddr)	# save proc0 uarea pointer
	bicl3	$0x80000000,%r1,%r0		# get phys proc0 uarea addr
#if 0
	movl	%r0,PCB_PADDR(%r1)		# save PCB physical address
#endif
	mtpr	%r0,$PR_PCBB			# Save in IPR PCBB
	addl3	$USPACE,%r1,%r0			# Get kernel stack top
	mtpr	%r0,$PR_KSP			# put in IPR KSP
	movl	%r0,_C_LABEL(Sysmap)		# SPT start addr after KSP

# Set some registers in known state
	movl	%r1,%r0
	clrl	P0LR(%r0)
	clrl	P1LR(%r0)
	mtpr	$0,$PR_P0LR
	mtpr	$0,$PR_P1LR
	movl	$0x80000000,%r1
	movl	%r1,P0BR(%r0)
	movl	%r1,P1BR(%r0)
	mtpr	%r1,$PR_P0BR
	mtpr	%r1,$PR_P1BR
	clrl	IFTRAP(%r0)
	mtpr	$0,$PR_SCBB

# Copy the RPB to its new position
#if 1 /* compat with old bootblocks */
	tstl	(%ap)				# Any arguments?
	bneq	1f				# Yes, called from new boot
	movl	%r11,_C_LABEL(boothowto)	# Howto boot (single etc...)
#	movl	%r10,_C_LABEL(bootdev)		# uninteresting, will complain
	movl	%r8,_C_LABEL(avail_end)		# Usable memory (from VMB)
	clrl	-(%sp)				# Have no RPB
	brb	2f
#endif

1:	pushl	4(%ap)				# Address of old rpb
2:	calls	$1,_C_LABEL(_start)		# Jump away.
	/* NOTREACHED */

/*
 * Signal handler code.
 */

	.globl	_C_LABEL(sigcode),_C_LABEL(esigcode)
_C_LABEL(sigcode):
	movl	0x0c(%sp),%r0	/* get signal handler */
	calls	$3,(%r0)	/* and call it */
	chmk	$SYS_sigreturn	/* sigreturn frame set up by sendsig */
	chmk	$SYS_exit
	halt
	_ALIGN_TEXT
_C_LABEL(esigcode):

	.globl	_C_LABEL(idsptch), _C_LABEL(eidsptch)
_C_LABEL(idsptch):
	pushr	$0x3f
	.word	0x9f16		# jsb to absolute address
	.long	_cmn_idsptch	# the absolute address
	.long	0		# the callback interrupt routine
	.long	0		# its argument
	.long	0		# ptr to correspond evcount struct
_C_LABEL(eidsptch):

_cmn_idsptch:
	movl	(%sp)+,%r0	# get pointer to idspvec
	movl	8(%r0),%r1	# get evcount pointer
	beql	1f		# no ptr, skip increment
	incl	EC_COUNT(%r1)	# increment low longword
	adwc	$0,EC_COUNT+4(%r1) # add any carry to hi longword
1:	pushl	4(%r0)		# push argument
	calls	$1,*(%r0)	# call interrupt routine
	popr	$0x3f		# pop registers
	rei			# return from interrut

ENTRY_NOPROFILE(badaddr,R2|R3)		# Called with addr,b/w/l
	mfpr	$0x12,%r0	# splhigh()
	mtpr	$0x1f,$0x12
	movl	4(%ap),%r2	# First argument, the address
	movl	8(%ap),%r1	# Sec arg, b,w,l
	pushl	%r0		# Save old IPL
	clrl	%r3
	movab	4f,_ASM_LABEL(memtest)	# Set the return address

	caseb	%r1,$1,$4	# What is the size
1:	.word	1f-1b
	.word	2f-1b
	.word	3f-1b		# This is unused
	.word	3f-1b

1:	movb	(%r2),%r1	# Test a byte
	brb	5f

2:	movw	(%r2),%r1	# Test a word
	brb	5f

3:	movl	(%r2),%r1	# Test a long
	brb	5f

4:	incl	%r3		# Got machine chk => addr bad
5:	clrl	_ASM_LABEL(memtest)	# do not ignore further mchk
	mtpr	(%sp)+,$0x12
	movl	%r3,%r0
	ret

#ifdef DDB
/*
 * DDB is the only routine that uses setjmp/longjmp.
 */
ENTRY_NOPROFILE(setjmp, 0)
	movl	4(%ap), %r0
	movl	8(%fp), (%r0)
	movl	12(%fp), 4(%r0)
	movl	16(%fp), 8(%r0)
	addl3	%fp,$28,12(%r0)
	clrl	%r0
	ret

ENTRY_NOPROFILE(longjmp, 0)
	movl	4(%ap), %r1
	movl	$1, %r0
	movl	(%r1), %ap
	movl	4(%r1), %fp
	movl	12(%r1), %sp
	jmp	*8(%r1)
#endif

#
# void
# cpu_switchto(struct proc *oldproc = r0, struct proc *newproc = r1);
#

#define CURPROC _C_LABEL(cpu_info_store) + CI_CURPROC

JSBENTRY(__cpu_switchto)
	svpctx

	movb	$SONPROC,P_STAT(%r1)	# p->p_stat = SONPROC
	movl	%r1, CURPROC		# set new process running

	movl	P_ADDR(%r1),%r0		# Get pointer to new pcb.
	addl3	%r0,$IFTRAP,pcbtrap	# Save for copy* functions.

#
# Do the actual process switch. pc + psl are already on stack, from
# the beginning of this routine.
#
	mtpr	PCB_PADDR(%r0),$PR_PCBB

	pushl	CURPROC
	calls	$1, _C_LABEL(pmap_activate)

	ldpctx
	rei

#
# copy/fetch/store routines.
#
	.align 2
ENTRY_NOPROFILE(copyin, R2|R3|R4|R5|R6)
	movl	4(%ap), %r0
	blss	3f		# kernel space
	movl	8(%ap), %r1
	brb	2f

ENTRY_NOPROFILE(copyout, R2|R3|R4|R5|R6)
	movl	8(%ap), %r1
	blss	3f		# kernel space
	movl	4(%ap), %r0
2:	movab	1f,*pcbtrap
	movzwl	12(%ap), %r2
	movzwl	14(%ap), %r6

	movc3	%r2, (%r0), (%r1)

	tstl	%r6
	bleq	1f
0:	movb	(%r1)+, (%r3)+
	movc3	$0xffff, (%r1), (%r3)
	sobgtr	%r6,0b

1:	clrl	*pcbtrap
	ret

3:	movl	$EFAULT, %r0
	ret

/* kcopy:  just like bcopy, except return EFAULT upon failure */
ENTRY_NOPROFILE(kcopy,R2|R3|R4|R5|R6)
	movl	*pcbtrap,-(%sp)
	movab	1f,*pcbtrap
	movl	4(%ap), %r0
	movl	8(%ap), %r1
	movzwl	12(%ap), %r2
	movzwl	14(%ap), %r6

	movc3	%r2, (%r0), (%r1)

	tstl	%r6
	bleq	1f
0:	movb	(%r1)+, (%r3)+
	movc3	$0xffff, (%r1), (%r3)
	sobgtr	%r6, 0b

	/*
	 * If there is a failure, trap.c will set r0 to EFAULT, and jump
	 * to the following 1.  If not, we return 0 (movc3 sets r0 to 0).
	 */
1:
	movl	(%sp)+,*pcbtrap
	ret

ENTRY_NOPROFILE(copyinstr,0)
	tstl	4(%ap)		# is from a kernel address?
	bgeq	8f		# no, continue

6:	movl	$EFAULT,%r0
	ret

ENTRY_NOPROFILE(copyoutstr,0)
	tstl	8(%ap)		# is to a kernel address?
	bgeq	8f		# no, continue
	brb	6b

ENTRY_NOPROFILE(copystr,0)
8:	movl	4(%ap),%r4	# from
	movl	8(%ap),%r5	# to
	movl	16(%ap),%r3	# copied
	movl	12(%ap),%r2	# len

	bneq	1f		# nothing to copy?
	movl	$ENAMETOOLONG,%r0
	tstl	%r3
	beql	0f
	movl	$0,(%r3)
0:	ret

1:	movab	2f,*pcbtrap

/*
 * This routine consists of two parts: One is for MV2 that doesn't have
 * locc in hardware, the other is a fast version with locc. But because
 * locc only handles <64k strings, we default to the slow version if the
 * string is longer.
 */
	cmpl	_C_LABEL(vax_cputype),$VAX_TYP_UV2
	bneq	4f		# Check if locc emulated

9:	movl	%r2,%r0
7:	movb	(%r4)+,(%r5)+
	beql	6f		# end of string
	sobgtr	%r0,7b		# no null byte in the len first bytes?
	brb 1f

6:	tstl	%r3
	beql	5f
	incl	%r2
	subl3	%r0,%r2,(%r3)
5:	clrl	%r0
	clrl	*pcbtrap
	ret

4:	cmpl	%r2,$65535	# maxlen < 64k?
	blss	8f		# then use fast code.

	locc	$0,$65535,(%r4)	# is strlen < 64k?
	beql	9b		# No, use slow code
	subl3	%r0,$65535,%r1	# Get string len
	brb	0f		# do the copy

8:	locc	$0,%r2,(%r4)	# check for null byte
	beql	1f

	subl3	%r0,%r2,%r1	# Calculate len to copy
0:	incl	%r1		# Copy null byte also
	tstl	%r3
	beql	3f
	movl	%r1,(%r3)	# save len copied
3:	movc3	%r1,(%r4),(%r5)
	brb	4f

1:	movl	$ENAMETOOLONG,%r0
2:	movab	4f,*pcbtrap	# if we fault again, don't resume there
	subl3	8(%ap),%r5,%r1	# did we write to the string?
	beql	3f
	decl	%r5
3:	movb	$0,(%r5)	# null terminate the output string
	tstl	%r3
	beql	4f
	incl	%r1		# null byte accounts for outlen...
	movl	%r1,(%r3)	# save len copied
4:	clrl	*pcbtrap
	ret

#
# data department
#
	.data

_ASM_LABEL(memtest):			# badaddr() in progress
	.long 0
pcbtrap:
	.long 0x800001fc		# Safe place

	.globl _C_LABEL(bootdev)
_C_LABEL(bootdev):
	.long 0