~kris/9p

9hist

8f59696e8431c186f8e40e0835aa883cfc6e7dd8 — David du Colombier 26 years ago e165207
Plan 9 from Bell Labs 2000-06-24
2 files changed, 168 insertions(+), 60 deletions(-)

A ip/netdevmedium.c
M pc/i8253.c
A ip/netdevmedium.c => ip/netdevmedium.c +160 -0
@@ 0,0 1,160 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"

#include "ip.h"
#include "kernel.h"

static void	netdevbind(Ipifc *ifc, int argc, char **argv);
static void	netdevunbind(Ipifc *ifc);
static void	netdevbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
static void	netdevread(void *a);

typedef struct	Netdevrock Netdevrock;
struct Netdevrock
{
	Fs	*f;		/* file system we belong to */
	Proc	*readp;		/* reading process */
	Chan	*mchan;		/* Data channel */
};

Medium netdevmedium =
{
.name=		"netdev",
.hsize=		14,		//ZZZ what should these be?
.minmtu=	60,
.maxmtu=	1514,
.maclen=	6,
.bind=		netdevbind,
.unbind=	netdevunbind,
.bwrite=	netdevbwrite,
.unbindonclose=	0,
};

/*
 *  called to bind an IP ifc to a generic network device
 *  called with ifc qlock'd
 */
static void
netdevbind(Ipifc *ifc, int argc, char **argv)
{
	int fd;
	Chan *mchan;
	Netdevrock *er;

	if(argc < 2)
		error(Ebadarg);

	fd = kopen(argv[2], ORDWR);
	if(fd < 0)
		error("fd open failed");

	mchan = commonfdtochan(fd, ORDWR, 0, 1);
	kclose(fd);

	er = smalloc(sizeof(*er));
	er->mchan = mchan;
	er->f = ifc->conv->p->f;

	ifc->arg = er;

	kproc("netdevread", netdevread, ifc);
}

/*
 *  called with ifc wlock'd
 */
static void
netdevunbind(Ipifc *ifc)
{
	Netdevrock *er = ifc->arg;

	if(er->readp != nil)
		postnote(er->readp, 1, "unbind", 0);

	/* wait for readers to die */
	while(er->readp != nil)
		tsleep(&up->sleep, return0, 0, 300);

	if(er->mchan != nil)
		cclose(er->mchan);

	free(er);
}

/*
 *  called by ipoput with a single block to write
 */
static void
netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*)
{
	Netdevrock *er = ifc->arg;

	if(bp->next)
		bp = concatblock(bp);
	if(BLEN(bp) < ifc->minmtu)
		bp = adjustblock(bp, ifc->minmtu);

	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
	ifc->out++;
}

/*
 *  process to read from the device
 */
static void
netdevread(void *a)
{
	Ipifc *ifc;
	Block *bp;
	Netdevrock *er;
	char *argv[1];

	ifc = a;
	er = ifc->arg;
	er->readp = up;	/* hide identity under a rock for unbind */
	if(waserror()){
		er->readp = nil;
		pexit("hangup", 1);
	}
	for(;;){
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0);
		if(bp == nil){
			/*
			 * get here if mchan is a pipe and other side hangs up
			 * clean up this interface & get out
ZZZ is this a good idea?
			 */
			poperror();
			er->readp = nil;
			argv[0] = "unbind";
			if(!waserror())
				ifc->conv->p->ctl(ifc->conv, argv, 1);
			pexit("hangup", 1);
		}
		if(!canrlock(ifc)){
			freeb(bp);
			continue;
		}
		if(waserror()){
			runlock(ifc);
			nexterror();
		}
		ifc->in++;
		if(ifc->lifc == nil)
			freeb(bp);
		else
			ipiput(er->f, ifc->lifc->local, bp);
		runlock(ifc);
		poperror();
	}
}

void
netdevmediumlink(void)
{
	addipmedium(&netdevmedium);
}

M pc/i8253.c => pc/i8253.c +8 -60
@@ 156,71 156,19 @@ i8253init(int aalcycles, int havecycleclock)
		m->cpumhz = (cpufreq + cpufreq/200)/1000000;
		m->cpuhz = cpufreq;
	}

outb(Tmode, Load0|Trigger);
outb(T0cntr, (Freq/HZ));	/* low byte */
outb(T0cntr, (Freq/HZ)>>8);	/* high byte */
}

static vlong lastfast;

int
i8253readcnt(int cntr)
{
	int v;

	ilock(&i8253.lock);
	if(cntr == 2){
		outb(Tmode, Rdback|Rd2cntr);
		v = inb(T2cntr) << 16;
		v |= inb(T2cntr);
		v |= inb(T2cntr) << 8;
	}else if(cntr == 0){
		outb(Tmode, Rdback|Rd0cntr);
		v = inb(T0cntr) << 16;
		v |= inb(T0cntr);
		v |= inb(T0cntr) << 8;
	}else if(cntr == 3){
		vlong nf = fastticks(nil);
		long set;

		set = (long)(nf - lastfast) * 100 / (long)((vlong)m->cpuhz * 100 / Freq);
		set = (Freq/HZ) - set;
		set -= 3 - 1;	/* outb, outb, wait - outb(mode) */
		outb(Tmode, Rdback|Rdnstat|Rd0cntr);
		v = inb(T0cntr);
		v |= inb(T0cntr) << 8;
		v = set - v;
	}else if(cntr == 4){
		vlong nf = fastticks(nil);
		long set;

		set = (long)(nf - lastfast) * 16 / (long)((vlong)m->cpuhz * 16 / Freq);
		set = (Freq/HZ) - set;
		set -= 3 - 1;	/* outb, outb, wait - outb(mode) */
		outb(Tmode, Rdback|Rdnstat|Rd0cntr);
		v = inb(T0cntr);
		v |= inb(T0cntr) << 8;
		v = set - v;
	}else{
		vlong nf = fastticks(nil);
		long set;

		set = (nf - lastfast) * Freq / m->cpuhz;
		set = (Freq/HZ) - set;
		set -= 3 - 1;	/* outb, outb, wait - outb(mode) */
		outb(Tmode, Rdback|Rdnstat|Rd0cntr);
		v = inb(T0cntr);
		v |= inb(T0cntr) << 8;
		v = set - v;
	}
	iunlock(&i8253.lock);
	return v;
}
#ifdef SETNEXT
set up clock so it is reloaded every interrupt
	outb(Tmode, Load0|Trigger);
	outb(T0cntr, (Freq/HZ));	/* low byte */
	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */
#endif

static void
clockintr0(Ureg* ureg, void *v)
{
#ifdef SETNEXT
	vlong now;
	long set;



@@ 229,9 177,9 @@ clockintr0(Ureg* ureg, void *v)
		i8253.when += i8253.fastperiod;
	set = (long)(i8253.when - now) * FreqMul / i8253.fast2freq;
	set -= 3;	/* three cycles for the count to take effect: outb, outb, wait */
lastfast = now;
	outb(T0cntr, set);	/* low byte */
	outb(T0cntr, set>>8);	/* high byte */
#endif

	checkcycintr(ureg, v);
	clockintr(ureg, v);