~kris/9p

9hist

56d6000950883bfd3f5cad269bd5180e69ea96c4 — David du Colombier 34 years ago b289cd8
Plan 9 from Bell Labs 1992-06-21
M gnot/dat.h => gnot/dat.h +1 -14
@@ 68,30 68,20 @@ struct Conf
{
	int	nmach;		/* processors */
	int	nproc;		/* processes */
	int	npgrp;		/* process groups */
	ulong	npage0;		/* total physical pages of memory, bank 0 */
	ulong	npage1;		/* total physical pages of memory, bank 1 */
	ulong	npage;
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
	ulong	nseg;		/* number of segments */
	ulong	upages;		/* user page pool */
	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 */
	int	nenvchar;	/* environment text storage */
	int	npgenv;		/* environment files per process group */
	int	nmtab;		/* mounted-upon channels per process group */
	int	nmount;		/* mounts */
	int	nmntdev;	/* mounted devices (devmnt.c) */
	int	nmntbuf;	/* buffers for devmnt.c messages */
	int	nmnthdr;	/* headers for devmnt.c messages */
	int	nmux;		/* number of mux devices */
	int	nstream;	/* streams */
	int	nqueue;		/* stream queues */
	int	nblock;		/* stream blocks */
	int	nsrv;		/* public servers (devsrv.c) */
	int	nbitmap;	/* bitmap structs (devbit.c) */
	int	nbitbyte;	/* bytes of bitmap data (devbit.c) */


@@ 99,12 89,9 @@ struct Conf
	int	nsubfont;	/* Gsubfont structs (devbit.c) */
	int	nurp;		/* max urp conversations */
	int	nasync;		/* number of async protocol modules */
	int	npipe;		/* number of pipes */
	int	nservice;	/* number of services */
	int	nfsyschan;	/* number of filsys open channels */
	int	nisdn;		/* number of isdn interfaces */
	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;	/* ??? */
	int	cntrlp;		/* panic on ^P */

M gnot/devport.c => gnot/devport.c +41 -20
@@ 11,7 11,15 @@
#define	ROMADDR	0x40000000
#define	ROMSIZE	((256*1024)/8)

enum {
#define	P_oper(sel, inst)	(P_qlock(sel), inst, P_qunlock(sel))
#define	P_qlock(sel)		(sel >= 0 ? (qlock(&portpage), \
				PORTSELECT = portpage.select = sel) : -1)
#define	P_qunlock(sel)		(sel >= 0 ? (qunlock(&portpage),0) : -1)
#define	P_read(sel, addr, val, type)	P_oper(sel, val = *(type *)(PORT+addr))
#define	P_write(sel, addr, val, type)	P_oper(sel, *(type *)(PORT+addr) = val)

