~kris/9p

9hist

ad8a1de3448aaf3172e0d64565c77904177cd885 — David du Colombier 32 years ago 5d86b5b
Plan 9 from Bell Labs 1994-04-12
5 files changed, 377 insertions(+), 529 deletions(-)

M carrera/screen.c
M pc/devvga.c
M pc/l.s
M port/devmouse.c
M port/portfns.h
M carrera/screen.c => carrera/screen.c +31 -1
@@ 503,11 503,13 @@ extern	cursorunlock(void);
 * gscreen.ldepth is known to be >= 3
 */
void
screenload(Rectangle r, uchar *data, int tl, int l)
screenload(Rectangle r, uchar *data, int tl, int l, int dolock)
{
	uchar *q;
	int y;

	USED(dolock);

	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;



@@ 520,3 522,31 @@ screenload(Rectangle r, uchar *data, int tl, int l)
	}
	unlock(&screenlock);
}

/*
 * get a tile from screen memory.
 * tile is at location r, first pixel in *data. 
 * tl is length of scan line to insert,
 * l is amount to advance data after each scan line.
 * gscreen.ldepth is known to be >= 3
 */
void
screenunload(Rectangle r, uchar *data, int tl, int l, int dolock)
{
	uchar *q;
	int y;

	USED(dolock);

	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;

	lock(&screenlock);
	q = gbaddr(&gscreen, r.min);
	for(y=r.min.y; y<r.max.y; y++){
		memmove(data, q, tl);
		q += gscreen.width*sizeof(ulong);
		data += l;
	}
	unlock(&screenlock);
}

M pc/devvga.c => pc/devvga.c +316 -395
@@ 31,6 31,12 @@ enum
	CM=		0x3C9,		/* color map data reg */
};

enum
{
	Footshift=	16,
	Footprint=	1<<Footshift,
};

/* imported */
extern	GSubfont defont0;
extern Cursor arrow;


@@ 41,16 47,12 @@ GBitmap	gscreen;

/* vga screen */
static	Lock	screenlock;
static	GBitmap	vgascreen;
static	ulong	colormap[256][3];
static	Rectangle mbb;
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000};

/* cga screen */
static	int	cga = 1;		/* true if in cga mode */

/* system window */
static	int	isscroll;
static	Rectangle window;
static	int	h, w;
static	Point	cursor;


@@ 175,17 177,12 @@ static void	srout(int, int);
static void	grout(int, int);
static void	arout(int, int);
static void	crout(int, int);
static void	setmode(VGAmode*);
static void	getmode(VGAmode*);
static void	printmode(VGAmode*);
static void	cgascreenputc(int);
static void	cgascreenputs(char*, int);
static void	screenputc(char*);
static void	scroll(void);
static ulong	x3to32(uchar);
static ulong	x6to32(uchar);
void	screenupdate(void);
void	mbbrect(Rectangle);

/*
 *  vga device


@@ 399,6 396,7 @@ screeninit(void)
	l = defont->bits->base;
	for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++)
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);

	/*
	 *  start in CGA mode
	 */


@@ 407,60 405,69 @@ screeninit(void)
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
}

static void
setmode(VGAmode *v)
{
	int i;

	/* turn screen off (to avoid damage) */
	srout(1, 0x21);

	for(i = 0; i < sizeof(v->general); i++)
		genout(i, v->general[i]);

	for(i = 0; i < sizeof(v->sequencer); i++)
		if(i == 1)
			srout(i, v->sequencer[i]|0x20);		/* avoid enabling screen */
		else
			srout(i, v->sequencer[i]);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);

	for(i = 0; i < sizeof(v->graphics); i++)
		grout(i, v->graphics[i]);

	for(i = 0; i < sizeof(v->attribute); i++)
		arout(i, v->attribute[i]);

	/* turn screen on */
	srout(1, v->sequencer[1]);
}

/*
 *  reconfigure screen shape
 */
