V8/usr/sys/dev/kmc.c

Compare this file to the similar file:
Show the results in this format:

/*
 * KMC11 microprocessor driver
 */
#include "kmc.h"
#if NKMC > 0
/* this driver supports ONE kmc ONLY */
/* it should be modified to support only kmc11b's too */

/* nonstandard crap */
typedef unsigned short ushort;
#define lobyte(X) (((unsigned char *)&X)[0])
#define hibyte(X) (((unsigned char *)&X)[1])

#include "../h/param.h"
#include "../h/systm.h"
#include "../h/kmc.h"
#include "../h/pte.h"
#include "../h/map.h"
#include "../h/buf.h"
#include "../h/ubareg.h"
#include "../h/ubavar.h"
#include "../h/conf.h"
#include "../h/dir.h"
#include "../h/user.h"

struct kmc {
	char	k_stat;
	char	k_type;
} kmc[NKMC];

#define	KMC11A	1
#define	KMC11B	2
#define	KASIZE	1024
#define	KBSIZE	4096

#define	RUN	(1<<7)
#define	MCLR	(1<<6)
#define	CWRT	(1<<5)
#define	LUB	(1<<4)
#define	LUA	(1<<3)
#define	ROMO	(1<<2)
#define	ROMI	(1<<1)
#define	STEP	(1<<0)

#define RDYO	0200
#define RDYI	020
#define RQI	0200
#define IEI	01
#define IEO	020

#define	STYPE	017
#define SRUN	020
#define SRINT	040
#define	SOPEN	0100

struct device {
	union {
		char	b[8];
		ushort	w[4];
	} un;
};

#define	bsel0	un.b[0]
#define	bsel1	un.b[1]
#define	bsel2	un.b[2]
#define	bsel3	un.b[3]
#define	bsel4	un.b[4]
#define	bsel5	un.b[5]
#define	bsel6	un.b[6]
#define	bsel7	un.b[7]
#define	sel0	un.w[0]
#define	sel2	un.w[1]
#define	sel4	un.w[2]
#define	sel6	un.w[3]

int	kmcwritten;
int kmcprobe(), kmcattach(), kmcxint();
struct uba_device *kmcdinfo[NKMC];
unsigned short kmcstd[] = { 0};
struct uba_driver kmcdriver = {
	kmcprobe, 0, kmcattach, 0, kmcstd, "kmc", kmcdinfo
};

int	(*kdirint)();
int	(*kdixint)();

kmcprobe(reg)
caddr_t reg;
{	register int br, cvec;	/* don't touch */
	register struct device *kp = (struct device *)reg;
	register s;

#ifdef lint
	br = 0; cvec = br; br = cvec;
#endif
	s = spl7();
	kp->bsel1 = MCLR;
	splx(s);
	kp->bsel1 = ROMI;
	kp->sel4 = 0200;		/* bus request */
	kp->sel6 = 0121111;		/* mov csr4,obr */
	kp->bsel1 = ROMI|STEP;
	DELAY(50);
	kp->bsel1 = 0;
	return(1);
}

kmcattach(ui)
register struct uba_device *ui;
{}

kmcopen(dev, flag)
dev_t dev;
{	register struct device *kp;
	register struct kmc *tp;
	register sav;

	dev = minor(dev);
	if (dev>=NKMC || (tp = &kmc[dev])->k_stat&SOPEN) {
		u.u_error = ENXIO;
		return;
	}
	kmcwritten = 0;
	tp->k_stat |= SOPEN;
	if (tp->k_type==0) {
		kp = ((struct device *)kmcdinfo[dev]->ui_addr);
		kp->bsel1 = ROMO;
		kp->sel4 = 0;
		sav = kp->sel6;
		kp->sel6 = ~sav;
		if (kp->sel6 != sav) {
			tp->k_type = KMC11B;
			kp->sel6 = sav;
		} else
			tp->k_type = KMC11A;
		kp->bsel1 = 0;
	}
}

kmcclose(dev)
dev_t dev;
{
	dev = minor(dev);
	if(dev >= NKMC)
		return;
	kmc[dev].k_stat &= ~SOPEN;
	if (kmcwritten)
		kdireload();
}

kmcread(dev)
dev_t dev;
{	register struct device *kp;
	register ad;
	int	dsize;
	ushort	sav;

	dev = minor(dev);
	if(dev >= NKMC) {
		u.u_error = ENXIO;
		return;
	}
	if (kmc[dev].k_stat&SRUN)
		return;
	dsize = (kmc[dev].k_type==KMC11A)?KASIZE:KBSIZE;
	kp = ((struct device *)kmcdinfo[dev]->ui_addr);
	kp->bsel1 = 0;
	do {
		ad = u.u_offset;
		if (ad<dsize*2) {
			if (ad&1) {
				u.u_error = ENXIO;
				break;
			}
			ad >>= 1;
			kp->bsel1 = ROMO;
			kp->sel4 = ad;
			passc(kp->bsel6);
			passc(kp->bsel7);
			kp->bsel1 = 0;
		} else if (ad -= dsize*2, ad<dsize) {
			kp->bsel1 = ROMO;
			kp->sel4 = 0;
			sav = kp->sel6;
			kp->bsel1 = ROMI;
			kp->sel6 = 010000|(ad&0377);	/* mov ad,mar */
			kp->bsel1 = ROMI|STEP;
			kp->bsel1 = ROMI;
			kp->sel6 = 04000|((ad>>8)&0377);	/* mov %ad,%mar */
			kp->bsel1 = ROMI|STEP;
			kp->bsel1 = ROMI;
			kp->sel6 = 055222;	/* mov mem,csr2|mar++ */
			kp->bsel1 = ROMI|STEP;
			passc(kp->bsel2);
			kp->bsel1 = ROMI;
			kp->sel6 = sav;
			kp->bsel1 = 0;
		} else
			break;
	} while (u.u_error==0 && u.u_count);
}

