~kris/9p

9hist

723ef488946c687f418a40ecf22a20951db229cc — David du Colombier 27 years ago eeee59b
Plan 9 from Bell Labs 1999-06-09
6 files changed, 124 insertions(+), 309 deletions(-)

M mpc/devsac.c
M mpc/l.s
M mpc/main.c
M mpc/mem.h
M mpc/unsac.c
M pc/l.s
M mpc/devsac.c => mpc/devsac.c +113 -274
@@ 4,6 4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"

/*
 * Rather than reading /adm/users, which is a lot of work for


@@ 73,32 74,31 @@ enum
	Powner =	64,
};

uchar *data = SACMEM;
int blocksize;
Sac root;

void	sacstat(SacDir*, char*);
void	io(void);
void	usage(void);
ulong	getl(void *p);
vlong	getv(void *p);
void	init(char*);
Sac	*saccpy(Sac *s);
Sac *saclookup(Sac *s, char *name);
int sacdirread(Sac *s, char *p, long off, long cnt);
void loadblock(void *buf, uchar *offset, int blocksize);
void sacfree(Sac*);

void
devinit(void)
static uchar *data = SACMEM;
static int blocksize;
static Sac root;

static void	sacdir(Chan *, SacDir*, char*);
static ulong	getl(void *p);
static vlong	getv(void *p);
static Sac	*saccpy(Sac *s);
static Sac *saclookup(Sac *s, char *name);
static int sacdirread(Chan *, char *p, long off, long cnt);
static void loadblock(void *buf, uchar *offset, int blocksize);
static void sacfree(Sac*);

static void
sacinit(void)
{
	SacHeader *hdr;
print("sacinit\n");
	hdr = (SacHeader*)data;
	if(getl(hdr->magic) != Magic) {
print("devsac: bad magic");
print("devsac: bad magic\n");
		return;
	}
	blocksize = getl(hdr->blocksize);
print("blocksize = %d\n", blocksize);
	root.SacDir = *(SacDir*)(data + sizeof(SacHeader));
}



@@ 123,7 123,7 @@ sacattach(char* spec)
	return c;
}

Chan*
static Chan*
sacclone(Chan *c, Chan *nc)
{
	nc = devclone(c, nc);


@@ 131,15 131,17 @@ sacclone(Chan *c, Chan *nc)
	return nc;
}

int
devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen)
static int
sacwalk(Chan *c, char *name)
{
	Sac *sac;
	Path *op;

print("sacwalk\n");
	isdir(c);
	sac = c->aux;
	if(strcmp(name, ".") == 0)
	if(name[0]=='.' && name[1]==0)
		return 1;
	sac = c->aux;
	sac = saclookup(sac, name);
	if(sac == nil) {
		strncpy(up->error, Enonexist, NAMELEN);


@@ 148,163 150,119 @@ devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen)
	c->aux = sac;
	c->qid = (Qid){getl(sac->qid), 0};
	op = c->path;
print("op=%ux name = %s\n", op, name);
	c->path = ptenter(&syspt, op, name);
	decref(op);
	return 1;
}

char *
ropen(Fid *f)
static Chan*
sacopen(Chan *c, int omode)
{
	int mode, trunc;

	if(f->open)
		return Eisopen;
	if(f->busy == 0)
		return Enotexist;
	mode = rhdr.mode;
	if(f->qid.path & CHDIR){
		if(mode != OREAD)
			return Eperm;
		thdr.qid = f->qid;
		return 0;
	}
	if(mode & ORCLOSE)
		return Erdonly;
	trunc = mode & OTRUNC;
	mode &= OPERM;
	if(mode==OWRITE || mode==ORDWR || trunc)
		return Erdonly;
	if(mode==OREAD)
		if(!perm(f, f->sac, Pread))
			return Eperm;
	if(mode==OEXEC)
		if(!perm(f, f->sac, Pexec))
			return Eperm;
	thdr.qid = f->qid;
	f->open = 1;
	return 0;
}
	ulong t, mode;
	Sac *sac;
	static int access[] = { 0400, 0200, 0600, 0100 };

char *
rcreate(Fid *f)
{
	if(f->open)
		return Eisopen;
	if(f->busy == 0)
		return Enotexist;
	return Erdonly;
	sac = c->aux;
	mode = getl(sac->mode);
	if(strcmp(up->user, sac->uid) == 0)
		mode = mode;
	else if(strcmp(up->user, sac->gid) == 0)
		mode = mode<<3;
	else
		mode = mode<<6;

	t = access[omode&3];
	if((t & mode) != t)
			error(Eperm);
	c->offset = 0;
	c->mode = openmode(omode);
	c->flag |= COPEN;
	return c;
}

char*
rread(Fid *f)

static long
sacread(Chan *c, void *a, long n, vlong off)
{
	Sac *sac;
	char *buf, *buf2;
	long off;
	int n, cnt, i, j;
	int nn, cnt, i, j;
	uchar *blocks;
	vlong length;

	if(f->busy == 0)
		return Enotexist;
	sac = f->sac;
	thdr.count = 0;
	off = rhdr.offset;
	buf = thdr.data;
	cnt = rhdr.count;
	if(f->qid.path & CHDIR){
		cnt = (rhdr.count/DIRLEN)*DIRLEN;
	buf = a;
	cnt = n;
	if(c->qid.path & CHDIR){
		cnt = (cnt/DIRLEN)*DIRLEN;
		if(off%DIRLEN)
			return "i/o error";
		thdr.count = sacdirread(sac, buf, off, cnt);
		return 0;
			error("i/o error");
		return sacdirread(c, buf, off, cnt);
	}
print("data read\n");
	sac = c->aux;
	length = getv(sac->length);
	if(off >= length) {
		rhdr.count = 0;
	if(off >= length)
		return 0;
	}
	if(cnt > length-off)
		cnt = length-off;
	thdr.count = cnt;
	if(cnt == 0)
		return 0;
	n = cnt;
	blocks = data + getv(sac->blocks);
	buf2 = malloc(blocksize);
	while(cnt > 0) {
		i = off/blocksize;
		loadblock(buf2, blocks+i*8, blocksize);
		j = off-i*blocksize;
		n = blocksize-j;
		if(n > cnt)
			n = cnt;
		memmove(buf, buf2+j, n);
		cnt -= n;
		off += n;
		nn = blocksize-j;
		if(nn > cnt)
			nn = cnt;
		memmove(buf, buf2+j, nn);
		cnt -= nn;
		off += nn;
	}
	free(buf2);
	return 0;
}

char*
sacwrite(Fid *f)
{
	if(f->busy == 0)
		return Enotexist;
	return Erdonly;
	return n;
}

char *
rclunk(Fid *f)
static long
sacwrite(Chan *, void *, long, vlong)
{
	f->busy = 0;
	f->open = 0;
	free(f->user);
	sacfree(f->sac);
	error(Eperm);
	return 0;
}

char *
rremove(Fid *f)
static void
sacclose(Chan* c)
{
	f->busy = 0;
	f->open = 0;
	free(f->user);
	sacfree(f->sac);
	return Erdonly;
	Sac *sac = c->aux;
print("close %ux\n", sac);
	c->aux = nil;
	sacfree(sac);
}

char *
rstat(Fid *f)
{
	if(f->busy == 0)
		return Enotexist;
	sacstat(f->sac, thdr.stat);
	return 0;
}

char *
rwstat(Fid *f)
static void
sacstat(Chan *c, char *db)
{
	if(f->busy == 0)
		return Enotexist;
	return Erdonly;
	sacdir(c, c->aux, db);
}

Sac*
static Sac*
saccpy(Sac *s)
{
	Sac *ss;
	
	ss = malloc(sizeof(Sac));
print("saccpy = %ux\n", ss);
	*ss = *s;
	if(ss->path)
		incref(ss->path);
	return ss;
}

SacPath *
static SacPath *
sacpathalloc(SacPath *p, vlong blocks, int entry)
{
	SacPath *pp = malloc(sizeof(SacPath));


@@ 327,15 285,15 @@ sacpathfree(SacPath *p)
}


void
static void
sacfree(Sac *s)
{
	sacpathfree(s->path);
	free(s);
}

void
sacstat(SacDir *s, char *buf)
static void
sacdir(Chan *c, SacDir *s, char *buf)
{
	Dir dir;



@@ 349,10 307,12 @@ sacstat(SacDir *s, char *buf)
	strcpy(dir.gid, s->gid);
	dir.atime = getl(s->atime);
	dir.mtime = getl(s->mtime);
	dir.type = devtab[c->type]->dc;
	dir.dev = c->dev;
	convD2M(&dir, buf);
}

void
static void
loadblock(void *buf, uchar *offset, int blocksize)
{
	vlong block, n;


@@ 364,15 324,16 @@ loadblock(void *buf, uchar *offset, int blocksize)
		if(n < 0)
			n = -n;
		n -= block;
//fprint(2, "blocksize = %d, block = %lld n = %lld\n", blocksize, block, n);
print("blocksize = %d, block = %lld n = %lld\n", blocksize, block, n);
		if(unsac(buf, data+block, blocksize, n)<0)
			panic("unsac failed!");
	} else {
print("memmove: blocksize = %d\n", blocksize);
		memmove(buf, data+block, blocksize);
	}
}

Sac*
static Sac*
sacparent(Sac *s)
{
	uchar *blocks;


@@ 382,34 343,37 @@ sacparent(Sac *s)

	p = s->path;
	if(p == nil || p->up == nil) {
		pathfree(p);
		sacpathfree(p);
		*s = root;
		return s;
	}
	p = p->up;

//fprint(2, "sacparent = %lld %d\n", p->blocks, p->entry);
print("sacparent = %lld %d\n", p->blocks, p->entry);
	blocks = data + p->blocks;
	per = blocksize/sizeof(SacDir);
	i = p->entry/per;
	buf = malloc(per*sizeof(SacDir));
	loadblock(buf, blocks + i*8, per*sizeof(SacDir));
	s->SacDir = buf[p->entry-i*per];
//fprint(2, "sacparent = %s\n", s->name);
print("sacparent = %s\n", s->name);
	free(buf);
	incref(p);
	pathfree(s->path);
	sacpathfree(s->path);
	s->path = p;
	return s;
}

int
sacdirread(Sac *s, char *p, long off, long cnt)
static int
sacdirread(Chan *c, char *p, long off, long cnt)
{
	uchar *blocks;
	SacDir *buf;
	int iblock, per, i, j, ndir;
	Sac *s;

print("sacdirread %d %d\n", off, cnt);
	s = c->aux;
	blocks = data + getv(s->blocks);
	per = blocksize/sizeof(SacDir);
	ndir = getv(s->length);


@@ 428,18 392,18 @@ sacdirread(Sac *s, char *p, long off, long cnt)
			iblock = j;
		}
		j *= per;
		sacstat(buf+i-j, p);
		sacdir(c, buf+i-j, p);
		p += DIRLEN;
	}
	free(buf);
	return cnt*DIRLEN;
}

Sac*
static Sac*
saclookup(Sac *s, char *name)
{
	int ndir;
	int top, bot, i, j, k, per;
	int i, j, k, per;
	uchar *blocks;
	SacDir *buf;
	int iblock;


@@ 453,36 417,8 @@ saclookup(Sac *s, char *name)
	buf = malloc(per*sizeof(SacDir));
	iblock = -1;

	if(1) {
		// linear search
		for(i=0; i<ndir; i++) {
			j = i/per;
			if(j != iblock) {
				loadblock(buf, blocks + j*8, per*sizeof(SacDir));
				iblock = j;
			}
			j *= per;
			sd = buf+i-j;
			k = strcmp(name, sd->name);
			if(k == 0) {
//print("walk %s %lld %d\n", name, getv(s->blocks), i);
				s->path = sacpathalloc(s->path, getv(s->blocks), i);
				s->SacDir = *sd;
				free(buf);
				return s;
			}
		}
		free(buf);
		return 0;
	}

	// binary search
	top = ndir;
	bot = 0;
	while(bot != top){
if(bot>top)
sysfatal("binary serach failed: %d %d\n", bot, top);
		i = (bot+top)>>1;
	// linear search
	for(i=0; i<ndir; i++) {
		j = i/per;
		if(j != iblock) {
			loadblock(buf, blocks + j*8, per*sizeof(SacDir));


@@ 492,115 428,18 @@ sysfatal("binary serach failed: %d %d\n", bot, top);
		sd = buf+i-j;
		k = strcmp(name, sd->name);
		if(k == 0) {
			s->path = sacpathalloc(s->path, getv(s->blocks), i);
print("walk %s %lld %d\n", name, getv(s->blocks), i);
		s->path = sacpathalloc(s->path, getv(s->blocks), i);
			s->SacDir = *sd;
			free(buf);
			return s;
		}
		if(k < 0) {
			top = i;
			sd = buf;
			if(strcmp(name, sd->name) < 0)
				top = j;
		} else {
			bot = i+1;
			if(ndir-j < per)
				i = ndir-j;
			else
				i = per;
			sd = buf+i-1;
			if(strcmp(name, sd->name) > 0)
				bot = j+i;
		}
	}
	return 0;
}

Fid *
newfid(int fid)
{
	Fid *f, *ff;

	ff = 0;
	for(f = fids; f; f = f->next)
		if(f->fid == fid)
			return f;
		else if(!ff && !f->busy)
			ff = f;
	if(ff){
		ff->fid = fid;
		return ff;
	}
	f = malloc(sizeof *f);
//fprint(2, "newfid\n");
	memset(f, 0 , sizeof(Fid));
	f->fid = fid;
	f->next = fids;
	fids = f;
	return f;
}

void
io(void)
{
	char *err;
	int n;

	for(;;){
		/*
		 * reading from a pipe or a network device
		 * will give an error after a few eof reads
		 * however, we cannot tell the difference
		 * between a zero-length read and an interrupt
		 * on the processes writing to us,
		 * so we wait for the error
		 */
		n = read(mfd[0], mdata, sizeof mdata);
		if(n == 0)
			continue;
		if(n < 0)
			error("mount read");
		if(convM2S(mdata, &rhdr, n) == 0)
			continue;

		if(debug)
			fprint(2, "sacfs:<-%F\n", &rhdr);

		thdr.data = mdata + MAXMSG;
		if(!fcalls[rhdr.type])
			err = "bad fcall type";
		else
			err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
		if(err){
			thdr.type = Rerror;
			strncpy(thdr.ename, err, ERRLEN);
		}else{
			thdr.type = rhdr.type + 1;
			thdr.fid = rhdr.fid;
		}
		thdr.tag = rhdr.tag;
		if(debug)
			fprint(2, "ramfs:->%F\n", &thdr);/**/
		n = convS2M(&thdr, mdata);
		if(write(mfd[1], mdata, n) != n)
			error("mount write");
	}
}