static void
setscreen(int maxx, int maxy, int ldepth)
{
	int len, vgamaxy, width, i, x, s;
	ulong *p, *oldp;
	int i, x;

	if(ldepth == 3)
		setmode(&mode13);
	else
	switch(ldepth){
	case 0:
		setmode(&mode12);

	/* allocate a new soft bitmap area */
	width = (maxx*(1<<ldepth))/32;
	len = width * BY2WD * maxy;
	p = xalloc(len);
	if(p == 0)
		error(Enobitstore);
	memset(p, 0xff, len);
	mbb = NULLMBB;

	/*
	 *  zero hard screen and setup a bitmap for the new size
	 */
	if(ldepth == 3)
		vgascreen.ldepth = 3;
	else
		vgascreen.ldepth = 0;
	vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32;
	if(maxy > (64*1024)/(vgascreen.width*BY2WD))
		vgamaxy = (64*1024)/(vgascreen.width*BY2WD);
	else
		vgamaxy = maxy;
	vgascreen.base = (void*)SCREENMEM;
	vgascreen.r.min = Pt(0, 0);
	vgascreen.r.max = Pt(maxx, vgamaxy);
	vgascreen.clipr = vgascreen.r;
		break;
	case 3:
		setmode(&mode13);
		break;
	default:
		error(Ebadarg);
	}

	/*
	 *  setup new soft screen, free memory for old screen
	 *  setup a bitmap for the new size
	 */
	oldp = gscreen.base;
	s = splhi();
	gscreen.ldepth = ldepth;
	gscreen.width = width;
	gscreen.width = (maxx*(1<<gscreen.ldepth))/32;
	gscreen.base = (void*)SCREENMEM;
	gscreen.r.min = Pt(0, 0);
	gscreen.r.max = Pt(maxx, maxy);
	gscreen.clipr = gscreen.r;
	gscreen.base = p;
	splx(s);
	if(oldp)
		xfree(oldp);
	for(i = 0; i < gscreen.width*BY2WD*maxy; i += Footprint){
		vgacard->setpage(i>>Footshift);
		memset(gscreen.base, 0, Footprint);
	}

	/*
	 *  default color map


@@ 482,54 489,112 @@ setscreen(int maxx, int maxy, int ldepth)
	cga = 0;

	/*
	 * display white window
	 */
	mbb = gscreen.r;
	screenupdate();

	/*
	 *  set up inset system window
	 */
	h = defont0.height;
	w = defont0.info[' '].width;

	window.min = Pt(50, 50);
	window.max = add(window.min, Pt(10+w*64, 10+h*24));
	window.max = add(window.min, Pt(10+w*64, Footprint/(BY2WD*gscreen.width)));

	vgacard->setpage(0);
	gbitblt(&gscreen, window.min, &gscreen, window, Zero);
	window = inset(window, 5);
	cursor = window.min;
	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
	hwcurs = 0;
}

	mbb = gscreen.r;
	screenupdate();
/*
 *  Load a byte into screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
static int
byteload(uchar *q, uchar *data, int m, int *page, uchar *e)
{
	int pg;
	int diff;

	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}
	*q ^= (*data^*q) & m;
	return diff;
}

/*
 *   paste tile into soft screen.
 *  Load adjacent bytes into a screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
static int
lineload(uchar *q, uchar *data, int len, int *page, uchar *e)
{
	int rem, pg;
	int diff;

	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}

	rem = e - q;

	if(rem < len){
		memmove(q, data, rem);
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
		memmove(q+rem, data+rem, len-rem);
	} else
		memmove(q, data, len);

	return diff;
}

/*
 *   paste tile into hard screen.
 *   tile is at location r, first pixel in *data.  tl is length of scan line to insert,
 *   l is amount to advance data after each scan line.
 */
