~kris/9p

9hist

6bc41a53311561691c0ae0d8db0192e77af6d650 — David du Colombier 35 years ago 9f03239
Plan 9 from Bell Labs 1991-07-06
M gnot/dat.h => gnot/dat.h +1 -0
@@ 101,6 101,7 @@ struct Conf
	int	npipe;		/* number of pipes */
	int	nservice;	/* number of services */
	int	nfsyschan;	/* number of filsys open channels */
	int	nlapd;		/* number of dragnet protocol modules */
	ulong	maxialloc;	/* maximum bytes used by ialloc */
	int	copymode;	/* 0 is copy on write, 1 is copy on reference */
	int	portispaged;	/* ??? */

M gnot/screen.c => gnot/screen.c +50 -0
@@ 83,3 83,53 @@ screenputs(char *s, int n)
	while(n-- > 0)
		screenputc(*s++);
}

int
screenbits(void)
{
	if(*(uchar*)MOUSE & (1<<4))
		return 2;
	else
		return 1;
}

void
getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
{
	ulong ans;

	/*
	 * The gnot says 0 is white (max intensity)
	 */
	if(gscreen.ldepth == 0){
		if(p == 0)
				ans = ~0;
		else
				ans = 0;
	}else{
		switch(p){
		case 0:		ans = ~0;		break;
		case 1:		ans = 0xAAAAAAAA;	break;
		case 2:		ans = 0x55555555;	break;
		default:	ans = 0;		break;
	}
	*pr = *pg = *pb = ans;
}

int
setcolor(ulong p, ulong r, ulong g, ulong b)
{
	return 0;	/* can't change mono screen colormap */
}

int
hwcursset(uchar *s, uchar *c, int ox, int oy)
{
	return 0;
}

int
hwcursmove(int x, int y)
{
	return 0;
}

M pc/clock.c => pc/clock.c +15 -4
@@ 4,6 4,7 @@
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"

/*
 *  8253 timer


@@ 24,10 25,20 @@ clockinit(void)
}

void
clock(void *arg)
clock(Ureg *ur)
{
	Proc *p;

	m->ticks++;
	if((m->ticks%185)==0)
		print("%d secs\n", TK2SEC(m->ticks));
	INT0ENABLE;
	p = m->proc;
	if(p){
		p->pc = ur->eip;
		if (p->state==Running)
			p->time[p->insyscall]++;
	}

	if((m->ticks%185) == 92)
		floppystart();
	else if((m->ticks%185) == 0)
		floppystop();
}

M pc/dat.h => pc/dat.h +0 -3
@@ 126,7 126,6 @@ typedef void		KMap;

#define	NERR	15
#define	NNOTE	5
#define	NFD	100
struct User
{
	Proc	*p;


@@ 137,8 136,6 @@ struct User
	char	elem[NAMELEN];		/* last name element from namec */
	Chan	*slash;
	Chan	*dot;
	Chan	*fd[NFD];
	int	maxfd;			/* highest fd in use */
	/*
	 * Rest of structure controlled by devproc.c and friends.
	 * lock(&p->debug) to modify.

M pc/fns.h => pc/fns.h +16 -4
@@ 1,8 1,13 @@
#include "../port/portfns.h"

void	clock(void*);
void	clock(Ureg*);
void	clockinit(void);
void	delay(int);
void	floppyinit(void);
void	floppyintr(Ureg*);
void	floppystart(void);
void	floppystop(void);
void	idle(void);
int	inb(int);
void	intr0(void);
void	intr1(void);


@@ 21,18 26,25 @@ void	intr13(void);
void	intr14(void);
void	intr15(void);
void	intr16(void);
void	intr17(void);
void	intr18(void);
void	intr19(void);
void	intr20(void);
void	intr21(void);
void	intr22(void);
void	intr23(void);
void	intrbad(void);
int	kbdc(void);
void	kbdinit(void);
void	kbdintr(void*);
void	kbdintr(Ureg*);
void	lgdt(Segdesc*, int);
void	lidt(Segdesc*, int);
void	mmuinit(void);
void	outb(int, int);
void	prhex(ulong);
void	screeninit(void);
void	screenputc(int);
void	screenputs(char*, int);
void	setvec(int, void (*)(void*), int);
void	setvec(int, void (*)(Ureg*), int);
void	systrap(void);
void	trapinit(void);
int	tas(Lock*);

M pc/io.h => pc/io.h +1 -1
@@ 10,7 10,7 @@ enum

	Intena=		0x20,		/* written to Intctlport, enables next int */

	Int0vec=	17,		/* first interrupt vector used by the 8259 */
	Int0vec=	16,		/* first interrupt vector used by the 8259 */
	Clockvec=	Int0vec+0,	/* clock interrupts */
	Kbdvec=		Int0vec+1,	/* keyboard interrupts */
};

M pc/kbd.c => pc/kbd.c +14 -33
@@ 1,9 1,9 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"mem.h"

enum {
	Data=		0x60,	/* data port */


@@ 241,28 241,11 @@ kbdinit(void)
	setvec(Kbdvec, kbdintr, SEGIG);
}

/*
 *  get a byte from the keyboard
 */
int
kbdc(void)
{
	int c;

	for(;;){
		while((inb(Status)&Inready)==0)
			;
		kbdintr(&c);
		c = getc(&kbdq);
		if(c != -1)
			return c;
	}
}

int
kbdputc(IOQ* q, int c)
{
	screenputc(c);
	if(c==0x10)
		panic("^p");
	putc(q, c);
}



@@ 270,7 253,7 @@ kbdputc(IOQ* q, int c)
 *  keyboard interrupt
 */
void
kbdintr(void *a)
kbdintr(Ureg *ur)
{
	int c, nc;
	static int esc1, esc2;


@@ 291,7 274,7 @@ kbdintr(void *a)
	if(c > sizeof kbtab){
		print("unknown key %ux\n", c|keyup);
		kbdputc(&kbdq, k1);
		goto out;
		return;
	}

	/*


@@ 299,10 282,10 @@ kbdintr(void *a)
	 */
	if(c == 0xe0){
		esc1 = 1;
		goto out;
		return;
	} else if(c == 0xe1){
		esc2 = 2;
		goto out;
		return;
	}

	if(esc1){


@@ 310,7 293,7 @@ kbdintr(void *a)
		esc1 = 0;
	} else if(esc2){
		esc2--;
		goto out;
		return;
	} else if(shift)
		c = kbtabshift[c];
	else


@@ 331,7 314,7 @@ kbdintr(void *a)
			ctl = 0;
			break;
		}
		goto out;
		return;
	}

	/*


@@ 361,23 344,21 @@ kbdintr(void *a)
		switch(c){
		case Caps:
			caps ^= 1;
			goto out;
			return;
		case Num:
			num ^= 1;
			goto out;
			return;
		case Shift:
			shift = 1;
			goto out;
			return;
		case Latin:
			lstate = 1;
			goto out;
			return;
		case Ctrl:
			ctl = 1;
			goto out;
			return;
		}
	}
	kbdputc(&kbdq, c);
out:
	INT0ENABLE;			/* reenable interrupt */
	return;
}

