~kris/9p

9hist

f1c292848e331e5616ed0b966692ffb23c6580fd — David du Colombier 25 years ago 617f6d9
Plan 9 from Bell Labs 2001-06-19
M bitsy/dat.h => bitsy/dat.h +0 -14
@@ 227,17 227,6 @@ struct PCMconftab
};

/*
 *  For walking a PCMCIA card's information structure
 */
struct Cisdat
{
	uchar	*cisbase;
	int	cispos;
	int	cisskip;
	int	cislen;
};

/*
 *  PCMCIA card slot
 */
struct PCMslot


@@ 265,9 254,6 @@ struct PCMslot
	PCMconftab	ctab[8];
	PCMconftab	*def;		/* default conftab */

	/* for walking through cis */
	Cisdat;

	/* maps are fixed */
	PCMmap memmap;
	PCMmap attrmap;

M bitsy/devpcmcia.c => bitsy/devpcmcia.c +11 -8
@@ 44,7 44,7 @@ static void slotinfo(Ureg*, void*);
#define PATH(s,t)	(((s)<<8)|(t))

static PCMslot*
slotno(Chan *c)
slotof(Chan *c)
{
	ulong x;



@@ 89,6 89,7 @@ pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp)
		break;
	}
	qid.vers = 0;
	qid.type = QTFILE;
	devdir(c, qid, up->genbuf, len, eve, 0660, dp);
	return 1;
}


@@ 148,12 149,15 @@ pcmciastat(Chan *c, uchar *db, int n)
static Chan*
pcmciaopen(Chan *c, int omode)
{
	print("pcmciaopen\n");
	PCMslot *slotp;

	if(c->qid.type & QTDIR){
		if(omode != OREAD)
			error(Eperm);
	} else
		increfp(slotno(c));
	} else {
		slotp = slotof(c);
		increfp(slotp);
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;


@@ 165,7 169,7 @@ pcmciaclose(Chan *c)
{
	if(c->flag & COPEN)
		if((c->qid.type & QTDIR) == 0)
			decrefp(slotno(c));
			decrefp(slotof(c));
}

/* a memmove using only bytes */


@@ 244,7 248,7 @@ pcmciaread(Chan *c, void *a, long n, vlong off)
	PCMslot *sp;
	ulong offset = off;

	sp = slotno(c);
	sp = slotof(c);

	switch(TYPE(c)){
	case Qdir:


@@ 356,7 360,7 @@ pcmciawrite(Chan *c, void *a, long n, vlong off)
	PCMslot *sp;
	ulong offset = off;

	sp = slotno(c);
	sp = slotof(c);

	switch(TYPE(c)){
	case Qmem:


@@ 430,7 434,6 @@ slotinfo(Ureg*, void*)
static void
increfp(PCMslot *sp)
{
	print("increfp\n");
	wlock(sp);
	if(waserror()){
		wunlock(sp);

M bitsy/fns.h => bitsy/fns.h +1 -0
@@ 91,6 91,7 @@ void	trapdump(char *tag);
void	trapinit(void);
void	trapresume(void);
int	tas(void*);
void	uartpower(int);
int	uartstageoutput(Uart*);
void	uartkick(void*);
void	uartrecv(Uart*, char);

M bitsy/l.s => bitsy/l.s +0 -2
@@ 624,8 624,6 @@ TEXT sa1100_power_resume(SB), $-4
loop:
	B	loop



/* The first MCR instruction of this function needs to be on a cache-line
 * boundary; to make this happen, it will be copied (in trap.c).
 *

M bitsy/main.c => bitsy/main.c +0 -1
@@ 364,7 364,6 @@ PPCregs *ppcregs;
MemConfRegs *memconfregs;
PowerRegs *powerregs;
ResetRegs *resetregs;
OSTimerRegs *timerregs = (OSTimerRegs*)OSTIMERREGS;

/*
 *  configure the machine

M bitsy/power.c => bitsy/power.c +14 -25
@@ 15,15 15,14 @@
 */
ulong power_resume[200/4];

extern void sa1100_power_resume(void);
extern int setpowerlabel(void);

extern void	sa1100_power_resume(void);
extern int		setpowerlabel(void);
extern Uart	sa1110uart[];

GPIOregs savedgpioregs;
Uartregs saveduart3regs;
Uartregs saveduart1regs;
Intrregs savedintrregs;

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

static void
dumpitall(void)


@@ 36,8 35,8 @@ dumpitall(void)
		gpioregs->direction, gpioregs->rising, gpioregs->falling,
		gpioregs->edgestatus, gpioregs->altfunc);
	iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n", 
		uart1regs->ctl[0], uart1regs->status[0], uart1regs->status[1], 
		uart3regs->ctl[0], uart3regs->status[0], uart3regs->status[1]); 
		R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1], 
		R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]); 
	iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n",
		timerregs->osmr[0], timerregs->osmr[1],
		timerregs->osmr[2], timerregs->osmr[3],


