~kris/9p

9hist

75093007b62c58ba3da073f70424df0c78302331 — David du Colombier 27 years ago f472fe0
Plan 9 from Bell Labs 1999-01-28
8 files changed, 618 insertions(+), 36 deletions(-)

M carrera/devrtc.c
M carrera/main.c
M mpc/devuart.c
M mpc/l.s
M mpc/mmu.c
A mpc/sh.c
M mpc/trap.c
M port/devdraw.c
M carrera/devrtc.c => carrera/devrtc.c +9 -2
@@ 10,6 10,8 @@
 *  real time clock and non-volatile ram
 */

extern ulong boottime;

typedef struct Rtc	Rtc;
struct Rtc
{


@@ 192,8 194,6 @@ rtctime(void)

	return t;
#else
	extern ulong boottime;

	return boottime+TK2SEC(MACHP(0)->ticks);
#endif /* notdef */
}


@@ 264,6 264,8 @@ rtcwrite(Chan *c, void *buf, long n, vlong off)
			rtc.year = PUTBCD(rtc.year);
		}

/* disgusting hack because RTC doesn't work and m->ticks drifts */
if(boottime == 0){
		ilock(&rtclock);
		/* set clock values */
		x = (*(uchar*)Rtcindex)&~0x7f;


@@ 280,6 282,11 @@ rtcwrite(Chan *c, void *buf, long n, vlong off)
		*(uchar*)Rtcindex = x|Year;
		*(uchar*)Rtcdata = rtc.year;
		iunlock(&rtclock);
}else{
		splhi();
		MACHP(0)->ticks = HZ*(secs - boottime);	/* inverse of SEC2TK() */
		spllo();
}

		return n;
	case Qnvram:

M carrera/main.c => carrera/main.c +1 -1
@@ 472,7 472,7 @@ confinit(void)

	if(top > 16*MB/BY2PG){
		conf.upages = (conf.npage*60)/100;
		poolsetparam("Image", 0, 0, 4*1024*1024);
		poolsetparam("Image", 0, 0, 4*1024*1024, nil);
	}else
		conf.upages = (conf.npage*40)/100;
	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;

M mpc/devuart.c => mpc/devuart.c +0 -2
@@ 997,7 997,6 @@ uartintr(Uart *p, int events)
		p->overrun++;
	p->interrupts++;
	dokick = 0;