M pc/l.s => pc/l.s +35 -1
@@ 80,7 80,7 @@ flush:
	MOVW	AX,SS
	MOVW	AX,ES

/*	JMPFAR*	SELECTOR(2, SELGDT, 0):$protected(SB) /**/
/*	JMPFAR	SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
	 BYTE	$0xEA
	 WORD	$mode32bit(SB)
	 WORD	$SELECTOR(2, SELGDT, 0)


@@ 261,6 261,34 @@ TEXT	intr16(SB),$0
	PUSHL	$0
	PUSHL	$16
	JMP	intrcommon
TEXT	intr17(SB),$0
	PUSHL	$0
	PUSHL	$17
	JMP	intrcommon
TEXT	intr18(SB),$0
	PUSHL	$0
	PUSHL	$18
	JMP	intrcommon
TEXT	intr19(SB),$0
	PUSHL	$0
	PUSHL	$19
	JMP	intrcommon
TEXT	intr20(SB),$0
	PUSHL	$0
	PUSHL	$20
	JMP	intrcommon
TEXT	intr21(SB),$0
	PUSHL	$0
	PUSHL	$21
	JMP	intrcommon
TEXT	intr22(SB),$0
	PUSHL	$0
	PUSHL	$22
	JMP	intrcommon
TEXT	intr23(SB),$0
	PUSHL	$0
	PUSHL	$23
	JMP	intrcommon
TEXT	intrbad(SB),$0
	PUSHL	$0
	PUSHL	$0x1ff


@@ 311,3 339,9 @@ TEXT	splhi(SB),$0
 */
TEXT	splx(SB),$0
	RET

/*
 *	
 */
TEXT	idle(SB),$0
	HLT

M pc/main.c => pc/main.c +19 -6
@@ 1,18 1,27 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

main(void)
{
	screeninit();
	print("screen inited\n");
	trapinit();
	print("traps inited\n");
	kbdinit();
	print("kbd inited\n");
	clockinit();
	mmuinit();
	floppyinit();
	spllo();
	for(;;);
	for(;;){
		int c;

		c = getc(&kbdq);
		if(c!=-1)
			screenputc(c);
		idle();
	}
}

void


@@ 21,7 30,7 @@ delay(int l)
	int i;

	while(--l){
		for(i=0; i < 10000; i++)
		for(i=0; i < 100; i++)
			;
	}
}


@@ 52,7 61,11 @@ panic(char *fmt, ...)
	screenputs("panic: ", 7);
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
	screenputs(buf, n);
	for(;;);
	screenputs("\n", 1);
	INT0ENABLE;
	spllo();
	for(;;)
		idle();
}

void

M pc/mem.h => pc/mem.h +12 -6
@@ 5,7 5,6 @@
/*
 * Sizes
 */

#define	BI2BY		8			/* bits per byte */
#define BI2WD		32			/* bits per word */
#define	BY2WD		4			/* bytes per word */


@@ 20,7 19,6 @@
 * Time
 * Clock frequency is ??? HZ
 */

#define	HZ		(18)			/* clock frequency */
#define	MS2HZ		(54)			/* millisec per clock tick */
#define	TK2SEC(t)	((t)*10/185)		/* ticks to seconds */


@@ 30,7 28,6 @@
/*
 * Fundamental addresses
 */

#define	USERADDR	0xC0000000
#define	UREGADDR	(USERADDR+BY2PG-4*16)



@@ 40,7 37,6 @@
 * User is at 0-2GB
 * Kernel is at 2GB-4GB
 */

#define	UZERO	0			/* base of user address space */
#define	UTZERO	(UZERO+BY2PG)		/* first address in user text */
#define	TSTKTOP	USERADDR		/* end of new stack in sysexec */


@@ 55,15 51,16 @@
#define isphys(x) ((x)&KZERO)

/*
 *  known segments (in GDT) and their selectors
 *  known 80386 segments (in GDT) and their selectors
 */

#define	NULLSEG	0	/* null segment */
#define	KDSEG	1	/* kernel data/stack */
#define	KESEG	2	/* kernel executable */	
#define	UDSEG	3	/* user data/stack */
#define	UESEG	4	/* user executable */
#define	SYSGATE	5	/* system call gate */
#define	RDSEG	6	/* reboot data/stack */
#define	RESEG	7	/* reboot executable */	

#define SELGDT	(0<<3)	/* selector is in gdt */
#define	SELLDT	(1<<3)	/* selector is in ldt */


@@ 77,6 74,8 @@
#define UESEL	SELECTOR(UESEG, SELGDT, 3)
#define UDSEL	SELECTOR(UDSEG, SELGDT, 3)
#define USSEL	SELECTOR(UDSEG, SELGDT, 3)
#define RDSEL	SELECTOR(RDSEG, SELGDT, 0)
#define RESEL	SELECTOR(RESEG, SELGDT, 0)

/*
 *  fields in segment descriptors


@@ 96,3 95,10 @@
#define SEGW	(1<<9)		/* writable (for data/stack) */
#define	SEGR	(1<<9)		/* readable (for code) */
#define SEGD	(1<<22)		/* default 1==32bit (for code) */

/*
 *  virtual MMU entries
 */
#define PTEMAPMEM	(1024*1024)	/* ??? */	
#define SEGMAPSIZE	16		/* ??? */
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)	/* ??? */

M pc/mmu.c => pc/mmu.c +5 -1
@@ 49,11 49,13 @@ struct Tss
#define	DATASEG(p) 	{ 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW }
#define	EXECSEG(p) 	{ 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR }
#define CALLGATE(s,o,p)	{ (o)&0xFFFF|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG }
#define	D16SEG(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW }
#define	E16SEG(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR }

/*
 *  global descriptor table describing all segments
 */
Segdesc gdt[6] =
Segdesc gdt[] =
{
[NULLSEG]	{ 0, 0},		/* null descriptor */
[KDSEG]		DATASEG(0),		/* kernel data/stack */


@@ 61,6 63,8 @@ Segdesc gdt[6] =
[UDSEG]		DATASEG(3),		/* user data/stack */
[UESEG]		EXECSEG(3),		/* user code */
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */
[RDSEG]		D16SEG(0),		/* reboot data/stack */
[RESEG]		E16SEG(0),		/* reboot code */
};

void

M pc/trap.c => pc/trap.c +10 -20
@@ 20,7 20,7 @@ sethvec(int v, void (*r)(void), int type)
}

