19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier #include <authsrv.h>
99ef1f84bSDavid du Colombier
109ef1f84bSDavid du Colombier enum
119ef1f84bSDavid du Colombier {
129ef1f84bSDavid du Colombier Nconsdevs = 64, /* max number of consoles */
139ef1f84bSDavid du Colombier
149ef1f84bSDavid du Colombier /* Consdev flags */
159ef1f84bSDavid du Colombier Ciprint = 2, /* call this fn from iprint */
169ef1f84bSDavid du Colombier Cntorn = 4, /* change \n to \r\n */
179ef1f84bSDavid du Colombier };
189ef1f84bSDavid du Colombier
199ef1f84bSDavid du Colombier typedef struct Consdev Consdev;
209ef1f84bSDavid du Colombier
219ef1f84bSDavid du Colombier struct Consdev
229ef1f84bSDavid du Colombier {
239ef1f84bSDavid du Colombier Chan* c; /* external file */
249ef1f84bSDavid du Colombier Queue* q; /* i/o queue, if any */
259ef1f84bSDavid du Colombier void (*fn)(char*, int); /* i/o function when no queue */
269ef1f84bSDavid du Colombier int flags;
279ef1f84bSDavid du Colombier };
289ef1f84bSDavid du Colombier
299ef1f84bSDavid du Colombier void (*consdebug)(void) = nil;
309ef1f84bSDavid du Colombier void (*consputs)(char*, int) = nil;
319ef1f84bSDavid du Colombier
329ef1f84bSDavid du Colombier static void kmesgputs(char *, int);
339ef1f84bSDavid du Colombier static void kprintputs(char*, int);
349ef1f84bSDavid du Colombier
359ef1f84bSDavid du Colombier static Lock consdevslock;
369ef1f84bSDavid du Colombier static int nconsdevs = 3;
379ef1f84bSDavid du Colombier static Consdev consdevs[Nconsdevs] = /* keep this order */
389ef1f84bSDavid du Colombier {
399ef1f84bSDavid du Colombier {nil, nil, kmesgputs, 0}, /* kmesg */
409ef1f84bSDavid du Colombier {nil, nil, kprintputs, Ciprint}, /* kprint */
419ef1f84bSDavid du Colombier {nil, nil, uartputs, Ciprint|Cntorn}, /* serial */
429ef1f84bSDavid du Colombier };
439ef1f84bSDavid du Colombier
449ef1f84bSDavid du Colombier static int nkbdqs;
459ef1f84bSDavid du Colombier static int nkbdprocs;
469ef1f84bSDavid du Colombier static Queue* kbdqs[Nconsdevs];
479ef1f84bSDavid du Colombier static int kbdprocs[Nconsdevs];
489ef1f84bSDavid du Colombier static Queue* kbdq; /* unprocessed console input */
499ef1f84bSDavid du Colombier static Queue* lineq; /* processed console input */
509ef1f84bSDavid du Colombier static Queue* serialoq; /* serial console output */
519ef1f84bSDavid du Colombier static Queue* kprintoq; /* console output, for /dev/kprint */
529ef1f84bSDavid du Colombier static ulong kprintinuse; /* test and set whether /dev/kprint is open */
539ef1f84bSDavid du Colombier
549ef1f84bSDavid du Colombier int panicking;
559ef1f84bSDavid du Colombier
569ef1f84bSDavid du Colombier static struct
579ef1f84bSDavid du Colombier {
589ef1f84bSDavid du Colombier QLock;
599ef1f84bSDavid du Colombier
609ef1f84bSDavid du Colombier int raw; /* true if we shouldn't process input */
619ef1f84bSDavid du Colombier Ref ctl; /* number of opens to the control file */
629ef1f84bSDavid du Colombier int x; /* index into line */
639ef1f84bSDavid du Colombier char line[1024]; /* current input line */
649ef1f84bSDavid du Colombier
659ef1f84bSDavid du Colombier int count;
669ef1f84bSDavid du Colombier int ctlpoff;
679ef1f84bSDavid du Colombier
689ef1f84bSDavid du Colombier /*
699ef1f84bSDavid du Colombier * A place to save up characters at interrupt time
709ef1f84bSDavid du Colombier * before dumping them in the queue
719ef1f84bSDavid du Colombier */
729ef1f84bSDavid du Colombier Lock lockputc;
739ef1f84bSDavid du Colombier char istage[1024];
749ef1f84bSDavid du Colombier char *iw;
759ef1f84bSDavid du Colombier char *ir;
769ef1f84bSDavid du Colombier char *ie;
779ef1f84bSDavid du Colombier } kbd = {
789ef1f84bSDavid du Colombier .iw = kbd.istage,
799ef1f84bSDavid du Colombier .ir = kbd.istage,
809ef1f84bSDavid du Colombier .ie = kbd.istage + sizeof(kbd.istage),
819ef1f84bSDavid du Colombier };
829ef1f84bSDavid du Colombier
839ef1f84bSDavid du Colombier char *sysname;
849ef1f84bSDavid du Colombier vlong fasthz;
859ef1f84bSDavid du Colombier
869ef1f84bSDavid du Colombier static void seedrand(void);
879ef1f84bSDavid du Colombier static int readtime(ulong, char*, int);
889ef1f84bSDavid du Colombier static int readbintime(char*, int);
899ef1f84bSDavid du Colombier static int writetime(char*, int);
909ef1f84bSDavid du Colombier static int writebintime(char*, int);
919ef1f84bSDavid du Colombier
929ef1f84bSDavid du Colombier enum
939ef1f84bSDavid du Colombier {
949ef1f84bSDavid du Colombier CMhalt,
959ef1f84bSDavid du Colombier CMreboot,
969ef1f84bSDavid du Colombier CMpanic,
979ef1f84bSDavid du Colombier };
989ef1f84bSDavid du Colombier
999ef1f84bSDavid du Colombier Cmdtab rebootmsg[] =
1009ef1f84bSDavid du Colombier {
1019ef1f84bSDavid du Colombier CMhalt, "halt", 1,
1029ef1f84bSDavid du Colombier CMreboot, "reboot", 0,
1039ef1f84bSDavid du Colombier CMpanic, "panic", 0,
1049ef1f84bSDavid du Colombier };
1059ef1f84bSDavid du Colombier
1069ef1f84bSDavid du Colombier /* To keep the rest of the kernel unware of new consdevs for now */
1079ef1f84bSDavid du Colombier static void
kprintputs(char * s,int n)1089ef1f84bSDavid du Colombier kprintputs(char *s, int n)
1099ef1f84bSDavid du Colombier {
1109ef1f84bSDavid du Colombier if(consputs != nil)
1119ef1f84bSDavid du Colombier consputs(s, n);
1129ef1f84bSDavid du Colombier }
1139ef1f84bSDavid du Colombier
1149ef1f84bSDavid du Colombier int
addconsdev(Queue * q,void (* fn)(char *,int),int i,int flags)1159ef1f84bSDavid du Colombier addconsdev(Queue *q, void (*fn)(char*,int), int i, int flags)
1169ef1f84bSDavid du Colombier {
1179ef1f84bSDavid du Colombier Consdev *c;
1189ef1f84bSDavid du Colombier
1199ef1f84bSDavid du Colombier ilock(&consdevslock);
1209ef1f84bSDavid du Colombier if(i < 0)
1219ef1f84bSDavid du Colombier i = nconsdevs;
1229ef1f84bSDavid du Colombier else
1239ef1f84bSDavid du Colombier flags |= consdevs[i].flags;
1249ef1f84bSDavid du Colombier if(nconsdevs == Nconsdevs)
1259ef1f84bSDavid du Colombier panic("Nconsdevs too small");
1269ef1f84bSDavid du Colombier c = &consdevs[i];
1279ef1f84bSDavid du Colombier c->flags = flags;
1289ef1f84bSDavid du Colombier c->q = q;
1299ef1f84bSDavid du Colombier c->fn = fn;
1309ef1f84bSDavid du Colombier if(i == nconsdevs)
1319ef1f84bSDavid du Colombier nconsdevs++;
1329ef1f84bSDavid du Colombier iunlock(&consdevslock);
1339ef1f84bSDavid du Colombier return i;
1349ef1f84bSDavid du Colombier }
1359ef1f84bSDavid du Colombier
1369ef1f84bSDavid du Colombier void
delconsdevs(void)1379ef1f84bSDavid du Colombier delconsdevs(void)
1389ef1f84bSDavid du Colombier {
1399ef1f84bSDavid du Colombier nconsdevs = 2; /* throw away serial consoles and kprint */
1409ef1f84bSDavid du Colombier consdevs[1].q = nil;
1419ef1f84bSDavid du Colombier }
1429ef1f84bSDavid du Colombier
1439ef1f84bSDavid du Colombier static void
conskbdqproc(void * a)1449ef1f84bSDavid du Colombier conskbdqproc(void *a)
1459ef1f84bSDavid du Colombier {
1469ef1f84bSDavid du Colombier char buf[64];
1479ef1f84bSDavid du Colombier Queue *q;
1489ef1f84bSDavid du Colombier int nr;
1499ef1f84bSDavid du Colombier
1509ef1f84bSDavid du Colombier q = a;
1519ef1f84bSDavid du Colombier while((nr = qread(q, buf, sizeof(buf))) > 0)
1529ef1f84bSDavid du Colombier qwrite(kbdq, buf, nr);
1539ef1f84bSDavid du Colombier pexit("hangup", 1);
1549ef1f84bSDavid du Colombier }
1559ef1f84bSDavid du Colombier
1569ef1f84bSDavid du Colombier static void
kickkbdq(void)1579ef1f84bSDavid du Colombier kickkbdq(void)
1589ef1f84bSDavid du Colombier {
1599ef1f84bSDavid du Colombier int i;
1609ef1f84bSDavid du Colombier
1619ef1f84bSDavid du Colombier if(up != nil && nkbdqs > 1 && nkbdprocs != nkbdqs){
1629ef1f84bSDavid du Colombier lock(&consdevslock);
1639ef1f84bSDavid du Colombier if(nkbdprocs == nkbdqs){
1649ef1f84bSDavid du Colombier unlock(&consdevslock);
1659ef1f84bSDavid du Colombier return;
1669ef1f84bSDavid du Colombier }
1679ef1f84bSDavid du Colombier for(i = 0; i < nkbdqs; i++)
1689ef1f84bSDavid du Colombier if(kbdprocs[i] == 0){
1699ef1f84bSDavid du Colombier kbdprocs[i] = 1;
1709ef1f84bSDavid du Colombier kproc("conskbdq", conskbdqproc, kbdqs[i]);
1719ef1f84bSDavid du Colombier }
1729ef1f84bSDavid du Colombier unlock(&consdevslock);
1739ef1f84bSDavid du Colombier }
1749ef1f84bSDavid du Colombier }
1759ef1f84bSDavid du Colombier
1769ef1f84bSDavid du Colombier int
addkbdq(Queue * q,int i)1779ef1f84bSDavid du Colombier addkbdq(Queue *q, int i)
1789ef1f84bSDavid du Colombier {
1799ef1f84bSDavid du Colombier int n;
1809ef1f84bSDavid du Colombier
1819ef1f84bSDavid du Colombier ilock(&consdevslock);
1829ef1f84bSDavid du Colombier if(i < 0)
1839ef1f84bSDavid du Colombier i = nkbdqs++;
1849ef1f84bSDavid du Colombier if(nkbdqs == Nconsdevs)
1859ef1f84bSDavid du Colombier panic("Nconsdevs too small");
1869ef1f84bSDavid du Colombier kbdqs[i] = q;
1879ef1f84bSDavid du Colombier n = nkbdqs;
1889ef1f84bSDavid du Colombier iunlock(&consdevslock);
1899ef1f84bSDavid du Colombier switch(n){
1909ef1f84bSDavid du Colombier case 1:
1919ef1f84bSDavid du Colombier /* if there's just one, pull directly from it. */
1929ef1f84bSDavid du Colombier kbdq = q;
1939ef1f84bSDavid du Colombier break;
1949ef1f84bSDavid du Colombier case 2:
1959ef1f84bSDavid du Colombier /* later we'll merge bytes from all kbdqs into a single kbdq */
1969ef1f84bSDavid du Colombier kbdq = qopen(4*1024, 0, 0, 0);
1979ef1f84bSDavid du Colombier if(kbdq == nil)
1989ef1f84bSDavid du Colombier panic("no kbdq");
1999ef1f84bSDavid du Colombier /* fall */
2009ef1f84bSDavid du Colombier default:
2019ef1f84bSDavid du Colombier kickkbdq();
2029ef1f84bSDavid du Colombier }
2039ef1f84bSDavid du Colombier return i;
2049ef1f84bSDavid du Colombier }
2059ef1f84bSDavid du Colombier
2069ef1f84bSDavid du Colombier void
printinit(void)2079ef1f84bSDavid du Colombier printinit(void)
2089ef1f84bSDavid du Colombier {
2099ef1f84bSDavid du Colombier lineq = qopen(2*1024, 0, nil, nil);
2109ef1f84bSDavid du Colombier if(lineq == nil)
2119ef1f84bSDavid du Colombier panic("printinit");
2129ef1f84bSDavid du Colombier qnoblock(lineq, 1);
2139ef1f84bSDavid du Colombier }
2149ef1f84bSDavid du Colombier
2159ef1f84bSDavid du Colombier int
consactive(void)2169ef1f84bSDavid du Colombier consactive(void)
2179ef1f84bSDavid du Colombier {
2189ef1f84bSDavid du Colombier int i;
2199ef1f84bSDavid du Colombier Queue *q;
2209ef1f84bSDavid du Colombier
2219ef1f84bSDavid du Colombier for(i = 0; i < nconsdevs; i++)
2229ef1f84bSDavid du Colombier if((q = consdevs[i].q) != nil && qlen(q) > 0)
2239ef1f84bSDavid du Colombier return 1;
2249ef1f84bSDavid du Colombier return 0;
2259ef1f84bSDavid du Colombier }
2269ef1f84bSDavid du Colombier
2279ef1f84bSDavid du Colombier void
prflush(void)2289ef1f84bSDavid du Colombier prflush(void)
2299ef1f84bSDavid du Colombier {
2309ef1f84bSDavid du Colombier ulong now;
2319ef1f84bSDavid du Colombier
2329ef1f84bSDavid du Colombier now = m->ticks;
2339ef1f84bSDavid du Colombier while(consactive())
2349ef1f84bSDavid du Colombier if(m->ticks - now >= 10*HZ)
2359ef1f84bSDavid du Colombier break;
2369ef1f84bSDavid du Colombier }
2379ef1f84bSDavid du Colombier
2389ef1f84bSDavid du Colombier /*
2399ef1f84bSDavid du Colombier * Log console output so it can be retrieved via /dev/kmesg.
2409ef1f84bSDavid du Colombier * This is good for catching boot-time messages after the fact.
2419ef1f84bSDavid du Colombier */
2429ef1f84bSDavid du Colombier struct {
2439ef1f84bSDavid du Colombier Lock lk;
2449ef1f84bSDavid du Colombier char buf[16384];
2459ef1f84bSDavid du Colombier uint n;
2469ef1f84bSDavid du Colombier } kmesg;
2479ef1f84bSDavid du Colombier
2489ef1f84bSDavid du Colombier static void
kmesgputs(char * str,int n)2499ef1f84bSDavid du Colombier kmesgputs(char *str, int n)
2509ef1f84bSDavid du Colombier {
2519ef1f84bSDavid du Colombier uint nn, d;
2529ef1f84bSDavid du Colombier
2539ef1f84bSDavid du Colombier ilock(&kmesg.lk);
2549ef1f84bSDavid du Colombier /* take the tail of huge writes */
2559ef1f84bSDavid du Colombier if(n > sizeof kmesg.buf){
2569ef1f84bSDavid du Colombier d = n - sizeof kmesg.buf;
2579ef1f84bSDavid du Colombier str += d;
2589ef1f84bSDavid du Colombier n -= d;
2599ef1f84bSDavid du Colombier }
2609ef1f84bSDavid du Colombier
2619ef1f84bSDavid du Colombier /* slide the buffer down to make room */
2629ef1f84bSDavid du Colombier nn = kmesg.n;
2639ef1f84bSDavid du Colombier if(nn + n >= sizeof kmesg.buf){
2649ef1f84bSDavid du Colombier d = nn + n - sizeof kmesg.buf;
2659ef1f84bSDavid du Colombier if(d)
2669ef1f84bSDavid du Colombier memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
2679ef1f84bSDavid du Colombier nn -= d;
2689ef1f84bSDavid du Colombier }
2699ef1f84bSDavid du Colombier
2709ef1f84bSDavid du Colombier /* copy the data in */
2719ef1f84bSDavid du Colombier memmove(kmesg.buf+nn, str, n);
2729ef1f84bSDavid du Colombier nn += n;
2739ef1f84bSDavid du Colombier kmesg.n = nn;
2749ef1f84bSDavid du Colombier iunlock(&kmesg.lk);
2759ef1f84bSDavid du Colombier }
2769ef1f84bSDavid du Colombier
2779ef1f84bSDavid du Colombier static void
consdevputs(Consdev * c,char * s,int n,int usewrite)2789ef1f84bSDavid du Colombier consdevputs(Consdev *c, char *s, int n, int usewrite)
2799ef1f84bSDavid du Colombier {
2809ef1f84bSDavid du Colombier Chan *cc;
2819ef1f84bSDavid du Colombier Queue *q;
2829ef1f84bSDavid du Colombier
2839ef1f84bSDavid du Colombier if((cc = c->c) != nil && usewrite)
2849ef1f84bSDavid du Colombier cc->dev->write(cc, s, n, 0);
2859ef1f84bSDavid du Colombier else if((q = c->q) != nil && !qisclosed(q))
2869ef1f84bSDavid du Colombier if(usewrite)
2879ef1f84bSDavid du Colombier qwrite(q, s, n);
2889ef1f84bSDavid du Colombier else
2899ef1f84bSDavid du Colombier qiwrite(q, s, n);
2909ef1f84bSDavid du Colombier else if(c->fn != nil)
2919ef1f84bSDavid du Colombier c->fn(s, n);
2929ef1f84bSDavid du Colombier }
2939ef1f84bSDavid du Colombier
2949ef1f84bSDavid du Colombier /*
2959ef1f84bSDavid du Colombier * Print a string on the console. Convert \n to \r\n for serial
2969ef1f84bSDavid du Colombier * line consoles. Locking of the queues is left up to the screen
2979ef1f84bSDavid du Colombier * or uart code. Multi-line messages to serial consoles may get
2989ef1f84bSDavid du Colombier * interspersed with other messages.
2999ef1f84bSDavid du Colombier */
3009ef1f84bSDavid du Colombier static void
putstrn0(char * str,int n,int usewrite)3019ef1f84bSDavid du Colombier putstrn0(char *str, int n, int usewrite)
3029ef1f84bSDavid du Colombier {
3039ef1f84bSDavid du Colombier Consdev *c;
3049ef1f84bSDavid du Colombier char *s, *t;
3059ef1f84bSDavid du Colombier int i, len, m;
3069ef1f84bSDavid du Colombier
3079ef1f84bSDavid du Colombier if(!islo())
3089ef1f84bSDavid du Colombier usewrite = 0;
3099ef1f84bSDavid du Colombier
3109ef1f84bSDavid du Colombier for(i = 0; i < nconsdevs; i++){
3119ef1f84bSDavid du Colombier c = &consdevs[i];
3129ef1f84bSDavid du Colombier len = n;
3139ef1f84bSDavid du Colombier s = str;
3149ef1f84bSDavid du Colombier while(len > 0){
3159ef1f84bSDavid du Colombier t = nil;
3169ef1f84bSDavid du Colombier if((c->flags&Cntorn) && !kbd.raw)
3179ef1f84bSDavid du Colombier t = memchr(s, '\n', len);
3189ef1f84bSDavid du Colombier if(t != nil && !kbd.raw){
3199ef1f84bSDavid du Colombier m = t-s;
3209ef1f84bSDavid du Colombier consdevputs(c, s, m, usewrite);
3219ef1f84bSDavid du Colombier consdevputs(c, "\r\n", 2, usewrite);
3229ef1f84bSDavid du Colombier len -= m+1;
3239ef1f84bSDavid du Colombier s = t+1;
3249ef1f84bSDavid du Colombier }else{
3259ef1f84bSDavid du Colombier consdevputs(c, s, len, usewrite);
3269ef1f84bSDavid du Colombier break;
3279ef1f84bSDavid du Colombier }
3289ef1f84bSDavid du Colombier }
3299ef1f84bSDavid du Colombier }
3309ef1f84bSDavid du Colombier }
3319ef1f84bSDavid du Colombier
3329ef1f84bSDavid du Colombier void
putstrn(char * str,int n)3339ef1f84bSDavid du Colombier putstrn(char *str, int n)
3349ef1f84bSDavid du Colombier {
3359ef1f84bSDavid du Colombier putstrn0(str, n, 0);
3369ef1f84bSDavid du Colombier }
3379ef1f84bSDavid du Colombier
3389ef1f84bSDavid du Colombier int
print(char * fmt,...)3399ef1f84bSDavid du Colombier print(char *fmt, ...)
3409ef1f84bSDavid du Colombier {
3419ef1f84bSDavid du Colombier int n;
3429ef1f84bSDavid du Colombier va_list arg;
3439ef1f84bSDavid du Colombier char buf[PRINTSIZE];
3449ef1f84bSDavid du Colombier
3459ef1f84bSDavid du Colombier va_start(arg, fmt);
3469ef1f84bSDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
3479ef1f84bSDavid du Colombier va_end(arg);
3489ef1f84bSDavid du Colombier if(panicking <= 0 || up == nil || up->pid == panicking)
3499ef1f84bSDavid du Colombier putstrn(buf, n);
3509ef1f84bSDavid du Colombier
3519ef1f84bSDavid du Colombier return n;
3529ef1f84bSDavid du Colombier }
3539ef1f84bSDavid du Colombier
3549ef1f84bSDavid du Colombier /*
3559ef1f84bSDavid du Colombier * Want to interlock iprints to avoid interlaced output on
3569ef1f84bSDavid du Colombier * multiprocessor, but don't want to deadlock if one processor
3579ef1f84bSDavid du Colombier * dies during print and another has something important to say.
3589ef1f84bSDavid du Colombier * Make a good faith effort.
3599ef1f84bSDavid du Colombier */
3609ef1f84bSDavid du Colombier static Lock iprintlock;
3619ef1f84bSDavid du Colombier
3629ef1f84bSDavid du Colombier static int
iprintcanlock(Lock * l)3639ef1f84bSDavid du Colombier iprintcanlock(Lock *l)
3649ef1f84bSDavid du Colombier {
3659ef1f84bSDavid du Colombier int i;
3669ef1f84bSDavid du Colombier
3679ef1f84bSDavid du Colombier for(i=0; i<1000; i++){
3689ef1f84bSDavid du Colombier if(canlock(l))
3699ef1f84bSDavid du Colombier return 1;
3709ef1f84bSDavid du Colombier if(l->m == m)
3719ef1f84bSDavid du Colombier return 0;
3729ef1f84bSDavid du Colombier microdelay(100);
3739ef1f84bSDavid du Colombier }
3749ef1f84bSDavid du Colombier return 0;
3759ef1f84bSDavid du Colombier }
3769ef1f84bSDavid du Colombier
3779ef1f84bSDavid du Colombier int
iprint(char * fmt,...)3789ef1f84bSDavid du Colombier iprint(char *fmt, ...)
3799ef1f84bSDavid du Colombier {
3809ef1f84bSDavid du Colombier Mreg s;
3819ef1f84bSDavid du Colombier int i, n, locked;
3829ef1f84bSDavid du Colombier va_list arg;
3839ef1f84bSDavid du Colombier char buf[PRINTSIZE];
3849ef1f84bSDavid du Colombier
3859ef1f84bSDavid du Colombier s = splhi();
3869ef1f84bSDavid du Colombier va_start(arg, fmt);
3879ef1f84bSDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
3889ef1f84bSDavid du Colombier va_end(arg);
3899ef1f84bSDavid du Colombier if(panicking > 0 && up != nil && up->pid != panicking)
3909ef1f84bSDavid du Colombier return n;
3919ef1f84bSDavid du Colombier locked = iprintcanlock(&iprintlock);
3929ef1f84bSDavid du Colombier for(i = 0; i < nconsdevs; i++){
3939ef1f84bSDavid du Colombier if((consdevs[i].flags&Ciprint) != 0){
3949ef1f84bSDavid du Colombier if(consdevs[i].q != nil)
3959ef1f84bSDavid du Colombier qiwrite(consdevs[i].q, buf, n);
3969ef1f84bSDavid du Colombier else
3979ef1f84bSDavid du Colombier consdevs[i].fn(buf, n);
3989ef1f84bSDavid du Colombier }
3999ef1f84bSDavid du Colombier }
4009ef1f84bSDavid du Colombier if(locked)
4019ef1f84bSDavid du Colombier unlock(&iprintlock);
4029ef1f84bSDavid du Colombier splx(s);
4039ef1f84bSDavid du Colombier
4049ef1f84bSDavid du Colombier return n;
4059ef1f84bSDavid du Colombier }
4069ef1f84bSDavid du Colombier
4079ef1f84bSDavid du Colombier #pragma profile 0
4089ef1f84bSDavid du Colombier void
panic(char * fmt,...)4099ef1f84bSDavid du Colombier panic(char *fmt, ...)
4109ef1f84bSDavid du Colombier {
4119ef1f84bSDavid du Colombier int n;
4129ef1f84bSDavid du Colombier Mreg s;
4139ef1f84bSDavid du Colombier va_list arg;
4149ef1f84bSDavid du Colombier char buf[PRINTSIZE];
4159ef1f84bSDavid du Colombier
4169ef1f84bSDavid du Colombier consdevs[1].q = nil; /* don't try to write to /dev/kprint */
4179ef1f84bSDavid du Colombier
4189ef1f84bSDavid du Colombier if(panicking)
4199ef1f84bSDavid du Colombier for(;;);
4209ef1f84bSDavid du Colombier panicking = -1;
4219ef1f84bSDavid du Colombier if(up)
4229ef1f84bSDavid du Colombier panicking = up->pid;
4239ef1f84bSDavid du Colombier
4249ef1f84bSDavid du Colombier s = splhi();
4259ef1f84bSDavid du Colombier strcpy(buf, "panic: ");
4269ef1f84bSDavid du Colombier va_start(arg, fmt);
4279ef1f84bSDavid du Colombier n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
4289ef1f84bSDavid du Colombier va_end(arg);
4299ef1f84bSDavid du Colombier // iprint("%s\n", buf);
4309ef1f84bSDavid du Colombier if(consdebug)
4319ef1f84bSDavid du Colombier (*consdebug)();
4329ef1f84bSDavid du Colombier splx(s);
4339ef1f84bSDavid du Colombier prflush();
4349ef1f84bSDavid du Colombier buf[n] = '\n';
4359ef1f84bSDavid du Colombier putstrn(buf, n+1);
4369ef1f84bSDavid du Colombier prflush();
4379ef1f84bSDavid du Colombier dumpstack();
4389ef1f84bSDavid du Colombier prflush();
4399ef1f84bSDavid du Colombier
4409ef1f84bSDavid du Colombier exit(1);
4419ef1f84bSDavid du Colombier }
4429ef1f84bSDavid du Colombier #pragma profile 1
4439ef1f84bSDavid du Colombier /* libmp at least contains a few calls to sysfatal; simulate with panic */
4449ef1f84bSDavid du Colombier void
sysfatal(char * fmt,...)4459ef1f84bSDavid du Colombier sysfatal(char *fmt, ...)
4469ef1f84bSDavid du Colombier {
4479ef1f84bSDavid du Colombier char err[256];
4489ef1f84bSDavid du Colombier va_list arg;
4499ef1f84bSDavid du Colombier
4509ef1f84bSDavid du Colombier va_start(arg, fmt);
4519ef1f84bSDavid du Colombier vseprint(err, err + sizeof err, fmt, arg);
4529ef1f84bSDavid du Colombier va_end(arg);
4539ef1f84bSDavid du Colombier panic("sysfatal: %s", err);
4549ef1f84bSDavid du Colombier }
4559ef1f84bSDavid du Colombier
4569ef1f84bSDavid du Colombier void
_assert(char * fmt)4579ef1f84bSDavid du Colombier _assert(char *fmt)
4589ef1f84bSDavid du Colombier {
4599ef1f84bSDavid du Colombier panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
4609ef1f84bSDavid du Colombier }
4619ef1f84bSDavid du Colombier
4629ef1f84bSDavid du Colombier int
pprint(char * fmt,...)4639ef1f84bSDavid du Colombier pprint(char *fmt, ...)
4649ef1f84bSDavid du Colombier {
4659ef1f84bSDavid du Colombier int n;
4669ef1f84bSDavid du Colombier Chan *c;
4679ef1f84bSDavid du Colombier va_list arg;
4689ef1f84bSDavid du Colombier char buf[2*PRINTSIZE];
4699ef1f84bSDavid du Colombier
4709ef1f84bSDavid du Colombier if(up == nil || up->fgrp == nil)
4719ef1f84bSDavid du Colombier return 0;
4729ef1f84bSDavid du Colombier
4739ef1f84bSDavid du Colombier c = up->fgrp->fd[2];
4749ef1f84bSDavid du Colombier if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
4759ef1f84bSDavid du Colombier return 0;
4769ef1f84bSDavid du Colombier n = snprint(buf, sizeof buf, "%s %d: ", up->text, up->pid);
4779ef1f84bSDavid du Colombier va_start(arg, fmt);
4789ef1f84bSDavid du Colombier n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
4799ef1f84bSDavid du Colombier va_end(arg);
4809ef1f84bSDavid du Colombier
4819ef1f84bSDavid du Colombier if(waserror())
4829ef1f84bSDavid du Colombier return 0;
4839ef1f84bSDavid du Colombier c->dev->write(c, buf, n, c->offset);
4849ef1f84bSDavid du Colombier poperror();
4859ef1f84bSDavid du Colombier
4869ef1f84bSDavid du Colombier lock(c);
4879ef1f84bSDavid du Colombier c->offset += n;
4889ef1f84bSDavid du Colombier unlock(c);
4899ef1f84bSDavid du Colombier
4909ef1f84bSDavid du Colombier return n;
4919ef1f84bSDavid du Colombier }
4929ef1f84bSDavid du Colombier
4939ef1f84bSDavid du Colombier static void
echo(char * buf,int n)4949ef1f84bSDavid du Colombier echo(char *buf, int n)
4959ef1f84bSDavid du Colombier {
4969ef1f84bSDavid du Colombier Mreg s;
4979ef1f84bSDavid du Colombier static int ctrlt, pid;
4989ef1f84bSDavid du Colombier char *e, *p;
4999ef1f84bSDavid du Colombier
5009ef1f84bSDavid du Colombier if(n == 0)
5019ef1f84bSDavid du Colombier return;
5029ef1f84bSDavid du Colombier
5039ef1f84bSDavid du Colombier e = buf+n;
5049ef1f84bSDavid du Colombier for(p = buf; p < e; p++){
5059ef1f84bSDavid du Colombier switch(*p){
5069ef1f84bSDavid du Colombier case 0x10: /* ^P */
5079ef1f84bSDavid du Colombier if(cpuserver && !kbd.ctlpoff){
5089ef1f84bSDavid du Colombier active.exiting = 1;
5099ef1f84bSDavid du Colombier return;
5109ef1f84bSDavid du Colombier }
5119ef1f84bSDavid du Colombier break;
5129ef1f84bSDavid du Colombier case 0x14: /* ^T */
5139ef1f84bSDavid du Colombier ctrlt++;
5149ef1f84bSDavid du Colombier if(ctrlt > 2)
5159ef1f84bSDavid du Colombier ctrlt = 2;
5169ef1f84bSDavid du Colombier continue;
5179ef1f84bSDavid du Colombier }
5189ef1f84bSDavid du Colombier
5199ef1f84bSDavid du Colombier if(ctrlt != 2)
5209ef1f84bSDavid du Colombier continue;
5219ef1f84bSDavid du Colombier
5229ef1f84bSDavid du Colombier /* ^T escapes */
5239ef1f84bSDavid du Colombier ctrlt = 0;
5249ef1f84bSDavid du Colombier switch(*p){
5259ef1f84bSDavid du Colombier case 'S':
5269ef1f84bSDavid du Colombier s = splhi();
5279ef1f84bSDavid du Colombier dumpstack();
5289ef1f84bSDavid du Colombier procdump();
5299ef1f84bSDavid du Colombier splx(s);
5309ef1f84bSDavid du Colombier return;
5319ef1f84bSDavid du Colombier case 's':
5329ef1f84bSDavid du Colombier dumpstack();
5339ef1f84bSDavid du Colombier return;
5349ef1f84bSDavid du Colombier case 'x':
5359ef1f84bSDavid du Colombier ixsummary();
5369ef1f84bSDavid du Colombier mallocsummary();
5379ef1f84bSDavid du Colombier // memorysummary();
5389ef1f84bSDavid du Colombier return;
5399ef1f84bSDavid du Colombier case 'd':
5409ef1f84bSDavid du Colombier if(consdebug == nil)
5419ef1f84bSDavid du Colombier consdebug = rdb;
5429ef1f84bSDavid du Colombier else
5439ef1f84bSDavid du Colombier consdebug = nil;
5449ef1f84bSDavid du Colombier print("consdebug now %#p\n", consdebug);
5459ef1f84bSDavid du Colombier return;
5469ef1f84bSDavid du Colombier case 'D':
5479ef1f84bSDavid du Colombier if(consdebug == nil)
5489ef1f84bSDavid du Colombier consdebug = rdb;
5499ef1f84bSDavid du Colombier consdebug();
5509ef1f84bSDavid du Colombier return;
5519ef1f84bSDavid du Colombier case 'p':
5529ef1f84bSDavid du Colombier s = spllo();
5539ef1f84bSDavid du Colombier procdump();
5549ef1f84bSDavid du Colombier splx(s);
5559ef1f84bSDavid du Colombier return;
5569ef1f84bSDavid du Colombier case 'q':
5579ef1f84bSDavid du Colombier scheddump();
5589ef1f84bSDavid du Colombier return;
5599ef1f84bSDavid du Colombier case 'k':
5609ef1f84bSDavid du Colombier killbig("^t ^t k");
5619ef1f84bSDavid du Colombier return;
5629ef1f84bSDavid du Colombier case 'r':
5639ef1f84bSDavid du Colombier exit(0);
5649ef1f84bSDavid du Colombier return;
5659ef1f84bSDavid du Colombier }
5669ef1f84bSDavid du Colombier }
5679ef1f84bSDavid du Colombier
5689ef1f84bSDavid du Colombier if(kbdq != nil)
5699ef1f84bSDavid du Colombier qproduce(kbdq, buf, n);
5709ef1f84bSDavid du Colombier if(kbd.raw == 0)
5719ef1f84bSDavid du Colombier putstrn(buf, n);
5729ef1f84bSDavid du Colombier }
5739ef1f84bSDavid du Colombier
5749ef1f84bSDavid du Colombier /*
5759ef1f84bSDavid du Colombier * Called by a uart interrupt for console input.
5769ef1f84bSDavid du Colombier *
5779ef1f84bSDavid du Colombier * turn '\r' into '\n' before putting it into the queue.
5789ef1f84bSDavid du Colombier */
5799ef1f84bSDavid du Colombier int
kbdcr2nl(Queue *,int ch)5809ef1f84bSDavid du Colombier kbdcr2nl(Queue*, int ch)
5819ef1f84bSDavid du Colombier {
5829ef1f84bSDavid du Colombier char *next;
5839ef1f84bSDavid du Colombier
5849ef1f84bSDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
5859ef1f84bSDavid du Colombier if(ch == '\r' && !kbd.raw)
5869ef1f84bSDavid du Colombier ch = '\n';
5879ef1f84bSDavid du Colombier next = kbd.iw+1;
5889ef1f84bSDavid du Colombier if(next >= kbd.ie)
5899ef1f84bSDavid du Colombier next = kbd.istage;
5909ef1f84bSDavid du Colombier if(next != kbd.ir){
5919ef1f84bSDavid du Colombier *kbd.iw = ch;
5929ef1f84bSDavid du Colombier kbd.iw = next;
5939ef1f84bSDavid du Colombier }
5949ef1f84bSDavid du Colombier iunlock(&kbd.lockputc);
5959ef1f84bSDavid du Colombier return 0;
5969ef1f84bSDavid du Colombier }
5979ef1f84bSDavid du Colombier
5989ef1f84bSDavid du Colombier /*
5999ef1f84bSDavid du Colombier * Put character, possibly a rune, into read queue at interrupt time.
6009ef1f84bSDavid du Colombier * Called at interrupt time to process a character.
6019ef1f84bSDavid du Colombier */
6029ef1f84bSDavid du Colombier int
kbdputc(Queue *,int ch)6039ef1f84bSDavid du Colombier kbdputc(Queue*, int ch)
6049ef1f84bSDavid du Colombier {
6059ef1f84bSDavid du Colombier int i, n;
6063b1e49d4SDavid du Colombier char buf[UTFmax];
6079ef1f84bSDavid du Colombier Rune r;
6089ef1f84bSDavid du Colombier char *next;
6099ef1f84bSDavid du Colombier
6109ef1f84bSDavid du Colombier if(kbd.ir == nil)
6119ef1f84bSDavid du Colombier return 0; /* in case we're not inited yet */
6129ef1f84bSDavid du Colombier
6139ef1f84bSDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
6149ef1f84bSDavid du Colombier r = ch;
6159ef1f84bSDavid du Colombier n = runetochar(buf, &r);
6169ef1f84bSDavid du Colombier for(i = 0; i < n; i++){
6179ef1f84bSDavid du Colombier next = kbd.iw+1;
6189ef1f84bSDavid du Colombier if(next >= kbd.ie)
6199ef1f84bSDavid du Colombier next = kbd.istage;
6209ef1f84bSDavid du Colombier if(next == kbd.ir)
6219ef1f84bSDavid du Colombier break;
6229ef1f84bSDavid du Colombier *kbd.iw = buf[i];
6239ef1f84bSDavid du Colombier kbd.iw = next;
6249ef1f84bSDavid du Colombier }
6259ef1f84bSDavid du Colombier iunlock(&kbd.lockputc);
6269ef1f84bSDavid du Colombier return 0;
6279ef1f84bSDavid du Colombier }
6289ef1f84bSDavid du Colombier
6299ef1f84bSDavid du Colombier /*
6309ef1f84bSDavid du Colombier * we save up input characters till clock time to reduce
6319ef1f84bSDavid du Colombier * per character interrupt overhead.
6329ef1f84bSDavid du Colombier */
6339ef1f84bSDavid du Colombier static void
kbdputcclock(void)6349ef1f84bSDavid du Colombier kbdputcclock(void)
6359ef1f84bSDavid du Colombier {
6369ef1f84bSDavid du Colombier char *iw;
6379ef1f84bSDavid du Colombier
6389ef1f84bSDavid du Colombier /* this amortizes cost of qproduce */
6399ef1f84bSDavid du Colombier if(kbd.iw != kbd.ir){
6409ef1f84bSDavid du Colombier iw = kbd.iw;
6419ef1f84bSDavid du Colombier if(iw < kbd.ir){
6429ef1f84bSDavid du Colombier echo(kbd.ir, kbd.ie-kbd.ir);
6439ef1f84bSDavid du Colombier kbd.ir = kbd.istage;
6449ef1f84bSDavid du Colombier }
6459ef1f84bSDavid du Colombier if(kbd.ir != iw){
6469ef1f84bSDavid du Colombier echo(kbd.ir, iw-kbd.ir);
6479ef1f84bSDavid du Colombier kbd.ir = iw;
6489ef1f84bSDavid du Colombier }
6499ef1f84bSDavid du Colombier }
6509ef1f84bSDavid du Colombier }
6519ef1f84bSDavid du Colombier
6529ef1f84bSDavid du Colombier enum{
6539ef1f84bSDavid du Colombier Qdir,
6549ef1f84bSDavid du Colombier Qbintime,
6559ef1f84bSDavid du Colombier Qcons,
6569ef1f84bSDavid du Colombier Qconsctl,
6579ef1f84bSDavid du Colombier Qcputime,
6589ef1f84bSDavid du Colombier Qdrivers,
6599ef1f84bSDavid du Colombier Qkmesg,
6609ef1f84bSDavid du Colombier Qkprint,
6619ef1f84bSDavid du Colombier Qhostdomain,
6629ef1f84bSDavid du Colombier Qhostowner,
6639ef1f84bSDavid du Colombier Qnull,
6649ef1f84bSDavid du Colombier Qosversion,
6659ef1f84bSDavid du Colombier Qpgrpid,
6669ef1f84bSDavid du Colombier Qpid,
6679ef1f84bSDavid du Colombier Qppid,
6689ef1f84bSDavid du Colombier Qrandom,
6699ef1f84bSDavid du Colombier Qreboot,
6709ef1f84bSDavid du Colombier Qswap,
6719ef1f84bSDavid du Colombier Qsysname,
6729ef1f84bSDavid du Colombier Qsysstat,
6739ef1f84bSDavid du Colombier Qtime,
6749ef1f84bSDavid du Colombier Quser,
6759ef1f84bSDavid du Colombier Qzero,
6769ef1f84bSDavid du Colombier Qconfig,
6779ef1f84bSDavid du Colombier };
6789ef1f84bSDavid du Colombier
6799ef1f84bSDavid du Colombier enum
6809ef1f84bSDavid du Colombier {
6819ef1f84bSDavid du Colombier VLNUMSIZE= 22,
6829ef1f84bSDavid du Colombier };
6839ef1f84bSDavid du Colombier
6849ef1f84bSDavid du Colombier static Dirtab consdir[]={
6859ef1f84bSDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
6869ef1f84bSDavid du Colombier "bintime", {Qbintime}, 24, 0664,
6879ef1f84bSDavid du Colombier "cons", {Qcons}, 0, 0660,
6889ef1f84bSDavid du Colombier "consctl", {Qconsctl}, 0, 0220,
6899ef1f84bSDavid du Colombier "cputime", {Qcputime}, 6*NUMSIZE, 0444,
6909ef1f84bSDavid du Colombier "drivers", {Qdrivers}, 0, 0444,
6919ef1f84bSDavid du Colombier "hostdomain", {Qhostdomain}, DOMLEN, 0664,
6929ef1f84bSDavid du Colombier "hostowner", {Qhostowner}, 0, 0664,
6939ef1f84bSDavid du Colombier "kmesg", {Qkmesg}, 0, 0440,
6949ef1f84bSDavid du Colombier "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
6959ef1f84bSDavid du Colombier "null", {Qnull}, 0, 0666,
6969ef1f84bSDavid du Colombier "osversion", {Qosversion}, 0, 0444,
6979ef1f84bSDavid du Colombier "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
6989ef1f84bSDavid du Colombier "pid", {Qpid}, NUMSIZE, 0444,
6999ef1f84bSDavid du Colombier "ppid", {Qppid}, NUMSIZE, 0444,
7009ef1f84bSDavid du Colombier "random", {Qrandom}, 0, 0444,
701406c76faSDavid du Colombier "reboot", {Qreboot}, 0, 0660,
7029ef1f84bSDavid du Colombier "swap", {Qswap}, 0, 0664,
7039ef1f84bSDavid du Colombier "sysname", {Qsysname}, 0, 0664,
7049ef1f84bSDavid du Colombier "sysstat", {Qsysstat}, 0, 0666,
7059ef1f84bSDavid du Colombier "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
7069ef1f84bSDavid du Colombier "user", {Quser}, 0, 0666,
7079ef1f84bSDavid du Colombier "zero", {Qzero}, 0, 0444,
7089ef1f84bSDavid du Colombier "config", {Qconfig}, 0, 0444,
7099ef1f84bSDavid du Colombier };
7109ef1f84bSDavid du Colombier
7119ef1f84bSDavid du Colombier int
readnum(ulong off,char * buf,ulong n,ulong val,int size)7129ef1f84bSDavid du Colombier readnum(ulong off, char *buf, ulong n, ulong val, int size)
7139ef1f84bSDavid du Colombier {
7149ef1f84bSDavid du Colombier char tmp[64];
7159ef1f84bSDavid du Colombier
7169ef1f84bSDavid du Colombier snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
7179ef1f84bSDavid du Colombier tmp[size-1] = ' ';
7189ef1f84bSDavid du Colombier if(off >= size)
7199ef1f84bSDavid du Colombier return 0;
7209ef1f84bSDavid du Colombier if(off+n > size)
7219ef1f84bSDavid du Colombier n = size-off;
7229ef1f84bSDavid du Colombier memmove(buf, tmp+off, n);
7239ef1f84bSDavid du Colombier return n;
7249ef1f84bSDavid du Colombier }
7259ef1f84bSDavid du Colombier
7269ef1f84bSDavid du Colombier long
readstr(long offset,char * buf,long n,char * str)7279ef1f84bSDavid du Colombier readstr(long offset, char *buf, long n, char *str)
7289ef1f84bSDavid du Colombier {
7299ef1f84bSDavid du Colombier long size;
7309ef1f84bSDavid du Colombier
7319ef1f84bSDavid du Colombier size = strlen(str);
7329ef1f84bSDavid du Colombier if(offset >= size)
7339ef1f84bSDavid du Colombier return 0;
7349ef1f84bSDavid du Colombier if(offset+n > size)
7359ef1f84bSDavid du Colombier n = size-offset;
7369ef1f84bSDavid du Colombier memmove(buf, str+offset, n);
7379ef1f84bSDavid du Colombier return n;
7389ef1f84bSDavid du Colombier }
7399ef1f84bSDavid du Colombier
7409ef1f84bSDavid du Colombier static void
consinit(void)7419ef1f84bSDavid du Colombier consinit(void)
7429ef1f84bSDavid du Colombier {
7439ef1f84bSDavid du Colombier todinit();
7449ef1f84bSDavid du Colombier randominit();
7459ef1f84bSDavid du Colombier /*
7469ef1f84bSDavid du Colombier * at 115200 baud, the 1024 char buffer takes 56 ms to process,
7479ef1f84bSDavid du Colombier * processing it every 22 ms should be fine
7489ef1f84bSDavid du Colombier */
7499ef1f84bSDavid du Colombier addclock0link(kbdputcclock, 22);
7509ef1f84bSDavid du Colombier kickkbdq();
7519ef1f84bSDavid du Colombier }
7529ef1f84bSDavid du Colombier
7539ef1f84bSDavid du Colombier static Chan*
consattach(char * spec)7549ef1f84bSDavid du Colombier consattach(char *spec)
7559ef1f84bSDavid du Colombier {
7569ef1f84bSDavid du Colombier return devattach('c', spec);
7579ef1f84bSDavid du Colombier }
7589ef1f84bSDavid du Colombier
7599ef1f84bSDavid du Colombier static Walkqid*
conswalk(Chan * c,Chan * nc,char ** name,int nname)7609ef1f84bSDavid du Colombier conswalk(Chan *c, Chan *nc, char **name, int nname)
7619ef1f84bSDavid du Colombier {
7629ef1f84bSDavid du Colombier return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
7639ef1f84bSDavid du Colombier }
7649ef1f84bSDavid du Colombier
7659ef1f84bSDavid du Colombier static long
consstat(Chan * c,uchar * dp,long n)7669ef1f84bSDavid du Colombier consstat(Chan *c, uchar *dp, long n)
7679ef1f84bSDavid du Colombier {
7689ef1f84bSDavid du Colombier return devstat(c, dp, n, consdir, nelem(consdir), devgen);
7699ef1f84bSDavid du Colombier }
7709ef1f84bSDavid du Colombier
7719ef1f84bSDavid du Colombier static Chan*
consopen(Chan * c,int omode)7729ef1f84bSDavid du Colombier consopen(Chan *c, int omode)
7739ef1f84bSDavid du Colombier {
7749ef1f84bSDavid du Colombier c->aux = nil;
7759ef1f84bSDavid du Colombier c = devopen(c, omode, consdir, nelem(consdir), devgen);
7769ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
7779ef1f84bSDavid du Colombier case Qconsctl:
7789ef1f84bSDavid du Colombier incref(&kbd.ctl);
7799ef1f84bSDavid du Colombier break;
7809ef1f84bSDavid du Colombier
7819ef1f84bSDavid du Colombier case Qkprint:
7829ef1f84bSDavid du Colombier if(TAS(&kprintinuse) != 0){
7839ef1f84bSDavid du Colombier c->flag &= ~COPEN;
7849ef1f84bSDavid du Colombier error(Einuse);
7859ef1f84bSDavid du Colombier }
7869ef1f84bSDavid du Colombier if(kprintoq == nil){
7879ef1f84bSDavid du Colombier kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
7889ef1f84bSDavid du Colombier if(kprintoq == nil){
7899ef1f84bSDavid du Colombier c->flag &= ~COPEN;
7909ef1f84bSDavid du Colombier error(Enomem);
7919ef1f84bSDavid du Colombier }
7929ef1f84bSDavid du Colombier qnoblock(kprintoq, 1);
7939ef1f84bSDavid du Colombier consdevs[1].q = kprintoq;
7949ef1f84bSDavid du Colombier }else
7959ef1f84bSDavid du Colombier qreopen(kprintoq);
7969ef1f84bSDavid du Colombier c->iounit = qiomaxatomic;
7979ef1f84bSDavid du Colombier break;
7989ef1f84bSDavid du Colombier }
7999ef1f84bSDavid du Colombier return c;
8009ef1f84bSDavid du Colombier }
8019ef1f84bSDavid du Colombier
8029ef1f84bSDavid du Colombier static void
consclose(Chan * c)8039ef1f84bSDavid du Colombier consclose(Chan *c)
8049ef1f84bSDavid du Colombier {
8059ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
8069ef1f84bSDavid du Colombier /* last close of control file turns off raw */
8079ef1f84bSDavid du Colombier case Qconsctl:
8089ef1f84bSDavid du Colombier if(c->flag&COPEN){
8099ef1f84bSDavid du Colombier if(decref(&kbd.ctl) == 0)
8109ef1f84bSDavid du Colombier kbd.raw = 0;
8119ef1f84bSDavid du Colombier }
8129ef1f84bSDavid du Colombier break;
8139ef1f84bSDavid du Colombier
8149ef1f84bSDavid du Colombier /* close of kprint allows other opens */
8159ef1f84bSDavid du Colombier case Qkprint:
8169ef1f84bSDavid du Colombier if(c->flag & COPEN){
8179ef1f84bSDavid du Colombier kprintinuse = 0;
8189ef1f84bSDavid du Colombier qhangup(kprintoq, nil);
8199ef1f84bSDavid du Colombier }
8209ef1f84bSDavid du Colombier break;
8219ef1f84bSDavid du Colombier }
8229ef1f84bSDavid du Colombier }
8239ef1f84bSDavid du Colombier
8249ef1f84bSDavid du Colombier static long
consread(Chan * c,void * buf,long n,vlong off)8259ef1f84bSDavid du Colombier consread(Chan *c, void *buf, long n, vlong off)
8269ef1f84bSDavid du Colombier {
8279ef1f84bSDavid du Colombier ulong l;
8289ef1f84bSDavid du Colombier Mach *mp;
829*094d6818SDavid du Colombier char *b, *bp, ch, *s;
8309ef1f84bSDavid du Colombier char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
8319ef1f84bSDavid du Colombier int i, k, id, send;
8329ef1f84bSDavid du Colombier long offset;
8339ef1f84bSDavid du Colombier
8349ef1f84bSDavid du Colombier
8359ef1f84bSDavid du Colombier if(n <= 0)
8369ef1f84bSDavid du Colombier return n;
8379ef1f84bSDavid du Colombier
8389ef1f84bSDavid du Colombier offset = off;
8399ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
8409ef1f84bSDavid du Colombier case Qdir:
8419ef1f84bSDavid du Colombier return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
8429ef1f84bSDavid du Colombier
8439ef1f84bSDavid du Colombier case Qcons:
8449ef1f84bSDavid du Colombier qlock(&kbd);
8459ef1f84bSDavid du Colombier if(waserror()) {
8469ef1f84bSDavid du Colombier qunlock(&kbd);
8479ef1f84bSDavid du Colombier nexterror();
8489ef1f84bSDavid du Colombier }
8499ef1f84bSDavid du Colombier while(!qcanread(lineq)){
8509ef1f84bSDavid du Colombier if(qread(kbdq, &ch, 1) == 0)
8519ef1f84bSDavid du Colombier continue;
8529ef1f84bSDavid du Colombier send = 0;
8539ef1f84bSDavid du Colombier if(ch == 0){
8549ef1f84bSDavid du Colombier /* flush output on rawoff -> rawon */
8559ef1f84bSDavid du Colombier if(kbd.x > 0)
8569ef1f84bSDavid du Colombier send = !qcanread(kbdq);
8579ef1f84bSDavid du Colombier }else if(kbd.raw){
8589ef1f84bSDavid du Colombier kbd.line[kbd.x++] = ch;
8599ef1f84bSDavid du Colombier send = !qcanread(kbdq);
8609ef1f84bSDavid du Colombier }else{
8619ef1f84bSDavid du Colombier switch(ch){
8629ef1f84bSDavid du Colombier case '\b':
8639ef1f84bSDavid du Colombier if(kbd.x > 0)
8649ef1f84bSDavid du Colombier kbd.x--;
8659ef1f84bSDavid du Colombier break;
8669ef1f84bSDavid du Colombier case 0x15: /* ^U */
8679ef1f84bSDavid du Colombier kbd.x = 0;
8689ef1f84bSDavid du Colombier break;
8699ef1f84bSDavid du Colombier case '\n':
8709ef1f84bSDavid du Colombier case 0x04: /* ^D */
8719ef1f84bSDavid du Colombier send = 1;
8729ef1f84bSDavid du Colombier default:
8739ef1f84bSDavid du Colombier if(ch != 0x04)
8749ef1f84bSDavid du Colombier kbd.line[kbd.x++] = ch;
8759ef1f84bSDavid du Colombier break;
8769ef1f84bSDavid du Colombier }
8779ef1f84bSDavid du Colombier }
8789ef1f84bSDavid du Colombier if(send || kbd.x == sizeof kbd.line){
8799ef1f84bSDavid du Colombier qwrite(lineq, kbd.line, kbd.x);
8809ef1f84bSDavid du Colombier kbd.x = 0;
8819ef1f84bSDavid du Colombier }
8829ef1f84bSDavid du Colombier }
8839ef1f84bSDavid du Colombier n = qread(lineq, buf, n);
8849ef1f84bSDavid du Colombier qunlock(&kbd);
8859ef1f84bSDavid du Colombier poperror();
8869ef1f84bSDavid du Colombier return n;
8879ef1f84bSDavid du Colombier
8889ef1f84bSDavid du Colombier case Qcputime:
8899ef1f84bSDavid du Colombier k = offset;
8909ef1f84bSDavid du Colombier if(k >= 6*NUMSIZE)
8919ef1f84bSDavid du Colombier return 0;
8929ef1f84bSDavid du Colombier if(k+n > 6*NUMSIZE)
8939ef1f84bSDavid du Colombier n = 6*NUMSIZE - k;
8949ef1f84bSDavid du Colombier /* easiest to format in a separate buffer and copy out */
8959ef1f84bSDavid du Colombier for(i=0; i<6 && NUMSIZE*i<k+n; i++){
8969ef1f84bSDavid du Colombier l = up->time[i];
8979ef1f84bSDavid du Colombier if(i == TReal)
8989ef1f84bSDavid du Colombier l = sys->ticks - l;
8999ef1f84bSDavid du Colombier l = TK2MS(l);
9009ef1f84bSDavid du Colombier readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
9019ef1f84bSDavid du Colombier }
9029ef1f84bSDavid du Colombier memmove(buf, tmp+k, n);
9039ef1f84bSDavid du Colombier return n;
9049ef1f84bSDavid du Colombier
9059ef1f84bSDavid du Colombier case Qkmesg:
9069ef1f84bSDavid du Colombier /*
9079ef1f84bSDavid du Colombier * This is unlocked to avoid tying up a process
9089ef1f84bSDavid du Colombier * that's writing to the buffer. kmesg.n never
9099ef1f84bSDavid du Colombier * gets smaller, so worst case the reader will
9109ef1f84bSDavid du Colombier * see a slurred buffer.
9119ef1f84bSDavid du Colombier */
9129ef1f84bSDavid du Colombier if(off >= kmesg.n)
9139ef1f84bSDavid du Colombier n = 0;
9149ef1f84bSDavid du Colombier else{
9159ef1f84bSDavid du Colombier if(off+n > kmesg.n)
9169ef1f84bSDavid du Colombier n = kmesg.n - off;
9179ef1f84bSDavid du Colombier memmove(buf, kmesg.buf+off, n);
9189ef1f84bSDavid du Colombier }
9199ef1f84bSDavid du Colombier return n;
9209ef1f84bSDavid du Colombier
9219ef1f84bSDavid du Colombier case Qkprint:
9229ef1f84bSDavid du Colombier return qread(kprintoq, buf, n);
9239ef1f84bSDavid du Colombier
9249ef1f84bSDavid du Colombier case Qpgrpid:
9259ef1f84bSDavid du Colombier return readnum(offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
9269ef1f84bSDavid du Colombier
9279ef1f84bSDavid du Colombier case Qpid:
9289ef1f84bSDavid du Colombier return readnum(offset, buf, n, up->pid, NUMSIZE);
9299ef1f84bSDavid du Colombier
9309ef1f84bSDavid du Colombier case Qppid:
9319ef1f84bSDavid du Colombier return readnum(offset, buf, n, up->parentpid, NUMSIZE);
9329ef1f84bSDavid du Colombier
9339ef1f84bSDavid du Colombier case Qtime:
9349ef1f84bSDavid du Colombier return readtime(offset, buf, n);
9359ef1f84bSDavid du Colombier
9369ef1f84bSDavid du Colombier case Qbintime:
9379ef1f84bSDavid du Colombier return readbintime(buf, n);
9389ef1f84bSDavid du Colombier
9399ef1f84bSDavid du Colombier case Qhostowner:
9409ef1f84bSDavid du Colombier return readstr(offset, buf, n, eve);
9419ef1f84bSDavid du Colombier
9429ef1f84bSDavid du Colombier case Qhostdomain:
9439ef1f84bSDavid du Colombier return readstr(offset, buf, n, hostdomain);
9449ef1f84bSDavid du Colombier
9459ef1f84bSDavid du Colombier case Quser:
9469ef1f84bSDavid du Colombier return readstr(offset, buf, n, up->user);
9479ef1f84bSDavid du Colombier
9489ef1f84bSDavid du Colombier case Qnull:
9499ef1f84bSDavid du Colombier return 0;
9509ef1f84bSDavid du Colombier
9519ef1f84bSDavid du Colombier case Qconfig:
9529ef1f84bSDavid du Colombier return readstr(offset, buf, n, configfile);
9539ef1f84bSDavid du Colombier
9549ef1f84bSDavid du Colombier case Qsysstat:
9559ef1f84bSDavid du Colombier b = smalloc(sys->nonline*(NUMSIZE*11+1) + 1); /* +1 for NUL */
9569ef1f84bSDavid du Colombier bp = b;
9579ef1f84bSDavid du Colombier for(id = 0; id < MACHMAX; id++){
9589ef1f84bSDavid du Colombier if((mp = sys->machptr[id]) == nil || !mp->online)
9599ef1f84bSDavid du Colombier continue;
9609ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, id, NUMSIZE);
9619ef1f84bSDavid du Colombier bp += NUMSIZE;
9629ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
9639ef1f84bSDavid du Colombier bp += NUMSIZE;
9649ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
9659ef1f84bSDavid du Colombier bp += NUMSIZE;
9669ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
9679ef1f84bSDavid du Colombier bp += NUMSIZE;
9689ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
9699ef1f84bSDavid du Colombier bp += NUMSIZE;
9709ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
9719ef1f84bSDavid du Colombier bp += NUMSIZE;
9729ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
9739ef1f84bSDavid du Colombier bp += NUMSIZE;
9749ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
9759ef1f84bSDavid du Colombier bp += NUMSIZE;
9769ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE,
9779ef1f84bSDavid du Colombier (mp->perf.avg_inidle*100)/mp->perf.period,
9789ef1f84bSDavid du Colombier NUMSIZE);
9799ef1f84bSDavid du Colombier bp += NUMSIZE;
9809ef1f84bSDavid du Colombier readnum(0, bp, NUMSIZE,
9819ef1f84bSDavid du Colombier (mp->perf.avg_inintr*100)/mp->perf.period,
9829ef1f84bSDavid du Colombier NUMSIZE);
9839ef1f84bSDavid du Colombier bp += NUMSIZE;
9849ef1f84bSDavid du Colombier *bp++ = '\n';
9859ef1f84bSDavid du Colombier }
9869ef1f84bSDavid du Colombier if(waserror()){
9879ef1f84bSDavid du Colombier free(b);
9889ef1f84bSDavid du Colombier nexterror();
9899ef1f84bSDavid du Colombier }
9909ef1f84bSDavid du Colombier n = readstr(offset, buf, n, b);
9919ef1f84bSDavid du Colombier free(b);
9929ef1f84bSDavid du Colombier poperror();
9939ef1f84bSDavid du Colombier return n;
9949ef1f84bSDavid du Colombier
9959ef1f84bSDavid du Colombier case Qswap:
996*094d6818SDavid du Colombier tmp[0] = 0;
997*094d6818SDavid du Colombier s = seprintpagestats(tmp, tmp + sizeof tmp);
998*094d6818SDavid du Colombier s = seprintphysstats(s, tmp + sizeof tmp);
9999ef1f84bSDavid du Colombier b = buf;
1000*094d6818SDavid du Colombier l = s - tmp;
1001*094d6818SDavid du Colombier i = readstr(offset, b, l, tmp);
10029ef1f84bSDavid du Colombier b += i;
10039ef1f84bSDavid du Colombier n -= i;
10049ef1f84bSDavid du Colombier if(offset > l)
10059ef1f84bSDavid du Colombier offset -= l;
10069ef1f84bSDavid du Colombier else
10079ef1f84bSDavid du Colombier offset = 0;
10089ef1f84bSDavid du Colombier
10099ef1f84bSDavid du Colombier return i + mallocreadsummary(c, b, n, offset);
10109ef1f84bSDavid du Colombier
10119ef1f84bSDavid du Colombier case Qsysname:
10129ef1f84bSDavid du Colombier if(sysname == nil)
10139ef1f84bSDavid du Colombier return 0;
10149ef1f84bSDavid du Colombier return readstr(offset, buf, n, sysname);
10159ef1f84bSDavid du Colombier
10169ef1f84bSDavid du Colombier case Qrandom:
10179ef1f84bSDavid du Colombier return randomread(buf, n);
10189ef1f84bSDavid du Colombier
10199ef1f84bSDavid du Colombier case Qdrivers:
10209ef1f84bSDavid du Colombier return devtabread(c, buf, n, off);
10219ef1f84bSDavid du Colombier
10229ef1f84bSDavid du Colombier case Qzero:
10239ef1f84bSDavid du Colombier memset(buf, 0, n);
10249ef1f84bSDavid du Colombier return n;
10259ef1f84bSDavid du Colombier
10269ef1f84bSDavid du Colombier case Qosversion:
10279ef1f84bSDavid du Colombier snprint(tmp, sizeof tmp, "2000");
10289ef1f84bSDavid du Colombier n = readstr(offset, buf, n, tmp);
10299ef1f84bSDavid du Colombier return n;
10309ef1f84bSDavid du Colombier
10319ef1f84bSDavid du Colombier default:
10329ef1f84bSDavid du Colombier print("consread %#llux\n", c->qid.path);
10339ef1f84bSDavid du Colombier error(Egreg);
10349ef1f84bSDavid du Colombier }
10359ef1f84bSDavid du Colombier return -1; /* never reached */
10369ef1f84bSDavid du Colombier }
10379ef1f84bSDavid du Colombier
10389ef1f84bSDavid du Colombier static long
conswrite(Chan * c,void * va,long n,vlong off)10399ef1f84bSDavid du Colombier conswrite(Chan *c, void *va, long n, vlong off)
10409ef1f84bSDavid du Colombier {
10419ef1f84bSDavid du Colombier char buf[256], ch;
10429ef1f84bSDavid du Colombier long l, bp;
10439ef1f84bSDavid du Colombier char *a;
10449ef1f84bSDavid du Colombier Mach *mp;
10459ef1f84bSDavid du Colombier int i;
10469ef1f84bSDavid du Colombier ulong offset;
10479ef1f84bSDavid du Colombier Cmdbuf *cb;
10489ef1f84bSDavid du Colombier Cmdtab *ct;
10499ef1f84bSDavid du Colombier
10509ef1f84bSDavid du Colombier a = va;
10519ef1f84bSDavid du Colombier offset = off;
10529ef1f84bSDavid du Colombier
10539ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
10549ef1f84bSDavid du Colombier case Qcons:
10559ef1f84bSDavid du Colombier /*
10569ef1f84bSDavid du Colombier * Can't page fault in putstrn, so copy the data locally.
10579ef1f84bSDavid du Colombier */
10589ef1f84bSDavid du Colombier l = n;
10599ef1f84bSDavid du Colombier while(l > 0){
10609ef1f84bSDavid du Colombier bp = l;
10619ef1f84bSDavid du Colombier if(bp > sizeof buf)
10629ef1f84bSDavid du Colombier bp = sizeof buf;
10639ef1f84bSDavid du Colombier memmove(buf, a, bp);
10649ef1f84bSDavid du Colombier putstrn0(buf, bp, 1);
10659ef1f84bSDavid du Colombier a += bp;
10669ef1f84bSDavid du Colombier l -= bp;
10679ef1f84bSDavid du Colombier }
10689ef1f84bSDavid du Colombier break;
10699ef1f84bSDavid du Colombier
10709ef1f84bSDavid du Colombier case Qconsctl:
10719ef1f84bSDavid du Colombier if(n >= sizeof(buf))
10729ef1f84bSDavid du Colombier n = sizeof(buf)-1;
10739ef1f84bSDavid du Colombier strncpy(buf, a, n);
10749ef1f84bSDavid du Colombier buf[n] = 0;
10759ef1f84bSDavid du Colombier for(a = buf; a;){
10769ef1f84bSDavid du Colombier if(strncmp(a, "rawon", 5) == 0){
10779ef1f84bSDavid du Colombier kbd.raw = 1;
10789ef1f84bSDavid du Colombier /* clumsy hack - wake up reader */
10799ef1f84bSDavid du Colombier ch = 0;
10809ef1f84bSDavid du Colombier qwrite(kbdq, &ch, 1);
10819ef1f84bSDavid du Colombier }
10829ef1f84bSDavid du Colombier else if(strncmp(a, "rawoff", 6) == 0)
10839ef1f84bSDavid du Colombier kbd.raw = 0;
10849ef1f84bSDavid du Colombier else if(strncmp(a, "ctlpon", 6) == 0)
10859ef1f84bSDavid du Colombier kbd.ctlpoff = 0;
10869ef1f84bSDavid du Colombier else if(strncmp(a, "ctlpoff", 7) == 0)
10879ef1f84bSDavid du Colombier kbd.ctlpoff = 1;
10889ef1f84bSDavid du Colombier if(a = strchr(a, ' '))
10899ef1f84bSDavid du Colombier a++;
10909ef1f84bSDavid du Colombier }
10919ef1f84bSDavid du Colombier break;
10929ef1f84bSDavid du Colombier
10939ef1f84bSDavid du Colombier case Qtime:
10949ef1f84bSDavid du Colombier if(!iseve())
10959ef1f84bSDavid du Colombier error(Eperm);
10969ef1f84bSDavid du Colombier return writetime(a, n);
10979ef1f84bSDavid du Colombier
10989ef1f84bSDavid du Colombier case Qbintime:
10999ef1f84bSDavid du Colombier if(!iseve())
11009ef1f84bSDavid du Colombier error(Eperm);
11019ef1f84bSDavid du Colombier return writebintime(a, n);
11029ef1f84bSDavid du Colombier
11039ef1f84bSDavid du Colombier case Qhostowner:
11049ef1f84bSDavid du Colombier return hostownerwrite(a, n);
11059ef1f84bSDavid du Colombier
11069ef1f84bSDavid du Colombier case Qhostdomain:
11079ef1f84bSDavid du Colombier return hostdomainwrite(a, n);
11089ef1f84bSDavid du Colombier
11099ef1f84bSDavid du Colombier case Quser:
11109ef1f84bSDavid du Colombier return userwrite(a, n);
11119ef1f84bSDavid du Colombier
11129ef1f84bSDavid du Colombier case Qnull:
11139ef1f84bSDavid du Colombier break;
11149ef1f84bSDavid du Colombier
11159ef1f84bSDavid du Colombier case Qconfig:
11169ef1f84bSDavid du Colombier error(Eperm);
11179ef1f84bSDavid du Colombier break;
11189ef1f84bSDavid du Colombier
11199ef1f84bSDavid du Colombier case Qreboot:
11209ef1f84bSDavid du Colombier if(!iseve())
11219ef1f84bSDavid du Colombier error(Eperm);
11229ef1f84bSDavid du Colombier cb = parsecmd(a, n);
11239ef1f84bSDavid du Colombier
11249ef1f84bSDavid du Colombier if(waserror()) {
11259ef1f84bSDavid du Colombier free(cb);
11269ef1f84bSDavid du Colombier nexterror();
11279ef1f84bSDavid du Colombier }
11289ef1f84bSDavid du Colombier ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
11299ef1f84bSDavid du Colombier switch(ct->index) {
11309ef1f84bSDavid du Colombier case CMhalt:
11319ef1f84bSDavid du Colombier reboot(nil, 0, 0);
11329ef1f84bSDavid du Colombier break;
11339ef1f84bSDavid du Colombier case CMreboot:
11349ef1f84bSDavid du Colombier rebootcmd(cb->nf-1, cb->f+1);
11359ef1f84bSDavid du Colombier break;
11369ef1f84bSDavid du Colombier case CMpanic:
11379ef1f84bSDavid du Colombier *(ulong*)0=0;
11389ef1f84bSDavid du Colombier panic("/dev/reboot");
11399ef1f84bSDavid du Colombier }
11409ef1f84bSDavid du Colombier poperror();
11419ef1f84bSDavid du Colombier free(cb);
11429ef1f84bSDavid du Colombier break;
11439ef1f84bSDavid du Colombier
11449ef1f84bSDavid du Colombier case Qsysstat:
11459ef1f84bSDavid du Colombier for(i = 0; i < MACHMAX; i++){
11469ef1f84bSDavid du Colombier if((mp = sys->machptr[i]) == nil || !mp->online)
11479ef1f84bSDavid du Colombier continue;
11489ef1f84bSDavid du Colombier mp->cs = 0;
11499ef1f84bSDavid du Colombier mp->intr = 0;
11509ef1f84bSDavid du Colombier mp->syscall = 0;
11519ef1f84bSDavid du Colombier mp->pfault = 0;
11529ef1f84bSDavid du Colombier mp->tlbfault = 0;
11539ef1f84bSDavid du Colombier mp->tlbpurge = 0;
11549ef1f84bSDavid du Colombier }
11559ef1f84bSDavid du Colombier break;
11569ef1f84bSDavid du Colombier
11579ef1f84bSDavid du Colombier case Qswap:
11589ef1f84bSDavid du Colombier /* no more */
11599ef1f84bSDavid du Colombier break;
11609ef1f84bSDavid du Colombier
11619ef1f84bSDavid du Colombier case Qsysname:
11629ef1f84bSDavid du Colombier if(offset != 0)
11639ef1f84bSDavid du Colombier error(Ebadarg);
11649ef1f84bSDavid du Colombier if(n <= 0 || n >= sizeof buf)
11659ef1f84bSDavid du Colombier error(Ebadarg);
11669ef1f84bSDavid du Colombier strncpy(buf, a, n);
11679ef1f84bSDavid du Colombier buf[n] = 0;
11689ef1f84bSDavid du Colombier if(buf[n-1] == '\n')
11699ef1f84bSDavid du Colombier buf[n-1] = 0;
11709ef1f84bSDavid du Colombier kstrdup(&sysname, buf);
11719ef1f84bSDavid du Colombier break;
11729ef1f84bSDavid du Colombier
11739ef1f84bSDavid du Colombier default:
11749ef1f84bSDavid du Colombier print("conswrite: %#llux\n", c->qid.path);
11759ef1f84bSDavid du Colombier error(Egreg);
11769ef1f84bSDavid du Colombier }
11779ef1f84bSDavid du Colombier return n;
11789ef1f84bSDavid du Colombier }
11799ef1f84bSDavid du Colombier
11809ef1f84bSDavid du Colombier Dev consdevtab = {
11819ef1f84bSDavid du Colombier 'c',
11829ef1f84bSDavid du Colombier "cons",
11839ef1f84bSDavid du Colombier
11849ef1f84bSDavid du Colombier devreset,
11859ef1f84bSDavid du Colombier consinit,
11869ef1f84bSDavid du Colombier devshutdown,
11879ef1f84bSDavid du Colombier consattach,
11889ef1f84bSDavid du Colombier conswalk,
11899ef1f84bSDavid du Colombier consstat,
11909ef1f84bSDavid du Colombier consopen,
11919ef1f84bSDavid du Colombier devcreate,
11929ef1f84bSDavid du Colombier consclose,
11939ef1f84bSDavid du Colombier consread,
11949ef1f84bSDavid du Colombier devbread,
11959ef1f84bSDavid du Colombier conswrite,
11969ef1f84bSDavid du Colombier devbwrite,
11979ef1f84bSDavid du Colombier devremove,
11989ef1f84bSDavid du Colombier devwstat,
11999ef1f84bSDavid du Colombier };
12009ef1f84bSDavid du Colombier
12019ef1f84bSDavid du Colombier static ulong randn;
12029ef1f84bSDavid du Colombier
12039ef1f84bSDavid du Colombier static void
seedrand(void)12049ef1f84bSDavid du Colombier seedrand(void)
12059ef1f84bSDavid du Colombier {
12069ef1f84bSDavid du Colombier if(!waserror()){
12079ef1f84bSDavid du Colombier randomread((void*)&randn, sizeof(randn));
12089ef1f84bSDavid du Colombier poperror();
12099ef1f84bSDavid du Colombier }
12109ef1f84bSDavid du Colombier }
12119ef1f84bSDavid du Colombier
12129ef1f84bSDavid du Colombier int
nrand(int n)12139ef1f84bSDavid du Colombier nrand(int n)
12149ef1f84bSDavid du Colombier {
12159ef1f84bSDavid du Colombier if(randn == 0)
12169ef1f84bSDavid du Colombier seedrand();
12179ef1f84bSDavid du Colombier randn = randn*1103515245 + 12345 + sys->ticks;
12189ef1f84bSDavid du Colombier return (randn>>16) % n;
12199ef1f84bSDavid du Colombier }
12209ef1f84bSDavid du Colombier
12219ef1f84bSDavid du Colombier int
rand(void)12229ef1f84bSDavid du Colombier rand(void)
12239ef1f84bSDavid du Colombier {
12249ef1f84bSDavid du Colombier nrand(1);
12259ef1f84bSDavid du Colombier return randn;
12269ef1f84bSDavid du Colombier }
12279ef1f84bSDavid du Colombier
12289ef1f84bSDavid du Colombier static uvlong uvorder = 0x0001020304050607ULL;
12299ef1f84bSDavid du Colombier
12309ef1f84bSDavid du Colombier static uchar*
le2vlong(vlong * to,uchar * f)12319ef1f84bSDavid du Colombier le2vlong(vlong *to, uchar *f)
12329ef1f84bSDavid du Colombier {
12339ef1f84bSDavid du Colombier uchar *t, *o;
12349ef1f84bSDavid du Colombier int i;
12359ef1f84bSDavid du Colombier
12369ef1f84bSDavid du Colombier t = (uchar*)to;
12379ef1f84bSDavid du Colombier o = (uchar*)&uvorder;
12389ef1f84bSDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
12399ef1f84bSDavid du Colombier t[o[i]] = f[i];
12409ef1f84bSDavid du Colombier return f+sizeof(vlong);
12419ef1f84bSDavid du Colombier }
12429ef1f84bSDavid du Colombier
12439ef1f84bSDavid du Colombier static uchar*
vlong2le(uchar * t,vlong from)12449ef1f84bSDavid du Colombier vlong2le(uchar *t, vlong from)
12459ef1f84bSDavid du Colombier {
12469ef1f84bSDavid du Colombier uchar *f, *o;
12479ef1f84bSDavid du Colombier int i;
12489ef1f84bSDavid du Colombier
12499ef1f84bSDavid du Colombier f = (uchar*)&from;
12509ef1f84bSDavid du Colombier o = (uchar*)&uvorder;
12519ef1f84bSDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
12529ef1f84bSDavid du Colombier t[i] = f[o[i]];
12539ef1f84bSDavid du Colombier return t+sizeof(vlong);
12549ef1f84bSDavid du Colombier }
12559ef1f84bSDavid du Colombier
12569ef1f84bSDavid du Colombier static long order = 0x00010203;
12579ef1f84bSDavid du Colombier
12589ef1f84bSDavid du Colombier static uchar*
le2long(long * to,uchar * f)12599ef1f84bSDavid du Colombier le2long(long *to, uchar *f)
12609ef1f84bSDavid du Colombier {
12619ef1f84bSDavid du Colombier uchar *t, *o;
12629ef1f84bSDavid du Colombier int i;
12639ef1f84bSDavid du Colombier
12649ef1f84bSDavid du Colombier t = (uchar*)to;
12659ef1f84bSDavid du Colombier o = (uchar*)ℴ
12669ef1f84bSDavid du Colombier for(i = 0; i < sizeof(long); i++)
12679ef1f84bSDavid du Colombier t[o[i]] = f[i];
12689ef1f84bSDavid du Colombier return f+sizeof(long);
12699ef1f84bSDavid du Colombier }
12709ef1f84bSDavid du Colombier
12719ef1f84bSDavid du Colombier static uchar*
long2le(uchar * t,long from)12729ef1f84bSDavid du Colombier long2le(uchar *t, long from)
12739ef1f84bSDavid du Colombier {
12749ef1f84bSDavid du Colombier uchar *f, *o;
12759ef1f84bSDavid du Colombier int i;
12769ef1f84bSDavid du Colombier
12779ef1f84bSDavid du Colombier f = (uchar*)&from;
12789ef1f84bSDavid du Colombier o = (uchar*)ℴ
12799ef1f84bSDavid du Colombier for(i = 0; i < sizeof(long); i++)
12809ef1f84bSDavid du Colombier t[i] = f[o[i]];
12819ef1f84bSDavid du Colombier return t+sizeof(long);
12829ef1f84bSDavid du Colombier }
12839ef1f84bSDavid du Colombier
12849ef1f84bSDavid du Colombier char *Ebadtimectl = "bad time control";
12859ef1f84bSDavid du Colombier
12869ef1f84bSDavid du Colombier /*
12879ef1f84bSDavid du Colombier * like the old #c/time but with added info. Return
12889ef1f84bSDavid du Colombier *
12899ef1f84bSDavid du Colombier * secs nanosecs fastticks fasthz
12909ef1f84bSDavid du Colombier */
12919ef1f84bSDavid du Colombier static int
readtime(ulong off,char * buf,int n)12929ef1f84bSDavid du Colombier readtime(ulong off, char *buf, int n)
12939ef1f84bSDavid du Colombier {
12949ef1f84bSDavid du Colombier vlong nsec, ticks;
12959ef1f84bSDavid du Colombier long sec;
12969ef1f84bSDavid du Colombier char str[7*NUMSIZE];
12979ef1f84bSDavid du Colombier
12989ef1f84bSDavid du Colombier nsec = todget(&ticks);
12999ef1f84bSDavid du Colombier if(fasthz == 0LL)
13009ef1f84bSDavid du Colombier fastticks((uvlong*)&fasthz);
13019ef1f84bSDavid du Colombier sec = nsec/1000000000ULL;
13029ef1f84bSDavid du Colombier snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
13039ef1f84bSDavid du Colombier NUMSIZE-1, sec,
13049ef1f84bSDavid du Colombier VLNUMSIZE-1, nsec,
13059ef1f84bSDavid du Colombier VLNUMSIZE-1, ticks,
13069ef1f84bSDavid du Colombier VLNUMSIZE-1, fasthz);
13079ef1f84bSDavid du Colombier return readstr(off, buf, n, str);
13089ef1f84bSDavid du Colombier }
13099ef1f84bSDavid du Colombier
13109ef1f84bSDavid du Colombier /*
13119ef1f84bSDavid du Colombier * set the time in seconds
13129ef1f84bSDavid du Colombier */
13139ef1f84bSDavid du Colombier static int
writetime(char * buf,int n)13149ef1f84bSDavid du Colombier writetime(char *buf, int n)
13159ef1f84bSDavid du Colombier {
13169ef1f84bSDavid du Colombier char b[13];
13179ef1f84bSDavid du Colombier long i;
13189ef1f84bSDavid du Colombier vlong now;
13199ef1f84bSDavid du Colombier
13209ef1f84bSDavid du Colombier if(n >= sizeof(b))
13219ef1f84bSDavid du Colombier error(Ebadtimectl);
13229ef1f84bSDavid du Colombier strncpy(b, buf, n);
13239ef1f84bSDavid du Colombier b[n] = 0;
13249ef1f84bSDavid du Colombier i = strtol(b, 0, 0);
13259ef1f84bSDavid du Colombier if(i <= 0)
13269ef1f84bSDavid du Colombier error(Ebadtimectl);
13279ef1f84bSDavid du Colombier now = i*1000000000LL;
13289ef1f84bSDavid du Colombier todset(now, 0, 0);
13299ef1f84bSDavid du Colombier return n;
13309ef1f84bSDavid du Colombier }
13319ef1f84bSDavid du Colombier
13329ef1f84bSDavid du Colombier /*
13339ef1f84bSDavid du Colombier * read binary time info. all numbers are little endian.
13349ef1f84bSDavid du Colombier * ticks and nsec are syncronized.
13359ef1f84bSDavid du Colombier */
13369ef1f84bSDavid du Colombier static int
readbintime(char * buf,int n)13379ef1f84bSDavid du Colombier readbintime(char *buf, int n)
13389ef1f84bSDavid du Colombier {
13399ef1f84bSDavid du Colombier int i;
13409ef1f84bSDavid du Colombier vlong nsec, ticks;
13419ef1f84bSDavid du Colombier uchar *b = (uchar*)buf;
13429ef1f84bSDavid du Colombier
13439ef1f84bSDavid du Colombier i = 0;
13449ef1f84bSDavid du Colombier if(fasthz == 0LL)
13459ef1f84bSDavid du Colombier fastticks((uvlong*)&fasthz);
13469ef1f84bSDavid du Colombier nsec = todget(&ticks);
13479ef1f84bSDavid du Colombier if(n >= 3*sizeof(uvlong)){
13489ef1f84bSDavid du Colombier vlong2le(b+2*sizeof(uvlong), fasthz);
13499ef1f84bSDavid du Colombier i += sizeof(uvlong);
13509ef1f84bSDavid du Colombier }
13519ef1f84bSDavid du Colombier if(n >= 2*sizeof(uvlong)){
13529ef1f84bSDavid du Colombier vlong2le(b+sizeof(uvlong), ticks);
13539ef1f84bSDavid du Colombier i += sizeof(uvlong);
13549ef1f84bSDavid du Colombier }
13559ef1f84bSDavid du Colombier if(n >= 8){
13569ef1f84bSDavid du Colombier vlong2le(b, nsec);
13579ef1f84bSDavid du Colombier i += sizeof(vlong);
13589ef1f84bSDavid du Colombier }
13599ef1f84bSDavid du Colombier return i;
13609ef1f84bSDavid du Colombier }
13619ef1f84bSDavid du Colombier
13629ef1f84bSDavid du Colombier /*
13639ef1f84bSDavid du Colombier * set any of the following
13649ef1f84bSDavid du Colombier * - time in nsec
13659ef1f84bSDavid du Colombier * - nsec trim applied over some seconds
13669ef1f84bSDavid du Colombier * - clock frequency
13679ef1f84bSDavid du Colombier */
13689ef1f84bSDavid du Colombier static int
writebintime(char * buf,int n)13699ef1f84bSDavid du Colombier writebintime(char *buf, int n)
13709ef1f84bSDavid du Colombier {
13719ef1f84bSDavid du Colombier uchar *p;
13729ef1f84bSDavid du Colombier vlong delta;
13739ef1f84bSDavid du Colombier long period;
13749ef1f84bSDavid du Colombier
13759ef1f84bSDavid du Colombier n--;
13769ef1f84bSDavid du Colombier p = (uchar*)buf + 1;
13779ef1f84bSDavid du Colombier switch(*buf){
13789ef1f84bSDavid du Colombier case 'n':
13799ef1f84bSDavid du Colombier if(n < sizeof(vlong))
13809ef1f84bSDavid du Colombier error(Ebadtimectl);
13819ef1f84bSDavid du Colombier le2vlong(&delta, p);
13829ef1f84bSDavid du Colombier todset(delta, 0, 0);
13839ef1f84bSDavid du Colombier break;
13849ef1f84bSDavid du Colombier case 'd':
13859ef1f84bSDavid du Colombier if(n < sizeof(vlong)+sizeof(long))
13869ef1f84bSDavid du Colombier error(Ebadtimectl);
13879ef1f84bSDavid du Colombier p = le2vlong(&delta, p);
13889ef1f84bSDavid du Colombier le2long(&period, p);
13899ef1f84bSDavid du Colombier todset(-1, delta, period);
13909ef1f84bSDavid du Colombier break;
13919ef1f84bSDavid du Colombier case 'f':
13929ef1f84bSDavid du Colombier if(n < sizeof(uvlong))
13939ef1f84bSDavid du Colombier error(Ebadtimectl);
13949ef1f84bSDavid du Colombier le2vlong(&fasthz, p);
13959ef1f84bSDavid du Colombier todsetfreq(fasthz);
13969ef1f84bSDavid du Colombier break;
13979ef1f84bSDavid du Colombier }
13989ef1f84bSDavid du Colombier return n;
13999ef1f84bSDavid du Colombier }
1400