Demo code to set up a VMMCP, including #c access
[akaros.git] / kern / drivers / dev / cons.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 extern char *eve;
17 /* much stuff not ready yet. */
18
19 extern int cflag;
20
21 /* this would be good to have; when processes die, keep them around so we can
22  * debug them.
23  */
24 int keepbroken;
25
26 #if 0
27 void (*serwrite) (char *, int);
28
29 struct queue *kscanq;                   /* keyboard raw scancodes (when needed) */
30 char *kscanid;                                  /* name of raw scan format (if defined) */
31 struct queue *kbdq;                             /* unprocessed console input */
32 struct queue *lineq;                    /* processed console input */
33 struct queue *printq;                   /* console output */
34 struct queue *klogq;                    /* kernel print (log) output */
35 int iprintscreenputs;
36
37 static struct {
38         rwlock_t rwlock;
39         Queue *q;
40 } kprintq;
41
42 static struct {
43         qlock_t qlock;
44
45         int raw;                                        /* true if we shouldn't process input */
46         int ctl;                                        /* number of opens to the control file */
47         int kbdr;                                       /* number of open reads to the keyboard */
48         int scan;                                       /* true if reading raw scancodes */
49         int x;                                          /* index into line */
50         char line[1024];                        /* current input line */
51
52         char c;
53         int count;
54         int repeat;
55 } kbd;
56
57 #endif
58 char *sysname = "Your machine";
59 char *eve = "eve";
60
61 enum {
62         CMreboot,
63         CMhalt,
64         CMpanic,
65         CMbroken,
66         CMnobroken,
67         CMconsole,
68         CMV,
69 };
70
71 static struct cmdtab sysctlcmd[] = {
72         {CMreboot, "reboot", 0},
73         {CMhalt, "halt", 0},
74         {CMpanic, "panic", 0},
75         {CMconsole, "console", 1},
76         {CMbroken, "broken", 0},
77         {CMnobroken, "nobroken", 0},
78         {CMV, "V", 4},
79 };
80
81 void printinit(void)
82 {
83 #if 0
84         lineq = qopen(2 * 1024, 0, NULL, NULL);
85         if (lineq == NULL)
86                 panic("printinit");
87         qnoblock(lineq, 1);
88 #endif
89 }
90
91 /*
92  *  return true if current user is eve
93  */
94 int iseve(void)
95 {
96 #if 0
97         Osenv *o;
98
99         o = up->env;
100         return strcmp(eve, o->user) == 0;
101 #endif
102         return 1;
103 }
104
105 #if 0
106 static int consactive(void)
107 {
108         if (printq)
109                 return qlen(printq) > 0;
110         return 0;
111 }
112
113 static void prflush(void)
114 {
115         uint32_t now;
116
117         now = m->ticks;
118         while (serwrite == NULL && consactive())
119                 if (m->ticks - now >= HZ)
120                         break;
121 }
122
123 /*
124  *   Print a string on the console.  Convert \n to \r\n for serial
125  *   line consoles.  Locking of the queues is left up to the screen
126  *   or uart code.  Multi-line messages to serial consoles may get
127  *   interspersed with other messages.
128  */
129 static void putstrn0(char *str, int n, int usewrite)
130 {
131         int m;
132         char *t;
133         char buf[PRINTSIZE + 2];
134         ERRSTACK(1);
135
136         /*
137          *  if kprint is open, put the message there, otherwise
138          *  if there's an attached bit mapped display,
139          *  put the message there.
140          */
141         m = consoleprint;
142         if (canrlock(&(&kprintq)->rwlock)) {
143                 if (kprintq.q != NULL) {
144                         if (waserror()) {
145                                 runlock(&(&kprintq)->rwlock);
146                                 nexterror();
147                         }
148                         if (usewrite)
149                                 qwrite(kprintq.q, str, n);
150                         else
151                                 qiwrite(kprintq.q, str, n);
152                         poperror();
153                         m = 0;
154                 }
155                 runlock(&(&kprintq)->rwlock);
156         }
157         if (m && screenputs != NULL)
158                 screenputs(str, n);
159
160         /*
161          *  if there's a serial line being used as a console,
162          *  put the message there.
163          */
164         if (serwrite != NULL) {
165                 serwrite(str, n);
166                 return;
167         }
168
169         if (printq == 0)
170                 return;
171
172         while (n > 0) {
173                 t = memchr(str, '\n', n);
174                 if (t && !kbd.raw) {
175                         m = t - str;
176                         if (m > sizeof(buf) - 2)
177                                 m = sizeof(buf) - 2;
178                         memmove(buf, str, m);
179                         buf[m] = '\r';
180                         buf[m + 1] = '\n';
181                         if (usewrite)
182                                 qwrite(printq, buf, m + 2);
183                         else
184                                 qiwrite(printq, buf, m + 2);
185                         str = t + 1;
186                         n -= m + 1;
187                 } else {
188                         if (usewrite)
189                                 qwrite(printq, str, n);
190                         else
191                                 qiwrite(printq, str, n);
192                         break;
193                 }
194         }
195 }
196
197 /*
198  * mainly for libmp
199  */
200 void sysfatal(char *fmt, ...)
201 {
202         va_list arg;
203         char buf[64];
204
205         va_start(arg, fmt);
206         vsnprintf(buf, sizeof(buf), fmt, arg);
207         va_end(arg);
208         error(buf);
209 }
210
211 int pprint(char *fmt, ...)
212 {
213         ERRSTACK(1);
214         int n;
215         struct chan *c;
216         Osenv *o;
217         va_list arg;
218         char buf[2 * PRINTSIZE];
219
220         n = sprint(buf, "%s %ld: ", up->text, up->pid);
221         va_start(arg, fmt);
222         n = vseprintf(buf + n, buf + sizeof(buf), fmt, arg) - buf;
223         va_end(arg);
224
225         o = up->env;
226         if (o->fgrp == 0) {
227                 printd("%s", buf);
228                 return 0;
229         }
230         /* TODO: this is probably wrong (VFS hack) */
231         c = o->fgrp->fd[2];
232         if (c == 0 || (c->mode != OWRITE && c->mode != ORDWR)) {
233                 printd("%s", buf);
234                 return 0;
235         }
236
237         if (waserror()) {
238                 printd("%s", buf);
239                 poperror();
240                 return 0;
241         }
242         devtab[c->type].write(c, buf, n, c->offset);
243         poperror();
244
245         spin_lock(&c->lock);
246         c->offset += n;
247         spin_unlock(&c->lock);
248
249         return n;
250 }
251
252 void echo(Rune r, char *buf, int n)
253 {
254         if (kbd.raw)
255                 return;
256
257         if (r == '\n') {
258                 if (printq)
259                         qiwrite(printq, "\r", 1);
260         } else if (r == 0x15) {
261                 buf = "^U\n";
262                 n = 3;
263         }
264         if (consoleprint && screenputs != NULL)
265                 screenputs(buf, n);
266         if (printq)
267                 qiwrite(printq, buf, n);
268 }
269 #endif
270 #if 0
271 /*
272  *      Debug key support.  Allows other parts of the kernel to register debug
273  *      key handlers, instead of devcons.c having to know whatever's out there.
274  *      A kproc is used to invoke most handlers, rather than tying up the CPU at
275  *      splhi, which can choke some device drivers (eg softmodem).
276  */
277 typedef struct {
278         Rune r;
279         char *m;
280         void (*f) (Rune);
281         int i;                                          /* function called at interrupt time */
282 } Dbgkey;
283
284 static struct {
285         Rendez;
286         Dbgkey *work;
287         Dbgkey keys[50];
288         int nkeys;
289         int on;
290 } dbg;
291
292 static Dbgkey *finddbgkey(Rune r)
293 {
294         int i;
295         Dbgkey *dp;
296
297         for (dp = dbg.keys, i = 0; i < dbg.nkeys; i++, dp++)
298                 if (dp->r == r)
299                         return dp;
300         return NULL;
301 }
302
303 static int dbgwork(void *)
304 {
305         return dbg.work != 0;
306 }
307
308 static void dbgproc(void *)
309 {
310         Dbgkey *dp;
311
312         setpri(PriRealtime);
313         for (;;) {
314                 do {
315                         rendez_sleep(&dbg, dbgwork, 0);
316                         dp = dbg.work;
317                 } while (dp == NULL);
318                 dp->f(dp->r);
319                 dbg.work = NULL;
320         }
321 }
322
323 void debugkey(Rune r, char *msg, void (*fcn) (), int iflag)
324 {
325         Dbgkey *dp;
326
327         if (dbg.nkeys >= ARRAY_SIZE(dbg.keys))
328                 return;
329         if (finddbgkey(r) != NULL)
330                 return;
331         for (dp = &dbg.keys[dbg.nkeys++] - 1; dp >= dbg.keys; dp--) {
332                 if (strcmp(dp->m, msg) < 0)
333                         break;
334                 dp[1] = dp[0];
335         }
336         dp++;
337         dp->r = r;
338         dp->m = msg;
339         dp->f = fcn;
340         dp->i = iflag;
341 }
342
343 static int isdbgkey(Rune r)
344 {
345         static int ctrlt;
346         Dbgkey *dp;
347         int echoctrlt = ctrlt;
348
349         /*
350          * ^t hack BUG
351          */
352         if (dbg.on || (ctrlt >= 2)) {
353                 if (r == 0x14 || r == 0x05) {
354                         ctrlt++;
355                         return 0;
356                 }
357                 if (dp = finddbgkey(r)) {
358                         if (dp->i || ctrlt > 2)
359                                 dp->f(r);
360                         else {
361                                 dbg.work = dp;
362                                 rendez_wakeup(&dbg);
363                         }
364                         ctrlt = 0;
365                         return 1;
366                 }
367                 ctrlt = 0;
368         } else if (r == 0x14) {
369                 ctrlt++;
370                 return 1;
371         } else
372                 ctrlt = 0;
373         if (echoctrlt) {
374                 char buf[3];
375
376                 buf[0] = 0x14;
377                 while (--echoctrlt >= 0) {
378                         echo(buf[0], buf, 1);
379                         qproduce(kbdq, buf, 1);
380                 }
381         }
382         return 0;
383 }
384
385 static void dbgtoggle(Rune)
386 {
387         dbg.on = !dbg.on;
388         printd("Debug keys %s\n", dbg.on ? "HOT" : "COLD");
389 }
390
391 static void dbghelp(void)
392 {
393         int i;
394         Dbgkey *dp;
395         Dbgkey *dp2;
396         static char fmt[] = "%c: %-22s";
397
398         dp = dbg.keys;
399         dp2 = dp + (dbg.nkeys + 1) / 2;
400         for (i = dbg.nkeys; i > 1; i -= 2, dp++, dp2++) {
401                 printd(fmt, dp->r, dp->m);
402                 printd(fmt, dp2->r, dp2->m);
403                 printd("\n");
404         }
405         if (i)
406                 printd(fmt, dp->r, dp->m);
407         printd("\n");
408 }
409
410 static void debuginit(void)
411 {
412         ktask("consdbg", dbgproc, NULL);
413         debugkey('|', "HOT|COLD keys", dbgtoggle, 0);
414         debugkey('?', "help", dbghelp, 0);
415 }
416 #endif
417 #if 0
418 /*
419  *  Called by a uart interrupt for console input.
420  *
421  *  turn '\r' into '\n' before putting it into the queue.
422  */
423 int kbdcr2nl(struct queue *q, int ch)
424 {
425         if (ch == '\r')
426                 ch = '\n';
427         return kbdputc(q, ch);
428 }
429
430 /*
431  *  Put character, possibly a rune, into read queue at interrupt time.
432  *  Performs translation for compose sequences
433  *  Called at interrupt time to process a character.
434  */
435 int kbdputc(struct queue *q, int ch)
436 {
437         int n;
438         char buf[3];
439         Rune r;
440         static Rune kc[15];
441         static int nk, collecting = 0;
442
443         r = ch;
444         if (r == Latin) {
445                 collecting = 1;
446                 nk = 0;
447                 return 0;
448         }
449         if (collecting) {
450                 int c;
451                 nk += runetochar((char *unused_char_p_t)&kc[nk], &r);
452                 c = latin1(kc, nk);
453                 if (c < -1)     /* need more keystrokes */
454                         return 0;
455                 collecting = 0;
456                 if (c == -1) {  /* invalid sequence */
457                         echo(kc[0], (char *unused_char_p_t)kc, nk);
458                         qproduce(q, kc, nk);
459                         return 0;
460                 }
461                 r = (Rune) c;
462         }
463         kbd.c = r;
464         n = runetochar(buf, &r);
465         if (n == 0)
466                 return 0;
467         if (!isdbgkey(r)) {
468                 echo(r, buf, n);
469                 qproduce(q, buf, n);
470         }
471         return 0;
472 }
473
474 void kbdrepeat(int rep)
475 {
476         kbd.repeat = rep;
477         kbd.count = 0;
478 }
479
480 void kbdclock(void)
481 {
482         if (kbd.repeat == 0)
483                 return;
484         if (kbd.repeat == 1 && ++kbd.count > HZ) {
485                 kbd.repeat = 2;
486                 kbd.count = 0;
487                 return;
488         }
489         if (++kbd.count & 1)
490                 kbdputc(kbdq, kbd.c);
491 }
492 #endif
493
494 enum {
495         Qdir,
496         Qcons,
497         Qsysctl,
498         Qconsctl,
499         Qdrivers,
500         Qhostowner,
501         Qkeyboard,
502         Qklog,
503         Qkprint,
504         Qscancode,
505         Qmemory,
506         Qmsec,
507         Qnull,
508         Qrandom,
509         Qnotquiterandom,
510         Qsysname,
511         Qtime,
512         Quser,
513         Qjit,
514 };
515
516 static struct dirtab consdir[] = {
517         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
518         {"cons", {Qcons}, 0, 0660},
519         {"consctl", {Qconsctl}, 0, 0220},
520         {"sysctl", {Qsysctl}, 0, 0666},
521         {"drivers", {Qdrivers}, 0, 0444},
522         {"hostowner", {Qhostowner}, 0, 0644},
523         {"keyboard", {Qkeyboard}, 0, 0666},
524         {"klog", {Qklog}, 0, 0444},
525         {"kprint", {Qkprint}, 0, 0444},
526         {"scancode", {Qscancode}, 0, 0444},
527         {"memory", {Qmemory}, 0, 0444},
528         {"msec", {Qmsec}, NUMSIZE, 0444},
529         {"null", {Qnull}, 0, 0666},
530         {"random", {Qrandom}, 0, 0444},
531         {"notquiterandom", {Qnotquiterandom}, 0, 0444},
532         {"sysname", {Qsysname}, 0, 0664},
533         {"time", {Qtime}, 0, 0664},
534         {"user", {Quser}, 0, 0644},
535         {"jit", {Qjit}, 0, 0666},
536 };
537
538 uint32_t boottime;                              /* seconds since epoch at boot */
539
540 #if 0
541 void fddump()
542 {
543         struct proc *p;
544         Osenv *o;
545         int i;
546         struct chan *c;
547
548         p = proctab(6);
549         o = p->env;
550         for (i = 0; i <= o->fgrp->maxfd; i++) {
551                 if ((c = o->fgrp->fd[i]) == NULL)
552                         continue;
553                 printd("%d: %s\n", i, c->name == NULL ? "???" : c->name->s);
554         }
555 }
556 #endif
557
558 static void consinit(void)
559 {
560         randominit();
561 #if 0
562         debuginit();
563         debugkey('f', "files/6", fddump, 0);
564         debugkey('q', "panic", qpanic, 1);
565         debugkey('r', "exit", rexit, 1);
566         klogq = qopen(128 * 1024, 0, 0, 0);
567 #endif
568 }
569
570 static struct chan *consattach(char *spec)
571 {
572         return devattach('c', spec);
573 }
574
575 static struct walkqid *conswalk(struct chan *c, struct chan *nc, char **name,
576                                                                 int nname)
577 {
578         return devwalk(c, nc, name, nname, consdir, ARRAY_SIZE(consdir), devgen);
579 }
580
581 static int consstat(struct chan *c, uint8_t * dp, int n)
582 {
583         return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen);
584 }
585
586 #if 0
587 static void flushkbdline(struct queue *q)
588 {
589         if (kbd.x) {
590                 qwrite(q, kbd.line, kbd.x);
591                 kbd.x = 0;
592         }
593 }
594 #endif
595
596 static struct chan *consopen(struct chan *c, int omode)
597 {
598         c->aux = 0;
599 #if 0
600         switch ((uint32_t) c->qid.path) {
601                 case Qconsctl:
602                         if (!iseve())
603                                 error(Eperm);
604                         qlock(&(&kbd)->qlock);
605                         kbd.ctl++;
606                         qunlock(&(&kbd)->qlock);
607                         break;
608
609                 case Qkeyboard:
610                         if ((omode & 3) != OWRITE) {
611                                 qlock(&(&kbd)->qlock);
612                                 kbd.kbdr++;
613                                 flushkbdline(kbdq);
614                                 kbd.raw = 1;
615                                 qunlock(&(&kbd)->qlock);
616                         }
617                         break;
618
619                 case Qscancode:
620                         qlock(&(&kbd)->qlock);
621                         if (kscanq || !kscanid) {
622                                 qunlock(&(&kbd)->qlock);
623                                 c->flag &= ~COPEN;
624                                 if (kscanq)
625                                         error(Einuse);
626                                 else
627                                         error(Ebadarg);
628                         }
629                         kscanq = qopen(256, 0, NULL, NULL);
630                         qunlock(&(&kbd)->qlock);
631                         break;
632
633                 case Qkprint:
634                         if ((omode & 3) != OWRITE) {
635                                 wlock(&(&kprintq)->rwlock);
636                                 if (kprintq.q != NULL) {
637                                         wunlock(&(&kprintq)->rwlock);
638                                         error(Einuse);
639                                 }
640                                 kprintq.q = qopen(32 * 1024, Qcoalesce, NULL, NULL);
641                                 if (kprintq.q == NULL) {
642                                         wunlock(&(&kprintq)->rwlock);
643                                         error(Enomem);
644                                 }
645                                 qnoblock(kprintq.q, 1);
646                                 wunlock(&(&kprintq)->rwlock);
647                                 c->iounit = qiomaxatomic;
648                         }
649                         break;
650         }
651 #endif
652         return devopen(c, omode, consdir, ARRAY_SIZE(consdir), devgen);
653 }
654
655 static void consclose(struct chan *c)
656 {
657         if ((c->flag & COPEN) == 0)
658                 return;
659
660         switch ((uint32_t) c->qid.path) {
661 #if 0
662                 case Qconsctl:
663                         /* last close of control file turns off raw */
664                         qlock(&(&kbd)->qlock);
665                         if (--kbd.ctl == 0)
666                                 kbd.raw = 0;
667                         qunlock(&(&kbd)->qlock);
668                         break;
669
670                 case Qkeyboard:
671                         if (c->mode != OWRITE) {
672                                 qlock(&(&kbd)->qlock);
673                                 --kbd.kbdr;
674                                 qunlock(&(&kbd)->qlock);
675                         }
676                         break;
677
678                 case Qscancode:
679                         qlock(&(&kbd)->qlock);
680                         if (kscanq) {
681                                 qfree(kscanq);
682                                 kscanq = 0;
683                         }
684                         qunlock(&(&kbd)->qlock);
685                         break;
686
687                 case Qkprint:
688                         wlock(&(&kprintq)->rwlock);
689                         qfree(kprintq.q);
690                         kprintq.q = NULL;
691                         wunlock(&(&kprintq)->rwlock);
692                         break;
693 #endif
694                 default:
695                         break;
696         }
697 }
698
699 /* we do it this way to avoid the many fun deadlock opportunities
700  * we keep hitting. And, if you don't suck it
701  * out soon enough, you lost it. No real effort to ensure goodness
702  * here as it can get called anywhere. Barret will fix it.
703  */
704 static uint8_t logbuffer[1 << 20];
705 static int index = 0;
706 static struct queue *logqueue = NULL;
707 static int reading_kmesg = 0;
708 void logbuf(int c)
709 {
710         if (reading_kmesg)
711                 return;
712         if (index > 1 << 20)
713                 return;
714         logbuffer[index++] = c;
715 }
716
717 static long consread(struct chan *c, void *buf, long n, int64_t offset)
718 {
719         ERRSTACK(1);
720         int l;
721
722         int ch, eol, i;
723         char *p, tmp[128];
724         char *cbuf = buf;
725
726         if (n <= 0)
727                 return n;
728
729         switch ((uint32_t) c->qid.path) {
730                 case Qdir:
731                         return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen);
732                 case Qsysctl:
733                         return readstr(offset, buf, n, "akaros");
734 #if 0
735                 case Qcons:
736                 case Qkeyboard:
737                         qlock(&(&kbd)->qlock);
738                         if (waserror()) {
739                                 qunlock(&(&kbd)->qlock);
740                                 nexterror();
741                         }
742                         if (kbd.raw || kbd.kbdr) {
743                                 if (qcanread(lineq))
744                                         n = qread(lineq, buf, n);
745                                 else {
746                                         /* read as much as possible */
747                                         do {
748                                                 i = qread(kbdq, cbuf, n);
749                                                 cbuf += i;
750                                                 n -= i;
751                                         } while (n > 0 && qcanread(kbdq));
752                                         n = cbuf - (char *unused_char_p_t)buf;
753                                 }
754                         } else {
755                                 while (!qcanread(lineq)) {
756                                         qread(kbdq, &kbd.line[kbd.x], 1);
757                                         ch = kbd.line[kbd.x];
758                                         eol = 0;
759                                         switch (ch) {
760                                                 case '\b':
761                                                         if (kbd.x)
762                                                                 kbd.x--;
763                                                         break;
764                                                 case 0x15:
765                                                         kbd.x = 0;
766                                                         break;
767                                                 case '\n':
768                                                 case 0x04:
769                                                         eol = 1;
770                                                 default:
771                                                         kbd.line[kbd.x++] = ch;
772                                                         break;
773                                         }
774                                         if (kbd.x == sizeof(kbd.line) || eol) {
775                                                 if (ch == 0x04)
776                                                         kbd.x--;
777                                                 qwrite(lineq, kbd.line, kbd.x);
778                                                 kbd.x = 0;
779                                         }
780                                 }
781                                 n = qread(lineq, buf, n);
782                         }
783                         qunlock(&(&kbd)->qlock);
784                         poperror();
785                         return n;
786
787                 case Qscancode:
788                         if (offset == 0)
789                                 return readstr(0, buf, n, kscanid);
790                         else
791                                 return qread(kscanq, buf, n);
792
793                 case Qtime:
794                         snprintf(tmp, sizeof(tmp), "%.lld", (int64_t) mseconds() * 1000);
795                         return readstr(offset, buf, n, tmp);
796
797                 case Qhostowner:
798                         return readstr(offset, buf, n, eve);
799
800                 case Quser:
801                         return readstr(offset, buf, n, o->user);
802
803                 case Qjit:
804                         snprintf(tmp, sizeof(tmp), "%d", cflag);
805                         return readstr(offset, buf, n, tmp);
806 #endif
807                 case Qnull:
808                         return 0;
809 #if 0
810                 case Qmsec:
811                         return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
812 #endif
813                 case Qsysname:
814                         if (sysname == NULL)
815                                 return 0;
816                         return readstr(offset, buf, n, "Windows 95");
817
818 /* not in akaros, inferno was a special case. 
819         case Qnotquiterandom:
820                 genrandom(buf, n);
821                 return n;
822 */
823
824                 case Qrandom:
825                         return randomread(buf, n);
826 #if 0
827                 case Qmemory:
828                         return poolread(buf, n, offset);
829 #endif
830                 case Qdrivers:
831                         p = kzmalloc(READSTR, 0);
832                         if (p == NULL)
833                                 error(Enomem);
834                         l = 0;
835                         for (i = 0; &devtab[i] < __devtabend; i++)
836                                 l += snprintf(p + l, READSTR - l, "#%c %s\n", devtab[i].dc,
837                                                           devtab[i].name);
838                         if (waserror()) {
839                                 kfree(p);
840                                 nexterror();
841                         }
842                         n = readstr(offset, buf, n, p);
843                         kfree(p);
844                         poperror();
845                         return n;
846                 case Qklog:
847                         //return qread(klogq, buf, n);  
848                         /* the queue gives us some elasticity for log reading. */
849                         if (!logqueue)
850                                 logqueue = qopen(1 << 20, 0, 0, 0);
851                         if (logqueue) {
852                                 int ret;
853                                 /* atomic sets/gets are not that important in this case. */
854                                 reading_kmesg = 1;
855                                 qwrite(logqueue, logbuffer, index);
856                                 index = 0;
857                                 ret = qread(logqueue, buf, n);
858                                 reading_kmesg = 0;
859                                 return ret;
860                         }
861                         break;
862 #if 0
863                 case Qkprint:
864                         rlock(&(&kprintq)->rwlock);
865                         if (waserror()) {
866                                 runlock(&(&kprintq)->rwlock);
867                                 nexterror();
868                         }
869                         n = qread(kprintq.q, buf, n);
870                         poperror();
871                         runlock(&(&kprintq)->rwlock);
872                         return n;
873 #endif
874                 default:
875                         printd("consread %llu\n", c->qid.path);
876                         error(Egreg);
877         }
878         return -1;      /* never reached */
879 }
880
881 static long conswrite(struct chan *c, void *va, long n, int64_t offset)
882 {
883         ERRSTACK(1);
884         int64_t t;
885         uint64_t ip;
886         long l, bp;
887         char *a = va;
888         struct cmdbuf *cb;
889         struct cmdtab *ct;
890         char buf[256];
891         int x;
892         uint64_t rip, rsp, cr3, flags, vcpu;
893         int ret;
894
895         switch ((uint32_t) c->qid.path) {
896 #if 0
897                 case Qcons:
898                         /*
899                          * Can't page fault in putstrn, so copy the data locally.
900                          */
901                         l = n;
902                         while (l > 0) {
903                                 bp = l;
904                                 if (bp > sizeof buf)
905                                         bp = sizeof buf;
906                                 memmove(buf, a, bp);
907                                 putstrn0(a, bp, 1);
908                                 a += bp;
909                                 l -= bp;
910                         }
911                         break;
912
913                 case Qconsctl:
914                         if (n >= sizeof(buf))
915                                 n = sizeof(buf) - 1;
916                         strncpy(buf, a, n);
917                         buf[n] = 0;
918                         for (a = buf; a;) {
919                                 if (strncmp(a, "rawon", 5) == 0) {
920                                         qlock(&(&kbd)->qlock);
921                                         flushkbdline(kbdq);
922                                         kbd.raw = 1;
923                                         qunlock(&(&kbd)->qlock);
924                                 } else if (strncmp(a, "rawoff", 6) == 0) {
925                                         qlock(&(&kbd)->qlock);
926                                         kbd.raw = 0;
927                                         kbd.x = 0;
928                                         qunlock(&(&kbd)->qlock);
929                                 }
930                                 if (a = strchr(a, ' '))
931                                         a++;
932                         }
933                         break;
934
935                 case Qkeyboard:
936                         for (x = 0; x < n;) {
937                                 Rune r;
938                                 x += chartorune(&r, &a[x]);
939                                 kbdputc(kbdq, r);
940                         }
941                         break;
942
943                 case Qtime:
944                         if (n >= sizeof(buf))
945                                 n = sizeof(buf) - 1;
946                         strncpy(buf, a, n);
947                         buf[n] = 0;
948                         t = strtoll(buf, 0, 0) / 1000000;
949                         boottime = t - TK2SEC(MACHP(0)->ticks);
950                         break;
951
952                 case Qhostowner:
953                         if (!iseve())
954                                 error(Eperm);
955                         if (offset != 0 || n >= sizeof(buf))
956                                 error(Ebadarg);
957                         memmove(buf, a, n);
958                         buf[n] = '\0';
959                         if (n > 0 && buf[n - 1] == '\n')
960                                 buf[--n] = 0;
961                         if (n <= 0)
962                                 error(Ebadarg);
963                         renameuser(eve, buf);
964                         renameproguser(eve, buf);
965                         kstrdup(&eve, buf);
966                         kstrdup(&up->env->user, buf);
967                         break;
968
969                 case Quser:
970                         if (!iseve())
971                                 error(Eperm);
972                         if (offset != 0)
973                                 error(Ebadarg);
974                         if (n <= 0 || n >= sizeof(buf))
975                                 error(Ebadarg);
976                         strncpy(buf, a, n);
977                         buf[n] = 0;
978                         if (buf[n - 1] == '\n')
979                                 buf[n - 1] = 0;
980                         kstrdup(&up->env->user, buf);
981                         break;
982
983                 case Qjit:
984                         if (n >= sizeof(buf))
985                                 n = sizeof(buf) - 1;
986                         strncpy(buf, va, n);
987                         buf[n] = '\0';
988                         x = atoi(buf);
989                         if (x < 0 || x > 9)
990                                 error(Ebadarg);
991                         cflag = x;
992                         return n;
993
994                 case Qnull:
995                         break;
996
997                 case Qsysname:
998                         if (offset != 0)
999                                 error(Ebadarg);
1000                         if (n <= 0 || n >= sizeof(buf))
1001                                 error(Ebadarg);
1002                         strncpy(buf, a, n);
1003                         buf[n] = 0;
1004                         if (buf[n - 1] == '\n')
1005                                 buf[n - 1] = 0;
1006                         kstrdup(&sysname, buf);
1007                         break;
1008 #endif
1009                 case Qsysctl:
1010                         //if (!iseve()) error(Eperm);
1011                         cb = parsecmd(a, n);
1012                         if (cb->nf > 1) 
1013                         printk("cons sysctl cmd %s\n", cb->f[0]);
1014                         if (waserror()) {
1015                                 kfree(cb);
1016                                 nexterror();
1017                         }
1018                         ct = lookupcmd(cb, sysctlcmd, ARRAY_SIZE(sysctlcmd));
1019                         switch (ct->index) {
1020                                 case CMreboot:
1021                                         reboot();
1022                                         break;
1023                                 case CMhalt:
1024                                         cpu_halt();
1025                                         break;
1026                                 case CMpanic:
1027                                         panic("sysctl");
1028                                         //case CMconsole:
1029                                         //consoleprint = strcmp(cb->f[1], "off") != 0;
1030                                         break;
1031                                 case CMbroken:
1032                                         keepbroken = 1;
1033                                         break;
1034                                 case CMnobroken:
1035                                         keepbroken = 0;
1036                                         break;
1037                                 case CMV:
1038                                         rip =  strtoul(cb->f[1], NULL, 0);
1039                                         rsp =  strtoul(cb->f[2], NULL, 0);
1040                                         cr3 =  strtoul(cb->f[3], NULL, 0);
1041                                         disable_irq();
1042                                         ret = vm_run(rip, rsp, cr3);
1043                                         enable_irq();
1044                                         printk("vm_run returns %d\n", ret);
1045                                         return ret;
1046         
1047                                         ip = strtoul(cb->f[1], 0, 0);
1048                                         //                      vm_run(ip);
1049                                         break;
1050                         }
1051                         poperror();
1052                         kfree(cb);
1053                         break;
1054                 default:
1055                         printd("conswrite: %llu\n", c->qid.path);
1056                         error(Egreg);
1057         }
1058         return n;
1059 }
1060
1061 struct dev consdevtab __devtab = {
1062         'c',
1063         "cons",
1064
1065         devreset,
1066         consinit,
1067         devshutdown,
1068         consattach,
1069         conswalk,
1070         consstat,
1071         consopen,
1072         devcreate,
1073         consclose,
1074         consread,
1075         devbread,
1076         conswrite,
1077         devbwrite,
1078         devremove,
1079         devwstat,
1080         devpower,
1081         devchaninfo,
1082 };
1083
1084 static uint32_t randn;
1085
1086 static void seedrand(void)
1087 {
1088         randomread((void *)&randn, sizeof(randn));
1089 }
1090
1091 int nrand(int n)
1092 {
1093         if (randn == 0)
1094                 seedrand();
1095         randn = randn * 1103515245 + 12345 + read_tsc();
1096         return (randn >> 16) % n;
1097 }
1098
1099 int rand(void)
1100 {
1101         nrand(1);
1102         return randn;
1103 }
1104
1105 uint32_t truerand(void)
1106 {
1107         uint32_t x;
1108
1109         randomread(&x, sizeof(x));
1110         return x;
1111 }
1112
1113 /* TODO: qlock_init this, if you ever use this */
1114 qlock_t grandomlk;
1115
1116 void _genrandomqlock(void)
1117 {
1118         qlock(&grandomlk);
1119 }
1120
1121 void _genrandomqunlock(void)
1122 {
1123         qunlock(&grandomlk);
1124 }