From 8f59696e8431c186f8e40e0835aa883cfc6e7dd8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 24 Jun 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-06-24 --- ip/netdevmedium.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++ pc/i8253.c | 68 +++----------------- 2 files changed, 168 insertions(+), 60 deletions(-) create mode 100644 ip/netdevmedium.c diff --git a/ip/netdevmedium.c b/ip/netdevmedium.c new file mode 100644 index 0000000000000000000000000000000000000000..e54c9c4b4e25aae208a7e02547cd1bfd6c63d711 --- /dev/null +++ b/ip/netdevmedium.c @@ -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); +} diff --git a/pc/i8253.c b/pc/i8253.c index 344f04c1d5f76bb73c81beca2bfca7041c6c129b..8b43c0c687ea111050637027a189cc5c3f0d185d 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -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);