This links.
authorRonald G. Minnich <rminnich@google.com>
Fri, 17 Jan 2014 22:17:17 +0000 (14:17 -0800)
committerRonald G. Minnich <rminnich@google.com>
Fri, 17 Jan 2014 22:17:37 +0000 (14:17 -0800)
We now have a console dev.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/drivers/dev/Kbuild
kern/drivers/dev/alarm.c
kern/drivers/dev/cons.c [new file with mode: 0644]
kern/drivers/dev/dev.c
kern/include/ns.h
kern/src/net/devip.c
kern/src/net/ipprotoinit.c
kern/src/net/tcp.c
kern/src/ns/allocb.c

index ddcd54c..3457696 100644 (file)
@@ -1,4 +1,5 @@
 obj-y                                          += alarm.o
+obj-y                                          += cons.o
 obj-y                                          += dev.o
 obj-y                                          += mnt.o
 obj-y                                          += tab.o
index f85b232..0ef0723 100644 (file)
@@ -66,6 +66,7 @@
 #define QID2A(q) ((struct proc_alarm*)KADDR(((q).path >> ADDR_SHIFT)))
 #define TYPE(q) ((q).path & ((1 << ADDR_SHIFT) - 1))
 #define QID(ptr, type) ((PADDR(ptr) << ADDR_SHIFT) | type)
