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