~kris/9p

9hist

4f9e39d754d57960bad24e65b5cfca5af8ba59a5 — David du Colombier 31 years ago ef4f4f0
Plan 9 from Bell Labs 1995-01-08
M carrera/clock.c => carrera/clock.c +9 -2
@@ 47,6 47,8 @@ clockinit(void)
void
clock(Ureg *ur)
{
	int n;

	wrcompare(rdcount()+(m->speed*1000000)/HZ);

	m->ticks++;


@@ 76,8 78,13 @@ clock(Ureg *ur)
	if(up == 0 || up->state != Running)
		return;

	if(anyready())
		sched();
	if(anyready()) {
		n = up->inlock;
		if(n == 0)
			sched();
		else
			up->inlock = n-1;
	}

	/* user profiling clock */
	if(ur->status & KUSER)

M carrera/devether.c => carrera/devether.c +12 -0
@@ 691,6 691,12 @@ etherread(Chan *c, void *buf, long n, ulong offset)
	return netifread(ether[0], c, buf, n, offset);
}

Block*
etherbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

static int
etherloop(Etherpkt *p, long n)
{


@@ 781,6 787,12 @@ etherwrite(Chan *c, void *buf, long n, ulong offset)
	return n;
}

long
etherbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
etherremove(Chan *c)
{

M carrera/devrtc.c => carrera/devrtc.c +14 -1
@@ 24,7 24,8 @@ struct Rtc
QLock rtclock;	/* mutex on clock operations */


enum{
enum
{
	Qrtc = 1,
	Qnvram,



@@ 185,6 186,12 @@ rtcread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
rtcbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

static void
binary2bcd(int reg, uchar val)
{


@@ 249,6 256,12 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

long
rtcbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void	 
rtcremove(Chan *c)
{

M carrera/trap.c => carrera/trap.c +1 -4
@@ 376,9 376,6 @@ intr(Ureg *ur)
		case 7:
			audiosbintr();
			break;
		case 10:
			mpegintr();
			break;
		case 13:
			eisadmaintr();
			break;


@@ 400,7 397,7 @@ intr(Ureg *ur)
	}

	/* preemptive scheduling */
	if(up && up->state == Running && anyhigher())
	if(up && up->state == Running && anyhigher() && up->inlock == 0)
		sched();
}


M pc/devastar.c => pc/devastar.c +12 -0
@@ 709,6 709,12 @@ astarread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
astarbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

/*
 *  write ISA mapped memory
 */


@@ 1200,6 1206,12 @@ astarwrite(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

long
astarbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
astarcreate(Chan *c, char *name, int omode, ulong perm)
{

M pc/devconfig.c => pc/devconfig.c +12 -0
@@ 121,6 121,12 @@ configread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
configbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
configwrite(Chan *c, void *buf, long n, ulong offset)
{


@@ 181,6 187,12 @@ configwrite(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

long
configbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
configremove(Chan *c)
{

M pc/devether.c => pc/devether.c +12 -0
@@ 82,6 82,12 @@ etherread(Chan *c, void *buf, long n, ulong offset)
	return netifread(ether[c->dev], c, buf, n, offset);
}

Block*
etherbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

void
etherremove(Chan *c)
{


@@ 153,6 159,12 @@ etherwrite(Chan *c, void *buf, long n, ulong offset)
	return n;
}

long
etherbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

static struct {
	char	*type;
	int	(*reset)(Ether*);

M pc/devfloppy.c => pc/devfloppy.c +12 -0
@@ 524,6 524,12 @@ floppyread(Chan *c, void *a, long n, ulong offset)
	return rv;
}

Block*
floppybread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)
long
floppywrite(Chan *c, void *a, long n, ulong offset)


@@ 589,6 595,12 @@ floppywrite(Chan *c, void *a, long n, ulong offset)
	return rv;
}

long
floppybwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

static void
floppykproc(void *a)
{

M pc/devhard.c => pc/devhard.c +12 -0
@@ 371,6 371,12 @@ hardread(Chan *c, void *a, long n, ulong offset)
	return rv;
}

Block*
hardbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
hardwrite(Chan *c, void *a, long n, ulong offset)
{


@@ 441,6 447,12 @@ hardwrite(Chan *c, void *a, long n, ulong offset)
	return rv;
}

long
hardbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

/*
 *  did an interrupt happen?
 */

M pc/devi82365.c => pc/devi82365.c +12 -0
@@ 712,6 712,12 @@ i82365read(Chan *c, void *a, long n, ulong offset)
	return n;
}

Block*
i82365bread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
pcmwrite(int dev, int attr, void *a, long n, ulong offset)
{


@@ 764,6 770,12 @@ i82365write(Chan *c, void *a, long n, ulong offset)
	return n;
}

long
i82365bwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

/*
 *  configure the Slot for IO.  We assume very heavily that we can read
 *  cofiguration info from the CIS.  If not, we won't set up correctly.

M pc/devlpt.c => pc/devlpt.c +12 -0
@@ 166,6 166,12 @@ lptread(Chan *c, void *a, long n)
	return n;
}

Block*
lptbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
lptwrite(Chan *c, void *a, long n)
{


@@ 195,6 201,12 @@ lptwrite(Chan *c, void *a, long n)
	return n;
}

long
lptbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

static void
outch(int base, int c)
{

M pc/devrtc.c => pc/devrtc.c +12 -0
@@ 201,6 201,12 @@ rtcread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
rtcbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)

long	 


@@ 276,6 282,12 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

long
rtcbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void	 
rtcremove(Chan *c)
{

M pc/devvga.c => pc/devvga.c +12 -0
@@ 244,6 244,12 @@ vgaread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
vgabread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

static void
vgactl(char *arg)
{


@@ 358,6 364,12 @@ vgawrite(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

long
vgabwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
vgaremove(Chan *c)
{

M port/dev.c => port/dev.c +29 -0
@@ 232,3 232,32 @@ Return:
	c->flag |= COPEN;
	return c;
}

Block*
devbread(Chan *c, long n, ulong offset)
{
	Block *bp;

	bp = allocb(n);
	if(bp == 0)
		error(Enomem);
	if(waserror()) {
		freeb(bp);
		nexterror();
	}
	bp->wp += devtab[c->type].read(c, bp->wp, n, offset);
	poperror();
	return bp;
}

long
devbwrite(Chan *c, Block *bp, ulong offset)
{
	long n;

	n = devtab[c->type].write(c, bp->rp, BLEN(bp), offset);
	freeb(bp);

	return n;	
}


M port/devboot.c => port/devboot.c +12 -0
@@ 95,6 95,12 @@ bootread(Chan *c, void *buf, long n, ulong offset)
	return 0;	/* not reached */
}

Block*
bootbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long	 
bootwrite(Chan *c, void *buf, long n, ulong offset)
{


@@ 120,6 126,12 @@ bootwrite(Chan *c, void *buf, long n, ulong offset)
	return 0;	/* not reached */
}

long
bootbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void	 
bootremove(Chan *c)
{

M port/devcons.c => port/devcons.c +12 -0
@@ 640,6 640,12 @@ consread(Chan *c, void *buf, long n, ulong offset)
	return -1;		/* never reached */
}

Block*
consbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

void
conslights(char *a, int n)
{


@@ 825,6 831,12 @@ conswrite(Chan *c, void *va, long n, ulong offset)
	return n;
}

long
consbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
consremove(Chan *c)
{

M port/devdup.c => port/devdup.c +12 -0
@@ 122,6 122,12 @@ dupread(Chan *c, void *va, long n, ulong offset)
	return devdirread(c, a, n, (Dirtab *)0, 0L, dupgen);
}

Block*
dupbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
dupwrite(Chan *c, void *va, long n, ulong offset)
{


@@ 129,3 135,9 @@ dupwrite(Chan *c, void *va, long n, ulong offset)
	panic("dupwrite");
	return 0;		/* not reached */
}

long
dupbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

M port/devenv.c => port/devenv.c +12 -0
@@ 220,6 220,12 @@ envread(Chan *c, void *a, long n, ulong offset)
	return n;
}

Block*
envbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
envwrite(Chan *c, void *a, long n, ulong offset)
{


@@ 259,6 265,12 @@ envwrite(Chan *c, void *a, long n, ulong offset)
	return n;
}

long
envbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
envcpy(Egrp *to, Egrp *from)
{

M port/devkprof.c => port/devkprof.c +12 -0
@@ 162,6 162,12 @@ kprofread(Chan *c, void *va, long n, ulong offset)
	return n;
}

Block*
kprofbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
kprofwrite(Chan *c, char *a, long n, ulong offset)
{


@@ 183,6 189,12 @@ kprofwrite(Chan *c, char *a, long n, ulong offset)
	return n;
}

long
kprofbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
kproftimer(ulong pc)
{

M port/devlance.c => port/devlance.c +12 -0
@@ 425,6 425,12 @@ lanceread(Chan *c, void *buf, long n, ulong offset)
	return netifread(&l, c, buf, n, offset);
}

Block*
lancebread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

static int
isoutbuf(void *x)
{


@@ 509,6 515,12 @@ lancewrite(Chan *c, void *buf, long n, ulong offset)
	return n;
}

long
lancebwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
lanceremove(Chan *c)
{

M port/devmnt.c => port/devmnt.c +12 -0
@@ 523,6 523,12 @@ mntread(Chan *c, void *buf, long n, ulong offset)
	return n;
}

Block*
mntbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long	 
mntwrite9p(Chan *c, void *buf, long n, ulong offset)
{


@@ 536,6 542,12 @@ mntwrite(Chan *c, void *buf, long n, ulong offset)
}

long
mntbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

long
mntrdwr(int type, Chan *c, void *buf, long n, ulong offset, int p9msg)
{
	Mnt *m;

M port/devmouse.c => port/devmouse.c +12 -0
@@ 230,6 230,12 @@ mouseread(Chan *c, void *va, long n, ulong offset)
	return 0;
}

Block*
mousebread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
mousewrite(Chan *c, void *va, long n, ulong offset)
{


@@ 296,6 302,12 @@ mousewrite(Chan *c, void *va, long n, ulong offset)
	return -1;
}

long
mousebwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
Cursortocursor(Cursor *c)
{

M port/devns16552.c => port/devns16552.c +12 -0
@@ 837,6 837,12 @@ ns16552read(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
ns16552bread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

static void
ns16552ctl(Uart *p, char *cmd)
{


@@ 944,6 950,12 @@ ns16552write(Chan *c, void *buf, long n, ulong offset)
	}
}

long
ns16552bwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
ns16552remove(Chan *c)
{

M port/devpipe.c => port/devpipe.c +12 -0
@@ 291,6 291,12 @@ piperead(Chan *c, void *va, long n, ulong offset)
	return -1;	/* not reached */
}

Block*
pipebread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

/*
 *  a write to a closed pipe causes a note to be sent to
 *  the process.


@@ 329,3 335,9 @@ pipewrite(Chan *c, void *va, long n, ulong offset)
	poperror();
	return n;
}

long
pipebwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

M port/devproc.c => port/devproc.c +12 -0
@@ 480,6 480,12 @@ procread(Chan *c, void *va, long n, ulong offset)
	return 0;		/* not reached */
}

Block*
procbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

void
mntscan(Mntwalk *mw)
{


@@ 612,6 618,12 @@ procwrite(Chan *c, void *va, long n, ulong offset)
	return n;
}

long
procbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

Chan *
proctext(Chan *c, Proc *p)
{

M port/devroot.c => port/devroot.c +12 -0
@@ 211,6 211,12 @@ rootread(Chan *c, void *buf, long n, ulong offset)
	return n;
}

Block*
rootbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long	 
rootwrite(Chan *c, void *buf, long n, ulong offset)
{


@@ 232,6 238,12 @@ rootwrite(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

long
rootbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void	 
rootremove(Chan *c)
{

M port/devsd.c => port/devsd.c +12 -0
@@ 229,12 229,24 @@ sdread(Chan *c, void *a, long n, ulong offset)
	return sdio(c, 0, a, n, offset);
}

Block*
sdbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
sdwrite(Chan *c, char *a, long n, ulong offset)
{
	return sdio(c, 1, a, n, offset);
}

long
sdbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

static void
sdrdpart(Disk *d)
{

M port/devsrv.c => port/devsrv.c +12 -0
@@ 226,6 226,12 @@ srvread(Chan *c, void *va, long n, ulong offset)
	return devdirread(c, va, n, 0, 0, srvgen);
}

Block*
srvbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long
srvwrite(Chan *c, void *va, long n, ulong offset)
{


@@ 265,6 271,12 @@ srvwrite(Chan *c, void *va, long n, ulong offset)
	return n;
}

long
srvbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
srvrecover(Chan *old, Chan *new)
{

M port/error.h => port/error.h +1 -1
@@ 52,5 52,5 @@ extern char Emouseset[];	/* mouse type already set */
extern char Erecover[];		/* failed to recover fd */
extern char Eshort[];		/* i/o count too small */
extern char Enobitstore[];	/* out of screen memory */
extern char Egreg[];		/* coherency problem */
extern char Egreg[];		/* ken scheduled it */
extern char Ebadspec[];		/* bad attach specifier */

M port/portdat.h => port/portdat.h +4 -1
@@ 177,7 177,9 @@ struct Dev
	void	(*create)(Chan*, char*, int, ulong);
	void	(*close)(Chan*);
	long	(*read)(Chan*, void*, long, ulong);
	Block*	(*bread)(Chan*, long, ulong);
	long	(*write)(Chan*, void*, long, ulong);
	long	(*bwrite)(Chan*, Block*, ulong);
	void	(*remove)(Chan*);
	void	(*wstat)(Chan*, char*);
};


@@ 587,7 589,8 @@ struct Proc
	Mach	*wired;		/* machine this process must run on */
	int	pri;		/* scheduling priority - low is high priority */
	short	nice;		/* time-passing algorithm - low is high priority */
	short	yield;		/* force one lap in the runq */	
	char	yield;		/* force one lap in the runq */
	char	inlock;		/* temp hi proirity ~= 2*num of locks set */

	void	*ureg;		/* User registers for notes */
	void	*dbgreg;	/* User registers for devproc */

M port/portfns.h => port/portfns.h +2 -0
@@ 49,6 49,8 @@ int		decref(Ref*);
int		decrypt(void*, void*, int);
void		delay(int);
Chan*		devattach(int, char*);
Block*		devbread(Chan*, long, ulong);
long		devbwrite(Chan*, Block*, ulong);
Chan*		devclone(Chan*, Chan*);
void		devdir(Chan*, Qid, char*, long, char*, long, Dir*);
long		devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);

M port/proc.c => port/proc.c +2 -1
@@ 172,7 172,8 @@ loop:
		if(p->mach || (p->wired && p->wired != m))
			continue;
		if(bp == 0) {
			p->yield = 0;
			if(p->yield)
				p->yield = 0;
			bp = p;
		} else
		if(p->yield == 0 && p->pri < bp->pri)

M port/qio.c => port/qio.c +3 -3
@@ 111,7 111,7 @@ freeb(Block *b)
{
	/*
	 * drivers which perform non cache coherent DMA manage their
	 * own buffer pools, so they provide their own free routines.
	 * own buffer pool and provide their own free routine.
	 */
	if(b->free) {
		b->free(b);


@@ 520,8 520,8 @@ qwrite(Queue *q, void *vp, int len)

	dowakeup = 0;

	if((getstatus()&IE) == 0)
		print("qwrite hi %lux\n", getcallerpc(q));
if((getstatus()&IE) == 0)
print("qwrite hi %lux\n", getcallerpc(q));

	if(waserror()){
		qunlock(&q->wlock);

M port/taslock.c => port/taslock.c +28 -1
@@ 8,9 8,28 @@
void
lock(Lock *l)
{
	int n;

	if(up) {
		n = up->inlock+2;
		up->inlock = n;
		if(tas(&l->key) == 0)
			return;

		for(;;){
			while(l->key)
				if(conf.nproc == 1) {
					up->yield = 1;
					sched();
				}
			up->inlock = n;
			if(tas(&l->key) == 0)
				return;
		}
	}

	if(tas(&l->key) == 0)
		return;

	for(;;){
		while(l->key)
			;


@@ 52,7 71,15 @@ canlock(Lock *l)
void
unlock(Lock *l)
{
	int n;

	l->key = 0;
	if(up) {
		n = up->inlock-2;
		if(n < 0)
			n = 0;
		up->inlock = n;
	}
}

void

M power/clock.c => power/clock.c +0 -1
@@ 80,7 80,6 @@ clock(Ureg *ur)
		}
		return;
	}
	nrun = 0;
	i = *CLRTIM0;
	USED(i);


M power/dat.h => power/dat.h +1 -1
@@ 137,7 137,7 @@ typedef void		KMap;
#define	kmap(p)		(KMap*)((p)->pa|KZERO)
#define	kunmap(k)
#define PPN(x)		x

#define AOUT_MAGIC	V_MAGIC || magic==M_MAGIC
/*
 *  LANCE CSR3 (bus control bits)
 */

D power/devcyc.c => power/devcyc.c +0 -398
@@ 1,398 0,0 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"devtab.h"

#include	"io.h"
#include	"/sys/src/fs/cyc/comm.h"


typedef struct Commcyc	Commcyc;

enum
{
	Vmevec=		0xd2,		/* vme vector for interrupts */
	Intlevel=	5,		/* level to interrupt on */
	Qdir=		0,		/* Qid's */
	Qcyc=		1,
	Ncyc=		1,
};

Dirtab cycdir[]={
	"cyc",	{Qcyc},	0,	0600,
};

#define	NCYCDIR	(sizeof cycdir/sizeof(Dirtab))

struct Commcyc
{
	Lock;
	QLock		buflock;
	Lock		busy;
	Comm		*addr;		/* address of the device */
	int		vec;		/* vme interrupt vector */
	int		wi;		/* where to write next cmd */
	int		ri;		/* where to read next reply */
	uchar		buf[MAXFDATA+MAXMSG];
};

Commcyc cyclone[Ncyc];

void	cycintr(int);

#define	CYCLONE	VMEA24SUP(Comm, 0x10000);

/*
 * Commands
 */

Cycmsg**
cycsend(Commcyc *h, Cycmsg *m)
{
	Cycmsg **mp;

	lock(h);
	mp = (Cycmsg**)&h->addr->reqstq[h->wi];
	*mp = (Cycmsg*)MP2VME(m);
	h->wi++;
	if(h->wi >= NRQ)
		h->wi = 0;
	unlock(h);
	return mp;
}

void
cycwait(Cycmsg **mp)
{
	ulong l;

	l = 0;
	while(*mp){
		delay(0);	/* just a subroutine call; stay off VME */
		if(++l > 10*1000*1000){
			l = 0;
			panic("cycsend blocked");
		}
	}
	return;
}

/*
 *  reset all cyclone boards
 */
void
cycreset(void)
{
	int i;
	Commcyc *cp;

	for(cp=cyclone,i=0; i<Ncyc; i++,cp++){
		cp->addr = CYCLONE+i;
		/*
		 * Write queue is at end of cyclone memory
		 */
		cp->vec = Vmevec+i;
		setvmevec(cp->vec, cycintr);
	}	
}

void
cycinit(void)
{
}

/*
 *  enable the device for interrupts, spec is the device number
 */
Chan*
cycattach(char *spec)
{
	int i;
	Chan *c;

	i = strtoul(spec, 0, 0);
	if(i >= Ncyc)
		error(Ebadarg);

	c = devattach('C', spec);
	c->dev = i;
	c->qid.path = CHDIR;
	c->qid.vers = 0;
	return c;
}

Chan*
cycclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int	 
cycwalk(Chan *c, char *name)
{
	return devwalk(c, name, cycdir, NCYCDIR, devgen);
}

void	 
cycstat(Chan *c, char *dp)
{
	devstat(c, dp, cycdir, NCYCDIR, devgen);
}

Chan*
cycopen(Chan *c, int omode)
{
	Commcyc *cp;
	Cycmsg *mp, **cmp;

	if(c->qid.path == CHDIR){
		if(omode != OREAD)
			error(Eperm);
	}else if(c->qid.path == Qcyc){
		cp = &cyclone[c->dev];
		if(!canlock(&cp->busy))
			error(Einuse);
		/*
		 * Clear communications region
		 */
		memset(cp->addr->reqstq, 0, NRQ*sizeof(ulong));
		cp->addr->reqstp = 0;
		memset(cp->addr->replyq, 0, NRQ*sizeof(ulong));
		cp->addr->replyp = 0;

		/* Set the interrupt vector for the cyclone to pick up */
		cp->addr->vmevec = Vmevec;

		/*
		 * Issue reset
		 */
		cp->wi = 0;
		cp->ri = 0;
		mp = up->kcyc;
		mp->cmd = Ureset;
		cmp = cycsend(cp, up->kcyc);
		cycwait(cmp);
		delay(100);
		print("reset\n");
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

void	 
cyccreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void	 
cycclose(Chan *c)
{
	Commcyc *cp;
	Cycmsg **cmp;

	cp = &cyclone[c->dev];
	if(c->qid.path != CHDIR){
		up->kcyc->cmd = Ureboot;
		cmp = cycsend(cp, up->kcyc);
		cycwait(cmp);
		unlock(&cp->busy);
	}
}

int
cycmsgintr(Cycmsg *hm)
{
	return hm->intr;
}

/*
 * Read and write use physical addresses if they can, which they usually can.
 * Most I/O is from devmnt, which has local buffers.  Therefore just check
 * that buf is in KSEG0 and is at an even address.
 */

long	 
cycread(Chan *c, void *buf, long n, ulong offset)
{
	ulong l, m;
	Commcyc *cp;
	Cycmsg *mp, **cmp;

	USED(offset);
	cp = &cyclone[c->dev];
	switch(c->qid.path & ~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, cycdir, NCYCDIR, devgen);

	case Qcyc:
		if(n > sizeof cp->buf){
			print("cyclone bufsize %d %d\n", n, sizeof cp->buf);
			error(Egreg);
		}
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 *  use supplied buffer, no need to lock for reply
			 */

			mp = up->kcyc;
			mp->cmd = Uread;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			mp->param[2] = 0;		/* reply checksum */
			mp->param[3] = 0xdeadbeef;	/* reply count */
			mp->intr = 0;
			cycsend(cp, mp);

			while(waserror())
				;
			sleep(&mp->r, cycmsgintr, mp);
			poperror();

			m = mp->param[3];
			if(m==0 || m>n){
				print("devcyc: count 0x%lux 0x%lux\n", m, n);
				error(Egreg);
			}
		}
		else{
			/*
			 * use cyclone buffer. lock the buffer until the reply
			 */
			mp = up->ucyc;
			qlock(&cp->buflock);
			mp->cmd = Uread;
			mp->param[0] = MP2VME(cp->buf);
			mp->param[1] = n;
			mp->param[2] = 0;	/* reply checksum */
			mp->param[3] = 0;	/* reply count */
			mp->intr = 0;
			cmp = cycsend(cp, mp);
			cycwait(cmp);
			l = 100*1000*1000;
			do
				m = mp->param[3];
			while(m==0 && --l>0);

			if(m==0 || m>n){
				print("devcyc: count %ld %ld\n", m, n);
				qunlock(&cp->buflock);
				error(Egreg);
			}
			memmove(buf, cp->buf, m);
			qunlock(&cp->buflock);
		}
		return m;
	}
	print("devcyc read unk\n");
	error(Egreg);
	return 0;
}

long	 
cycwrite(Chan *c, void *buf, long n, ulong offset)
{
	Commcyc *cp;
	Cycmsg *mp, **cmp;

	USED(offset);
	cp = &cyclone[c->dev];
	switch(c->qid.path & ~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, cycdir, NCYCDIR, devgen);

	case Qcyc:
		if(n > sizeof cp->buf){
			print("cyclone write bufsize\n");
			error(Egreg);
		}
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 * use supplied buffer, no need to lock for reply
			 */
			mp = up->kcyc;

			mp->cmd = Uwrite;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			mp->param[2] = 0;

			cmp = cycsend(cp, mp);
			cycwait(cmp);
		}else{
			/*
			 * use cyclone buffer.  lock the buffer until the reply
			 */
			mp = up->ucyc;
			qlock(&cp->buflock);
			memmove(cp->buf, buf, n);

			mp->cmd = Uwrite;
			mp->param[0] = MP2VME(cp->buf);
			mp->param[1] = n;
			mp->param[2] = 0;

			cmp = cycsend(cp, mp);
			cycwait(cmp);
			qunlock(&cp->buflock);
		}
		return n;
	}
	print("cyclone write unk\n");
	error(Egreg);
	return 0;
}

void	 
cycremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void	 
cycwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

void
cycintr(int vec)
{
	Cycmsg *cm;
	Commcyc *h;
	ulong l, n, *r;

	h = &cyclone[vec - Vmevec];
	if(h<cyclone || h>&cyclone[Ncyc]){
		print("bad cyclone vec\n");
		return;
	}

	r = h->addr->replyq;

	for(;;) {
		l = r[h->ri];
		if(l == 0)
			break;

		r[h->ri++] = 0;
		if(h->ri >= NRQ)
			h->ri = 0;

		cm = (Cycmsg*)VME2MP(l);
		cm->intr = 1;
		n = cm->param[3];
		if(n==0 || n > 10000)
			print("cycintr count 0x%lux\n", n);

		wakeup(&cm->r);
	}
}

M power/devduart.c => power/devduart.c +12 -0
@@ 615,6 615,12 @@ duartread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

Block*
duartbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

static void
duartctl(Uart *p, char *cmd)
{


@@ 683,6 689,12 @@ duartwrite(Chan *c, void *va, long n, ulong offset)
	}
}

long
duartbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void
duartremove(Chan *c)
{

M power/devrtc.c => power/devrtc.c +12 -0
@@ 165,6 165,12 @@ rtcread(Chan *c, void *buf, long n, ulong offset)
	return -1;		/* never reached */
}

Block*
rtcbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

long	 
rtcwrite(Chan *c, void *buf, long n, ulong offset)
{


@@ 217,6 223,12 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
	return -1;		/* never reached */
}

long
rtcbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
}

void	 
rtcremove(Chan *c)
{

M power/fns.h => power/fns.h +1 -0
@@ 25,6 25,7 @@ void	firmware(int);
void	flushmmu(void);
#define	flushpage(s)	icflush((void*)(s), BY2PG)
void	fptrap(Ureg*);
ulong	getstatus(void);
void	gettlb(int, ulong*);
ulong	gettlbvirt(int);
void	gotopc(ulong);

M power/l.s => power/l.s +5 -5
@@ 101,7 101,7 @@ TEXT	splhi(SB), $0

	MOVW	R31, 0xC(R(MACH))	/* save PC in m->splpc */
	MOVW	M(STATUS), R1
	AND	$~IEC, R1, R2
	AND	$~IE, R1, R2
	MOVW	R2, M(STATUS)
	NOOP
	RET


@@ 110,8 110,8 @@ TEXT	splx(SB), $0

	MOVW	R31, 0xC(R(MACH))	/* save PC in m->splpc */
	MOVW	M(STATUS), R2
	AND	$IEC, R1
	AND	$~IEC, R2
	AND	$IE, R1
	AND	$~IE, R2
	OR	R2, R1
	MOVW	R1, M(STATUS)
	NOOP


@@ 120,7 120,7 @@ TEXT	splx(SB), $0
TEXT	spllo(SB), $0

	MOVW	M(STATUS), R1
	OR	$IEC, R1, R2
	OR	$IE, R1, R2
	MOVW	R2, M(STATUS)
	NOOP
	RET


@@ 131,7 131,7 @@ TEXT	muxlock(SB),$0
	MOVW	4(FP), R3	/* lk->val */

	MOVW	M(STATUS), R5	/* splhi */
	AND	$~IEC, R5, R4
	AND	$~IE, R5, R4
	MOVW	R4, M(STATUS)

	MOVW	0(R2),R4	/* grab sbsem */

M power/mem.h => power/mem.h +1 -1
@@ 46,7 46,7 @@
/*
 * M(STATUS) bits
 */
#define IEC		0x00000001
#define IE		0x00000001
#define KUC		0x00000002
#define IEP		0x00000004
#define KUP		0x00000008

M power/trap.c => power/trap.c +0 -1
@@ 521,7 521,6 @@ syscall(Ureg *aur)
			postnote(up, 1, "sys: bad sys call", NDebug);
			error(Ebadarg);
		}
		up->syscall[up->scallnr]++;

		if(sp & (BY2WD-1)){
			pprint("odd sp in sys call pc %lux sp %lux\n", ur->pc, ur->sp);