+extern char *eve;
 
 static void alarm_release(struct kref *kref)
 {
diff --git a/kern/drivers/dev/cons.c b/kern/drivers/dev/cons.c
new file mode 100644 (file)
index 0000000..858a555
--- /dev/null
@@ -0,0 +1,1227 @@
+// INFERNO
+#include <vfs.h>
+#include <kfs.h>
+#include <slab.h>
+#include <kmalloc.h>
+#include <kref.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <error.h>
+#include <cpio.h>
+#include <pmap.h>
+#include <smp.h>
+#include <ip.h>
+
+extern char *eve;
+/* much stuff not ready yet. */
+#if 0
+extern int cflag;
+extern int keepbroken;
+
+void   (*serwrite)(char *, int);
+
+struct queue*  kscanq;                 /* keyboard raw scancodes (when needed) */
+char*  kscanid;                /* name of raw scan format (if defined) */
+struct queue*  kbdq;                   /* unprocessed console input */
+struct queue*  lineq;                  /* processed console input */
+struct queue*  printq;                 /* console output */
+struct queue*  klogq;                  /* kernel print (log) output */
+int    iprintscreenputs;
+
+static struct
+{
+       rwlock_t rwlock;
+       Queue*  q;
+} kprintq;
+
+static struct
+{
+       qlock_t qlock;
+
+       int     raw;            /* true if we shouldn't process input */
+       int     ctl;            /* number of opens to the control file */
+       int     kbdr;           /* number of open reads to the keyboard */
+       int     scan;           /* true if reading raw scancodes */
+       int     x;              /* index into line */
+       char    line[1024];     /* current input line */
+
+       char    c;
+       int     count;
+       int     repeat;
+} kbd;
+
+#endif
+char*  sysname = "Your machine";
+char*  eve = "eve";
+
+enum
+{
+       CMreboot,
+       CMhalt,
+       CMpanic,
+       CMbroken,
+       CMnobroken,
+       CMconsole,
+};
+
+static struct cmdtab sysctlcmd[] =
+{
+       {CMreboot,      "reboot",       0},
+       {CMhalt,        "halt", 0},
+       {CMpanic,       "panic", 0},
+       {CMconsole,     "console", 1},
+       {CMbroken,      "broken", 0},
+       {CMnobroken,    "nobroken", 0},
+};
+
+void
+printinit(void)
+{
+#if 0
+       lineq = qopen(2*1024, 0, NULL, NULL);
+       if(lineq == NULL)
+               panic("printinit");
+       qnoblock(lineq, 1);
+#endif
+}
+
+/*
+ *  return true if current user is eve
+ */
+int
+iseve(void)
+{
+#if 0
+       Osenv *o;
+
+       o = up->env;
+       return strcmp(eve, o->user) == 0;
+#endif
+       return 1;
+}
+
+#if 0
+static int
+consactive(void)
+{
+       if(printq)
+               return qlen(printq) > 0;
+       return 0;
+}
+
+static void
+prflush(void)
+{
+       uint32_t now;
+
+       now = m->ticks;
+       while(serwrite==NULL && consactive())
+               if(m->ticks - now >= HZ)
+                       break;
+}
+
+/*
+ *   Print a string on the console.  Convert \n to \r\n for serial
+ *   line consoles.  Locking of the queues is left up to the screen
+ *   or uart code.  Multi-line messages to serial consoles may get
+ *   interspersed with other messages.
+ */
+static void
+putstrn0(char *str, int n, int usewrite)
+{
+       int m;
+       char *t;
+       char buf[PRINTSIZE+2];
+
+       /*
+        *  if kprint is open, put the message there, otherwise
+        *  if there's an attached bit mapped display,
+        *  put the message there.
+        */
+       m = consoleprint;
+       if(canrlock(&(&kprintq)->rwlock)){
+               if(kprintq.q != NULL){
+                       if(waserror()){
+                               runlock(&(&kprintq)->rwlock);
+                               nexterror();
+                       }
+                       if(usewrite)
+                               qwrite(kprintq.q, str, n);
+                       else
+                               qiwrite(kprintq.q, str, n);
+                       poperror();
+                       m = 0;
+               }
+               runlock(&(&kprintq)->rwlock);
+       }
+       if(m && screenputs != NULL)
+               screenputs(str, n);
+
+       /*
+        *  if there's a serial line being used as a console,
+        *  put the message there.
+        */
+       if(serwrite != NULL) {
+               serwrite(str, n);
+               return;
+       }
+
+       if(printq == 0)
+               return;
+
+       while(n > 0) {
+               t = memchr(str, '\n', n);
+               if(t && !kbd.raw) {
+                       m = t - str;
+                       if(m > sizeof(buf)-2)
+                               m = sizeof(buf)-2;
+                       memmove(buf, str, m);
+                       buf[m] = '\r';
+                       buf[m+1] = '\n';
+                       if(usewrite)
+                               qwrite(printq, buf, m+2);
+                       else
+                               qiwrite(printq, buf, m+2);
+                       str = t + 1;
+                       n -= m + 1;
+               } else {
+                       if(usewrite)
+                               qwrite(printq, str, n);
+                       else 
+                               qiwrite(printq, str, n);
+                       break;
+               }
+       }
+}
+
+void
+putstrn(char *str, int n)
+{
+       putstrn0(str, n, 0);
+}
+
+int
+snprintf(char *s, int n, char *fmt, ...)
+{
+       va_list arg;
+
+       va_start(arg, fmt);
+       n = vseprintf(s, s+n, fmt, arg) - s;
+       va_end(arg);
+
+       return n;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+       int n;
+       va_list arg;
+
+       va_start(arg, fmt);
+       n = vseprintf(s, s+PRINTSIZE, fmt, arg) - s;
+       va_end(arg);
+
+       return n;
+}
+
+int
+print(char *fmt, ...)
+{
+       int n;
+       va_list arg;
+       char buf[PRINTSIZE];
+
+       va_start(arg, fmt);
+       n = vseprintf(buf, buf+sizeof(buf), fmt, arg) - buf;
+       va_end(arg);
+       putstrn(buf, n);
+
+       return n;
+}
+
+int
+fprint(int fd, char *fmt, ...)
+{
+       int n;
+       va_list arg;
+       char buf[PRINTSIZE];
+
+       va_start(arg, fmt);
+       n = vseprintf(buf, buf+sizeof(buf), fmt, arg) - buf;
+       va_end(arg);
+       putstrn(buf, n);
+
+       return n;
+}
+
+int
+kprint(char *fmt, ...)
+{
+       va_list arg;
+       char buf[PRINTSIZE];
+       int n;
+
+       va_start(arg, fmt);
+       n = vseprintf(buf, buf+sizeof(buf), fmt, arg) - buf;
+       va_end(arg);
+       if(qfull(klogq))
+               qflush(klogq);
+       return qproduce(klogq, buf, n);
+}
+
+int
+iprint(char *fmt, ...)
+{
+       int n, s;
+       va_list arg;
+       char buf[PRINTSIZE];
+
+       s = splhi();
+       va_start(arg, fmt);
+       n = vseprintf(buf, buf+sizeof(buf), fmt, arg) - buf;
+       va_end(arg);
+       if(screenputs != NULL && iprintscreenputs)
+               screenputs(buf, n);
+       uartputs(buf, n);
+       splx(s);
+
+       return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+       int n;
+       va_list arg;
+       char buf[PRINTSIZE];
+
+       setpanic();
+       kprintq.q = NULL;
+       strncpy(buf,  "panic: ", sizeof(buf));
+       va_start(arg, fmt);
+       n = vseprintf(buf+strlen(buf), buf+sizeof(buf)-1, fmt, arg) - buf;
+       va_end(arg);
+       buf[n] = '\n';
+       putstrn(buf, n+1);
+       spllo();
+       dumpstack();
+
+       exit(1);
+}
+
+void
+_assert(char *fmt)
+{
+       panic("assert failed: %s", fmt);
+}
+
+/*
+ * mainly for libmp
+ */
+void
+sysfatal(char *fmt, ...)
+{
+       va_list arg;
+       char buf[64];
+
+       va_start(arg, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, arg);
+       va_end(arg);
+       error(buf);
+}
+
+int
+pprint(char *fmt, ...)
+{
+       ERRSTACK(2);
+       int n;
+       struct chan *c;
+       Osenv *o;
+       va_list arg;
+       char buf[2*PRINTSIZE];
+
+       n = sprint(buf, "%s %ld: ", up->text, up->pid);
+       va_start(arg, fmt);
+       n = vseprintf(buf+n, buf+sizeof(buf), fmt, arg) - buf;
+       va_end(arg);
+
+       o = up->env;
+       if(o->fgrp == 0) {
+               printd("%s", buf);
+               return 0;
+       }
+       c = o->fgrp->fd[2];
+       if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) {
+               printd("%s", buf);
+               return 0;
+       }
+
+       if(waserror()) {
+               printd("%s", buf);
+               return 0;
+       }
+       devtab[c->type]->write(c, buf, n, c->offset);
+       poperror();
+
+       spin_lock(&c->lock);
+       c->offset += n;
+       spin_unlock(&c->lock);
+
+       return n;
+}
+
+void
+echo(Rune r, char *buf, int n)
+{
+       if(kbd.raw)
+               return;
+
+       if(r == '\n'){
+               if(printq)
+                       qiwrite(printq, "\r", 1);
+       } else if(r == 0x15){
+               buf = "^U\n";
+               n = 3;
+       }
+       if(consoleprint && screenputs != NULL)
+               screenputs(buf, n);
+       if(printq)
+               qiwrite(printq, buf, n);
+}
+#endif
+#if 0
+/*
+ *     Debug key support.  Allows other parts of the kernel to register debug
+ *     key handlers, instead of devcons.c having to know whatever's out there.
+ *     A kproc is used to invoke most handlers, rather than tying up the CPU at
+ *     splhi, which can choke some device drivers (eg softmodem).
+ */
+typedef struct {
+       Rune    r;
+       char    *m;
+       void    (*f)(Rune);
+       int     i;      /* function called at interrupt time */
+} Dbgkey;
+
+static struct {
+       Rendez;
+       Dbgkey  *work;
+       Dbgkey  keys[50];
+       int     nkeys;
+       int     on;
+} dbg;
+
+static Dbgkey *
+finddbgkey(Rune r)
+{
+       int i;
+       Dbgkey *dp;
+
+       for(dp = dbg.keys, i = 0; i < dbg.nkeys; i++, dp++)
+               if(dp->r == r)
+                       return dp;
+       return NULL;
+}
+
+static int
+dbgwork(void *)
+{
+       return dbg.work != 0;
+}
+
+static void
+dbgproc(void *)
+{
+       Dbgkey *dp;
+
+       setpri(PriRealtime);
+       for(;;) {
+               do {
+                       rendez_sleep(&dbg, dbgwork, 0);
+                       dp = dbg.work;
+               } while(dp == NULL);
+               dp->f(dp->r);
+               dbg.work = NULL;
+       }
+}
+
+void
+debugkey(Rune r, char *msg, void (*fcn)(), int iflag)
+{
+       Dbgkey *dp;
+
+       if(dbg.nkeys >= ARRAY_SIZE(dbg.keys))
+               return;
+       if(finddbgkey(r) != NULL)
+               return;
+       for(dp = &dbg.keys[dbg.nkeys++] - 1; dp >= dbg.keys; dp--) {
+               if(strcmp(dp->m, msg) < 0)
+                       break;
+               dp[1] = dp[0];
+       }
+       dp++;
+       dp->r = r;
+       dp->m = msg;
+       dp->f = fcn;
+       dp->i = iflag;
+}
+
+static int
+isdbgkey(Rune r)
+{
+       static int ctrlt;
+       Dbgkey *dp;
+       int echoctrlt = ctrlt;
+
+       /*
+        * ^t hack BUG
+        */
+       if(dbg.on || (ctrlt >= 2)) {
+               if(r == 0x14 || r == 0x05) {
+                       ctrlt++;
+                       return 0;
+               }
+               if(dp = finddbgkey(r)) {
+                       if(dp->i || ctrlt > 2)
+                               dp->f(r);
+                       else {
+                               dbg.work = dp;
+                               rendez_wakeup(&dbg);
+                       }
+                       ctrlt = 0;
+                       return 1;
+               }
+               ctrlt = 0;
+       }
+       else if(r == 0x14){
+               ctrlt++;
+               return 1;
+       }
+       else
+               ctrlt = 0;
+       if(echoctrlt){
+               char buf[3];
+
+               buf[0] = 0x14;
+               while(--echoctrlt >= 0){
+                       echo(buf[0], buf, 1);
+                       qproduce(kbdq, buf, 1);
+               }
+       }
+       return 0;
+}
+
+static void
+dbgtoggle(Rune)
+{
+       dbg.on = !dbg.on;
+       printd("Debug keys %s\n", dbg.on ? "HOT" : "COLD");
+}
+
+static void
+dbghelp(void)
+{
+       int i;
+       Dbgkey *dp;
+       Dbgkey *dp2;
+       static char fmt[] = "%c: %-22s";
+
+       dp = dbg.keys;
+       dp2 = dp + (dbg.nkeys + 1)/2;
+       for(i = dbg.nkeys; i > 1; i -= 2, dp++, dp2++) {
+               printd(fmt, dp->r, dp->m);
+               printd(fmt, dp2->r, dp2->m);
+               printd("\n");
+       }
+       if(i)
+               printd(fmt, dp->r, dp->m);
+       printd("\n");
+}
+
+static void
+debuginit(void)
+{
+       ktask("consdbg", dbgproc, NULL);
+       debugkey('|', "HOT|COLD keys", dbgtoggle, 0);
+       debugkey('?', "help", dbghelp, 0);
+}
+#endif
+#if 0
+/*
+ *  Called by a uart interrupt for console input.
+ *
+ *  turn '\r' into '\n' before putting it into the queue.
+ */
+int
+kbdcr2nl(struct queue *q, int ch)
+{
+       if(ch == '\r')
+               ch = '\n';
+       return kbdputc(q, ch);
+}
+
+/*
+ *  Put character, possibly a rune, into read queue at interrupt time.
+ *  Performs translation for compose sequences
+ *  Called at interrupt time to process a character.
+ */
+int
+kbdputc(struct queue *q, int ch)
+{
+       int n;
+       char buf[3];
+       Rune r;
+       static Rune kc[15];
+       static int nk, collecting = 0;
+
+       r = ch;
+       if(r == Latin) {
+               collecting = 1;
+               nk = 0;
+               return 0;
+       }
+       if(collecting) {
+               int c;
+               nk += runetochar(( char *unused_char_p_t)&kc[nk], &r);
+               c = latin1(kc, nk);
+               if(c < -1)      /* need more keystrokes */
+                       return 0;
+               collecting = 0;
+               if(c == -1) {   /* invalid sequence */
+                       echo(kc[0], ( char *unused_char_p_t)kc, nk);
+                       qproduce(q, kc, nk);
+                       return 0;
+               }
+               r = (Rune)c;
+       }
+       kbd.c = r;
+       n = runetochar(buf, &r);
+       if(n == 0)
+               return 0;
+       if(!isdbgkey(r)) {
+               echo(r, buf, n);
+               qproduce(q, buf, n);
+       }
+       return 0;
+}
+
+void
+kbdrepeat(int rep)
+{
+       kbd.repeat = rep;
+       kbd.count = 0;
+}
+
+void
+kbdclock(void)
+{
+       if(kbd.repeat == 0)
+               return;
+       if(kbd.repeat==1 && ++kbd.count>HZ){
+               kbd.repeat = 2;
+               kbd.count = 0;
+               return;
+       }
+       if(++kbd.count&1)
+               kbdputc(kbdq, kbd.c);
+}
+#endif
+
+enum{
+       Qdir,
+       Qcons,
+       Qsysctl,
+       Qconsctl,
+       Qdrivers,
+       Qhostowner,
+       Qkeyboard,
+       Qklog,
+       Qkprint,
+       Qscancode,
+       Qmemory,
+       Qmsec,
+       Qnull,
+       Qrandom,
+       Qnotquiterandom,
+       Qsysname,
+       Qtime,
+       Quser,
+       Qjit,
+};
+
+static struct dirtab consdir[]=
+{
+       {".",   {Qdir, 0, QTDIR},       0,              DMDIR|0555},
+       {"cons",                {Qcons},        0,              0660},
+       {"consctl",     {Qconsctl},     0,              0220},
+       {"sysctl",      {Qsysctl},      0,              0644},
+       {"drivers",     {Qdrivers},     0,              0444},
+       {"hostowner",   {Qhostowner},   0,      0644},
+       {"keyboard",    {Qkeyboard},    0,              0666},
+       {"klog",                {Qklog},        0,              0444},
+       {"kprint",              {Qkprint},      0,              0444},
+       {"scancode",    {Qscancode},    0,              0444},
+       {"memory",      {Qmemory},      0,              0444},
+       {"msec",                {Qmsec},        NUMSIZE,        0444},
+       {"null",                {Qnull},        0,              0666},
+       {"random",      {Qrandom},      0,              0444},
+       {"notquiterandom", {Qnotquiterandom}, 0,        0444},
+       {"sysname",     {Qsysname},     0,              0664},
+       {"time",                {Qtime},        0,              0664},
+       {"user",                {Quser},        0,      0644},
+       {"jit",         {Qjit}, 0,      0666},
+};
+
+uint32_t       boottime;               /* seconds since epoch at boot */
+
+#if 0
+void
+fddump()
+{
+       struct proc *p;
+       Osenv *o;
+       int i;
+       struct chan *c;
+
+       p = proctab(6);
+       o = p->env;
+       for(i = 0; i <= o->fgrp->maxfd; i++) {
+               if((c = o->fgrp->fd[i]) == NULL)
+                       continue;
+               printd("%d: %s\n", i, c->name == NULL? "???": c->name->s);
+       }
+}
+#endif
+
+static void
+consinit(void)
+{
+       randominit();
+#if 0
+       debuginit();
+       debugkey('f', "files/6", fddump, 0);
+       debugkey('q', "panic", qpanic, 1);
+       debugkey('r', "exit", rexit, 1);
+       klogq = qopen(128*1024, 0, 0, 0);
+#endif
+}
+
+static struct chan*
+consattach(char *spec)
+{
+       return devattach('c', spec);
+}
+
+static struct walkqid*
+conswalk(struct chan *c, struct chan *nc, char **name, int nname)
+{
+       return devwalk(c, nc, name, nname, consdir, ARRAY_SIZE(consdir), devgen);
+}
+
+static int
+consstat(struct chan *c, uint8_t *dp, int n)
+{
+       return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen);
+}
+
+#if 0
+static void
+flushkbdline(struct queue *q)
+{
+       if(kbd.x){
+               qwrite(q, kbd.line, kbd.x);
+               kbd.x = 0;
+       }
+}
+#endif
+
+static struct chan*
+consopen(struct chan *c, int omode)
+{
+       c->aux = 0;
+#if 0
+       switch((uint32_t)c->qid.path){
+       case Qconsctl:
+               if(!iseve())
+                       error(Eperm);
+               qlock(&(&kbd)->qlock);
+               kbd.ctl++;
+               qunlock(&(&kbd)->qlock);
+               break;
+
+       case Qkeyboard:
+               if((omode & 3) != OWRITE) {
+                       qlock(&(&kbd)->qlock);
+                       kbd.kbdr++;
+                       flushkbdline(kbdq);
+                       kbd.raw = 1;
+                       qunlock(&(&kbd)->qlock);
+               }
+               break;
+
+       case Qscancode:
+               qlock(&(&kbd)->qlock);
+               if(kscanq || !kscanid) {
+                       qunlock(&(&kbd)->qlock);
+                       c->flag &= ~COPEN;
+                       if(kscanq)
+                               error(Einuse);
+                       else
+                               error(Ebadarg);
+               }
+               kscanq = qopen(256, 0, NULL, NULL);
+               qunlock(&(&kbd)->qlock);
+               break;
+
+       case Qkprint:
+               if((omode & 3) != OWRITE) {
+                       wlock(&(&kprintq)->rwlock);
+                       if(kprintq.q != NULL){
+                               wunlock(&(&kprintq)->rwlock);
+                               error(Einuse);
+                       }
+                       kprintq.q = qopen(32*1024, Qcoalesce, NULL, NULL);
+                       if(kprintq.q == NULL){
+                               wunlock(&(&kprintq)->rwlock);
+                               error(Enomem);
+                       }
+                       qnoblock(kprintq.q, 1);
+                       wunlock(&(&kprintq)->rwlock);
+                       c->iounit = qiomaxatomic;
+               }
+               break;
+       }
+#endif
+       return devopen(c, omode, consdir, ARRAY_SIZE(consdir), devgen);
+}
+
+static void
+consclose(struct chan *c)
+{
+       if((c->flag&COPEN) == 0)
+               return;
+
+       switch((uint32_t)c->qid.path){
+#if 0
+       case Qconsctl:
+               /* last close of control file turns off raw */
+               qlock(&(&kbd)->qlock);
+               if(--kbd.ctl == 0)
+                       kbd.raw = 0;
+               qunlock(&(&kbd)->qlock);
+               break;
+
+       case Qkeyboard:
+               if(c->mode != OWRITE) {
+                       qlock(&(&kbd)->qlock);
+                       --kbd.kbdr;
+                       qunlock(&(&kbd)->qlock);
+               }
+               break;
+
+       case Qscancode:
+               qlock(&(&kbd)->qlock);
+               if(kscanq) {
+                       qfree(kscanq);
+                       kscanq = 0;
+               }
+               qunlock(&(&kbd)->qlock);
+               break;
+
+       case Qkprint:
+               wlock(&(&kprintq)->rwlock);
+               qfree(kprintq.q);
+               kprintq.q = NULL;
+               wunlock(&(&kprintq)->rwlock);
+               break;
+#endif
+       default: 
+               break;
+       }
+}
+
+static long
+consread(struct chan *c, void *buf, long n, int64_t offset)
+{
+       ERRSTACK(2);
+       int l;
+
+       int ch, eol, i;
+       char *p, tmp[128];
+       char *cbuf = buf;
+
+       if(n <= 0)
+               return n;
+
+       switch((uint32_t)c->qid.path){
+       case Qdir:
+               return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen);
+       case Qsysctl:
+               return readstr(offset, buf, n, "akaros");
+#if 0
+       case Qcons:
+       case Qkeyboard:
+               qlock(&(&kbd)->qlock);
+               if(waserror()) {
+                       qunlock(&(&kbd)->qlock);
+                       nexterror();
+               }
+               if(kbd.raw || kbd.kbdr) {
+                       if(qcanread(lineq))
+                               n = qread(lineq, buf, n);
+                       else {
+                               /* read as much as possible */
+                               do {
+                                       i = qread(kbdq, cbuf, n);
+                                       cbuf += i;
+                                       n -= i;
+                               } while(n>0 && qcanread(kbdq));
+                               n = cbuf - ( char *unused_char_p_t)buf;
+                       }
+               } else {
+                       while(!qcanread(lineq)) {
+                               qread(kbdq, &kbd.line[kbd.x], 1);
+                               ch = kbd.line[kbd.x];
+                               eol = 0;
+                               switch(ch){
+                               case '\b':
+                                       if(kbd.x)
+                                               kbd.x--;
+                                       break;
+                               case 0x15:
+                                       kbd.x = 0;
+                                       break;
+                               case '\n':
+                               case 0x04:
+                                       eol = 1;
+                               default:
+                                       kbd.line[kbd.x++] = ch;
+                                       break;
+                               }
+                               if(kbd.x == sizeof(kbd.line) || eol) {
+                                       if(ch == 0x04)
+                                               kbd.x--;
+                                       qwrite(lineq, kbd.line, kbd.x);
+                                       kbd.x = 0;
+                               }
+                       }
+                       n = qread(lineq, buf, n);
+               }
+               qunlock(&(&kbd)->qlock);
+               poperror();
+               return n;
+
+       case Qscancode:
+               if(offset == 0)
+                       return readstr(0, buf, n, kscanid);
+               else
+                       return qread(kscanq, buf, n);
+
+       case Qtime:
+               snprintf(tmp, sizeof(tmp), "%.lld", (int64_t)mseconds()*1000);
+               return readstr(offset, buf, n, tmp);
+
+       case Qhostowner:
+               return readstr(offset, buf, n, eve);
+
+       case Quser:
+               return readstr(offset, buf, n, o->user);
+
+       case Qjit:
+               snprintf(tmp, sizeof(tmp), "%d", cflag);
+               return readstr(offset, buf, n, tmp);
+#endif
+       case Qnull:
+               return 0;
+#if 0
+       case Qmsec:
+               return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
+#endif
+       case Qsysname:
+               if(sysname == NULL)
+                       return 0;
+               return readstr(offset, buf, n, "Windows 95");
+
+/* not in akaros, inferno was a special case. 
+       case Qnotquiterandom:
+               genrandom(buf, n);
+               return n;
+*/
+
+       case Qrandom:
+               return randomread(buf, n);
+#if 0
+       case Qmemory:
+               return poolread(buf, n, offset);
+#endif
+       case Qdrivers:
+               p = kzmalloc(READSTR, 0);
+               if(p == NULL)
+                       error(Enomem);
+               l = 0;
+               for(i = 0; devtab[i] != NULL; i++)
+                       l += snprintf(p+l, READSTR-l, "#%C %s\n", devtab[i]->dc,  devtab[i]->name);
+               if(waserror()){
+                       kfree(p);
+                       nexterror();
+               }
+               n = readstr(offset, buf, n, p);
+               kfree(p);
+               poperror();
+               return n;
+#if 0
+       case Qklog:
+               return qread(klogq, buf, n);
+
+       case Qkprint:
+               rlock(&(&kprintq)->rwlock);
+               if(waserror()){
+                       runlock(&(&kprintq)->rwlock);
+                       nexterror();
+               }
+               n = qread(kprintq.q, buf, n);
+               poperror();
+               runlock(&(&kprintq)->rwlock);
+               return n;
+#endif
+       default:
+               printd("consread %llud\n", c->qid.path);
+               error(Egreg);
+       }
+       return -1;              /* never reached */
+}
+
+static long
+conswrite(struct chan *c, void *va, long n, int64_t offset)
+{
+       int64_t t;
+       long l, bp;
+       char *a = va;
+       struct cmdbuf *cb;
+       struct cmdtab *ct;
+       char buf[256];
+       int x;
+
+       switch((uint32_t)c->qid.path){
+#if 0
+       case Qcons:
+               /*
+                * Can't page fault in putstrn, so copy the data locally.
+                */
+               l = n;
+               while(l > 0){
+                       bp = l;
+                       if(bp > sizeof buf)
+                               bp = sizeof buf;
+                       memmove(buf, a, bp);
+                       putstrn0(a, bp, 1);
+                       a += bp;
+                       l -= bp;
+               }
+               break;
+
+       case Qconsctl:
+               if(n >= sizeof(buf))
+                       n = sizeof(buf)-1;
+               strncpy(buf, a, n);
+               buf[n] = 0;
+               for(a = buf; a;){
+                       if(strncmp(a, "rawon", 5) == 0){
+                               qlock(&(&kbd)->qlock);
+                               flushkbdline(kbdq);
+                               kbd.raw = 1;
+                               qunlock(&(&kbd)->qlock);
+                       } else if(strncmp(a, "rawoff", 6) == 0){
+                               qlock(&(&kbd)->qlock);
+                               kbd.raw = 0;
+                               kbd.x = 0;
+                               qunlock(&(&kbd)->qlock);
+                       }
+                       if(a = strchr(a, ' '))
+                               a++;
+               }
+               break;
+
+       case Qkeyboard:
+               for(x=0; x<n; ) {
+                       Rune r;
+                       x += chartorune(&r, &a[x]);
+                       kbdputc(kbdq, r);
+               }
+               break;
+       
+       case Qtime:
+               if(n >= sizeof(buf))
+                       n = sizeof(buf)-1;
+               strncpy(buf, a, n);
+               buf[n] = 0;
+               t = strtoll(buf, 0, 0)/1000000;
+               boottime = t - TK2SEC(MACHP(0)->ticks);
+               break;
+
+       case Qhostowner:
+               if(!iseve())
+                       error(Eperm);
+               if(offset != 0 || n >= sizeof(buf))
+                       error(Ebadarg);
+               memmove(buf, a, n);
+               buf[n] = '\0';
+               if(n > 0 && buf[n-1] == '\n')
+                       buf[--n] = 0;
+               if(n <= 0)
+                       error(Ebadarg);
+               renameuser(eve, buf);
+               renameproguser(eve, buf);
+               kstrdup(&eve, buf);
+               kstrdup(&up->env->user, buf);
+               break;
+
+       case Quser:
+               if(!iseve())
+                       error(Eperm);
+               if(offset != 0)
+                       error(Ebadarg);
+               if(n <= 0 || n >= sizeof(buf))
+                       error(Ebadarg);
+               strncpy(buf, a, n);
+               buf[n] = 0;
+               if(buf[n-1] == '\n')
+                       buf[n-1] = 0;
+               kstrdup(&up->env->user, buf);
+               break;
+
+       case Qjit:
+               if(n >= sizeof(buf))
+                       n = sizeof(buf)-1;
+               strncpy(buf, va, n);
+               buf[n] = '\0';
+               x = atoi(buf);
+               if(x < 0 || x > 9)
+                       error(Ebadarg);
+               cflag = x;
+               return n;
+
+       case Qnull:
+               break;
+
+       case Qsysname:
+               if(offset != 0)
+                       error(Ebadarg);
+               if(n <= 0 || n >= sizeof(buf))
+                       error(Ebadarg);
+               strncpy(buf, a, n);
+               buf[n] = 0;
+               if(buf[n-1] == '\n')
+                       buf[n-1] = 0;
+               kstrdup(&sysname, buf);
+               break;
+
+       case Qsysctl:
+               if(!iseve())
+                       error(Eperm);
+               cb = parsecmd(a, n);
+               if(waserror()){
+                       kfree(cb);
+                       nexterror();
+               }
+               ct = lookupcmd(cb, sysctlcmd, ARRAY_SIZE(sysctlcmd));
+               switch(ct->index){
+               case CMreboot:
+                       reboot();
+                       break;
+               case CMhalt:
+                       halt();
+                       break;
+               case CMpanic:
+                       panic("sysctl");
+               case CMconsole:
+                       consoleprint = strcmp(cb->f[1], "off") != 0;
+                       break;
+               case CMbroken:
+                       keepbroken = 1;
+                       break;
+               case CMnobroken:
+                       keepbroken = 0;
+                       break;
+               }
+               poperror();
+               kfree(cb);
+               break;
+#endif
+       default:
+               printd("conswrite: %llud\n", c->qid.path);
+               error(Egreg);
+       }
+       return n;
+}
+
+struct dev consdevtab = {
+       'c',
+       "cons",
+
+       devreset,
+       consinit,
+       devshutdown,
+       consattach,
+       conswalk,
+       consstat,
+       consopen,
+       devcreate,
+       consclose,
+       consread,
+       devbread,
+       conswrite,
+       devbwrite,
+       devremove,
+       devwstat,
+};
+
+static uint32_t        randn;
+
+static void
+seedrand(void)
+{
+       randomread((void*)&randn, sizeof(randn));
+}
+
+int
+nrand(int n)
+{
+       if(randn == 0)
+               seedrand();
+       randn = randn*1103515245 + 12345 + read_tsc();
+       return (randn>>16) % n;
+}
+
+int
+rand(void)
+{
+       nrand(1);
+       return randn;
+}
+
+uint32_t
+truerand(void)
+{
+       uint32_t x;
+
+       randomread(&x, sizeof(x));
+       return x;
+}
+
+qlock_t grandomlk;
+
+void
+_genrandomqlock(void)
+{
+       qlock(&grandomlk);
+}
+
+
+void
+_genrandomqunlock(void)
+{
+       qunlock(&grandomlk);
+}
index 590a8e6..eb03299 100644 (file)
@@ -14,6 +14,7 @@
 #include <ip.h>
 
 extern uint32_t        kerndate;