@@ 61,16 60,6 @@ intrcpy(Intrregs *to, Intrregs *from)
	to->icmr = from->icmr;	// interrupts enabled
}

static  void
uartcpy(Uartregs *to, Uartregs *from)
{
	to->ctl[0] = from->ctl[0];
//	to->ctl[1] = from->ctl[1];
//	to->ctl[2] = from->ctl[2];
	to->ctl[3] = from->ctl[3];

}

static void
gpiocpy(GPIOregs *to, GPIOregs *from)
{


@@ 83,8 72,10 @@ gpiocpy(GPIOregs *to, GPIOregs *from)
static void
sa1100_power_off(void)
{
	iprint("11..");
	/* enable wakeup by µcontroller, on/off switch or real-time clock alarm */
	powerregs->pwer =  1 << IRQrtc | 1 << IRQgpio0 | 1 << IRQgpio1;
	iprint("12..");

	/* clear previous reset status */
	resetregs->rcsr =  RCSR_all;


@@ 126,8 117,6 @@ onoffintr(Ureg* , void*)
		cacheflush();
		trapresume();
		rs232power(1);
		irpower(1);
		audiopower(1);
		clockpower(1);
		gpclkregs->r0 = 1<<0;
		gpiocpy(gpioregs, &savedgpioregs);


@@ 137,12 126,11 @@ onoffintr(Ureg* , void*)
			gpioregs->edgestatus = (1<<IRQgpio0);
			intrregs->icip = (1<<IRQgpio0);
		}
		uartcpy(uart3regs,&saveduart3regs);
		uart3regs->status[0] = uart3regs->status[0];
		uartcpy(uart1regs,&saveduart1regs);
		uart1regs->status[0] = uart1regs->status[0];
		uartpower(1);
		µcpower(1);
		screenpower(1);
		irpower(1);
		audiopower(1);
		iprint("\nresuming execution\n");
//		dumpitall();
		delay(800);


@@ 153,15 141,16 @@ onoffintr(Ureg* , void*)
	iprint("\nentering suspend mode\n");
	gpiocpy(&savedgpioregs, gpioregs);
	intrcpy(&savedintrregs, intrregs);
	uartcpy(&saveduart3regs, uart3regs);
	uartcpy(&saveduart1regs, uart1regs);
	delay(400);
	clockpower(0);
	irpower(0);
	audiopower(0);
	screenpower(0);
	µcpower(0);
	uartpower(0);
	iprint("rs\n");
	rs232power(0);
	iprint("10..");
	sa1100_power_off();
	/* no return */
}

M bitsy/uartsa1110.c => bitsy/uartsa1110.c +32 -3
@@ 10,6 10,8 @@

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

static void sa1110_uartpower(Uart *, int);

