~kris/9p

9hist

2f74d45e15e6e5f1583e9118b6c2d2cc507bdf85 — David du Colombier 34 years ago bbc3d65
Plan 9 from Bell Labs 1991-12-25
10 files changed, 170 insertions(+), 205 deletions(-)

M gnot/screen.c
M gnot/screen.h
M pc/screen.h
M port/devbit.c
M port/devscc.c
M port/portfns.h
M ss/io.h
M ss/main.c
M ss/screen.c
M ss/screen.h
M gnot/screen.c => gnot/screen.c +38 -40
@@ 40,57 40,55 @@ screeninit(void)
	if(*(uchar*)MOUSE & (1<<4))
		gscreen.ldepth = 1;
	defont = &defont0;	/* save space; let bitblt do the conversion work */
	kbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0);
	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0);
	out.pos.x = MINX;
	out.pos.y = 0;
	out.bwid = defont0.info[' '].width;
}

void
screenputc(int c)
screenputs(char *s, int n)
{
	char buf[2];
	int nx;

	if(c == '\n'){
		out.pos.x = MINX;
		out.pos.y += defont0.height;
		if(out.pos.y > gscreen.r.max.y-defont0.height)
			out.pos.y = gscreen.r.min.y;
		kbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
		    Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height), 0);
	}else if(c == '\t'){
		out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
		if(out.pos.x >= gscreen.r.max.x)
			screenputc('\n');
	}else if(c == '\b'){
		if(out.pos.x >= out.bwid+MINX){
			out.pos.x -= out.bwid;
			screenputc(' ');
			out.pos.x -= out.bwid;
	Rune r;
	int i;
	char buf[4];

	while(n > 0){
		i = chartorune(&r, s);
		if(i == 0){
			s++;
			--n;
			continue;
		}
		memmove(buf, s, i);
		buf[i] = 0;
		n -= i;
		s += i;
		if(r == '\n'){
			out.pos.x = MINX;
			out.pos.y += defont0.height;
			if(out.pos.y > gscreen.r.max.y-defont0.height)
				out.pos.y = gscreen.r.min.y;
			gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
			    Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height), 0);
		}else if(r == '\t'){
			out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
			if(out.pos.x >= gscreen.r.max.x)
				screenputs("\n", 1);
		}else if(r == '\b'){
			if(out.pos.x >= out.bwid+MINX){
				out.pos.x -= out.bwid;
				screenputs(" ", 1);
				out.pos.x -= out.bwid;
			}
		}else{
			if(out.pos.x >= gscreen.r.max.x-out.bwid)
				screenputs("\n", 1);
			out.pos = gstring(&gscreen, out.pos, defont, buf, S);
		}
	}else{
		if(out.pos.x >= gscreen.r.max.x-out.bwid)
			screenputc('\n');
		buf[0] = c&0x7F;
		buf[1] = 0;
		out.pos = gstring(&gscreen, out.pos, defont, buf, S);
	}
}

void
screenputs(char *s, int n)
{
	int x;

	x = splhi();
	lock(&printq);
	while(n-- > 0)
		screenputc(*s++);
	unlock(&printq);
	splx(x);
}

int
screenbits(void)
{

M gnot/screen.h => gnot/screen.h +0 -6
@@ 27,9 27,3 @@ extern Mouseinfo	mouse;
extern Cursorinfo	cursor;

extern void		mouseupdate(int);

/*
 * kernel mustn't use balu; user (/dev/bitblt) can
 */
#define kbitblt 	gbitblt
#define	ubitblt		gbitblt

M pc/screen.h => pc/screen.h +0 -3
@@ 27,6 27,3 @@ extern Mouseinfo	mouse;
extern Cursorinfo	cursor;

extern void		mouseupdate(int);

#define kbitblt 	gbitblt
#define	ubitblt		gbitblt

M port/devbit.c => port/devbit.c +5 -5
@@ 652,7 652,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				cursoroff(1);
				isoff = 1;
			}
			ubitblt(dst, pt, src, rect, fc);
			gbitblt(dst, pt, src, rect, fc);
			m -= 31;
			p += 31;
			break;


