~kris/9p

9hist

437dd1f6f13d774d07428f40ece2d4574a80b3e2 — David du Colombier 36 years ago 135a573
Plan 9 from Bell Labs 1990-09-05
M gnot/dat.h => gnot/dat.h +3 -3
@@ 106,10 106,10 @@ struct Chan

struct	FPsave
{
	char	type;
	char	size;
	uchar	type;
	uchar	size;
	short	reserved;
	char	junk[180];
	char	junk[212];	/* 68881: sizes 24, 180; 68882: 56, 212 */
	char	reg[3*4+8*12];
};


M gnot/devcons.c => gnot/devcons.c +53 -43
@@ 357,12 357,12 @@ enum{
	Qpid,
	Qppid,
	Qrcons,
	Qrs232ctl,
	Qtime,
	Quser,
	Qklog,
	Qmsec,
	Qclock,
	Qrs232ctl = STREAMQID(1, Sctlqid),
	Qrs232 = STREAMQID(1, Sdataqid),
};



@@ 479,14 479,17 @@ consopen(Chan *c, int omode)
{
	int ch;

	if(c->qid==Quser && omode==(OWRITE|OTRUNC)){
		/* truncate? */
		if(strcmp(u->p->pgrp->user, "bootes") == 0)	/* BUG */
			u->p->pgrp->user[0] = 0;
		else
			error(0, Eperm);
	}
	if(c->qid == Qrcons)
	switch(c->qid){
	case Quser:
		if(omode==(OWRITE|OTRUNC)){
			/* truncate? */
			if(strcmp(u->p->pgrp->user, "bootes") == 0)	/* BUG */
				u->p->pgrp->user[0] = 0;
			else
				error(0, Eperm);
		}
		break;
	case Qrcons:
		if(incref(&raw) == 1){
			lock(&lineq);
			while((ch=getc(&kbdq)) != -1){


@@ 496,8 499,12 @@ consopen(Chan *c, int omode)
			}
			unlock(&lineq);
		}
	if(c->qid == Qrs232)
		break;
	case Qrs232:
	case Qrs232ctl:
		streamopen(c, &rs232info);
		break;
	}
	return devopen(c, omode, consdir, NCONS, consgen);
}



@@ 688,31 695,8 @@ conswrite(Chan *c, void *va, long n)
		break;

	case Qrs232:
		n = streamwrite(c, va, n, 1);
		break;

	case Qrs232ctl:
		qlock(&rs232);
		if(waserror()){
			qunlock(&rs232);
			nexterror();
		}
		if(n<=2 || n>=sizeof buf)
			error(0, Ebadarg);
		strncpy(buf, a, n);
		buf[n] = 0;
		l = strtoul(buf+1, 0, 0);
		switch(buf[0]){
		case 'B':
			duartbaud(l); break;
		case 'D':
			duartdtr(l); break;
		case 'K':
			duartbreak(l); break;
		default:
			error(0, Ebadarg);
		}
		qunlock(&rs232);
		n = streamwrite(c, va, n, 1);
		break;

	case Qtime:


@@ 776,32 760,58 @@ consuserstr(Error *e, char *buf)

/*
 *  rs232 stream routines
 *
 *  A kernel process, rs232kproc, stages blocks to be output and
 *  packages input bytes into stream blocks to send upstream.
 *  The process is awakened whenever the interrupt side is almost
 *  out of bytes to xmit or 1/16 second has elapsed since a byte
 *  was input.
 */
static int
rs232empty(void *a)
{
	Rs232 *r;

	r = a;
	return r->out.w == r->out.r;
}