enum
{
	Qdir,
	Qdata,
	Qrom


@@ 24,6 32,11 @@ Dirtab portdir[]={

#define	NPORT	(sizeof portdir/sizeof(Dirtab))

#define	Nportservice	8
static	int (*portservice[Nportservice])(void);
static	Portpage portpage;
static	Lock intrlock;

int
portprobe(char *what, int select, int addr, int rw, long val)
{


@@ 33,17 46,23 @@ portprobe(char *what, int select, int addr, int rw, long val)
	P_qlock(select);
	switch (rw) {
	case -1:
		val = *(uchar *)(PORT+addr); break;
		val = *(uchar *)(PORT+addr);
		break;
	case -2:
		val = *(ushort *)(PORT+addr); break;
		val = *(ushort *)(PORT+addr);
		break;
	case -4:
		val = *(long *)(PORT+addr); break;
		val = *(long *)(PORT+addr);
		break;
	case 1:
		*(uchar *)(PORT+addr) = val; break;
		*(uchar *)(PORT+addr) = val;
		break;
	case 2:
		*(ushort *)(PORT+addr) = val; break;
		*(ushort *)(PORT+addr) = val;
		break;
	case 4:
		*(long *)(PORT+addr) = val; break;
		*(long *)(PORT+addr) = val;
		break;
	default:
		panic("portprobe");
	}


@@ 68,7 87,8 @@ portreset(void)

void
portinit(void)
{}
{
}

Chan *
portattach(char *param)


@@ 108,7 128,8 @@ portcreate(Chan *c, char *name, int omode, ulong perm)

void
portclose(Chan *c)
{}
{
}

long
portread(Chan *c, char *a, long n, ulong offset)


@@ 167,9 188,11 @@ portwrite(Chan *c, char *a, long n, ulong offset)
		case 1:
			PORT[k] = *a; break;
		case 2:
			*(short *)(PORT+k) = *(short *)a; break;
			*(short *)(PORT+k) = *(short *)a;
			break;
		case 4:
			*(long *)(PORT+k) = *(long *)a; break;
			*(long *)(PORT+k) = *(long *)a;
			break;
		default:
			P_qunlock(s);
			error(Ebadarg);


@@ 185,27 208,23 @@ portwrite(Chan *c, char *a, long n, ulong offset)
void
portremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
portwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

#define	Nportservice	8
int	(*portservice[Nportservice])(void);

Portpage portpage;

Lock	intrlock;

void
addportintr(int (*f)(void))
{
	int s = splhi();
	int (**p)(void);

	lock(&intrlock);
	for (p=portservice; *p; p++)
		if (*p == f)


@@ 221,13 240,15 @@ out:
void
devportintr(void)
{
	int (**p)(void); int i = 0;
	int (**p)(void);
	int i = 0;

	for (p=portservice; *p; p++)
		i |= (**p)();

	if (!i)
		/*putstring("spurious portintr\n");*/
		panic("portintr");
	if (portpage.select >= 0)
		PORTSELECT = portpage.select;

}

M gnot/fns.h => gnot/fns.h +2 -6
@@ 1,11 1,5 @@
#include "../port/portfns.h"

#define	P_oper(sel, inst)	(P_qlock(sel), inst, P_qunlock(sel))
#define	P_qlock(sel)	(sel >= 0 ? (qlock(&portpage), PORTSELECT = portpage.select = sel) : -1)
#define	P_qunlock(sel)	(sel >= 0 ? (qunlock(&portpage),0) : -1)
#define	P_read(sel, addr, val, type)	P_oper(sel, val = *(type *)(PORT+addr))
#define	P_write(sel, addr, val, type)	P_oper(sel, *(type *)(PORT+addr) = val)

void	addportintr(int (*)(void));
void	bootargs(ulong);
void	clearmmucache(void);


@@ 63,3 57,5 @@ void	touser(void*);
#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define	kmapperm(x)	kmap(x)
#define getcallerpc(x)	(*(ulong*)(x))
#define KADDR(a)	((void*)((ulong)(a)|KZERO))
#define PADDR(a)	((ulong)(a)&~KZERO)

M gnot/main.c => gnot/main.c +3 -15
@@ 312,27 312,17 @@ confinit(void)
	conf.npage1 = (bank[1]*1024*1024)/BY2PG;
	conf.base1 = 16*1024*1024;
	conf.npage = conf.npage0+conf.npage1;
	conf.maxialloc = (4*1024*1024-256*1024-BY2PG);
	conf.upages = (conf.npage*70)/100;

	mul = 1 + (conf.npage1>0);
	conf.nproc = 50*mul;
	conf.nseg = conf.nproc*4;
	conf.npagetab = conf.nseg*2;
	conf.nswap = 4096;
	conf.nimage = 50;
	conf.npgrp = 20*mul;
	conf.nalarm = 1000;
	conf.nchan = 200*mul;
	conf.nenv = 100*mul;
	conf.nenvchar = 8000*mul;
	conf.npgenv = 200*mul;
	conf.nmtab = 50*mul;
	conf.nmount = 80*mul;
	conf.nmntdev = 10*mul;
	conf.nmntbuf = conf.nmntdev+5;
	conf.nmnthdr = 2*conf.nmntdev;
	conf.nstream = 40 + 32*mul;
	conf.nqueue = 5 * conf.nstream;
	conf.nblock = 24 * conf.nstream;
	conf.nsrv = 16*mul;			/* was 32 */
	conf.nbitmap = 300*mul;
	conf.nbitbyte = 300*1024*mul;


@@ 343,13 333,11 @@ confinit(void)
	conf.nfont = 10*mul;
	conf.nurp = 32;
	conf.nasync = 1;
	conf.npipe = conf.nstream/2;
	conf.nservice = 3*mul;			/* was conf.nproc/5 */
	conf.nfsyschan = 31 + conf.nchan/20;
	conf.copymode = 0;		/* copy on write */
	conf.portispaged = 0;
	conf.cntrlp = 0;
	conf.dkif = 2;

	confinit1(mul);
}


M port/alloc.c => port/alloc.c +43 -10
@@ 4,9 4,18 @@
#include	"dat.h"
#include	"fns.h"

/*
 * Plan 9 has two kernel allocators, the x... routines provide a first
 * fit hole allocator which should be used for permanent or large structures.
 * Routines are provided to allocate aligned memory which does not cross
 * arbitrary 2^n boundaries. A second allocator malloc, smalloc, free is
 * a 2n bucket allocator which steals from the x routines. This should
 * be used for small frequently used structures.
 */

#define	nil		((void*)0)
#define datoff		((ulong)&((Xhdr*)0)->data)
#define bdatoff		((ulong)&((Bucket*)0)->data)
#define datoff		((ulong)((Xhdr*)0)->data)
#define bdatoff		((ulong)((Bucket*)0)->data)

enum
{


@@ 14,6 23,7 @@ enum
	Nhole		= 128,
	Magichole	= 0xDeadBabe,
	Magic2n		= 0xFeedBeef,
	Spanlist	= 64,
};

typedef struct Hole Hole;


@@ 75,14 85,7 @@ ialloc(ulong size, int align)
		p &= ~(BY2PG-1);
		return (void*)p;
	}

	return xalloc(size);
}

void*
iallocspan(ulong size, int quanta, ulong span)
{
	return ialloc(size, quanta);
	return xalloc(size);;
}

void


@@ 127,6 130,36 @@ xinit(void)
	palloc.np1 = np1;
}

/*
 * NB. spanalloc memory will cause a panic if free'd
 */
void*
xspanalloc(ulong size, int align, ulong span)
{
	int i, j;
	ulong a, p;
	ulong ptr[Spanlist];

	span = ~(span-1);
	for(i = 0; i < Spanlist; i++) {
		p = (ulong)xalloc(size+align);
		if(p == 0)
			panic("xspanalloc: size %d align %d span %d", size, align, span);

		a = p+align;
		a &= ~(align-1);
		if((a&span) == ((a+size)&span)) {
			for(j = 0; j < i; j++)
				xfree((void*)ptr[j]);

			return (void*)a;
		}
		ptr[i] = p;
	}
	panic("xspanalloc: spanlist");		
	return 0;
}