void
setvec(int v, void (*r)(void*), int type)
setvec(int v, void (*r)(Ureg*), int type)
{
	ilt[v].d1 &= ~SEGTYPE;
	ilt[v].d1 |= type;


@@ 55,11 55,18 @@ trapinit(void)
	sethvec(14, intr14, SEGTG);
	sethvec(15, intr15, SEGTG);
	sethvec(16, intr16, SEGTG);
	sethvec(17, intr17, SEGTG);
	sethvec(18, intr18, SEGTG);
	sethvec(19, intr19, SEGTG);
	sethvec(20, intr20, SEGTG);
	sethvec(21, intr21, SEGTG);
	sethvec(22, intr22, SEGTG);
	sethvec(23, intr23, SEGTG);

	/*
	 *  set all others to unknown
	 */
	for(i = 17; i < 256; i++)
	for(i = 24; i < 256; i++)
		sethvec(i, intrbad, SEGIG);

	/*


@@ 88,26 95,9 @@ trapinit(void)
 */
trap(Ureg *ur)
{
	print("trap %lux\n", ur->trap);
	print(" edi %lux\n", ur->edi);
	print(" esi %lux\n", ur->esi);
	print(" ebp %lux\n", ur->ebp);
	print(" esp %lux\n", ur->esp);
	print(" ebx %lux\n", ur->ebx);
	print(" edx %lux\n", ur->edx);
	print(" ecx %lux\n", ur->ecx);
	print(" eax %lux\n", ur->eax);
	print(" ds %lux\n", ur->ds);
	print(" trap %lux\n", ur->trap);
	print(" ecode %lux\n", ur->ecode);
	print(" eip %lux\n", ur->eip);
	print(" cs %lux\n", ur->cs);
	print(" eflags %lux\n", ur->eflags);
	print(" oesp %lux\n", ur->oesp);
	print(" ss %lux\n", ur->ss);
	delay(500);
	if(ur->trap>=256 || ivec[ur->trap] == 0)
		panic("bad trap type %d\n", ur->trap);

	(*ivec[ur->trap])(ur);
	INT0ENABLE;
}

M port/devbit.c => port/devbit.c +223 -97
@@ 6,7 6,6 @@
#include	"errno.h"

#include	"devtab.h"
#include	"ureg.h"

#include	<libg.h>
#include	<gnot.h>


@@ 14,6 13,25 @@
extern GFont	*defont;

/*
 * Some monochrome screens are reversed from what we like:
 * We want 0's bright and 1s 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? */
int hwcursor;	/* is there a hardware cursor? */

/*
 * Device (#b/bitblt) is exclusive use on open, so no locks are necessary
 * for i/o
 */


@@ 41,26 59,25 @@ struct
	int	rid;		/* read bitmap id */
	int	rminy;		/* read miny */
	int	rmaxy;		/* read maxy */
	int	mid;		/* colormap read bitmap id */
}bit;

#define	FREE	0x80000000
void	bitcompact(void);
void	bitfree(GBitmap*);
void	mouseupdate(int);
extern	GBitmap	gscreen;

struct{
	/*
	 * First three fields are known in l.s
	 * First four fields are known in screen.c
	 */
	int	dx;		/* interrupt-time delta */
	int	dy;
	int	track;		/* update cursor on screen */
	int	clock;		/* check mouse.track on RTE */
	Mouse;
	int	changed;	/* mouse structure changed since last read */
	int	newbuttons;	/* interrupt time access only */
	Rendez	r;
	int	newbuttons;	/* interrupt time access only */
}mouse;

Cursor	arrow =


@@ 105,7 122,7 @@ GBitmap	clr =
	{0, 0, 16, 16}
};

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


@@ 141,6 158,7 @@ bitreset(void)
{
	int i;
	GBitmap *bp;
	ulong r;

	bit.map = ialloc(conf.nbitmap * sizeof(GBitmap), 0);
	for(i=0,bp=bit.map; i<conf.nbitmap; i++,bp++){


@@ 150,6 168,9 @@ bitreset(void)
	bp--;
	bp->base = 0;
	bit.map[0] = gscreen;	/* bitmap 0 is screen */
	getcolor(0, &r, &r, &r);
	if(r == 0)
		flipping = 1;
	bit.free = bit.map+1;
	bit.lastid = -1;
	bit.lastfid = -1;


@@ 168,9 189,12 @@ bitinit(void)
{
	lock(&bit);
	unlock(&bit);
	if(gscreen.ldepth > 1)
		panic("bitinit ldepth>1");
	cursorback.ldepth = gscreen.ldepth;
	if(gscreen.ldepth > 3)
		cursorback.ldepth = 0;
	else {
		cursorback.ldepth = gscreen.ldepth;
		cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5;
	}
	cursoron(1);
}



@@ 186,6 210,7 @@ bitclone(Chan *c, Chan *nc)
	nc = devclone(c, nc);
	if(c->qid.path != CHDIR)
		incref(&bit);
	return nc;
}

int


@@ 215,6 240,7 @@ bitopen(Chan *c, int omode)
		bit.lastid = -1;
		bit.lastfid = -1;
		bit.rid = -1;
		bit.mid = -1;
		bit.init = 0;
		bit.ref = 1;
		Cursortocursor(&arrow);


@@ 272,7 298,8 @@ bitclose(Chan *c)

/*
 * These macros turn user-level (high bit at left) into internal (whatever)
 * bit order.  On the gnot they're trivial.
 * bit order. So far all machines have the same (good) order; when
 * that changes, these should switch on a variable set at init time.
 */
#define	U2K(x)	(x)
#define	K2U(x)	(x)


@@ 282,7 309,7 @@ bitread(Chan *c, void *va, long n, ulong offset)
{
	uchar *p, *q;
	long miny, maxy, t, x, y;
	ulong l, nw, ws;
	ulong l, nw, ws, rv, gv, bv;
	int off, j;
	Fontchar *i;
	GBitmap *src;


@@ 387,9 414,36 @@ bitread(Chan *c, void *va, long n, ulong offset)
			n = 3;
			break;
		}
		if(bit.mid >= 0){
			/*
			 * read colormap:
			 *	data		12*(2**bitmapdepth)
			 */
			l = (1<<bit.map[bit.mid].ldepth);
			nw = 1 << l;
			if(n < 12*nw)
				error(Ebadblt);
			for(j = 0; j < nw; j++){
				if(bit.mid == 0){
					getcolor(flipping? ~j : j, &rv, &gv, &bv);
				}else{
					rv = j;
					for(off = 32-l; off > 0; off -= l)
						rv = (rv << l) | j;
					gv = bv = rv;
				}
				PLONG(p, rv);
				PLONG(p+4, gv);
				PLONG(p+8, bv);
				p += 12;
			}
			bit.mid = -1;
			n = 12*nw;
			break;
		}
		if(bit.rid >= 0){
			/*
			 * read
			 * read bitmap:
			 *	data		bytewidth*(maxy-miny)
			 */
			src = &bit.map[bit.rid];


@@ 420,8 474,12 @@ bitread(Chan *c, void *va, long n, ulong offset)
			for(y=miny; y<maxy; y++){
				q = (uchar*)gaddr(src, Pt(src->r.min.x, y));
				q += (src->r.min.x&((sizeof(ulong))*ws-1))/ws;
				for(x=0; x<l; x++)
					*p++ = K2U(*q++);
				if(bit.rid == 0 && flipping)	/* flip bits */
					for(x=0; x<l; x++)
						*p++ = ~K2U(*q++);
				else
					for(x=0; x<l; x++)
						*p++ = K2U(*q++);
				n += l;
			}
			if(off)


@@ 473,12 531,13 @@ long
bitwrite(Chan *c, void *va, long n, ulong offset)
{
	uchar *p, *q;
	long m, v, miny, maxy, minx, maxx, t, x, y, tw, th;
	ulong l, nw, ws;
	int off, isoff, i;
	long m, v, miny, maxy, minx, maxx, t, x, y;
	ulong l, nw, ws, rv;
	int off, isoff, i, ok;
	Point pt, pt1, pt2;
	Rectangle rect;
	Cursor curs;
	Fcode fc;
	Fontchar *fcp;
	GBitmap *bp, *src, *dst;
	GFont *f;


@@ 514,7 573,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 18)
				error(Ebadblt);
			v = *(p+1);
			if(v!=0 && v!=1)	/* BUG */
			if(v>3)	/* BUG */
				error(Ebadblt);
			ws = 1<<(5-v);	/* pixels per word */
			if(bit.free == 0)


@@ 572,31 631,37 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			 */
			if(m < 31)
				error(Ebadblt);
			fc = GSHORT(p+29) & 0xF;
			v = GSHORT(p+11);
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth < 0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0){
				if(flipping)
					fc = flipS[fc];
				off = 1;
			}
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth < 0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0)
			if(v == 0){
				if(flipping)
					fc = flipD[fc];
				off = 1;
			}
			pt.x = GLONG(p+3);
			pt.y = GLONG(p+7);
			v = GSHORT(p+11);
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth < 0)
				error(Ebadbitmap);
			if(v == 0)
				off = 1;
			rect.min.x = GLONG(p+13);
			rect.min.y = GLONG(p+17);
			rect.max.x = GLONG(p+21);
			rect.max.y = GLONG(p+25);
			v = GSHORT(p+29);
			if(off && !isoff){
				cursoroff(1);
				isoff = 1;
			}
			balubitblt(dst, pt, src, rect, v);
			gbitblt(dst, pt, src, rect, fc);
			m -= 31;
			p += 31;
			break;


