~kris/9p

9hist

58e97a10c9e0ca4cfeb12a4a26bb5b37218dcb30 — David du Colombier 25 years ago 9df8240
Plan 9 from Bell Labs 2000-11-07
8 files changed, 485 insertions(+), 86 deletions(-)

M bitsy/clock.c
M bitsy/devflash.c
M bitsy/devuda1341.c
M boot/boot.c
M boot/boot.h
M boot/bootip.c
M pc/devi82365.c
M port/netif.c
M bitsy/clock.c => bitsy/clock.c +1 -72
@@ 7,44 7,6 @@
#include	"ureg.h"
#include	"../port/error.h"

typedef struct OSTimer
{
	ulong	osmr[4];	/* match registers */
	ulong	oscr;		/* counter register */
	ulong	ossr;		/* status register */
	ulong	ower;		/* watchdog enable register */
	ulong	oier;		/* timer interrupt enable register */
} OSTimer;

static OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
static int clockinited;

static void	clockintr(Ureg*, void*);

typedef struct Clock0link Clock0link;
typedef struct Clock0link {
	void		(*clock)(void);
	Clock0link*	link;
} Clock0link;

static Clock0link *clock0link;
static Lock clock0lock;

void
addclock0link(void (*clock)(void))
{
	Clock0link *lp;

	if((lp = malloc(sizeof(Clock0link))) == 0){
		print("addclock0link: too many links\n");
		return;
	}
	ilock(&clock0lock);
	lp->clock = clock;
	lp->link = clock0link;
	clock0link = lp;
	iunlock(&clock0lock);
}

void
clockinit(void)


@@ 83,40 45,7 @@ clockintr(Ureg *ureg, void*)
	/* post interrupt 1/HZ secs from now */
	timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;

	m->ticks++;

	if(m->proc)
		m->proc->pc = ureg->pc;

	if(inclockintr)
		return;		/* interrupted ourself */

	inclockintr = 1;

	accounttime();
	if(kproftimer != nil)
		(*kproftimer)(ureg->pc);

	checkalarms();
	ilock(&clock0lock);
	for(lp = clock0link; lp; lp = lp->link)
		lp->clock();
	iunlock(&clock0lock);

	if(active.exiting && (active.machs & (1<<m->machno)))
		exit(0);
	inclockintr = 0;

	if(up == 0 || up->state != Running)
		return;

	if(anyready())
		sched();
	
	if((ureg->psr & PsrMask) == PsrMusr) {
		(*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
		segclock(ureg->pc);
	}
	portclock();
}

void

M bitsy/devflash.c => bitsy/devflash.c +57 -0
@@ 15,3 15,60 @@ struct FlashPart
	ulong	start;		/* byte offsets */
	ulong	end;
};

static ulong *flash = (ulong*)FLASHZERO;

/*
 *  on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit
 *  accesses, one to the low half of the chip and the other to the high
 *  half.  Therefore for all command accesses, ushort indices in the
 *  manuals turn into ulong indices in our code.  Also, by copying all
 *  16 bit commands to both halves of a 32 bit command, we erase 2
 *  sectors for each request erase request.
 */

/*
 *  common flash memory interface
 */
enum
{
	CFIidoff=	0x10,
	CFIsysoff=	0x1B,
	CFIgeomoff=	0x27,
};

struct CFIid
{
	ulong	q;
	ulong	r;
	ulong	y;
	ulong	cmd_set;
	ulong	vendor_alg;
	ulong	ext_alg_addr[2];
	ulong	alt_cmd_set;
	ulong	alt_vendor_alg;
	ulong	alt_ext_ald_addr[2];
	
};

struct CFIsys
{
	ulong 	vcc_min;	/* 100 mv */
	ulong	vcc_max;
	ulong	vpp_min;
	ulong	vpp_max;
	ulong	word_wr_to;		/* 2**n µs */
	ulong	buf_wr_to;		/* 2**n µs */
	ulong	block_erase_to;		/* 2**n ms */
	ulong	chip_erase_to;		/* 2**n ms */
	ulong	max_word_wr_to;		/* 2**n µs */
	ulong	max_buf_wr_to;		/* 2**n µs */
	ulong	max_block_erase_to;	/* 2**n ms */
	ulong	max_chip_erase_to;	/* 2**n ms */
};