void*
xalloc(ulong size)
{

M port/devbit.c => port/devbit.c +180 -149
@@ 37,23 37,26 @@ int flipping;	/* are flip tables being used to transform Fcodes? */
 */

/*
 * Some fields in GBitmaps are overloaded:
 *	ldepth = -1 means free.
 *	base is next pointer when free.
 * Arena is a word containing N, followed by a pointer to its bitmap,
 * followed by N blocks.  The bitmap pointer is zero if block is free. 
 * followed by N blocks.  The bitmap pointer is zero if block is free.
 * bit.map is an array of pointers to GBitmaps.  The GBitmaps are
 * freed individually and their corresponding entries in bit.map are zeroed.
 * The index into bit.map is the Bitmap id as seen in libg.  Subfonts and
 * fonts are handled similarly.
 */

struct
{
	Ref;
	GBitmap	*map;		/* arena */
	GBitmap	*free;		/* free list */
	GBitmap	**map;		/* indexed array */
	int	nmap;		/* number allocated */
	ulong	*words;		/* storage */
	ulong	nwords;		/* total in arena */
	ulong	*wfree;		/* pointer to next free word */
	GFont *font;		/* arena; looked up linearly BUG */
	GSubfont *subfont;	/* arena; looked up linearly BUG */
	GFont	**font;		/* indexed array */
	int	nfont;		/* number allocated */
	GSubfont**subfont;	/* indexed array */
	int	nsubfont;	/* number allocated */
	int	lastid;		/* last allocated bitmap id */
	int	lastsubfid;	/* last allocated subfont id */
	int	lastfid;	/* last allocated font id */


@@ 64,10 67,13 @@ struct
	int	mid;		/* colormap read bitmap id */
}bit;

#define	DMAP	32		/* delta increase in size of arrays */
#define	FREE	0x80000000
void	bitcompact(void);
GBitmap*bitalloc(Rectangle, int);
int	bitalloc(Rectangle, int);
void	bitfree(GBitmap*);
void	fontfree(GFont*);
void	subfontfree(GSubfont*);
void	bitstring(GBitmap*, Point, GFont*, uchar*, long, Fcode);
void	bitloadchar(GFont*, int, GSubfont*, int);
extern	GBitmap	gscreen;


@@ 142,7 148,7 @@ Dirtab bitdir[]={
};

#define	NBIT	(sizeof bitdir/sizeof(Dirtab))
#define	NINFO	257
#define	NINFO	8192

void
bitreset(void)


@@ 151,31 157,22 @@ bitreset(void)
	GBitmap *bp;
	ulong r;

	bit.map = ialloc(conf.nbitmap * sizeof(GBitmap), 0);
	for(i=0,bp=bit.map; i<conf.nbitmap; i++,bp++){
		bp->ldepth = -1;
		bp->base = (ulong*)(bp+1);
	}
	bp--;
	bp->base = 0;
	bit.map[0] = gscreen;	/* bitmap 0 is screen */
	bit.map = smalloc(DMAP*sizeof(GBitmap*));
	bit.nmap = DMAP;
	getcolor(0, &r, &r, &r);
	if(r == 0)
		flipping = 1;
	bit.free = bit.map+1;
	bit.lastid = -1;
	bit.lastsubfid = -1;
	bit.lastfid = -1;
	bit.words = ialloc(conf.nbitbyte, 0);
print("bitreset %lux\n", bit.words);
	bit.nwords = conf.nbitbyte/sizeof(ulong);
	bit.wfree = bit.words;
	bit.subfont = ialloc(conf.nsubfont * sizeof(GSubfont), 0);
	bit.subfont[0] = *defont;
	bit.font = ialloc(conf.nfont * sizeof(GFont), 0);
	for(i=1; i<conf.nsubfont; i++)
		bit.subfont[i].info = ialloc((NINFO+1)*sizeof(Fontchar), 0);
	for(i=0; i<conf.nfont; i++)
		bit.font[i].ldepth = -1;
	bit.font = smalloc(DMAP*sizeof(GFont*));
	bit.nfont = DMAP;
	bit.subfont = smalloc(DMAP*sizeof(GSubfont*));
	bit.nsubfont = DMAP;
	Cursortocursor(&arrow);
}



@@ 186,7 183,7 @@ bitinit(void)
	unlock(&bit);
	if(gscreen.ldepth > 3)
		cursorback.ldepth = 0;
	else {
	else{
		cursorback.ldepth = gscreen.ldepth;
		cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5;
	}


@@ 196,7 193,6 @@ bitinit(void)
Chan*
bitattach(char *spec)
{
	bit.map[0] = gscreen;	/* bitmap 0 is screen */
	return devattach('b', spec);
}



@@ 221,9 217,11 @@ bitstat(Chan *c, char *db)
	devstat(c, db, bitdir, NBIT, devgen);
}