@@ 744,23 809,44 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0)
			fc = GSHORT(p+20) & 0xF;
			if(v == 0){
				if(flipping)
					fc = flipD[fc];
				off = 1;
			}
			pt1.x = GLONG(p+3);
			pt1.y = GLONG(p+7);
			pt2.x = GLONG(p+11);
			pt2.y = GLONG(p+15);
			t = p[19];
			v = GSHORT(p+20);
			if(off && !isoff){
				cursoroff(1);
				isoff = 1;
			}
			gsegment(dst, pt1, pt2, t, v);
			gsegment(dst, pt1, pt2, t, fc);
			m -= 22;
			p += 22;
			break;

		case 'm':
			/*
			 * read colormap
			 *
			 *	'm'		1
			 *	id		2
			 */
			if(m < 3)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
				error(Ebadbitmap);
			bit.mid = v;
			m -= 3;
			p += 3;
			break;

		case 'p':
			/*
			 * point


@@ 778,17 864,20 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0)
			fc = GSHORT(p+12) & 0xF;
			if(v == 0){
				if(flipping)
					fc = flipD[fc];
				off = 1;
			}
			pt1.x = GLONG(p+3);
			pt1.y = GLONG(p+7);
			t = p[11];
			v = GSHORT(p+12);
			if(off && !isoff){
				cursoroff(1);
				isoff = 1;
			}
			gpoint(dst, pt1, t, v);
			gpoint(dst, pt1, t, fc);
			m -= 14;
			p += 14;
			break;


@@ 835,15 924,18 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0)
			fc = GSHORT(p+13) & 0xF;
			if(v == 0){
				if(flipping)
					fc = flipD[fc];
				off = 1;
			}
			pt.x = GLONG(p+3);
			pt.y = GLONG(p+7);
			v = GSHORT(p+11);
			f = &bit.font[v];
			if(v<0 || v>=conf.nfont || f->bits==0 || f->bits->ldepth<0)
				error(Ebadblt);
			v = GSHORT(p+13);
			p += 15;
			m -= 15;
			q = memchr(p, 0, m);


@@ 853,7 945,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				cursoroff(1);
				isoff = 1;
			}
			gstring(dst, pt, f, (char*)p, v);
			gstring(dst, pt, f, (char*)p, fc);
			q++;
			m -= q-p;
			p = q;


@@ 875,8 967,12 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0)
			fc = GSHORT(p+21) & 0xF;
			if(v == 0){
				if(flipping)
					fc = flipD[fc];
				off = 1;
			}
			rect.min.x = GLONG(p+3);
			rect.min.y = GLONG(p+7);
			rect.max.x = GLONG(p+11);


@@ 885,12 981,11 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth<0)
				error(Ebadbitmap);
			v = GSHORT(p+21);
			if(off && !isoff){
				cursoroff(1);
				isoff = 1;
			}
			gtexture(dst, rect, src, v);
			gtexture(dst, rect, src, fc);
			m -= 23;
			p += 23;
			break;


@@ 937,8 1032,12 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			for(y=miny; y<maxy; y++){
				q = (uchar*)gaddr(dst, Pt(dst->r.min.x, y));
				q += (dst->r.min.x&((sizeof(ulong))*ws-1))/ws;
				for(x=0; x<l; x++)
					*q++ = U2K(*p++);
				if(v == 0 && flipping)	/* flip bits */
					for(x=0; x<l; x++)
						*q++ = ~U2K(*p++);
				else
					for(x=0; x<l; x++)
						*q++ = U2K(*p++);
				m -= l;
			}
			break;