/*
	while(p->rxb != nil && ((bd = &p->rxb[p->rdrx])->status & BDEmpty) == 0){
		if(p->mode)
			framedinput(p, bd);


@@ 1008,7 1007,6 @@ uartintr(Uart *p, int events)
		bd->status = (bd->status & BDWrap) | BDEmpty|BDInt;
		p->rdrx ^= 1;
	}
*/
	if((bd = p->txb) != nil){
		if((bd->status & BDReady) == 0){
			ilock(&p->plock);

M mpc/l.s => mpc/l.s +6 -2
@@ 60,7 60,7 @@
/* special instruction definitions */
#define	BDNZ	BC	16,0,
#define	BDNE	BC	0,2,
#define	TLBIA	WORD	$(31<<26)
#define	TLBIA	WORD	$((31<<26)|(370<<1))
#define	MFTB(tbr,d)	WORD	$((31<<26)|((d)<<21)|((tbr&0x1f)<<16)|(((tbr>>5)&0x1f)<<11)|(371<<1))

/* on some models mtmsr doesn't synchronise enough (eg, 603e) */


@@ 427,7 427,7 @@ TEXT	eieio(SB), $0
	EIEIO
	RETURN

TEXT	flushmmu(SB), $0
TEXT	_flushmmu(SB), $0
	TLBIA
	RETURN



@@ 639,6 639,9 @@ TEXT	intrvec(SB), $-4
/*
 * restore state from Ureg and return from trap/interrupt
 */
TEXT	forkret(SB), $0
	BR	restoreureg

restoreureg:
	MOVMW	48(R1), R2	/* r2:r31 */
	/* defer R1 */


@@ 664,6 667,7 @@ restoreureg:
	MOVW	SPR(SAVER0), R0
	RFI

	
GLOBL	mach0+0(SB), $MACHSIZE
GLOBL	spltbl+0(SB), $4
GLOBL	intrtbl+0(SB), $4

M mpc/mmu.c => mpc/mmu.c +8 -1
@@ 14,6 14,13 @@ mmuinit(void)
}

void
flushmmu(void)
{
//	print("flushmmu()\n");
	_flushmmu();
}

void
mmuswitch(Proc*)
{
	flushmmu();


@@ 30,7 37,7 @@ void
putmmu(ulong va, ulong pa, Page*)
{
	int x, r;
print("putmmu va=%ux pa=%ux\n", va, pa);
//print("putmmu va=%ux pa=%ux\n", va, pa);
	x = splhi();
	r = _putmmu(va, pa);
	splx(x);

A mpc/sh.c => mpc/sh.c +481 -0
@@ 0,0 1,481 @@
/* sh - simple shell - great for early stages of porting */
#include <u.h>
#include <libc.h>

#define MAXLINE 200		/* maximum line length */
#define WORD 256		/* token code for words */
#define EOF -1			/* token code for end of file */
#define ispunct(c)		(c=='|' || c=='&' || c==';' || c=='<' || \
				 c=='>' || c=='(' || c==')' || c=='\n')
#define isspace(c)		(c==' ' || c=='\t')
#define execute(np)		(np? (*(np)->op)(np) : 0)

typedef struct Node	Node;
struct Node{			/* parse tree node */
	int (*op)(Node *); 	/* operator function */
	Node *args[2];		/* argument nodes */
	char *argv[100];	/* argument pointers */
	char *io[3];		/* i/o redirection */
};

Node	nodes[25];		/* node pool */
Node	*nfree;			/* next available node */
char	strspace[10*MAXLINE];	/* string storage */
char	*sfree;			/* next free character in strspace */
int	t;			/* current token code */
char 	*token;			/* current token text (in strspace) */
int	putback = 0;		/* lookahead */
Waitmsg	status;			/* exit status of most recent command */
int	cflag = 0;		/* command is argument to sh */
int	tflag = 0;		/* read only one line */
int	interactive = 0;	/* prompt */
char	*cflagp;		/* command line for cflag */
char	*path[] ={"/bin", 0};

Node	*alloc(int (*op)(Node *));
int	builtin(Node *np);
Node	*command(void);
int	getch(void);
int	gettoken(void);
Node	*list(void);
void	error(char *s, char *t);
Node	*pipeline(void);
void	redirect(Node *np);
int	setio(Node *np);
Node	*simple(void);
int	xpipeline(Node *np);
int	xsimple(Node *np);
int	xsubshell(Node *np);
int	xnowait(Node *np);
int	xwait(Node *np);

main(int argc, char *argv[])
{
	Node *np;

	open("#c/cons", OREAD);
	open("#c/cons", OWRITE);
	open("#c/cons", OWRITE);
	
	print("hello world\n");

	if(argc>1 && strcmp(argv[1], "-t")==0)
		tflag++;
	else if(argc>2 && strcmp(argv[1], "-c")==0){
		cflag++;
		cflagp = argv[2];
	}else if(argc>1){
		close(0);
		if(open(argv[1], 0) != 0){
			error(": can't open", argv[1]);
			exits("argument");
		}
	}else
		interactive = 1;
	for(;;){
		if(interactive)
			fprint(2, "%d$ ", getpid());
		nfree = nodes;
		sfree = strspace;
		if((t=gettoken()) == EOF)
			break;
		if(t != '\n')
			if(np = list())
				execute(np);
			else
				error("syntax error", "");
		while(t!=EOF && t!='\n')	/* flush syntax errors */
			t = gettoken();
	}
	exits(status.msg);
}

/* alloc - allocate for op and return a node */
Node*
alloc(int (*op)(Node *))
{
	if(nfree < nodes+sizeof(nodes)){
		nfree->op = op;
		nfree->args[0] = nfree->args[1] = 0;
		nfree->argv[0] = nfree->argv[1] = 0;
		nfree->io[0] = nfree->io[1] = nfree->io[2] = 0;
		return nfree++;
	}
	error("node storage overflow", "");
	exits("node storage overflow");
}

/* builtin - check np for builtin command and, if found, execute it */
int
builtin(Node *np)
{
	int n = 0;
	char *s, name[MAXLINE];

	if(np->argv[1])
		n = strtoul(np->argv[1], 0, 0);
	if(strcmp(np->argv[0], "cd") == 0){
		if(chdir(np->argv[1]? np->argv[1] : "/") == -1)
			error(": bad directory", np->argv[0]);
		return 1;
	}else if(strcmp(np->argv[0], "exit") == 0)
		exits(np->argv[1]? np->argv[1] : status.msg);
	else if(strcmp(np->argv[0], "bind") == 0){
		if(np->argv[1]==0 || np->argv[2]==0)
			error("usage: bind new old", "");
		else if(bind(np->argv[1], np->argv[2], 0)==-1)
			error("bind failed", "");
		return 1;
#ifdef asdf
	}else if(strcmp(np->argv[0], "unmount") == 0){
		if(np->argv[1] == 0)
			error("usage: unmount [new] old", "");
		else if(np->argv[2] == 0){
			if(unmount((char *)0, np->argv[1]) == -1)
				error("unmount:", "");
		}else if(unmount(np->argv[1], np->argv[2]) == -1)
			error("unmount", "");
		return 1;
#endif
	}else if(strcmp(np->argv[0], "wait") == 0){
		while(wait(&status) != -1)
			if(n && atoi(status.pid)==n){
				n = 0;
				break;
			}
		if(n)
			error("wait error", "");
		return 1;
	}else if(strcmp(np->argv[0], "newpgrp") == 0){
		int i;
		i = rfork(RFNAMEG|RFENVG);
		if(i < 0)
			error("rfork error", "");
		else
			fprint(2, "%d\n", i);
		return 1;
	}else if(strcmp(np->argv[0], "exec") == 0){
		redirect(np);
		if(np->argv[1] == (char *) 0)
			return 1;
		exec(np->argv[1], &np->argv[1]);
		n = np->argv[1][0];
		if(n!='/' && n!='#' && (n!='.' || np->argv[1][1]!='/'))
			for(n = 0; path[n]; n++){
				sprint(name, "%s/%s", path[n], np->argv[1]);
				exec(name, &np->argv[1]);
			}
		error(": not found", np->argv[1]);
		return 1;
	}
	return 0;
}

/* command - ( list ) [ ( < | > | >> ) word ]* | simple */
Node*
command(void)
{
	Node *np;

	if(t != '(')
		return simple();
	np = alloc(xsubshell);
	t = gettoken();
	if((np->args[0]=list())==0 || t!=')')
		return 0;
	while((t=gettoken())=='<' || t=='>')
		if(!setio(np))
			return 0;
	return np;
}

/* getch - get next, possibly pushed back, input character */
int
getch(void)
{
	unsigned char c;
	static done=0;

	if(putback){
		c = putback;
		putback = 0;
	}else if(tflag){
		if(done || read(0, &c, 1)!=1){
			done = 1;
			return EOF;
		}
		if(c == '\n')
			done = 1;
	}else if(cflag){
		if(done)
			return EOF;
		if((c=*cflagp++) == 0){
			done = 1;
			c = '\n';
		}
	}else if(read(0, &c, 1) != 1)
		return EOF;
	return c;
}

/* gettoken - get next token into string space, return token code */
int
gettoken(void)
{
	int c;

	while((c = getch()) != EOF)
		if(!isspace(c))
			break;
	if(c==EOF || ispunct(c))
		return c;
	token = sfree;
	do{
		if(sfree >= strspace+sizeof(strspace) - 1){
			error("string storage overflow", "");
			exits("string storage overflow");
		}
		*sfree++ = c;
	}while((c=getch()) != EOF && !ispunct(c) && !isspace(c));
	*sfree++ = 0;
	putback = c;
	return WORD;
}

/* list - pipeline ( ( ; | & ) pipeline )* [ ; | & ]  (not LL(1), but ok) */
Node*
list(void)
{
	Node *np, *np1;

	np = alloc(0);
	if((np->args[1]=pipeline()) == 0)
		return 0;
	while(t==';' || t=='&'){
		np->op = (t==';')? xwait : xnowait;
		t = gettoken();
		if(t==')' || t=='\n')	/* tests ~first(pipeline) */
			break;
		np1 = alloc(0);
		np1->args[0] = np;
		if((np1->args[1]=pipeline()) == 0)
			return 0;
		np = np1;
	}
	if(np->op == 0)
		np->op = xwait;
	return np;
}

/* error - print error message s, prefixed by t */
void
error(char *s, char *t)
{
	char buf[ERRLEN];

	fprint(2, "%s%s", t, s);
	errstr(buf);
	fprint(2, ": %s\n", buf);
}

/* pipeline - command ( | command )* */
Node*
pipeline(void)
{
	Node *np, *np1;

	if((np=command()) == 0)
		return 0;
	while(t == '|'){
		np1 = alloc(xpipeline);
		np1->args[0] = np;
		t = gettoken();
		if((np1->args[1]=command()) == 0)
			return 0;
		np = np1;
	}
	return np;
}

/* redirect - redirect i/o according to np->io[] values */
void
redirect(Node *np)
{
	int fd;

	if(np->io[0]){
		if((fd = open(np->io[0], 0)) < 0){
			error(": can't open", np->io[0]);
			exits("open");
		}
		dup(fd, 0);
		close(fd);
	}
	if(np->io[1]){
		if((fd = create(np->io[1], 1, 0666L)) < 0){
			error(": can't create", np->io[1]);
			exits("create");
		}
		dup(fd, 1);
		close(fd);
	}
	if(np->io[2]){
		if((fd = open(np->io[2], 1)) < 0 && (fd = create(np->io[2], 1, 0666L)) < 0){
			error(": can't write", np->io[2]);
			exits("write");
		}
		dup(fd, 1);
		close(fd);
		seek(1, 0, 2);
	}
}

/* setio - ( < | > | >> ) word; fill in np->io[] */
int
setio(Node *np)
{
	if(t == '<'){
		t = gettoken();
		np->io[0] = token;
	}else if(t == '>'){
		t = gettoken();
		if(t == '>'){
			t = gettoken();
			np->io[2] = token;
			}else
			np->io[1] = token;
	}else
		return 0;
	if(t != WORD)
		return 0;
	return 1;
}
			
/* simple - word ( [ < | > | >> ] word )* */
Node*
simple(void)
{
	Node *np;
	int n = 1;

	if(t != WORD)
		return 0;
	np = alloc(xsimple);
	np->argv[0] = token;
	while((t = gettoken())==WORD || t=='<' || t=='>')
		if(t == WORD)
			np->argv[n++] = token;
		else if(!setio(np))
			return 0;
	np->argv[n] = 0;
	return np;
}

/* xpipeline - execute cmd | cmd */
int
xpipeline(Node *np)
{
	int pid, fd[2];

	if(pipe(fd) < 0){
		error("can't create pipe", "");
		return 0;
	}
	if((pid=fork()) == 0){	/* left side; redirect stdout */
		dup(fd[1], 1);
		close(fd[0]);
		close(fd[1]);
		execute(np->args[0]);
		exits(status.msg);
	}else if(pid == -1){
		error("can't create process", "");
		return 0;
	}
	if((pid=fork()) == 0){	/* right side; redirect stdin */
		dup(fd[0], 0);
		close(fd[0]);
		close(fd[1]);
		pid = execute(np->args[1]); /*BUG: this is wrong sometimes*/
		if(pid > 0)
			while(wait(&status)!=-1  && atoi(status.pid)!=pid)
				;
		exits(0);
	}else if(pid == -1){
		error("can't create process", "");
		return 0;
	}
	close(fd[0]);	/* avoid using up fd's */
	close(fd[1]);
	return pid;
}

/* xsimple - execute a simple command */
int
xsimple(Node *np)
{
	char name[MAXLINE];
	int pid, i;

	if(builtin(np))
		return 0;
	if(pid = fork()){
		if(pid == -1)
			error(": can't create process", np->argv[0]);
		return pid;
	}
	redirect(np);	/* child process */
	exec(np->argv[0], &np->argv[0]);
	i = np->argv[0][0];
	if(i!='/' && i!='#' && (i!='.' || np->argv[0][1]!='/'))
		for(i = 0; path[i]; i++){
			sprint(name, "%s/%s", path[i], np->argv[0]);
			exec(name, &np->argv[0]);
		}
	error(": not found", np->argv[0]);
	exits("not found");
}

/* xsubshell - execute (cmd) */
int
xsubshell(Node *np)
{
	int pid;

	if(pid = fork()){
		if(pid == -1)
			error("can't create process", "");
		return pid;
	}
	redirect(np);	/* child process */
	execute(np->args[0]);
	exits(status.msg);
}

/* xnowait - execute cmd & */
int
xnowait(Node *np)
{
	int pid;

	execute(np->args[0]);
	pid = execute(np->args[1]);
	if(interactive)
		fprint(2, "%d\n", pid);
	return 0;
}

/* xwait - execute cmd ; */
int xwait(Node *np)
{
	int pid;

	execute(np->args[0]);
	pid = execute(np->args[1]);
	if(pid > 0){
		while(wait(&status) != -1 && atoi(status.pid) != pid)
			;
		if(atoi(status.pid) != pid)
			error("wait error", "");
	}
	return 0;
}

M mpc/trap.c => mpc/trap.c +79 -16
@@ 33,6 33,7 @@ struct

void	faultpower(Ureg *ur, ulong addr, int read);
void	kernfault(Ureg*, int);
void	syscall(Ureg* ureg);

char *excname[] =
{


@@ 179,11 180,7 @@ trap(Ureg *ur)
		break;

	case CSYSCALL:
		spllo();
		print("syscall!\n");
		dumpregs(ur);
		delay(100);
		splhi();
		syscall(ur);
		break;

	case CPROG:


@@ 214,7 211,7 @@ faultpower(Ureg *ureg, ulong addr, int read)
	char buf[ERRLEN];

	user = (ureg->srr1 & MSR_PR) != 0;
print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg);
//print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg);
	insyscall = up->insyscall;
	up->insyscall = 1;
	spllo();


@@ 229,7 226,6 @@ print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, a
		postnote(up, 1, buf, NDebug);
	}
	up->insyscall = insyscall;
	splhi();
}