@@ 1164,10 1164,10 @@ cursoron(int dolock)
		cursor.r.min = mouse.xy;
		cursor.r.max = add(mouse.xy, Pt(16, 16));
		cursor.r = raddp(cursor.r, cursor.offset);
		kbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S);
		kbitblt(&gscreen, add(mouse.xy, cursor.offset),
		gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S);
		gbitblt(&gscreen, add(mouse.xy, cursor.offset),
			&clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S);
		kbitblt(&gscreen, add(mouse.xy, cursor.offset),
		gbitblt(&gscreen, add(mouse.xy, cursor.offset),
			&set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D);
	}
	if(dolock)


@@ 1180,7 1180,7 @@ cursoroff(int dolock)
	if(dolock)
		lock(&cursor);
	if(--cursor.visible == 0)
		kbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S);
		gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S);
	if(dolock)
		unlock(&cursor);
}

M port/devscc.c => port/devscc.c +118 -108
@@ 89,6 89,7 @@ struct SCC
	uchar	*ptr;		/* command/pointer register in Z8530 */
	uchar	*data;		/* data register in Z8530 */
	int	printing;	/* true if printing */
	ulong	freq;		/* clock frequency */

	/* console interface */
	int	nostream;	/* can't use the stream interface */


@@ 101,7 102,9 @@ struct SCC
	Alarm	*a;		/* alarm for waking the kernel process */
 	int	kstarted;	/* kproc started */
};
SCC	scc[2];

int	nscc;
SCC	*scc[8];	/* up to 4 8530's */

void
onepointseven(void)