@@ 954,7 1053,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				error(Ebadblt);
			pt1.x = GLONG(p+1);
			pt1.y = GLONG(p+5);
			if(!eqpt(mouse.xy, pt1)){
/*			if(!eqpt(mouse.xy, pt1))*/{
				mouse.xy = pt1;
				mouse.track = 1;
				mouseclock();


@@ 962,6 1061,38 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			m -= 9;
			p += 9;
			break;

		case 'z':
			/*
			 * write the colormap
			 *
			 *	'z'		1
			 *	id		2
			 *	map		12*(2**bitmapdepth)
			 */
			if(m < 3)
				error(Ebadblt);
			v = GSHORT(p+1);
			if(v != 0)
				error(Ebadbitmap);
			m -= 3;
			p += 3;
			nw = 1 << (1 << bit.map[v].ldepth);
			if(m < 12*nw)
				error(Ebadblt);
			ok = 1;
			for(i = 0; i < nw; i++){
				ok &= setcolor(i, GLONG(p), GLONG(p+4), GLONG(p+8));
				p += 12;
				m -= 12;
			}
			if(!ok){
				/* assume monochrome: possibly change flipping */
				l = GLONG(p-12);
				getcolor(nw-1, &rv, &rv, &rv);
				flipping = (l != rv);
			}
			break;
		}

	poperror();


@@ 1011,8 1142,6 @@ bitcompact(void)
		p1 += 2 + p1[0];
	}
	bit.wfree = p1;
	if(p1<bit.words || p1>=bit.words+bit.nwords)
		panic("bitcompact");
	qunlock(&bitlock);
}



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


@@ 1061,7 1190,16 @@ cursoroff(int dolock)
}

void
mousebuttons(int b)	/* called spl5 */
mousedelta(int b, int dx, int dy)	/* called at higher priority */
{
	mouse.dx += dx;
	mouse.dy += dy;
	mouse.newbuttons = b;
	mouse.track = 1;
}

void
mousebuttons(int b)	/* called at higher priority */
{
	/*
	 * It is possible if you click very fast and get bad luck


@@ 1074,20 1212,28 @@ mousebuttons(int b)	/* called spl5 */
}

void
mouseclock(void)	/* called spl6 */
{
	++mouse.clock;
}