Chan *
Chan*
bitopen(Chan *c, int omode)
{
	GBitmap *b;

	if(c->qid.path == CHDIR){
		if(omode != OREAD)
			error(Eperm);


@@ 233,7 231,10 @@ bitopen(Chan *c, int omode)
			unlock(&bit);
			error(Einuse);
		}
		bit.map[0].clipr = gscreen.clipr;
		b = smalloc(sizeof(GBitmap));
		*b = gscreen;
		bit.map[0] = b;			/* bitmap 0 is screen */
		bit.subfont[0] = defont;	/* subfont 0 is default */
		bit.lastid = -1;
		bit.lastfid = -1;
		bit.lastsubfid = -1;


@@ 275,24 276,43 @@ bitwstat(Chan *c, char *db)
void
bitclose(Chan *c)
{
	int i;
	GBitmap *bp;
	GSubfont *fp;
	GFont *ffp;
	GBitmap *b, **bp, **ebp;
	GSubfont *s, **sp, **esp;
	GFont *f, **fp, **efp;

	if(c->qid.path!=CHDIR && (c->flag&COPEN)){
		lock(&bit);
		if(--bit.ref == 0){
			for(i=1,bp=&bit.map[1]; i<conf.nbitmap; i++,bp++)
				if(bp->ldepth >= 0)
					bitfree(bp);
			for(i=1,fp=&bit.subfont[1]; i<conf.nsubfont; i++,fp++)
				fp->bits = 0;
			for(i=0,ffp=&bit.font[0]; i<conf.nfont; i++,ffp++){
				ffp->b = 0;
				ffp->ldepth = -1;
			/* 0th bitmap, screen, has no special storage */
			bp = bit.map;
			free(*bp);
			*bp = 0;
			ebp = &bit.map[bit.nmap];
			bp++;
			for(; bp<ebp; bp++){
				b = *bp;
				if(b){
					bitfree(b);
					*bp = 0;
				}
			}
			/* 0th subfont, defont, points to real storage */
			esp = &bit.subfont[bit.nsubfont];
			for(sp=&bit.subfont[1]; sp<esp; sp++){
				s = *sp;
				if(s){
					subfontfree(s);
					*sp = 0;
				}
			}
			efp = &bit.font[bit.nfont];
			for(fp=bit.font; fp<efp; fp++){
				f = *fp;
				if(f){
					fontfree(f);
					*fp = 0;
				}
			}
bit.font[0].ldepth=0;/*BUG */
		}
		unlock(&bit);
	}


@@ 440,7 460,10 @@ bitread(Chan *c, void *va, long n, ulong offset)
			 * read colormap:
			 *	data		12*(2**bitmapdepth)
			 */
			l = (1<<bit.map[bit.mid].ldepth);
			src = bit.map[bit.mid];
			if(src == 0)
				error(Ebadbitmap);
			l = (1<<src->ldepth);
			nw = 1 << l;
			if(n < 12*nw)
				error(Ebadblt);


@@ 467,8 490,8 @@ bitread(Chan *c, void *va, long n, ulong offset)
			 * read bitmap:
			 *	data		bytewidth*(maxy-miny)
			 */
			src = &bit.map[bit.rid];
			if(src->ldepth<0)
			src = bit.map[bit.rid];
			if(src == 0)
				error(Ebadbitmap);
			off = 0;
			if(bit.rid == 0)


@@ 558,15 581,15 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	uchar *p, *q;
	long m, v, miny, maxy, minx, maxx, t, x, y;
	ulong l, nw, ws, rv;
	int off, isoff, i, ok;
	int off, isoff, i, j, ok;
	Point pt, pt1, pt2;
	Rectangle rect;
	Cursor curs;
	Fcode fc;
	Fontchar *fcp;
	GBitmap *bp, *src, *dst;
	GSubfont *f;
	GFont *ff;
	GBitmap *b, *src, *dst, *bp;
	GSubfont *f, **fp;
	GFont *ff, **ffp;

	if(c->qid.path == CHDIR)
		error(Eisdir);


@@ 582,6 605,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	}
	p = va;
	m = n;
	SET(src, dst, f, ff);
	while(m > 0)
		switch(*p){
		default:


@@ 607,8 631,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			rect.max.y = GLONG(p+14);
			if(Dx(rect) < 0 || Dy(rect) < 0)
				error(Ebadblt);
			bp = bitalloc(rect, v);
			bit.lastid = bp-bit.map;
			bit.lastid = bitalloc(rect, v);
			m -= 18;
			p += 18;
			break;


@@ 627,8 650,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				error(Ebadblt);
			fc = GSHORT(p+29) & 0xF;
			v = GSHORT(p+11);
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth < 0)
			if(v<0 || v>=bit.nmap || (src=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0){


@@ 637,8 659,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				off = 1;
			}
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth < 0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			if(v == 0){
				if(flipping)


@@ 703,10 724,10 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 3)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			bitfree(dst);
			bit.map[v] = 0;
			m -= 3;
			p += 3;
			break;


@@ 720,10 741,10 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 3)
				error(Ebadblt);
			v = GSHORT(p+1);
			f = &bit.subfont[v];
			if(v<0 || v>=conf.nsubfont || f->bits==0)
			if(v<0 || v>=bit.nsubfont || (f=bit.subfont[v])==0)
				error(Ebadfont);
			f->bits = 0;
			subfontfree(f);
			bit.subfont[v] = 0;
			m -= 3;
			p += 3;
			break;


@@ 737,13 758,10 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 3)
				error(Ebadblt);
			v = GSHORT(p+1);
			ff = &bit.font[v];
			if(v<0 || v>=conf.nfont || ff->ldepth<0)
			if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0)
				error(Ebadfont);
			if(ff->b)
				bitfree(ff->b);
			ff->b = 0;
			ff->ldepth = -1;
			fontfree(ff);
			bit.font[v] = 0;
			m -= 3;
			p += 3;
			break;


