V10/sys/md/mcrnaut.c

/*
 * memory controller support for nautilus
 *
 * an interpretation of the VMS code
 */

#include "sys/param.h"
#include "sys/systm.h"

extern long *mcrcsr;	/* virt addr of mem csrs; filled in when spt built */

/*
 * mem csrs have no names, just numbers 0-7
 * 0-3 have control and status bits
 * 4-7 are just magic places to read:
 *	csr4 clears memory interrupt
 *	csr5 clears memory (and nmi) fault
 */

/*
 * csr0
 */

#define	TOCODE	0x7000000	/* timeout code */
#define	ILTO	0x2000000	/* interlock timeout */

/*
 * csr1
 */

#define	WENABLE	0x100000	/* decode ram write enable -- make sure off */

/*
 * csr2
 */

#define	RDSHER	0x80000000	/* rds thick and fast */
#define	RDS	0x40000000	/* read data substitute (hard error) */
#define	CRD	0x20000000	/* corrected read data (soft error) */
#define	RDFORCE	0x10000000	/* RDS really NMI bus error */

/*
 * csr3
 */

#define	IEINTERR 0x80000000	/* internal error intr enab */
#define	IEILERR	0x40000000	/* interlock error ie */
#define	IECRD	0x20000000	/* soft error ie */
#define	IERDS	0x10000000	/* hard error ie */
#define	INTERR	0x2000000	/* internal error */

#define	IE	(IEINTERR|IEILERR|IECRD|IERDS)

/*
 * init the memory controller:
 * enable interrupts
 */

mcrinit()
{
	register long junk;
	register long *m;

	if ((m = mcrcsr) == 0)
		panic("mcrinit");
	mcrclr();
	m[3] = IE;
}

/*
 * here on memory interrupt
 * guess whether it's an error
 */

mcrint()
{
	register long *m;

	if ((m = mcrcsr) == 0)
		return;
	/* cknofault? */
	mcrerr();
}

/*
 * memory error, because controller interrupted or otherwise
 */
static int crdoff;
int mcrreenb();

mcrerr()
{
	register long *m;
	register long csr0, csr1, csr2, csr3;
	register long xcsr1;		/* eventually toss out */
	register int hard;
	static time_t lastcrd;

	if ((m = mcrcsr) == 0)
		return;		/* hopeless */
	csr0 = m[0];
	xcsr1 = m[1];
	m[1] = xcsr1 & ~WENABLE;
	csr1 = m[1];
	csr2 = m[2];
	csr3 = m[3];
	mcrclr();
	hard = 0;
	if (csr3 & INTERR)
		hard++;
	if ((csr0 & TOCODE) == ILTO)
		hard++;
	if (csr2 & (RDS|RDFORCE))
		hard++;
	printf("mem %s err: %x %x %x %x (%x)\n", hard ? "hard" : "soft",
		csr0, csr1, csr2, csr3, xcsr1);
	if (hard)
		panic("mcrerr");
	if (lastcrd && lastcrd + 5 < time) {
		if (crdoff++ == 0)
			timeout(mcrreenb, (caddr_t)0, 15*HZ);
		m[3] = (IE &~ IECRD);
	}
	else
		lastcrd = time;
}

mcrreenb(x)
caddr_t x;
{
	crdoff = 0;
	mcrcsr[3] = IE;
}

mcrclr()
{
	register long junk;
	register long *m;

	if ((m = mcrcsr) == 0)
		return;
	junk = m[4];
	junk = m[5];
	m[0] = m[0]|TOCODE;
	m[1] = m[1];
	m[2] = m[2];
}