@@ 145,7 148,10 @@ sccsetbaud(SCC *sp, int rate)
{
	int brconst;

	brconst = (SCCFREQ+16*rate-1)/(2*16*rate) - 2;
	if(rate == 0)
		errors("bad baud rate");

	brconst = (sp->freq+16*rate-1)/(2*16*rate) - 2;

	sccwrreg(sp, 12, brconst & 0xff);
	sccwrreg(sp, 13, (brconst>>8) & 0xff);


@@ 183,6 189,8 @@ sccrts(SCC *sp, int n)
void
sccbreak(SCC *sp, int ms)
{
	if(ms == 0)
		ms = 100;
	sp->sticky[1] &=~TxIntEna;
	sccwrreg(sp, 1, 0);
	sccwrreg(sp, 5, TxBreak|TxEna);


@@ 198,51 206,57 @@ sccbreak(SCC *sp, int ms)
 *  default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,
 *  transmit and receive enabled, interrupts disabled.
 */
static void
sccsetup0(SCC *sp)
{
	memset(sp->sticky, 0, sizeof(sp->sticky));

	/*
	 *  turn on baud rate generator and set rate to 9600 baud.
	 *  use 1 stop bit.
	 */
	sp->sticky[14] = BRSource;
	sccwrreg(sp, 14, 0);
	sccsetbaud(sp, 9600);
	sp->sticky[4] = Rx1stop | X16;
	sccwrreg(sp, 4, 0);
	sp->sticky[11] = TxClockBR | RxClockBR | TRxCOutBR | TRxCOI;
	sccwrreg(sp, 11, 0);
	sp->sticky[14] = BREna | BRSource;
	sccwrreg(sp, 14, 0);

	/*
	 *  enable I/O, 8 bits/character
	 */
	sp->sticky[3] = RxEna | Rx8bits;
	sccwrreg(sp, 3, 0);
	sp->sticky[5] = TxEna | Tx8bits;
	sccwrreg(sp, 5, 0);
}
void
sccsetup(void *addr)
sccsetup(void *addr, ulong freq)
{
	SCCdev *dev;
	SCC *sp;
	static int already;

	if(already)
		return;
	already = 1;
	dev = addr;

	/*
	 *  get port addresses
	 *  allocate a structure, set port addresses, and setup the line
	 */
	scc[0].ptr = &dev->ptra;
	scc[0].data = &dev->dataa;
	scc[1].ptr = &dev->ptrb;
	scc[1].data = &dev->datab;

	for(sp = scc; sp < &scc[2]; sp++){
		memset(sp->sticky, 0, sizeof(sp->sticky));

		/*
		 *  turn on baud rate generator and set rate to 9600 baud.
		 *  use 1 stop bit.
		 */
		sp->sticky[14] = BRSource;
		sccwrreg(sp, 14, 0);
		sccsetbaud(sp, 9600);
		sp->sticky[4] = Rx1stop | X16;
		sccwrreg(sp, 4, 0);
		sp->sticky[11] = TxClockBR | RxClockBR | TRxCOutBR | TRxCOI;
		sccwrreg(sp, 11, 0);
		sp->sticky[14] = BREna | BRSource;
		sccwrreg(sp, 14, 0);

		/*
		 *  enable I/O, 8 bits/character
		 */
		sp->sticky[3] = RxEna | Rx8bits;
		sccwrreg(sp, 3, 0);
		sp->sticky[5] = TxEna | Tx8bits;
		sccwrreg(sp, 5, 0);
	}
	sp = ialloc(sizeof(SCC), 0);
	scc[nscc] = sp;
	sp->ptr = &dev->ptra;
	sp->data = &dev->dataa;
	sp->freq = freq;
	sccsetup0(sp);
	sp = ialloc(sizeof(SCC), 0);
	scc[nscc+1] = sp;
	sp->ptr = &dev->ptrb;
	sp->data = &dev->datab;
	sp->freq = freq;
	sccsetup0(sp);
	nscc += 2;
}

/*


@@ 313,10 327,16 @@ void
sccintr(void)
{
	uchar x;
	int i;

	x = sccrdreg(&scc[0], 3);
	sccintr0(&scc[1], x);
	sccintr0(&scc[0], x>>3);
	for(i = 0; i < nscc; i += 2){
		x = sccrdreg(scc[i], 3);
		if(x & (ExtPendB|RxPendB|TxPendB))
			sccintr0(scc[i+1], x);
		x = x >> 3;
		if(x & (ExtPendB|RxPendB|TxPendB))
			sccintr0(scc[i], x);
	}
}

void


@@ 324,8 344,10 @@ sccclock(void)
{
	SCC *sp;
	IOQ *cq;
	int i;

	for(sp = scc; sp < &scc[2]; sp++){
	for(i = 0; i < nscc; i++){
		sp = scc[i];
		cq = sp->iq;
		if(sp->wq && cangetc(cq))
			wakeup(&cq->r);


@@ 371,7 393,7 @@ sccenable(SCC *sp)
void
sccspecial(int port, IOQ *oq, IOQ *iq, int baud)
{
	SCC *sp = &scc[port];
	SCC *sp = scc[port];

	sp->nostream = 1;
	sp->oq = oq;


@@ 410,7 432,7 @@ sccstopen(Queue *q, Stream *s)

	kprint("sccstopen: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n",
		q, s->inuse, s->type, s->dev, s->id);
	sp = &scc[s->id];
	sp = scc[s->id];
	qlock(sp);
	sp->wq = WR(q);
	WR(q)->ptr = sp;


@@ 430,7 452,6 @@ sccstclose(Queue *q)
	SCC *sp = q->ptr;

	qlock(sp);
	kprint("sccstclose: q=0x%ux, id=%d\n", q, sp-scc);
	sp->wq = 0;
	sp->iq->putc = 0;
	WR(q)->ptr = 0;


@@ 461,7 482,10 @@ sccoput(Queue *q, Block *bp)
		switch(*bp->rptr){
		case 'B':
		case 'b':
			sccsetbaud(sp, n);
			if(BLEN(bp)>4 && strncmp((char*)(bp->rptr+1), "reak", 4) == 0)
				sccbreak(sp, 0);
			else
				sccsetbaud(sp, n);
			break;
		case 'D':
		case 'd':


@@ 522,32 546,34 @@ loop:
	goto loop;
}

enum{
	Qdir=		0,
	Qeia0=		STREAMQID(0, Sdataqid),
	Qeia0ctl=	STREAMQID(0, Sctlqid),
	Qeia1=		STREAMQID(1, Sdataqid),
	Qeia1ctl=	STREAMQID(1, Sctlqid),
};

Dirtab sccdir[]={
	"eia0",		{Qeia0},	0,		0666,
	"eia0ctl",	{Qeia0ctl},	0,		0666,
	"eia1",		{Qeia1},	0,		0666,
	"eia1ctl",	{Qeia1ctl},	0,		0666,
};

#define	NSCC	(sizeof sccdir/sizeof(Dirtab))
Dirtab *sccdir;

/*
 *  allocate the queues if no one else has
 *  create 2 directory entries for each 'sccsetup' ports.
 *  allocate the queues if no one else has.
 */
void
sccreset(void)
{
	SCC *sp;

	for(sp = scc; sp < &scc[2]; sp++){
	int i;
	Dirtab *dp;

	sccdir = ialloc(2 * nscc * sizeof(Dirtab), 0);
	dp = sccdir;
	for(i = 0; i < nscc; i++){
		/* 2 directory entries per port */
		sprint(dp->name, "eia%d", i);
		dp->qid.path = STREAMQID(i, Sdataqid);
		dp->perm = 0666;
		dp++;
		sprint(dp->name, "eia%dctl", i);
		dp->qid.path = STREAMQID(i, Sctlqid);
		dp->perm = 0666;
		dp++;

		/* set up queues if a stream port */
		sp = scc[i];
		if(sp->nostream)
			continue;
		sp->iq = ialloc(sizeof(IOQ), 0);


@@ 578,21 604,21 @@ sccclone(Chan *c, Chan *nc)
int
sccwalk(Chan *c, char *name)
{
	return devwalk(c, name, sccdir, NSCC, devgen);
	return devwalk(c, name, sccdir, 2*nscc, devgen);
}

void
sccstat(Chan *c, char *dp)
{
	switch(c->qid.path){
	case Qeia0:
		streamstat(c, dp, "eia0");
		break;
	case Qeia1:
		streamstat(c, dp, "eia1");
	int i;

	i = STREAMID(c->qid.path);
	switch(STREAMTYPE(c->qid.path)){
	case Sdataqid:
		streamstat(c, dp, sccdir[2*i].name);
		break;
	default:
		devstat(c, dp, sccdir, NSCC, devgen);
		devstat(c, dp, sccdir, 2*nscc, devgen);
		break;
	}
}


@@ 602,26 628,13 @@ sccopen(Chan *c, int omode)
{
	SCC *sp;

	switch(c->qid.path){
	case Qeia0:
	case Qeia0ctl:
		sp = &scc[0];
		break;
	case Qeia1:
	case Qeia1ctl:
		sp = &scc[1];
		break;
	default:
		sp = 0;
		break;
	}

	if(sp && sp->nostream)
		errors("in use");

	if((c->qid.path & CHDIR) == 0)
	if(c->qid.path != CHDIR){
		sp = scc[STREAMID(c->qid.path)];
		if(sp->nostream)
			errors("in use");
		streamopen(c, &sccinfo);
	return devopen(c, omode, sccdir, NSCC, devgen);
	}
	return devopen(c, omode, sccdir, 2*nscc, devgen);
}

void


@@ 641,23 654,20 @@ sccclose(Chan *c)
long
sccread(Chan *c, void *buf, long n, ulong offset)
{
	SCC *sp = &scc[0]; int s;

	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, sccdir, NSCC, devgen);
	case Qeia1ctl:
		++sp;
		/* fall through */
	case Qeia0ctl:
		if(offset)
			return 0;
		s = splhi();
		*(uchar *)buf = *sp->ptr;
		splx(s);
		return 1;
	SCC *sp;
	char b[8];

	if(c->qid.path == CHDIR)
		return devdirread(c, buf, n, sccdir, 2*nscc, devgen);

	switch(STREAMTYPE(c->qid.path)){
	case Sdataqid:
		return streamread(c, buf, n);
	case Sctlqid:
		sprint(b, "%d", STREAMID(c->qid.path));
		return stringread(buf, n, b, offset);
	}
	return streamread(c, buf, n);
	errors("bad qid");
}

long

M port/portfns.h => port/portfns.h +1 -1
@@ 195,7 195,7 @@ Proc*	runproc(void);
void	savefpregs(FPsave*);
void	sccclock(void);
void	sccintr(void);
void	sccsetup(void*);
void	sccsetup(void*, ulong);
void	sccspecial(int, IOQ*, IOQ*, int);
void	sched(void);
void	schedinit(void);

M ss/io.h => ss/io.h +4 -6
@@ 2,8 2,8 @@
#define	EPROM		0xF6000000
#define	CLOCK		0xF3000000
#define	CLOCKFREQ	1000000		/* one microsecond increments */
#define	KMDUART0	0xF0000000	/* keyboard A, mouse B */
#define	KMDUART1	0xF1000000	/* serial ports */
#define	KMDUART		0xF0000000	/* keyboard A, mouse B */
#define	EIADUART	0xF1000000	/* serial ports */
#define	ETHER		0xF8C00000	/* RDP, RAP */
#define	EEPROM		0xF2000000
#define	INTRREG		0xF5000000	/* interrupt register, IO space */


@@ 21,7 21,5 @@ struct SCCdev
	uchar	dummy4;
};

/*
 *  crystal frequency for SCC
 */
#define SCCFREQ	10000000
#define KMFREQ	10000000	/* crystal frequency for kbd/mouse 8530 */
#define EIAFREQ	5000000		/* crystal frequency for serial port 8530 */

M ss/main.c => ss/main.c +4 -2
@@ 80,9 80,11 @@ ioinit(void)
{
	KMap *k;

	/* tell scc driver it's address */
	/* tell scc driver it's addresses */
	k = kmappa(KMDUART, PTEIO|PTENOCACHE);
	sccsetup((void*)(k->va));
	sccsetup((void*)(k->va), KMFREQ);
	k = kmappa(EIADUART, PTEIO|PTENOCACHE);
	sccsetup((void*)(k->va), EIAFREQ);

	/* scc port 0 is the keyboard */
	sccspecial(0, 0, &kbdq, 2400);

M ss/screen.c => ss/screen.c +0 -32
@@ 44,38 44,6 @@ screeninit(void)
}

void
screenputc(int c)
{
	char buf[2];
	int nx;

	if(c == '\n'){
		out.pos.x = MINX;
		out.pos.y += defont0.height;
		if(out.pos.y > gscreen.r.max.y-defont0.height)
			out.pos.y = gscreen.r.min.y;
		gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
		    Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height), 0);
	}else if(c == '\t'){
		out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
		if(out.pos.x >= gscreen.r.max.x)
			screenputc('\n');
	}else if(c == '\b'){
		if(out.pos.x >= out.bwid+MINX){
			out.pos.x -= out.bwid;
			screenputc(' ');
			out.pos.x -= out.bwid;
		}
	}else{
		if(out.pos.x >= gscreen.r.max.x-out.bwid)
			screenputc('\n');
		buf[0] = c&0x7F;
		buf[1] = 0;
		out.pos = gstring(&gscreen, out.pos, defont, buf, S);
	}
}

void
screenputs(char *s, int n)
{
	Rune r;

M ss/screen.h => ss/screen.h +0 -2
@@ 27,5 27,3 @@ extern Mouseinfo	mouse;
extern Cursorinfo	cursor;

extern void		mouseupdate(int);
#define kbitblt 	gbitblt
#define ubitblt 	gbitblt