@@ 776,23 794,28 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			v = GSHORT(p+1);
			if(v<0 || v>NINFO || m<7+6*(v+1))	/* BUG */
				error(Ebadblt);
			for(i=1; i<conf.nsubfont; i++)
				if(bit.subfont[i].bits == 0)
			for(i=1; i<bit.nsubfont; i++)
				if(bit.subfont[i] == 0)
					goto subfontfound;
			error(Enofont);
			fp = bit.subfont;
			bit.subfont = smalloc((bit.nsubfont+DMAP)*sizeof(GSubfont*));
			memmove(bit.subfont, fp, bit.nsubfont*sizeof(GSubfont*));
			free(fp);
			bit.nsubfont += DMAP;
		subfontfound:
			f = &bit.subfont[i];
			f = smalloc(sizeof(GSubfont));
			bit.subfont[i] = f;
			f->info = smalloc((v+1)*sizeof(Fontchar));
			f->n = v;
			f->height = p[3];
			f->ascent = p[4];
			v = GSHORT(p+5);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			m -= 7;
			p += 7;
			fcp = f->info;
			for(i=0; i<=f->n; i++,fcp++){
			for(j=0; j<=f->n; j++,fcp++){
				fcp->x = GSHORT(p);
				fcp->top = p[2];
				fcp->bottom = p[3];


@@ 802,7 825,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				p += 6;
				m -= 6;
			}
			bit.lastsubfid = f - bit.subfont;
			bit.lastsubfid = i;
			f->bits = dst;
			break;



@@ 820,8 843,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 22)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			fc = GSHORT(p+20) & 0xF;


@@ 854,8 876,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 3)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			bit.mid = v;
			m -= 3;


@@ 876,12 897,18 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			v = GSHORT(p+3);
			if(v < 0)
				error(Ebadblt);
			for(i=0; i<conf.nfont; i++)
				if(bit.font[i].ldepth < 0)
			for(i=0; i<bit.nfont; i++)
				if(bit.font[i] == 0)
					goto fontfound;
			error(Enofont);
			ffp = bit.font;
			bit.font = smalloc((bit.nfont+DMAP)*sizeof(GFont*));
			memmove(bit.font, ffp, bit.nfont*sizeof(GFont*));
			free(ffp);
			bit.nfont += DMAP;
		fontfound:
			ff = &bit.font[i];
			ff = smalloc(sizeof(GFont));
			bit.font[i] = ff;
			ff = bit.font[i];
			ff->height = p[1];
			ff->ascent = p[2];
			ff->ldepth = v;


@@ 889,7 916,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			ff->b = 0;
			m -= 5;
			p += 5;
			bit.lastfid = ff - bit.font;
			bit.lastfid = i;
			break;

		case 'p':


@@ 905,8 932,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 14)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			fc = GSHORT(p+12) & 0xF;


@@ 937,8 963,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 19)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			rect.min.x = GLONG(p+3);
			rect.min.y = GLONG(p+7);


@@ 963,8 988,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 11)
				error(Ebadblt);
			v = GSHORT(p+1);
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth<0)
			if(v<0 || v>=bit.nmap || (src=bit.map[v])==0)
				error(Ebadbitmap);
			miny = GLONG(p+3);
			maxy = GLONG(p+7);


@@ 990,8 1014,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 16)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			fc = GSHORT(p+13) & 0xF;


@@ 1003,8 1026,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			pt.x = GLONG(p+3);
			pt.y = GLONG(p+7);
			v = GSHORT(p+11);
			f = &bit.subfont[v];
			if(v<0 || v>=conf.nsubfont || f->bits==0 || f->bits->ldepth<0)
			if(v<0 || v>=bit.nsubfont || (f=bit.subfont[v])==0)
				error(Ebadblt);
			p += 15;
			m -= 15;


@@ 1033,8 1055,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 23)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			fc = GSHORT(p+21) & 0xF;


@@ 1048,8 1069,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			rect.max.x = GLONG(p+11);
			rect.max.y = GLONG(p+15);
			v = GSHORT(p+19);
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth<0)
			if(v<0 || v>=bit.nmap || (src=bit.map[v])==0)
				error(Ebadbitmap);
			if(off && !isoff){
				cursoroff(1);


@@ 1074,8 1094,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 17)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			fc = GSHORT(p+13) & 0xF;


@@ 1087,8 1106,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			pt.x = GLONG(p+3);
			pt.y = GLONG(p+7);
			v = GSHORT(p+11);
			ff = &bit.font[v];
			if(v<0 || v>=conf.nfont || ff->ldepth<0)
			if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0)
				error(Ebadblt);
			l = GSHORT(p+15)*2;
			p += 17;


@@ 1114,8 1132,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 5)
				error(Ebadblt);
			v = GSHORT(p+1);
			ff = &bit.font[v];
			if(v<0 || v>=conf.nfont || ff->ldepth<0)
			if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0)
				error(Ebadblt);
			/*
			 * memset not necessary but helps avoid


@@ 1127,7 1144,9 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				bitfree(ff->b);
			ff->width = GSHORT(p+3);
			ff->b = 0;
			ff->b = bitalloc(Rect(0, 0, (NFCACHE+NFLOOK)*ff->width, ff->height), ff->ldepth);
			i = bitalloc(Rect(0, 0, (NFCACHE+NFLOOK)*ff->width, ff->height), ff->ldepth);
			ff->b = bit.map[i];
			bit.map[i] = 0;	/* disconnect it from GBitmap space */
			p += 5;
			m -= 5;
			break;


@@ 1144,8 1163,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 11)
				error(Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth<0)
			if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0)
				error(Ebadbitmap);
			off = 0;
			if(v == 0)


@@ 1216,15 1234,13 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			if(m < 9)
				error(Ebadblt);
			v = GSHORT(p+1);
			ff = &bit.font[v];
			if(v<0 || v>=conf.nfont || ff->ldepth<0 || ff->b==0)
			if(v<0 || v>=conf.nfont || (ff=bit.font[v])==0)
				error(Ebadblt);
			l = GSHORT(p+3);
			if(l >= NFCACHE+NFLOOK)
				error(Ebadblt);
			v = GSHORT(p+5);
			f = &bit.subfont[v];
			if(v<0 || v>=conf.nsubfont || f->bits->ldepth<0)
			if(v<0 || v>=conf.nsubfont || (f=bit.subfont[v])==0)
				error(Ebadblt);
			nw = GSHORT(p+7);
			if(nw >= f->n)