kmcwrite(dev)
dev_t dev;
{	register struct device *kp;
	register ad;
	int	dsize;
	short	ins;
	ushort	sav;

	dev = minor(dev);
	if(dev >= NKMC) {
		u.u_error = ENXIO;
		return;
	}
	if (kmc[dev].k_stat&SRUN)
		return;
	dsize = (kmc[dev].k_type==KMC11A)?KASIZE:KBSIZE;
	kp = ((struct device *)kmcdinfo[dev]->ui_addr);
	kp->bsel1 = 0;
	kmcwritten = 1;
	while (u.u_error==0 && u.u_count) {
		ad = u.u_offset;
		if (ad<dsize*2) {
			if (ad&1) {
				u.u_error = ENXIO;
				break;
			}
			kp->bsel1 = ROMO;
			kp->sel4 = ad>>1;
			lobyte(ins) = cpass();
			hibyte(ins) = cpass();
			kp->sel6 = ins;
			kp->bsel1 |= CWRT;
			kp->bsel1 = 0;
		} else if (ad -= dsize*2, ad<dsize) {
			kp->bsel1 = ROMO;
			kp->sel4 = 0;
			sav = kp->sel6;
			kp->bsel1 = ROMI;
			kp->sel6 = 010000|(ad&0377);	/* mov ad,mar */
			kp->bsel1 = ROMI|STEP;
			kp->bsel1 = ROMI;
			kp->sel6 = 04000|((ad>>8)&0377);	/* mov %ad,%mar */
			kp->bsel1 = ROMI|STEP;
			kp->bsel1 = ROMI;
			kp->bsel2 = cpass();
			kp->sel6 = 0136440;	/* mov csr2,mem|mar++ */
			kp->bsel1 = ROMI|STEP;
			kp->bsel1 = ROMI;
			kp->sel6 = sav;
			kp->bsel1 = 0;
		} else
			break;
	}
}

kmcioctl(dev, cmd, arg, mode)
caddr_t arg;
dev_t dev;
{	register struct device *kp;
	register struct kmc *tp;
	struct kmcntl kk;
	short	csr[4];
	ushort	sav;

	dev = minor(dev);
	if (cmd != KCSETA) {
		u.u_error = EINVAL;
		return;
	}
	if(dev >= NKMC) {
		u.u_error = ENXIO;
		return;
	}
	if (copyin(arg, &kk, sizeof(kk))) {
		u.u_error = EFAULT;
		return;
	}
	kp = ((struct device *)kmcdinfo[dev]->ui_addr);
	tp = &kmc[dev];
	switch (kk.kmd) {
	case KMCLR:
	case KRESET:
		spl7();
		kp->bsel1 = MCLR;
		spl0();
	case KSTOP:
		tp->k_stat &= ~SRUN;
		kp->bsel1 = 0;
		if (kk.kmd == KRESET) {
			tp->k_stat = 0;
			/* flush here */
		}
		return;
	case KMS:
		if (tp->k_stat&SRUN)
			break;
		kp->bsel1 = ROMI|ROMO;
		sav = kp->sel6;
		kp->bsel1 = ROMI;
		kp->sel6 = kk.kval;
		kp->bsel1 = ROMI|STEP;
		kp->bsel1 = ROMI;
		kp->sel6 = sav;
		kp->bsel1 = 0;
		goto lcsr;
	case KSTEP:
		if (tp->k_stat&SRUN)
			break;
		kp->bsel1 |= STEP;
		kp->bsel1 = 0;
	case KCSR:
	lcsr:
		csr[0] = kp->sel0;
		csr[1] = kp->sel2;
		csr[2] = kp->sel4;
		csr[3] = kp->sel6;
		if (copyout(csr, kk.kcsr, sizeof csr))
			u.u_error = EFAULT;
		return;
	case KWRCR:
		if (tp->k_stat&SRINT)
			break;
		kp->sel6 = kk.kval;
		return;
	case KRUN:
		if (tp->k_stat&SRUN)
			break;
		tp->k_stat &= ~STYPE;
		tp->k_stat |= (kk.kval&STYPE)|SRUN;
		kp->bsel1 |= RUN;
		if (tp->k_stat&SRINT) {
			spl5();
			kmcrint(dev);
			spl0();
		}
		return;
	case KLU:
		kp->bsel1 = kk.kval&(LUA|LUB);
		return;
	}
	u.u_error = EIO;
}

kmcrint(dev)
dev_t dev;
{
	if (kdirint)
		(*kdirint)();
}

kmcxint(dev)
{
	if (kdixint)
		(*kdixint)();
}