void
screenload(Rectangle r, uchar *data, int tl, int l)
screenload(Rectangle r, uchar *data, int tl, int l, int dolock)
{
	int y, lpart, rpart, mx, m, mr;
	uchar *q;
	int y, lpart, rpart, mx, m, mr, page, sw;
	ulong off;
	uchar *q, *e;
	extern void cursorlock(Rectangle);
	extern void cursorunlock(void);

	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;

	if(dolock)
		cursorlock(r);
	lock(&screenlock);
	cursorlock(r);
	screenupdate();

	q = gbaddr(&gscreen, r.min);
	mx = 7>>gscreen.ldepth;
	lpart = (r.min.x & mx) << gscreen.ldepth;
	rpart = (r.max.x & mx) << gscreen.ldepth;
	m = 0xFF >> lpart;
	mr = 0xFF ^ (0xFF >> rpart);

	off = q - (uchar*)gscreen.base;
	page = off>>Footshift;
	vgacard->setpage(page);
	q = ((uchar*)gscreen.base) + (off&(Footprint-1));

	sw = gscreen.width*sizeof(ulong);
	e = ((uchar*)gscreen.base) + Footprint;

	/* may need to do bit insertion on edges */
	if(tl <= 0){
		;


@@ 537,139 602,228 @@ screenload(Rectangle r, uchar *data, int tl, int l)
		if(rpart)
			m &= mr;
		for(y=r.min.y; y<r.max.y; y++){
			*q ^= (*data^*q) & m;
			q += gscreen.width*sizeof(ulong);
			if(q < e)
				*q ^= (*data^*q) & m;
			else
				q += byteload(q, data, m, &page, e);
			q += sw;
			data += l;
		}
	}else if(lpart==0 && rpart==0){	/* easy case */
		for(y=r.min.y; y<r.max.y; y++){
			memmove(q, data, tl);
			q += gscreen.width*sizeof(ulong);
			if(q + tl <= e)
				memmove(q, data, tl);
			else
				q += lineload(q, data, tl, &page, e);
			q += sw;
			data += l;
		}
	}else if(rpart==0){
		for(y=r.min.y; y<r.max.y; y++){
			*q ^= (*data^*q) & m;
			memmove(q+1, data+1, tl-1);
			q += gscreen.width*sizeof(ulong);
			if(q + tl <= e){
				*q ^= (*data^*q) & m;
				memmove(q+1, data+1, tl-1);
			} else {
				q += byteload(q, data, m, &page, e);
				q += lineload(q+1, data+1, tl-1, &page, e);
			}
			q += sw;
			data += l;
		}
	}else if(lpart == 0){
		for(y=r.min.y; y<r.max.y; y++){
			memmove(q, data, tl-1);
			q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			q += gscreen.width*sizeof(ulong);
			if(q + tl <= e){
				memmove(q, data, tl-1);
				q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			} else {	/* new page */
				q += lineload(q, data, tl-1, &page, e);
				q += byteload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
			data += l;
		}
	}else for(y=r.min.y; y<r.max.y; y++){
			*q ^= (*data^*q) & m;
			if(tl > 2)
				memmove(q+1, data+1, tl-2);
			q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			q += gscreen.width*sizeof(ulong);
			if(q + tl <= e){
				*q ^= (*data^*q) & m;
				if(tl > 2)
					memmove(q+1, data+1, tl-2);
				q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			} else {	/* new page */
				q += byteload(q, data, m, &page, e);
				if(tl > 2)
					q += lineload(q+1, data+1, tl-2, &page, e);
				q += byteload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
			data += l;
		}
	mbbrect(r);
	screenupdate();
	cursorunlock();
	screenupdate();

	unlock(&screenlock);
	if(dolock)
		cursorunlock();
}

/*
 *  copy little endian soft screen to big endian hard screen
 *  Get a byte from screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
void
screenupdate(void)
static int
byteunload(uchar *q, uchar *data, int m, int *page, uchar *e)
{
	uchar *sp, *hp, *edisp;
	int y, len, incs, inch, off, page;
	Rectangle r;
	void* (*f)(void*, void*, long);
	int pg;
	int diff;

	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}
	*data ^= (*q^*data) & m;
	return diff;
}

	r = mbb;
	mbb = NULLMBB;
/*
 *  Get a vector of bytes from screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
static int
lineunload(uchar *q, uchar *data, int len, int *page, uchar *e)
{
	int rem, pg;
	int diff;

	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}

	if(Dy(r) < 0)
		return;
	rem = e - q;

	if(r.min.x < 0)
		r.min.x = 0;
	if(r.min.y < 0)
		r.min.y = 0;
	if(r.max.x > gscreen.r.max.x)
		r.max.x = gscreen.r.max.x;
	if(r.max.y > gscreen.r.max.y)
		r.max.y = gscreen.r.max.y;
	if(rem < len){
		memmove(data, q, rem);
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
		memmove(data+rem, q+rem, len-rem);
	} else
		memmove(data, q, len);

	incs = gscreen.width * BY2WD;
	inch = vgascreen.width * BY2WD;
	return diff;
}

	switch(gscreen.ldepth){
	case 0:
		r.min.x &= ~15;		/* 16 pixel alignment for l0update() */
		f = memmove;
		len = (r.max.x + 7)/8 - r.min.x/8;
		if(len & 1)
			len++;		/* 16 bit alignment for l0update() */
		break;
	case 1:
		r.min.x &= ~15;		/* 8 pixel alignment for l1update() */
		f = l1update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		if(len & 1)
			len++;		/* 8 pixel alignment for l1update() */
		break;
	case 2:
		r.min.x &= ~7;		/* 8 pixel alignment for l2update() */
		f = l2update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		break;
	case 3:
		f = memmove;
		r.min.x &= ~3;
		r.max.x = ROUND(r.max.x, 4);
		len = r.max.x - r.min.x;
		break;
	default:
		return;
	}
	if(len < 1)
/*
 *   paste tile into hard screen.
 *   tile is at location r, first pixel in *data.  tl is length of scan line to insert,
 *   l is amount to advance data after each scan line.
 */
void
screenunload(Rectangle r, uchar *data, int tl, int l, int dolock)
{
	int y, lpart, rpart, mx, m, mr, page, sw;
	ulong off;
	uchar *q, *e;
	extern void cursorlock(Rectangle);
	extern void cursorunlock(void);

	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;

	off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth));
	page = off>>16;
	off &= (1<<16)-1;
	hp = ((uchar*)vgascreen.base) + off;
	off = r.min.y * gscreen.width * BY2WD
		+ (r.min.x>>(3 - gscreen.ldepth));
	sp = ((uchar*)gscreen.base) + off;
	if(dolock)
		cursorlock(r);
	lock(&screenlock);

	edisp = ((uchar*)vgascreen.base) + 64*1024;
	q = gbaddr(&gscreen, r.min);
	mx = 7>>gscreen.ldepth;
	lpart = (r.min.x & mx) << gscreen.ldepth;
	rpart = (r.max.x & mx) << gscreen.ldepth;
	m = 0xFF >> lpart;
	mr = 0xFF ^ (0xFF >> rpart);

	off = q - (uchar*)gscreen.base;
	page = off>>Footshift;
	vgacard->setpage(page);
	for(y = r.min.y; y < r.max.y; y++){
		if(hp + inch < edisp){
			f(hp, sp, len);
			sp += incs;
			hp += inch;
		} else {
			off = edisp - hp;
			if(off <= len){
				if(off > 0)
					f(hp, sp, off);
				vgacard->setpage(++page);
				if(len - off > 0)
					f(vgascreen.base, sp+off, len - off);
	q = ((uchar*)gscreen.base) + (off&(Footprint-1));

	sw = gscreen.width*sizeof(ulong);
	e = ((uchar*)gscreen.base) + Footprint;

	/* may need to do bit insertion on edges */
	if(tl <= 0){
		;
	}else if(tl == 1){	/* all in one byte */
		if(rpart)
			m &= mr;
		for(y=r.min.y; y<r.max.y; y++){
			if(q < e)
				*data ^= (*q^*data) & m;
			else
				q += byteunload(q, data, m, &page, e);
			q += sw;
			data += l;
		}
	}else if(lpart==0 && rpart==0){	/* easy case */
		for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e)
				memmove(data, q, tl);
			else
				q += lineunload(q, data, tl, &page, e);
			q += sw;
			data += l;
		}
	}else if(rpart==0){
		for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e){
				*data ^= (*q^*data) & m;
				memmove(data+1, q+1, tl-1);
			} else {
				f(hp, sp, len);
				vgacard->setpage(++page);
				q += byteunload(q, data, m, &page, e);
				q += lineunload(q+1, data+1, tl-1, &page, e);
			}
			sp += incs;
			hp += inch - 64*1024;
			q += sw;
			data += l;
		}
	}
	}else if(lpart == 0){
		for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e){
				memmove(data, q, tl-1);
				data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
			} else {	/* new page */
				q += lineunload(q, data, tl-1, &page, e);
				q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
			data += l;
		}
	}else for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e){
				*data ^= (*q^*data) & m;
				if(tl > 2)
					memmove(data+1, q+1, tl-2);
				data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
			} else {	/* new page */
				q += byteunload(q, data, m, &page, e);
				if(tl > 2)
					q += lineunload(q+1, data+1, tl-2, &page, e);
				q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
			data += l;
		}

	unlock(&screenlock);
	if(dolock)
		cursorunlock();
}

