@@ 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);
+}
@@ 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);