@@ 1249,7 1265,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				error(Ebadbitmap);
			m -= 3;
			p += 3;
			nw = 1 << (1 << bit.map[v].ldepth);
			nw = 1 << (1 << gscreen.ldepth);
			if(m < 12*nw)
				error(Ebadblt);
			ok = 1;


@@ 1273,21 1289,20 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	return n;
}

GBitmap*
int
bitalloc(Rectangle rect, int ld)
{
	GBitmap *bp;
	GBitmap *b, **bp, **ep;
	ulong l, ws, nw;
	long t;
	int i;

	if(bit.free == 0)
		error(Enobitmap);
print("bitalloc %lux\n", bit.wfree);
	ws = 1<<(5-ld);	/* pixels per word */
	if(rect.min.x >= 0) {
	if(rect.min.x >= 0){
		l = (rect.max.x+ws-1)/ws;
		l -= rect.min.x/ws;
	}
	else{	/* make positive before divide */
	}else{	/* make positive before divide */
		t = (-rect.min.x)+ws-1;
		t = (t/ws)*ws;
		l = (t+rect.max.x+ws-1)/ws;


@@ 1298,34 1313,60 @@ bitalloc(Rectangle rect, int ld)
		if(bit.wfree+2+nw > bit.words+bit.nwords)
			error(Enobitstore);
	}
	bp = bit.free;
	bit.free = (GBitmap*)(bp->base);
	b = smalloc(sizeof(GBitmap));
	*bit.wfree++ = nw;
	*bit.wfree++ = (ulong)bp;
	bp->base = bit.wfree;
	memset(bp->base, 0, nw*sizeof(ulong));
	*bit.wfree++ = (ulong)b;
	b->base = bit.wfree;
	memset(b->base, 0, nw*sizeof(ulong));
	bit.wfree += nw;
	bp->zero = l*rect.min.y;
	b->zero = l*rect.min.y;
	if(rect.min.x >= 0)
		bp->zero += rect.min.x/ws;
		b->zero += rect.min.x/ws;
	else
		bp->zero -= (-rect.min.x+ws-1)/ws;
	bp->zero = -bp->zero;
	bp->width = l;
	bp->ldepth = ld;
	bp->r = rect;
	bp->clipr = rect;
	bp->cache = 0;
	return bp;
		b->zero -= (-rect.min.x+ws-1)/ws;
	b->zero = -b->zero;
	b->width = l;
	b->ldepth = ld;
	b->r = rect;
	b->clipr = rect;
	b->cache = 0;
	/* worth doing better than linear lookup? */
	ep = bit.map+bit.nmap;
	for(bp=bit.map; bp<ep; bp++)
		if(*bp == 0)
			break;
	if(bp == ep){
		bp = bit.map;
		bit.map = smalloc((bit.nmap+DMAP)*sizeof(GBitmap*));
		memmove(bit.map, bp, bit.nmap*sizeof(GBitmap*));
		free(bp);
		bp = bit.map+bit.nmap;
		bit.nmap += DMAP;
	}
	*bp = b;
	return bp-bit.map;
}

void
bitfree(GBitmap *b)
{
	b->base[-1] = 0;
	free(b);
}

void
bitfree(GBitmap *bp)
fontfree(GFont *f)
{
	bp->base[-1] = 0;
	bp->ldepth = -1;
	bp->base = (ulong*)bit.free;
	bit.free = bp;
	if(f->b)
		bitfree(f->b);
	free(f);
}

void
subfontfree(GSubfont *s)
{
	free(s->info);
	free(s);
}

void


@@ 1396,16 1437,6 @@ bitloadchar(GFont *f, int ci, GSubfont *subf, int si)

QLock	bitlock;

GBitmap*
id2bit(int k)
{
	GBitmap *bp;
	bp = &bit.map[k];
	if(k<0 || k>=conf.nbitmap || bp->ldepth < 0)
		error(Ebadbitmap);
	return bp;
}

void
bitcompact(void)
{

M port/devlance.c => port/devlance.c +4 -10
@@ 14,10 14,6 @@ enum {
#define RSUCC(x) (((x)+1)%l.nrrb)
#define TSUCC(x) (((x)+1)%l.ntrb)

#define NOW (MACHP(0)->ticks*MS2HZ)

static int netlight;

/*
 *  Communication with the lance is via a transmit and receive ring of
 *  message descriptors.  The Initblock contains pointers to and sizes of


@@ 238,6 234,7 @@ isclosed(void *x)
{
	return ((Ethertype *)x)->q == 0;
}

static void
lancestclose(Queue *q)
{


@@ 286,6 283,7 @@ isobuf(void *x)
	m = x;
	return (MPus(m->flags)&LANCEOWNER) == 0;
}

static void
lanceoput(Queue *q, Block *bp)
{


@@ 549,9 547,6 @@ lancestart(int mode)
	*l.rdp = INEA|INIT|STRT; /**/
}

/*
 *  set up lance directory.
 */
void
lanceinit(void)
{


@@ 561,12 556,11 @@ Chan*
lanceattach(char *spec)
{
	if(l.kstarted == 0){
		kproc("lancekproc", lancekproc, 0);/**/
		kproc("lancekproc", lancekproc, 0);
		l.kstarted = 1;
		lancestart(0);
		print("lance ether: %.2x%.2x%.2x%.2x%.2x%.2x\n",
			l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);

	}
	return devattach('l', spec);
}


@@ 643,7 637,7 @@ lancewstat(Chan *c, char *dp)
static void
lancestatsfill(Chan *c, char* p, int n)
{
	char buf[256];
	char buf[512];

	USED(c);
	sprint(buf, "in: %d\nout: %d\ncrc errs %d\noverflows: %d\nframe errs %d\nbuff errs: %d\noerrs %d\naddr: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",

M port/devpipe.c => port/devpipe.c +53 -41
@@ 8,24 8,26 @@
#include	"devtab.h"

typedef struct Pipe	Pipe;

struct Pipe
{
	Ref;
	QLock;
	Pipe	*next;
	ulong	path;
};

struct Pipealloc
struct
{
	Lock;
	Pipe *pipe;
	Pipe *free;
	Pipe	*pipe;
	ulong	path;
} pipealloc;

static Pipe *getpipe(ulong);
static void pipeiput(Queue*, Block*);
static void pipeoput(Queue*, Block*);
static void pipestclose(Queue *);

Qinfo pipeinfo =
{
	pipeiput,


@@ 35,7 37,8 @@ Qinfo pipeinfo =
	"pipe"
};

Dirtab pipedir[]={
Dirtab pipedir[] =
{
	"data",		{Sdataqid},	0,			0600,
	"ctl",		{Sctlqid},	0,			0600,
	"data1",	{Sdataqid},	0,			0600,


@@ 48,19 51,9 @@ pipeinit(void)
{
}

/*
 *  allocate structures for conf.npipe pipes
 */
void
pipereset(void)
{
	Pipe *p, *ep;

	pipealloc.pipe = ialloc(conf.npipe * sizeof(Pipe), 0);
	ep = &pipealloc.pipe[conf.npipe-1];
	for(p = pipealloc.pipe; p < ep; p++)
		p->next = p+1;
	pipealloc.free = pipealloc.pipe;
}

/*


@@ 73,20 66,16 @@ pipeattach(char *spec)
	Chan *c;

	c = devattach('|', spec);
	p = smalloc(sizeof(Pipe));
	p->ref = 1;

	lock(&pipealloc);
	if(pipealloc.free == 0){
		unlock(&pipealloc);
		close(c);
		exhausted("pipes");
	}
	p = pipealloc.free;
	pipealloc.free = p->next;
	if(incref(p) != 1)
		panic("pipeattach");
	p->path = ++pipealloc.path;
	p->next = pipealloc.pipe;
	pipealloc.pipe = p;
	unlock(&pipealloc);

	c->qid = (Qid){CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0), 0};
	c->qid = (Qid){CHDIR|STREAMQID(2*p->path, 0), 0};
	c->dev = 0;
	return c;
}


@@ 96,7 85,7 @@ pipeclone(Chan *c, Chan *nc)
{
	Pipe *p;

	p = &pipealloc.pipe[STREAMID(c->qid.path)/2];
	p = getpipe(STREAMID(c->qid.path)/2);
	nc = devclone(c, nc);
	if(incref(p) <= 1)
		panic("pipeclone");


@@ 138,6 127,7 @@ Chan *
pipeopen(Chan *c, int omode)
{
	Pipe *p;
	int other;
	Stream *local, *remote;

	if(c->qid.path & CHDIR){


@@ 149,7 139,7 @@ pipeopen(Chan *c, int omode)
		return c;
	}

	p = &pipealloc.pipe[STREAMID(c->qid.path)/2];
	p = getpipe(STREAMID(c->qid.path)/2);
	if(waserror()){
		qunlock(p);
		nexterror();


@@ 161,7 151,8 @@ pipeopen(Chan *c, int omode)
		/*
		 *  first open, create the other end also
		 */
		remote = streamnew(c->type, c->dev, STREAMID(c->qid.path)^1, &pipeinfo,1);
		other = STREAMID(c->qid.path)^1;
		remote = streamnew(c->type, c->dev, other, &pipeinfo,1);

		/*
		 *  connect the device ends of both streams


@@ 170,7 161,9 @@ pipeopen(Chan *c, int omode)
		remote->devq->ptr = local;
		local->devq->other->next = remote->devq;
		remote->devq->other->next = local->devq;
	} else if(local->opens == 1){
	}
	else
	if(local->opens == 1){
		/*
		 *  keep other side around till last close of this side
		 */


@@ 209,10 202,10 @@ pipewstat(Chan *c, char *db)
void
pipeclose(Chan *c)
{
	Pipe *p;
	Pipe *p, *f, **l;
	Stream *remote;

	p = &pipealloc.pipe[STREAMID(c->qid.path)/2];
	p = getpipe(STREAMID(c->qid.path)/2);

	/*
	 *  take care of local and remote streams


@@ 232,12 225,17 @@ pipeclose(Chan *c)
	 */
	if(decref(p) == 0){
		lock(&pipealloc);
		p->next = pipealloc.free;
		pipealloc.free = p;
		l = &pipealloc.pipe;
		for(f = *l; f; f = f->next) {
			if(f == p) {
				*l = p->next;
				break;
			}
			l = &p->next;
		}
		unlock(&pipealloc);
		free(p);
	}
	if(p->ref < 0)
		panic("pipeexit");
}

long


@@ 245,8 243,8 @@ piperead(Chan *c, void *va, long n, ulong offset)
{
	if(c->qid.path & CHDIR)
		return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);
	else
		return streamread(c, va, n);

	return streamread(c, va, n);
}

/*


@@ 256,7 254,7 @@ piperead(Chan *c, void *va, long n, ulong offset)
long
pipewrite(Chan *c, void *va, long n, ulong offset)
{
	if(waserror()){
	if(waserror()) {
		postnote(u->p, 1, "sys: write on closed pipe", NExit);
		error(Egreg);
	}


@@ 266,9 264,6 @@ pipewrite(Chan *c, void *va, long n, ulong offset)
}

/*
 *  stream stuff
 */
/*
 *  send a block up stream to the process.
 *  sleep untill there's room upstream.
 */


@@ 312,3 307,20 @@ pipestclose(Queue *q)
	bp->type = M_HANGUP;
	PUTNEXT(q, bp);
}

Pipe*
getpipe(ulong path)
{
	Pipe *p;

	lock(&pipealloc);
	for(p = pipealloc.pipe; p; p = p->next) {
		if(path == p->path) {
			unlock(&pipealloc);
			return p;
		}
	}
	unlock(&pipealloc);
	panic("getpipe");
	return 0;
}

M port/page.c => port/page.c +1 -1
@@ 21,7 21,7 @@ pageinit(void)
	palloc.head = xalloc(np*sizeof(Page));
	if(palloc.head == 0)
		panic("pageinit");

print("page: %lux %d %lux %d\n", palloc.p0, palloc.np0, palloc.p1, palloc.np1);
	p = palloc.head;
	while(palloc.np0 > 0) {
		p->prev = p-1;

M port/portdat.h => port/portdat.h +6 -8
@@ 41,11 41,6 @@ typedef int    Devgen(Chan*, Dirtab*, int, int, Dir*);

#include "fcall.h"

struct List
{
	void	*next;
};

struct Ref
{
	Lock;


@@ 108,7 103,8 @@ struct Block
	ulong	pc;			/* pc of caller */
};

struct Blist {
struct Blist
{
	Lock;
	Block	*first;			/* first data block */
	Block	*last;			/* last data block */


@@ 205,7 201,8 @@ struct Env
/*
 *  Ethernet packet buffers.
 */
struct Etherpkt {
struct Etherpkt
{
	uchar d[6];
	uchar s[6];
	uchar type[2];


@@ 639,7 636,8 @@ struct Stream
/*
 *  stream file qid's & high water mark
 */
enum {
enum
{
	Shighqid = STREAMQID(1,0) - 1,
	Sdataqid = Shighqid,
	Sctlqid = Sdataqid-1,

M port/portfns.h => port/portfns.h +1 -4
@@ 1,7 1,6 @@
void	alarmkproc(void*);
Block*	allocb(ulong);
int	anyready(void);
void	append(List**, List*);
Image*	attachimage(int, Chan*, ulong, ulong);
int	blen(Block *);
int	bround(Block *, int);


@@ 34,8 33,6 @@ void	copypage(Page*, Page*);
int	decref(Ref*);
int	decrypt(void*, void*, int);
void	delay(int);
void	delete(List**, List*, List*);
void	delete0(List**, List*);
Chan*	devattach(int, char*);
Chan*	devclone(Chan*, Chan*);
void	devdir(Chan*, Qid, char*, long, char*, long, Dir*);


@@ 90,7 87,6 @@ long	ibrk(ulong, int);
int	incref(Ref*);
void	initq(IOQ*);
void	initseg(void);
void	insert(List**, List*, List*);
void	invalidateu(void);
void	isdir(Chan*);
int	ispages(void*);


@@ 248,6 244,7 @@ void	unmount(Chan*, Chan*);
void	urpfillstats(Chan*, char*, int);
void	xinit(void);
void	*xalloc(ulong);
void	*xspanalloc(ulong, int, ulong);
void	xfree(void*);
void	xhole(ulong, ulong);
void	xsummary(void);

M port/segment.c => port/segment.c +0 -2
@@ 27,7 27,6 @@ static QLock ireclaim;
void
initseg(void)
{
	Segment *s, *se;
	Image *i, *ie;

	imagealloc.free = xalloc(conf.nimage*sizeof(Image));


@@ 360,7 359,6 @@ ibrk(ulong addr, int seg)

	s->top = newtop;
	s->size = newsize;

	qunlock(&s->lk);
	return 0;
}

M ss/dat.h => ss/dat.h +0 -1
@@ 79,7 79,6 @@ struct Conf
	int	nsubfont;	/* Gsubfont structs (devbit.c) */
	int	nurp;		/* max urp conversations */
	int	nasync;		/* number of async protocol modules */
	int	npipe;		/* number of pipes */
	int	copymode;	/* 0 is copy on write, 1 is copy on reference */
	ulong	ipif;		/* Ip protocol interfaces */
	ulong	ip;		/* Ip conversations per interface */

M ss/main.c => ss/main.c +2 -2
@@ 222,7 222,6 @@ confinit(void)
	conf.nsubfont = 10*mul;
	conf.nurp = 32;
	conf.nasync = 1;
	conf.npipe = conf.nstream/2;
	conf.copymode = 0;		/* copy on write */
	conf.ipif = 8;
	conf.ip = 64;


@@ 263,7 262,8 @@ lancesetup(Lance *lp)
	/*
	 * Allocate area for lance init block and descriptor rings
	 */
	pa = (ulong)ialloc(BY2PG, 1)&~KZERO;	/* one whole page */
	pa = (ulong)xspanalloc(BY2PG, BY2PG, 0);

	/* map at LANCESEGM */
	k = kmappa(pa, PTEMAINMEM|PTENOCACHE);
	lp->lanceram = (ushort*)k->va;