/*
 *  write a string to the screen
 */
void
screenputs(char *s, int n)
{


@@ 702,12 856,7 @@ screenputs(char *s, int n)
		s += i;
		screenputc(buf);
	}
	if(isscroll) {
		mbb = window;
		isscroll = 0;
	}

	screenupdate();
	unlock(&screenlock);
}



@@ 760,91 909,6 @@ crout(int reg, int val)
	outb(CR, val);
}

static void
setmode(VGAmode *v)
{
	int i;

	/* turn screen off (to avoid damage) */
	srout(1, 0x21);

	for(i = 0; i < sizeof(v->general); i++)
		genout(i, v->general[i]);

	for(i = 0; i < sizeof(v->sequencer); i++)
		if(i == 1)
			srout(i, v->sequencer[i]|0x20);		/* avoid enabling screen */
		else
			srout(i, v->sequencer[i]);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);

	for(i = 0; i < sizeof(v->graphics); i++)
		grout(i, v->graphics[i]);

	for(i = 0; i < sizeof(v->attribute); i++)
		arout(i, v->attribute[i]);

	/* turn screen on */
	srout(1, v->sequencer[1]);
}

static void
getmode(VGAmode *v)
{
	int i;
	v->general[0] = inb(0x3cc);
	v->general[1] = inb(0x3ca);
	for(i = 0; i < sizeof(v->sequencer); i++) {
		outb(SRX, i);
		v->sequencer[i] = inb(SR);
	}
	for(i = 0; i < sizeof(v->crt); i++) {
		outb(CRX, i);
		v->crt[i] = inb(CR);
	}
	for(i = 0; i < sizeof(v->graphics); i++) {
		outb(GRX, i);
		v->graphics[i] = inb(GR);
	}
	for(i = 0; i < sizeof(v->attribute); i++) {
		inb(0x3DA);
		outb(ARW, i | 0x20);
		v->attribute[i] = inb(ARR);
	}
}

static void
printmode(VGAmode *v)
{
	int i;
	print("g %2.2x %2x\n",
		v->general[0], v->general[1]);

	print("s ");
	for(i = 0; i < sizeof(v->sequencer); i++) {
		print(" %2.2x", v->sequencer[i]);
	}

	print("\nc ");
	for(i = 0; i < sizeof(v->crt); i++) {
		print(" %2.2x", v->crt[i]);
	}

	print("\ng ");
	for(i = 0; i < sizeof(v->graphics); i++) {
		print(" %2.2x", v->graphics[i]);
	}

	print("\na ");
	for(i = 0; i < sizeof(v->attribute); i++) {
		print(" %2.2x", v->attribute[i]);
	}
	print("\n");
}

/*
 *  expand 3 and 6 bits of color to 32
 */


@@ 884,35 948,6 @@ hwcursmove(int x, int y)
}