void


@@ 540,9 536,8 @@ forkchild(Proc *p, Ureg *ur)

	cur = (Ureg*)(p->sched.sp+2*BY2WD);
	memmove(cur, ur, sizeof(Ureg));

	cur->pc += 4;

	cur->r3 = 0;
	
	/* Things from bottom of syscall we never got to execute */
	p->psstate = 0;
	p->insyscall = 0;


@@ 558,12 553,6 @@ userpc(void)
}


// need to be in l.s
void
forkret(void)
{
	panic("forkret");
}
/* This routine must save the values of registers the user is not 
 * permitted to write from devproc and then restore the saved values 
 * before returning


@@ 599,3 588,77 @@ dbgpc(Proc *p)

	return ureg->pc;
}

/*
 *  system calls
 */
#include "../port/systab.h"

/*
 *  Syscall should be called directly from assembler without going through trap().
 */
void
syscall(Ureg* ureg)
{
	ulong	sp;
	long	ret;
	int	i, scallnr;

	if((ureg->srr1 & MSR_PR) == 0)
		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1);

	m->syscall++;
	up->insyscall = 1;
	up->pc = ureg->pc;
	up->dbgreg = ureg;

	scallnr = ureg->r3;
//print("scall %s\n", sysctab[scallnr]);
	up->scallnr = scallnr;
	spllo();

	sp = ureg->usp;
	up->nerrlab = 0;
	ret = -1;
	if(!waserror()){
		if(scallnr >= nsyscall){
			pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
			postnote(up, 1, "sys: bad sys call", NDebug);
			error(Ebadarg);
		}

		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
			validaddr(sp, sizeof(Sargs)+BY2WD, 0);

		up->s = *((Sargs*)(sp+BY2WD));
		up->psstate = sysctab[scallnr];

		ret = systab[scallnr](up->s.args);
		poperror();
	}
	if(up->nerrlab){
		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
		for(i = 0; i < NERR; i++)
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
		panic("error stack");
	}

	up->insyscall = 0;
	up->psstate = 0;

	/*
	 *  Put return value in frame.  On the x86 the syscall is
	 *  just another trap and the return value from syscall is
	 *  ignored.  On other machines the return value is put into
	 *  the results register by caller of syscall.
	 */
	ureg->r3 = ret;
