~kris/9p

9hist

8e823fe409c14555db6826990a890908da7dbe4e — David du Colombier 25 years ago 6273cbe
Plan 9 from Bell Labs 2001-05-29
M bitsy/dat.h => bitsy/dat.h +3 -1
@@ 189,6 189,7 @@ enum
	OneMeg=	1024*1024,
};

#ifdef NDEF
/*
 *  routines to access UART hardware
 */


@@ 265,6 266,7 @@ struct Uart

	Rendez	r;
};
#endif

/*
 * PCMCIA structures known by both port/cis.c and the pcmcia driver


@@ 360,5 362,5 @@ struct DevConf
	int	size;		/* access size */
	int	itype;		/* type of interrupt */
	ulong	interrupt;	/* interrupt number */
	char	type[NAMELEN];	/* card type */
	char	*type;	/* card type, mallocated */
};

M bitsy/devether.c => bitsy/devether.c +13 -12
@@ 34,7 34,7 @@ etherconfig(int on, char *spec, DevConf *cf)
{
	Ether *ether;
	int n, ctlrno;
	char name[NAMELEN], buf[128];
	char name[32], buf[128];
	char *p, *e;

	/* can't unconfigure yet */


@@ 98,6 98,8 @@ etherconfig(int on, char *spec, DevConf *cf)
		return 0;
	}

	if (ether->type)
		free(ether->type);
	free(ether);
	return -1;
}


@@ 127,16 129,16 @@ etherattach(char* spec)
	return chan;
}

static int
etherwalk(Chan* chan, char* name)
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
	return netifwalk(etherxx[chan->dev], chan, name);
	return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}

static void
etherstat(Chan* chan, char* dp)
static int
etherstat(Chan* chan, uchar* dp, int n)
{
	netifstat(etherxx[chan->dev], chan, dp);
	return netifstat(etherxx[chan->dev], chan, dp, n);
}

static Chan*