/*
 *  collect changes to the 'soft' screen
 */
void
mbbrect(Rectangle r)
{
	if (r.min.x < mbb.min.x)
		mbb.min.x = r.min.x;
	if (r.min.y < mbb.min.y)
		mbb.min.y = r.min.y;
	if (r.max.x > mbb.max.x)
		mbb.max.x = r.max.x;
	if (r.max.y > mbb.max.y)
		mbb.max.y = r.max.y;
}

void
mbbpt(Point p)
{
	if (p.x < mbb.min.x)
		mbb.min.x = p.x;
	if (p.y < mbb.min.y)
		mbb.min.y = p.y;
	if (p.x >= mbb.max.x)
		mbb.max.x = p.x+1;
	if (p.y >= mbb.max.y)
		mbb.max.y = p.y+1;
}

/*
 *  paging routines for different cards
 */
static void


@@ 975,7 1010,7 @@ s3page(int page)
	/*
	 * I don't understand why these are different.
	 */
	if(vgascreen.ldepth == 3){
	if(gscreen.ldepth == 3){
		/*
		 * The S3 registers need to be unlocked for this.
		 * Let's hope they are already:


@@ 994,16 1029,6 @@ s3page(int page)
		crout(0x35, (page<<2) & 0x0C);
}

void
mousescreenupdate(void)
{
	if(canlock(&screenlock) == 0)
		return;

	screenupdate();
	unlock(&screenlock);
}

static void
cgascreenputc(int c)
{


@@ 1047,13 1072,12 @@ scroll(void)
	int o;
	Rectangle r;

	o = 5*h;
	r = Rpt(Pt(window.min.x, window.min.y+o), window.max);
	vgacard->setpage(0);
	r = Rpt(Pt(window.min.x, window.max.y+h), window.max);
	gbitblt(&gscreen, window.min, &gscreen, r, S);
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
	gbitblt(&gscreen, r.min, &gscreen, r, Zero);
	cursor.y -= o;
	isscroll = 1;
}

static void


@@ 1061,7 1085,6 @@ screenputc(char *buf)
{
	int pos;

	mbbpt(cursor);
	switch(buf[0]) {
	case '\n':
		if(cursor.y+h >= window.max.y)


@@ 1087,7 1110,6 @@ screenputc(char *buf)

		cursor = gsubfstring(&gscreen, cursor, &defont0, buf, S);
	}
	mbbpt(Pt(cursor.x, cursor.y+h));
}

int


@@ 1144,104 1166,3 @@ setcolor(ulong p, ulong r, ulong g, ulong b)
	unlock(&screenlock);
	return ~0;
}

/*
 *  Table for separating bits in a ldepth 1 bitmap.
 *  This aids in coverting a big-endian ldepth 1 bitmap into the
 *  2 big-endian ldepth 0 bitmaps used for the VGA bit planes.
 *
 *	if the bits in uchar x are labeled
 *		76543210
 *	then l1septab[x] yields a ulong with bits
 *		________7531________6420
 *	where _ represents a bit whose value is 0.
 *
 *  This table is used by l1update() in l.s.  l1update is implemented
 *  in assembler for speed.
 *
 */
ulong l1septab[] = {
 0x00000, 0x00001, 0x10000, 0x10001, 0x00002, 0x00003, 0x10002, 0x10003,
 0x20000, 0x20001, 0x30000, 0x30001, 0x20002, 0x20003, 0x30002, 0x30003,
 0x00004, 0x00005, 0x10004, 0x10005, 0x00006, 0x00007, 0x10006, 0x10007,
 0x20004, 0x20005, 0x30004, 0x30005, 0x20006, 0x20007, 0x30006, 0x30007,
 0x40000, 0x40001, 0x50000, 0x50001, 0x40002, 0x40003, 0x50002, 0x50003,
 0x60000, 0x60001, 0x70000, 0x70001, 0x60002, 0x60003, 0x70002, 0x70003,
 0x40004, 0x40005, 0x50004, 0x50005, 0x40006, 0x40007, 0x50006, 0x50007,
 0x60004, 0x60005, 0x70004, 0x70005, 0x60006, 0x60007, 0x70006, 0x70007,
 0x00008, 0x00009, 0x10008, 0x10009, 0x0000a, 0x0000b, 0x1000a, 0x1000b,
 0x20008, 0x20009, 0x30008, 0x30009, 0x2000a, 0x2000b, 0x3000a, 0x3000b,
 0x0000c, 0x0000d, 0x1000c, 0x1000d, 0x0000e, 0x0000f, 0x1000e, 0x1000f,
 0x2000c, 0x2000d, 0x3000c, 0x3000d, 0x2000e, 0x2000f, 0x3000e, 0x3000f,
 0x40008, 0x40009, 0x50008, 0x50009, 0x4000a, 0x4000b, 0x5000a, 0x5000b,
 0x60008, 0x60009, 0x70008, 0x70009, 0x6000a, 0x6000b, 0x7000a, 0x7000b,
 0x4000c, 0x4000d, 0x5000c, 0x5000d, 0x4000e, 0x4000f, 0x5000e, 0x5000f,
 0x6000c, 0x6000d, 0x7000c, 0x7000d, 0x6000e, 0x6000f, 0x7000e, 0x7000f,
 0x80000, 0x80001, 0x90000, 0x90001, 0x80002, 0x80003, 0x90002, 0x90003,
 0xa0000, 0xa0001, 0xb0000, 0xb0001, 0xa0002, 0xa0003, 0xb0002, 0xb0003,
 0x80004, 0x80005, 0x90004, 0x90005, 0x80006, 0x80007, 0x90006, 0x90007,
 0xa0004, 0xa0005, 0xb0004, 0xb0005, 0xa0006, 0xa0007, 0xb0006, 0xb0007,
 0xc0000, 0xc0001, 0xd0000, 0xd0001, 0xc0002, 0xc0003, 0xd0002, 0xd0003,
 0xe0000, 0xe0001, 0xf0000, 0xf0001, 0xe0002, 0xe0003, 0xf0002, 0xf0003,
 0xc0004, 0xc0005, 0xd0004, 0xd0005, 0xc0006, 0xc0007, 0xd0006, 0xd0007,
 0xe0004, 0xe0005, 0xf0004, 0xf0005, 0xe0006, 0xe0007, 0xf0006, 0xf0007,
 0x80008, 0x80009, 0x90008, 0x90009, 0x8000a, 0x8000b, 0x9000a, 0x9000b,
 0xa0008, 0xa0009, 0xb0008, 0xb0009, 0xa000a, 0xa000b, 0xb000a, 0xb000b,
 0x8000c, 0x8000d, 0x9000c, 0x9000d, 0x8000e, 0x8000f, 0x9000e, 0x9000f,
 0xa000c, 0xa000d, 0xb000c, 0xb000d, 0xa000e, 0xa000f, 0xb000e, 0xb000f,
 0xc0008, 0xc0009, 0xd0008, 0xd0009, 0xc000a, 0xc000b, 0xd000a, 0xd000b,
 0xe0008, 0xe0009, 0xf0008, 0xf0009, 0xe000a, 0xe000b, 0xf000a, 0xf000b,
 0xc000c, 0xc000d, 0xd000c, 0xd000d, 0xc000e, 0xc000f, 0xd000e, 0xd000f,
 0xe000c, 0xe000d, 0xf000c, 0xf000d, 0xe000e, 0xe000f, 0xf000e, 0xf000f,
};

/*
 *  Table for separating and reversing bits in a ldepth 2 bitmap.
 *  This aids in coverting a little endian ldepth 1 bitmap into the
 *  4 big-endian ldepth 0 bitmaps used for the VGA bit planes.
 *
 *	if the bits in uchar x are labeled
 *		76543210
 *	then l1septab[x] yields a ulongt with bits
 *		______73______62______51______40
 *	where _ represents a bit whose value is 0.
 *
 *  This table is used by l2update() in l.s.  l2update is implemented
 *  in assembler for speed.
 *
 */
ulong l2septab[] = {
 0x0000000, 0x0000001, 0x0000100, 0x0000101, 0x0010000, 0x0010001, 0x0010100, 0x0010101,
 0x1000000, 0x1000001, 0x1000100, 0x1000101, 0x1010000, 0x1010001, 0x1010100, 0x1010101,
 0x0000002, 0x0000003, 0x0000102, 0x0000103, 0x0010002, 0x0010003, 0x0010102, 0x0010103,
 0x1000002, 0x1000003, 0x1000102, 0x1000103, 0x1010002, 0x1010003, 0x1010102, 0x1010103,
 0x0000200, 0x0000201, 0x0000300, 0x0000301, 0x0010200, 0x0010201, 0x0010300, 0x0010301,
 0x1000200, 0x1000201, 0x1000300, 0x1000301, 0x1010200, 0x1010201, 0x1010300, 0x1010301,
 0x0000202, 0x0000203, 0x0000302, 0x0000303, 0x0010202, 0x0010203, 0x0010302, 0x0010303,
 0x1000202, 0x1000203, 0x1000302, 0x1000303, 0x1010202, 0x1010203, 0x1010302, 0x1010303,
 0x0020000, 0x0020001, 0x0020100, 0x0020101, 0x0030000, 0x0030001, 0x0030100, 0x0030101,
 0x1020000, 0x1020001, 0x1020100, 0x1020101, 0x1030000, 0x1030001, 0x1030100, 0x1030101,
 0x0020002, 0x0020003, 0x0020102, 0x0020103, 0x0030002, 0x0030003, 0x0030102, 0x0030103,
 0x1020002, 0x1020003, 0x1020102, 0x1020103, 0x1030002, 0x1030003, 0x1030102, 0x1030103,
 0x0020200, 0x0020201, 0x0020300, 0x0020301, 0x0030200, 0x0030201, 0x0030300, 0x0030301,
 0x1020200, 0x1020201, 0x1020300, 0x1020301, 0x1030200, 0x1030201, 0x1030300, 0x1030301,
 0x0020202, 0x0020203, 0x0020302, 0x0020303, 0x0030202, 0x0030203, 0x0030302, 0x0030303,
 0x1020202, 0x1020203, 0x1020302, 0x1020303, 0x1030202, 0x1030203, 0x1030302, 0x1030303,
 0x2000000, 0x2000001, 0x2000100, 0x2000101, 0x2010000, 0x2010001, 0x2010100, 0x2010101,
 0x3000000, 0x3000001, 0x3000100, 0x3000101, 0x3010000, 0x3010001, 0x3010100, 0x3010101,
 0x2000002, 0x2000003, 0x2000102, 0x2000103, 0x2010002, 0x2010003, 0x2010102, 0x2010103,
 0x3000002, 0x3000003, 0x3000102, 0x3000103, 0x3010002, 0x3010003, 0x3010102, 0x3010103,
 0x2000200, 0x2000201, 0x2000300, 0x2000301, 0x2010200, 0x2010201, 0x2010300, 0x2010301,
 0x3000200, 0x3000201, 0x3000300, 0x3000301, 0x3010200, 0x3010201, 0x3010300, 0x3010301,
 0x2000202, 0x2000203, 0x2000302, 0x2000303, 0x2010202, 0x2010203, 0x2010302, 0x2010303,
 0x3000202, 0x3000203, 0x3000302, 0x3000303, 0x3010202, 0x3010203, 0x3010302, 0x3010303,
 0x2020000, 0x2020001, 0x2020100, 0x2020101, 0x2030000, 0x2030001, 0x2030100, 0x2030101,
 0x3020000, 0x3020001, 0x3020100, 0x3020101, 0x3030000, 0x3030001, 0x3030100, 0x3030101,
 0x2020002, 0x2020003, 0x2020102, 0x2020103, 0x2030002, 0x2030003, 0x2030102, 0x2030103,
 0x3020002, 0x3020003, 0x3020102, 0x3020103, 0x3030002, 0x3030003, 0x3030102, 0x3030103,
 0x2020200, 0x2020201, 0x2020300, 0x2020301, 0x2030200, 0x2030201, 0x2030300, 0x2030301,
 0x3020200, 0x3020201, 0x3020300, 0x3020301, 0x3030200, 0x3030201, 0x3030300, 0x3030301,
 0x2020202, 0x2020203, 0x2020302, 0x2020303, 0x2030202, 0x2030203, 0x2030302, 0x2030303,
 0x3020202, 0x3020203, 0x3020302, 0x3020303, 0x3030202, 0x3030203, 0x3030302, 0x3030303,
};


M pc/l.s => pc/l.s +1 -117
@@ 585,7 585,7 @@ TEXT	x86(SB),$0
	JZ	is486
	MOVL	$586,AX
	JMP	done
is486
is486:
	MOVL	$486,AX
	JMP	done
is386:


@@ 647,122 647,6 @@ TEXT	config(SB),$0
#define Smmask	0x02		/*  map mask */

/*
 *  invert the ldepth 0 bitmap
 */
TEXT	l0update(SB),$0
	MOVL	from+4(FP),SI
	MOVL	to+0(FP),DI
	MOVL	len+8(FP),BX

	MOVL	BX,CX
	SHRL	$2,CX
	JZ	l01
l00:
	MOVL	-4(SI)(CX*4),AX
	NOTL	AX
	MOVL	AX,-4(DI)(CX*4)
	LOOP	l00
l01:
	MOVL	BX,CX
	ANDL	$(~3),BX
	ANDL	$3,CX
	JZ	l03
	ADDL	BX,SI
	ADDL	BX,DI
l02:
	MOVB	-1(SI)(CX*1),AL
	NOTL	AX
	MOVB	AL,-1(DI)(CX*1)
	LOOP	l02
l03:
	RET

/*
 *  separate ldepth 1 bitmap into 2 bit planes
 */
TEXT	l1update(SB),$0
	XORL	AX,AX
	MOVL	from+4(FP),SI
	MOVL	to+0(FP),DI
	MOVL	len+8(FP),CX
	MOVB	$(Smmask),AL
	MOVW	$(SRX),DX
	OUTB
l10:
	MOVL	-4(SI)(CX*2),DX
	MOVB	DL,AL
	MOVL	l1septab(SB)(AX*4),BX
	SHLL	$4,BX
	RORL	$8,DX
	MOVB	DL,AL
	ORL	l1septab(SB)(AX*4),BX
	RORL	$12,BX
	RORL	$8,DX
	MOVB	DL,AL
	ORL	l1septab(SB)(AX*4),BX
	SHLL	$4,BX
	RORL	$8,DX
	MOVB	DL,AL
	ORL	l1septab(SB)(AX*4),BX
	ROLL	$8,BX
	MOVW	$(SR),DX
	MOVB	$0x5,AL			/* write lo order bits to bit planes 1 & 3 */
	OUTB
	MOVW	BX,-2(DI)(CX*1)
	SHRL	$16,BX			/* write hi order bits to bit planes 0 & 2 */
	MOVB	$0xA,AL
	OUTB
	MOVW	BX,-2(DI)(CX*1)
	LOOP	l10
	RET

/*
 *  separate ldepth 2 bitmap into 4 bit planes
 */
TEXT	l2update(SB),$0
	XORL	AX,AX
	MOVL	from+4(FP),SI
	MOVL	to+0(FP),DI
	MOVL	len+8(FP),CX
	MOVB	$(Smmask),AL
	MOVW	$(SRX),DX
	OUTB
l20:
	MOVL	-4(SI)(CX*4),DX
	MOVB	DL,AL
	MOVL	l2septab(SB)(AX*4),BX
	SHLL	$2,BX
	SHRL	$8,DX
	MOVB	DL,AL
	ORL	l2septab(SB)(AX*4),BX
	SHLL	$2,BX
	SHRL	$8,DX
	MOVB	DL,AL
	ORL	l2septab(SB)(AX*4),BX
	SHLL	$2,BX
	SHRL	$8,DX
	MOVB	DL,AL
	ORL	l2septab(SB)(AX*4),BX
	MOVW	$(SR),DX
	MOVB	$0x1,AL			/* plane 3 */
	OUTB
	MOVB	BX,-1(DI)(CX*1)
	MOVB	$0x2,AL			/* plane 2 */
	OUTB
	SHRL	$8,BX
	MOVB	BX,-1(DI)(CX*1)
	MOVB	$0x4,AL			/* plane 1 */
	OUTB
	SHRL	$8,BX
	MOVB	BX,-1(DI)(CX*1)
	MOVB	$0x8,AL			/* plane 0*/
	OUTB
	SHRL	$8,BX
	MOVB	BX,-1(DI)(CX*1)
	LOOP	l20
	RET

/*
 * The DP8390 ethernet chip needs some time between
 * successive chip selects, so we force a jump into
 * the instruction stream to break the pipeline.

M port/devmouse.c => port/devmouse.c +29 -12
@@ 115,9 115,23 @@ GBitmap cursorback =
	{0, 0, 16, 16}
};

ulong cursorworkbits[16*4];
GBitmap cursorwork =
{
	cursorworkbits,
	0,
	1,
	0,
	{0, 0, 16, 16},
	{0, 0, 16, 16}
};

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

extern	void	screenload(Rectangle, uchar*, int, int, int);
extern	void	screenunload(Rectangle, uchar*, int, int, int);

enum{
	Qdir,
	Qcursor,


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


@@ 434,12 451,15 @@ cursoron(int dolock)
			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,
			screenunload(cursor.r, (uchar*)cursorworkbits,
				(16>>3) << gscreen.ldepth, cursorwork.width*BY2WD, 0);
			memmove(cursorbackbits, cursorworkbits, 16*cursorback.width*BY2WD);
			gbitblt(&cursorwork, cursorwork.r.min,
				&clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S);
			gbitblt(&gscreen, cursor.r.min,
			gbitblt(&cursorwork, cursorwork.r.min,
				&set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D);
			mbbrect(cursor.r);
			screenload(cursor.r, (uchar*)cursorworkbits,
				(16>>3) << gscreen.ldepth, cursorwork.width*BY2WD, 0);
		}
	}
	if(dolock)


@@ 454,11 474,9 @@ cursoroff(int dolock)
	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(!hwcurs)
			screenload(cursor.r, (uchar*)cursorbackbits,
				(16>>3) << gscreen.ldepth, cursorback.width*BY2WD, 0);
	}
	if(dolock)
		unlock(&cursor);


@@ 480,7 498,6 @@ mouseclock(void)
		mouse.redraw = 0;
		cursoroff(0);
		cursoron(0);
		mousescreenupdate();
		unlock(&cursor);
	}
}

M port/portfns.h => port/portfns.h +0 -4
@@ 129,8 129,6 @@ int		m3mouseputc(int);
void		machinit(void);
#define		malloc(s)	mallocz(s, 1)
void*		mallocz(ulong, int);
void		mbbpt(Point);
void		mbbrect(Rectangle);
void		mfreeseg(Segment*, ulong, int);
void		mmurelease(Proc*);
void		mmuswitch(Proc*);


@@ 144,7 142,6 @@ void		mousebuttons(int);
void		mouseclock(void);
void		mousectl(char*);
int		mouseputc(int);
void		mousescreenupdate(void);
void		mousetrack(int, int, int);
int		msize(void*);
Chan*		namec(char*, int, int, ulong);


@@ 228,7 225,6 @@ void		sccsetup(void*, ulong, int);
void		sched(void);
void		schedinit(void);
int		screenbits(void);
void		screenupdate(void);
int		scsiexec(Target*, int, uchar*, int, void*, int*);
int		scsiinv(int, int, Target**, uchar**, char*);
Target*		scsiunit(int, int);