struct CFIgeom
{
	ulong	size;		/* 2**n bytes */
	ulong	
};

M bitsy/devuda1341.c => bitsy/devuda1341.c +373 -0
@@ 460,3 460,376 @@ audioinit(void)

	return 0;
}

static void
audioinit(void)
{}


static Chan*
audioattach(char *param)
{
	return devattach('A', param);
}

static int
audiowalk(Chan *c, char *name)
{
	return devwalk(c, name, audiodir, nelem(audiodir), devgen);
}

static void
audiostat(Chan *c, char *db)
{
	devstat(c, db, audiodir, nelem(audiodir), devgen);
}

static Chan*
audioopen(Chan *c, int omode)
{
	int amode;

	switch(c->qid.path & ~CHDIR) {
	default:
		error(Eperm);
		break;

	case Qstatus:
		if((omode&7) != OREAD)
			error(Eperm);
	case Qvolume:
	case Qdir:
		break;

	case Qaudio:
		amode = Awrite;
		switch (omode & 0x7)
		case OREAD:
			break;
		case OWRITE
		qlock(&audio);
		if(audio.amode != Aclosed){
			qunlock(&audio);
			error(Einuse);
		}
		if(audio.bufinit == 0) {
			audio.bufinit = 1;
			sbbufinit();
		}
		audio.amode = amode;
		setempty();
		audio.curcount = 0;
		qunlock(&audio);
		mxvolume();
		break;
	}
	c = devopen(c, omode, audiodir, nelem(audiodir), devgen);
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;

	return c;
}

static void
audioclose(Chan *c)
{
	Buf *b;

	switch(c->qid.path & ~CHDIR) {
	default:
		error(Eperm);
		break;

	case Qdir:
	case Qvolume:
	case Qstatus:
		break;

	case Qaudio:
		if(c->flag & COPEN) {
			qlock(&audio);
			if(audio.amode == Awrite) {
				/* flush out last partial buffer */
				b = audio.filling;
				if(b) {
					audio.filling = 0;
					memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount);
					swab(b->virt);
					putbuf(&audio.full, b);
				}
				if(!audio.active && audio.full.first)
					pokeaudio();
			}
			audio.amode = Aclosed;
			if(waserror()){
				qunlock(&audio);
				nexterror();
			}
			while(audio.active)
				waitaudio();
			setempty();
			poperror();
			qunlock(&audio);
		}
		break;
	}
}

static long
audioread(Chan *c, void *v, long n, vlong off)
{
	int liv, riv, lov, rov;
	long m, n0;
	char buf[300];
	Buf *b;
	int j;
	ulong offset = off;
	char *a;

	n0 = n;
	a = v;
	switch(c->qid.path & ~CHDIR) {
	default:
		error(Eperm);
		break;

	case Qdir:
		return devdirread(c, a, n, audiodir, nelem(audiodir), devgen);

	case Qaudio:
		if(audio.amode != Aread)
			error(Emode);
		qlock(&audio);
		if(waserror()){
			qunlock(&audio);
			nexterror();
		}
		while(n > 0) {
			b = audio.filling;
			if(b == 0) {
				b = getbuf(&audio.full);
				if(b == 0) {
					waitaudio();
					continue;
				}
				audio.filling = b;
				swab(b->virt);
				audio.curcount = 0;
			}
			m = Bufsize-audio.curcount;
			if(m > n)
				m = n;
			memmove(a, b->virt+audio.curcount, m);

			audio.curcount += m;
			n -= m;
			a += m;
			if(audio.curcount >= Bufsize) {
				audio.filling = 0;
				putbuf(&audio.empty, b);
			}
		}
		poperror();
		qunlock(&audio);
		break;

	case Qstatus:
		buf[0] = 0;
		snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n",
			audio.totcount, audio.tottime);
		return readstr(offset, a, n, buf);

	case Qvolume:
		j = 0;
		buf[0] = 0;
		for(m=0; volumes[m].name; m++){
			liv = audio.livol[m];
			riv = audio.rivol[m];
			lov = audio.lovol[m];
			rov = audio.rovol[m];
			j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
			if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
					j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
				else{
					if(volumes[m].flag & Fin)
						j += snprint(buf+j, sizeof(buf)-j,
							" in %d", liv);
					if(volumes[m].flag & Fout)
						j += snprint(buf+j, sizeof(buf)-j,
							" out %d", lov);
				}
			}else{
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
				    liv==lov && riv==rov)
					j += snprint(buf+j, sizeof(buf)-j,
						" left %d right %d",
						liv, riv);
				else{
					if(volumes[m].flag & Fin)
						j += snprint(buf+j, sizeof(buf)-j,
							" in left %d right %d",
							liv, riv);
					if(volumes[m].flag & Fout)
						j += snprint(buf+j, sizeof(buf)-j,
							" out left %d right %d",
							lov, rov);
				}
			}
			j += snprint(buf+j, sizeof(buf)-j, "\n");
		}
		return readstr(offset, a, n, buf);
	}
	return n0-n;
}