@@ 163,7 165,7 @@ etherread(Chan* chan, void* buf, long n, vlong off)
	ulong offset = off;

	ether = etherxx[chan->dev];
	if((chan->qid.path & CHDIR) == 0 && ether->ifstat){
	if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
		/*
		 * With some controllers it is necessary to reach
		 * into the chip to extract statistics.


@@ 188,10 190,10 @@ etherremove(Chan*)
{
}

static void
etherwstat(Chan* chan, char* dp)
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
	netifwstat(etherxx[chan->dev], chan, dp);
	return netifwstat(etherxx[chan->dev], chan, dp, n);
}

static void


@@ 449,7 451,6 @@ Dev etherdevtab = {
	etherreset,
	devinit,
	etherattach,
	devclone,
	etherwalk,
	etherstat,
	etheropen,

M bitsy/devflash.c => bitsy/devflash.c +41 -30
@@ 152,7 152,7 @@ enum
typedef struct FPart FPart;
struct FPart
{
	char	name[NAMELEN-4];
	char	*name;
	ulong	start;
	ulong	end;
};


@@ 163,25 163,26 @@ static FPart	part[Maxpart];
#define FPART(q)	(&part[(q) >>8])

static int
gen(Chan *c, Dirtab*, int, int i, Dir *dp)
gen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
{
	Qid q;
	char buf[NAMELEN];
	char buf[KNAMELEN];
	FPart *fp;

	q.vers = 0;

	/* top level directory contains the name of the network */
	if(c->qid.path == CHDIR){
	if(c->qid.path == Qtopdir){
		switch(i){
		case DEVDOTDOT:
			q.path = CHDIR;
			devdir(c, q, ".", 0, eve, CHDIR|0555, dp);
			q.path = Qtopdir;
			q.type = QTDIR;
			devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
			break;
		case 0:
			q.path = CHDIR | Q2nddir;
			strcpy(buf, "flash");
			devdir(c, q, buf, 0, eve, CHDIR|0555, dp);
			q.path = Q2nddir;
			q.type = QTDIR;
			devdir(c, q, "flash", 0, eve, DMDIR|0555, dp);
			break;
		default:
			return -1;


@@ 192,21 193,24 @@ gen(Chan *c, Dirtab*, int, int i, Dir *dp)
	/* second level contains all partitions and their control files */
	switch(i) {
	case DEVDOTDOT:
		q.path = CHDIR;
		devdir(c, q, "#F", 0, eve, CHDIR|0555, dp);
		q.path = Qtopdir;
		q.type = QTDIR;
		devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
		break;
	default:
		if(i >= 2*Maxpart)
			return -1;
		fp = &part[i>>1];
		if(fp->name[0] == 0)
		if(fp->name == nil)
			return 0;
		if(i & 1){
			q.path = FQID(i>>1, Qfdata);
			q.type = QTFILE;
			devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);
		} else {
			snprint(buf, sizeof(buf), "%sctl", fp->name);
			q.path = FQID(i>>1, Qfctl);
			q.type = QTFILE;
			devdir(c, q, buf, 0, eve, 0660, dp);
		}
		break;


@@ 232,8 236,6 @@ addpart(FPart *fp, char *name, ulong start, ulong end)
{
	int i;

	if(strlen(name) > NAMELEN-3)
		error("name too long");
	if(fp == nil){
		if(start >= flash.size || end > flash.size)
			error(Ebadarg);


@@ 257,7 259,7 @@ addpart(FPart *fp, char *name, ulong start, ulong end)
	if(i == Maxpart)
		error("no more partitions");
	fp = &part[i];
	strncpy(fp->name, name, sizeof(fp->name)-1);
	kstrdup(&fp->name, name);
	fp->start = start;
	fp->end = end;
}


@@ 265,7 267,11 @@ addpart(FPart *fp, char *name, ulong start, ulong end)
static void
rempart(FPart *fp)
{
	fp->name[0] = 0;
	char *p;

	p = fp->name;
	fp->name = nil;
	free(p);
}

void


@@ 292,16 298,16 @@ flashattach(char* spec)
	return devattach('F', spec);
}

static int	 
flashwalk(Chan* c, char* name)
static Walkqid*
flashwalk(Chan *c, Chan *nc, char **name, int nname)
{
	return devwalk(c, name, nil, 0, gen);
	return devwalk(c, nc, name, nname, nil, 0, gen);
}

static void	 
flashstat(Chan* c, char* dp)
static int	 
flashstat(Chan *c, uchar *db, int n)
{
	devstat(c, dp, nil, 0, gen);
	return devstat(c, db, n, nil, 0, gen);
}

static Chan*


@@ 353,7 359,7 @@ flashdataread(FPart *fp, void* a, long n, vlong off)
		runlock(&flash);
		nexterror();
	}
	if(fp->name[0] == 0)
	if(fp->name == nil)
		error("partition vanished");
	if(!iseve())
		error(Eperm);


@@ 373,9 379,12 @@ flashdataread(FPart *fp, void* a, long n, vlong off)
static long	 
flashread(Chan* c, void* a, long n, vlong off)
{
	if(c->qid.path&CHDIR)
	int t;

	if(c->qid.type == QTDIR)
		return devdirread(c, a, n, nil, 0, gen);
	switch(FTYPE(c->qid.path)){
	t = FTYPE(c->qid.path);
	switch(t){
	default:
		error(Eperm);
	case Qfctl:


@@ 514,7 523,7 @@ flashdatawrite(FPart *fp, uchar *p, long n, long off)
		nexterror();
	}

	if(fp->name[0] == 0)
	if(fp->name == nil)
		error("partition vanished");
	if(!iseve())
		error(Eperm);


@@ 575,13 584,16 @@ flashdatawrite(FPart *fp, uchar *p, long n, long off)
static long	 
flashwrite(Chan* c, void* a, long n, vlong off)
{
	if(c->qid.path & CHDIR)
	int t;

	if(c->qid.type == QTDIR)
		error(Eperm);

	if(!iseve())
		error(Eperm);

	switch(FTYPE(c->qid.path)){
	t = FTYPE(c->qid.path);
	switch(t){
	default:
		panic("flashwrite");
	case Qfctl:


@@ 601,7 613,6 @@ Dev flashdevtab = {
	devreset,
	flashinit,
	flashattach,
	devclone,
	flashwalk,
	flashstat,
	flashopen,


@@ 655,7 666,7 @@ ise_clearerror(void)
static void
ise_error(int bank, ulong status)
{
	char err[ERRLEN];
	char err[64];

	if(status & (ISEs_lockerr)){
		sprint(err, "flash%d: block locked %lux", bank, status);

M bitsy/devpcmcia.c => bitsy/devpcmcia.c +18 -20
@@ 34,8 34,8 @@ enum
	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */
};

#define SLOTNO(c)	((c->qid.path>>8)&0xff)
#define TYPE(c)		(c->qid.path&0xff)
#define SLOTNO(c)	((ulong)((c->qid.path>>8)&0xff))
#define TYPE(c)	((ulong)(c->qid.path&0xff))
#define QID(s,t)	(((s)<<8)|(t))

static void increfp(PCMslot*);


@@ 45,16 45,16 @@ static void slottiming(int, int, int, int, int);
static void slotinfo(Ureg*, void*);

static int
pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp)
{
	int slotno;
	Qid qid;
	long len;
	PCMslot *sp;
	char name[NAMELEN];

	if(i == DEVDOTDOT){
		devdir(c, (Qid){CHDIR, 0}, "#y", 0, eve, 0555, dp);
		mkqid(&qid, Qdir, 0, QTDIR);
		devdir(c, qid, "#y", 0, eve, 0555, dp);
		return 1;
	}



@@ 67,21 67,21 @@ pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
	switch(i%Nents){
	case 0:
		qid.path = QID(slotno, Qmem);
		sprint(name, "pcm%dmem", slotno);
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
		len = sp->memlen;
		break;
	case 1:
		qid.path = QID(slotno, Qattr);
		sprint(name, "pcm%dattr", slotno);
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
		len = sp->memlen;
		break;
	case 2:
		qid.path = QID(slotno, Qctl);
		sprint(name, "pcm%dctl", slotno);
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
		break;
	}
	qid.vers = 0;
	devdir(c, qid, name, len, eve, 0660, dp);
	devdir(c, qid, up->genbuf, len, eve, 0660, dp);
	return 1;
}



@@ 125,22 125,22 @@ pcmciaattach(char *spec)
	return devattach('y', spec);
}

static int
pcmciawalk(Chan *c, char *name)
static Walkqid*
pcmciawalk(Chan *c, Chan *nc, char **name, int nname)
{
	return devwalk(c, name, 0, 0, pcmgen);
	return devwalk(c, nc, name, nname, 0, 0, pcmgen);
}

static void
pcmciastat(Chan *c, char *db)
static int
pcmciastat(Chan *c, uchar *db, int n)
{
	devstat(c, db, 0, 0, pcmgen);
	return devstat(c, db, n, 0, 0, pcmgen);
}

static Chan*
pcmciaopen(Chan *c, int omode)
{
	if(c->qid.path == CHDIR){
	if(c->qid.type & QTDIR){
		if(omode != OREAD)
			error(Eperm);
	} else


@@ 155,7 155,7 @@ static void
pcmciaclose(Chan *c)
{
	if(c->flag & COPEN)
		if(c->qid.path != CHDIR)
		if((c->qid.type & QTDIR) == 0)
			decrefp(slot+SLOTNO(c));
}



@@ 320,8 320,7 @@ pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
		}

		/* configure device */
		strncpy(cf.type, cmd->f[2], sizeof(cf.type)-1);
		cf.type[sizeof(cf.type)-1] = 0;
		kstrdup(&cf.type, cmd->f[2]);
		cf.mem = (ulong)sp->mem;
		cf.port = (ulong)sp->regs;
		cf.itype = GPIOfalling;


@@ 374,7 373,6 @@ Dev pcmciadevtab = {
	pcmciareset,
	devinit,
	pcmciaattach,
	devclone,
	pcmciawalk,
	pcmciastat,
	pcmciaopen,

M bitsy/devpenmouse.c => bitsy/devpenmouse.c +16 -25
@@ 77,9 77,10 @@ enum{
};

static Dirtab mousedir[]={
	"mouse",	{Qmouse},		0,			0666,
	"mousein",	{Qmousein},		0,			0220,
	"mousectl",	{Qmousectl},	0,			0660,
	".",			{Qdir, 0, QTDIR},	0,	DMDIR|0555,
	"mouse",		{Qmouse},		0,	0666,
	"mousein",	{Qmousein},		0,	0220,
	"mousectl",	{Qmousectl},		0,	0660,
};

static uchar buttonmap[8] = {


@@ 145,32 146,23 @@ penmouseattach(char *spec)
	return devattach('m', spec);
}

static Chan*
penmouseclone(Chan *c, Chan *nc)
static Walkqid*
penmousewalk(Chan *c, Chan *nc, char **name, int nname)
{
	nc = devclone(c, nc);
	if(c->qid.path != CHDIR)
		incref(&mouse);
	return nc;
	return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
}

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

static void
penmousestat(Chan *c, char *db)
penmousestat(Chan *c, uchar *db, int n)
{
	devstat(c, db, mousedir, nelem(mousedir), devgen);
	return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
}

static Chan*
penmouseopen(Chan *c, int omode)
{
	switch(c->qid.path){
	case CHDIR:
	switch((ulong)c->qid.path){
	case Qdir:
		if(omode != OREAD)
			error(Eperm);
		break;


@@ 214,7 206,7 @@ penmousecreate(Chan*, char*, int, ulong)
static void
penmouseclose(Chan *c)
{
	if(c->qid.path!=CHDIR && (c->flag&COPEN)){
	if(c->qid.path != Qdir && (c->flag&COPEN)){
		lock(&mouse);
		if(c->qid.path == Qmouse)
			mouse.open = 0;


@@ 235,8 227,8 @@ penmouseread(Chan *c, void *va, long n, vlong)
	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
	Mousestate m;

	switch(c->qid.path){
	case CHDIR:
	switch((ulong)c->qid.path){
	case Qdir:
		return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);

	case Qmousectl:


@@ 334,8 326,8 @@ penmousewrite(Chan *c, void *va, long n, vlong)
	int nf, b;

	p = va;
	switch(c->qid.path){
	case CHDIR:
	switch((ulong)c->qid.path){
	case Qdir:
		error(Eisdir);

	case Qmousectl:


@@ 419,7 411,6 @@ Dev penmousedevtab = {
	penmousereset,
	penmouseinit,
	penmouseattach,
	penmouseclone,
	penmousewalk,
	penmousestat,
	penmouseopen,

M bitsy/devsac.c => bitsy/devsac.c +11 -4
@@ 26,9 26,9 @@ enum {

struct SacDir
{
	char	name[NAMELEN];
	char	uid[NAMELEN];
	char	gid[NAMELEN];
	char	name[KNAMELEN];
	char	uid[KNAMELEN];
	char	gid[KNAMELEN];
	uchar	qid[4];
	uchar	mode[4];
	uchar	atime[4];


@@ 127,6 127,7 @@ sacattach(char* spec)
{
	Chan *c;
	int dev;
	int opath;

	dev = atoi(spec);
	if(dev != 0)


@@ 137,7 138,13 @@ sacattach(char* spec)
		error("devsac: bad magic");

	c = devattach('C', spec);
	c->qid = (Qid){getl(root.qid), 0};
	path = getl(root.qid);
	if(path & CHDIR)
		c->qid.type = QTDIR;
	else
		c->qid.type = QTFILE;
	c->qid.path = path & ~CHDIR;
	c->qid.vers = 0;
	c->dev = dev;
	c->aux = saccpy(&root);
	return c;

D bitsy/devuart.c => bitsy/devuart.c +0 -603
@@ 1,603 0,0 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

#include	"../port/netif.h"

enum
{
	Nuart = 4,

	/* soft flow control chars */
	CTLS= 023,
	CTLQ= 021,
};

static	Uart*	uart[Nuart];
static	int	nuart;

static Dirtab *uartdir;
static int uartndir;

/*
 * means the kernel is using this as a console
 */
static char	Ekinuse[] = "device in use by kernel";

struct Uartalloc {
	Lock;
	Uart *elist;	/* list of enabled interfaces */
} uartalloc;

static void	uartdcdhup(Uart*, int);
static void	uartdcdts(Uart*, int);
static void	uartdsrhup(Uart*, int);
static void	uartenable(Uart*);
static void	uartdisable(Uart*);
static void	uartclock(void);
static void	uartflow(void*);

/*
 *  define a Uart
 */
Uart*
uartsetup(PhysUart *phys, void *regs, ulong freq, char *name)
{
	Uart *p;

	if(nuart >= Nuart)
		return nil;

	p = xalloc(sizeof(Uart));
	memset(p, 0, sizeof(*p));
	uart[nuart] = p;
	strcpy(p->name, name);
	p->dev = nuart++;
	p->freq = freq;
	p->regs = regs;
	p->phys = phys;

	/*
	 *  set rate to 115200 baud.
	 *  8 bits/character.
	 *  1 stop bit.
	 *  enabled with interrupts disabled.
	 */
	(*p->phys->bits)(p, 8);
	(*p->phys->stop)(p, 1);
	(*p->phys->baud)(p, 115200);
	(*p->phys->enable)(p, 0);

	p->iq = qopen(4*1024, 0, uartflow, p);
	p->oq = qopen(4*1024, 0, uartkick, p);
	if(p->iq == nil || p->oq == nil)
		panic("uartsetup");

	p->ir = p->istage;
	p->iw = p->istage;
	p->ie = &p->istage[Stagesize];
	p->op = p->ostage;
	p->oe = p->ostage;
	return p;
}

/*
 *  enable/diable uart and add/remove to list of enabled uarts
 */
static void
uartenable(Uart *p)
{
	Uart **l;

	p->hup_dsr = p->hup_dcd = 0;
	p->dsr = p->dcd = 0;

	/* assume we can send */
	p->cts = 1;

	(*p->phys->enable)(p, 1);

	lock(&uartalloc);
	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
		if(*l == p)
			break;
	}
	if(*l == 0){
		p->elist = uartalloc.elist;
		uartalloc.elist = p;
	}
	p->enabled = 1;
	unlock(&uartalloc);
}
static void
uartdisable(Uart *p)
{
	Uart **l;

	(*p->phys->disable)(p);

	lock(&uartalloc);
	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
		if(*l == p){
			*l = p->elist;
			break;
		}
	}
	p->enabled = 0;
	unlock(&uartalloc);
}

static void
setlength(int i)
{
	Uart *p;

	if(i > 0){
		p = uart[i];
		if(p && p->opens && p->iq)
			uartdir[3*i].length = qlen(p->iq);
	} else for(i = 0; i < nuart; i++){
		p = uart[i];
		if(p && p->opens && p->iq)
			uartdir[3*i].length = qlen(p->iq);
	}
}

/*
 *  setup the '#t' directory
 */
static void
uartreset(void)
{
	int i;
	Dirtab *dp;

	uartndir = 3*nuart;
	uartdir = xalloc(uartndir * sizeof(Dirtab));
	dp = uartdir;
	for(i = 0; i < nuart; i++){
		/* 3 directory entries per port */
		sprint(dp->name, "eia%d", i);
		dp->qid.path = NETQID(i, Ndataqid);
		dp->perm = 0660;
		dp++;
		sprint(dp->name, "eia%dctl", i);
		dp->qid.path = NETQID(i, Nctlqid);
		dp->perm = 0660;
		dp++;
		sprint(dp->name, "eia%dstat", i);
		dp->qid.path = NETQID(i, Nstatqid);
		dp->perm = 0444;
		dp++;
	}

	addclock0link(uartclock);
}


static Chan*
uartattach(char *spec)
{
	return devattach('t', spec);
}

static int
uartwalk(Chan *c, char *name)
{
	return devwalk(c, name, uartdir, uartndir, devgen);
}

static void
uartstat(Chan *c, char *dp)
{
	if(NETTYPE(c->qid.path) == Ndataqid)
		setlength(NETID(c->qid.path));
	devstat(c, dp, uartdir, uartndir, devgen);
}

static Chan*
uartopen(Chan *c, int omode)
{
	Uart *p;

	c = devopen(c, omode, uartdir, uartndir, devgen);

	switch(NETTYPE(c->qid.path)){
	case Nctlqid:
	case Ndataqid:
		p = uart[NETID(c->qid.path)];
		if(p->kinuse)
			error(Ekinuse);
		qlock(p);
		if(p->opens++ == 0){
			uartenable(p);
			qreopen(p->iq);
			qreopen(p->oq);
		}
		qunlock(p);
		break;
	}

	return c;
}

static void
uartclose(Chan *c)
{
	Uart *p;

	if(c->qid.path & CHDIR)
		return;
	if((c->flag & COPEN) == 0)
		return;
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
	case Nctlqid:
		p = uart[NETID(c->qid.path)];
		if(p->kinuse)
			error(Ekinuse);
		qlock(p);
		if(--(p->opens) == 0){
			uartdisable(p);
			qclose(p->iq);
			qclose(p->oq);
			p->ir = p->iw = p->istage;
			p->dcd = p->dsr = p->dohup = 0;
		}
		qunlock(p);
		break;
	}
}

static long
uartread(Chan *c, void *buf, long n, vlong off)
{
	Uart *p;
	ulong offset = off;

	if(c->qid.path & CHDIR){
		setlength(-1);
		return devdirread(c, buf, n, uartdir, uartndir, devgen);
	}

	p = uart[NETID(c->qid.path)];
	if(p->kinuse)
		error(Ekinuse);
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		return qread(p->iq, buf, n);
	case Nctlqid:
		return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
	case Nstatqid:
		return (*p->phys->status)(p, buf, n, offset);
	}

	return 0;
}

static void
uartctl(Uart *p, char *cmd)
{
	int i, n;
	char *f[32];
	int nf;

	/* let output drain for a while */
	for(i = 0; i < 16 && qlen(p->oq); i++)
		tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125);

	nf = getfields(cmd, f, nelem(f), 1, " \t\n");

	for(i = 0; i < nf; i++){

		if(strncmp(f[i], "break", 5) == 0){
			(*p->phys->dobreak)(p, 0);
			continue;
		}

		n = atoi(f[i]+1);
		switch(*f[i]){
		case 'B':
		case 'b':
			(*p->phys->baud)(p, n);
			break;
		case 'C':
		case 'c':
			uartdcdhup(p, n);
			break;
		case 'D':
		case 'd':
			(*p->phys->dtr)(p, n);
			break;
		case 'E':
		case 'e':
			uartdsrhup(p, n);
			break;
		case 'f':
		case 'F':
			qflush(p->oq);
			break;
		case 'H':
		case 'h':
			qhangup(p->iq, 0);
			qhangup(p->oq, 0);
			break;
		case 'i':
		case 'I':
			break;
		case 'L':
		case 'l':
			(*p->phys->bits)(p, n);
			break;
		case 'm':
		case 'M':
			(*p->phys->modemctl)(p, n);
			break;
		case 'n':
		case 'N':
			qnoblock(p->oq, n);
			break;
		case 'P':
		case 'p':
			(*p->phys->parity)(p, *(cmd+1));
			break;
		case 'K':
		case 'k':
			(*p->phys->dobreak)(p, n);
			break;
		case 'R':
		case 'r':
			(*p->phys->rts)(p, n);
			break;
		case 'Q':
		case 'q':
			qsetlimit(p->iq, n);
			qsetlimit(p->oq, n);
			break;
		case 'T':
		case 't':
			uartdcdts(p, n);
			break;
		case 'W':
		case 'w':
			/* obsolete */
			break;
		case 'X':
		case 'x':
			ilock(&p->tlock);
			p->xonoff = n;
			iunlock(&p->tlock);
			break;
		}
	}
}

static long
uartwrite(Chan *c, void *buf, long n, vlong)
{
	Uart *p;
	char cmd[32];

	if(c->qid.path & CHDIR)
		error(Eperm);

	p = uart[NETID(c->qid.path)];
	if(p->kinuse)
		error(Ekinuse);

	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		return qwrite(p->oq, buf, n);
	case Nctlqid:
		if(n >= sizeof(cmd))
			n = sizeof(cmd)-1;
		memmove(cmd, buf, n);
		cmd[n] = 0;
		uartctl(p, cmd);
		return n;
	}
}

static void
uartwstat(Chan *c, char *dp)
{
	Dir d;
	Dirtab *dt;

	if(!iseve())
		error(Eperm);
	if(CHDIR & c->qid.path)
		error(Eperm);
	if(NETTYPE(c->qid.path) == Nstatqid)
		error(Eperm);

	dt = &uartdir[3 * NETID(c->qid.path)];
	convM2D(dp, &d);
	d.mode &= 0666;
	dt[0].perm = dt[1].perm = d.mode;
}

Dev uartdevtab = {
	't',
	"uart",

	uartreset,
	devinit,
	uartattach,
	devclone,
	uartwalk,
	uartstat,
	uartopen,
	devcreate,
	uartclose,
	uartread,
	devbread,
	uartwrite,
	devbwrite,
	devremove,
	uartwstat,
};

/*
 * decide if we should hangup when dsr or dcd drops.
 */
static void
uartdsrhup(Uart *p, int n)
{
	p->hup_dsr = n;
}

static void
uartdcdhup(Uart *p, int n)
{
	p->hup_dcd = n;
}

/*
 *  save dcd timestamps for gps clock
 */
static void
uartdcdts(Uart *p, int n)
{
	p->dcdts = n;
}

/*
 *  restart input if it's off
 */
static void
uartflow(void *v)
{
	Uart *p;

	p = v;
	if(p->modem)
		(*p->phys->rts)(p, 1);
}

/*
 *  put some bytes into the local queue to avoid calling
 *  qconsume for every character
 */
int
uartstageoutput(Uart *p)
{
	int n;

	n = qconsume(p->oq, p->ostage, Stagesize);
	if(n <= 0)
		return 0;
	p->op = p->ostage;
	p->oe = p->ostage + n;
	return n;
}

/*
 *  restart output
 */
void
uartkick(void *v)
{
	Uart *p = v;

	ilock(&p->tlock);
	(*p->phys->kick)(p);
	iunlock(&p->tlock);
}

/*
 *  streceiveage a character at interrupt time
 */
void
uartrecv(Uart *p,  char ch)
{
	uchar *next;

	/* software flow control */
	if(p->xonoff){
		if(ch == CTLS){
			p->blocked = 1;
		}else if (ch == CTLQ){
			p->blocked = 0;
			p->ctsbackoff = 2; /* clock gets output going again */
		}
	}

	/* receive the character */
	if(p->putc)
		p->putc(p->iq, ch);
	else {
		next = p->iw + 1;
		if(next == p->ie)
			next = p->istage;
		if(next != p->ir){
			*p->iw = ch;
			p->iw = next;
		}
	}
}

/*
 *  we save up input characters till clock time to reduce
 *  per character interrupt overhead.
 */
static void
uartclock(void)
{
	Uart *p;
	uchar *iw;

	for(p = uartalloc.elist; p; p = p->elist){

		/* this amortizes cost of qproduce to many chars */
		if(p->iw != p->ir){
			iw = p->iw;
			if(iw < p->ir){
				if(qproduce(p->iq, p->ir, p->ie-p->ir) < 0)
					(*p->phys->rts)(p, 0);
				p->ir = p->istage;
			}
			if(qproduce(p->iq, p->ir, iw-p->ir) < 0)
				(*p->phys->rts)(p, 0);
			p->ir = iw;
		}

		/* hang up if requested */
		if(p->dohup){
			qhangup(p->iq, 0);
			qhangup(p->oq, 0);
			p->dohup = 0;
		}

		/* this adds hysteresis to hardware/software flow control */
		if(p->ctsbackoff){
			ilock(&p->tlock);
			if(p->ctsbackoff){
				if(--(p->ctsbackoff) == 0)
					(*p->phys->kick)(p);
			}
			iunlock(&p->tlock);
		}
	}
}

/*
 *  configure a uart port as a console or a mouse
 */
void
uartspecial(Uart *p, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int))
{
	uartenable(p);
	if(baud)
		(*p->phys->baud)(p, baud);
	p->putc = putc;
	if(in)
		*in = p->iq;
	if(out)
		*out = p->oq;
	p->opens++;
}

M bitsy/devuda1341.c => bitsy/devuda1341.c +1 -1
@@ 904,7 904,7 @@ audioattach(char *param)
	return devattach('A', param);
}

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

M bitsy/devµc.c => bitsy/devµc.c +19 -18
@@ 7,7 7,8 @@
#include	"../port/error.h"

enum{
	Qbacklight = 1,
	Qdir,
	Qbacklight,
	Qbattery,
	Qbuttons,
	Qcruft,


@@ 48,19 49,20 @@ enum {
};

Dirtab µcdir[]={
	".",			{ Qdir, 0, QTDIR },	0,	DMDIR|0755,
	"backlight",	{ Qbacklight, 0 },	0,	0664,
	"battery",	{ Qbattery, 0 },	0,	0664,
	"buttons",	{ Qbuttons, 0 },	0,	0664,
	"cruft",	{ Qcruft, 0 },		0,	0664,
	"kbdin",	{ Qkbdin, 0 },		0,	0664,
	"led",		{ Qled, 0 },		0,	0664,
	"version",	{ Qversion, 0 },	0,	0664,
	"battery",		{ Qbattery, 0 },		0,	0664,
	"buttons",		{ Qbuttons, 0 },		0,	0664,
	"cruft",		{ Qcruft, 0 },		0,	0664,
	"kbdin",		{ Qkbdin, 0 },		0,	0664,
	"led",		{ Qled, 0 },			0,	0664,
	"version",		{ Qversion, 0 },		0,	0664,
};

static struct µcontroller
{
	/* message being rcvd */
	int	state;
	int		state;
	uchar	buf[16+4];
	uchar	n;



@@ 261,16 263,16 @@ static Chan*
	return devattach('r', spec);
}

static int	 
µcwalk(Chan* c, char* name)
static Walkqid*
µcwalk(Chan *c, Chan *nc, char **name, int nname)
{
	return devwalk(c, name, µcdir, nelem(µcdir), devgen);
	return devwalk(c, nc, name, nname, µcdir, nelem(µcdir), devgen);
}

static void	 
µcstat(Chan* c, char* dp)
static int	 
µcstat(Chan *c, uchar *dp, int n)
{
	devstat(c, dp, µcdir, nelem(µcdir), devgen);
	return devstat(c, dp, n, µcdir, nelem(µcdir), devgen);
}

static Chan*


@@ 314,10 316,10 @@ static long
{
	char buf[64];

	if(c->qid.path & CHDIR)
	if(c->qid.path == Qdir)
		return devdirread(c, a, n, µcdir, nelem(µcdir), devgen);

	switch(c->qid.path){
	switch((ulong)c->qid.path){
	case Qbattery:
		sendmsgwithack(BLbattery, nil, 0);		/* send a battery request */
		sprint(buf, "voltage: %d\nac: %s\nstatus: %s\n", ctlr.voltage,


@@ 361,7 363,7 @@ static long
	for(i = 0; i < cmd->nf; i++)
		data[i] = atoi(cmd->f[i]);

	switch(c->qid.path){
	switch((ulong)c->qid.path){
	case Qled:
		sendmsgwithack(BLled, data, cmd->nf);
		break;


@@ 384,7 386,6 @@ Dev µcdevtab = {
	devreset,
	µcinit,
	µcattach,
	devclone,
	µcwalk,
	µcstat,
	µcopen,

M bitsy/fns.h => bitsy/fns.h +0 -2
@@ 74,12 74,10 @@ void	putttb(ulong);
void	putpid(ulong);
void	qpanic(char *, ...);
void	rs232power(int);
Uart*	uartsetup(PhysUart*, void*, ulong, char*);
void	uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int));
void	sa1100_uartsetup(int);
void	screeninit(void);
int	screenprint(char*, ...);			/* debugging */
void	screenputs(char*, int);
void	serialµcputs(uchar *str, int n);
void	setr13(int, ulong*);
uchar*	tarlookup(uchar*, char*, int*);

M bitsy/main.c => bitsy/main.c +4 -3
@@ 89,7 89,7 @@ init0(void)
	up->slash = namec("#/", Atodir, 0, 0);
	cnameclose(up->slash->name);
	up->slash->name = newcname("/");
	up->dot = cclone(up->slash, 0);
	up->dot = cclone(up->slash);

	chandevinit();



@@ 188,8 188,9 @@ userinit(void)
	p->rgrp = newrgrp();
	p->procmode = 0640;

	strcpy(p->text, "*init*");
	strcpy(p->user, eve);
	kstrdup(&eve, "");
	kstrdup(&p->text, "*init*");
	kstrdup(&p->user, eve);

	/*
	 * Kernel Stack

M bitsy/screen.c => bitsy/screen.c +4 -2
@@ 152,6 152,7 @@ int			drawdebug;
static	ulong	rep(ulong, int);
static	void	screenwin(void);
static	void	screenputc(char *buf);
static	void	bitsyscreenputs(char *s, int n);
static	void	scroll(void);

static void


@@ 248,6 249,7 @@ screeninit(void)
	blanktime = 3;	/* minutes */

	screenwin();
	screenputs = bitsyscreenputs;
}

void


@@ 312,8 314,8 @@ blankscreen(int blank)
	}
}

void
screenputs(char *s, int n)
static void
bitsyscreenputs(char *s, int n)
{
	int i;
	Rune r;

M bitsy/trap.c => bitsy/trap.c +13 -13
@@ 22,7 22,7 @@ struct Intrregs *intrregs;

typedef struct Vctl {
	Vctl*	next;			/* handlers on this vector */
	char	name[NAMELEN];		/* of driver */
	char	*name;		/* of driver, xallocated */
	void	(*f)(Ureg*, void*);	/* handler to call */
	void*	a;			/* argument to call it with */
} Vctl;


@@ 133,8 133,8 @@ irqenable(int irq, IntrHandler *f, void* a, char *name)
	v = xalloc(sizeof(Vctl));
	v->f = f;
	v->a = a;
	strncpy(v->name, name, NAMELEN-1);
	v->name[NAMELEN-1] = 0;
	v->name = xalloc(strlen(name)+1);
	strcpy(v->name, name);

	lock(&vctllock);
	v->next = vctl[irq];


@@ 172,8 172,8 @@ intrenable(int type, int which, IntrHandler *f, void* a, char *name)
	v = xalloc(sizeof(Vctl));
	v->f = f;
	v->a = a;
	strncpy(v->name, name, NAMELEN-1);
	v->name[NAMELEN-1] = 0;
	v->name = xalloc(strlen(name)+1);
	strcpy(v->name, name);

	lock(&vctllock);
	v->next = gpiovctl[which];


@@ 206,7 206,7 @@ static void
faultarm(Ureg *ureg, ulong va, int user, int read)
{
	int n, insyscall;
	char buf[ERRLEN];
	char buf[ERRMAX];

	insyscall = up->insyscall;
	up->insyscall = 1;


@@ 250,7 250,7 @@ trap(Ureg *ureg)
	ulong inst;
	int user, x, rv;
	ulong va, fsr;
	char buf[ERRLEN];
	char buf[ERRMAX];
	int rem;

	if(up != nil)


@@ 531,7 531,7 @@ noted(Ureg* ureg, ulong arg0)
			pexit("Suicide", 0);
		}
		qunlock(&up->debug);
		sp = oureg-4*BY2WD-ERRLEN;
		sp = oureg-4*BY2WD-ERRMAX;
		splhi();
		ureg->sp = sp;
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */


@@ 575,8 575,8 @@ notify(Ureg* ureg)
	n = &up->note[0];
	if(strncmp(n->msg, "sys:", 4) == 0){
		l = strlen(n->msg);
		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */
			l = ERRLEN-15;
		if(l > ERRMAX-15)	/* " pc=0x12345678\0" */
			l = ERRMAX-15;
		sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
	}



@@ 601,7 601,7 @@ notify(Ureg* ureg)
	sp -= sizeof(Ureg);

	if(!okaddr((ulong)up->notify, 1, 0)
	|| !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){
	|| !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
		pprint("suicide: bad address in notify\n");
		qunlock(&up->debug);
		pexit("Suicide", 0);


@@ 611,8 611,8 @@ notify(Ureg* ureg)
	memmove((Ureg*)sp, ureg, sizeof(Ureg));
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */
	up->ureg = (void*)sp;
	sp -= BY2WD+ERRLEN;
	memmove((char*)sp, up->note[0].msg, ERRLEN);
	sp -= BY2WD+ERRMAX;
	memmove((char*)sp, up->note[0].msg, ERRMAX);
	sp -= 3*BY2WD;
	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */
	*(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;	/* arg 1 is ureg* */

R bitsy/sa1110uart.c => bitsy/uartsa1110.c +174 -126
@@ 8,7 8,7 @@

#include	"../port/netif.h"

/* this isn't strictly a sa1100 driver.  The rts/cts stuff is h3650 specific */
/* this isn't strictly a sa1110 driver.  The rts/cts stuff is h3650 specific */

enum
{


@@ 51,38 51,33 @@ enum
	Overrun=	1<<5,
};

Uartregs *uart3regs = UART3REGS;
Uartregs *uart1regs = UART1REGS ;

static void	sa1100_uartbaud(Uart *p, int rate);
static void	sa1100_uartkick(Uart *p);
static void	sa1100_uartrts(Uart *p, int on);
static void	sa1100_uartintr(Ureg*, void*);
static void	sa1100_uartbreak(Uart*, int);
static void	sa1100_uartbits(Uart*, int);
static void	sa1100_uartparity(Uart*, int);
static void	sa1100_uartmodemctl(Uart*, int);
static void	sa1100_uartstop(Uart*, int);
static void	sa1100_uartdtr(Uart*, int);
static long	sa1100_uartstatus(Uart*, void*, long, long);
static void	sa1100_uartenable(Uart*, int);
static void	sa1100_uartdisable(Uart*);

PhysUart sa1100_uart = {
	.enable=	sa1100_uartenable,
	.disable=	sa1100_uartdisable,
	.bits=		sa1100_uartbits,
	.kick=		sa1100_uartkick,
	.intr=		sa1100_uartintr,
	.modemctl=	sa1100_uartmodemctl,
	.baud=		sa1100_uartbaud,
	.stop=		sa1100_uartstop,
	.parity=	sa1100_uartparity,
	.dobreak=	sa1100_uartbreak,
	.rts=		sa1100_uartrts,
	.dtr=		sa1100_uartdtr,
	.status=	sa1100_uartstatus,
extern PhysUart sa1110physuart;

static Uart sa1110uart[2] = {
{	.regs	= UART3REGS,
	.name	= "serialport3",
	.freq	= ClockFreq,
	.bits	= 8,
	.stop	= 1,
	.parity	= 'n',
	.baud	= 115200,
	.phys	= &sa1110physuart,
	.special=0,
	.next	= &sa1110uart[1], },

{	.regs	= UART1REGS,
	.name	= "serialport1",
	.freq	= ClockFreq,
	.bits	= 8,
	.stop	= 1,
	.parity	= 'n',
	.baud	= 115200,
	.phys	= &sa1110physuart,
	.special=0,
	.next	= nil, },
};
static Uart* consuart;
static Uart* µcuart;

#define R(p) ((Uartregs*)(p->regs))



@@ 90,7 85,7 @@ PhysUart sa1100_uart = {
 *  enable a port's interrupts.  set DTR and RTS
 */
static void
sa1100_uartenable(Uart *p, int intena)
sa1110_uartenable(Uart *p, int intena)
{
	ulong s;



@@ 105,13 100,13 @@ sa1100_uartenable(Uart *p, int intena)
 *  disable interrupts. clear DTR, and RTS
 */
static void
sa1100_uartdisable(Uart *p)
sa1110_uartdisable(Uart *p)
{
	R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena);
}

static long
sa1100_uartstatus(Uart *p, void *buf, long n, long offset)
sa1110_uartstatus(Uart *p, void *buf, long n, long offset)
{
	char str[256];
	ulong ctl0;


@@ 134,8 129,8 @@ sa1100_uartstatus(Uart *p, void *buf, long n, long offset)

		p->dev,
		p->type,
		p->frame,
		p->overrun, 
		p->ferr,
		p->oerr, 
		"",
		"",
		"",


@@ 146,14 141,14 @@ sa1100_uartstatus(Uart *p, void *buf, long n, long offset)
/*
 *  set the buad rate
 */
static void
sa1100_uartbaud(Uart *p, int rate)
static int
sa1110_uartbaud(Uart *p, int rate)
{
	ulong brconst;
	ulong ctl3;

	if(rate <= 0)
		return;
		return -1;

	/* disable */
	ctl3 = R(p)->ctl[3];


@@ 165,14 160,16 @@ sa1100_uartbaud(Uart *p, int rate)

	/* reenable */
	R(p)->ctl[3] = ctl3;

	p->baud = rate;
	return 0;
}

/*
 *  send a break
 */
static void
sa1100_uartbreak(Uart *p, int ms)
sa1110_uartbreak(Uart *p, int ms)
{
	if(ms == 0)
		ms = 200;


@@ 185,62 182,74 @@ sa1100_uartbreak(Uart *p, int ms)
/*
 *  set bits/char
 */
static void
sa1100_uartbits(Uart *p, int n)
static int
sa1110_uartbits(Uart *p, int n)
{
	ulong ctl3;

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;
	ulong ctl0, ctl3;

	ctl0 = R(p)->ctl[0];
	switch(n){
	case 7:
		R(p)->ctl[0] &= ~Bits8;
		ctl0 &= ~Bits8;
		break;
	case 8:
		R(p)->ctl[0] |= Bits8;
		ctl0 |= Bits8;
		break;
	default:
		error(Ebadarg);
		return -1;
	}

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	R(p)->ctl[0] = ctl0;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	p->bits = n;
	return 0;
}

/*
 *  set stop bits
 */
static void
sa1100_uartstop(Uart *p, int n)
static int
sa1110_uartstop(Uart *p, int n)
{
	ulong ctl3;

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;
	ulong ctl0, ctl3;

	ctl0 = R(p)->ctl[0];
	switch(n){
	case 1:
		R(p)->ctl[0] &= ~Stop2;
		ctl0 &= ~Stop2;
		break;
	case 2:
		R(p)->ctl[0] |= Stop2;
		ctl0 |= Stop2;
		break;
	default:
		error(Ebadarg);
		return -1;
	}

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	R(p)->ctl[0] = ctl0;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	p->stop = n;
	return 0;
}

/*
 *  turn on/off rts
 */
static void
sa1100_uartrts(Uart*, int)
sa1110_uartrts(Uart*, int)
{
}



@@ 248,7 257,7 @@ sa1100_uartrts(Uart*, int)
 *  turn on/off dtr
 */
static void
sa1100_uartdtr(Uart*, int)
sa1110_uartdtr(Uart*, int)
{
}



@@ 256,7 265,7 @@ sa1100_uartdtr(Uart*, int)
 *  turn on/off modem flow control on/off (rts/cts)
 */
static void
sa1100_uartmodemctl(Uart *p, int on)
sa1110_uartmodemctl(Uart *p, int on)
{
	if(on) {
	} else {


@@ 267,36 276,41 @@ sa1100_uartmodemctl(Uart *p, int on)
/*
 *  set parity
 */
static void
sa1100_uartparity(Uart *p, int type)
static int
sa1110_uartparity(Uart *p, int type)
{
	ulong ctl3;

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;
	ulong ctl0, ctl3;

	ctl0 = R(p)->ctl[0];
	switch(type){
	case 'e':
		R(p)->ctl[0] |= Parity|Even;
		ctl0 |= Parity|Even;
		break;
	case 'o':
		R(p)->ctl[0] |= Parity;
		ctl0 |= Parity;
		break;
	default:
		R(p)->ctl[0] &= ~(Parity|Even);
		ctl0 &= ~(Parity|Even);
		break;
	}

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	R(p)->ctl[0] = ctl0;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	return 0;
}

/*
 *  restart output if not blocked and OK to send
 */
static void
sa1100_uartkick(Uart *p)
sa1110_uartkick(Uart *p)
{
	int i;



@@ 317,48 331,10 @@ sa1100_uartkick(Uart *p)
}

/*
 *  for iprint, just write it
 */
void
serialputs(char *str, int n)
{
	Uartregs *ur;

	ur = uart3regs;
	while(n-- > 0){
		/* wait for output ready */
		while((ur->status[1] & Tnotfull) == 0)
			;
		ur->data = *str++;
	}
	while((ur->status[1] & Tbusy))
		;
}

/*
 *  for iprint, just write it
 */
void
serialµcputs(uchar *str, int n)
{
	Uartregs *ur;

	ur = uart1regs;
	while(n-- > 0){
		/* wait for output ready */
		while((ur->status[1] & Tnotfull) == 0)
			;
		ur->data = *str++;
	}
	while((ur->status[1] & Tbusy))
		;
}

/*
 *  take an interrupt
 */
static void
sa1100_uartintr(Ureg*, void *x)
sa1110_uartintr(Ureg*, void *x)
{
	Uart *p;
	ulong s;


@@ 384,9 360,9 @@ sa1100_uartintr(Ureg*, void *x)
		if(s & ParityError)
			p->parity++;
		if(s & FrameError)
			p->frame++;
			p->ferr++;
		if(s & Overrun)
			p->overrun++;
			p->oerr++;
	}

	/* receiver interrupt, snarf bytes */


@@ 394,6 370,71 @@ sa1100_uartintr(Ureg*, void *x)
		uartrecv(p, regs->data);
}

static Uart*
sa1110_pnp(void)
{
	return sa1110uart;
}

PhysUart sa1110physuart = {
	.name=		"sa1110",
	.pnp= 		sa1110_pnp,
	.enable=	sa1110_uartenable,
	.disable=	sa1110_uartdisable,
	.bits=		sa1110_uartbits,
	.kick=		sa1110_uartkick,
	.modemctl=	sa1110_uartmodemctl,
	.baud=		sa1110_uartbaud,
	.stop=		sa1110_uartstop,
	.parity=	sa1110_uartparity,
	.dobreak=	sa1110_uartbreak,
	.rts=		sa1110_uartrts,
	.dtr=		sa1110_uartdtr,
	.status=	sa1110_uartstatus,
};

/*
 *  for iprint, just write it
 */
static void
sa1110puts(char *str, int n)
{
	Uartregs *ur;

	if(consuart == nil)
		return;
	ur = consuart->regs;
	while(n-- > 0){
		/* wait for output ready */
		while((ur->status[1] & Tnotfull) == 0)
			;
		ur->data = *str++;
	}
	while((ur->status[1] & Tbusy))
		;
}

/*
 *  for iprint, just write it
 */
void
serialµcputs(uchar *str, int n)
{
	Uartregs *ur;

	if(µcuart == nil)
		return;
	ur = µcuart->regs;
	while(n-- > 0){
		/* wait for output ready */
		while((ur->status[1] & Tnotfull) == 0)
			;
		ur->data = *str++;
	}
	while((ur->status[1] & Tbusy))
		;
}

typedef struct Gpclkregs Gpclkregs;
struct Gpclkregs
{


@@ 417,25 458,32 @@ Gpclkregs *gpclkregs;
 *  a serial port)
 */
void
sa1100_uartsetup(int console)
sa1110_uartsetup(int console)
{
	Uart *p;

	/* external serial port (eia0) */
	uart3regs = mapspecial(UART3REGS, 64);
	p = uartsetup(&sa1100_uart, uart3regs, ClockFreq, "serialport3");
	intrenable(IRQ, IRQuart3, sa1100_uartintr, p, p->name);
	p = &sa1110uart[0];
	p->regs = mapspecial(UART3REGS, 64);

	/* set eia0 up as a console */
	if(console)
		uartspecial(p, 115200, &kbdq, &printq, kbdcr2nl);
	if(console){
		uartctl(p, "b115200 l8 pn s1");
		consuart = p;
		(*p->phys->enable)(p, 0);
		serialputs = sa1110puts;
		p->console = 1;
	}
	intrenable(IRQ, IRQuart3, sa1110_uartintr, p, p->name);

	/* port for talking to microcontroller (eia1) */
	gpclkregs = mapspecial(GPCLKREGS, 64);
	gpclkregs->r0 = Gpclk_sus;	/* set uart mode */
	uart1regs = mapspecial(UART1REGS, 64);

	p = uartsetup(&sa1100_uart, uart1regs, ClockFreq, "serialport1");
	uartspecial(p, 115200, 0, 0, µcputc);
	intrenable(IRQ, IRQuart1b, sa1100_uartintr, p, p->name);
	p = &sa1110uart[1];
	p->regs = mapspecial(UART1REGS, 64);
	uartctl(p, "b115200 l8 pn s1");
	µcuart = p;
	(*p->phys->enable)(p, 0);
	intrenable(IRQ, IRQuart1b, sa1110_uartintr, p, p->name);
}

M pc/devi82365.c => pc/devi82365.c +1 -1
@@ 420,7 420,7 @@ enum
};

#define SLOTNO(c)	((ulong)((c->qid.path>>8)&0xff))
#define TYPE(c)		((ulong)(c->qid.path&0xff))
#define TYPE(c)	((ulong)(c->qid.path&0xff))
#define QID(s,t)	(((s)<<8)|(t))

static int

M port/auth.c => port/auth.c +6 -6
@@ 54,12 54,12 @@ sysfversion(ulong *arg)
	if(vers[0] == '\0')
		vers = VERSION9P;
	f.version = vers;
	msg = smalloc(MAXMSG);
	msg = smalloc(8192+IOHDRSZ);
	if(waserror()){
		free(msg);
		nexterror();
	}
	n = convS2M(&f, msg, MAXMSG);
	n = convS2M(&f, msg, 8192+IOHDRSZ);
	if(n == 0)
		error("bad fversion conversion on send");



@@ 78,7 78,7 @@ sysfversion(ulong *arg)
	}

	/* message sent; receive and decode reply */
	m = devtab[c->type]->read(c, msg, MAXMSG, c->offset);
	m = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
	if(m <= 0)
		error("EOF receiving fversion reply");



@@ 141,12 141,12 @@ sysfsession(ulong *arg)
	f.tag = NOTAG;
	f.nchal = 0;
	f.chal = (uchar*)"";
	msg = smalloc(MAXMSG);
	msg = smalloc(8192+IOHDRSZ);
	if(waserror()){
		free(msg);
		nexterror();
	}
	n = convS2M(&f, msg, MAXMSG);
	n = convS2M(&f, msg, 8192+IOHDRSZ);
	if(n == 0)
		error("bad fsession conversion on send");



@@ 165,7 165,7 @@ sysfsession(ulong *arg)
	}

	/* message sent; receive and decode reply */
	m = devtab[c->type]->read(c, msg, MAXMSG, c->offset);
	m = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
	if(m <= 0)
		error("EOF receiving fsession reply");


M port/devkprof.c => port/devkprof.c +1 -1
@@ 24,7 24,7 @@ enum{
	Kprofctlqid,
};
Dirtab kproftab[]={
	".",	{Kprofdirqid, 0, QTDIR},		0,	DMDIR|0600,
	".",	{Kprofdirqid, 0, QTDIR},		0,	DMDIR|0550,
	"kpdata",	{Kprofdataqid},		0,	0600,
	"kpctl",	{Kprofctlqid},		0,	0600,
};

M port/portdat.h => port/portdat.h +3 -0
@@ 9,6 9,7 @@ typedef struct Dirtab	Dirtab;
typedef struct Egrp	Egrp;
typedef struct Evalue	Evalue;
typedef struct Fgrp	Fgrp;
typedef struct DevConf	DevConf;
typedef struct Image	Image;
typedef struct List	List;
typedef struct Log	Log;


@@ 197,6 198,8 @@ struct Dev
	long	(*bwrite)(Chan*, Block*, ulong);
	void	(*remove)(Chan*);
	int	(*wstat)(Chan*, uchar*, int);
	void	(*power)(int);	/* power mgt: power(1) → on, power (0) → off */
	int	(*config)(int, char*, DevConf*);
};

struct Dirtab

M port/proc.c => port/proc.c +2 -4
@@ 544,10 544,9 @@ tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms)
Proc*
wakeup(Rendez *r)
{
	Proc *p, *rv;
	Proc *p;
	int s;

	rv = 0;
	s = splhi();

	lock(r);


@@ 560,7 559,6 @@ wakeup(Rendez *r)
		r->p = nil;
		p->r = nil;
		ready(p);
		rv = p;
		unlock(&p->rlock);
	}



@@ 568,7 566,7 @@ wakeup(Rendez *r)

	splx(s);

	return rv;
	return p;
}

/*