~kris/9p

9hist

674af24da0ced3821a25d87329fc49f36b4b9b6e — David du Colombier 32 years ago 81e752e
Plan 9 from Bell Labs 1993-10-06
7 files changed, 529 insertions(+), 45 deletions(-)

M carrera/dat.h
M carrera/screen.c
M carrera/trap.c
M port/devcons.c
M port/devmnt.c
A port/devmouse.c
M port/error.h
M carrera/dat.h => carrera/dat.h +0 -17
@@ 1,6 1,5 @@
typedef struct Conf	Conf;
typedef struct FPsave	FPsave;
typedef struct Cycmsg	Cycmsg;
typedef struct KMap	KMap;
typedef struct Lance	Lance;
typedef struct Lancemem	Lancemem;


@@ 77,26 76,10 @@ struct	FPsave
struct PMMU
{
	int	pidonmach[MAXMACH];
	/*
	 * I/O point for hotrod interfaces.
	 * This is the easiest way to allocate
	 * them, but not the prettiest or most general.
	 */
	Cycmsg	*kcyc;
	Cycmsg	*ucyc;
	Cycmsg	*fcyc;
};

#include "../port/portdat.h"

struct Cycmsg
{
	ulong	cmd;
	ulong	param[5];
	Rendez	r;
	uchar	intr;			/* flag: interrupt has occurred */
};

/* First FOUR members offsets known by l.s */
struct Mach
{

M carrera/screen.c => carrera/screen.c +1 -17
@@ 112,22 112,6 @@ GBitmap	vgascreen =
	0
};

uchar bdata[] =
{
	0xC0,
};

GBitmap bgrnd =
{
	(ulong*)bdata,
	0,
	4,
	3,
	{ 0, 0, 1, 1 },
	{ 0, 0, 1, 1 },
	0
};

static Rectangle window;
static Point cursor;
static int h, w;