//print("ret = %d\n", ret);
//	if(scallnr == NOTED)
//		noted(ureg, *(ulong*)(sp+BY2WD));

//	if(scallnr!=RFORK && (up->procctl || up->nnote)){
//		splhi();
//		notify(ureg);
//	}
}

M port/devdraw.c => port/devdraw.c +34 -12
@@ 787,21 787,37 @@ drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int ind
	return p;
}

Chan*
drawattach(char *spec)
static int
initscreenimage(void)
{
	int width;

	if(screendata.data == nil){
		screendata.base = nil;
		screendata.data = attachscreen(&screenimage.r, &screenimage.ldepth, &width, &sdraw.softscreen);
		if(screendata.data != nil){
			screendata.ref = 1;
			screenimage.data = &screendata;
			screenimage.width = width;
			screenimage.clipr  = screenimage.r;
		}
	if(screendata.data != nil)
		return 1;
	screendata.data = attachscreen(&screenimage.r, &screenimage.ldepth, &width, &sdraw.softscreen);
	if(screendata.data == nil)
		return 0;

	screendata.base = nil;
	if(screendata.data != nil){
		screendata.ref = 1;
		screenimage.data = &screendata;
		screenimage.width = width;
		screenimage.clipr  = screenimage.r;
	}

	return 1;
}

Chan*
drawattach(char *spec)
{
	qlock(&sdraw);
	if(!initscreenimage()){
		qunlock(&sdraw);
		error("no frame buffer");
	}
	qunlock(&sdraw);
	return devattach('i', spec);
}



@@ 1606,7 1622,6 @@ drawmesg(Client *client, void *av, int n)
			if(n < m)
				error(Eshortdraw);

		CaseS:
			dst = drawimage(client, a+1);
			dstid = BGLONG(a+1);
			src = drawimage(client, a+5);


@@ 1808,6 1823,12 @@ drawblankscreen(int blank)

	if(blank == sdraw.blanked)
		return;
	if(!canqlock(&sdraw))
		return;
	if(!initscreenimage()){
		qunlock(&sdraw);
		return;
	}
	p = sdraw.savemap;
	nc = 1<<(1<<screenimage.ldepth);
	if(blank == 0)	/* turn screen on */


@@ 1819,6 1840,7 @@ drawblankscreen(int blank)
			setcolor(i, 0, 0, 0);
		}
	sdraw.blanked = blank;
	qunlock(&sdraw);
}

/*