static long
audiowrite(Chan *c, void *vp, long n, vlong)
{
	long m, n0;
	int i, nf, v, left, right, in, out;
	char buf[255], *field[Ncmd];
	Buf *b;
	char *a;

	a = vp;
	n0 = n;
	switch(c->qid.path & ~CHDIR) {
	default:
		error(Eperm);
		break;

	case Qvolume:
		v = Vaudio;
		left = 1;
		right = 1;
		in = 1;
		out = 1;
		if(n > sizeof(buf)-1)
			n = sizeof(buf)-1;
		memmove(buf, a, n);
		buf[n] = '\0';

		nf = getfields(buf, field, Ncmd, 1, " \t\n");
		for(i = 0; i < nf; i++){
			/*
			 * a number is volume
			 */
			if(field[i][0] >= '0' && field[i][0] <= '9') {
				m = strtoul(field[i], 0, 10);
				if(left && out)
					audio.lovol[v] = m;
				if(left && in)
					audio.livol[v] = m;
				if(right && out)
					audio.rovol[v] = m;
				if(right && in)
					audio.rivol[v] = m;
				mxvolume();
				goto cont0;
			}

			for(m=0; volumes[m].name; m++) {
				if(strcmp(field[i], volumes[m].name) == 0) {
					v = m;
					in = 1;
					out = 1;
					left = 1;
					right = 1;
					goto cont0;
				}
			}

			if(strcmp(field[i], "reset") == 0) {
				resetlevel();
				mxvolume();
				goto cont0;
			}
			if(strcmp(field[i], "in") == 0) {
				in = 1;
				out = 0;
				goto cont0;
			}
			if(strcmp(field[i], "out") == 0) {
				in = 0;
				out = 1;
				goto cont0;
			}
			if(strcmp(field[i], "left") == 0) {
				left = 1;
				right = 0;
				goto cont0;
			}
			if(strcmp(field[i], "right") == 0) {
				left = 0;
				right = 1;
				goto cont0;
			}
			error(Evolume);
			break;
		cont0:;
		}
		break;

	case Qaudio:
		if(audio.amode != Awrite)
			error(Emode);
		qlock(&audio);
		if(waserror()){
			qunlock(&audio);
			nexterror();
		}
		while(n > 0) {
			b = audio.filling;
			if(b == 0) {
				b = getbuf(&audio.empty);
				if(b == 0) {
					waitaudio();
					continue;
				}
				audio.filling = b;
				audio.curcount = 0;
			}

			m = Bufsize-audio.curcount;
			if(m > n)
				m = n;
			memmove(b->virt+audio.curcount, a, m);

			audio.curcount += m;
			n -= m;
			a += m;
			if(audio.curcount >= Bufsize) {
				audio.filling = 0;
				swab(b->virt);
				putbuf(&audio.full, b);
			}
		}
		poperror();
		qunlock(&audio);
		break;
	}
	return n0 - n;
}

Dev audiodevtab = {
	'A',
	"audio",

	devreset,
	audioinit,
	audioattach,
	devclone,
	audiowalk,
	audiostat,
	audioopen,
	devcreate,
	audioclose,
	audioread,
	devbread,
	audiowrite,
	devbwrite,
	devremove,
	devwstat,
};

