18e32b400SDavid du Colombier #include "u.h"
28e32b400SDavid du Colombier #include "../port/lib.h"
38e32b400SDavid du Colombier #include "mem.h"
48e32b400SDavid du Colombier #include "dat.h"
58e32b400SDavid du Colombier #include "fns.h"
68e32b400SDavid du Colombier #include "../port/error.h"
78e32b400SDavid du Colombier #include "pool.h"
88e32b400SDavid du Colombier #include <authsrv.h>
98e32b400SDavid du Colombier
108e32b400SDavid du Colombier void (*consdebug)(void) = nil;
118e32b400SDavid du Colombier void (*screenputs)(char*, int) = nil;
128e32b400SDavid du Colombier
138e32b400SDavid du Colombier Queue* kbdq; /* unprocessed console input */
148e32b400SDavid du Colombier Queue* lineq; /* processed console input */
158e32b400SDavid du Colombier Queue* serialoq; /* serial console output */
168e32b400SDavid du Colombier Queue* kprintoq; /* console output, for /dev/kprint */
178e32b400SDavid du Colombier ulong kprintinuse; /* test and set whether /dev/kprint is open */
188e32b400SDavid du Colombier int iprintscreenputs = 1;
198e32b400SDavid du Colombier
208e32b400SDavid du Colombier int panicking;
218e32b400SDavid du Colombier
228e32b400SDavid du Colombier static struct
238e32b400SDavid du Colombier {
248e32b400SDavid du Colombier QLock;
258e32b400SDavid du Colombier
268e32b400SDavid du Colombier int raw; /* true if we shouldn't process input */
278e32b400SDavid du Colombier Ref ctl; /* number of opens to the control file */
288e32b400SDavid du Colombier int x; /* index into line */
298e32b400SDavid du Colombier char line[1024]; /* current input line */
308e32b400SDavid du Colombier
318e32b400SDavid du Colombier int count;
328e32b400SDavid du Colombier int ctlpoff;
338e32b400SDavid du Colombier
348e32b400SDavid du Colombier /* a place to save up characters at interrupt time before dumping them in the queue */
358e32b400SDavid du Colombier Lock lockputc;
368e32b400SDavid du Colombier char istage[1024];
378e32b400SDavid du Colombier char *iw;
388e32b400SDavid du Colombier char *ir;
398e32b400SDavid du Colombier char *ie;
408e32b400SDavid du Colombier } kbd = {
418e32b400SDavid du Colombier .iw = kbd.istage,
428e32b400SDavid du Colombier .ir = kbd.istage,
438e32b400SDavid du Colombier .ie = kbd.istage + sizeof(kbd.istage),
448e32b400SDavid du Colombier };
458e32b400SDavid du Colombier
468e32b400SDavid du Colombier char *sysname;
478e32b400SDavid du Colombier vlong fasthz;
488e32b400SDavid du Colombier
498e32b400SDavid du Colombier static void seedrand(void);
508e32b400SDavid du Colombier static int readtime(ulong, char*, int);
518e32b400SDavid du Colombier static int readbintime(char*, int);
528e32b400SDavid du Colombier static int writetime(char*, int);
538e32b400SDavid du Colombier static int writebintime(char*, int);
548e32b400SDavid du Colombier
558e32b400SDavid du Colombier enum
568e32b400SDavid du Colombier {
578e32b400SDavid du Colombier CMhalt,
588e32b400SDavid du Colombier CMreboot,
598e32b400SDavid du Colombier CMpanic,
608e32b400SDavid du Colombier };
618e32b400SDavid du Colombier
628e32b400SDavid du Colombier Cmdtab rebootmsg[] =
638e32b400SDavid du Colombier {
648e32b400SDavid du Colombier CMhalt, "halt", 1,
658e32b400SDavid du Colombier CMreboot, "reboot", 0,
668e32b400SDavid du Colombier CMpanic, "panic", 0,
678e32b400SDavid du Colombier };
688e32b400SDavid du Colombier
698e32b400SDavid du Colombier void
printinit(void)708e32b400SDavid du Colombier printinit(void)
718e32b400SDavid du Colombier {
728e32b400SDavid du Colombier lineq = qopen(2*1024, 0, nil, nil);
738e32b400SDavid du Colombier if(lineq == nil)
748e32b400SDavid du Colombier panic("printinit");
758e32b400SDavid du Colombier qnoblock(lineq, 1);
768e32b400SDavid du Colombier }
778e32b400SDavid du Colombier
788e32b400SDavid du Colombier int
consactive(void)798e32b400SDavid du Colombier consactive(void)
808e32b400SDavid du Colombier {
818e32b400SDavid du Colombier if(serialoq)
828e32b400SDavid du Colombier return qlen(serialoq) > 0;
838e32b400SDavid du Colombier return 0;
848e32b400SDavid du Colombier }
858e32b400SDavid du Colombier
868e32b400SDavid du Colombier void
prflush(void)878e32b400SDavid du Colombier prflush(void)
888e32b400SDavid du Colombier {
898e32b400SDavid du Colombier ulong now;
908e32b400SDavid du Colombier
918e32b400SDavid du Colombier now = m->ticks;
928e32b400SDavid du Colombier while(consactive())
938e32b400SDavid du Colombier if(m->ticks - now >= HZ)
948e32b400SDavid du Colombier break;
958e32b400SDavid du Colombier }
968e32b400SDavid du Colombier
978e32b400SDavid du Colombier /*
988e32b400SDavid du Colombier * Log console output so it can be retrieved via /dev/kmesg.
998e32b400SDavid du Colombier * This is good for catching boot-time messages after the fact.
1008e32b400SDavid du Colombier */
1018e32b400SDavid du Colombier struct {
1028e32b400SDavid du Colombier Lock lk;
103*e5a0fbb7SDavid du Colombier char buf[KMESGSIZE];
1048e32b400SDavid du Colombier uint n;
1058e32b400SDavid du Colombier } kmesg;
1068e32b400SDavid du Colombier
1078e32b400SDavid du Colombier static void
kmesgputs(char * str,int n)1088e32b400SDavid du Colombier kmesgputs(char *str, int n)
1098e32b400SDavid du Colombier {
1108e32b400SDavid du Colombier uint nn, d;
1118e32b400SDavid du Colombier
1128e32b400SDavid du Colombier ilock(&kmesg.lk);
1138e32b400SDavid du Colombier /* take the tail of huge writes */
1148e32b400SDavid du Colombier if(n > sizeof kmesg.buf){
1158e32b400SDavid du Colombier d = n - sizeof kmesg.buf;
1168e32b400SDavid du Colombier str += d;
1178e32b400SDavid du Colombier n -= d;
1188e32b400SDavid du Colombier }
1198e32b400SDavid du Colombier
1208e32b400SDavid du Colombier /* slide the buffer down to make room */
1218e32b400SDavid du Colombier nn = kmesg.n;
1228e32b400SDavid du Colombier if(nn + n >= sizeof kmesg.buf){
1238e32b400SDavid du Colombier d = nn + n - sizeof kmesg.buf;
1248e32b400SDavid du Colombier if(d)
1258e32b400SDavid du Colombier memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
1268e32b400SDavid du Colombier nn -= d;
1278e32b400SDavid du Colombier }
1288e32b400SDavid du Colombier
1298e32b400SDavid du Colombier /* copy the data in */
1308e32b400SDavid du Colombier memmove(kmesg.buf+nn, str, n);
1318e32b400SDavid du Colombier nn += n;
1328e32b400SDavid du Colombier kmesg.n = nn;
1338e32b400SDavid du Colombier iunlock(&kmesg.lk);
1348e32b400SDavid du Colombier }
1358e32b400SDavid du Colombier
1368e32b400SDavid du Colombier /*
1378e32b400SDavid du Colombier * Print a string on the console. Convert \n to \r\n for serial
1388e32b400SDavid du Colombier * line consoles. Locking of the queues is left up to the screen
1398e32b400SDavid du Colombier * or uart code. Multi-line messages to serial consoles may get
1408e32b400SDavid du Colombier * interspersed with other messages.
1418e32b400SDavid du Colombier */
1428e32b400SDavid du Colombier static void
putstrn0(char * str,int n,int usewrite)1438e32b400SDavid du Colombier putstrn0(char *str, int n, int usewrite)
1448e32b400SDavid du Colombier {
1458e32b400SDavid du Colombier int m;
1468e32b400SDavid du Colombier char *t;
1478e32b400SDavid du Colombier
1488e32b400SDavid du Colombier if(!islo())
1498e32b400SDavid du Colombier usewrite = 0;
1508e32b400SDavid du Colombier
1518e32b400SDavid du Colombier /*
1528e32b400SDavid du Colombier * how many different output devices do we need?
1538e32b400SDavid du Colombier */
1548e32b400SDavid du Colombier kmesgputs(str, n);
1558e32b400SDavid du Colombier
1568e32b400SDavid du Colombier /*
1578e32b400SDavid du Colombier * if someone is reading /dev/kprint,
1588e32b400SDavid du Colombier * put the message there.
1598e32b400SDavid du Colombier * if not and there's an attached bit mapped display,
1608e32b400SDavid du Colombier * put the message there.
1618e32b400SDavid du Colombier *
1628e32b400SDavid du Colombier * if there's a serial line being used as a console,
1638e32b400SDavid du Colombier * put the message there.
1648e32b400SDavid du Colombier */
1658e32b400SDavid du Colombier if(kprintoq != nil && !qisclosed(kprintoq)){
1668e32b400SDavid du Colombier if(usewrite)
1678e32b400SDavid du Colombier qwrite(kprintoq, str, n);
1688e32b400SDavid du Colombier else
1698e32b400SDavid du Colombier qiwrite(kprintoq, str, n);
1708e32b400SDavid du Colombier }else if(screenputs != nil)
1718e32b400SDavid du Colombier screenputs(str, n);
1728e32b400SDavid du Colombier
1738e32b400SDavid du Colombier if(serialoq == nil){
1748e32b400SDavid du Colombier uartputs(str, n);
1758e32b400SDavid du Colombier return;
1768e32b400SDavid du Colombier }
1778e32b400SDavid du Colombier
1788e32b400SDavid du Colombier while(n > 0) {
1798e32b400SDavid du Colombier t = memchr(str, '\n', n);
1808e32b400SDavid du Colombier if(t && !kbd.raw) {
1818e32b400SDavid du Colombier m = t-str;
1828e32b400SDavid du Colombier if(usewrite){
1838e32b400SDavid du Colombier qwrite(serialoq, str, m);
1848e32b400SDavid du Colombier qwrite(serialoq, "\r\n", 2);
1858e32b400SDavid du Colombier } else {
1868e32b400SDavid du Colombier qiwrite(serialoq, str, m);
1878e32b400SDavid du Colombier qiwrite(serialoq, "\r\n", 2);
1888e32b400SDavid du Colombier }
1898e32b400SDavid du Colombier n -= m+1;
1908e32b400SDavid du Colombier str = t+1;
1918e32b400SDavid du Colombier } else {
1928e32b400SDavid du Colombier if(usewrite)
1938e32b400SDavid du Colombier qwrite(serialoq, str, n);
1948e32b400SDavid du Colombier else
1958e32b400SDavid du Colombier qiwrite(serialoq, str, n);
1968e32b400SDavid du Colombier break;
1978e32b400SDavid du Colombier }
1988e32b400SDavid du Colombier }
1998e32b400SDavid du Colombier }
2008e32b400SDavid du Colombier
2018e32b400SDavid du Colombier void
putstrn(char * str,int n)2028e32b400SDavid du Colombier putstrn(char *str, int n)
2038e32b400SDavid du Colombier {
2048e32b400SDavid du Colombier putstrn0(str, n, 0);
2058e32b400SDavid du Colombier }
2068e32b400SDavid du Colombier
2078e32b400SDavid du Colombier int noprint;
2088e32b400SDavid du Colombier
2098e32b400SDavid du Colombier int
print(char * fmt,...)2108e32b400SDavid du Colombier print(char *fmt, ...)
2118e32b400SDavid du Colombier {
2128e32b400SDavid du Colombier int n;
2138e32b400SDavid du Colombier va_list arg;
2148e32b400SDavid du Colombier char buf[PRINTSIZE];
2158e32b400SDavid du Colombier
2168e32b400SDavid du Colombier if(noprint)
2178e32b400SDavid du Colombier return -1;
2188e32b400SDavid du Colombier
2198e32b400SDavid du Colombier va_start(arg, fmt);
2208e32b400SDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
2218e32b400SDavid du Colombier va_end(arg);
22293631029SDavid du Colombier
22393631029SDavid du Colombier if(!normalprint) {
22493631029SDavid du Colombier if(0) iprint("\nprint called too early from %#lux\n",
22593631029SDavid du Colombier getcallerpc(&fmt));
22693631029SDavid du Colombier iprint("%.*s", n, buf);
22793631029SDavid du Colombier } else
2288e32b400SDavid du Colombier putstrn(buf, n);
2298e32b400SDavid du Colombier
2308e32b400SDavid du Colombier return n;
2318e32b400SDavid du Colombier }
2328e32b400SDavid du Colombier
2338e32b400SDavid du Colombier /*
2348e32b400SDavid du Colombier * Want to interlock iprints to avoid interlaced output on
2358e32b400SDavid du Colombier * multiprocessor, but don't want to deadlock if one processor
2368e32b400SDavid du Colombier * dies during print and another has something important to say.
2378e32b400SDavid du Colombier * Make a good faith effort.
2388e32b400SDavid du Colombier */
2398e32b400SDavid du Colombier static Lock iprintlock;
2408e32b400SDavid du Colombier static int
iprintcanlock(Lock * l)2418e32b400SDavid du Colombier iprintcanlock(Lock *l)
2428e32b400SDavid du Colombier {
2438e32b400SDavid du Colombier int i;
2448e32b400SDavid du Colombier
2458e32b400SDavid du Colombier for(i=0; i<1000; i++){
2468e32b400SDavid du Colombier if(canlock(l))
2478e32b400SDavid du Colombier return 1;
2488e32b400SDavid du Colombier if(l->m == MACHP(m->machno))
2498e32b400SDavid du Colombier return 0;
2508e32b400SDavid du Colombier microdelay(100);
2518e32b400SDavid du Colombier }
2528e32b400SDavid du Colombier return 0;
2538e32b400SDavid du Colombier }
2548e32b400SDavid du Colombier
2558e32b400SDavid du Colombier int
iprint(char * fmt,...)2568e32b400SDavid du Colombier iprint(char *fmt, ...)
2578e32b400SDavid du Colombier {
2588e32b400SDavid du Colombier int n, s, locked;
2598e32b400SDavid du Colombier va_list arg;
2608e32b400SDavid du Colombier char buf[PRINTSIZE];
2618e32b400SDavid du Colombier
2628e32b400SDavid du Colombier s = splhi();
2638e32b400SDavid du Colombier va_start(arg, fmt);
2648e32b400SDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
2658e32b400SDavid du Colombier va_end(arg);
2668e32b400SDavid du Colombier locked = iprintcanlock(&iprintlock);
2678e32b400SDavid du Colombier if(screenputs != nil && iprintscreenputs)
2688e32b400SDavid du Colombier screenputs(buf, n);
26993631029SDavid du Colombier if(consuart == nil || consuart->phys == nil ||
27093631029SDavid du Colombier consuart->phys->putc == nil)
27193631029SDavid du Colombier _uartputs(buf, n);
27293631029SDavid du Colombier else
2738e32b400SDavid du Colombier uartputs(buf, n);
2748e32b400SDavid du Colombier if(locked)
2758e32b400SDavid du Colombier unlock(&iprintlock);
2768e32b400SDavid du Colombier splx(s);
2778e32b400SDavid du Colombier
2788e32b400SDavid du Colombier return n;
2798e32b400SDavid du Colombier }
2808e32b400SDavid du Colombier
2818e32b400SDavid du Colombier void
panic(char * fmt,...)2828e32b400SDavid du Colombier panic(char *fmt, ...)
2838e32b400SDavid du Colombier {
2848e32b400SDavid du Colombier int n, s;
2858e32b400SDavid du Colombier va_list arg;
2868e32b400SDavid du Colombier char buf[PRINTSIZE];
2878e32b400SDavid du Colombier
2888e32b400SDavid du Colombier kprintoq = nil; /* don't try to write to /dev/kprint */
2898e32b400SDavid du Colombier
2908e32b400SDavid du Colombier if(panicking)
2918e32b400SDavid du Colombier for(;;);
2928e32b400SDavid du Colombier panicking = 1;
2938e32b400SDavid du Colombier
2948e32b400SDavid du Colombier delay(20);
2958e32b400SDavid du Colombier s = splhi();
2968e32b400SDavid du Colombier strcpy(buf, "panic: ");
2978e32b400SDavid du Colombier va_start(arg, fmt);
2988e32b400SDavid du Colombier n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
2998e32b400SDavid du Colombier va_end(arg);
3008e32b400SDavid du Colombier iprint("%s\n", buf);
3018e32b400SDavid du Colombier if(consdebug)
3028e32b400SDavid du Colombier (*consdebug)();
3038e32b400SDavid du Colombier splx(s);
3048e32b400SDavid du Colombier prflush();
3058e32b400SDavid du Colombier buf[n] = '\n';
306047f1f95SDavid du Colombier // putstrn(buf, n+1);
307047f1f95SDavid du Colombier // dumpstack();
3088e32b400SDavid du Colombier
3098e32b400SDavid du Colombier exit(1);
3108e32b400SDavid du Colombier }
3118e32b400SDavid du Colombier
3128e32b400SDavid du Colombier /* libmp at least contains a few calls to sysfatal; simulate with panic */
3138e32b400SDavid du Colombier void
sysfatal(char * fmt,...)3148e32b400SDavid du Colombier sysfatal(char *fmt, ...)
3158e32b400SDavid du Colombier {
3168e32b400SDavid du Colombier char err[256];
3178e32b400SDavid du Colombier va_list arg;
3188e32b400SDavid du Colombier
3198e32b400SDavid du Colombier va_start(arg, fmt);
3208e32b400SDavid du Colombier vseprint(err, err + sizeof err, fmt, arg);
3218e32b400SDavid du Colombier va_end(arg);
3228e32b400SDavid du Colombier panic("sysfatal: %s", err);
3238e32b400SDavid du Colombier }
3248e32b400SDavid du Colombier
3258e32b400SDavid du Colombier void
_assert(char * fmt)3268e32b400SDavid du Colombier _assert(char *fmt)
3278e32b400SDavid du Colombier {
3288e32b400SDavid du Colombier panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
3298e32b400SDavid du Colombier }
3308e32b400SDavid du Colombier
3318e32b400SDavid du Colombier int
pprint(char * fmt,...)3328e32b400SDavid du Colombier pprint(char *fmt, ...)
3338e32b400SDavid du Colombier {
3348e32b400SDavid du Colombier int n;
3358e32b400SDavid du Colombier Chan *c;
3368e32b400SDavid du Colombier va_list arg;
3378e32b400SDavid du Colombier char buf[2*PRINTSIZE];
3388e32b400SDavid du Colombier
3398e32b400SDavid du Colombier if(up == nil || up->fgrp == nil)
3408e32b400SDavid du Colombier return 0;
3418e32b400SDavid du Colombier
3428e32b400SDavid du Colombier c = up->fgrp->fd[2];
3438e32b400SDavid du Colombier if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
3448e32b400SDavid du Colombier return 0;
3458e32b400SDavid du Colombier n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
3468e32b400SDavid du Colombier va_start(arg, fmt);
3478e32b400SDavid du Colombier n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
3488e32b400SDavid du Colombier va_end(arg);
3498e32b400SDavid du Colombier
3508e32b400SDavid du Colombier if(waserror())
3518e32b400SDavid du Colombier return 0;
3528e32b400SDavid du Colombier devtab[c->type]->write(c, buf, n, c->offset);
3538e32b400SDavid du Colombier poperror();
3548e32b400SDavid du Colombier
3558e32b400SDavid du Colombier lock(c);
3568e32b400SDavid du Colombier c->offset += n;
3578e32b400SDavid du Colombier unlock(c);
3588e32b400SDavid du Colombier
3598e32b400SDavid du Colombier return n;
3608e32b400SDavid du Colombier }
3618e32b400SDavid du Colombier
3628e32b400SDavid du Colombier static void
echoscreen(char * buf,int n)3638e32b400SDavid du Colombier echoscreen(char *buf, int n)
3648e32b400SDavid du Colombier {
3658e32b400SDavid du Colombier char *e, *p;
3668e32b400SDavid du Colombier char ebuf[128];
3678e32b400SDavid du Colombier int x;
3688e32b400SDavid du Colombier
3698e32b400SDavid du Colombier p = ebuf;
3708e32b400SDavid du Colombier e = ebuf + sizeof(ebuf) - 4;
3718e32b400SDavid du Colombier while(n-- > 0){
3728e32b400SDavid du Colombier if(p >= e){
3738e32b400SDavid du Colombier screenputs(ebuf, p - ebuf);
3748e32b400SDavid du Colombier p = ebuf;
3758e32b400SDavid du Colombier }
3768e32b400SDavid du Colombier x = *buf++;
3778e32b400SDavid du Colombier if(x == 0x15){
3788e32b400SDavid du Colombier *p++ = '^';
3798e32b400SDavid du Colombier *p++ = 'U';
3808e32b400SDavid du Colombier *p++ = '\n';
3818e32b400SDavid du Colombier } else
3828e32b400SDavid du Colombier *p++ = x;
3838e32b400SDavid du Colombier }
3848e32b400SDavid du Colombier if(p != ebuf)
3858e32b400SDavid du Colombier screenputs(ebuf, p - ebuf);
3868e32b400SDavid du Colombier }
3878e32b400SDavid du Colombier
3888e32b400SDavid du Colombier static void
echoserialoq(char * buf,int n)3898e32b400SDavid du Colombier echoserialoq(char *buf, int n)
3908e32b400SDavid du Colombier {
3918e32b400SDavid du Colombier int x;
3928e32b400SDavid du Colombier char *e, *p;
3938e32b400SDavid du Colombier char ebuf[128];
3948e32b400SDavid du Colombier
3958e32b400SDavid du Colombier p = ebuf;
3968e32b400SDavid du Colombier e = ebuf + sizeof(ebuf) - 4;
3978e32b400SDavid du Colombier while(n-- > 0){
3988e32b400SDavid du Colombier if(p >= e){
3998e32b400SDavid du Colombier qiwrite(serialoq, ebuf, p - ebuf);
4008e32b400SDavid du Colombier p = ebuf;
4018e32b400SDavid du Colombier }
4028e32b400SDavid du Colombier x = *buf++;
4038e32b400SDavid du Colombier if(x == '\n'){
4048e32b400SDavid du Colombier *p++ = '\r';
4058e32b400SDavid du Colombier *p++ = '\n';
4068e32b400SDavid du Colombier } else if(x == 0x15){
4078e32b400SDavid du Colombier *p++ = '^';
4088e32b400SDavid du Colombier *p++ = 'U';
4098e32b400SDavid du Colombier *p++ = '\n';
4108e32b400SDavid du Colombier } else
4118e32b400SDavid du Colombier *p++ = x;
4128e32b400SDavid du Colombier }
4138e32b400SDavid du Colombier if(p != ebuf)
4148e32b400SDavid du Colombier qiwrite(serialoq, ebuf, p - ebuf);
4158e32b400SDavid du Colombier }
4168e32b400SDavid du Colombier
4178e32b400SDavid du Colombier static void
echo(char * buf,int n)4188e32b400SDavid du Colombier echo(char *buf, int n)
4198e32b400SDavid du Colombier {
4208e32b400SDavid du Colombier static int ctrlt, pid;
4218e32b400SDavid du Colombier int x;
4228e32b400SDavid du Colombier char *e, *p;
4238e32b400SDavid du Colombier
4248e32b400SDavid du Colombier if(n == 0)
4258e32b400SDavid du Colombier return;
4268e32b400SDavid du Colombier
4278e32b400SDavid du Colombier e = buf+n;
4288e32b400SDavid du Colombier for(p = buf; p < e; p++){
4298e32b400SDavid du Colombier switch(*p){
4308e32b400SDavid du Colombier case 0x10: /* ^P */
4318e32b400SDavid du Colombier if(cpuserver && !kbd.ctlpoff){
4328e32b400SDavid du Colombier active.exiting = 1;
4338e32b400SDavid du Colombier return;
4348e32b400SDavid du Colombier }
4358e32b400SDavid du Colombier break;
4368e32b400SDavid du Colombier case 0x14: /* ^T */
4378e32b400SDavid du Colombier ctrlt++;
4388e32b400SDavid du Colombier if(ctrlt > 2)
4398e32b400SDavid du Colombier ctrlt = 2;
4408e32b400SDavid du Colombier continue;
4418e32b400SDavid du Colombier }
4428e32b400SDavid du Colombier
4438e32b400SDavid du Colombier if(ctrlt != 2)
4448e32b400SDavid du Colombier continue;
4458e32b400SDavid du Colombier
4468e32b400SDavid du Colombier /* ^T escapes */
4478e32b400SDavid du Colombier ctrlt = 0;
4488e32b400SDavid du Colombier switch(*p){
4498e32b400SDavid du Colombier case 'S':
4508e32b400SDavid du Colombier x = splhi();
4518e32b400SDavid du Colombier dumpstack();
4528e32b400SDavid du Colombier procdump();
4538e32b400SDavid du Colombier splx(x);
4548e32b400SDavid du Colombier return;
4558e32b400SDavid du Colombier case 's':
4568e32b400SDavid du Colombier dumpstack();
4578e32b400SDavid du Colombier return;
4588e32b400SDavid du Colombier case 'x':
4598e32b400SDavid du Colombier xsummary();
4608e32b400SDavid du Colombier ixsummary();
4618e32b400SDavid du Colombier mallocsummary();
4628e32b400SDavid du Colombier // memorysummary();
4638e32b400SDavid du Colombier pagersummary();
4648e32b400SDavid du Colombier return;
4658e32b400SDavid du Colombier case 'd':
4668e32b400SDavid du Colombier if(consdebug == nil)
4678e32b400SDavid du Colombier consdebug = rdb;
4688e32b400SDavid du Colombier else
4698e32b400SDavid du Colombier consdebug = nil;
4708e32b400SDavid du Colombier print("consdebug now %#p\n", consdebug);
4718e32b400SDavid du Colombier return;
4728e32b400SDavid du Colombier case 'D':
4738e32b400SDavid du Colombier if(consdebug == nil)
4748e32b400SDavid du Colombier consdebug = rdb;
4758e32b400SDavid du Colombier consdebug();
4768e32b400SDavid du Colombier return;
4778e32b400SDavid du Colombier case 'p':
4788e32b400SDavid du Colombier x = spllo();
4798e32b400SDavid du Colombier procdump();
4808e32b400SDavid du Colombier splx(x);
4818e32b400SDavid du Colombier return;
4828e32b400SDavid du Colombier case 'q':
4838e32b400SDavid du Colombier scheddump();
4848e32b400SDavid du Colombier return;
4858e32b400SDavid du Colombier case 'k':
4868e32b400SDavid du Colombier killbig("^t ^t k");
4878e32b400SDavid du Colombier return;
4888e32b400SDavid du Colombier case 'r':
4898e32b400SDavid du Colombier exit(0);
4908e32b400SDavid du Colombier return;
4918e32b400SDavid du Colombier }
4928e32b400SDavid du Colombier }
4938e32b400SDavid du Colombier
4948e32b400SDavid du Colombier qproduce(kbdq, buf, n);
4958e32b400SDavid du Colombier if(kbd.raw)
4968e32b400SDavid du Colombier return;
4978e32b400SDavid du Colombier kmesgputs(buf, n);
4988e32b400SDavid du Colombier if(screenputs != nil)
4998e32b400SDavid du Colombier echoscreen(buf, n);
5008e32b400SDavid du Colombier if(serialoq)
5018e32b400SDavid du Colombier echoserialoq(buf, n);
5028e32b400SDavid du Colombier }
5038e32b400SDavid du Colombier
5048e32b400SDavid du Colombier /*
5058e32b400SDavid du Colombier * Called by a uart interrupt for console input.
5068e32b400SDavid du Colombier *
5078e32b400SDavid du Colombier * turn '\r' into '\n' before putting it into the queue.
5088e32b400SDavid du Colombier */
5098e32b400SDavid du Colombier int
kbdcr2nl(Queue *,int ch)5108e32b400SDavid du Colombier kbdcr2nl(Queue*, int ch)
5118e32b400SDavid du Colombier {
5128e32b400SDavid du Colombier char *next;
5138e32b400SDavid du Colombier
5148e32b400SDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
5158e32b400SDavid du Colombier if(ch == '\r' && !kbd.raw)
5168e32b400SDavid du Colombier ch = '\n';
5178e32b400SDavid du Colombier next = kbd.iw+1;
5188e32b400SDavid du Colombier if(next >= kbd.ie)
5198e32b400SDavid du Colombier next = kbd.istage;
5208e32b400SDavid du Colombier if(next != kbd.ir){
5218e32b400SDavid du Colombier *kbd.iw = ch;
5228e32b400SDavid du Colombier kbd.iw = next;
5238e32b400SDavid du Colombier }
5248e32b400SDavid du Colombier iunlock(&kbd.lockputc);
5258e32b400SDavid du Colombier return 0;
5268e32b400SDavid du Colombier }
5278e32b400SDavid du Colombier
5288e32b400SDavid du Colombier /*
5298e32b400SDavid du Colombier * Put character, possibly a rune, into read queue at interrupt time.
5308e32b400SDavid du Colombier * Called at interrupt time to process a character.
5318e32b400SDavid du Colombier */
5328e32b400SDavid du Colombier int
kbdputc(Queue *,int ch)5338e32b400SDavid du Colombier kbdputc(Queue*, int ch)
5348e32b400SDavid du Colombier {
5358e32b400SDavid du Colombier int i, n;
5368e32b400SDavid du Colombier char buf[3];
5378e32b400SDavid du Colombier Rune r;
5388e32b400SDavid du Colombier char *next;
5398e32b400SDavid du Colombier
5408e32b400SDavid du Colombier if(kbd.ir == nil)
5418e32b400SDavid du Colombier return 0; /* in case we're not inited yet */
5428e32b400SDavid du Colombier
5438e32b400SDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
5448e32b400SDavid du Colombier r = ch;
5458e32b400SDavid du Colombier n = runetochar(buf, &r);
5468e32b400SDavid du Colombier for(i = 0; i < n; i++){
5478e32b400SDavid du Colombier next = kbd.iw+1;
5488e32b400SDavid du Colombier if(next >= kbd.ie)
5498e32b400SDavid du Colombier next = kbd.istage;
5508e32b400SDavid du Colombier if(next == kbd.ir)
5518e32b400SDavid du Colombier break;
5528e32b400SDavid du Colombier *kbd.iw = buf[i];
5538e32b400SDavid du Colombier kbd.iw = next;
5548e32b400SDavid du Colombier }
5558e32b400SDavid du Colombier iunlock(&kbd.lockputc);
5568e32b400SDavid du Colombier return 0;
5578e32b400SDavid du Colombier }
5588e32b400SDavid du Colombier
5598e32b400SDavid du Colombier /*
5608e32b400SDavid du Colombier * we save up input characters till clock time to reduce
5618e32b400SDavid du Colombier * per character interrupt overhead.
5628e32b400SDavid du Colombier */
5638e32b400SDavid du Colombier static void
kbdputcclock(void)5648e32b400SDavid du Colombier kbdputcclock(void)
5658e32b400SDavid du Colombier {
5668e32b400SDavid du Colombier char *iw;
5678e32b400SDavid du Colombier
5688e32b400SDavid du Colombier /* this amortizes cost of qproduce */
5698e32b400SDavid du Colombier if(kbd.iw != kbd.ir){
5708e32b400SDavid du Colombier iw = kbd.iw;
5718e32b400SDavid du Colombier if(iw < kbd.ir){
5728e32b400SDavid du Colombier echo(kbd.ir, kbd.ie-kbd.ir);
5738e32b400SDavid du Colombier kbd.ir = kbd.istage;
5748e32b400SDavid du Colombier }
5758e32b400SDavid du Colombier if(kbd.ir != iw){
5768e32b400SDavid du Colombier echo(kbd.ir, iw-kbd.ir);
5778e32b400SDavid du Colombier kbd.ir = iw;
5788e32b400SDavid du Colombier }
5798e32b400SDavid du Colombier }
5808e32b400SDavid du Colombier }
5818e32b400SDavid du Colombier
5828e32b400SDavid du Colombier enum{
5838e32b400SDavid du Colombier Qdir,
5848e32b400SDavid du Colombier Qbintime,
5858e32b400SDavid du Colombier Qcons,
5868e32b400SDavid du Colombier Qconsctl,
5878e32b400SDavid du Colombier Qcputime,
5888e32b400SDavid du Colombier Qdrivers,
5898e32b400SDavid du Colombier Qkmesg,
5908e32b400SDavid du Colombier Qkprint,
5918e32b400SDavid du Colombier Qhostdomain,
5928e32b400SDavid du Colombier Qhostowner,
5938e32b400SDavid du Colombier Qnull,
5948e32b400SDavid du Colombier Qosversion,
5958e32b400SDavid du Colombier Qpgrpid,
5968e32b400SDavid du Colombier Qpid,
5978e32b400SDavid du Colombier Qppid,
5988e32b400SDavid du Colombier Qrandom,
5998e32b400SDavid du Colombier Qreboot,
6008e32b400SDavid du Colombier Qswap,
6018e32b400SDavid du Colombier Qsysname,
6028e32b400SDavid du Colombier Qsysstat,
6038e32b400SDavid du Colombier Qtime,
6048e32b400SDavid du Colombier Quser,
6058e32b400SDavid du Colombier Qzero,
6068e32b400SDavid du Colombier };
6078e32b400SDavid du Colombier
6088e32b400SDavid du Colombier enum
6098e32b400SDavid du Colombier {
6108e32b400SDavid du Colombier VLNUMSIZE= 22,
6118e32b400SDavid du Colombier };
6128e32b400SDavid du Colombier
6138e32b400SDavid du Colombier static Dirtab consdir[]={
6148e32b400SDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
6158e32b400SDavid du Colombier "bintime", {Qbintime}, 24, 0664,
6168e32b400SDavid du Colombier "cons", {Qcons}, 0, 0660,
6178e32b400SDavid du Colombier "consctl", {Qconsctl}, 0, 0220,
6188e32b400SDavid du Colombier "cputime", {Qcputime}, 6*NUMSIZE, 0444,
6198e32b400SDavid du Colombier "drivers", {Qdrivers}, 0, 0444,
6208e32b400SDavid du Colombier "hostdomain", {Qhostdomain}, DOMLEN, 0664,
6218e32b400SDavid du Colombier "hostowner", {Qhostowner}, 0, 0664,
6228e32b400SDavid du Colombier "kmesg", {Qkmesg}, 0, 0440,
6238e32b400SDavid du Colombier "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
6248e32b400SDavid du Colombier "null", {Qnull}, 0, 0666,
6258e32b400SDavid du Colombier "osversion", {Qosversion}, 0, 0444,
6268e32b400SDavid du Colombier "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
6278e32b400SDavid du Colombier "pid", {Qpid}, NUMSIZE, 0444,
6288e32b400SDavid du Colombier "ppid", {Qppid}, NUMSIZE, 0444,
6298e32b400SDavid du Colombier "random", {Qrandom}, 0, 0444,
6308e32b400SDavid du Colombier "reboot", {Qreboot}, 0, 0664,
6318e32b400SDavid du Colombier "swap", {Qswap}, 0, 0664,
6328e32b400SDavid du Colombier "sysname", {Qsysname}, 0, 0664,
6338e32b400SDavid du Colombier "sysstat", {Qsysstat}, 0, 0666,
6348e32b400SDavid du Colombier "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
6358e32b400SDavid du Colombier "user", {Quser}, 0, 0666,
6368e32b400SDavid du Colombier "zero", {Qzero}, 0, 0444,
6378e32b400SDavid du Colombier };
6388e32b400SDavid du Colombier
6398e32b400SDavid du Colombier int
readnum(ulong off,char * buf,ulong n,ulong val,int size)6408e32b400SDavid du Colombier readnum(ulong off, char *buf, ulong n, ulong val, int size)
6418e32b400SDavid du Colombier {
6428e32b400SDavid du Colombier char tmp[64];
6438e32b400SDavid du Colombier
6448e32b400SDavid du Colombier snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
6458e32b400SDavid du Colombier tmp[size-1] = ' ';
6468e32b400SDavid du Colombier if(off >= size)
6478e32b400SDavid du Colombier return 0;
6488e32b400SDavid du Colombier if(off+n > size)
6498e32b400SDavid du Colombier n = size-off;
6508e32b400SDavid du Colombier memmove(buf, tmp+off, n);
6518e32b400SDavid du Colombier return n;
6528e32b400SDavid du Colombier }
6538e32b400SDavid du Colombier
6548e32b400SDavid du Colombier int
readstr(ulong off,char * buf,ulong n,char * str)6558e32b400SDavid du Colombier readstr(ulong off, char *buf, ulong n, char *str)
6568e32b400SDavid du Colombier {
6578e32b400SDavid du Colombier int size;
6588e32b400SDavid du Colombier
6598e32b400SDavid du Colombier size = strlen(str);
6608e32b400SDavid du Colombier if(off >= size)
6618e32b400SDavid du Colombier return 0;
6628e32b400SDavid du Colombier if(off+n > size)
6638e32b400SDavid du Colombier n = size-off;
6648e32b400SDavid du Colombier memmove(buf, str+off, n);
6658e32b400SDavid du Colombier return n;
6668e32b400SDavid du Colombier }
6678e32b400SDavid du Colombier
6688e32b400SDavid du Colombier static void
consinit(void)6698e32b400SDavid du Colombier consinit(void)
6708e32b400SDavid du Colombier {
6718e32b400SDavid du Colombier todinit();
6728e32b400SDavid du Colombier randominit();
6738e32b400SDavid du Colombier /*
6748e32b400SDavid du Colombier * at 115200 baud, the 1024 char buffer takes 56 ms to process,
6758e32b400SDavid du Colombier * processing it every 22 ms should be fine
6768e32b400SDavid du Colombier */
6778e32b400SDavid du Colombier addclock0link(kbdputcclock, 22);
6788e32b400SDavid du Colombier }
6798e32b400SDavid du Colombier
6808e32b400SDavid du Colombier static Chan*
consattach(char * spec)6818e32b400SDavid du Colombier consattach(char *spec)
6828e32b400SDavid du Colombier {
6838e32b400SDavid du Colombier return devattach('c', spec);
6848e32b400SDavid du Colombier }
6858e32b400SDavid du Colombier
6868e32b400SDavid du Colombier static Walkqid*
conswalk(Chan * c,Chan * nc,char ** name,int nname)6878e32b400SDavid du Colombier conswalk(Chan *c, Chan *nc, char **name, int nname)
6888e32b400SDavid du Colombier {
6898e32b400SDavid du Colombier return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
6908e32b400SDavid du Colombier }
6918e32b400SDavid du Colombier
6928e32b400SDavid du Colombier static int
consstat(Chan * c,uchar * dp,int n)6938e32b400SDavid du Colombier consstat(Chan *c, uchar *dp, int n)
6948e32b400SDavid du Colombier {
6958e32b400SDavid du Colombier return devstat(c, dp, n, consdir, nelem(consdir), devgen);
6968e32b400SDavid du Colombier }
6978e32b400SDavid du Colombier
6988e32b400SDavid du Colombier static Chan*
consopen(Chan * c,int omode)6998e32b400SDavid du Colombier consopen(Chan *c, int omode)
7008e32b400SDavid du Colombier {
7018e32b400SDavid du Colombier c->aux = nil;
7028e32b400SDavid du Colombier c = devopen(c, omode, consdir, nelem(consdir), devgen);
7038e32b400SDavid du Colombier switch((ulong)c->qid.path){
7048e32b400SDavid du Colombier case Qconsctl:
7058e32b400SDavid du Colombier incref(&kbd.ctl);
7068e32b400SDavid du Colombier break;
7078e32b400SDavid du Colombier
7088e32b400SDavid du Colombier case Qkprint:
7098e32b400SDavid du Colombier if(tas(&kprintinuse) != 0){
7108e32b400SDavid du Colombier c->flag &= ~COPEN;
7118e32b400SDavid du Colombier error(Einuse);
7128e32b400SDavid du Colombier }
7138e32b400SDavid du Colombier if(kprintoq == nil){
7148e32b400SDavid du Colombier kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
7158e32b400SDavid du Colombier if(kprintoq == nil){
7168e32b400SDavid du Colombier c->flag &= ~COPEN;
7178e32b400SDavid du Colombier error(Enomem);
7188e32b400SDavid du Colombier }
7198e32b400SDavid du Colombier qnoblock(kprintoq, 1);
7208e32b400SDavid du Colombier }else
7218e32b400SDavid du Colombier qreopen(kprintoq);
7228e32b400SDavid du Colombier c->iounit = qiomaxatomic;
7238e32b400SDavid du Colombier break;
7248e32b400SDavid du Colombier }
7258e32b400SDavid du Colombier return c;
7268e32b400SDavid du Colombier }
7278e32b400SDavid du Colombier
7288e32b400SDavid du Colombier static void
consclose(Chan * c)7298e32b400SDavid du Colombier consclose(Chan *c)
7308e32b400SDavid du Colombier {
7318e32b400SDavid du Colombier switch((ulong)c->qid.path){
7328e32b400SDavid du Colombier /* last close of control file turns off raw */
7338e32b400SDavid du Colombier case Qconsctl:
7348e32b400SDavid du Colombier if(c->flag&COPEN){
7358e32b400SDavid du Colombier if(decref(&kbd.ctl) == 0)
7368e32b400SDavid du Colombier kbd.raw = 0;
7378e32b400SDavid du Colombier }
7388e32b400SDavid du Colombier break;
7398e32b400SDavid du Colombier
7408e32b400SDavid du Colombier /* close of kprint allows other opens */
7418e32b400SDavid du Colombier case Qkprint:
7428e32b400SDavid du Colombier if(c->flag & COPEN){
7438e32b400SDavid du Colombier kprintinuse = 0;
7448e32b400SDavid du Colombier qhangup(kprintoq, nil);
7458e32b400SDavid du Colombier }
7468e32b400SDavid du Colombier break;
7478e32b400SDavid du Colombier }
7488e32b400SDavid du Colombier }
7498e32b400SDavid du Colombier
7508e32b400SDavid du Colombier static long
consread(Chan * c,void * buf,long n,vlong off)7518e32b400SDavid du Colombier consread(Chan *c, void *buf, long n, vlong off)
7528e32b400SDavid du Colombier {
7538e32b400SDavid du Colombier ulong l;
7548e32b400SDavid du Colombier Mach *mp;
7558e32b400SDavid du Colombier char *b, *bp, ch;
7568e32b400SDavid du Colombier char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
7578e32b400SDavid du Colombier int i, k, id, send;
7588e32b400SDavid du Colombier vlong offset = off;
7598e32b400SDavid du Colombier
7608e32b400SDavid du Colombier if(n <= 0)
7618e32b400SDavid du Colombier return n;
7628e32b400SDavid du Colombier
7638e32b400SDavid du Colombier switch((ulong)c->qid.path){
7648e32b400SDavid du Colombier case Qdir:
7658e32b400SDavid du Colombier return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
7668e32b400SDavid du Colombier
7678e32b400SDavid du Colombier case Qcons:
7688e32b400SDavid du Colombier qlock(&kbd);
7698e32b400SDavid du Colombier if(waserror()) {
7708e32b400SDavid du Colombier qunlock(&kbd);
7718e32b400SDavid du Colombier nexterror();
7728e32b400SDavid du Colombier }
7738e32b400SDavid du Colombier while(!qcanread(lineq)){
7748e32b400SDavid du Colombier if(qread(kbdq, &ch, 1) == 0)
7758e32b400SDavid du Colombier continue;
7768e32b400SDavid du Colombier send = 0;
7778e32b400SDavid du Colombier if(ch == 0){
7788e32b400SDavid du Colombier /* flush output on rawoff -> rawon */
7798e32b400SDavid du Colombier if(kbd.x > 0)
7808e32b400SDavid du Colombier send = !qcanread(kbdq);
7818e32b400SDavid du Colombier }else if(kbd.raw){
7828e32b400SDavid du Colombier kbd.line[kbd.x++] = ch;
7838e32b400SDavid du Colombier send = !qcanread(kbdq);
7848e32b400SDavid du Colombier }else{
7858e32b400SDavid du Colombier switch(ch){
7868e32b400SDavid du Colombier case '\b':
7878e32b400SDavid du Colombier if(kbd.x > 0)
7888e32b400SDavid du Colombier kbd.x--;
7898e32b400SDavid du Colombier break;
7908e32b400SDavid du Colombier case 0x15: /* ^U */
7918e32b400SDavid du Colombier kbd.x = 0;
7928e32b400SDavid du Colombier break;
7938e32b400SDavid du Colombier case '\n':
7948e32b400SDavid du Colombier case 0x04: /* ^D */
7958e32b400SDavid du Colombier send = 1;
7968e32b400SDavid du Colombier default:
7978e32b400SDavid du Colombier if(ch != 0x04)
7988e32b400SDavid du Colombier kbd.line[kbd.x++] = ch;
7998e32b400SDavid du Colombier break;
8008e32b400SDavid du Colombier }
8018e32b400SDavid du Colombier }
8028e32b400SDavid du Colombier if(send || kbd.x == sizeof kbd.line){
8038e32b400SDavid du Colombier qwrite(lineq, kbd.line, kbd.x);
8048e32b400SDavid du Colombier kbd.x = 0;
8058e32b400SDavid du Colombier }
8068e32b400SDavid du Colombier }
8078e32b400SDavid du Colombier n = qread(lineq, buf, n);
8088e32b400SDavid du Colombier qunlock(&kbd);
8098e32b400SDavid du Colombier poperror();
8108e32b400SDavid du Colombier return n;
8118e32b400SDavid du Colombier
8128e32b400SDavid du Colombier case Qcputime:
8138e32b400SDavid du Colombier k = offset;
8148e32b400SDavid du Colombier if(k >= 6*NUMSIZE)
8158e32b400SDavid du Colombier return 0;
8168e32b400SDavid du Colombier if(k+n > 6*NUMSIZE)
8178e32b400SDavid du Colombier n = 6*NUMSIZE - k;
8188e32b400SDavid du Colombier /* easiest to format in a separate buffer and copy out */
8198e32b400SDavid du Colombier for(i=0; i<6 && NUMSIZE*i<k+n; i++){
8208e32b400SDavid du Colombier l = up->time[i];
8218e32b400SDavid du Colombier if(i == TReal)
8228e32b400SDavid du Colombier l = MACHP(0)->ticks - l;
8238e32b400SDavid du Colombier l = TK2MS(l);
8248e32b400SDavid du Colombier readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
8258e32b400SDavid du Colombier }
8268e32b400SDavid du Colombier memmove(buf, tmp+k, n);
8278e32b400SDavid du Colombier return n;
8288e32b400SDavid du Colombier
8298e32b400SDavid du Colombier case Qkmesg:
8308e32b400SDavid du Colombier /*
8318e32b400SDavid du Colombier * This is unlocked to avoid tying up a process
8328e32b400SDavid du Colombier * that's writing to the buffer. kmesg.n never
8338e32b400SDavid du Colombier * gets smaller, so worst case the reader will
8348e32b400SDavid du Colombier * see a slurred buffer.
8358e32b400SDavid du Colombier */
8368e32b400SDavid du Colombier if(off >= kmesg.n)
8378e32b400SDavid du Colombier n = 0;
8388e32b400SDavid du Colombier else{
8398e32b400SDavid du Colombier if(off+n > kmesg.n)
8408e32b400SDavid du Colombier n = kmesg.n - off;
8418e32b400SDavid du Colombier memmove(buf, kmesg.buf+off, n);
8428e32b400SDavid du Colombier }
8438e32b400SDavid du Colombier return n;
8448e32b400SDavid du Colombier
8458e32b400SDavid du Colombier case Qkprint:
8468e32b400SDavid du Colombier return qread(kprintoq, buf, n);
8478e32b400SDavid du Colombier
8488e32b400SDavid du Colombier case Qpgrpid:
8498e32b400SDavid du Colombier return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
8508e32b400SDavid du Colombier
8518e32b400SDavid du Colombier case Qpid:
8528e32b400SDavid du Colombier return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
8538e32b400SDavid du Colombier
8548e32b400SDavid du Colombier case Qppid:
8558e32b400SDavid du Colombier return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
8568e32b400SDavid du Colombier
8578e32b400SDavid du Colombier case Qtime:
8588e32b400SDavid du Colombier return readtime((ulong)offset, buf, n);
8598e32b400SDavid du Colombier
8608e32b400SDavid du Colombier case Qbintime:
8618e32b400SDavid du Colombier return readbintime(buf, n);
8628e32b400SDavid du Colombier
8638e32b400SDavid du Colombier case Qhostowner:
8648e32b400SDavid du Colombier return readstr((ulong)offset, buf, n, eve);
8658e32b400SDavid du Colombier
8668e32b400SDavid du Colombier case Qhostdomain:
8678e32b400SDavid du Colombier return readstr((ulong)offset, buf, n, hostdomain);
8688e32b400SDavid du Colombier
8698e32b400SDavid du Colombier case Quser:
8708e32b400SDavid du Colombier return readstr((ulong)offset, buf, n, up->user);
8718e32b400SDavid du Colombier
8728e32b400SDavid du Colombier case Qnull:
8738e32b400SDavid du Colombier return 0;
8748e32b400SDavid du Colombier
8758e32b400SDavid du Colombier case Qsysstat:
8768e32b400SDavid du Colombier b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
8778e32b400SDavid du Colombier bp = b;
8788e32b400SDavid du Colombier for(id = 0; id < 32; id++) {
8798e32b400SDavid du Colombier if(active.machs & (1<<id)) {
8808e32b400SDavid du Colombier mp = MACHP(id);
8818e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, id, NUMSIZE);
8828e32b400SDavid du Colombier bp += NUMSIZE;
8838e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
8848e32b400SDavid du Colombier bp += NUMSIZE;
8858e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
8868e32b400SDavid du Colombier bp += NUMSIZE;
8878e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
8888e32b400SDavid du Colombier bp += NUMSIZE;
8898e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
8908e32b400SDavid du Colombier bp += NUMSIZE;
8918e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
8928e32b400SDavid du Colombier bp += NUMSIZE;
8938e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
8948e32b400SDavid du Colombier bp += NUMSIZE;
8958e32b400SDavid du Colombier readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
8968e32b400SDavid du Colombier bp += NUMSIZE;
8978e32b400SDavid du Colombier readnum(0, bp, NUMSIZE,
8988e32b400SDavid du Colombier (mp->perf.avg_inidle*100)/mp->perf.period,
8998e32b400SDavid du Colombier NUMSIZE);
9008e32b400SDavid du Colombier bp += NUMSIZE;
9018e32b400SDavid du Colombier readnum(0, bp, NUMSIZE,
9028e32b400SDavid du Colombier (mp->perf.avg_inintr*100)/mp->perf.period,
9038e32b400SDavid du Colombier NUMSIZE);
9048e32b400SDavid du Colombier bp += NUMSIZE;
9058e32b400SDavid du Colombier *bp++ = '\n';
9068e32b400SDavid du Colombier }
9078e32b400SDavid du Colombier }
9088e32b400SDavid du Colombier if(waserror()){
9098e32b400SDavid du Colombier free(b);
9108e32b400SDavid du Colombier nexterror();
9118e32b400SDavid du Colombier }
9128e32b400SDavid du Colombier n = readstr((ulong)offset, buf, n, b);
9138e32b400SDavid du Colombier free(b);
9148e32b400SDavid du Colombier poperror();
9158e32b400SDavid du Colombier return n;
9168e32b400SDavid du Colombier
9178e32b400SDavid du Colombier case Qswap:
9188e32b400SDavid du Colombier snprint(tmp, sizeof tmp,
9198e32b400SDavid du Colombier "%lud memory\n"
9208e32b400SDavid du Colombier "%d pagesize\n"
9218e32b400SDavid du Colombier "%lud kernel\n"
9228e32b400SDavid du Colombier "%lud/%lud user\n"
9238e32b400SDavid du Colombier "%lud/%lud swap\n"
9248e32b400SDavid du Colombier "%lud/%lud kernel malloc\n"
9258e32b400SDavid du Colombier "%lud/%lud kernel draw\n",
9268e32b400SDavid du Colombier conf.npage*BY2PG,
9278e32b400SDavid du Colombier BY2PG,
9288e32b400SDavid du Colombier conf.npage-conf.upages,
9298e32b400SDavid du Colombier palloc.user-palloc.freecount, palloc.user,
9308e32b400SDavid du Colombier conf.nswap-swapalloc.free, conf.nswap,
9318e32b400SDavid du Colombier mainmem->cursize, mainmem->maxsize,
9328e32b400SDavid du Colombier imagmem->cursize, imagmem->maxsize);
9338e32b400SDavid du Colombier
9348e32b400SDavid du Colombier return readstr((ulong)offset, buf, n, tmp);
9358e32b400SDavid du Colombier
9368e32b400SDavid du Colombier case Qsysname:
9378e32b400SDavid du Colombier if(sysname == nil)
9388e32b400SDavid du Colombier return 0;
9398e32b400SDavid du Colombier return readstr((ulong)offset, buf, n, sysname);
9408e32b400SDavid du Colombier
9418e32b400SDavid du Colombier case Qrandom:
9428e32b400SDavid du Colombier return randomread(buf, n);
9438e32b400SDavid du Colombier
9448e32b400SDavid du Colombier case Qdrivers:
9458e32b400SDavid du Colombier b = malloc(READSTR);
9468e32b400SDavid du Colombier if(b == nil)
9478e32b400SDavid du Colombier error(Enomem);
94893631029SDavid du Colombier k = 0;
9498e32b400SDavid du Colombier for(i = 0; devtab[i] != nil; i++)
95093631029SDavid du Colombier k += snprint(b+k, READSTR-k, "#%C %s\n",
95193631029SDavid du Colombier devtab[i]->dc, devtab[i]->name);
9528e32b400SDavid du Colombier if(waserror()){
9538e32b400SDavid du Colombier free(b);
9548e32b400SDavid du Colombier nexterror();
9558e32b400SDavid du Colombier }
9568e32b400SDavid du Colombier n = readstr((ulong)offset, buf, n, b);
9578e32b400SDavid du Colombier free(b);
9588e32b400SDavid du Colombier poperror();
9598e32b400SDavid du Colombier return n;
9608e32b400SDavid du Colombier
9618e32b400SDavid du Colombier case Qzero:
9628e32b400SDavid du Colombier memset(buf, 0, n);
9638e32b400SDavid du Colombier return n;
9648e32b400SDavid du Colombier
9658e32b400SDavid du Colombier case Qosversion:
9668e32b400SDavid du Colombier snprint(tmp, sizeof tmp, "2000");
9678e32b400SDavid du Colombier n = readstr((ulong)offset, buf, n, tmp);
9688e32b400SDavid du Colombier return n;
9698e32b400SDavid du Colombier
9708e32b400SDavid du Colombier default:
9718e32b400SDavid du Colombier print("consread %#llux\n", c->qid.path);
9728e32b400SDavid du Colombier error(Egreg);
9738e32b400SDavid du Colombier }
9748e32b400SDavid du Colombier return -1; /* never reached */
9758e32b400SDavid du Colombier }
9768e32b400SDavid du Colombier
9778e32b400SDavid du Colombier static long
conswrite(Chan * c,void * va,long n,vlong off)9788e32b400SDavid du Colombier conswrite(Chan *c, void *va, long n, vlong off)
9798e32b400SDavid du Colombier {
9808e32b400SDavid du Colombier char buf[256], ch;
9818e32b400SDavid du Colombier long l, bp;
9828e32b400SDavid du Colombier char *a;
9838e32b400SDavid du Colombier Mach *mp;
9848e32b400SDavid du Colombier int id, fd;
9858e32b400SDavid du Colombier Chan *swc;
9868e32b400SDavid du Colombier ulong offset;
9878e32b400SDavid du Colombier Cmdbuf *cb;
9888e32b400SDavid du Colombier Cmdtab *ct;
9898e32b400SDavid du Colombier
9908e32b400SDavid du Colombier a = va;
9918e32b400SDavid du Colombier offset = off;
9928e32b400SDavid du Colombier
9938e32b400SDavid du Colombier switch((ulong)c->qid.path){
9948e32b400SDavid du Colombier case Qcons:
9958e32b400SDavid du Colombier /*
9968e32b400SDavid du Colombier * Can't page fault in putstrn, so copy the data locally.
9978e32b400SDavid du Colombier */
9988e32b400SDavid du Colombier l = n;
9998e32b400SDavid du Colombier while(l > 0){
10008e32b400SDavid du Colombier bp = l;
10018e32b400SDavid du Colombier if(bp > sizeof buf)
10028e32b400SDavid du Colombier bp = sizeof buf;
10038e32b400SDavid du Colombier memmove(buf, a, bp);
10048e32b400SDavid du Colombier putstrn0(buf, bp, 1);
10058e32b400SDavid du Colombier a += bp;
10068e32b400SDavid du Colombier l -= bp;
10078e32b400SDavid du Colombier }
10088e32b400SDavid du Colombier break;
10098e32b400SDavid du Colombier
10108e32b400SDavid du Colombier case Qconsctl:
10118e32b400SDavid du Colombier if(n >= sizeof(buf))
10128e32b400SDavid du Colombier n = sizeof(buf)-1;
10138e32b400SDavid du Colombier strncpy(buf, a, n);
10148e32b400SDavid du Colombier buf[n] = 0;
10158e32b400SDavid du Colombier for(a = buf; a;){
10168e32b400SDavid du Colombier if(strncmp(a, "rawon", 5) == 0){
10178e32b400SDavid du Colombier kbd.raw = 1;
10188e32b400SDavid du Colombier /* clumsy hack - wake up reader */
10198e32b400SDavid du Colombier ch = 0;
10208e32b400SDavid du Colombier qwrite(kbdq, &ch, 1);
10218e32b400SDavid du Colombier } else if(strncmp(a, "rawoff", 6) == 0){
10228e32b400SDavid du Colombier kbd.raw = 0;
10238e32b400SDavid du Colombier } else if(strncmp(a, "ctlpon", 6) == 0){
10248e32b400SDavid du Colombier kbd.ctlpoff = 0;
10258e32b400SDavid du Colombier } else if(strncmp(a, "ctlpoff", 7) == 0){
10268e32b400SDavid du Colombier kbd.ctlpoff = 1;
10278e32b400SDavid du Colombier }
10288e32b400SDavid du Colombier if(a = strchr(a, ' '))
10298e32b400SDavid du Colombier a++;
10308e32b400SDavid du Colombier }
10318e32b400SDavid du Colombier break;
10328e32b400SDavid du Colombier
10338e32b400SDavid du Colombier case Qtime:
10348e32b400SDavid du Colombier if(!iseve())
10358e32b400SDavid du Colombier error(Eperm);
10368e32b400SDavid du Colombier return writetime(a, n);
10378e32b400SDavid du Colombier
10388e32b400SDavid du Colombier case Qbintime:
10398e32b400SDavid du Colombier if(!iseve())
10408e32b400SDavid du Colombier error(Eperm);
10418e32b400SDavid du Colombier return writebintime(a, n);
10428e32b400SDavid du Colombier
10438e32b400SDavid du Colombier case Qhostowner:
10448e32b400SDavid du Colombier return hostownerwrite(a, n);
10458e32b400SDavid du Colombier
10468e32b400SDavid du Colombier case Qhostdomain:
10478e32b400SDavid du Colombier return hostdomainwrite(a, n);
10488e32b400SDavid du Colombier
10498e32b400SDavid du Colombier case Quser:
10508e32b400SDavid du Colombier return userwrite(a, n);
10518e32b400SDavid du Colombier
10528e32b400SDavid du Colombier case Qnull:
10538e32b400SDavid du Colombier break;
10548e32b400SDavid du Colombier
10558e32b400SDavid du Colombier case Qreboot:
10568e32b400SDavid du Colombier if(!iseve())
10578e32b400SDavid du Colombier error(Eperm);
10588e32b400SDavid du Colombier cb = parsecmd(a, n);
10598e32b400SDavid du Colombier
10608e32b400SDavid du Colombier if(waserror()) {
10618e32b400SDavid du Colombier free(cb);
10628e32b400SDavid du Colombier nexterror();
10638e32b400SDavid du Colombier }
10648e32b400SDavid du Colombier ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
10658e32b400SDavid du Colombier switch(ct->index) {
10668e32b400SDavid du Colombier case CMhalt:
10678e32b400SDavid du Colombier reboot(nil, 0, 0);
10688e32b400SDavid du Colombier break;
10698e32b400SDavid du Colombier case CMreboot:
10708e32b400SDavid du Colombier rebootcmd(cb->nf-1, cb->f+1);
10718e32b400SDavid du Colombier break;
10728e32b400SDavid du Colombier case CMpanic:
10738e32b400SDavid du Colombier *(ulong*)0=0;
10748e32b400SDavid du Colombier panic("/dev/reboot");
10758e32b400SDavid du Colombier }
10768e32b400SDavid du Colombier poperror();
10778e32b400SDavid du Colombier free(cb);
10788e32b400SDavid du Colombier break;
10798e32b400SDavid du Colombier
10808e32b400SDavid du Colombier case Qsysstat:
10818e32b400SDavid du Colombier for(id = 0; id < 32; id++) {
10828e32b400SDavid du Colombier if(active.machs & (1<<id)) {
10838e32b400SDavid du Colombier mp = MACHP(id);
10848e32b400SDavid du Colombier mp->cs = 0;
10858e32b400SDavid du Colombier mp->intr = 0;
10868e32b400SDavid du Colombier mp->syscall = 0;
10878e32b400SDavid du Colombier mp->pfault = 0;
10888e32b400SDavid du Colombier mp->tlbfault = 0;
10898e32b400SDavid du Colombier mp->tlbpurge = 0;
10908e32b400SDavid du Colombier }
10918e32b400SDavid du Colombier }
10928e32b400SDavid du Colombier break;
10938e32b400SDavid du Colombier
10948e32b400SDavid du Colombier case Qswap:
10958e32b400SDavid du Colombier if(n >= sizeof buf)
10968e32b400SDavid du Colombier error(Egreg);
10978e32b400SDavid du Colombier memmove(buf, va, n); /* so we can NUL-terminate */
10988e32b400SDavid du Colombier buf[n] = 0;
10998e32b400SDavid du Colombier /* start a pager if not already started */
11008e32b400SDavid du Colombier if(strncmp(buf, "start", 5) == 0){
11018e32b400SDavid du Colombier kickpager();
11028e32b400SDavid du Colombier break;
11038e32b400SDavid du Colombier }
11048e32b400SDavid du Colombier if(!iseve())
11058e32b400SDavid du Colombier error(Eperm);
11068e32b400SDavid du Colombier if(buf[0]<'0' || '9'<buf[0])
11078e32b400SDavid du Colombier error(Ebadarg);
11088e32b400SDavid du Colombier fd = strtoul(buf, 0, 0);
11098e32b400SDavid du Colombier swc = fdtochan(fd, -1, 1, 1);
11108e32b400SDavid du Colombier setswapchan(swc);
11118e32b400SDavid du Colombier break;
11128e32b400SDavid du Colombier
11138e32b400SDavid du Colombier case Qsysname:
11148e32b400SDavid du Colombier if(offset != 0)
11158e32b400SDavid du Colombier error(Ebadarg);
11168e32b400SDavid du Colombier if(n <= 0 || n >= sizeof buf)
11178e32b400SDavid du Colombier error(Ebadarg);
11188e32b400SDavid du Colombier strncpy(buf, a, n);
11198e32b400SDavid du Colombier buf[n] = 0;
11208e32b400SDavid du Colombier if(buf[n-1] == '\n')
11218e32b400SDavid du Colombier buf[n-1] = 0;
11228e32b400SDavid du Colombier kstrdup(&sysname, buf);
11238e32b400SDavid du Colombier break;
11248e32b400SDavid du Colombier
11258e32b400SDavid du Colombier default:
11268e32b400SDavid du Colombier print("conswrite: %#llux\n", c->qid.path);
11278e32b400SDavid du Colombier error(Egreg);
11288e32b400SDavid du Colombier }
11298e32b400SDavid du Colombier return n;
11308e32b400SDavid du Colombier }
11318e32b400SDavid du Colombier
11328e32b400SDavid du Colombier Dev consdevtab = {
11338e32b400SDavid du Colombier 'c',
11348e32b400SDavid du Colombier "cons",
11358e32b400SDavid du Colombier
11368e32b400SDavid du Colombier devreset,
11378e32b400SDavid du Colombier consinit,
11388e32b400SDavid du Colombier devshutdown,
11398e32b400SDavid du Colombier consattach,
11408e32b400SDavid du Colombier conswalk,
11418e32b400SDavid du Colombier consstat,
11428e32b400SDavid du Colombier consopen,
11438e32b400SDavid du Colombier devcreate,
11448e32b400SDavid du Colombier consclose,
11458e32b400SDavid du Colombier consread,
11468e32b400SDavid du Colombier devbread,
11478e32b400SDavid du Colombier conswrite,
11488e32b400SDavid du Colombier devbwrite,
11498e32b400SDavid du Colombier devremove,
11508e32b400SDavid du Colombier devwstat,
11518e32b400SDavid du Colombier };
11528e32b400SDavid du Colombier
11538e32b400SDavid du Colombier static ulong randn;
11548e32b400SDavid du Colombier
11558e32b400SDavid du Colombier static void
seedrand(void)11568e32b400SDavid du Colombier seedrand(void)
11578e32b400SDavid du Colombier {
11588e32b400SDavid du Colombier if(!waserror()){
11598e32b400SDavid du Colombier randomread((void*)&randn, sizeof(randn));
11608e32b400SDavid du Colombier poperror();
11618e32b400SDavid du Colombier }
11628e32b400SDavid du Colombier }
11638e32b400SDavid du Colombier
11648e32b400SDavid du Colombier int
nrand(int n)11658e32b400SDavid du Colombier nrand(int n)
11668e32b400SDavid du Colombier {
11678e32b400SDavid du Colombier if(randn == 0)
11688e32b400SDavid du Colombier seedrand();
11698e32b400SDavid du Colombier randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
11708e32b400SDavid du Colombier return (randn>>16) % n;
11718e32b400SDavid du Colombier }
11728e32b400SDavid du Colombier
11738e32b400SDavid du Colombier int
rand(void)11748e32b400SDavid du Colombier rand(void)
11758e32b400SDavid du Colombier {
11768e32b400SDavid du Colombier nrand(1);
11778e32b400SDavid du Colombier return randn;
11788e32b400SDavid du Colombier }
11798e32b400SDavid du Colombier
11808e32b400SDavid du Colombier static uvlong uvorder = 0x0001020304050607ULL;
11818e32b400SDavid du Colombier
11828e32b400SDavid du Colombier static uchar*
le2vlong(vlong * to,uchar * f)11838e32b400SDavid du Colombier le2vlong(vlong *to, uchar *f)
11848e32b400SDavid du Colombier {
11858e32b400SDavid du Colombier uchar *t, *o;
11868e32b400SDavid du Colombier int i;
11878e32b400SDavid du Colombier
11888e32b400SDavid du Colombier t = (uchar*)to;
11898e32b400SDavid du Colombier o = (uchar*)&uvorder;
11908e32b400SDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
11918e32b400SDavid du Colombier t[o[i]] = f[i];
11928e32b400SDavid du Colombier return f+sizeof(vlong);
11938e32b400SDavid du Colombier }
11948e32b400SDavid du Colombier
11958e32b400SDavid du Colombier static uchar*
vlong2le(uchar * t,vlong from)11968e32b400SDavid du Colombier vlong2le(uchar *t, vlong from)
11978e32b400SDavid du Colombier {
11988e32b400SDavid du Colombier uchar *f, *o;
11998e32b400SDavid du Colombier int i;
12008e32b400SDavid du Colombier
12018e32b400SDavid du Colombier f = (uchar*)&from;
12028e32b400SDavid du Colombier o = (uchar*)&uvorder;
12038e32b400SDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
12048e32b400SDavid du Colombier t[i] = f[o[i]];
12058e32b400SDavid du Colombier return t+sizeof(vlong);
12068e32b400SDavid du Colombier }
12078e32b400SDavid du Colombier
12088e32b400SDavid du Colombier static long order = 0x00010203;
12098e32b400SDavid du Colombier
12108e32b400SDavid du Colombier static uchar*
le2long(long * to,uchar * f)12118e32b400SDavid du Colombier le2long(long *to, uchar *f)
12128e32b400SDavid du Colombier {
12138e32b400SDavid du Colombier uchar *t, *o;
12148e32b400SDavid du Colombier int i;
12158e32b400SDavid du Colombier
12168e32b400SDavid du Colombier t = (uchar*)to;
12178e32b400SDavid du Colombier o = (uchar*)ℴ
12188e32b400SDavid du Colombier for(i = 0; i < sizeof(long); i++)
12198e32b400SDavid du Colombier t[o[i]] = f[i];
12208e32b400SDavid du Colombier return f+sizeof(long);
12218e32b400SDavid du Colombier }
12228e32b400SDavid du Colombier
12238e32b400SDavid du Colombier static uchar*
long2le(uchar * t,long from)12248e32b400SDavid du Colombier long2le(uchar *t, long from)
12258e32b400SDavid du Colombier {
12268e32b400SDavid du Colombier uchar *f, *o;
12278e32b400SDavid du Colombier int i;
12288e32b400SDavid du Colombier
12298e32b400SDavid du Colombier f = (uchar*)&from;
12308e32b400SDavid du Colombier o = (uchar*)ℴ
12318e32b400SDavid du Colombier for(i = 0; i < sizeof(long); i++)
12328e32b400SDavid du Colombier t[i] = f[o[i]];
12338e32b400SDavid du Colombier return t+sizeof(long);
12348e32b400SDavid du Colombier }
12358e32b400SDavid du Colombier
12368e32b400SDavid du Colombier char *Ebadtimectl = "bad time control";
12378e32b400SDavid du Colombier
12388e32b400SDavid du Colombier /*
12398e32b400SDavid du Colombier * like the old #c/time but with added info. Return
12408e32b400SDavid du Colombier *
12418e32b400SDavid du Colombier * secs nanosecs fastticks fasthz
12428e32b400SDavid du Colombier */
12438e32b400SDavid du Colombier static int
readtime(ulong off,char * buf,int n)12448e32b400SDavid du Colombier readtime(ulong off, char *buf, int n)
12458e32b400SDavid du Colombier {
12468e32b400SDavid du Colombier vlong nsec, ticks;
12478e32b400SDavid du Colombier long sec;
12488e32b400SDavid du Colombier char str[7*NUMSIZE];
12498e32b400SDavid du Colombier
12508e32b400SDavid du Colombier nsec = todget(&ticks);
12518e32b400SDavid du Colombier if(fasthz == 0LL)
12528e32b400SDavid du Colombier fastticks((uvlong*)&fasthz);
12538e32b400SDavid du Colombier sec = nsec/1000000000ULL;
12548e32b400SDavid du Colombier snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
12558e32b400SDavid du Colombier NUMSIZE-1, sec,
12568e32b400SDavid du Colombier VLNUMSIZE-1, nsec,
12578e32b400SDavid du Colombier VLNUMSIZE-1, ticks,
12588e32b400SDavid du Colombier VLNUMSIZE-1, fasthz);
12598e32b400SDavid du Colombier return readstr(off, buf, n, str);
12608e32b400SDavid du Colombier }
12618e32b400SDavid du Colombier
12628e32b400SDavid du Colombier /*
12638e32b400SDavid du Colombier * set the time in seconds
12648e32b400SDavid du Colombier */
12658e32b400SDavid du Colombier static int
writetime(char * buf,int n)12668e32b400SDavid du Colombier writetime(char *buf, int n)
12678e32b400SDavid du Colombier {
12688e32b400SDavid du Colombier char b[13];
12698e32b400SDavid du Colombier long i;
12708e32b400SDavid du Colombier vlong now;
12718e32b400SDavid du Colombier
12728e32b400SDavid du Colombier if(n >= sizeof(b))
12738e32b400SDavid du Colombier error(Ebadtimectl);
12748e32b400SDavid du Colombier strncpy(b, buf, n);
12758e32b400SDavid du Colombier b[n] = 0;
12768e32b400SDavid du Colombier i = strtol(b, 0, 0);
12778e32b400SDavid du Colombier if(i <= 0)
12788e32b400SDavid du Colombier error(Ebadtimectl);
12798e32b400SDavid du Colombier now = i*1000000000LL;
12808e32b400SDavid du Colombier todset(now, 0, 0);
12818e32b400SDavid du Colombier return n;
12828e32b400SDavid du Colombier }
12838e32b400SDavid du Colombier
12848e32b400SDavid du Colombier /*
12858e32b400SDavid du Colombier * read binary time info. all numbers are little endian.
12868e32b400SDavid du Colombier * ticks and nsec are syncronized.
12878e32b400SDavid du Colombier */
12888e32b400SDavid du Colombier static int
readbintime(char * buf,int n)12898e32b400SDavid du Colombier readbintime(char *buf, int n)
12908e32b400SDavid du Colombier {
12918e32b400SDavid du Colombier int i;
12928e32b400SDavid du Colombier vlong nsec, ticks;
12938e32b400SDavid du Colombier uchar *b = (uchar*)buf;
12948e32b400SDavid du Colombier
12958e32b400SDavid du Colombier i = 0;
12968e32b400SDavid du Colombier if(fasthz == 0LL)
12978e32b400SDavid du Colombier fastticks((uvlong*)&fasthz);
12988e32b400SDavid du Colombier nsec = todget(&ticks);
12998e32b400SDavid du Colombier if(n >= 3*sizeof(uvlong)){
13008e32b400SDavid du Colombier vlong2le(b+2*sizeof(uvlong), fasthz);
13018e32b400SDavid du Colombier i += sizeof(uvlong);
13028e32b400SDavid du Colombier }
13038e32b400SDavid du Colombier if(n >= 2*sizeof(uvlong)){
13048e32b400SDavid du Colombier vlong2le(b+sizeof(uvlong), ticks);
13058e32b400SDavid du Colombier i += sizeof(uvlong);
13068e32b400SDavid du Colombier }
13078e32b400SDavid du Colombier if(n >= 8){
13088e32b400SDavid du Colombier vlong2le(b, nsec);
13098e32b400SDavid du Colombier i += sizeof(vlong);
13108e32b400SDavid du Colombier }
13118e32b400SDavid du Colombier return i;
13128e32b400SDavid du Colombier }
13138e32b400SDavid du Colombier
13148e32b400SDavid du Colombier /*
13158e32b400SDavid du Colombier * set any of the following
13168e32b400SDavid du Colombier * - time in nsec
13178e32b400SDavid du Colombier * - nsec trim applied over some seconds
13188e32b400SDavid du Colombier * - clock frequency
13198e32b400SDavid du Colombier */
13208e32b400SDavid du Colombier static int
writebintime(char * buf,int n)13218e32b400SDavid du Colombier writebintime(char *buf, int n)
13228e32b400SDavid du Colombier {
13238e32b400SDavid du Colombier uchar *p;
13248e32b400SDavid du Colombier vlong delta;
13258e32b400SDavid du Colombier long period;
13268e32b400SDavid du Colombier
13278e32b400SDavid du Colombier n--;
13288e32b400SDavid du Colombier p = (uchar*)buf + 1;
13298e32b400SDavid du Colombier switch(*buf){
13308e32b400SDavid du Colombier case 'n':
13318e32b400SDavid du Colombier if(n < sizeof(vlong))
13328e32b400SDavid du Colombier error(Ebadtimectl);
13338e32b400SDavid du Colombier le2vlong(&delta, p);
13348e32b400SDavid du Colombier todset(delta, 0, 0);
13358e32b400SDavid du Colombier break;
13368e32b400SDavid du Colombier case 'd':
13378e32b400SDavid du Colombier if(n < sizeof(vlong)+sizeof(long))
13388e32b400SDavid du Colombier error(Ebadtimectl);
13398e32b400SDavid du Colombier p = le2vlong(&delta, p);
13408e32b400SDavid du Colombier le2long(&period, p);
13418e32b400SDavid du Colombier todset(-1, delta, period);
13428e32b400SDavid du Colombier break;
13438e32b400SDavid du Colombier case 'f':
13448e32b400SDavid du Colombier if(n < sizeof(uvlong))
13458e32b400SDavid du Colombier error(Ebadtimectl);
13468e32b400SDavid du Colombier le2vlong(&fasthz, p);
13478e32b400SDavid du Colombier if(fasthz <= 0)
13488e32b400SDavid du Colombier error(Ebadtimectl);
13498e32b400SDavid du Colombier todsetfreq(fasthz);
13508e32b400SDavid du Colombier break;
13518e32b400SDavid du Colombier }
13528e32b400SDavid du Colombier return n;
13538e32b400SDavid du Colombier }
1354