#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ka670.c,v 1.17 2017/05/22 16:46:15 ragge Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <machine/sid.h>
#include <machine/nexus.h>
#include <machine/vsbus.h>
#include <machine/ka670.h>
#include <machine/clock.h>
static void ka670_memerr(void);
static void ka670_conf(void);
static void ka670_attach_cpu(device_t);
static int ka670_mchk(void *);
static int ka670_cache_init(void);
static const char * const ka670_devs[] = { "cpu", "sgec", "shac", "uba", NULL };
const struct cpu_dep ka670_calls = {
.cpu_mchk = ka670_mchk,
.cpu_memerr = ka670_memerr,
.cpu_conf = ka670_conf,
.cpu_gettime = generic_gettime,
.cpu_settime = generic_settime,
.cpu_vups = 8,
.cpu_scbsz = 2,
.cpu_halt = generic_halt,
.cpu_reboot = generic_reboot,
.cpu_devs = ka670_devs,
.cpu_attach_cpu = ka670_attach_cpu,
};
#define KA670_MC_RESTART 0x00008000
#define KA670_PSL_FPDONE 0x00010000
struct ka670_mcframe {
int mc670_bcnt;
int mc670_code;
int mc670_addr;
int mc670_viba;
int mc670_sisr;
int mc670_istate;
int mc670_sc;
int mc670_pc;
int mc670_psl;
};
#if 0
static const char * const ka670_mctype[] = {
"no error (0)",
"FPA: protocol error",
"FPA: illegal opcode",
"FPA: operand parity error",
"FPA: unknown status",
"FPA: result parity error",
"unused (6)",
"unused (7)",
"MMU error (TLB miss)",
"MMU error (TLB hit)",
"HW interrupt at unused IPL",
"MOVCx impossible state",
"undefined trap code (i-box)",
"undefined control store address",
"unused (14)",
"unused (15)",
"PC tag or data parity error",
"data bus parity error",
"data bus error (NXM)",
"undefined data bus state",
};
#define MC670_MAX 19
#endif
static int ka670_error_count = 0;
int
ka670_mchk(void *addr)
{
struct ka670_mcframe * const mcf = addr;
mtpr(0x00, PR_MCESR);
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 (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();
return (0);
}
printf("ka670_mchk: unknown error state!\n");
return (-1);
}
void
ka670_memerr(void)
{
char sbuf[256];
printf("memory error!\n");
snprintb(sbuf, sizeof(sbuf), KA670_PCSTS_BITS, mfpr(PR_PCSTS));
printf("primary cache status: %s\n", sbuf);
snprintb(sbuf, sizeof(sbuf), KA670_BCSTS_BITS, mfpr(PR_BCSTS));
printf("secondary cache status: %s\n", sbuf);
}
int
ka670_cache_init(void)
{
int val;
#ifdef DEBUG
char sbuf[256];
#endif
mtpr(KA670_PCS_REFRESH, PR_PCSTS);
val = mfpr(PR_PCSTS);
mtpr(val, PR_PCSTS);
mtpr(8, PR_BCCTL);
mtpr(0, PR_BCFBTS);
mtpr(0, PR_BCFPTS);
mtpr(0x0e, PR_BCCTL);
mtpr(KA670_PCS_FLUSH | KA670_PCS_REFRESH, PR_PCSTS);
mtpr(KA670_PCS_ENABLE | KA670_PCS_REFRESH, PR_PCSTS);
#ifdef DEBUG
snprintb(sbuf, sizeof(sbuf), KA670_PCSTS_BITS, mfpr(PR_PCSTS));
printf("primary cache status: %s\n", sbuf);
snprintb(sbuf, sizeof(sbuf), KA670_BCSTS_BITS, mfpr(PR_BCSTS));
printf("secondary cache status: %s\n", sbuf);
#endif
return (0);
}
void
ka670_conf(void)
{
ka670_cache_init();
cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1);
}
void
ka670_attach_cpu(device_t self)
{
aprint_normal(
": %s, Rigel (ucode rev %d), 2KB L1 cache, 128KB L2 cache\n",
"KA670",
vax_cpudata % 0377);
}