static void
rs232output(Rs232 *r)
{
	int next;
	Queue *q;
	Block *bp;
	long l;

	qlock(&r->outlock);
	q = r->wq;

	/*
 	 *  free emptied blocks
	 */
	for(; r->out.f != r->out.r; r->out.f = NEXT(r->out.f)){
		freeb(r->out.bp[r->out.f]);
		r->out.bp[r->out.f] = 0;
	}

	/*
	 *  stage new blocks
	 *
	 *  if we run into a control block, wait till the queue
	 *  is empty before doing the control.
	 */
	for(next = NEXT(r->out.w); next!=r->out.r; next = NEXT(next)){
	for(next = NEXT(r->out.w); next != r->out.r; next = NEXT(next)){
		bp = getq(q);
		if(bp == 0)
			break;
		if(bp->type == M_CTL){
			while(!rs232empty(r))
				sleep(&r->r, rs232empty, r);
			l = strtoul((char *)(bp->rptr+1), 0, 0);
			switch(*bp->rptr){
			case 'B':
				duartbaud(l); break;
			case 'D':
				duartdtr(l); break;
			case 'K':
				duartbreak(l); break;
			}
			freeb(bp);
			break;
		}
		r->out.bp[r->out.w] = bp;
		r->out.w = next;
	}

M gnot/devdk.c => gnot/devdk.c +3 -5
@@ 397,7 397,8 @@ dkiput(Queue *q, Block *bp)
/*
 *  we assume that each put is a message.
 *
 *  add a 2 byte channel number to the start of each message
 *  add a 2 byte channel number to the start of each message,
 *  low order byte first.
 */
static void
dkoput(Queue *q, Block *bp)


@@ 415,10 416,7 @@ dkoput(Queue *q, Block *bp)
	dp = lp->dp;
	line = lp - dp->line;

	if(bp->base && bp->rptr - bp->base >= 2)
		bp->rptr -= 2;
	else
		panic("dkoput");
	bp = padb(bp, 2);
	bp->rptr[0] = line;
	bp->rptr[1] = line>>8;


M gnot/fns.h => gnot/fns.h +1 -0
@@ 106,6 106,7 @@ char	*nextelem(char*, char*);
void	notify(Ureg*);
void	nullput(Queue*, Block*);
int	openmode(ulong);
Block*	padb(Block*, int);
void	pageinit(void);
void	panic(char*, ...);
void	pexit(char*, int);

M gnot/main.c => gnot/main.c +1 -2
@@ 59,14 59,13 @@ void
machinit(void)
{
	int n;
	long fpnull = 0;

	n = m->machno;
	memset(m, 0, sizeof(Mach));
	m->machno = n;
	m->mmask = 1<<m->machno;
	m->fpstate = FPinit;
	fprestore((FPsave*)&fpnull);
	fprestore(&initfp);
}

void

M gnot/proc.c => gnot/proc.c +4 -4
@@ 5,7 5,7 @@
#include	"fns.h"
#include	"errno.h"

#include	<balu.h>
#include	<gnot.h>

struct
{


@@ 79,8 79,6 @@ sched(void)
{
	Proc *p;
	ulong tlbvirt, tlbphys;
	void (*f)(ulong);
	long fpnull = 0;
	Balu balu;

	if(u){


@@ 88,6 86,8 @@ sched(void)

		fpsave(&u->fpsave);
		if(u->fpsave.type){
			if(u->fpsave.size > sizeof u->fpsave.junk)
				panic("fpsize %d max %d\n", u->fpsave.size, sizeof u->fpsave.junk);
			fpregsave(u->fpsave.reg);
			u->p->fpstate = FPactive;
			m->fpstate = FPdirty;


@@ 107,7 107,7 @@ if(u->p->mach)panic("mach non zero");
			if(p->fpstate != m->fpstate){
				if(p->fpstate == FPinit){
					u->p->fpstate = FPinit;
					fprestore((FPsave*)&fpnull);
					fprestore(&initfp);
					m->fpstate = FPinit;
				}else{
					fpregrestore(u->fpsave.reg);

A gnot/stasync.c => gnot/stasync.c +432 -0
@@ 0,0 1,432 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#define DPRINT 	if(asyncdebug)kprint

typedef struct Async {
	QLock;

	int	inuse;
	QLock	xmit;		/* transmit lock */
	int	chan;		/* current urp channel */
	Block	*bp;		/* current buffer */
	int	count;
	ushort	crc;

	/* statistics */

	ulong	toolong;
	ulong	tooshort;
	ulong	badcrc;
	ulong	badescape;
	ulong	in;		/* bytes in */
	ulong	out;		/* bytes out */
} Async;

Async async[Nasync];

/*
 *  async stream module definition
 */
static void asynciput(Queue*, Block*);
static void asyncoput(Queue*, Block*);
static void asyncopen(Queue*, Stream*);
static void asyncclose(Queue*);
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async" };

int asyncdebug = 1;
int asyncerror;

static ushort crc_table[256] = {
#include "crc_16.h"
};

#define	BOT	0050		/* begin trailer */
#define	BOTM	0051		/* begin trailer, more data follows */
#define	BOTS	0052		/* seq update alg. on this trailer */

#define	MAXFRAME	256
#define	FRAME		0x7e
#define	STUF		0x9d

#define	CRCSTART	(crc_table[0xff])
#define	CRCFUNC(crc,x)	(crc_table[((crc)^(x))&0xff]^((crc)>>8))

/*
 *  create the kernel process for input
 */
static void
asyncopen(Queue *q, Stream *s)
{
	DPRINT("asyncstopen %d\n", s->dev);

	for(ap = async; ap < &async[Nasync]; ap++){
		qlock(ap);
		if(ap->inuse == 0)
			break;
		qunlock(ap);
	}
	if(ap == &async[Nasync])
		error(0, Enoasync);
	q->ptr = q->other->ptr = ap;

	ap->bp = allocb(256);
	ap->chan = -1;
	ap->count = 0;
	ap->toolong = 0;
	ap->tooshort = 0;
	ap->badcrc = 0;
	ap->badescape = 0;
	ap->chan0 = 0;
	ap->in = 0;
	ap->out = 0;
}

static void
asyncclose(Queue * q)
{
	Async *ap = (Async *)q->ptr;

	DPRINT("asyncstclose %d\n", ap-async);
	qlock(ap);
	ap->inuse = 0;
	qunlock(ap);
}

/*
 *  free all blocks of a message in `q', `bp' is the first block
 *  of the message
 */
static void
freemsg(Queue *q, Block *bp)
{
	for(; bp; bp = getq(q)){
		if(bp->flags & S_DELIM){
			freeb(bp);
			return;
		}
		freeb(bp);
	}
}

static void
showframe(char *t, Async *ap, uchar *buf, int n)
{
	kprint("a%d %s [", ap-async, t);
	while (--n >= 0)
		kprint(" %2.2ux", *buf++);
	kprint(" ]\n");
}

void
aswrite(Async *ap)
{
	int n = ap->bp - ap->buf;
	if (n <= 0)
		return;
	if (asyncdebug > 2)
		showframe("out", ap, ap->buf, n);
	(*devtab[ap->c->type].write)(ap->c, ap->buf, n);
	ap->out += n;
	ap->bp = ap->buf;
}

void
asputf(Async *ap, int frame)
{
	uchar *p = ap->bp;
	int c;
	if (ap->count > 0) {
		if (asyncerror)
			ap->crc^=1, asyncerror=0;
		*p++ = c = ap->crc&0xff;
		if (c == FRAME)
			*p++ = 0x00;
		*p++ = c = (ap->crc>>8)&0xff;
		if (c == FRAME)
			*p++ = 0x00;
		ap->count = 0;
	}
	if (frame) {
		*p++ = FRAME;
		*p++ = FRAME;
	}
	ap->bp = p;
	aswrite(ap);
}

void
asputc(Async *ap, int c)
{
	int d;
	uchar *p = ap->bp;
	if (ap->count <= 0) {
		*p++ = FRAME;
		*p++ = FRAME;
		*p++ = d = 0x80|((ap->chan>>5)&0x7e);
		ap->crc = CRCFUNC(CRCSTART, d);
		*p++ = d = 0x80|((ap->chan<<1)&0x7e);
		ap->crc = CRCFUNC(ap->crc, d);
	}
	*p++ = c;
	if (c == FRAME)
		*p++ = 0x00;
	ap->crc = CRCFUNC(ap->crc, c);
	ap->bp = p;
	if (++ap->count >= MAXFRAME-4)
		asputf(ap, 0);
	else if (p-ap->buf >= sizeof(ap->buf)-8)
		aswrite(ap);
}

/*
 *  output a block
 *
 *  the first 2 bytes of every message are the channel number,
 *  low order byte first.  the third is a possible trailing control
 *  character.
 */
void
asyncoput(Queue *q, Block *bp)
{
	Async *ap = (Async *)q->ptr;
	int c, chan, ctl;

	if(bp->type != M_DATA){
		freeb(bp);
		return;
	}

	/*
	 *  get a whole message before handing bytes to the device
	 */
	if(!putq(q, bp))
		return;

	/*
	 *  one transmitter at a time
	 */
	qlock(&ap->xmit);

	/*
	 *  parse message
	 */
	bp = getq(q);
	if(bp->wptr - bp->rptr < 3){
		freemsg(q, bp);
		qunlock(&ap->xmit);
		return;
	}
	chan = bp->rptr[0] | (bp->rptr[1]<<8);
	ctl = bp->rptr[2];
	bp->rptr += 3;

	/*
	 *  new frame if the channel number has changed
	 */
	if (chan != ap->chan && ap->count > 0)
		asputf(ap, 0);
	ap->chan = chan;

	if (asyncdebug > 1)
		kprint("a%d->(%d)%3.3uo %d\n",
			ap-async, chan, ctl, bp->wptr - bp->rptr);

	/*
	 *  send the 8 bit data
	 */
	for(;;){
		/*
		 *  put in next packet
		 */
		while (bp->rptr < bp->wptr) {
			asputc(ap, c = *bp->rptr++);
			if (c == STUF)
				asputc(ap, 0);
		}

		/*
		 *  get next block 
		 */
		if(bp->flags & S_DELIM){
			freeb(bp);
			break;
		}
		freeb(bp);
		bp = getq(q);
		if(bp==0)
			break;
	}

	/*
	 *  send the control byte if there is one
	 */
	if(ctl){
		asputc(ap, STUF);
		asputc(ap, ctl);
		switch (ctl) {
		case BOT:
		case BOTM:
		case BOTS:
			break;
		default:
			asputf(ap, 1);
		}
	}

	qunlock(&ap->xmit);
	return;
}

/*
 *  Read bytes from the raw input.
 */

void
asdeliver(Async *ap, uchar *p, int n)
{
	Block *bp = 0;
	int chan, c;

	if (!ap->rq)
		return;

	chan = *p++ & 0x7e;
	chan = (chan<<5)|((*p++ & 0x7e)>>1);
	if (chan==0) {
		DPRINT("a%d deliver chan 0\n", ap-async);
		ap->chan0++;
		return;
	}
	for (n-=4; n>0; n--) {
		if (!bp) {
			bp = allocb(n+2);
			bp->flags |= S_DELIM;
			bp->wptr[0] = chan;
			bp->wptr[1] = chan>>8;
			bp->wptr[2] = 0;
			bp->wptr += 3;
		}
		if ((c = *p++) == STUF) {
			--n;
			if ((c = *p++) != 0) {
				bp->rptr[2] = c;
				if (asyncdebug > 1)
					kprint("a%d<-(%d)%3.3uo %d\n",
						ap-async, chan, bp->rptr[2],
						bp->wptr - bp->rptr - 3);
				PUTNEXT(ap->rq, bp);
				bp = 0;
				continue;
			} else
				c = STUF;
		}
		*bp->wptr++ = c;
	}
	if (bp) {
		if (asyncdebug > 1)
			kprint("a%d<-(%d)%3.3uo %d\n",
				ap-async, chan, bp->rptr[2],
				bp->wptr - bp->rptr - 3);
		PUTNEXT(ap->rq, bp);
	}
}

enum { Hunt=0, Framing, Framed, Data, Escape };

static void
asynckproc(void *arg)
{
	Async *ap = (Async *)arg;
	int c, state, count; unsigned short crc;
	uchar buf[MAXFRAME], ibuf[MAXFRAME], *p;
	int nibuf;

	DPRINT("asynckproc %d\n", ap-async);
	nibuf = 0;
	state = Hunt;
Loop:
	if (--nibuf < 0) {
		if (ap->rq)
			nibuf = (*devtab[ap->c->type].read)(ap->c,
					ibuf, sizeof ibuf);
		if (nibuf <= 0) {
			unlock(&ap->kstart);
			wakeup(&ap->r);
			return;
		}
		ap->in += nibuf--;
		p = ibuf;
	}
	c = *p++;
	switch (state) {
	case Hunt:	/* wait for framing byte */
		if (c == FRAME)
			state = Framing;
		break;

	case Framing:	/* saw 1 framing byte after Hunt */
		if (c == FRAME)
			state = Framed;
		else
			state = Hunt;
		break;

	case Framed:	/* saw 2 or more framing bytes */
		if (c == FRAME)
			break;
		state = Data;
		crc = CRCSTART;
		count = 0;
		goto Datachar;

	case Data:	/* mid-frame */
		if (c == FRAME) {
			state = Escape;
			break;
		}
	Datachar:
		if (count >= MAXFRAME) {
			DPRINT("a%d pkt too long\n", ap-async);
			ap->toolong++;
			state = Hunt;
			break;
		}
		crc = CRCFUNC(crc, c);
		buf[count++] = c;
		break;

	case Escape:	/* saw framing byte in Data */
		switch (c) {
		case FRAME:
			if (asyncdebug > 2)
				showframe("in", ap, buf, count);
			if (count < 5) {
				DPRINT("a%d pkt too short\n", ap-async);
				ap->tooshort++;
			} else if (crc != 0) {
				DPRINT("a%d bad crc\n", ap-async);
				ap->badcrc++;
			} else {
				asdeliver(ap, buf, count);
			}
			state = Framed;
			break;
		case 0:
			c = FRAME;
			state = Data;
			goto Datachar;
		default:
			DPRINT("a%d bad escape\n", ap-async);
			ap->badescape++;
			state = Hunt;
			break;
		}
		break;
	}
	goto Loop;
}

M gnot/stream.c => gnot/stream.c +20 -0
@@ 232,6 232,26 @@ freeb(Block *bp)
}

/*
 *  pad a block to the front with n bytes
 */
Block *
padb(Block *bp, int n)
{
	Block *nbp;

	if(bp->base && bp->rptr-bp->base>=n){
		bp->rptr -= n;
		return bp;
	} else {
		nbp = allocb(n);
		nbp->wptr = nbp->lim;
		nbp->rptr = nbp->wptr - n;
		nbp->next = nbp;
		return nbp;
	}
} 

/*
 *  allocate a pair of queues.  flavor them with the requested put routines.
 *  the `QINUSE' flag on the read side is the only one used.
 */

M gnot/trap.c => gnot/trap.c +2 -3
@@ 94,7 94,7 @@ trap(Ureg *ur)
		sprint(buf, "pc=%lux trap: %s", ur->pc, excname(ur->vo));
		postnote(u->p, 1, buf, NDebug);
	}else{
		print("kernel trap vo=%ux pc=%lux\n", ur->vo, ur->pc);
		print("kernel trap vo=0x%ux pc=%lux\n", ur->vo, ur->pc);
		dumpregs(ur);
		exit();
	}


@@ 243,7 243,6 @@ syscall(Ureg *aur)
	ulong r0;
	Ureg *ur;
	char *msg;
	long fpnull = 0;

	u->p->insyscall = 1;
	ur = aur;


@@ 258,7 257,7 @@ syscall(Ureg *aur)
	splhi();
	fpsave(&u->fpsave);
	if(u->p->fpstate==FPactive || u->fpsave.type){
		fprestore((FPsave*)&fpnull);
		fprestore(&initfp);
		u->p->fpstate = FPinit;
		m->fpstate = FPinit;
	}

M port/stream.c => port/stream.c +42 -72
@@ 24,19 24,6 @@ Qinfo procinfo = { stputq, nullput, 0, 0, "process" };
 */
static Qinfo *lds[Nlds+1];

void
newqinfo(Qinfo *qi)
{
	int i;

	for(i=0; i<Nlds && lds[i]; i++)
		if(lds[i] == qi)
			return;
	if(i == Nlds)
		panic("pushable");
	lds[i] = qi;
}

/*
 *  All stream structures are ialloc'd at boot time
 */


@@ 68,6 55,14 @@ Bclass bclass[Nclass]={
};

/*
 *  the per stream directory structure
 */
Dirtab streamdir[]={
	"data",		Sdataqid,	0,			0600,
	"ctl",		Sctlqid,	0,			0600,
};

/*
 *  Dump all block information of how many blocks are in which queues
 */
void


@@ 120,19 115,26 @@ dumpqueues(void)
 *  Allocate streams, queues, and blocks.  Allocate n block classes with
 *	1/2(m+1) to class m < n-1
 *	1/2(n-1) to class n-1
 *
 *  All data areas are alligned to their size.
 *
 *  No data area crosses a 4k boundary.  This allows us to use the
 *  VME/SCSI/LANCE to MP bus maps on the SGI power series machines.
 */
void
streaminit(void)
{
	int class, i, n;
	int class, i, n, left;
	Block *bp;
	Bclass *bcp;
	uchar *ptr;

	slist = (Stream *)ialloc(conf.nstream * sizeof(Stream), 0);
	qlist = (Queue *)ialloc(conf.nqueue * sizeof(Queue), 0);
	blist = (Block *)ialloc(conf.nblock * sizeof(Block), 0);
	bp = blist;
	n = conf.nblock;
	left = 0;
	for(class = 0; class < Nclass; class++){
		if(class < Nclass-1)
			n = n/2;


@@ 143,8 145,15 @@ streaminit(void)
			 *  starts on a page boundary.  This makes sure
			 *  no block crosses a page boundary.
			 */
			if(bcp->size)
				bp->base = (uchar *)ialloc(bcp->size, i == 0);
			if(bcp->size){
				if(bcp->size > left){
					left = bcp->size>4096 ? bcp->size : 4096;
					ptr = (uchar *)ialloc(left, 1);
				}
				bp->base = ptr;
				ptr += bcp->size;
				left -= bcp->size;
			}
			bp->lim = bp->base + bcp->size;
			bp->flags = class;
			freeb(bp);


@@ 479,54 488,6 @@ getb(Blist *q)
}

/*
 *  make sure the first block has n bytes
 */
Block *
pullup(Block *bp, int n)
{
	Block *nbp;
	int i;

	/*
	 *  this should almost always be true, the rest it
	 *  just for to avoid every caller checking.
	 */
	if(BLEN(bp) >= n)
		return bp;

	/*
	 *  if not enough room in the first block,
	 *  add another to the front of the list.
	if(bp->lim - bp->rptr < n){
		nbp = allocb(n);
		nbp->next = bp;
		bp = nbp;
	}

	/*
	 *  copy bytes from the trailing blocks into the first
	 */
	n -= BLEN(bp);
	while(nbp = bp->next){
		i = BLEN(nbp);
		if(i > n) {
			memcpy(bp->wptr, nbp->rptr, n);
			bp->wptr += n;
			nbp->rptr += n;
			return bp;
		} else {
			memcpy(bp->wptr, nbp->rptr, i);
			bp->wptr += i;
			bp->next = nbp->next;
			nbp->next = 0;
			freeb(nbp);
		}
	}
	freeb(bp);
	return 0;
}

/*
 *  grow the front of a list of blocks by n bytes
 */
Block *


@@ 626,14 587,6 @@ streamparse(char *name, Block *bp)
}

/*
 *  the per stream directory structure
 */
Dirtab streamdir[]={
	"data",		Sdataqid,	0,			0600,
	"ctl",		Sctlqid,	0,			0600,
};

/*
 *  A stream device consists of the contents of streamdir plus
 *  any directory supplied by the actual device.
 *


@@ 1197,3 1150,20 @@ streamstat(Chan *c, char *db, char *name)
	devdir(c, c->qid, name, n, 0, &dir);
	convD2M(&dir, db);
}

/*
 *  announce a line discipline that can be pushed
 */
void
newqinfo(Qinfo *qi)
{
	int i;

	for(i=0; i<Nlds && lds[i]; i++)
		if(lds[i] == qi)
			return;
	if(i == Nlds)
		panic("pushable");
	lds[i] = qi;
}


M power/dat.h => power/dat.h +1 -1
@@ 477,7 477,7 @@ enum {
	Sctlqid = Sdataqid-1,
	Slowqid = Sctlqid,
	Streamhi= (17*1024),	/* byte count high water mark */
	Streambhi= 16,		/* block count high water mark */
	Streambhi= 32,		/* block count high water mark */
};

/*

M power/fns.h => power/fns.h +1 -0
@@ 97,6 97,7 @@ Orig	*lookorig(ulong, ulong, int, Chan*);
void	machinit(void);
void	mapstack(Proc*);
int	mount(Chan*, Chan*, int);
void	mpbuserror(void);
Chan	*namec(char*, int, int, ulong);
void	nexterror(void);
Alarm	*newalarm(void);

M power/io.h => power/io.h +12 -10
@@ 44,9 44,12 @@ struct SBCC

#define LANCERAM	IO2(uchar, 0xE00000)
#define LANCEEND	IO2(uchar, 0xF00000)
#define LANCE3RAM	IO2(uchar, 0xFF4000)
#define LANCE3END	IO2(uchar, 0xFF8000)
#define LANCERDP	IO2(ushort, 0xFC0002)
#define LANCERAP	IO2(ushort, 0xFC000a)
#define LANCEID		IO2(ushort, 0xFF0002)

#define IOID		IO2(uchar, 0xFFFFF0)
#define IO2R1		1	/* IO2 revision level 1 */
#define IO2R2		2	/* IO2 revision level 2 */


@@ 83,21 86,20 @@ struct INTVEC {
#define	MPBERR1		IO2(ulong, 0xF4C000)
#define SBEADDR		((ulong *)(UNCACHED|0x1F080000))

/*
 *  IO board type
 */
extern int ioid;
extern int ioid;	/* io board type */
extern int iolevels;	/* number of io levels */
extern int iomask;	/* interrupts to enable */

/*
 *  The IO2/IO3 slave maps.  These maps are used to map
 *  external addresses to MP bus addresses.
 */
enum {
	a24map,		/* VME A24 non-priv address space */
	a32map,		/* VME A32 non-priv address space */
	lancemap,	/* Lance chip address space */
	scsi1map,	/* SCSI bus 1 address space */
	scsi0map,	/* SCSI bus 0 address space */
	nomap,
	A24map,		/* VME A24 non-priv address space */
	A32map,		/* VME A32 non-priv address space */
	Lancemap,	/* Lance chip address space */
	Scsi1map,	/* SCSI bus 1 address space */
	Scsi0map,	/* SCSI bus 0 address space */
	Nomap,
};
#define	WRITEMAP	IO2(ulong, 0xFA0000);

M power/main.c => power/main.c +22 -5
@@ 35,9 35,11 @@ char confbuf[4*1024];
char sysname[64];

/*
 *  IO board type
 *  IO board type, number of interrupt levels, and interrupt enable mask
 */
int ioid;
int iolevels;
int iomask;

void
main(void)


@@ 133,8 135,23 @@ void
ioboardinit(void)
{
	long i;
	int intrs;

	/*
	 *  set up interrupts based on IO board type
	 */
	ioid = *IOID;
	switch(ioid){
	case IO2R1:
	case IO2R2:
		iolevels = 8;
		iomask = 0xff;
		break;
	case IO3R1:
		iolevels = 11;
		iomask = 0x7fe;
		break;
	}

	/*
	 *  reset VME bus (MODEREG is on the IO2)


@@ 152,9 169,9 @@ ioboardinit(void)
		setvmevec(i, novme);

	/*
	 *  tell IO2 to sent all interrupts to CPU 0's SBCC
	 *  tell IO2 to send all interrupts to CPU 0's SBCC
	 */
	for(i=0; i<8; i++)
	for(i=0; i<iolevels; i++)
		INTVECREG->i[i].vec = 0<<8;

	/*


@@ 174,13 191,13 @@ ioboardinit(void)
	 *  The SBCC 16 bit registers are read/written as ulong, but only
	 *  bits 23-16 and 7-0 are meaningful.
	 */
	SBCCREG->fintenable |= 0xff;	  /* allow all interrupts on the IO2 */
	SBCCREG->fintenable |= iomask;	/* turn on all interrupts */
	SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */

	/*
	 *  enable all interrupts on the IO2
	 */
	*IO2SETMASK = 0xff;
	*IO2SETMASK = iomask;
}

void

M power/trap.c => power/trap.c +37 -31
@@ 180,6 180,14 @@ trap(Ureg *ur)
}

void
mpbuserror(void)
{
	print("io2 mp bus error %d %lux %lux\n", 0,
		*MPBERR0, *MPBERR1);
	*MPBERR0 = 0;
}

void
intr(ulong cause, ulong pc)
{
	int i, pend;


@@ 227,33 235,34 @@ intr(ulong cause, ulong pc)
		/*
		 *  5a. process lance, scsi
		 */
	loop:
		if(pend & 1) {
			v = INTVECREG->i[0].vec;
			if(!(v & (1<<12))){
				print("io2 mp bus error %d %lux %lux\n", 0,
					*MPBERR0, *MPBERR1);
				*MPBERR0 = 0;
			}
			switch(ioid){
			case IO2R1:
			case IO2R2:
				if(!(v & (1<<2)))
					lanceintr();
				if(!(v & (1<<1)))
					lanceparity();
				if(!(v & (1<<0)))
					print("SCSI interrupt\n");
				break;
			case IO3R1:
				if(v & (1<<2))
					lance3intr();
				if(v & (1<<1))
					print("SCSI 1 interrupt\n");
				if(v & (1<<0))
					print("SCSI 0 interrupt\n");
				break;
			}
			if(!(v & (1<<12)))
				mpbuserror();
			if(!(v & (1<<2)))
				lanceintr();
			if(!(v & (1<<1)))
				lanceparity();
			if(!(v & (1<<0)))
				print("SCSI interrupt\n");
		}
		if(pend & (1<<10)) {
			v = INTVECREG->i[10].vec;
			if(!(v & (1<<12)))
				mpbuserror();
			lance3intr();
		}
		if(pend & (1<<8)) {
			v = INTVECREG->i[10].vec;
			if(!(v & (1<<12)))
				mpbuserror();
			print("SCSI0 interrupt\n");
		}
		if(pend & (1<<9)) {
			v = INTVECREG->i[10].vec;
			if(!(v & (1<<12)))
				mpbuserror();
			print("SCSI1 interrupt\n");
		}
		/*
		 *  5b. process vme


@@ 263,11 272,8 @@ intr(ulong cause, ulong pc)
		for(i=1; pend; i++) {
			if(pend & 1) {
				v = INTVECREG->i[i].vec;
				if(!(v & (1<<12))){
					print("io2 mp bus error %d %lux %lux\n", i,
						*MPBERR0, *MPBERR1);
					*MPBERR0 = 0;
				}
				if(!(v & (1<<12)))
					mpbuserror();
				v &= 0xff;
				(*vmevec[v])(v);
			}


@@ 276,7 282,7 @@ intr(ulong cause, ulong pc)
		/*
		 *  6. re-enable interrupts
		 */
		*IO2SETMASK = 0xff;
		*IO2SETMASK = iomask;
		cause &= ~INTR5;
	}
	if(cause)