enum
{
	/* ctl[0] bits */


@@ 53,7 55,8 @@ enum

extern PhysUart sa1110physuart;

static Uart sa1110uart[2] = {
//static
Uart sa1110uart[2] = {
{	.regs		= UART3REGS,
	.name	= "serialport3",
	.freq		= ClockFreq,


@@ 80,7 83,8 @@ static Uart sa1110uart[2] = {
static Uart* consuart;
static Uart* µcuart;

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

/*
 *  enable a port's interrupts.  set DTR and RTS


@@ 392,6 396,7 @@ PhysUart sa1110physuart = {
	.rts=			sa1110_uartrts,
	.dtr=			sa1110_uartdtr,
	.status=		sa1110_uartstatus,
	.power=		sa1110_uartpower,
};

/*


@@ 456,7 461,7 @@ sa1110_uartsetup(int console)
	/* external serial port (eia0) */
	p = &sa1110uart[0];
	p->regs = mapspecial(UART3REGS, 64);

	p->saveregs = xalloc(sizeof(Uartregs));
	/* set eia0 up as a console */
	if(console){
		uartctl(p, "b115200 l8 pn s1");


@@ 473,9 478,33 @@ sa1110_uartsetup(int console)

	p = &sa1110uart[1];
	p->regs = mapspecial(UART1REGS, 64);
	p->saveregs = xalloc(sizeof(Uartregs));
	uartctl(p, "b115200 l8 pn s1");
	µcuart = p;
	p->special = 1;
	(*p->phys->enable)(p, 0);
	intrenable(IRQ, IRQuart1b, sa1110_uartintr, p, p->name);
}

static  void
uartcpy(Uartregs *to, Uartregs *from)
{
	to->ctl[0] = from->ctl[0];
//	to->ctl[1] = from->ctl[1];
//	to->ctl[2] = from->ctl[2];
	to->ctl[3] = from->ctl[3];

}

static void
sa1110_uartpower(Uart *p, int powerup)
{
	if (powerup) {
		/* power up, restore the registers */
		uartcpy(R(p), SR(p));
		R(p)->status[0] = R(p)->status[0];
	} else {
		/* power down, save the registers */
		uartcpy(SR(p), R(p));
	}
}

M pc/devi82365.c => pc/devi82365.c +4 -1
@@ 975,7 975,10 @@ pcmio(int slotno, ISAConf *isa)
		x |= x<<4;
	wrreg(pp, Rio, x);

	/* enable io port map 0 */
	/*
	 * enable io port map 0
	 * the 'top' register value includes the last valid address
	 */
	if(isa->port == 0)
		isa->port = ct->io[0].start;
	we = rdreg(pp, Rwe);

M pc/io.h => pc/io.h +0 -13
@@ 241,7 241,6 @@ struct SMBus {

typedef struct PCMslot		PCMslot;
typedef struct PCMconftab	PCMconftab;
typedef struct Cisdat 		Cisdat;

/*
 * Map between ISA memory space and PCMCIA card memory space.


@@ 275,15 274,6 @@ struct PCMconftab
	ulong	otherwait;
};

/* cis memory walking */
struct Cisdat
{
	uchar	*cisbase;
	int	cispos;
	int	cisskip;
	int	cislen;
};

/* a card slot */
struct PCMslot
{


@@ 315,9 305,6 @@ struct PCMslot
	PCMconftab	ctab[8];
	PCMconftab	*def;		/* default conftab */

	/* for walking through cis */
	Cisdat;

	/* memory maps */
	Lock	mlock;		/* lock down the maps */
	int	time;

M pc/sdscsi.c => pc/sdscsi.c +2 -0
@@ 211,6 211,8 @@ scsionline(SDunit* unit)
			break;
		case 0:
			unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
			if(unit->sectors == 0)
				continue;
			/*
			 * Read-capacity returns the LBA of the last sector,
			 * therefore the number of sectors must be incremented.

M port/cis.c => port/cis.c +59 -25
@@ 6,31 6,29 @@
#include "../port/error.h"
#include "io.h"


/*
 *  read and crack the card information structure enough to set
 *  important parameters like power
 */
/* cis memory walking */
typedef struct Cisdat {
	uchar	*cisbase;
	int	cispos;
	int	cisskip;
	int	cislen;
} Cisdat;

static void	tcfig(PCMslot*, Cisdat*, int);
static void	tentry(PCMslot*, Cisdat*, int);
static void	tvers1(PCMslot*, Cisdat*, int);

struct {
	int n;
	void (*parse)(PCMslot*, Cisdat*, int);
} cistab[] = {
	0x15, tvers1,
	0x1A, tcfig,
	0x1B, tentry,
};

static int
readc(Cisdat *pp, uchar *x)
readc(Cisdat *cis, uchar *x)
{
	if(pp->cispos >= pp->cislen)
	if(cis->cispos >= cis->cislen)
		return 0;
	*x = pp->cisbase[pp->cisskip*pp->cispos];
	pp->cispos++;
	*x = cis->cisbase[cis->cisskip*cis->cispos];
	cis->cispos++;
	return 1;
}



@@ 102,9 100,10 @@ pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
void
pcmcisread(PCMslot *pp)
{
	uchar v[256];
	int i, nv;
	int this;
	Cisdat cis;
	PCMmap *m;
	uchar type, link;

	memset(pp->ctab, 0, sizeof(pp->ctab));
	pp->caddr = 0;


@@ 113,16 112,47 @@ pcmcisread(PCMslot *pp)
	pp->nctab = 0;
	pp->verstr[0] = 0;

	for(i = 0; i < nelem(cistab); i++) {
		if((nv = pcmcistuple(pp->slotno, cistab[i].n, -1, v, sizeof(v))) >= 0) {
			cis.cisbase = v;
			cis.cispos = 0;
			cis.cisskip = 1;
			cis.cislen = nv;
			
			(*cistab[i].parse)(pp, &cis, cistab[i].n);
	/*
	 * Read all tuples in attribute space.
	 */
	m = pcmmap(pp->slotno, 0, 0, 1);
	if(m == 0)
		return;

	cis.cisbase = KADDR(m->isa);
	cis.cispos = 0;
	cis.cisskip = 2;
	cis.cislen = m->len;

	/* loop through all the tuples */
	for(;;){
		this = cis.cispos;
		if(readc(&cis, &type) != 1)
			break;
		if(type == 0xFF)
			break;
		if(readc(&cis, &link) != 1)
			break;

		switch(type){
		default:
			break;
		case 0x15:
			tvers1(pp, &cis, type);
			break;
		case 0x1A:
			tcfig(pp, &cis, type);
			break;
		case 0x1B:
			tentry(pp, &cis, type);
			break;
		}

		if(link == 0xFF)
			break;
		cis.cispos = this + (2+link);
	}
	pcmunmap(pp->slotno, m);
}

static ulong


@@ 301,10 331,14 @@ iospaces(Cisdat *cis, PCMconftab *ct)
	if(readc(cis, &c) != 1)
		return;

	/*
	 * For each of the range descriptions read the
	 * start address and the length (value is length-1).
	 */
	nio = (c&0xf)+1;
	for(i = 0; i < nio; i++){
		ct->io[i].start = getlong(cis, (c>>4)&0x3);
		ct->io[i].len = getlong(cis, (c>>6)&0x3);
		ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
	}
	ct->nio = nio;
}

M port/devmnt.c => port/devmnt.c +76 -66
@@ 12,10 12,11 @@ struct Mntrpc
	Chan*	c;		/* Channel for whom we are working */
	Mntrpc*	list;		/* Free/pending list */
	Fcall	request;	/* Outgoing file system protocol message */
	Fcall reply;		/* Incoming reply */
	Fcall 	reply;		/* Incoming reply */
	Mnt*	m;		/* Mount device during rpc */
	Rendez	r;		/* Place to hang out */
	uchar*	rpc;		/* I/O Data buffer */
	Block	*b;		/* reply blocks */
	char	done;		/* Rpc completed */
	uvlong	stime;		/* start time for mnt statistics */
	ulong	reqlen;		/* request length for mnt statistics */


@@ 126,6 127,7 @@ mntattach(char *muxattach)
	m->list = mntalloc.list;
	mntalloc.list = m;
	m->id = mntalloc.id++;
	m->q = qopen(10*MAXRPC, 0, nil, nil);
	unlock(&mntalloc);

	lock(m);


@@ 211,13 213,6 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname)
	Mntrpc *r;
	Walkqid *wq;

if(0){
	print("mntwalk ");
	for(i=0; i<nname; i++)
		print("%s/", name[i]);
	print("\n");
}

	if(nname > MAXWELEM)
		error("devmnt: too many name elements");
	alloc = 0;


@@ 415,6 410,7 @@ void
mntpntfree(Mnt *m)
{
	Mnt *f, **l;
	Queue *q;

	lock(&mntalloc);
	l = &mntalloc.list;


@@ 425,10 421,12 @@ mntpntfree(Mnt *m)
		}
		l = &f->list;
	}

	m->list = mntalloc.mntfree;
	mntalloc.mntfree = m;
	q = m->q;
	unlock(&mntalloc);

	qfree(q);
}

static void


@@ 553,7 551,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
			nr = nreq;

		if(type == Tread)
			memmove(uba, r->reply.data, nr);
			r->b = bl2mem((uchar*)uba, r->b, nr);
		else if(cache)
			cwrite(c, (uchar*)uba, nr, off);



@@ 661,67 659,78 @@ mountio(Mnt *m, Mntrpc *r)
}

int
mntreadn(Chan *c, uchar *buf, int n, int uninterruptable)
{
	int m, dm;

	for(m=0; m<n; m+=dm){
		if(uninterruptable)
			if(waserror()){
				/* user DEL may stop assembly; wait for full 9P msg. */
				if(strstr(up->error, "interrupt") == nil)
					nexterror();
				dm = 0;
				continue;
			}
		dm = devtab[c->type]->read(c, buf, n-m, 0);
		if(uninterruptable)
			poperror();
		if(dm <= 0)
			return 0;
		buf += dm;
	}
	return n;
}

int
mntrpcread(Mnt *m, Mntrpc *r)
{
	int n, len;
	ulong chunk;
	int i, t, len, hlen;
	Block *b, **l, *nb;

	chunk = m->c->iounit;
	if(chunk == 0 || chunk > m->c->iounit)
		chunk = m->c->iounit;
	r->reply.type = 0;
	r->reply.tag = 0;
	/* read size, then read exactly the right number of bytes */
	n = mntreadn(m->c, r->rpc, BIT32SZ, 0);
	if(n != BIT32SZ){
		if(n > 0)
			print("devmnt expected BIT32SZ got %d\n", n);
		return -1;
	}
	len = GBIT32((uchar*)r->rpc);
	if(len <= BIT32SZ || len > chunk){
		print("devmnt: len %d max messagesize %ld\n", len, m->c->iounit);
		return -1;
	}
	n += mntreadn(m->c, r->rpc+BIT32SZ, len-BIT32SZ, 1);
	if(n != len){
		print("devmnt: length %d expected %d\n", n, len);
		return -1;

	/* read at least length, type, and tag and pullup to a single block */
	while(qlen(m->q) < BIT32SZ+BIT8SZ+BIT16SZ){
		b = devtab[m->c->type]->bread(m->c, 2*MAXRPC, 0);
		if(b == nil)
			return -1;
		qadd(m->q, b);
	}
	nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ);
	len = GBIT32(nb->rp);

	/* read in the rest of the message */
	while(qlen(m->q) < len){
		b = devtab[m->c->type]->bread(m->c, 2*MAXRPC, 0);
		if(b == nil)
			return -1;
		qadd(m->q, b);
	}

	/* pullup the header (i.e. everything except data) */
	t = nb->rp[BIT32SZ];
	switch(t){
	case Rread:
		hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ;
		break;
	default:
		hlen = len;
		break;
	}
	nb = pullupqueue(m->q, hlen);

	r->replen = n;
	if(convM2S(r->rpc, n, &r->reply) == 0){
		int i;
		print("bad conversion of received message; %d bytes iounit %ld\n", n, m->c->iounit);
		for(i=0; i<n; i++)
			print("%.2ux ", (uchar)r->rpc[i]);
		print("\n");
	if(convM2S(nb->rp, len, &r->reply) <= 0){
		/* bad message, dump it */
		print("mntrpcread: convM2S failed\n");
		qdiscard(m->q, len);
		return -1;
	}

	/* hang the data off of the fcall struct */
	l = &r->b;
	*l = nil;
	do {
		b = qremove(m->q);
		if(hlen > 0){
			b->rp += hlen;
			len -= hlen;
			hlen = 0;
		}
		i = BLEN(b);
		if(i <= len){
			len -= i;
			*l = b;
			l = &(b->next);
		} else {
			/* split block and put unused bit back */
			nb = allocb(i-len);
			memmove(nb->wp, b->rp+len, i-len);
			b->wp = b->rp+len;
			nb->wp += i-len;
			qputback(m->q, nb);
			*l = b;
			return 0;
		}
	}while(len > 0);

	return 0;
}



@@ 743,7 752,6 @@ mntgate(Mnt *m)
void
mountmux(Mnt *m, Mntrpc *r)
{
	uchar *dp;
	Mntrpc **l, *q;

	lock(m);


@@ 757,10 765,9 @@ mountmux(Mnt *m, Mntrpc *r)
				 * Completed someone else.
				 * Trade pointers to receive buffer.
				 */
				dp = q->rpc;
				q->rpc = r->rpc;
				r->rpc = dp;
				q->reply = r->reply;
				q->b = r->b;
				r->b = nil;
			}
			q->done = 1;
			unlock(m);


@@ 857,12 864,15 @@ mntralloc(Chan *c, ulong iounit)
	new->c = c;
	new->done = 0;
	new->flushed = nil;
	new->b = nil;
	return new;
}

void
mntfree(Mntrpc *r)
{
	if(r->b != nil)
		freeblist(r->b);
	lock(&mntalloc);
	if(mntalloc.nrpcfree >= 10){
		free(r->rpc);

M port/devuart.c => port/devuart.c +12 -0
@@ 490,6 490,17 @@ uartwstat(Chan *c, uchar *dp, int n)
	return n;
}

void
uartpower(int on)
{
	Uart *p;

	for(p = uartlist; p != nil; p = p->next) {
		if (p->phys->power)
			(*p->phys->power)(p, on);
	}
}

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


@@ 508,6 519,7 @@ Dev uartdevtab = {
	devbwrite,
	devremove,
	uartwstat,
	uartpower,
};

/*

M port/error.h => port/error.h +3 -3
@@ 20,7 20,7 @@ extern char Eio[];		/* i/o error */
extern char Etoobig[];		/* read or write too large */
extern char Etoosmall[];	/* read or write too small */
extern char Enoport[];		/* network port not available */
extern char Ehungup[];		/* write to hungup channel */
extern char Ehungup[];		/* i/o on hungup channel */
extern char Ebadctl[];		/* bad process or channel control request */
extern char Enodev[];		/* no free devices */
extern char Eprocdied[];	/* process exited */


@@ 28,7 28,7 @@ extern char Enochild[];		/* no living children */
extern char Eioload[];		/* i/o error in demand load */
extern char Enovmem[];		/* virtual memory allocation failed */
extern char Ebadfd[];		/* fd out of range or not open */
extern char Enofd[];			/* no free file descriptors */
extern char Enofd[];		/* no free file descriptors */
extern char Eisstream[];	/* seek on a stream */
extern char Ebadexec[];		/* exec header invalid */
extern char Etimedout[];	/* connection timed out */


@@ 46,4 46,4 @@ extern char Enoreg[];		/* process has no saved registers */
extern char Enoattach[];	/* mount/attach disallowed */
extern char Eshortstat[];	/* stat buffer too small */
extern char Ebadstat[];		/* malformed stat buffer */
extern char Enegoff[];	/* negative i/o offset */
extern char Enegoff[];		/* negative i/o offset */

M port/portdat.h => port/portdat.h +2 -0
@@ 730,6 730,7 @@ struct PhysUart
	void	(*dtr)(Uart*, int);
	long	(*status)(Uart*, void*, long, long);
	void	(*fifo)(Uart*, int);
	void	(*power)(Uart*, int);
};

enum {


@@ 742,6 743,7 @@ enum {
struct Uart
{
	void*	regs;			/* hardware stuff */
	void*	saveregs;		/* place to put registers on power down */
	char*	name;			/* internal name */
	ulong	freq;			/* clock frequency */
	int	bits;			/* bits per character */

M port/portfns.h => port/portfns.h +2 -0
@@ 11,6 11,7 @@ int		anyready(void);
void		_assert(char*);
Image*		attachimage(int, Chan*, ulong, ulong);
Page*		auxpage(void);
Block*		bl2mem(uchar*, Block*, int);
int		blocklen(Block*);
void		cachedel(Image*, ulong);
void		cachepage(Page*, Image*);


@@ 155,6 156,7 @@ void		machinit(void);
void*		mallocz(ulong, int);
void*		malloc(ulong);
void		mallocsummary(void);
Block*		mem2bl(uchar*, int);
void		mfreeseg(Segment*, ulong, int);
void		microdelay(int);
void		mkqid(Qid*, vlong, ulong, int);

M port/qio.c => port/qio.c +83 -48
@@ 865,6 865,68 @@ qremove(Queue *q)
}

/*
 *  copy the contents of a string of blocks into
 *  memory.  emptied blocks are freed.  return
 *  pointer to first unconsumed block.
 */
Block*
bl2mem(uchar *p, Block *b, int n)
{
	int i;
	Block *next;

	for(; b != nil; b = next){
		i = BLEN(b);
		if(i > n){
			memmove(p, b->rp, n);
			b->rp += n;
			return b;
		}
		memmove(p, b->rp, i);
		n -= i;
		p += i;
		b->rp += i;
		next = b->next;
		freeb(b);
	}
	return nil;
}

/*
 *  copy the contents of memory into a string of blocks.
 *  return nil on error.
 */
Block*
mem2bl(uchar *p, int len)
{
	int n;
	Block *b, *first, **l;

	first = nil;
	l = &first;
	if(waserror()){
		freeblist(first);
		nexterror();
	}
	do {
		n = len;
		if(n > Maxatomic)
			n = Maxatomic;

		*l = b = allocb(n);
		setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]);
		memmove(b->wp, p, n);
		b->wp += n;
		p += n;
		len -= n;
		l = &b->next;
	} while(len > 0);
	poperror();

	return first;
}

/*
 *  put a block back to the front of the queue
 *  called with q ilocked
 */


@@ 965,12 1027,8 @@ qbread(Queue *q, int len)
long
qread(Queue *q, void *vp, int len)
{
	Block *b, *first, *next, **l;
	int m;
	uchar *s, *e, *p;

	s = p = vp;
	e = s+len;
	Block *b, *first, **l;
	int m, n;

	qlock(&q->rlock);
	if(waserror()){


@@ 1006,46 1064,34 @@ again:
		 *  following blocks as will completely
		 *  fit in the read.
		 */
		n = 0;
		l = &first;
		m = BLEN(b);
		for(;;) {
			*l = qremove(q);
			l = &b->next;
			p += m;
			n += m;

			b = q->bfirst;
			if(b == nil)
				break;
			m = BLEN(b);
			if(p+m > e)
			if(n+m > len)
				break;
		}
	} else {
		first = qremove(q);
		n = BLEN(first);
	}

	/* copy to user space outside of the ilock */
	iunlock(q);
	p = s;
	for(b = first; b != nil; b = next){
		m = BLEN(b);
		if(m > e - p){
			m = e - p;
			memmove(p, b->rp, m);
			p += m;
			b->rp += m;
			break;
		}
		memmove(p, b->rp, m);
		p += m;
		next = b->next;
		b->next = nil;
		freeb(b);
	}
	b = bl2mem(vp, first, len);
	ilock(q);

	/* take care of any left over partial block */
	if(b != nil){
		n -= BLEN(b);
		if(q->state & Qmsg)
			freeb(b);
		else


@@ 1057,7 1103,7 @@ again:

	poperror();
	qunlock(&q->rlock);
	return p-s;
	return n;
}

static int


@@ 1169,33 1215,22 @@ qbwrite(Queue *q, Block *b)
int
qwrite(Queue *q, void *vp, int len)
{
	int n, sofar;
	Block *b;
	uchar *p = vp;
	Block *b, *next;

	QDEBUG if(islo() == 0)
	QDEBUG if(!islo())
		print("qwrite hi %lux\n", getcallerpc(&q));

	sofar = 0;
	do {
		n = len-sofar;
		if(n > Maxatomic)
			n = Maxatomic;

		b = allocb(n);
		setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]);
		if(waserror()){
			freeb(b);
			nexterror();
		}
		memmove(b->wp, p+sofar, n);
		poperror();
		b->wp += n;

	b = mem2bl(vp, len);
	if(waserror()){
		freeblist(b);
		nexterror();
	}
	for(; b != nil; b = next){
		next = b->next;
		b->next = nil;
		qbwrite(q, b);

		sofar += n;
	} while(sofar < len && (q->state & Qmsg) == 0);
	}
	poperror();

	return len;
}