void
mousetry(Ureg *ur)
mouseclock(void)	/* called splhi */
{
	int s;

	if(mouse.clock && mouse.track && (ur->sr&SPL(7)) == 0 && canlock(&cursor)){
		s = spl1();
		mouseupdate(0);
		splx(s);
	int x, y;
	if(mouse.track && canlock(&cursor)){
		x = mouse.xy.x + mouse.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 + mouse.dy;
		if(y < gscreen.r.min.y)
			y = gscreen.r.min.y;
		if(y >= gscreen.r.max.y)
			y = gscreen.r.max.y;
		cursoroff(0);
		mouse.xy = Pt(x, y);
		cursoron(0);
		mouse.dx = 0;
		mouse.dy = 0;
		mouse.track = 0;
		mouse.buttons = mouse.newbuttons;
		mouse.changed = 1;
		unlock(&cursor);
		wakeup(&mouse.r);
	}


@@ 1096,42 1242,22 @@ mousetry(Ureg *ur)
int
mouseputc(IOQ *q, int c)
{
	/*
	 *  put your favorite serial mouse code here
	 */
}

void
mouseupdate(int dolock)
{
	int x, y;

	if(dolock && !canlock(&cursor))
		return;

	x = mouse.xy.x + mouse.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 + mouse.dy;
	if(y < gscreen.r.min.y)
		y = gscreen.r.min.y;
	if(y >= gscreen.r.max.y)
		y = gscreen.r.max.y;
	cursoroff(0);
	mouse.xy = Pt(x, y);
	cursoron(0);
	mouse.dx = 0;
	mouse.dy = 0;
	mouse.clock = 0;
	mouse.track = 0;
	mouse.buttons = mouse.newbuttons;
	mouse.changed = 1;

	if(dolock){
		unlock(&cursor);
		wakeup(&mouse.r);
	static short msg[5];
	static int nb;
	static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7};

	if((c&0xF0) == 0x80)
		nb=0;
	msg[nb] = c;
	if(c & 0x80)
		msg[nb] |= 0xFF00;	/* sign extend */
	if(++nb == 5){
		mouse.newbuttons = b[(msg[0]&7)^7];
		mouse.dx = msg[1]+msg[3];
		mouse.dy = -(msg[2]+msg[4]);
		mouse.track = 1;
		mouseclock();
		nb = 0;
	}
}


M port/devdk.c => port/devdk.c +3 -2
@@ 767,7 767,7 @@ dkstat(Chan *c, char *dp)
/*
 *  opening a dk device allocates a Line.  Opening the `clone'
 *  device is a ``macro'' for finding a free Line and opening
 *  it's ctl file.
 *  its ctl file.
 *
 *  opening the `listen' sub device is a macro for listening for
 *  a new call.  Lile `clone' the ctl file of the new channel is


@@ 1473,7 1473,8 @@ dkcsckproc(void *a)
			break;
		
		default:
			DPRINT("unrecognized csc message %o(%o)\n", d.type, line);
			print("unrecognized csc message %o.%o(%o)\n",
				d.type, d.srv, line);
			break;
		}
	}

M port/devscsi.c => port/devscsi.c +5 -1
@@ 104,7 104,7 @@ scsiwalk(Chan *c, char *name)
void
scsistat(Chan *c, char *db)
{
	devstat(c, db, 0, 0, scsigen);
	devstat(c, db, 0, 0, scsigeno);
}

Chan *


@@ 579,5 579,9 @@ scsictrlintr(void)
		default:
			panic("scsi status 0x%2.2ux", status);
		}
		kprint("resetting...");
		PUT(Own_id, ownid);
		PUT(Cmd, Reset);
		break;
	}
}

M port/devwren.c => port/devwren.c +1 -1
@@ 150,7 150,7 @@ wrenattach(char *param)
	d = &wren[dev];
	d->blocksize = BGLONG(&buf[4]);

	plen = BGLONG(&buf[0]);
	plen = BGLONG(&buf[0])+1;
	d->p[Npart].firstblock = 0;
	d->p[Npart].maxblock = plen;
	plen = plen/Npart;

M port/fault.c => port/fault.c +4 -3
@@ 165,9 165,6 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
		if(ask < BY2PG)
			memset(kaddr+ask, 0, BY2PG-ask);

		if((s->type&SG_TYPE) == SG_TEXT)
			memset(new->cachectl, PG_TXTFLUSH, sizeof(new->cachectl));

		poperror();
		kunmap(k);
		qunlock(&c->rdl);


@@ 176,6 173,8 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
			new->daddr = daddr;
			cachepage(new, s->image);
			*p = new;
			if(s->flushme)
				memset(new->cachectl, PG_TXTFLUSH, sizeof(new->cachectl));
		}
		else 
			putpage(new);


@@ 207,6 206,8 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
			cachepage(new, &swapimage);
			putswap(*p);
			*p = new;
			if(s->flushme)
				memset(new->cachectl, PG_TXTFLUSH, sizeof(new->cachectl));
		}
		else
			putpage(new);

M port/portdat.h => port/portdat.h +1 -0
@@ 348,6 348,7 @@ struct Segment
	ulong	size;			/* size in pages */
	ulong	fstart;			/* start address in file for demand load */
	ulong	flen;			/* length of segment in file */
	int	flushme;		/* maintain consistent icache for this segment */
	Image	*image;			/* image in file system attached to this segment */
	Page	*(*pgalloc)(ulong addr);/* SG_PHYSICAL page allocator */
	void	(*pgfree)(Page *);	/* SG_PHYSICAL page free */

M port/portfns.h => port/portfns.h +40 -35
@@ 2,12 2,12 @@
#define	SET(x)	x = 0
#define	USED(x)	if(x)

void	alarminit(void);
Alarm*	alarm(int, void (*)(Alarm*), void*);
void	alarminit(void);
Block*	allocb(ulong);
Image*	attachimage(int, Chan*, ulong, ulong);
int	anyready(void);
void	append(List**, List*);
Image*	attachimage(int, Chan*, ulong, ulong);
int	blen(Block *);
int	bround(Block *, int);
void	buzz(int, int);


@@ 15,9 15,9 @@ void	cachepage(Page*, Image*);
void	cancel(Alarm*);
int	cangetc(void*);
int	canlock(Lock*);
int	canqlock(QLock*);
int	canpage(Proc*);
int	canputc(void*);
int	canqlock(QLock*);
void	chandevinit(void);
void	chandevreset(void);
void	chaninit(void);


@@ 25,10 25,10 @@ void	checkalarms(void);
void	clock(Ureg*);
Chan*	clone(Chan*, Chan*);
void	close(Chan*);
void	closemount(Mount*);
void	closepgrp(Pgrp*);
void	closeegrp(Egrp*);
void	closefgrp(Fgrp*);
void	closemount(Mount*);
void	closepgrp(Pgrp*);
long	clrfpintr(void);
void	confinit(void);
int	consactive(void);


@@ 36,8 36,8 @@ Env*	copyenv(Env*, int);
void	copypage(Page*, Page*);
int	decref(Ref*);
void	delay(int);
void	delete0(List**, List*);
void	delete(List**, List*, List*);
void	delete0(List**, List*);
Chan*	devattach(int, char*);
Chan*	devclone(Chan*, Chan*);
void	devdir(Chan*, Qid, char*, long, long, Dir*);


@@ 52,11 52,11 @@ void	dumpqueues(void);
void	dumpregs(Ureg*);
void	dumpstack(void);
Fgrp*	dupfgrp(Fgrp*);
void	dupswap(Page*);
void	envpgclose(Env *);
void	duppage(Page*);
Segment* dupseg(Segment*);
Segment*	dupseg(Segment*);
void	dupswap(Page*);
void	envcpy(Egrp*, Egrp*);
void	envpgclose(Env *);
int	eqchan(Chan*, Chan*, long);
int	eqqid(Qid, Qid);
void	error(int);


@@ 77,10 77,14 @@ void	freepte(Segment*, Pte*);
void	freesegs(int);
Block*	getb(Blist*);
int	getc(IOQ*);
int	gets(IOQ*, void*, int);
void	getcolor(ulong, ulong*, ulong*, ulong*);
int	getfields(char*, char**, int, char);
Block*	getq(Queue*);
int	gets(IOQ*, void*, int);
void	gotolabel(Label*);
void	grpinit(void);
int	hwcursset(uchar*, uchar*, int, int);
int	hwcursmove(int, int);
void*	ialloc(ulong, int);
long	ibrk(ulong, int);
int	incref(Ref*);


@@ 91,23 95,23 @@ void	invalidateu(void);
void	isdir(Chan*);
int	ispages(void*);
void	kbdclock(void);
void	kbdrepeat(int);
int	kbdputc(IOQ*, int);
void	kbdrepeat(int);
void	kickpager(void);
int	kprint(char*, ...);
void	kproc(char*, void(*)(void*), void*);
void	kickpager(void);
void	lights(int);
void	lock(Lock*);
void	lockpage(Page*);
void	lockinit(void);
void	lockpage(Page*);
Page*	lookpage(Image*, ulong);
void	machinit(void);
void	mapstack(Proc*);
void	mfreeseg(Segment*, ulong, int);
void	mntdump(void);
void	mmurelease(Proc*);
int	mouseputc(IOQ*, int);
void	mntdump(void);
int	mount(Chan*, Chan*, int);
int	mouseputc(IOQ*, int);
Chan*	namec(char*, int, int, ulong);
Alarm*	newalarm(void);
Chan*	newchan(void);


@@ 118,7 122,7 @@ Page*	newpage(int, Segment **, ulong);
Pgrp*	newpgrp(void);
Proc*	newproc(void);
void	newqinfo(Qinfo*);
Segment* newseg(int, ulong, ulong);
Segment*	newseg(int, ulong, ulong);
char*	nextelem(char*, char*);
void	nexterror(void);
void	notify(Ureg*);


@@ 130,36 134,35 @@ int	pagemeis0(void*);
void	panic(char*, ...);
void	pexit(char*, int);
void	pgrpcpy(Pgrp*, Pgrp*);
void	pio(Segment *, ulong, ulong, Page **);
Pte*	ptecpy(Pte*);
void	putseg(Segment*);
void	putswap(Page*);
void	grpinit(void);
void	pgrpnote(Pgrp*, char*, long, int);
Pgrp*	pgrptab(int);
void	pio(Segment *, ulong, ulong, Page **);
#define	poperror()	u->nerrlab--
int	postnote(Proc*, int, char*, int);
int	pprint(char*, ...);
void	printinit(void);
void	procctl(Proc *p);
void	putimage(Image*);
void	putpage(Page*);
void	putstr(char*);
int	putc(IOQ*, int);
void	putstr(char*);
void	putstrn(char*, long);
void	puts(IOQ*, void*, int);
ulong 	procalarm(ulong);
ulong	procalarm(ulong);
void	procctl(Proc*);
void	procdump(void);
void	procinit0(void);
Proc*	proctab(int);
Pte*	ptealloc(void);
Pte*	ptecpy(Pte*);
Block*	pullup(Block *, int);
Queue*	pushq(Stream*, Qinfo*);
int	putb(Blist*, Block*);
void	putbq(Blist*, Block*);
int	putc(IOQ*, int);
void	putimage(Image*);
void	putmmu(ulong, ulong, Page*);
void	putpage(Page*);
int	putq(Queue*, Block*);
void	puts(IOQ*, void*, int);
void	putseg(Segment*);
void	putstr(char*);
void	putstr(char*);
void	putstrn(char*, long);
void	putswap(Page*);
ulong	pwait(Waitmsg*);
void	qlock(QLock*);
void	qunlock(QLock*);


@@ 174,12 177,14 @@ void	savefpregs(FPsave*);
void	sccintr(void);
void	sccsetup(void*);
void	sccspecial(int, IOQ*, IOQ*, int);
void	schedinit(void);
void	sched(void);
void	schedinit(void);
int	screenbits(void);
long	seconds(void);
Segment* seg(Proc*, ulong, int);
void	segpage(Segment*, Page*);
Segment*	seg(Proc*, ulong, int);
ulong	segattach(Proc*, ulong, char *, ulong, ulong);
void	segpage(Segment*, Page*);
int	setcolor(ulong, ulong, ulong, ulong);
int	setlabel(Label*);
void	setswapchan(Chan*);
char*	skipslash(char*);


@@ 187,13 192,13 @@ void	sleep(Rendez*, int(*)(void*), void*);
int	splhi(void);
int	spllo(void);
void	splx(int);
int	streamclose1(Stream*);
int	streamclose(Chan*);
int	streamclose1(Stream*);
int	streamenter(Stream*);
int	streamexit(Stream*, int);
Devgen	streamgen;
void	streaminit0(void);
void	streaminit(void);
void	streaminit0(void);
Stream*	streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);

M port/queue.c => port/queue.c +0 -1
@@ 4,7 4,6 @@
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"errno.h"

void
initq(IOQ *q)

M port/segment.c => port/segment.c +48 -10
@@ 11,6 11,7 @@
Page *lkpage(ulong addr);
Page *snewpage(ulong addr);
void lkpgfree(Page*);
void imagereclaim(void);

/* System specific segattach devices */
#include "segment.h"


@@ 30,6 31,8 @@ struct segalloc
	Segment *free;
}segalloc;