@@ 140,7 124,7 @@ static int isscroll;
void
screenwin(void)
{
	gtexture(&gscreen, gscreen.r, &bgrnd, S);
	memset(gscreen.base, 0xC0, gscreen.width*sizeof(ulong)*Dy(gscreen.r));
	w = defont0.info[' '].width;
	h = defont0.height;
	defont = &defont0;	

M carrera/trap.c => carrera/trap.c +1 -1
@@ 471,7 471,7 @@ notify(Ureg *ur)
	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */
	up->svr1 = ur->r1;			/* save away r1 */
	ur->r1 = (ulong)up->ureg;		/* arg 1 is ureg* */
	*(ulong*)(sp+1*BY2WD) = (ulong)u->ureg;	/* arg 1 0(FP) is ureg* */
	*(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;	/* arg 1 0(FP) is ureg* */
	*(ulong*)(sp+0*BY2WD) = 0;		/* arg 0 is pc */
	ur->usp = sp;
	ur->pc = (ulong)up->notify;

M port/devcons.c => port/devcons.c +0 -3
@@ 185,9 185,6 @@ echo(Rune r, char *buf, int n)
			xsummary();
			ixsummary();
			break;
		case 'b':
			bitdebug();
			break;
		case 'd':
			consdebug();
			return;

M port/devmnt.c => port/devmnt.c +6 -2
@@ 635,8 635,9 @@ mountio(Mnt *m, Mntrpc *r)
void
mntrpcread(Mnt *m, Mntrpc *r)
{
	int n;
	int n, zrd;

	zrd = 0;
	for(;;) {
		if(waserror()) {
			if(mntflush(m, r) == 0) {


@@ 650,8 651,11 @@ mntrpcread(Mnt *m, Mntrpc *r)
		r->reply.tag = 0;
		n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0);
		poperror();
		if(n == 0)
		if(n == 0) {
			if(++zrd > 3)
				error(Ehungup);
			continue;
		}

		if(convM2S(r->rpc, &r->reply, n) != 0)
			return;

A port/devmouse.c => port/devmouse.c +520 -0
@@ 0,0 1,520 @@
#include	"u.h"
#include	"../port/lib.h"
#include	<libg.h>
#include	<gnot.h>
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

#include	"devtab.h"

/*
 * Some monochrome screens are reversed from what we like:
 * We want 0's bright and 1's dark.
 * Indexed by an Fcode, these compensate for the source bitmap being wrong
 * (exchange S rows) and destination (exchange D columns and invert result)
 */
int flipS[] = {
	0x0, 0x4, 0x8, 0xC, 0x1, 0x5, 0x9, 0xD,
	0x2, 0x6, 0xA, 0xE, 0x3, 0x7, 0xB, 0xF
};

int flipD[] = {
	0xF, 0xD, 0xE, 0xC, 0x7, 0x5, 0x6, 0x4,
	0xB, 0x9, 0xA, 0x8, 0x3, 0x1, 0x2, 0x0, 
};

int flipping;	/* are flip tables being used to transform Fcodes? */

typedef struct Mouseinfo	Mouseinfo;
typedef struct Cursorinfo	Cursorinfo;

struct Mouseinfo
{
	/*
	 * First three fields are known in some l.s's
	 */
	int	dx;
	int	dy;
	int	track;		/* l.s has updated dx & dy */
	Mouse;
	int	redraw;		/* update cursor on screen */
	ulong	counter;	/* increments every update */
	ulong	lastcounter;	/* value when /dev/mouse read */
	Rendez	r;
	Ref;
	QLock;
	int	open;
};

struct Cursorinfo
{
	Cursor;
	Lock;
	int	visible;	/* on screen */
	int	disable;	/* from being used */
	Rectangle r;		/* location */
};

Mouseinfo	mouse;
Cursorinfo	cursor;
int		mouseshifted;
int		mousetype;
int		hwcurs;

Cursor	arrow =
{
	{-1, -1},
	{0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00,
	 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0,
	 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE,
	 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08,
	},
	{0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00,
	 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0,
	 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C,
	 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00,
	}
};

ulong setbits[16];
GBitmap	set =
{
	setbits,
	0,
	1,
	0,
	{0, 0, 16, 16},
	{0, 0, 16, 16}
};

ulong clrbits[16];
GBitmap	clr =
{
	clrbits,
	0,
	1,
	0,
	{0, 0, 16, 16},
	{0, 0, 16, 16}
};

ulong cursorbackbits[16*4];
GBitmap cursorback =
{
	cursorbackbits,
	0,
	1,
	0,
	{0, 0, 16, 16},
	{0, 0, 16, 16}
};

void	Cursortocursor(Cursor*);
int	mousechanged(void*);

enum{
	Qdir,
	Qmouse,
	Qmousectl,
};

Dirtab mousedir[]={
	"mouse",	{Qmouse},	0,			0666,
	"mousectl",	{Qmousectl},	0,			0220,
};

#define	NMOUSE	(sizeof(mousedir)/sizeof(Dirtab))

extern	GBitmap	gscreen;

void
mousereset(void)
{
	ulong r;

	if(!conf.monitor)
		return;

	getcolor(0, &r, &r, &r);
	if(r == 0)
		flipping = 1;
	flipping = 0;	/* howard, why is this necessary to get a black arrow on carrera? */
	Cursortocursor(&arrow);
}

void
mouseinit(void)
{
	if(!conf.monitor)
		return;
	if(gscreen.ldepth > 3)
		cursorback.ldepth = 0;
	else{
		cursorback.ldepth = gscreen.ldepth;
		cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5;
	}
	cursoron(1);
}

Chan*
mouseattach(char *spec)
{
	if(!conf.monitor)
		error(Egreg);
	return devattach('m', spec);
}

Chan*
mouseclone(Chan *c, Chan *nc)
{
	nc = devclone(c, nc);
	if(c->qid.path != CHDIR)
		incref(&mouse);
	return nc;
}

int
mousewalk(Chan *c, char *name)
{
	return devwalk(c, name, mousedir, NMOUSE, devgen);
}

void
mousestat(Chan *c, char *db)
{
	devstat(c, db, mousedir, NMOUSE, devgen);
}

Chan*
mouseopen(Chan *c, int omode)
{
	switch(c->qid.path){
	case CHDIR:
		if(omode != OREAD)
			error(Eperm);
		break;
	case Qmouse:
		lock(&mouse);
		if(mouse.open){
			unlock(&mouse);
			error(Einuse);
		}
		mouse.open = 1;
		mouse.ref++;
		unlock(&mouse);
		break;
	default:
		incref(&mouse);
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

void
mousecreate(Chan *c, char *name, int omode, ulong perm)
{
	if(!conf.monitor)
		error(Egreg);
	USED(c, name, omode, perm);
	error(Eperm);
}

void
mouseremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
mousewstat(Chan *c, char *db)
{
	USED(c, db);
	error(Eperm);
}

void
mouseclose(Chan *c)
{
	if(c->qid.path!=CHDIR && (c->flag&COPEN)){
		lock(&mouse);
		if(c->qid.path == Qmouse)
			mouse.open = 0;
		unlock(&mouse);
	}
}

long
mouseread(Chan *c, void *va, long n, ulong offset)
{
	uchar *p;

	USED(offset);
	if(c->qid.path & CHDIR)
		return devdirread(c, va, n, mousedir, NMOUSE, devgen);

	if(c->qid.path == Qmouse){
		/*
		 * mouse:
		 *	'm'		1
		 *	buttons		1
		 * 	point		8
		 * 	msec		4
		 */
		if(n < 14)
			error(Eshort);
		while(mousechanged(0) == 0)
			sleep(&mouse.r, mousechanged, 0);
		lock(&cursor);
		p = va;
		p[0] = 'm';
		p[1] = mouse.buttons;
		BPLONG(p+2, mouse.xy.x);
		BPLONG(p+6, mouse.xy.y);
		BPLONG(p+10, TK2MS(MACHP(0)->ticks));
		mouse.lastcounter = mouse.counter;
		unlock(&cursor);
		return 14;
	}
	return 0;
}

long
mousewrite(Chan *c, void *va, long n, ulong offset)
{
	uchar *p;
	Point pt;
	char buf[64];

	USED(offset);

	switch(c->qid.path){
	case CHDIR:
		error(Eisdir);

	case Qmousectl:
		if(n >= sizeof(buf))
			n = sizeof(buf)-1;
		strncpy(buf, va, n);
		buf[n] = 0;
		mousectl(buf);
		return n;

	case Qmouse:
		if(n != 9)
			error(Eshort);
		qlock(&mouse);
		p = va;
		pt.x = BGLONG(p+1);
		pt.y = BGLONG(p+5);
		if(ptinrect(pt, gscreen.r)){
			mouse.xy = pt;
			mouse.redraw = 1;
			mouse.track = 1;
			mouseclock();
		}
		qunlock(&mouse);
		return n;
	}

	error(Egreg);
	return -1;
}

void
Cursortocursor(Cursor *c)
{
	int i;
	uchar *p;

	lock(&cursor);
	memmove(&cursor, c, sizeof(Cursor));
	for(i=0; i<16; i++){
		p = (uchar*)&setbits[i];
		*p = c->set[2*i];
		*(p+1) = c->set[2*i+1];
		p = (uchar*)&clrbits[i];
		*p = c->clr[2*i];
		*(p+1) = c->clr[2*i+1];
	}
	if(hwcurs)
		hwcursset(set.base, clr.base, cursor.offset.x, cursor.offset.y);
	unlock(&cursor);
}

void
cursoron(int dolock)
{
	if(cursor.disable)
		return;
	if(dolock)
		lock(&cursor);
	if(cursor.visible++ == 0){
		if(hwcurs)
			hwcursmove(mouse.xy.x, mouse.xy.y);
		else {
			cursor.r.min = mouse.xy;
			cursor.r.max = add(mouse.xy, Pt(16, 16));
			cursor.r = raddp(cursor.r, cursor.offset);
			gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S);
			gbitblt(&gscreen, cursor.r.min,
				&clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S);
			gbitblt(&gscreen, cursor.r.min,
				&set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D);
			mbbrect(cursor.r);
		}
	}
	if(dolock)
		unlock(&cursor);
}

void
cursoroff(int dolock)
{
	if(cursor.disable)
		return;
	if(dolock)
		lock(&cursor);
	if(--cursor.visible == 0) {
		if(!hwcurs) {
			gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S);
			mbbrect(cursor.r);
			mousescreenupdate();
		}
	}
	if(dolock)
		unlock(&cursor);
}

/*
 *  called by the clock routine to redraw the cursor
 */
void
mouseclock(void)
{
	if(mouse.track){
		mousetrack(mouse.buttons, mouse.dx, mouse.dy);
		mouse.track = 0;
		mouse.dx = 0;
		mouse.dy = 0;
	}
	if(mouse.redraw && canlock(&cursor)){
		mouse.redraw = 0;
		cursoroff(0);
		cursoron(0);
		mousescreenupdate();
		unlock(&cursor);
	}
}

/*
 *  called at interrupt level to update the structure and
 *  awaken any waiting procs.
 */
void
mousetrack(int b, int dx, int dy)
{
	int x, y;

	x = mouse.xy.x + dx;
	if(x < gscreen.r.min.x)
		x = gscreen.r.min.x;
	if(x >= gscreen.r.max.x)
		x = gscreen.r.max.x;
	y = mouse.xy.y + dy;
	if(y < gscreen.r.min.y)
		y = gscreen.r.min.y;
	if(y >= gscreen.r.max.y)
		y = gscreen.r.max.y;
	mouse.counter++;
	mouse.xy = Pt(x, y);
	mouse.buttons = b;
	mouse.redraw = 1;
	wakeup(&mouse.r);
}

/*
 *  microsoft 3 button, 7 bit bytes
 *
 *	byte 0 -	1  L  R Y7 Y6 X7 X6
 *	byte 1 -	0 X5 X4 X3 X2 X1 X0
 *	byte 2 -	0 Y5 Y4 Y3 Y2 Y1 Y0
 *	byte 3 -	0  M  x  x  x  x  x	(optional)
 *
 *  shift & right button is the same as middle button (for 2 button mice)
 */
int
m3mouseputc(IOQ *q, int c)
{
	static uchar msg[3];
	static int nb;
	static int middle;
	static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 };
	short x;
	int dx, dy, newbuttons;

	USED(q);
	/* 
	 *  check bit 6 for consistency
	 */
	if(nb==0){
		if((c&0x40) == 0){
			/* an extra byte gets sent for the middle button */
			middle = (c&0x20) ? 2 : 0;
			newbuttons = (mouse.buttons & ~2) | middle;
			mousetrack(newbuttons, 0, 0);
			return 0;
		}
	}
	msg[nb] = c;
	if(++nb == 3){
		nb = 0;
		newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)];
		x = (msg[0]&0x3)<<14;
		dx = (x>>8) | msg[1];
		x = (msg[0]&0xc)<<12;
		dy = (x>>8) | msg[2];
		mousetrack(newbuttons, dx, dy);
	}
	return 0;
}

/*
 *  Logitech 5 byte packed binary mouse format, 8 bit bytes
 *
 *  shift & right button is the same as middle button (for 2 button mice)
 */
int
mouseputc(IOQ *q, int c)
{
	static short msg[5];
	static int nb;
	static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 5, 3, 7};
	int dx, dy, newbuttons;

	USED(q);
	if((c&0xF0) == 0x80)
		nb=0;
	msg[nb] = c;
	if(c & 0x80)
		msg[nb] |= ~0xFF;	/* sign extend */
	if(++nb == 5){
		newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)];
		dx = msg[1]+msg[3];
		dy = -(msg[2]+msg[4]);
		mousetrack(newbuttons, dx, dy);
		nb = 0;
	}
	return 0;
}

int
mousechanged(void *m)
{
	USED(m);
	return mouse.lastcounter - mouse.counter;
}

M port/error.h => port/error.h +1 -5
@@ 18,11 18,6 @@ extern char Einuse[];		/* device or object already in use */
extern char Eio[];		/* i/o error */
extern char Etoobig[];		/* read or write too large */
extern char Etoosmall[];	/* read or write too small */
extern char Ebadblt[];		/* bad bitblt or bitmap request */
extern char Ebadbitmap[];	/* unallocated bitmap */
extern char Enobitmap[];	/* out of bitmap descriptors */
extern char Enobitstore[];	/* out of bitmap storage */
extern char Ebadfont[];		/* unallocated font */
extern char Enetaddr[];		/* bad network address */
extern char Emsgsize[];		/* message is too big for protocol */
extern char Enetbusy[];		/* network device is busy or allocated */


@@ 55,4 50,5 @@ extern char Esfnotcached[];	/* subfont not cached */
extern char Esoverlap[];	/* segments overlap */
extern char Emouseset[];	/* mouse type already set */
extern char Erecover[];		/* failed to recover fd */
extern char Eshort[];		/* i/o count too small */
extern char Egreg[];		/* coherency problem */