M boot/boot.c => boot/boot.c +29 -1
@@ 199,6 199,34 @@ findmethod(char *a)
	return 0;
}

int
parsecmd(char *s, char **av, int n)
{
	int ac;

	n--;
	for(ac = 0; ac < n; ac++){
		while(*s == ' ' || *s == '\t')
			s++;
		if(*s == 0 || *s == '\n' || *s == '\r')
			break;
		if(*s == '\''){
			s++;
			av[ac] = s;
			while(*s && *s != '\'')
				s++;
		} else {
			av[ac] = s;
			while(*s && *s != ' ' && *s != '\t')
				s++;
		}
		if(*s != 0)
			*s++ = 0;
	}
	av[ac] = 0;
	return ac;
}

/*
 *  ask user from whence cometh the root file system
 */


@@ 234,7 262,7 @@ rootserver(char *arg)
		outin(prompt, reply, sizeof(reply));
		mp = findmethod(reply);
		if(mp){
			bargc = getfields(reply, bargv, Nbarg-1, 1, " ");
			bargc = parsecmd(reply, bargv, Nbarg);
			cp = strchr(reply, '!');
			if(cp)
				strcpy(sys, cp+1);

M boot/boot.h => boot/boot.h +1 -1
@@ 22,7 22,7 @@ extern uchar	hostkey[];
extern char	username[NAMELEN];
enum
{
	Nbarg=	16,
	Nbarg=	32,
};
extern int	bargc;
extern char	*bargv[Nbarg];

M boot/bootip.c => boot/bootip.c +1 -0
@@ 43,6 43,7 @@ configip(void)
	case 'b':
	case 'h':
	case 'm':
	case 'c':
		p = ARGF();
		USED(p);
		break;

M pc/devi82365.c => pc/devi82365.c +21 -11
@@ 178,6 178,7 @@ struct Slot
	uchar	busy;

	/* cis info */
	ulong	msec;		/* time of last slotinfo call */
	char	verstr[512];	/* version string */
	uchar	cpresent;	/* config registers present */
	ulong	caddr;		/* relative address of config registers */


@@ 236,6 237,7 @@ slotinfo(Slot *pp)
	pp->battery = (isr & 3) == 3;
	pp->wrprot = isr & (1<<4);
	pp->busy = isr & (1<<5);
	pp->msec = TK2MS(MACHP(0)->ticks);
}

static int


@@ 438,28 440,35 @@ pcmspecial(char *idstr, ISAConf *isa)
{
	Slot *pp;
	extern char *strstr(char*, char*);
	static int resetdone;
	int enabled;

	i82365reset();
print("pcmcia: looking for %s: ", idstr);
	for(pp = slot; pp < lastslot; pp++){
		if(pp->special)
			continue;	/* already taken */
		increfp(pp);
		enabled = 0;
		/* make sure we don't power on cards when we already know what's
		 * in them.  We'll reread every two minutes if necessary
		 */
		if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000) {
			increfp(pp);
			enabled++;
		}

		if(pp->occupied) {
print("[%8.8s]", pp->verstr);
			if(strstr(pp->verstr, idstr))
			if(isa == 0 || pcmio(pp->slotno, isa) == 0){
				pp->special = 1;
print(" - found\n");
				return pp->slotno;
			if(strstr(pp->verstr, idstr)) {
				if (!enabled)
					increfp(pp);
				if(isa == 0 || pcmio(pp->slotno, isa) == 0){
					pp->special = 1;
					return pp->slotno;
				}
			}
		} else
			pp->special = 1;
		decrefp(pp);
		if (enabled)
			decrefp(pp);
	}
print("\n");
	return -1;
}



@@ 680,6 689,7 @@ i82365reset(void)
			pp->memlen = 64*MB;
			pp->base = (cp->dev<<7) | (j<<6);
			pp->cp = cp;
			pp->msec = ~0;
			slotdis(pp);

			/* interrupt on status change */

M port/netif.c => port/netif.c +2 -1
@@ 318,7 318,8 @@ netifwrite(Netif *nif, Chan *c, void *a, long n)
		p = netmulti(nif, f, binaddr, 0);
		if(p)
			error(p);
	}
	} else
		n = -1;
	qunlock(nif);
	poperror();
	return n;