13e12c5d1SDavid du Colombier #include "u.h"
23e12c5d1SDavid du Colombier #include "../port/lib.h"
33e12c5d1SDavid du Colombier #include "mem.h"
43e12c5d1SDavid du Colombier #include "dat.h"
53e12c5d1SDavid du Colombier #include "fns.h"
63e12c5d1SDavid du Colombier #include "../port/error.h"
7e059317eSDavid du Colombier #include "pool.h"
83e12c5d1SDavid du Colombier
99a747e4fSDavid du Colombier #include <authsrv.h>
109a747e4fSDavid du Colombier
117dd7cddfSDavid du Colombier void (*consdebug)(void) = nil;
129a747e4fSDavid du Colombier void (*screenputs)(char*, int) = nil;
133e12c5d1SDavid du Colombier
147dd7cddfSDavid du Colombier Queue* kbdq; /* unprocessed console input */
157dd7cddfSDavid du Colombier Queue* lineq; /* processed console input */
169a747e4fSDavid du Colombier Queue* serialoq; /* serial console output */
179a747e4fSDavid du Colombier Queue* kprintoq; /* console output, for /dev/kprint */
189a747e4fSDavid du Colombier ulong kprintinuse; /* test and set whether /dev/kprint is open */
199a747e4fSDavid du Colombier int iprintscreenputs = 1;
203e12c5d1SDavid du Colombier
21d9306527SDavid du Colombier int panicking;
22d9306527SDavid du Colombier
237dd7cddfSDavid du Colombier static struct
247dd7cddfSDavid du Colombier {
257dd7cddfSDavid du Colombier QLock;
263e12c5d1SDavid du Colombier
277dd7cddfSDavid du Colombier int raw; /* true if we shouldn't process input */
2888110b43SDavid du Colombier Ref ctl; /* number of opens to the control file */
297dd7cddfSDavid du Colombier int x; /* index into line */
307dd7cddfSDavid du Colombier char line[1024]; /* current input line */
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier int count;
337dd7cddfSDavid du Colombier int ctlpoff;
3480ee5cbfSDavid du Colombier
3580ee5cbfSDavid du Colombier /* a place to save up characters at interrupt time before dumping them in the queue */
3680ee5cbfSDavid du Colombier Lock lockputc;
37d9306527SDavid du Colombier char istage[1024];
3880ee5cbfSDavid du Colombier char *iw;
3980ee5cbfSDavid du Colombier char *ir;
4080ee5cbfSDavid du Colombier char *ie;
419a747e4fSDavid du Colombier } kbd = {
429a747e4fSDavid du Colombier .iw = kbd.istage,
439a747e4fSDavid du Colombier .ir = kbd.istage,
449a747e4fSDavid du Colombier .ie = kbd.istage + sizeof(kbd.istage),
459a747e4fSDavid du Colombier };
463e12c5d1SDavid du Colombier
479a747e4fSDavid du Colombier char *sysname;
487dd7cddfSDavid du Colombier vlong fasthz;
493e12c5d1SDavid du Colombier
507dd7cddfSDavid du Colombier static void seedrand(void);
517dd7cddfSDavid du Colombier static int readtime(ulong, char*, int);
527dd7cddfSDavid du Colombier static int readbintime(char*, int);
537dd7cddfSDavid du Colombier static int writetime(char*, int);
547dd7cddfSDavid du Colombier static int writebintime(char*, int);
557dd7cddfSDavid du Colombier
569a747e4fSDavid du Colombier enum
579a747e4fSDavid du Colombier {
58e288d156SDavid du Colombier CMhalt,
599a747e4fSDavid du Colombier CMreboot,
609a747e4fSDavid du Colombier CMpanic,
619a747e4fSDavid du Colombier };
629a747e4fSDavid du Colombier
639a747e4fSDavid du Colombier Cmdtab rebootmsg[] =
649a747e4fSDavid du Colombier {
65e288d156SDavid du Colombier CMhalt, "halt", 1,
669a747e4fSDavid du Colombier CMreboot, "reboot", 0,
679a747e4fSDavid du Colombier CMpanic, "panic", 0,
689a747e4fSDavid du Colombier };
699a747e4fSDavid du Colombier
703e12c5d1SDavid du Colombier void
printinit(void)713e12c5d1SDavid du Colombier printinit(void)
723e12c5d1SDavid du Colombier {
733ff48bf5SDavid du Colombier lineq = qopen(2*1024, 0, nil, nil);
747dd7cddfSDavid du Colombier if(lineq == nil)
757dd7cddfSDavid du Colombier panic("printinit");
767dd7cddfSDavid du Colombier qnoblock(lineq, 1);
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier int
consactive(void)807dd7cddfSDavid du Colombier consactive(void)
817dd7cddfSDavid du Colombier {
829a747e4fSDavid du Colombier if(serialoq)
839a747e4fSDavid du Colombier return qlen(serialoq) > 0;
847dd7cddfSDavid du Colombier return 0;
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier void
prflush(void)887dd7cddfSDavid du Colombier prflush(void)
897dd7cddfSDavid du Colombier {
9080ee5cbfSDavid du Colombier ulong now;
9180ee5cbfSDavid du Colombier
9280ee5cbfSDavid du Colombier now = m->ticks;
937dd7cddfSDavid du Colombier while(consactive())
9480ee5cbfSDavid du Colombier if(m->ticks - now >= HZ)
9580ee5cbfSDavid du Colombier break;
963e12c5d1SDavid du Colombier }
973e12c5d1SDavid du Colombier
98fe853e23SDavid du Colombier /*
99fe853e23SDavid du Colombier * Log console output so it can be retrieved via /dev/kmesg.
100fe853e23SDavid du Colombier * This is good for catching boot-time messages after the fact.
101fe853e23SDavid du Colombier */
102f6eb8b35SDavid du Colombier struct {
103f6eb8b35SDavid du Colombier Lock lk;
10485878a71SDavid du Colombier char buf[KMESGSIZE];
105f6eb8b35SDavid du Colombier uint n;
106f6eb8b35SDavid du Colombier } kmesg;
107f6eb8b35SDavid du Colombier
108f6eb8b35SDavid du Colombier static void
kmesgputs(char * str,int n)109f6eb8b35SDavid du Colombier kmesgputs(char *str, int n)
110f6eb8b35SDavid du Colombier {
111f6eb8b35SDavid du Colombier uint nn, d;
112f6eb8b35SDavid du Colombier
113f6eb8b35SDavid du Colombier ilock(&kmesg.lk);
114f6eb8b35SDavid du Colombier /* take the tail of huge writes */
115f6eb8b35SDavid du Colombier if(n > sizeof kmesg.buf){
116f6eb8b35SDavid du Colombier d = n - sizeof kmesg.buf;
117f6eb8b35SDavid du Colombier str += d;
118f6eb8b35SDavid du Colombier n -= d;
119f6eb8b35SDavid du Colombier }
120f6eb8b35SDavid du Colombier
121f6eb8b35SDavid du Colombier /* slide the buffer down to make room */
122f6eb8b35SDavid du Colombier nn = kmesg.n;
123f6eb8b35SDavid du Colombier if(nn + n >= sizeof kmesg.buf){
124f6eb8b35SDavid du Colombier d = nn + n - sizeof kmesg.buf;
125f6eb8b35SDavid du Colombier if(d)
126f6eb8b35SDavid du Colombier memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
127f6eb8b35SDavid du Colombier nn -= d;
128f6eb8b35SDavid du Colombier }
129f6eb8b35SDavid du Colombier
130f6eb8b35SDavid du Colombier /* copy the data in */
131f6eb8b35SDavid du Colombier memmove(kmesg.buf+nn, str, n);
132f6eb8b35SDavid du Colombier nn += n;
133f6eb8b35SDavid du Colombier kmesg.n = nn;
134f6eb8b35SDavid du Colombier iunlock(&kmesg.lk);
135f6eb8b35SDavid du Colombier }
136f6eb8b35SDavid du Colombier
1373e12c5d1SDavid du Colombier /*
1383e12c5d1SDavid du Colombier * Print a string on the console. Convert \n to \r\n for serial
1393e12c5d1SDavid du Colombier * line consoles. Locking of the queues is left up to the screen
1403e12c5d1SDavid du Colombier * or uart code. Multi-line messages to serial consoles may get
1413e12c5d1SDavid du Colombier * interspersed with other messages.
1423e12c5d1SDavid du Colombier */
1437dd7cddfSDavid du Colombier static void
putstrn0(char * str,int n,int usewrite)1447dd7cddfSDavid du Colombier putstrn0(char *str, int n, int usewrite)
1453e12c5d1SDavid du Colombier {
1463e12c5d1SDavid du Colombier int m;
1473e12c5d1SDavid du Colombier char *t;
1483e12c5d1SDavid du Colombier
14988110b43SDavid du Colombier if(!islo())
15088110b43SDavid du Colombier usewrite = 0;
15188110b43SDavid du Colombier
1523e12c5d1SDavid du Colombier /*
153f6eb8b35SDavid du Colombier * how many different output devices do we need?
154f6eb8b35SDavid du Colombier */
155f6eb8b35SDavid du Colombier kmesgputs(str, n);
156f6eb8b35SDavid du Colombier
157f6eb8b35SDavid du Colombier /*
1589a747e4fSDavid du Colombier * if someone is reading /dev/kprint,
1599a747e4fSDavid du Colombier * put the message there.
1609a747e4fSDavid du Colombier * if not and there's an attached bit mapped display,
1619a747e4fSDavid du Colombier * put the message there.
1629a747e4fSDavid du Colombier *
1633e12c5d1SDavid du Colombier * if there's a serial line being used as a console,
1647dd7cddfSDavid du Colombier * put the message there.
1653e12c5d1SDavid du Colombier */
1669a747e4fSDavid du Colombier if(kprintoq != nil && !qisclosed(kprintoq)){
1679a747e4fSDavid du Colombier if(usewrite)
1689a747e4fSDavid du Colombier qwrite(kprintoq, str, n);
1699a747e4fSDavid du Colombier else
1709a747e4fSDavid du Colombier qiwrite(kprintoq, str, n);
1719a747e4fSDavid du Colombier }else if(screenputs != nil)
1729a747e4fSDavid du Colombier screenputs(str, n);
1739a747e4fSDavid du Colombier
1749a747e4fSDavid du Colombier if(serialoq == nil){
1759a747e4fSDavid du Colombier uartputs(str, n);
1763e12c5d1SDavid du Colombier return;
1779a747e4fSDavid du Colombier }
178219b2ee8SDavid du Colombier
1793e12c5d1SDavid du Colombier while(n > 0) {
1803e12c5d1SDavid du Colombier t = memchr(str, '\n', n);
18180ee5cbfSDavid du Colombier if(t && !kbd.raw) {
1823e12c5d1SDavid du Colombier m = t-str;
18380ee5cbfSDavid du Colombier if(usewrite){
1849a747e4fSDavid du Colombier qwrite(serialoq, str, m);
1859a747e4fSDavid du Colombier qwrite(serialoq, "\r\n", 2);
18680ee5cbfSDavid du Colombier } else {
1879a747e4fSDavid du Colombier qiwrite(serialoq, str, m);
1889a747e4fSDavid du Colombier qiwrite(serialoq, "\r\n", 2);
18980ee5cbfSDavid du Colombier }
1903e12c5d1SDavid du Colombier n -= m+1;
19180ee5cbfSDavid du Colombier str = t+1;
1923e12c5d1SDavid du Colombier } else {
1937dd7cddfSDavid du Colombier if(usewrite)
1949a747e4fSDavid du Colombier qwrite(serialoq, str, n);
1957dd7cddfSDavid du Colombier else
1969a747e4fSDavid du Colombier qiwrite(serialoq, str, n);
1973e12c5d1SDavid du Colombier break;
1983e12c5d1SDavid du Colombier }
1993e12c5d1SDavid du Colombier }
2003e12c5d1SDavid du Colombier }
2013e12c5d1SDavid du Colombier
2023e12c5d1SDavid du Colombier void
putstrn(char * str,int n)2037dd7cddfSDavid du Colombier putstrn(char *str, int n)
2043e12c5d1SDavid du Colombier {
2057dd7cddfSDavid du Colombier putstrn0(str, n, 0);
2063e12c5d1SDavid du Colombier }
2073e12c5d1SDavid du Colombier
2087dd7cddfSDavid du Colombier int noprint;
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier int
print(char * fmt,...)2117dd7cddfSDavid du Colombier print(char *fmt, ...)
2127dd7cddfSDavid du Colombier {
2137dd7cddfSDavid du Colombier int n;
2147dd7cddfSDavid du Colombier va_list arg;
2157dd7cddfSDavid du Colombier char buf[PRINTSIZE];
2167dd7cddfSDavid du Colombier
2177dd7cddfSDavid du Colombier if(noprint)
2187dd7cddfSDavid du Colombier return -1;
2197dd7cddfSDavid du Colombier
2207dd7cddfSDavid du Colombier va_start(arg, fmt);
2219a747e4fSDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
2227dd7cddfSDavid du Colombier va_end(arg);
2237dd7cddfSDavid du Colombier putstrn(buf, n);
2247dd7cddfSDavid du Colombier
2257dd7cddfSDavid du Colombier return n;
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier
228ea15f0ccSDavid du Colombier /*
229ea15f0ccSDavid du Colombier * Want to interlock iprints to avoid interlaced output on
230ea15f0ccSDavid du Colombier * multiprocessor, but don't want to deadlock if one processor
231ea15f0ccSDavid du Colombier * dies during print and another has something important to say.
232ea15f0ccSDavid du Colombier * Make a good faith effort.
233ea15f0ccSDavid du Colombier */
234ea15f0ccSDavid du Colombier static Lock iprintlock;
235ea15f0ccSDavid du Colombier static int
iprintcanlock(Lock * l)236ea15f0ccSDavid du Colombier iprintcanlock(Lock *l)
237ea15f0ccSDavid du Colombier {
238ea15f0ccSDavid du Colombier int i;
239ea15f0ccSDavid du Colombier
240ea15f0ccSDavid du Colombier for(i=0; i<1000; i++){
241ea15f0ccSDavid du Colombier if(canlock(l))
242ea15f0ccSDavid du Colombier return 1;
243ea15f0ccSDavid du Colombier if(l->m == MACHP(m->machno))
244ea15f0ccSDavid du Colombier return 0;
245ea15f0ccSDavid du Colombier microdelay(100);
246ea15f0ccSDavid du Colombier }
247ea15f0ccSDavid du Colombier return 0;
248ea15f0ccSDavid du Colombier }
249ea15f0ccSDavid du Colombier
2507dd7cddfSDavid du Colombier int
iprint(char * fmt,...)2517dd7cddfSDavid du Colombier iprint(char *fmt, ...)
2527dd7cddfSDavid du Colombier {
253ea15f0ccSDavid du Colombier int n, s, locked;
2547dd7cddfSDavid du Colombier va_list arg;
2557dd7cddfSDavid du Colombier char buf[PRINTSIZE];
2567dd7cddfSDavid du Colombier
2577dd7cddfSDavid du Colombier s = splhi();
2587dd7cddfSDavid du Colombier va_start(arg, fmt);
2599a747e4fSDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
2607dd7cddfSDavid du Colombier va_end(arg);
261ea15f0ccSDavid du Colombier locked = iprintcanlock(&iprintlock);
2629a747e4fSDavid du Colombier if(screenputs != nil && iprintscreenputs)
2639a747e4fSDavid du Colombier screenputs(buf, n);
2649a747e4fSDavid du Colombier uartputs(buf, n);
265ea15f0ccSDavid du Colombier if(locked)
266ea15f0ccSDavid du Colombier unlock(&iprintlock);
2677dd7cddfSDavid du Colombier splx(s);
2687dd7cddfSDavid du Colombier
2693e12c5d1SDavid du Colombier return n;
2703e12c5d1SDavid du Colombier }
2713e12c5d1SDavid du Colombier
2723e12c5d1SDavid du Colombier void
panic(char * fmt,...)2733e12c5d1SDavid du Colombier panic(char *fmt, ...)
2743e12c5d1SDavid du Colombier {
2755979f962SDavid du Colombier int n, s;
2767dd7cddfSDavid du Colombier va_list arg;
2777dd7cddfSDavid du Colombier char buf[PRINTSIZE];
2789a747e4fSDavid du Colombier
2799a747e4fSDavid du Colombier kprintoq = nil; /* don't try to write to /dev/kprint */
2809a747e4fSDavid du Colombier
2819a747e4fSDavid du Colombier if(panicking)
2829a747e4fSDavid du Colombier for(;;);
2839a747e4fSDavid du Colombier panicking = 1;
2843e12c5d1SDavid du Colombier
2855979f962SDavid du Colombier s = splhi();
2863e12c5d1SDavid du Colombier strcpy(buf, "panic: ");
2877dd7cddfSDavid du Colombier va_start(arg, fmt);
2889a747e4fSDavid du Colombier n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
2897dd7cddfSDavid du Colombier va_end(arg);
2900b9a5132SDavid du Colombier iprint("%s\n", buf);
2917dd7cddfSDavid du Colombier if(consdebug)
2929a747e4fSDavid du Colombier (*consdebug)();
2935979f962SDavid du Colombier splx(s);
2947dd7cddfSDavid du Colombier prflush();
2950b9a5132SDavid du Colombier buf[n] = '\n';
29680ee5cbfSDavid du Colombier putstrn(buf, n+1);
2973e12c5d1SDavid du Colombier dumpstack();
2987dd7cddfSDavid du Colombier
2993e12c5d1SDavid du Colombier exit(1);
3003e12c5d1SDavid du Colombier }
3017dd7cddfSDavid du Colombier
302ea58ad6fSDavid du Colombier /* libmp at least contains a few calls to sysfatal; simulate with panic */
303ea58ad6fSDavid du Colombier void
sysfatal(char * fmt,...)304ea58ad6fSDavid du Colombier sysfatal(char *fmt, ...)
305ea58ad6fSDavid du Colombier {
306ea58ad6fSDavid du Colombier char err[256];
307ea58ad6fSDavid du Colombier va_list arg;
308ea58ad6fSDavid du Colombier
309ea58ad6fSDavid du Colombier va_start(arg, fmt);
310ea58ad6fSDavid du Colombier vseprint(err, err + sizeof err, fmt, arg);
311ea58ad6fSDavid du Colombier va_end(arg);
312ea58ad6fSDavid du Colombier panic("sysfatal: %s", err);
313ea58ad6fSDavid du Colombier }
314ea58ad6fSDavid du Colombier
3157dd7cddfSDavid du Colombier void
_assert(char * fmt)3167dd7cddfSDavid du Colombier _assert(char *fmt)
3177dd7cddfSDavid du Colombier {
318567483c8SDavid du Colombier panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier
3213e12c5d1SDavid du Colombier int
pprint(char * fmt,...)3223e12c5d1SDavid du Colombier pprint(char *fmt, ...)
3233e12c5d1SDavid du Colombier {
3243e12c5d1SDavid du Colombier int n;
3257dd7cddfSDavid du Colombier Chan *c;
3267dd7cddfSDavid du Colombier va_list arg;
3277dd7cddfSDavid du Colombier char buf[2*PRINTSIZE];
3283e12c5d1SDavid du Colombier
3297dd7cddfSDavid du Colombier if(up == nil || up->fgrp == nil)
3303e12c5d1SDavid du Colombier return 0;
3313e12c5d1SDavid du Colombier
3327dd7cddfSDavid du Colombier c = up->fgrp->fd[2];
3333e12c5d1SDavid du Colombier if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
3343e12c5d1SDavid du Colombier return 0;
335208510e1SDavid du Colombier n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
3367dd7cddfSDavid du Colombier va_start(arg, fmt);
3379a747e4fSDavid du Colombier n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
3387dd7cddfSDavid du Colombier va_end(arg);
3393e12c5d1SDavid du Colombier
340219b2ee8SDavid du Colombier if(waserror())
341219b2ee8SDavid du Colombier return 0;
3427dd7cddfSDavid du Colombier devtab[c->type]->write(c, buf, n, c->offset);
343219b2ee8SDavid du Colombier poperror();
3443e12c5d1SDavid du Colombier
3453e12c5d1SDavid du Colombier lock(c);
3463e12c5d1SDavid du Colombier c->offset += n;
3473e12c5d1SDavid du Colombier unlock(c);
3483e12c5d1SDavid du Colombier
3493e12c5d1SDavid du Colombier return n;
3503e12c5d1SDavid du Colombier }
3513e12c5d1SDavid du Colombier
35280ee5cbfSDavid du Colombier static void
echoscreen(char * buf,int n)35380ee5cbfSDavid du Colombier echoscreen(char *buf, int n)
35480ee5cbfSDavid du Colombier {
35580ee5cbfSDavid du Colombier char *e, *p;
35680ee5cbfSDavid du Colombier char ebuf[128];
35780ee5cbfSDavid du Colombier int x;
35880ee5cbfSDavid du Colombier
35980ee5cbfSDavid du Colombier p = ebuf;
36080ee5cbfSDavid du Colombier e = ebuf + sizeof(ebuf) - 4;
36180ee5cbfSDavid du Colombier while(n-- > 0){
36280ee5cbfSDavid du Colombier if(p >= e){
36380ee5cbfSDavid du Colombier screenputs(ebuf, p - ebuf);
36480ee5cbfSDavid du Colombier p = ebuf;
36580ee5cbfSDavid du Colombier }
36680ee5cbfSDavid du Colombier x = *buf++;
36780ee5cbfSDavid du Colombier if(x == 0x15){
36880ee5cbfSDavid du Colombier *p++ = '^';
36980ee5cbfSDavid du Colombier *p++ = 'U';
37080ee5cbfSDavid du Colombier *p++ = '\n';
37180ee5cbfSDavid du Colombier } else
37280ee5cbfSDavid du Colombier *p++ = x;
37380ee5cbfSDavid du Colombier }
37480ee5cbfSDavid du Colombier if(p != ebuf)
37580ee5cbfSDavid du Colombier screenputs(ebuf, p - ebuf);
37680ee5cbfSDavid du Colombier }
37780ee5cbfSDavid du Colombier
37880ee5cbfSDavid du Colombier static void
echoserialoq(char * buf,int n)3799a747e4fSDavid du Colombier echoserialoq(char *buf, int n)
38080ee5cbfSDavid du Colombier {
38180ee5cbfSDavid du Colombier char *e, *p;
38280ee5cbfSDavid du Colombier char ebuf[128];
38380ee5cbfSDavid du Colombier int x;
38480ee5cbfSDavid du Colombier
38580ee5cbfSDavid du Colombier p = ebuf;
38680ee5cbfSDavid du Colombier e = ebuf + sizeof(ebuf) - 4;
38780ee5cbfSDavid du Colombier while(n-- > 0){
38880ee5cbfSDavid du Colombier if(p >= e){
3899a747e4fSDavid du Colombier qiwrite(serialoq, ebuf, p - ebuf);
39080ee5cbfSDavid du Colombier p = ebuf;
39180ee5cbfSDavid du Colombier }
39280ee5cbfSDavid du Colombier x = *buf++;
39380ee5cbfSDavid du Colombier if(x == '\n'){
39480ee5cbfSDavid du Colombier *p++ = '\r';
39580ee5cbfSDavid du Colombier *p++ = '\n';
39680ee5cbfSDavid du Colombier } else if(x == 0x15){
39780ee5cbfSDavid du Colombier *p++ = '^';
39880ee5cbfSDavid du Colombier *p++ = 'U';
39980ee5cbfSDavid du Colombier *p++ = '\n';
40080ee5cbfSDavid du Colombier } else
40180ee5cbfSDavid du Colombier *p++ = x;
40280ee5cbfSDavid du Colombier }
40380ee5cbfSDavid du Colombier if(p != ebuf)
4049a747e4fSDavid du Colombier qiwrite(serialoq, ebuf, p - ebuf);
40580ee5cbfSDavid du Colombier }
40680ee5cbfSDavid du Colombier
407ec46fab0SDavid du Colombier static void
echo(char * buf,int n)40880ee5cbfSDavid du Colombier echo(char *buf, int n)
4093e12c5d1SDavid du Colombier {
4107dd7cddfSDavid du Colombier static int ctrlt, pid;
4117dd7cddfSDavid du Colombier int x;
41280ee5cbfSDavid du Colombier char *e, *p;
4133e12c5d1SDavid du Colombier
414ec46fab0SDavid du Colombier if(n == 0)
415ec46fab0SDavid du Colombier return;
416ec46fab0SDavid du Colombier
41780ee5cbfSDavid du Colombier e = buf+n;
41880ee5cbfSDavid du Colombier for(p = buf; p < e; p++){
41980ee5cbfSDavid du Colombier switch(*p){
42080ee5cbfSDavid du Colombier case 0x10: /* ^P */
42180ee5cbfSDavid du Colombier if(cpuserver && !kbd.ctlpoff){
4227dd7cddfSDavid du Colombier active.exiting = 1;
42380ee5cbfSDavid du Colombier return;
42480ee5cbfSDavid du Colombier }
42580ee5cbfSDavid du Colombier break;
42680ee5cbfSDavid du Colombier case 0x14: /* ^T */
42780ee5cbfSDavid du Colombier ctrlt++;
42880ee5cbfSDavid du Colombier if(ctrlt > 2)
42980ee5cbfSDavid du Colombier ctrlt = 2;
43080ee5cbfSDavid du Colombier continue;
4317dd7cddfSDavid du Colombier }
4323e12c5d1SDavid du Colombier
43380ee5cbfSDavid du Colombier if(ctrlt != 2)
43480ee5cbfSDavid du Colombier continue;
43580ee5cbfSDavid du Colombier
43680ee5cbfSDavid du Colombier /* ^T escapes */
4373e12c5d1SDavid du Colombier ctrlt = 0;
43880ee5cbfSDavid du Colombier switch(*p){
4399a747e4fSDavid du Colombier case 'S':
4409a747e4fSDavid du Colombier x = splhi();
4419a747e4fSDavid du Colombier dumpstack();
4429a747e4fSDavid du Colombier procdump();
4439a747e4fSDavid du Colombier splx(x);
4449a747e4fSDavid du Colombier return;
4457dd7cddfSDavid du Colombier case 's':
4467dd7cddfSDavid du Colombier dumpstack();
4479a747e4fSDavid du Colombier return;
4483e12c5d1SDavid du Colombier case 'x':
4493e12c5d1SDavid du Colombier xsummary();
4507dd7cddfSDavid du Colombier ixsummary();
4517dd7cddfSDavid du Colombier mallocsummary();
45288110b43SDavid du Colombier // memorysummary();
4537dd7cddfSDavid du Colombier pagersummary();
4549a747e4fSDavid du Colombier return;
4553e12c5d1SDavid du Colombier case 'd':
4567dd7cddfSDavid du Colombier if(consdebug == nil)
4577dd7cddfSDavid du Colombier consdebug = rdb;
4587dd7cddfSDavid du Colombier else
4597dd7cddfSDavid du Colombier consdebug = nil;
460567483c8SDavid du Colombier print("consdebug now %#p\n", consdebug);
4617dd7cddfSDavid du Colombier return;
4627dd7cddfSDavid du Colombier case 'D':
4637dd7cddfSDavid du Colombier if(consdebug == nil)
4647dd7cddfSDavid du Colombier consdebug = rdb;
4653e12c5d1SDavid du Colombier consdebug();
4663e12c5d1SDavid du Colombier return;
4673e12c5d1SDavid du Colombier case 'p':
4687dd7cddfSDavid du Colombier x = spllo();
4693e12c5d1SDavid du Colombier procdump();
4707dd7cddfSDavid du Colombier splx(x);
4713e12c5d1SDavid du Colombier return;
4727dd7cddfSDavid du Colombier case 'q':
4737dd7cddfSDavid du Colombier scheddump();
4749a747e4fSDavid du Colombier return;
4757dd7cddfSDavid du Colombier case 'k':
476cd42b314SDavid du Colombier killbig("^t ^t k");
4779a747e4fSDavid du Colombier return;
4783e12c5d1SDavid du Colombier case 'r':
4793e12c5d1SDavid du Colombier exit(0);
4809a747e4fSDavid du Colombier return;
4813e12c5d1SDavid du Colombier }
4827dd7cddfSDavid du Colombier }
48380ee5cbfSDavid du Colombier
48480ee5cbfSDavid du Colombier qproduce(kbdq, buf, n);
4857dd7cddfSDavid du Colombier if(kbd.raw)
4863e12c5d1SDavid du Colombier return;
487f6eb8b35SDavid du Colombier kmesgputs(buf, n);
4889a747e4fSDavid du Colombier if(screenputs != nil)
48980ee5cbfSDavid du Colombier echoscreen(buf, n);
4909a747e4fSDavid du Colombier if(serialoq)
4919a747e4fSDavid du Colombier echoserialoq(buf, n);
4923e12c5d1SDavid du Colombier }
4933e12c5d1SDavid du Colombier
4943e12c5d1SDavid du Colombier /*
4957dd7cddfSDavid du Colombier * Called by a uart interrupt for console input.
4967dd7cddfSDavid du Colombier *
4977dd7cddfSDavid du Colombier * turn '\r' into '\n' before putting it into the queue.
4983e12c5d1SDavid du Colombier */
4993e12c5d1SDavid du Colombier int
kbdcr2nl(Queue *,int ch)50080ee5cbfSDavid du Colombier kbdcr2nl(Queue*, int ch)
5013e12c5d1SDavid du Colombier {
50280ee5cbfSDavid du Colombier char *next;
50380ee5cbfSDavid du Colombier
50480ee5cbfSDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
50580ee5cbfSDavid du Colombier if(ch == '\r' && !kbd.raw)
5063e12c5d1SDavid du Colombier ch = '\n';
50780ee5cbfSDavid du Colombier next = kbd.iw+1;
50880ee5cbfSDavid du Colombier if(next >= kbd.ie)
50980ee5cbfSDavid du Colombier next = kbd.istage;
51080ee5cbfSDavid du Colombier if(next != kbd.ir){
51180ee5cbfSDavid du Colombier *kbd.iw = ch;
51280ee5cbfSDavid du Colombier kbd.iw = next;
51380ee5cbfSDavid du Colombier }
51480ee5cbfSDavid du Colombier iunlock(&kbd.lockputc);
51580ee5cbfSDavid du Colombier return 0;
5163e12c5d1SDavid du Colombier }
5173e12c5d1SDavid du Colombier
5183e12c5d1SDavid du Colombier /*
5193e12c5d1SDavid du Colombier * Put character, possibly a rune, into read queue at interrupt time.
5207dd7cddfSDavid du Colombier * Called at interrupt time to process a character.
5213e12c5d1SDavid du Colombier */
5223e12c5d1SDavid du Colombier int
kbdputc(Queue *,int ch)5237dd7cddfSDavid du Colombier kbdputc(Queue*, int ch)
5243e12c5d1SDavid du Colombier {
52580ee5cbfSDavid du Colombier int i, n;
5263e12c5d1SDavid du Colombier char buf[3];
5273e12c5d1SDavid du Colombier Rune r;
52880ee5cbfSDavid du Colombier char *next;
5293e12c5d1SDavid du Colombier
5309a747e4fSDavid du Colombier if(kbd.ir == nil)
5319a747e4fSDavid du Colombier return 0; /* in case we're not inited yet */
5329a747e4fSDavid du Colombier
53380ee5cbfSDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
5343e12c5d1SDavid du Colombier r = ch;
5353e12c5d1SDavid du Colombier n = runetochar(buf, &r);
53680ee5cbfSDavid du Colombier for(i = 0; i < n; i++){
53780ee5cbfSDavid du Colombier next = kbd.iw+1;
53880ee5cbfSDavid du Colombier if(next >= kbd.ie)
53980ee5cbfSDavid du Colombier next = kbd.istage;
54080ee5cbfSDavid du Colombier if(next == kbd.ir)
54180ee5cbfSDavid du Colombier break;
54280ee5cbfSDavid du Colombier *kbd.iw = buf[i];
54380ee5cbfSDavid du Colombier kbd.iw = next;
54480ee5cbfSDavid du Colombier }
54580ee5cbfSDavid du Colombier iunlock(&kbd.lockputc);
5463e12c5d1SDavid du Colombier return 0;
5473e12c5d1SDavid du Colombier }
5483e12c5d1SDavid du Colombier
54980ee5cbfSDavid du Colombier /*
55080ee5cbfSDavid du Colombier * we save up input characters till clock time to reduce
55180ee5cbfSDavid du Colombier * per character interrupt overhead.
55280ee5cbfSDavid du Colombier */
55380ee5cbfSDavid du Colombier static void
kbdputcclock(void)55480ee5cbfSDavid du Colombier kbdputcclock(void)
5553e12c5d1SDavid du Colombier {
55680ee5cbfSDavid du Colombier char *iw;
557f6eb8b35SDavid du Colombier
55880ee5cbfSDavid du Colombier /* this amortizes cost of qproduce */
55980ee5cbfSDavid du Colombier if(kbd.iw != kbd.ir){
56080ee5cbfSDavid du Colombier iw = kbd.iw;
56180ee5cbfSDavid du Colombier if(iw < kbd.ir){
56280ee5cbfSDavid du Colombier echo(kbd.ir, kbd.ie-kbd.ir);
56380ee5cbfSDavid du Colombier kbd.ir = kbd.istage;
56480ee5cbfSDavid du Colombier }
565ec46fab0SDavid du Colombier if(kbd.ir != iw){
56680ee5cbfSDavid du Colombier echo(kbd.ir, iw-kbd.ir);
56780ee5cbfSDavid du Colombier kbd.ir = iw;
56880ee5cbfSDavid du Colombier }
5693e12c5d1SDavid du Colombier }
570ec46fab0SDavid du Colombier }
5713e12c5d1SDavid du Colombier
5723e12c5d1SDavid du Colombier enum{
5733e12c5d1SDavid du Colombier Qdir,
5747dd7cddfSDavid du Colombier Qbintime,
5753e12c5d1SDavid du Colombier Qcons,
5763e12c5d1SDavid du Colombier Qconsctl,
5773e12c5d1SDavid du Colombier Qcputime,
5787dd7cddfSDavid du Colombier Qdrivers,
579f6eb8b35SDavid du Colombier Qkmesg,
5809a747e4fSDavid du Colombier Qkprint,
581219b2ee8SDavid du Colombier Qhostdomain,
582219b2ee8SDavid du Colombier Qhostowner,
5833e12c5d1SDavid du Colombier Qnull,
5849a747e4fSDavid du Colombier Qosversion,
5853e12c5d1SDavid du Colombier Qpgrpid,
5863e12c5d1SDavid du Colombier Qpid,
5873e12c5d1SDavid du Colombier Qppid,
5887dd7cddfSDavid du Colombier Qrandom,
5897dd7cddfSDavid du Colombier Qreboot,
5903e12c5d1SDavid du Colombier Qswap,
5913e12c5d1SDavid du Colombier Qsysname,
5923e12c5d1SDavid du Colombier Qsysstat,
5933e12c5d1SDavid du Colombier Qtime,
5943e12c5d1SDavid du Colombier Quser,
5957dd7cddfSDavid du Colombier Qzero,
596add6b5c5SDavid du Colombier Qconfig,
5973e12c5d1SDavid du Colombier };
5983e12c5d1SDavid du Colombier
5997dd7cddfSDavid du Colombier enum
6007dd7cddfSDavid du Colombier {
6017dd7cddfSDavid du Colombier VLNUMSIZE= 22,
6027dd7cddfSDavid du Colombier };
6037dd7cddfSDavid du Colombier
6047dd7cddfSDavid du Colombier static Dirtab consdir[]={
6059a747e4fSDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
6067dd7cddfSDavid du Colombier "bintime", {Qbintime}, 24, 0664,
6073e12c5d1SDavid du Colombier "cons", {Qcons}, 0, 0660,
6083e12c5d1SDavid du Colombier "consctl", {Qconsctl}, 0, 0220,
6093e12c5d1SDavid du Colombier "cputime", {Qcputime}, 6*NUMSIZE, 0444,
6109a747e4fSDavid du Colombier "drivers", {Qdrivers}, 0, 0444,
611219b2ee8SDavid du Colombier "hostdomain", {Qhostdomain}, DOMLEN, 0664,
6129a747e4fSDavid du Colombier "hostowner", {Qhostowner}, 0, 0664,
613f6eb8b35SDavid du Colombier "kmesg", {Qkmesg}, 0, 0440,
6149a747e4fSDavid du Colombier "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
6153e12c5d1SDavid du Colombier "null", {Qnull}, 0, 0666,
6169a747e4fSDavid du Colombier "osversion", {Qosversion}, 0, 0444,
6173e12c5d1SDavid du Colombier "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
6183e12c5d1SDavid du Colombier "pid", {Qpid}, NUMSIZE, 0444,
6193e12c5d1SDavid du Colombier "ppid", {Qppid}, NUMSIZE, 0444,
6209a747e4fSDavid du Colombier "random", {Qrandom}, 0, 0444,
621*a826b788SDavid du Colombier "reboot", {Qreboot}, 0, 0660,
6223e12c5d1SDavid du Colombier "swap", {Qswap}, 0, 0664,
6233e12c5d1SDavid du Colombier "sysname", {Qsysname}, 0, 0664,
6243e12c5d1SDavid du Colombier "sysstat", {Qsysstat}, 0, 0666,
6257dd7cddfSDavid du Colombier "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
6269a747e4fSDavid du Colombier "user", {Quser}, 0, 0666,
6277dd7cddfSDavid du Colombier "zero", {Qzero}, 0, 0444,
628add6b5c5SDavid du Colombier "config", {Qconfig}, 0, 0444,
6293e12c5d1SDavid du Colombier };
6303e12c5d1SDavid du Colombier
6313e12c5d1SDavid du Colombier int
readnum(ulong off,char * buf,ulong n,ulong val,int size)6323e12c5d1SDavid du Colombier readnum(ulong off, char *buf, ulong n, ulong val, int size)
6333e12c5d1SDavid du Colombier {
6343e12c5d1SDavid du Colombier char tmp[64];
6353e12c5d1SDavid du Colombier
636567483c8SDavid du Colombier snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
6373e12c5d1SDavid du Colombier tmp[size-1] = ' ';
6383e12c5d1SDavid du Colombier if(off >= size)
6393e12c5d1SDavid du Colombier return 0;
6403e12c5d1SDavid du Colombier if(off+n > size)
6413e12c5d1SDavid du Colombier n = size-off;
6423e12c5d1SDavid du Colombier memmove(buf, tmp+off, n);
6433e12c5d1SDavid du Colombier return n;
6443e12c5d1SDavid du Colombier }
6453e12c5d1SDavid du Colombier
6463e12c5d1SDavid du Colombier int
readstr(ulong off,char * buf,ulong n,char * str)6473e12c5d1SDavid du Colombier readstr(ulong off, char *buf, ulong n, char *str)
6483e12c5d1SDavid du Colombier {
6493e12c5d1SDavid du Colombier int size;
6503e12c5d1SDavid du Colombier
6513e12c5d1SDavid du Colombier size = strlen(str);
6523e12c5d1SDavid du Colombier if(off >= size)
6533e12c5d1SDavid du Colombier return 0;
6543e12c5d1SDavid du Colombier if(off+n > size)
6553e12c5d1SDavid du Colombier n = size-off;
6563e12c5d1SDavid du Colombier memmove(buf, str+off, n);
6573e12c5d1SDavid du Colombier return n;
6583e12c5d1SDavid du Colombier }
6593e12c5d1SDavid du Colombier
6607dd7cddfSDavid du Colombier static void
consinit(void)6613e12c5d1SDavid du Colombier consinit(void)
6623e12c5d1SDavid du Colombier {
6637dd7cddfSDavid du Colombier todinit();
6647dd7cddfSDavid du Colombier randominit();
665d9306527SDavid du Colombier /*
666d9306527SDavid du Colombier * at 115200 baud, the 1024 char buffer takes 56 ms to process,
667d9306527SDavid du Colombier * processing it every 22 ms should be fine
668d9306527SDavid du Colombier */
669d9306527SDavid du Colombier addclock0link(kbdputcclock, 22);
6703e12c5d1SDavid du Colombier }
6713e12c5d1SDavid du Colombier
6727dd7cddfSDavid du Colombier static Chan*
consattach(char * spec)6733e12c5d1SDavid du Colombier consattach(char *spec)
6743e12c5d1SDavid du Colombier {
6753e12c5d1SDavid du Colombier return devattach('c', spec);
6763e12c5d1SDavid du Colombier }
6773e12c5d1SDavid du Colombier
6789a747e4fSDavid du Colombier static Walkqid*
conswalk(Chan * c,Chan * nc,char ** name,int nname)6799a747e4fSDavid du Colombier conswalk(Chan *c, Chan *nc, char **name, int nname)
6803e12c5d1SDavid du Colombier {
6819a747e4fSDavid du Colombier return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
6823e12c5d1SDavid du Colombier }
6833e12c5d1SDavid du Colombier
6849a747e4fSDavid du Colombier static int
consstat(Chan * c,uchar * dp,int n)6859a747e4fSDavid du Colombier consstat(Chan *c, uchar *dp, int n)
6863e12c5d1SDavid du Colombier {
6879a747e4fSDavid du Colombier return devstat(c, dp, n, consdir, nelem(consdir), devgen);
6883e12c5d1SDavid du Colombier }
6893e12c5d1SDavid du Colombier
6907dd7cddfSDavid du Colombier static Chan*
consopen(Chan * c,int omode)6913e12c5d1SDavid du Colombier consopen(Chan *c, int omode)
6923e12c5d1SDavid du Colombier {
6939a747e4fSDavid du Colombier c->aux = nil;
6949a747e4fSDavid du Colombier c = devopen(c, omode, consdir, nelem(consdir), devgen);
6959a747e4fSDavid du Colombier switch((ulong)c->qid.path){
6963e12c5d1SDavid du Colombier case Qconsctl:
69788110b43SDavid du Colombier incref(&kbd.ctl);
6983e12c5d1SDavid du Colombier break;
6999a747e4fSDavid du Colombier
7009a747e4fSDavid du Colombier case Qkprint:
7019a747e4fSDavid du Colombier if(tas(&kprintinuse) != 0){
7029a747e4fSDavid du Colombier c->flag &= ~COPEN;
7039a747e4fSDavid du Colombier error(Einuse);
7043e12c5d1SDavid du Colombier }
7059a747e4fSDavid du Colombier if(kprintoq == nil){
7063ff48bf5SDavid du Colombier kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
7079a747e4fSDavid du Colombier if(kprintoq == nil){
7089a747e4fSDavid du Colombier c->flag &= ~COPEN;
7099a747e4fSDavid du Colombier error(Enomem);
7109a747e4fSDavid du Colombier }
7119a747e4fSDavid du Colombier qnoblock(kprintoq, 1);
7129a747e4fSDavid du Colombier }else
7139a747e4fSDavid du Colombier qreopen(kprintoq);
7149a747e4fSDavid du Colombier c->iounit = qiomaxatomic;
7159a747e4fSDavid du Colombier break;
7169a747e4fSDavid du Colombier }
7179a747e4fSDavid du Colombier return c;
7183e12c5d1SDavid du Colombier }
7193e12c5d1SDavid du Colombier
7207dd7cddfSDavid du Colombier static void
consclose(Chan * c)7213e12c5d1SDavid du Colombier consclose(Chan *c)
7223e12c5d1SDavid du Colombier {
7239a747e4fSDavid du Colombier switch((ulong)c->qid.path){
7243e12c5d1SDavid du Colombier /* last close of control file turns off raw */
725219b2ee8SDavid du Colombier case Qconsctl:
726219b2ee8SDavid du Colombier if(c->flag&COPEN){
72788110b43SDavid du Colombier if(decref(&kbd.ctl) == 0)
7287dd7cddfSDavid du Colombier kbd.raw = 0;
7293e12c5d1SDavid du Colombier }
730219b2ee8SDavid du Colombier break;
7319a747e4fSDavid du Colombier
7329a747e4fSDavid du Colombier /* close of kprint allows other opens */
7339a747e4fSDavid du Colombier case Qkprint:
7349a747e4fSDavid du Colombier if(c->flag & COPEN){
7359a747e4fSDavid du Colombier kprintinuse = 0;
7369a747e4fSDavid du Colombier qhangup(kprintoq, nil);
7379a747e4fSDavid du Colombier }
7389a747e4fSDavid du Colombier break;
739219b2ee8SDavid du Colombier }
7403e12c5d1SDavid du Colombier }
7413e12c5d1SDavid du Colombier
7427dd7cddfSDavid du Colombier static long
consread(Chan * c,void * buf,long n,vlong off)7437dd7cddfSDavid du Colombier consread(Chan *c, void *buf, long n, vlong off)
7443e12c5d1SDavid du Colombier {
7453e12c5d1SDavid du Colombier ulong l;
7467dd7cddfSDavid du Colombier Mach *mp;
74788110b43SDavid du Colombier char *b, *bp, ch;
748e059317eSDavid du Colombier char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
74988110b43SDavid du Colombier int i, k, id, send;
7507dd7cddfSDavid du Colombier vlong offset = off;
751add6b5c5SDavid du Colombier extern char configfile[];
7523e12c5d1SDavid du Colombier
7533e12c5d1SDavid du Colombier if(n <= 0)
7543e12c5d1SDavid du Colombier return n;
75588110b43SDavid du Colombier
7569a747e4fSDavid du Colombier switch((ulong)c->qid.path){
7573e12c5d1SDavid du Colombier case Qdir:
7587dd7cddfSDavid du Colombier return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
7593e12c5d1SDavid du Colombier
7603e12c5d1SDavid du Colombier case Qcons:
7617dd7cddfSDavid du Colombier qlock(&kbd);
7623e12c5d1SDavid du Colombier if(waserror()) {
7637dd7cddfSDavid du Colombier qunlock(&kbd);
7643e12c5d1SDavid du Colombier nexterror();
7653e12c5d1SDavid du Colombier }
7667dd7cddfSDavid du Colombier while(!qcanread(lineq)){
767ec46fab0SDavid du Colombier if(qread(kbdq, &ch, 1) == 0)
768ec46fab0SDavid du Colombier continue;
76988110b43SDavid du Colombier send = 0;
77088110b43SDavid du Colombier if(ch == 0){
77188110b43SDavid du Colombier /* flush output on rawoff -> rawon */
77288110b43SDavid du Colombier if(kbd.x > 0)
77388110b43SDavid du Colombier send = !qcanread(kbdq);
77488110b43SDavid du Colombier }else if(kbd.raw){
77588110b43SDavid du Colombier kbd.line[kbd.x++] = ch;
77688110b43SDavid du Colombier send = !qcanread(kbdq);
77788110b43SDavid du Colombier }else{
7783e12c5d1SDavid du Colombier switch(ch){
7793e12c5d1SDavid du Colombier case '\b':
78088110b43SDavid du Colombier if(kbd.x > 0)
7817dd7cddfSDavid du Colombier kbd.x--;
7823e12c5d1SDavid du Colombier break;
78388110b43SDavid du Colombier case 0x15: /* ^U */
7847dd7cddfSDavid du Colombier kbd.x = 0;
7853e12c5d1SDavid du Colombier break;
7867dd7cddfSDavid du Colombier case '\n':
78788110b43SDavid du Colombier case 0x04: /* ^D */
78888110b43SDavid du Colombier send = 1;
7893e12c5d1SDavid du Colombier default:
79088110b43SDavid du Colombier if(ch != 0x04)
7917dd7cddfSDavid du Colombier kbd.line[kbd.x++] = ch;
7923e12c5d1SDavid du Colombier break;
7933e12c5d1SDavid du Colombier }
79488110b43SDavid du Colombier }
79588110b43SDavid du Colombier if(send || kbd.x == sizeof kbd.line){
7967dd7cddfSDavid du Colombier qwrite(lineq, kbd.line, kbd.x);
7977dd7cddfSDavid du Colombier kbd.x = 0;
7987dd7cddfSDavid du Colombier }
7997dd7cddfSDavid du Colombier }
8007dd7cddfSDavid du Colombier n = qread(lineq, buf, n);
8017dd7cddfSDavid du Colombier qunlock(&kbd);
8023e12c5d1SDavid du Colombier poperror();
8037dd7cddfSDavid du Colombier return n;
8043e12c5d1SDavid du Colombier
8053e12c5d1SDavid du Colombier case Qcputime:
8063e12c5d1SDavid du Colombier k = offset;
807219b2ee8SDavid du Colombier if(k >= 6*NUMSIZE)
8083e12c5d1SDavid du Colombier return 0;
809219b2ee8SDavid du Colombier if(k+n > 6*NUMSIZE)
810219b2ee8SDavid du Colombier n = 6*NUMSIZE - k;
8113e12c5d1SDavid du Colombier /* easiest to format in a separate buffer and copy out */
8123e12c5d1SDavid du Colombier for(i=0; i<6 && NUMSIZE*i<k+n; i++){
8137dd7cddfSDavid du Colombier l = up->time[i];
8143e12c5d1SDavid du Colombier if(i == TReal)
8153e12c5d1SDavid du Colombier l = MACHP(0)->ticks - l;
8163e12c5d1SDavid du Colombier l = TK2MS(l);
8173e12c5d1SDavid du Colombier readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
8183e12c5d1SDavid du Colombier }
8193e12c5d1SDavid du Colombier memmove(buf, tmp+k, n);
8203e12c5d1SDavid du Colombier return n;
8213e12c5d1SDavid du Colombier
822f6eb8b35SDavid du Colombier case Qkmesg:
823f6eb8b35SDavid du Colombier /*
824f6eb8b35SDavid du Colombier * This is unlocked to avoid tying up a process
825f6eb8b35SDavid du Colombier * that's writing to the buffer. kmesg.n never
826f6eb8b35SDavid du Colombier * gets smaller, so worst case the reader will
827f6eb8b35SDavid du Colombier * see a slurred buffer.
828f6eb8b35SDavid du Colombier */
829f6eb8b35SDavid du Colombier if(off >= kmesg.n)
830f6eb8b35SDavid du Colombier n = 0;
831f6eb8b35SDavid du Colombier else{
832f6eb8b35SDavid du Colombier if(off+n > kmesg.n)
833f6eb8b35SDavid du Colombier n = kmesg.n - off;
834f6eb8b35SDavid du Colombier memmove(buf, kmesg.buf+off, n);
835f6eb8b35SDavid du Colombier }
836f6eb8b35SDavid du Colombier return n;
837f6eb8b35SDavid du Colombier
8389a747e4fSDavid du Colombier case Qkprint:
8399a747e4fSDavid du Colombier return qread(kprintoq, buf, n);
8409a747e4fSDavid du Colombier
8413e12c5d1SDavid du Colombier case Qpgrpid:
8427dd7cddfSDavid du Colombier return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
8433e12c5d1SDavid du Colombier
8443e12c5d1SDavid du Colombier case Qpid:
8457dd7cddfSDavid du Colombier return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
8463e12c5d1SDavid du Colombier
8473e12c5d1SDavid du Colombier case Qppid:
8487dd7cddfSDavid du Colombier return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
8493e12c5d1SDavid du Colombier
8503e12c5d1SDavid du Colombier case Qtime:
8517dd7cddfSDavid du Colombier return readtime((ulong)offset, buf, n);
8523e12c5d1SDavid du Colombier
8537dd7cddfSDavid du Colombier case Qbintime:
8547dd7cddfSDavid du Colombier return readbintime(buf, n);
8553e12c5d1SDavid du Colombier
856219b2ee8SDavid du Colombier case Qhostowner:
8577dd7cddfSDavid du Colombier return readstr((ulong)offset, buf, n, eve);
858219b2ee8SDavid du Colombier
859219b2ee8SDavid du Colombier case Qhostdomain:
8607dd7cddfSDavid du Colombier return readstr((ulong)offset, buf, n, hostdomain);
8613e12c5d1SDavid du Colombier
8623e12c5d1SDavid du Colombier case Quser:
8637dd7cddfSDavid du Colombier return readstr((ulong)offset, buf, n, up->user);
8643e12c5d1SDavid du Colombier
8653e12c5d1SDavid du Colombier case Qnull:
8663e12c5d1SDavid du Colombier return 0;
8673e12c5d1SDavid du Colombier
868add6b5c5SDavid du Colombier case Qconfig:
869add6b5c5SDavid du Colombier return readstr((ulong)offset, buf, n, configfile);
870add6b5c5SDavid du Colombier
8713e12c5d1SDavid du Colombier case Qsysstat:
8723ff48bf5SDavid du Colombier b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
8733e12c5d1SDavid du Colombier bp = b;
8743e12c5d1SDavid du Colombier for(id = 0; id < 32; id++) {
8753e12c5d1SDavid du Colombier if(active.machs & (1<<id)) {
8763e12c5d1SDavid du Colombier mp = MACHP(id);
8773e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, id, NUMSIZE);
8783e12c5d1SDavid du Colombier bp += NUMSIZE;
8793e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
8803e12c5d1SDavid du Colombier bp += NUMSIZE;
8813e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
8823e12c5d1SDavid du Colombier bp += NUMSIZE;
8833e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
8843e12c5d1SDavid du Colombier bp += NUMSIZE;
8853e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
8863e12c5d1SDavid du Colombier bp += NUMSIZE;
8873e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
8883e12c5d1SDavid du Colombier bp += NUMSIZE;
8893e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
8903e12c5d1SDavid du Colombier bp += NUMSIZE;
8913e12c5d1SDavid du Colombier readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
8923e12c5d1SDavid du Colombier bp += NUMSIZE;
8933ff48bf5SDavid du Colombier readnum(0, bp, NUMSIZE,
8943ff48bf5SDavid du Colombier (mp->perf.avg_inidle*100)/mp->perf.period,
8953ff48bf5SDavid du Colombier NUMSIZE);
8963ff48bf5SDavid du Colombier bp += NUMSIZE;
8973ff48bf5SDavid du Colombier readnum(0, bp, NUMSIZE,
8983ff48bf5SDavid du Colombier (mp->perf.avg_inintr*100)/mp->perf.period,
8993ff48bf5SDavid du Colombier NUMSIZE);
9003ff48bf5SDavid du Colombier bp += NUMSIZE;
9013e12c5d1SDavid du Colombier *bp++ = '\n';
9023e12c5d1SDavid du Colombier }
9033e12c5d1SDavid du Colombier }
9049a747e4fSDavid du Colombier if(waserror()){
9059a747e4fSDavid du Colombier free(b);
9069a747e4fSDavid du Colombier nexterror();
9079a747e4fSDavid du Colombier }
9087dd7cddfSDavid du Colombier n = readstr((ulong)offset, buf, n, b);
9093e12c5d1SDavid du Colombier free(b);
9109a747e4fSDavid du Colombier poperror();
9113e12c5d1SDavid du Colombier return n;
9123e12c5d1SDavid du Colombier
9133e12c5d1SDavid du Colombier case Qswap:
914e059317eSDavid du Colombier snprint(tmp, sizeof tmp,
915e059317eSDavid du Colombier "%lud memory\n"
916e059317eSDavid du Colombier "%d pagesize\n"
917e059317eSDavid du Colombier "%lud kernel\n"
918e059317eSDavid du Colombier "%lud/%lud user\n"
919e059317eSDavid du Colombier "%lud/%lud swap\n"
920e059317eSDavid du Colombier "%lud/%lud kernel malloc\n"
921e059317eSDavid du Colombier "%lud/%lud kernel draw\n",
922e059317eSDavid du Colombier conf.npage*BY2PG,
923e059317eSDavid du Colombier BY2PG,
924e059317eSDavid du Colombier conf.npage-conf.upages,
925e059317eSDavid du Colombier palloc.user-palloc.freecount, palloc.user,
926e059317eSDavid du Colombier conf.nswap-swapalloc.free, conf.nswap,
927e059317eSDavid du Colombier mainmem->cursize, mainmem->maxsize,
928e059317eSDavid du Colombier imagmem->cursize, imagmem->maxsize);
9293e12c5d1SDavid du Colombier
9307dd7cddfSDavid du Colombier return readstr((ulong)offset, buf, n, tmp);
9313e12c5d1SDavid du Colombier
9323e12c5d1SDavid du Colombier case Qsysname:
9339a747e4fSDavid du Colombier if(sysname == nil)
9349a747e4fSDavid du Colombier return 0;
9357dd7cddfSDavid du Colombier return readstr((ulong)offset, buf, n, sysname);
9367dd7cddfSDavid du Colombier
9377dd7cddfSDavid du Colombier case Qrandom:
9387dd7cddfSDavid du Colombier return randomread(buf, n);
9397dd7cddfSDavid du Colombier
9407dd7cddfSDavid du Colombier case Qdrivers:
9417dd7cddfSDavid du Colombier b = malloc(READSTR);
9427dd7cddfSDavid du Colombier if(b == nil)
9437dd7cddfSDavid du Colombier error(Enomem);
944fcbb35d1SDavid du Colombier k = 0;
9457dd7cddfSDavid du Colombier for(i = 0; devtab[i] != nil; i++)
946fcbb35d1SDavid du Colombier k += snprint(b+k, READSTR-k, "#%C %s\n",
947fcbb35d1SDavid du Colombier devtab[i]->dc, devtab[i]->name);
9489a747e4fSDavid du Colombier if(waserror()){
9499a747e4fSDavid du Colombier free(b);
9509a747e4fSDavid du Colombier nexterror();
9519a747e4fSDavid du Colombier }
9527dd7cddfSDavid du Colombier n = readstr((ulong)offset, buf, n, b);
9537dd7cddfSDavid du Colombier free(b);
9549a747e4fSDavid du Colombier poperror();
9557dd7cddfSDavid du Colombier return n;
9567dd7cddfSDavid du Colombier
9577dd7cddfSDavid du Colombier case Qzero:
9587dd7cddfSDavid du Colombier memset(buf, 0, n);
9597dd7cddfSDavid du Colombier return n;
9603e12c5d1SDavid du Colombier
9619a747e4fSDavid du Colombier case Qosversion:
9629a747e4fSDavid du Colombier snprint(tmp, sizeof tmp, "2000");
9639a747e4fSDavid du Colombier n = readstr((ulong)offset, buf, n, tmp);
9649a747e4fSDavid du Colombier return n;
9659a747e4fSDavid du Colombier
9663e12c5d1SDavid du Colombier default:
967567483c8SDavid du Colombier print("consread %#llux\n", c->qid.path);
9683e12c5d1SDavid du Colombier error(Egreg);
9693e12c5d1SDavid du Colombier }
9703e12c5d1SDavid du Colombier return -1; /* never reached */
9713e12c5d1SDavid du Colombier }
9723e12c5d1SDavid du Colombier
9737dd7cddfSDavid du Colombier static long
conswrite(Chan * c,void * va,long n,vlong off)9747dd7cddfSDavid du Colombier conswrite(Chan *c, void *va, long n, vlong off)
9753e12c5d1SDavid du Colombier {
97688110b43SDavid du Colombier char buf[256], ch;
9773e12c5d1SDavid du Colombier long l, bp;
97888110b43SDavid du Colombier char *a;
9793e12c5d1SDavid du Colombier Mach *mp;
9807dd7cddfSDavid du Colombier int id, fd;
9813e12c5d1SDavid du Colombier Chan *swc;
98288110b43SDavid du Colombier ulong offset;
9839a747e4fSDavid du Colombier Cmdbuf *cb;
9849a747e4fSDavid du Colombier Cmdtab *ct;
9853e12c5d1SDavid du Colombier
98688110b43SDavid du Colombier a = va;
98788110b43SDavid du Colombier offset = off;
98888110b43SDavid du Colombier
9899a747e4fSDavid du Colombier switch((ulong)c->qid.path){
9903e12c5d1SDavid du Colombier case Qcons:
9917dd7cddfSDavid du Colombier /*
9927dd7cddfSDavid du Colombier * Can't page fault in putstrn, so copy the data locally.
9937dd7cddfSDavid du Colombier */
9943e12c5d1SDavid du Colombier l = n;
9953e12c5d1SDavid du Colombier while(l > 0){
9963e12c5d1SDavid du Colombier bp = l;
9973e12c5d1SDavid du Colombier if(bp > sizeof buf)
9983e12c5d1SDavid du Colombier bp = sizeof buf;
9993e12c5d1SDavid du Colombier memmove(buf, a, bp);
100080ee5cbfSDavid du Colombier putstrn0(buf, bp, 1);
10013e12c5d1SDavid du Colombier a += bp;
10023e12c5d1SDavid du Colombier l -= bp;
10033e12c5d1SDavid du Colombier }
10043e12c5d1SDavid du Colombier break;
10053e12c5d1SDavid du Colombier
10063e12c5d1SDavid du Colombier case Qconsctl:
10073e12c5d1SDavid du Colombier if(n >= sizeof(buf))
10083e12c5d1SDavid du Colombier n = sizeof(buf)-1;
10093e12c5d1SDavid du Colombier strncpy(buf, a, n);
10103e12c5d1SDavid du Colombier buf[n] = 0;
10117dd7cddfSDavid du Colombier for(a = buf; a;){
10123e12c5d1SDavid du Colombier if(strncmp(a, "rawon", 5) == 0){
10137dd7cddfSDavid du Colombier kbd.raw = 1;
101488110b43SDavid du Colombier /* clumsy hack - wake up reader */
101588110b43SDavid du Colombier ch = 0;
101688110b43SDavid du Colombier qwrite(kbdq, &ch, 1);
10177dd7cddfSDavid du Colombier } else if(strncmp(a, "rawoff", 6) == 0){
10187dd7cddfSDavid du Colombier kbd.raw = 0;
10197dd7cddfSDavid du Colombier } else if(strncmp(a, "ctlpon", 6) == 0){
10207dd7cddfSDavid du Colombier kbd.ctlpoff = 0;
10217dd7cddfSDavid du Colombier } else if(strncmp(a, "ctlpoff", 7) == 0){
10227dd7cddfSDavid du Colombier kbd.ctlpoff = 1;
1023219b2ee8SDavid du Colombier }
10247dd7cddfSDavid du Colombier if(a = strchr(a, ' '))
10257dd7cddfSDavid du Colombier a++;
10263e12c5d1SDavid du Colombier }
10273e12c5d1SDavid du Colombier break;
10283e12c5d1SDavid du Colombier
10293e12c5d1SDavid du Colombier case Qtime:
10307dd7cddfSDavid du Colombier if(!iseve())
10317dd7cddfSDavid du Colombier error(Eperm);
10327dd7cddfSDavid du Colombier return writetime(a, n);
10337dd7cddfSDavid du Colombier
10347dd7cddfSDavid du Colombier case Qbintime:
10357dd7cddfSDavid du Colombier if(!iseve())
10367dd7cddfSDavid du Colombier error(Eperm);
10377dd7cddfSDavid du Colombier return writebintime(a, n);
10383e12c5d1SDavid du Colombier
1039219b2ee8SDavid du Colombier case Qhostowner:
1040219b2ee8SDavid du Colombier return hostownerwrite(a, n);
1041219b2ee8SDavid du Colombier
1042219b2ee8SDavid du Colombier case Qhostdomain:
1043219b2ee8SDavid du Colombier return hostdomainwrite(a, n);
10443e12c5d1SDavid du Colombier
10453e12c5d1SDavid du Colombier case Quser:
1046219b2ee8SDavid du Colombier return userwrite(a, n);
10473e12c5d1SDavid du Colombier
10483e12c5d1SDavid du Colombier case Qnull:
10493e12c5d1SDavid du Colombier break;
10503e12c5d1SDavid du Colombier
1051add6b5c5SDavid du Colombier case Qconfig:
1052add6b5c5SDavid du Colombier error(Eperm);
1053add6b5c5SDavid du Colombier break;
1054add6b5c5SDavid du Colombier
10557dd7cddfSDavid du Colombier case Qreboot:
10567dd7cddfSDavid du Colombier if(!iseve())
10577dd7cddfSDavid du Colombier error(Eperm);
10589a747e4fSDavid du Colombier cb = parsecmd(a, n);
10599a747e4fSDavid du Colombier
10609a747e4fSDavid du Colombier if(waserror()) {
10619a747e4fSDavid du Colombier free(cb);
10629a747e4fSDavid du Colombier nexterror();
10637dd7cddfSDavid du Colombier }
10649a747e4fSDavid du Colombier ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
10659a747e4fSDavid du Colombier switch(ct->index) {
1066e288d156SDavid du Colombier case CMhalt:
1067e288d156SDavid du Colombier reboot(nil, 0, 0);
1068e288d156SDavid du Colombier break;
10699a747e4fSDavid du Colombier case CMreboot:
10709a747e4fSDavid du Colombier rebootcmd(cb->nf-1, cb->f+1);
10719a747e4fSDavid du Colombier break;
10729a747e4fSDavid du Colombier case CMpanic:
1073e288d156SDavid du Colombier *(ulong*)0=0;
10747dd7cddfSDavid du Colombier panic("/dev/reboot");
10759a747e4fSDavid du Colombier }
10769a747e4fSDavid du Colombier poperror();
10779a747e4fSDavid du Colombier free(cb);
10783e12c5d1SDavid du Colombier break;
10793e12c5d1SDavid du Colombier
10803e12c5d1SDavid du Colombier case Qsysstat:
10813e12c5d1SDavid du Colombier for(id = 0; id < 32; id++) {
10823e12c5d1SDavid du Colombier if(active.machs & (1<<id)) {
10833e12c5d1SDavid du Colombier mp = MACHP(id);
10843e12c5d1SDavid du Colombier mp->cs = 0;
10853e12c5d1SDavid du Colombier mp->intr = 0;
10863e12c5d1SDavid du Colombier mp->syscall = 0;
10873e12c5d1SDavid du Colombier mp->pfault = 0;
10883e12c5d1SDavid du Colombier mp->tlbfault = 0;
10893e12c5d1SDavid du Colombier mp->tlbpurge = 0;
10903e12c5d1SDavid du Colombier }
10913e12c5d1SDavid du Colombier }
10923e12c5d1SDavid du Colombier break;
10933e12c5d1SDavid du Colombier
10943e12c5d1SDavid du Colombier case Qswap:
10953e12c5d1SDavid du Colombier if(n >= sizeof buf)
10963e12c5d1SDavid du Colombier error(Egreg);
10973e12c5d1SDavid du Colombier memmove(buf, va, n); /* so we can NUL-terminate */
10983e12c5d1SDavid du Colombier buf[n] = 0;
10993e12c5d1SDavid du Colombier /* start a pager if not already started */
11003e12c5d1SDavid du Colombier if(strncmp(buf, "start", 5) == 0){
11013e12c5d1SDavid du Colombier kickpager();
11023e12c5d1SDavid du Colombier break;
11033e12c5d1SDavid du Colombier }
1104dc5a79c1SDavid du Colombier if(!iseve())
11053e12c5d1SDavid du Colombier error(Eperm);
11063e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0])
11077dd7cddfSDavid du Colombier error(Ebadarg);
11083e12c5d1SDavid du Colombier fd = strtoul(buf, 0, 0);
11097dd7cddfSDavid du Colombier swc = fdtochan(fd, -1, 1, 1);
11103e12c5d1SDavid du Colombier setswapchan(swc);
11113e12c5d1SDavid du Colombier break;
11123e12c5d1SDavid du Colombier
11133e12c5d1SDavid du Colombier case Qsysname:
11143e12c5d1SDavid du Colombier if(offset != 0)
11153e12c5d1SDavid du Colombier error(Ebadarg);
11169a747e4fSDavid du Colombier if(n <= 0 || n >= sizeof buf)
11173e12c5d1SDavid du Colombier error(Ebadarg);
11189a747e4fSDavid du Colombier strncpy(buf, a, n);
11199a747e4fSDavid du Colombier buf[n] = 0;
11209a747e4fSDavid du Colombier if(buf[n-1] == '\n')
11219a747e4fSDavid du Colombier buf[n-1] = 0;
11229a747e4fSDavid du Colombier kstrdup(&sysname, buf);
11233e12c5d1SDavid du Colombier break;
11243e12c5d1SDavid du Colombier
11253e12c5d1SDavid du Colombier default:
1126567483c8SDavid du Colombier print("conswrite: %#llux\n", c->qid.path);
11273e12c5d1SDavid du Colombier error(Egreg);
11283e12c5d1SDavid du Colombier }
11293e12c5d1SDavid du Colombier return n;
11303e12c5d1SDavid du Colombier }
11313e12c5d1SDavid du Colombier
11327dd7cddfSDavid du Colombier Dev consdevtab = {
11337dd7cddfSDavid du Colombier 'c',
11347dd7cddfSDavid du Colombier "cons",
11357dd7cddfSDavid du Colombier
11367dd7cddfSDavid du Colombier devreset,
11377dd7cddfSDavid du Colombier consinit,
11389a747e4fSDavid du Colombier devshutdown,
11397dd7cddfSDavid du Colombier consattach,
11407dd7cddfSDavid du Colombier conswalk,
11417dd7cddfSDavid du Colombier consstat,
11427dd7cddfSDavid du Colombier consopen,
11437dd7cddfSDavid du Colombier devcreate,
11447dd7cddfSDavid du Colombier consclose,
11457dd7cddfSDavid du Colombier consread,
11467dd7cddfSDavid du Colombier devbread,
11477dd7cddfSDavid du Colombier conswrite,
11487dd7cddfSDavid du Colombier devbwrite,
11497dd7cddfSDavid du Colombier devremove,
11507dd7cddfSDavid du Colombier devwstat,
11517dd7cddfSDavid du Colombier };
11527dd7cddfSDavid du Colombier
115314414594SDavid du Colombier static ulong randn;
11547dd7cddfSDavid du Colombier
11557dd7cddfSDavid du Colombier static void
seedrand(void)11567dd7cddfSDavid du Colombier seedrand(void)
11577dd7cddfSDavid du Colombier {
1158d04cc87cSDavid du Colombier if(!waserror()){
115914414594SDavid du Colombier randomread((void*)&randn, sizeof(randn));
1160d04cc87cSDavid du Colombier poperror();
1161d04cc87cSDavid du Colombier }
11627dd7cddfSDavid du Colombier }
11637dd7cddfSDavid du Colombier
11647dd7cddfSDavid du Colombier int
nrand(int n)11657dd7cddfSDavid du Colombier nrand(int n)
11667dd7cddfSDavid du Colombier {
116714414594SDavid du Colombier if(randn == 0)
11687dd7cddfSDavid du Colombier seedrand();
116914414594SDavid du Colombier randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
117014414594SDavid du Colombier return (randn>>16) % n;
11717dd7cddfSDavid du Colombier }
11727dd7cddfSDavid du Colombier
11737dd7cddfSDavid du Colombier int
rand(void)11747dd7cddfSDavid du Colombier rand(void)
11757dd7cddfSDavid du Colombier {
11767dd7cddfSDavid du Colombier nrand(1);
117714414594SDavid du Colombier return randn;
11787dd7cddfSDavid du Colombier }
11797dd7cddfSDavid du Colombier
11807dd7cddfSDavid du Colombier static uvlong uvorder = 0x0001020304050607ULL;
11817dd7cddfSDavid du Colombier
11827dd7cddfSDavid du Colombier static uchar*
le2vlong(vlong * to,uchar * f)11837dd7cddfSDavid du Colombier le2vlong(vlong *to, uchar *f)
11847dd7cddfSDavid du Colombier {
11857dd7cddfSDavid du Colombier uchar *t, *o;
11867dd7cddfSDavid du Colombier int i;
11877dd7cddfSDavid du Colombier
11887dd7cddfSDavid du Colombier t = (uchar*)to;
11897dd7cddfSDavid du Colombier o = (uchar*)&uvorder;
11907dd7cddfSDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
11917dd7cddfSDavid du Colombier t[o[i]] = f[i];
11927dd7cddfSDavid du Colombier return f+sizeof(vlong);
11937dd7cddfSDavid du Colombier }
11947dd7cddfSDavid du Colombier
11957dd7cddfSDavid du Colombier static uchar*
vlong2le(uchar * t,vlong from)11967dd7cddfSDavid du Colombier vlong2le(uchar *t, vlong from)
11977dd7cddfSDavid du Colombier {
11987dd7cddfSDavid du Colombier uchar *f, *o;
11997dd7cddfSDavid du Colombier int i;
12007dd7cddfSDavid du Colombier
12017dd7cddfSDavid du Colombier f = (uchar*)&from;
12027dd7cddfSDavid du Colombier o = (uchar*)&uvorder;
12037dd7cddfSDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
12047dd7cddfSDavid du Colombier t[i] = f[o[i]];
12057dd7cddfSDavid du Colombier return t+sizeof(vlong);
12067dd7cddfSDavid du Colombier }
12077dd7cddfSDavid du Colombier
12087dd7cddfSDavid du Colombier static long order = 0x00010203;
12097dd7cddfSDavid du Colombier
12107dd7cddfSDavid du Colombier static uchar*
le2long(long * to,uchar * f)12117dd7cddfSDavid du Colombier le2long(long *to, uchar *f)
12127dd7cddfSDavid du Colombier {
12137dd7cddfSDavid du Colombier uchar *t, *o;
12147dd7cddfSDavid du Colombier int i;
12157dd7cddfSDavid du Colombier
12167dd7cddfSDavid du Colombier t = (uchar*)to;
12177dd7cddfSDavid du Colombier o = (uchar*)ℴ
12187dd7cddfSDavid du Colombier for(i = 0; i < sizeof(long); i++)
12197dd7cddfSDavid du Colombier t[o[i]] = f[i];
12207dd7cddfSDavid du Colombier return f+sizeof(long);
12217dd7cddfSDavid du Colombier }
12227dd7cddfSDavid du Colombier
12237dd7cddfSDavid du Colombier static uchar*
long2le(uchar * t,long from)12247dd7cddfSDavid du Colombier long2le(uchar *t, long from)
12257dd7cddfSDavid du Colombier {
12267dd7cddfSDavid du Colombier uchar *f, *o;
12277dd7cddfSDavid du Colombier int i;
12287dd7cddfSDavid du Colombier
12297dd7cddfSDavid du Colombier f = (uchar*)&from;
12307dd7cddfSDavid du Colombier o = (uchar*)ℴ
12317dd7cddfSDavid du Colombier for(i = 0; i < sizeof(long); i++)
12327dd7cddfSDavid du Colombier t[i] = f[o[i]];
12337dd7cddfSDavid du Colombier return t+sizeof(long);
12347dd7cddfSDavid du Colombier }
12357dd7cddfSDavid du Colombier
12367dd7cddfSDavid du Colombier char *Ebadtimectl = "bad time control";
12377dd7cddfSDavid du Colombier
12387dd7cddfSDavid du Colombier /*
12397dd7cddfSDavid du Colombier * like the old #c/time but with added info. Return
12407dd7cddfSDavid du Colombier *
12417dd7cddfSDavid du Colombier * secs nanosecs fastticks fasthz
12427dd7cddfSDavid du Colombier */
12437dd7cddfSDavid du Colombier static int
readtime(ulong off,char * buf,int n)12447dd7cddfSDavid du Colombier readtime(ulong off, char *buf, int n)
12457dd7cddfSDavid du Colombier {
12467dd7cddfSDavid du Colombier vlong nsec, ticks;
12477dd7cddfSDavid du Colombier long sec;
124859cc4ca5SDavid du Colombier char str[7*NUMSIZE];
12497dd7cddfSDavid du Colombier
12507dd7cddfSDavid du Colombier nsec = todget(&ticks);
12517dd7cddfSDavid du Colombier if(fasthz == 0LL)
12527dd7cddfSDavid du Colombier fastticks((uvlong*)&fasthz);
12537dd7cddfSDavid du Colombier sec = nsec/1000000000ULL;
1254567483c8SDavid du Colombier snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
12557dd7cddfSDavid du Colombier NUMSIZE-1, sec,
12567dd7cddfSDavid du Colombier VLNUMSIZE-1, nsec,
12577dd7cddfSDavid du Colombier VLNUMSIZE-1, ticks,
12587dd7cddfSDavid du Colombier VLNUMSIZE-1, fasthz);
12597dd7cddfSDavid du Colombier return readstr(off, buf, n, str);
12607dd7cddfSDavid du Colombier }
12617dd7cddfSDavid du Colombier
12627dd7cddfSDavid du Colombier /*
12637dd7cddfSDavid du Colombier * set the time in seconds
12647dd7cddfSDavid du Colombier */
12657dd7cddfSDavid du Colombier static int
writetime(char * buf,int n)12667dd7cddfSDavid du Colombier writetime(char *buf, int n)
12677dd7cddfSDavid du Colombier {
12687dd7cddfSDavid du Colombier char b[13];
12697dd7cddfSDavid du Colombier long i;
12707dd7cddfSDavid du Colombier vlong now;
12717dd7cddfSDavid du Colombier
12727dd7cddfSDavid du Colombier if(n >= sizeof(b))
12737dd7cddfSDavid du Colombier error(Ebadtimectl);
12747dd7cddfSDavid du Colombier strncpy(b, buf, n);
12757dd7cddfSDavid du Colombier b[n] = 0;
12767dd7cddfSDavid du Colombier i = strtol(b, 0, 0);
12777dd7cddfSDavid du Colombier if(i <= 0)
12787dd7cddfSDavid du Colombier error(Ebadtimectl);
12797dd7cddfSDavid du Colombier now = i*1000000000LL;
12807dd7cddfSDavid du Colombier todset(now, 0, 0);
12817dd7cddfSDavid du Colombier return n;
12827dd7cddfSDavid du Colombier }
12837dd7cddfSDavid du Colombier
12847dd7cddfSDavid du Colombier /*
12857dd7cddfSDavid du Colombier * read binary time info. all numbers are little endian.
12867dd7cddfSDavid du Colombier * ticks and nsec are syncronized.
12877dd7cddfSDavid du Colombier */
12887dd7cddfSDavid du Colombier static int
readbintime(char * buf,int n)12897dd7cddfSDavid du Colombier readbintime(char *buf, int n)
12907dd7cddfSDavid du Colombier {
12917dd7cddfSDavid du Colombier int i;
12927dd7cddfSDavid du Colombier vlong nsec, ticks;
12937dd7cddfSDavid du Colombier uchar *b = (uchar*)buf;
12947dd7cddfSDavid du Colombier
12957dd7cddfSDavid du Colombier i = 0;
12967dd7cddfSDavid du Colombier if(fasthz == 0LL)
12977dd7cddfSDavid du Colombier fastticks((uvlong*)&fasthz);
12987dd7cddfSDavid du Colombier nsec = todget(&ticks);
12997dd7cddfSDavid du Colombier if(n >= 3*sizeof(uvlong)){
13007dd7cddfSDavid du Colombier vlong2le(b+2*sizeof(uvlong), fasthz);
13017dd7cddfSDavid du Colombier i += sizeof(uvlong);
13027dd7cddfSDavid du Colombier }
13037dd7cddfSDavid du Colombier if(n >= 2*sizeof(uvlong)){
13047dd7cddfSDavid du Colombier vlong2le(b+sizeof(uvlong), ticks);
13057dd7cddfSDavid du Colombier i += sizeof(uvlong);
13067dd7cddfSDavid du Colombier }
13077dd7cddfSDavid du Colombier if(n >= 8){
13087dd7cddfSDavid du Colombier vlong2le(b, nsec);
13097dd7cddfSDavid du Colombier i += sizeof(vlong);
13107dd7cddfSDavid du Colombier }
13117dd7cddfSDavid du Colombier return i;
13127dd7cddfSDavid du Colombier }
13137dd7cddfSDavid du Colombier
13147dd7cddfSDavid du Colombier /*
13157dd7cddfSDavid du Colombier * set any of the following
13167dd7cddfSDavid du Colombier * - time in nsec
13177dd7cddfSDavid du Colombier * - nsec trim applied over some seconds
13187dd7cddfSDavid du Colombier * - clock frequency
13197dd7cddfSDavid du Colombier */
13207dd7cddfSDavid du Colombier static int
writebintime(char * buf,int n)13217dd7cddfSDavid du Colombier writebintime(char *buf, int n)
13227dd7cddfSDavid du Colombier {
13237dd7cddfSDavid du Colombier uchar *p;
13247dd7cddfSDavid du Colombier vlong delta;
13257dd7cddfSDavid du Colombier long period;
13267dd7cddfSDavid du Colombier
13277dd7cddfSDavid du Colombier n--;
13287dd7cddfSDavid du Colombier p = (uchar*)buf + 1;
13297dd7cddfSDavid du Colombier switch(*buf){
13307dd7cddfSDavid du Colombier case 'n':
13317dd7cddfSDavid du Colombier if(n < sizeof(vlong))
13327dd7cddfSDavid du Colombier error(Ebadtimectl);
13337dd7cddfSDavid du Colombier le2vlong(&delta, p);
13347dd7cddfSDavid du Colombier todset(delta, 0, 0);
13357dd7cddfSDavid du Colombier break;
13367dd7cddfSDavid du Colombier case 'd':
13377dd7cddfSDavid du Colombier if(n < sizeof(vlong)+sizeof(long))
13387dd7cddfSDavid du Colombier error(Ebadtimectl);
13397dd7cddfSDavid du Colombier p = le2vlong(&delta, p);
13407dd7cddfSDavid du Colombier le2long(&period, p);
13417dd7cddfSDavid du Colombier todset(-1, delta, period);
13427dd7cddfSDavid du Colombier break;
13437dd7cddfSDavid du Colombier case 'f':
13447dd7cddfSDavid du Colombier if(n < sizeof(uvlong))
13457dd7cddfSDavid du Colombier error(Ebadtimectl);
13467dd7cddfSDavid du Colombier le2vlong(&fasthz, p);
1347d1be6b08SDavid du Colombier if(fasthz <= 0)
1348d1be6b08SDavid du Colombier error(Ebadtimectl);
13497dd7cddfSDavid du Colombier todsetfreq(fasthz);
13507dd7cddfSDavid du Colombier break;
13517dd7cddfSDavid du Colombier }
13527dd7cddfSDavid du Colombier return n;
13537dd7cddfSDavid du Colombier }
1354