+extern char *eve;
 
 void
 mkqid(struct qid *q, int64_t path, uint32_t vers, int type)
index 5909d5d..2a44f18 100644 (file)
@@ -747,7 +747,6 @@ long                mntversion(struct chan*, char *unused_char_p_t, int unused_int, int);
 void           mountfree(struct mount*);
 void           mousetrack( int unused_int, int, int, int);
 uint64_t               ms2fastticks(uint32_t);
-uint32_t               msize(void*);
 void           mul64fract(uint64_t*, uint64_t, uint64_t);
 void           muxclose(struct mnt*);
 struct chan*           namec( char *unused_char_p_t, int unused_int, int, uint32_t);
@@ -822,8 +821,6 @@ void                renameproguser( char *unused_char_p_t, char*);
 void           renameuser( char *unused_char_p_t, char*);
 void           resrcwait( char *unused_char_p_t);
 struct proc*           runproc(void);
-void           sched(void);
-void           schedinit(void);
 long           seconds(void);
 void           (*serwrite)( char *unused_char_p_t, int);
 int            setcolor(uint32_t, uint32_t, uint32_t, uint32_t);
@@ -954,7 +951,6 @@ void errpop(struct errbuf *errstack, int stacksize, int *curindex,
 char *get_cur_genbuf(void);
 
 /* hack for now. */
-#define eve "eve"
 #define        NOW     tsc2msec(read_tsc())
 #define        seconds() tsc2sec(read_tsc())
 
@@ -1003,10 +999,7 @@ int sysdirfwstat(int fd, struct dir *dir);
 long sysdirread(int fd, struct dir **d);
 int sysiounit(int fd);
 
-static inline int iseve(void)
-{
-       return 1;
-}
+int iseve(void);
 
 static inline int abs(int a)
 {
@@ -1015,4 +1008,5 @@ static inline int abs(int a)
        return a;
 }
 
+extern char *eve;
 #endif /* ROS_KERN_NS_H */
index 933c00c..d76a990 100644 (file)
@@ -64,6 +64,7 @@ struct queue  *qlog;
 
 extern void nullmediumlink(void);
 extern void pktmediumlink(void);
+extern char *eve;
 static long ndbwrite(struct Fs*, char *unused_char_p_t, uint32_t, int);
 static void    closeconv(struct conv*);
 
index b825ca7..8dddda4 100644 (file)
 #include <cpio.h>
 #include <pmap.h>
 #include <smp.h>
+#include <ip.h>
 
 /* normally automatically generated on plan 9. Move to ldscripts soon. */
-extern void tcpinit(struct fs*);
-extern void udpinit(struct fs*);
-extern void ipifcinit(struct fs*);
-extern void icmpinit(struct fs*);
-extern void icmp6init(struct fs*);
-void (*ipprotoinit[])(struct fs*) = {
+extern void tcpinit(struct Fs*);
+extern void udpinit(struct Fs*);
+extern void ipifcinit(struct Fs*);
+extern void icmpinit(struct Fs*);
+extern void icmp6init(struct Fs*);
+void (*ipprotoinit[])(struct Fs*) = {
        tcpinit,
        udpinit,
        ipifcinit,
index 0860097..56e46db 100644 (file)
@@ -2627,7 +2627,7 @@ tcpoutput(struct conv *s)
                }
                if((msgs%4) == 1){
                        qunlock(&s->qlock);
-                       sched();
+                       kthread_yield();
                        qlock(&s->qlock);
                }
        }
index 068f05d..52047c2 100644 (file)
@@ -48,7 +48,12 @@ struct block *_allocb(int size)
        addr = (uintptr_t)b;
        addr = ROUNDUP(addr + sizeof(struct block), BLOCKALIGN);
        b->base = (uint8_t*)addr;
+       /* interesting. We can ask the allocator, after allocating,
+        * the *real* size of the block we got. Very nice.
+        * Not on akaros yet.
        b->lim = ((uint8_t*)b) + msize(b);
+        */
+       b->lim = ((uint8_t*)b) + sizeof(struct block) + size + Hdrspc + (BLOCKALIGN - 1);
        b->rp = b->base;
        n = b->lim - b->base - size;
        b->rp += n & ~(BLOCKALIGN - 1);