static QLock ireclaim;

void
initseg(void)
{


@@ 75,6 78,7 @@ newseg(int type, ulong base, ulong size)
			s->flen = 0;
			s->pgalloc = 0;
			s->pgfree = 0;
			s->flushme = 0;
			memset(s->map, 0, sizeof(s->map));

			return s;


@@ 135,13 139,20 @@ dupseg(Segment *s)
	int i;

	switch(s->type&SG_TYPE) {
	case SG_TEXT:		/* new segment shares pte set */
	case SG_TEXT:			/* New segment shares pte set */
	case SG_SHARED:
	case SG_PHYSICAL:
		incref(s);
		return s;
	case SG_DATA:		/* copy on write both old and new plus demand load info */
		lock(s);

	case SG_BSS:			/* Just copy on write */
	case SG_STACK:
		qlock(&s->lk);
		n = newseg(s->type, s->base, s->size);
		goto copypte;

	case SG_DATA:			/* Copy on write plus demand load info */
		qlock(&s->lk);
		n = newseg(s->type, s->base, s->size);

		incref(s->image);


@@ 152,13 163,10 @@ dupseg(Segment *s)
		for(i = 0; i < SEGMAPSIZE; i++)
			if(pte = s->map[i])
				n->map[i] = ptecpy(pte);
		unlock(s);

		n->flushme = s->flushme;
		qunlock(&s->lk);
		return n;	
	case SG_BSS:		/* Just copy on write */
	case SG_STACK:
		lock(s);
		n = newseg(s->type, s->base, s->size);
		goto copypte;
	}

	panic("dupseg");


@@ 188,6 196,7 @@ attachimage(int type, Chan *c, ulong base, ulong len)

	lock(&imagealloc);

	/* Search the image cache for remains of the text from a previous incarnation */
	for(i = ihash(c->qid.path); i; i = i->hash) {
		if(c->qid.path == i->qid.path) {
			lock(i);


@@ 204,6 213,7 @@ attachimage(int type, Chan *c, ulong base, ulong len)
	
	while(!(i = imagealloc.free)) {
		unlock(&imagealloc);
		imagereclaim();
		resrcwait("no images");
		lock(&imagealloc);
	}


@@ 236,6 246,32 @@ found:
}

void
imagereclaim(void)
{
	Page *p;

	if(!canqlock(&ireclaim))	/* Somebody is already cleaning the page cache */
		return;

	lock(&palloc);
	for(p = palloc.head; p; p = p->next) {
		if(p->image == 0)
			continue;

		unlock(&palloc);
		lockpage(p);
		if(p->ref == 0 && p->image != &swapimage)
			uncachepage(p);
		unlockpage(p);
		lock(&palloc);
	}

	unlock(&palloc);

	qunlock(&ireclaim);
}

void
putimage(Image *i)
{
	Image *f, **l;


@@ 271,7 307,7 @@ putimage(Image *i)
}

long
ibrk(ulong addr, int seg)		/* Called with a locked segment */
ibrk(ulong addr, int seg)
{
	Segment *s, *ns;
	ulong newtop, newsize;


@@ 428,6 464,8 @@ syssegflush(ulong *arg)
	if(s == 0)
		errors("bad segment address");

	s->flushme = 1;

	soff = arg[0]-s->base;
	j = (soff&(PTEMAPMEM-1))/BY2PG;
	pages = ((arg[0]+arg[1]+(BY2PG-1))&~(BY2PG-1))-(arg[0]&~(BY2PG-1));

M port/swap.c => port/swap.c +2 -3
@@ 9,7 9,6 @@
/* Predeclaration */
void	pageout(Proc *p, Segment*);
int	pagepte(int, Segment*, Page**);
void	openswap(void);
int	needpages(void*);
void	pager(void*);
void	executeio(void);


@@ 17,7 16,7 @@ int	canflush(Proc *p, Segment*);

enum
{
	Maxpages = 500,		/* Max number of pageouts per process pass */
	Maxpages = 500,		/* Max number of pageouts per segment pass */
};

Image 	swapimage;


@@ 196,7 195,7 @@ canflush(Proc *p, Segment *s)
	unlock(s);

	/* Now we must do hardwork to ensure all processes which have tlb
	 * entries for this segment are flushed
	 * entries for this segment will be flushed if we suceed in pageing it out
	 */
	p = proctab(0);
	ep = &p[conf.nproc];

M port/sysfile.c => port/sysfile.c +2 -2
@@ 124,7 124,7 @@ sysdup(ulong *arg)
		unlock(f);
		if(oc)
			close(oc);
	}else {
	}else{
		if(waserror()) {
			close(c);
			nexterror();


@@ 144,7 144,7 @@ sysopen(ulong *arg)
	Chan *c = 0;

	openmode(arg[1]);	/* error check only */
	if(waserror()) {
	if(waserror()){
		if(c)
			close(c);
		nexterror();

M port/sysproc.c => port/sysproc.c +6 -6
@@ 129,6 129,7 @@ sysexec(ulong *arg)
	}
	if(!indir)
		strcpy(elem, u->elem);

	n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0);
	if(n < 2)
    Err:


@@ 257,6 258,7 @@ sysexec(ulong *arg)
	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
	ts = img->s;
	p->seg[TSEG] = ts;
	ts->flushme = 1;
	ts->fstart = 0;
	ts->flen = sizeof(Exec)+exec.text;



@@ 270,12 272,9 @@ sysexec(ulong *arg)
	s->fstart = ts->fstart+ts->flen;
	s->flen = exec.data;


	/* BSS. Zero fill on demand */
	p->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);

	close(tc);

	/*
	 * Move the stack
	 */


@@ 286,6 285,7 @@ sysexec(ulong *arg)
	relocateseg(s, TSTKTOP-USTKTOP);
	p->seg[ESEG] = 0;

	close(tc);
	poperror();

	/*


@@ 525,12 525,12 @@ syssegfree(ulong *arg)
	Segment *s;
	ulong from, len;

	s = seg(u->p, arg[0], 1);
	from = PGROUND(arg[0]);
	s = seg(u->p, from, 1);
	if(s == 0)
		errors("not in address space");

	from = PGROUND(arg[1]);
	len = arg[2];
	len = arg[1];

	if(from+len > s->top) {
		qunlock(&s->lk);

M ss/dat.h => ss/dat.h +4 -6
@@ 64,9 64,10 @@ struct Conf
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
	ulong	npage;		/* total physical pages of memory */
	ulong	norig;		/* origins */
	ulong	npte;		/* contiguous page table entries */
	ulong	nmod;		/* single (modifying) page table entries */
	ulong	nseg;		/* number of segments */
	ulong	nimage;		/* number of page cache image headers */
	ulong 	npagetab;	/* number of pte tables */
	ulong	nswap;		/* number of swap blocks */
	int	nalarm;		/* alarms */
	int	nchan;		/* channels */
	int	nenv;		/* distinct environment values */


@@ 147,7 148,6 @@ struct Mach

#define	NERR	15
#define	NNOTE	5
#define	NFD	100
struct User
{
	Proc	*p;


@@ 158,8 158,6 @@ struct User
	char	elem[NAMELEN];		/* last name element from namec */
	Chan	*slash;
	Chan	*dot;
	Chan	*fd[NFD];
	int	maxfd;			/* highest fd in use */
	/*
	 * Rest of structure controlled by devproc.c and friends.
	 * lock(&p->debug) to modify.

M ss/main.c => ss/main.c +17 -18
@@ 34,7 34,8 @@ main(void)
	cacheinit();
	intrinit();
	procinit0();
	pgrpinit();
	initseg();
	grpinit();
	chaninit();
	alarminit();
	chandevreset();


@@ 109,6 110,7 @@ init0(void)
	u->slash = (*devtab[0].attach)(0);
	u->dot = clone(u->slash, 0);

	kickpager();
	touser(USTKTOP-5*BY2WD);
}



@@ 118,12 120,15 @@ void
userinit(void)
{
	Proc *p;
	Seg *s;
	Segment *s;
	User *up;
	KMap *k;

	p = newproc();
	p->pgrp = newpgrp();
	p->egrp = newegrp();
	p->fgrp = newfgrp();

	strcpy(p->text, "*init*");
	savefpregs(&initfp);
	p->fpstate = FPinit;


@@ 146,25 151,18 @@ userinit(void)
	/*
	 * User Stack
	 */
	s = &p->seg[SSEG];
	s->proc = p;
	s->o = neworig(USTKTOP-BY2PG, 1, OWRPERM, 0);
	s->minva = USTKTOP-BY2PG;
	s->maxva = USTKTOP;
	s = newseg(SG_STACK, USTKTOP-BY2PG, 1);
	p->seg[SSEG] = s;

	/*
	 * Text
	 */
	s = &p->seg[TSEG];
	s->proc = p;
	s->o = neworig(UTZERO, 1, 0, 0);
	s->o->pte[0].page = newpage(0, 0, UTZERO);
	s->o->npage = 1;
	k = kmap(s->o->pte[0].page);
	s = newseg(SG_TEXT, UTZERO, 1);
	p->seg[TSEG] = s;
	segpage(s, newpage(1, 0, UTZERO));
	k = kmap(s->map[0]->pages[0]);
	memmove((ulong*)VA(k), initcode, sizeof initcode);
	kunmap(k);
	s->minva = UTZERO;
	s->maxva = UTZERO+BY2PG;

	ready(p);
}


@@ 271,10 269,11 @@ confinit(void)
		mul = 2;
	conf.nproc = 50*mul;
	conf.npgrp = 12*mul;
	conf.npte = 1400*mul;
	conf.nmod = 800*mul;
	conf.nseg = conf.nproc*4;
	conf.npagetab = conf.nseg*2;
	conf.nswap = 4096;
	conf.nimage = 50;
	conf.nalarm = 1000;
	conf.norig = 150*mul;
	conf.nchan = 200*mul;
	conf.nenv = 100*mul;
	conf.nenvchar = 8000*mul;

M ss/mem.h => ss/mem.h +3 -0
@@ 93,6 93,9 @@
#define	PTEACCESS	(1<<25)
#define	PTEMODIFY	(1<<24)
#define PTEUNCACHED	0
#define PTEMAPMEM	(1024*1024)	
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
#define SEGMAPSIZE	16

#define	INVALIDPTE	0
#define	PPN(pa)		((pa>>12)&0xFFFF)

M ss/mmu.c => ss/mmu.c +13 -1
@@ 22,6 22,8 @@ struct

int	newpid(Proc*);
void	purgepid(int);
void	flushcontext(void);

int	pidtime[NTLBPID];	/* should be per m */

/*


@@ 33,6 35,16 @@ mapstack(Proc *p)
	short tp;
	ulong tlbphys;

	if(p->newtlb) {
		flushcontext();
		tp = u->p->pidonmach[m->machno];
		if(tp)
			pidtime[tp] = 0;
		/* easiest is to forget what pid we had.... */
		memset(u->p->pidonmach, 0, sizeof u->p->pidonmach);
		p->newtlb = 0;
	}

	tp = p->pidonmach[m->machno];
	if(tp == 0){
		tp = newpid(p);


@@ 194,7 206,7 @@ mmuinit(void)
}

void
putmmu(ulong tlbvirt, ulong tlbphys)
putmmu(ulong tlbvirt, ulong tlbphys, Page *pg)
{
	short tp;
	Proc *p;

A ss/segment.h => ss/segment.h +19 -0
@@ 0,0 1,19 @@
/*
 * Attach segment types
 */

typedef struct Physseg Physseg;
struct Physseg
{
	ulong	attr;			/* Segment attributes */
	char	*name;			/* Attach name */
	ulong	pa;			/* Physical address */
	ulong	size;			/* Maximum segment size in pages */
	Page	*(*pgalloc)(ulong);	/* Allocation if we need it */
	void	(*pgfree)(Page*);
}physseg[] = {
	{ SG_SHARED,	"shared",	0,	SEGMAXSIZE,	0, 	0 },
	{ SG_PHYSICAL,	"kmem",		KZERO,	SEGMAXSIZE,	0,	0 },
	{ SG_BSS,	"memory",	0,	SEGMAXSIZE,	0,	0 },
	{ 0,		0,		0,	0,		0,	0 },
};