int
perm(Fid *f, Sac *s, int p)
{
	ulong perm = getl(s->mode);
	if((p*Pother) & perm)
		return 1;
	if(strcmp(f->user, s->gid)==0 && ((p*Pgroup) & perm))
		return 1;
	if(strcmp(f->user, s->uid)==0 && ((p*Powner) & perm))
		return 1;
	free(buf);
	return 0;
}


ulong
static ulong
getl(void *p)
{
	uchar *a = p;


@@ 608,7 447,7 @@ getl(void *p)
	return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
}

vlong
static vlong
getv(void *p)
{
	uchar *a = p;

M mpc/l.s => mpc/l.s +2 -2
@@ 694,8 694,8 @@ GLOBL	isavetbl+0(SB), $4

TEXT	tlbtab(SB), $-4
	/* epn, rpn, twc */
	TLBE(DRAMMEM|MMUEV, MMUPS8M|MMUWT|MMUV, DRAMMEM|MMUPP|MMUSPS|MMUSH|MMUV)	/* DRAM, 8M */
	TLBE((DRAMMEM+8*(1<<20))|MMUEV, MMUPS8M|MMUWT|MMUV, (DRAMMEM+8*(1<<20))|MMUPP|MMUSPS|MMUSH|MMUV)	/* DRAM, second 8M */
	TLBE(FLASHMEM|MMUEV, MMUPS8M|MMUWT|MMUV, FLASHMEM|MMUPP|MMUSPS|MMUSH|MMUCI|MMUV)	/* FLASH, 8M */
	TLBE(DRAMMEM|MMUEV, MMUPS8M|MMUWT|MMUV, DRAMMEM|MMUPP|MMUSPS|MMUSH|MMUV)	/* DRAM, second 8M */
	TLBE(INTMEM|MMUEV, MMUPS8M|MMUWT|MMUV, INTMEM|MMUPP|MMUSPS|MMUSH|MMUCI|MMUV)	/* IO space 8M */
TEXT	tlbtabe(SB), $-4
	RETURN

M mpc/main.c => mpc/main.c +5 -0
@@ 44,6 44,9 @@ if(0) {
//print("sr1=%ux sr2=%ux\n", *(uchar*)(NVRAMMEM+0x100000), *(uchar*)(NVRAMMEM+0x100001));

//print("sccr=%ulx\n", m->iomem->sccr);
print("%ux %ux\n", m->iomem->memc[0].base, m->iomem->memc[7].base);
print("%ux %ux\n", m->iomem->memc[0].option, m->iomem->memc[7].option);
print("%ux\n", *(uchar*)(0xff000000));
	pageinit();
	procinit0();
	initseg();


@@ 76,6 79,8 @@ machinit(void)
	m->clockgen = osc*MHz;		/* clock generator frequency (cycles) */

	*(ushort*)&(io->memc[4].base) = 0x8060;
//	*(ushort*)&(io->memc[7].option) = 0xffe0;
	*(ushort*)&(io->memc[7].base) = 0xff00;
}

void

M mpc/mem.h => mpc/mem.h +4 -7
@@ 173,15 173,12 @@
#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
#define TSTKSIZ 	100

/*
 * atlas board registers
 */
#define	INTMEM		0x80000000
#define	ISAMEM	0x80100000
#define	FLASH0MEM	0x80200000
#define	FLASH1MEM	0x80400000
#define	ISAMEM		0x80100000
#define	FLASHMEM	0xff000000
#define	SACMEM		FLASHMEM + 0x40000
#define	NVRAMMEM	0x80600000
#define DRAMMEM		0xff000000		/* to 0xffffffff: 16 Meg */
#define DRAMMEM		0xff800000		/* to 0xffffffff: 8 Meg */

#define	SIRAM	(INTMEM+0xC00)
#define	LCDCOLR	(INTMEM+0xE00)

M mpc/unsac.c => mpc/unsac.c +0 -2
@@ 43,8 43,6 @@ struct Decode{
	int	base;
	ulong	maxblocksym;

	jmp_buf	errjmp;

	uchar	*src;				/* input buffer */
	uchar	*smax;				/* limit */
};

M pc/l.s => pc/l.s +0 -24
@@ 511,37 511,13 @@ TEXT setlabel(SB), $0
 * The size of each entry in the vector table (6 bytes) is known in trapinit().
 */
TEXT _strayintr(SB), $0

	/* time stamp for interrupt */
	PUSHL	AX				/* save AX */
	PUSHL	DX
	PUSHL	CX
	MOVL	$0x10, CX
	RDMSR
	MOVL	AX, intrts(SB)
	MOVL	DX, intrts+4(SB)
	POPL	CX
	POPL	DX

	MOVL	4(SP), AX			/* return PC from vectortable(SB) */
	MOVBLZX	(AX), AX			/* trap type */
	XCHGL	AX, (SP)			/* restore AX and put the type on the stack */
	JMP	intrcommon

TEXT _strayintrx(SB), $0

	/* time stamp for interrupt */
	PUSHL	AX
	PUSHL	DX
	PUSHL	CX
	MOVL	$0x10, CX
	RDMSR
	MOVL	AX, intrts(SB)
	MOVL	DX, intrts+4(SB)
	POPL	CX
	POPL	DX
	POPL	AX

	XCHGL	AX, (SP)			/* exchange AX with pointer to trap type */
	MOVBLZX	(AX), AX			/* trap type -> AX */
	XCHGL	AX, (SP)			/* exchange trap type with AX */