1*3de6a9c0SDavid du Colombier #include "u.h"
2*3de6a9c0SDavid du Colombier #include "../port/lib.h"
3*3de6a9c0SDavid du Colombier #include "mem.h"
4*3de6a9c0SDavid du Colombier #include "dat.h"
5*3de6a9c0SDavid du Colombier #include "fns.h"
6*3de6a9c0SDavid du Colombier #include "../port/error.h"
7*3de6a9c0SDavid du Colombier #include "pool.h"
8*3de6a9c0SDavid du Colombier
9*3de6a9c0SDavid du Colombier #include <authsrv.h>
10*3de6a9c0SDavid du Colombier
11*3de6a9c0SDavid du Colombier void (*consdebug)(void) = nil;
12*3de6a9c0SDavid du Colombier void (*screenputs)(char*, int) = nil;
13*3de6a9c0SDavid du Colombier
14*3de6a9c0SDavid du Colombier Queue* kbdq; /* unprocessed console input */
15*3de6a9c0SDavid du Colombier Queue* lineq; /* processed console input */
16*3de6a9c0SDavid du Colombier Queue* serialoq; /* serial console output */
17*3de6a9c0SDavid du Colombier Queue* kprintoq; /* console output, for /dev/kprint */
18*3de6a9c0SDavid du Colombier ulong kprintinuse; /* test and set whether /dev/kprint is open */
19*3de6a9c0SDavid du Colombier int iprintscreenputs = 1;
20*3de6a9c0SDavid du Colombier
21*3de6a9c0SDavid du Colombier int panicking;
22*3de6a9c0SDavid du Colombier
23*3de6a9c0SDavid du Colombier static struct
24*3de6a9c0SDavid du Colombier {
25*3de6a9c0SDavid du Colombier QLock;
26*3de6a9c0SDavid du Colombier
27*3de6a9c0SDavid du Colombier int raw; /* true if we shouldn't process input */
28*3de6a9c0SDavid du Colombier Ref ctl; /* number of opens to the control file */
29*3de6a9c0SDavid du Colombier int x; /* index into line */
30*3de6a9c0SDavid du Colombier char line[1024]; /* current input line */
31*3de6a9c0SDavid du Colombier
32*3de6a9c0SDavid du Colombier int count;
33*3de6a9c0SDavid du Colombier int ctlpoff;
34*3de6a9c0SDavid du Colombier
35*3de6a9c0SDavid du Colombier /* a place to save up characters at interrupt time before dumping them in the queue */
36*3de6a9c0SDavid du Colombier Lock lockputc;
37*3de6a9c0SDavid du Colombier char istage[1024];
38*3de6a9c0SDavid du Colombier char *iw;
39*3de6a9c0SDavid du Colombier char *ir;
40*3de6a9c0SDavid du Colombier char *ie;
41*3de6a9c0SDavid du Colombier } kbd = {
42*3de6a9c0SDavid du Colombier .iw = kbd.istage,
43*3de6a9c0SDavid du Colombier .ir = kbd.istage,
44*3de6a9c0SDavid du Colombier .ie = kbd.istage + sizeof(kbd.istage),
45*3de6a9c0SDavid du Colombier };
46*3de6a9c0SDavid du Colombier
47*3de6a9c0SDavid du Colombier char *sysname;
48*3de6a9c0SDavid du Colombier vlong fasthz;
49*3de6a9c0SDavid du Colombier
50*3de6a9c0SDavid du Colombier static void seedrand(void);
51*3de6a9c0SDavid du Colombier static int readtime(ulong, char*, int);
52*3de6a9c0SDavid du Colombier static int readbintime(char*, int);
53*3de6a9c0SDavid du Colombier static int writetime(char*, int);
54*3de6a9c0SDavid du Colombier static int writebintime(char*, int);
55*3de6a9c0SDavid du Colombier
56*3de6a9c0SDavid du Colombier enum
57*3de6a9c0SDavid du Colombier {
58*3de6a9c0SDavid du Colombier CMhalt,
59*3de6a9c0SDavid du Colombier CMreboot,
60*3de6a9c0SDavid du Colombier CMpanic,
61*3de6a9c0SDavid du Colombier };
62*3de6a9c0SDavid du Colombier
63*3de6a9c0SDavid du Colombier Cmdtab rebootmsg[] =
64*3de6a9c0SDavid du Colombier {
65*3de6a9c0SDavid du Colombier CMhalt, "halt", 1,
66*3de6a9c0SDavid du Colombier CMreboot, "reboot", 0,
67*3de6a9c0SDavid du Colombier CMpanic, "panic", 0,
68*3de6a9c0SDavid du Colombier };
69*3de6a9c0SDavid du Colombier
70*3de6a9c0SDavid du Colombier void
printinit(void)71*3de6a9c0SDavid du Colombier printinit(void)
72*3de6a9c0SDavid du Colombier {
73*3de6a9c0SDavid du Colombier lineq = qopen(2*1024, 0, nil, nil);
74*3de6a9c0SDavid du Colombier if(lineq == nil)
75*3de6a9c0SDavid du Colombier panic("printinit");
76*3de6a9c0SDavid du Colombier qnoblock(lineq, 1);
77*3de6a9c0SDavid du Colombier }
78*3de6a9c0SDavid du Colombier
79*3de6a9c0SDavid du Colombier int
consactive(void)80*3de6a9c0SDavid du Colombier consactive(void)
81*3de6a9c0SDavid du Colombier {
82*3de6a9c0SDavid du Colombier if(serialoq)
83*3de6a9c0SDavid du Colombier return qlen(serialoq) > 0;
84*3de6a9c0SDavid du Colombier return 0;
85*3de6a9c0SDavid du Colombier }
86*3de6a9c0SDavid du Colombier
87*3de6a9c0SDavid du Colombier void
prflush(void)88*3de6a9c0SDavid du Colombier prflush(void)
89*3de6a9c0SDavid du Colombier {
90*3de6a9c0SDavid du Colombier ulong now;
91*3de6a9c0SDavid du Colombier
92*3de6a9c0SDavid du Colombier now = m->ticks;
93*3de6a9c0SDavid du Colombier while(consactive())
94*3de6a9c0SDavid du Colombier if(m->ticks - now >= HZ)
95*3de6a9c0SDavid du Colombier break;
96*3de6a9c0SDavid du Colombier }
97*3de6a9c0SDavid du Colombier
98*3de6a9c0SDavid du Colombier /*
99*3de6a9c0SDavid du Colombier * Log console output so it can be retrieved via /dev/kmesg.
100*3de6a9c0SDavid du Colombier * This is good for catching boot-time messages after the fact.
101*3de6a9c0SDavid du Colombier */
102*3de6a9c0SDavid du Colombier struct {
103*3de6a9c0SDavid du Colombier Lock lk;
104*3de6a9c0SDavid du Colombier char buf[KMESGSIZE];
105*3de6a9c0SDavid du Colombier uint n;
106*3de6a9c0SDavid du Colombier } kmesg;
107*3de6a9c0SDavid du Colombier
108*3de6a9c0SDavid du Colombier static void
kmesgputs(char * str,int n)109*3de6a9c0SDavid du Colombier kmesgputs(char *str, int n)
110*3de6a9c0SDavid du Colombier {
111*3de6a9c0SDavid du Colombier uint nn, d;
112*3de6a9c0SDavid du Colombier
113*3de6a9c0SDavid du Colombier ilock(&kmesg.lk);
114*3de6a9c0SDavid du Colombier /* take the tail of huge writes */
115*3de6a9c0SDavid du Colombier if(n > sizeof kmesg.buf){
116*3de6a9c0SDavid du Colombier d = n - sizeof kmesg.buf;
117*3de6a9c0SDavid du Colombier str += d;
118*3de6a9c0SDavid du Colombier n -= d;
119*3de6a9c0SDavid du Colombier }
120*3de6a9c0SDavid du Colombier
121*3de6a9c0SDavid du Colombier /* slide the buffer down to make room */
122*3de6a9c0SDavid du Colombier nn = kmesg.n;
123*3de6a9c0SDavid du Colombier if(nn + n >= sizeof kmesg.buf){
124*3de6a9c0SDavid du Colombier d = nn + n - sizeof kmesg.buf;
125*3de6a9c0SDavid du Colombier if(d)
126*3de6a9c0SDavid du Colombier memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
127*3de6a9c0SDavid du Colombier nn -= d;
128*3de6a9c0SDavid du Colombier }
129*3de6a9c0SDavid du Colombier
130*3de6a9c0SDavid du Colombier /* copy the data in */
131*3de6a9c0SDavid du Colombier memmove(kmesg.buf+nn, str, n);
132*3de6a9c0SDavid du Colombier nn += n;
133*3de6a9c0SDavid du Colombier kmesg.n = nn;
134*3de6a9c0SDavid du Colombier iunlock(&kmesg.lk);
135*3de6a9c0SDavid du Colombier }
136*3de6a9c0SDavid du Colombier
137*3de6a9c0SDavid du Colombier /*
138*3de6a9c0SDavid du Colombier * Print a string on the console. Convert \n to \r\n for serial
139*3de6a9c0SDavid du Colombier * line consoles. Locking of the queues is left up to the screen
140*3de6a9c0SDavid du Colombier * or uart code. Multi-line messages to serial consoles may get
141*3de6a9c0SDavid du Colombier * interspersed with other messages.
142*3de6a9c0SDavid du Colombier */
143*3de6a9c0SDavid du Colombier static void
putstrn0(char * str,int n,int usewrite)144*3de6a9c0SDavid du Colombier putstrn0(char *str, int n, int usewrite)
145*3de6a9c0SDavid du Colombier {
146*3de6a9c0SDavid du Colombier int m;
147*3de6a9c0SDavid du Colombier char *t;
148*3de6a9c0SDavid du Colombier
149*3de6a9c0SDavid du Colombier if(!islo())
150*3de6a9c0SDavid du Colombier usewrite = 0;
151*3de6a9c0SDavid du Colombier
152*3de6a9c0SDavid du Colombier /*
153*3de6a9c0SDavid du Colombier * how many different output devices do we need?
154*3de6a9c0SDavid du Colombier */
155*3de6a9c0SDavid du Colombier kmesgputs(str, n);
156*3de6a9c0SDavid du Colombier
157*3de6a9c0SDavid du Colombier /*
158*3de6a9c0SDavid du Colombier * if someone is reading /dev/kprint,
159*3de6a9c0SDavid du Colombier * put the message there.
160*3de6a9c0SDavid du Colombier * if not and there's an attached bit mapped display,
161*3de6a9c0SDavid du Colombier * put the message there.
162*3de6a9c0SDavid du Colombier *
163*3de6a9c0SDavid du Colombier * if there's a serial line being used as a console,
164*3de6a9c0SDavid du Colombier * put the message there.
165*3de6a9c0SDavid du Colombier */
166*3de6a9c0SDavid du Colombier if(kprintoq != nil && !qisclosed(kprintoq)){
167*3de6a9c0SDavid du Colombier if(usewrite)
168*3de6a9c0SDavid du Colombier qwrite(kprintoq, str, n);
169*3de6a9c0SDavid du Colombier else
170*3de6a9c0SDavid du Colombier qiwrite(kprintoq, str, n);
171*3de6a9c0SDavid du Colombier }else if(screenputs != nil)
172*3de6a9c0SDavid du Colombier screenputs(str, n);
173*3de6a9c0SDavid du Colombier
174*3de6a9c0SDavid du Colombier if(serialoq == nil){
175*3de6a9c0SDavid du Colombier uartputs(str, n);
176*3de6a9c0SDavid du Colombier return;
177*3de6a9c0SDavid du Colombier }
178*3de6a9c0SDavid du Colombier
179*3de6a9c0SDavid du Colombier while(n > 0) {
180*3de6a9c0SDavid du Colombier t = memchr(str, '\n', n);
181*3de6a9c0SDavid du Colombier if(t && !kbd.raw) {
182*3de6a9c0SDavid du Colombier m = t-str;
183*3de6a9c0SDavid du Colombier if(usewrite){
184*3de6a9c0SDavid du Colombier qwrite(serialoq, str, m);
185*3de6a9c0SDavid du Colombier qwrite(serialoq, "\r\n", 2);
186*3de6a9c0SDavid du Colombier } else {
187*3de6a9c0SDavid du Colombier qiwrite(serialoq, str, m);
188*3de6a9c0SDavid du Colombier qiwrite(serialoq, "\r\n", 2);
189*3de6a9c0SDavid du Colombier }
190*3de6a9c0SDavid du Colombier n -= m+1;
191*3de6a9c0SDavid du Colombier str = t+1;
192*3de6a9c0SDavid du Colombier } else {
193*3de6a9c0SDavid du Colombier if(usewrite)
194*3de6a9c0SDavid du Colombier qwrite(serialoq, str, n);
195*3de6a9c0SDavid du Colombier else
196*3de6a9c0SDavid du Colombier qiwrite(serialoq, str, n);
197*3de6a9c0SDavid du Colombier break;
198*3de6a9c0SDavid du Colombier }
199*3de6a9c0SDavid du Colombier }
200*3de6a9c0SDavid du Colombier }
201*3de6a9c0SDavid du Colombier
202*3de6a9c0SDavid du Colombier void
putstrn(char * str,int n)203*3de6a9c0SDavid du Colombier putstrn(char *str, int n)
204*3de6a9c0SDavid du Colombier {
205*3de6a9c0SDavid du Colombier putstrn0(str, n, 0);
206*3de6a9c0SDavid du Colombier }
207*3de6a9c0SDavid du Colombier
208*3de6a9c0SDavid du Colombier int noprint;
209*3de6a9c0SDavid du Colombier
210*3de6a9c0SDavid du Colombier int
print(char * fmt,...)211*3de6a9c0SDavid du Colombier print(char *fmt, ...)
212*3de6a9c0SDavid du Colombier {
213*3de6a9c0SDavid du Colombier int n;
214*3de6a9c0SDavid du Colombier va_list arg;
215*3de6a9c0SDavid du Colombier char buf[PRINTSIZE];
216*3de6a9c0SDavid du Colombier
217*3de6a9c0SDavid du Colombier if(noprint)
218*3de6a9c0SDavid du Colombier return -1;
219*3de6a9c0SDavid du Colombier
220*3de6a9c0SDavid du Colombier va_start(arg, fmt);
221*3de6a9c0SDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
222*3de6a9c0SDavid du Colombier va_end(arg);
223*3de6a9c0SDavid du Colombier
224*3de6a9c0SDavid du Colombier if(!normalprint) {
225*3de6a9c0SDavid du Colombier if(0) iprint("\nprint called too early from %#lux\n",
226*3de6a9c0SDavid du Colombier getcallerpc(&fmt));
227*3de6a9c0SDavid du Colombier iprint("%.*s", n, buf);
228*3de6a9c0SDavid du Colombier } else
229*3de6a9c0SDavid du Colombier putstrn(buf, n);
230*3de6a9c0SDavid du Colombier
231*3de6a9c0SDavid du Colombier return n;
232*3de6a9c0SDavid du Colombier }
233*3de6a9c0SDavid du Colombier
234*3de6a9c0SDavid du Colombier /*
235*3de6a9c0SDavid du Colombier * Want to interlock iprints to avoid interlaced output on
236*3de6a9c0SDavid du Colombier * multiprocessor, but don't want to deadlock if one processor
237*3de6a9c0SDavid du Colombier * dies during print and another has something important to say.
238*3de6a9c0SDavid du Colombier * Make a good faith effort.
239*3de6a9c0SDavid du Colombier */
240*3de6a9c0SDavid du Colombier static Lock iprintlock;
241*3de6a9c0SDavid du Colombier static int
iprintcanlock(Lock * l)242*3de6a9c0SDavid du Colombier iprintcanlock(Lock *l)
243*3de6a9c0SDavid du Colombier {
244*3de6a9c0SDavid du Colombier int i;
245*3de6a9c0SDavid du Colombier
246*3de6a9c0SDavid du Colombier for(i=0; i<1000; i++){
247*3de6a9c0SDavid du Colombier if(canlock(l))
248*3de6a9c0SDavid du Colombier return 1;
249*3de6a9c0SDavid du Colombier if(l->m == MACHP(m->machno))
250*3de6a9c0SDavid du Colombier return 0;
251*3de6a9c0SDavid du Colombier microdelay(100);
252*3de6a9c0SDavid du Colombier }
253*3de6a9c0SDavid du Colombier return 0;
254*3de6a9c0SDavid du Colombier }
255*3de6a9c0SDavid du Colombier
256*3de6a9c0SDavid du Colombier int
iprint(char * fmt,...)257*3de6a9c0SDavid du Colombier iprint(char *fmt, ...)
258*3de6a9c0SDavid du Colombier {
259*3de6a9c0SDavid du Colombier int n, s, locked;
260*3de6a9c0SDavid du Colombier va_list arg;
261*3de6a9c0SDavid du Colombier char buf[PRINTSIZE];
262*3de6a9c0SDavid du Colombier
263*3de6a9c0SDavid du Colombier s = splhi();
264*3de6a9c0SDavid du Colombier va_start(arg, fmt);
265*3de6a9c0SDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
266*3de6a9c0SDavid du Colombier va_end(arg);
267*3de6a9c0SDavid du Colombier locked = iprintcanlock(&iprintlock);
268*3de6a9c0SDavid du Colombier if(screenputs != nil && iprintscreenputs)
269*3de6a9c0SDavid du Colombier screenputs(buf, n);
270*3de6a9c0SDavid du Colombier if(consuart == nil || consuart->phys == nil ||
271*3de6a9c0SDavid du Colombier consuart->phys->putc == nil)
272*3de6a9c0SDavid du Colombier _uartputs(buf, n);
273*3de6a9c0SDavid du Colombier else
274*3de6a9c0SDavid du Colombier uartputs(buf, n);
275*3de6a9c0SDavid du Colombier if(locked)
276*3de6a9c0SDavid du Colombier unlock(&iprintlock);
277*3de6a9c0SDavid du Colombier splx(s);
278*3de6a9c0SDavid du Colombier
279*3de6a9c0SDavid du Colombier return n;
280*3de6a9c0SDavid du Colombier }
281*3de6a9c0SDavid du Colombier
282*3de6a9c0SDavid du Colombier void
panic(char * fmt,...)283*3de6a9c0SDavid du Colombier panic(char *fmt, ...)
284*3de6a9c0SDavid du Colombier {
285*3de6a9c0SDavid du Colombier int n, s;
286*3de6a9c0SDavid du Colombier va_list arg;
287*3de6a9c0SDavid du Colombier char buf[PRINTSIZE];
288*3de6a9c0SDavid du Colombier
289*3de6a9c0SDavid du Colombier kprintoq = nil; /* don't try to write to /dev/kprint */
290*3de6a9c0SDavid du Colombier
291*3de6a9c0SDavid du Colombier if(panicking)
292*3de6a9c0SDavid du Colombier for(;;);
293*3de6a9c0SDavid du Colombier panicking = 1;
294*3de6a9c0SDavid du Colombier
295*3de6a9c0SDavid du Colombier s = splhi();
296*3de6a9c0SDavid du Colombier delay(2000);
297*3de6a9c0SDavid du Colombier strcpy(buf, "\npanic: ");
298*3de6a9c0SDavid du Colombier va_start(arg, fmt);
299*3de6a9c0SDavid du Colombier n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
300*3de6a9c0SDavid du Colombier va_end(arg);
301*3de6a9c0SDavid du Colombier iprint("%s\n", buf);
302*3de6a9c0SDavid du Colombier if(consdebug)
303*3de6a9c0SDavid du Colombier (*consdebug)();
304*3de6a9c0SDavid du Colombier splx(s);
305*3de6a9c0SDavid du Colombier prflush();
306*3de6a9c0SDavid du Colombier USED(n);
307*3de6a9c0SDavid du Colombier // buf[n] = '\n';
308*3de6a9c0SDavid du Colombier // putstrn(buf, n+1); /* redundant */
309*3de6a9c0SDavid du Colombier // dumpstack();
310*3de6a9c0SDavid du Colombier
311*3de6a9c0SDavid du Colombier delay(2000);
312*3de6a9c0SDavid du Colombier exit(1);
313*3de6a9c0SDavid du Colombier }
314*3de6a9c0SDavid du Colombier
315*3de6a9c0SDavid du Colombier /* libmp at least contains a few calls to sysfatal; simulate with panic */
316*3de6a9c0SDavid du Colombier void
sysfatal(char * fmt,...)317*3de6a9c0SDavid du Colombier sysfatal(char *fmt, ...)
318*3de6a9c0SDavid du Colombier {
319*3de6a9c0SDavid du Colombier char err[256];
320*3de6a9c0SDavid du Colombier va_list arg;
321*3de6a9c0SDavid du Colombier
322*3de6a9c0SDavid du Colombier va_start(arg, fmt);
323*3de6a9c0SDavid du Colombier vseprint(err, err + sizeof err, fmt, arg);
324*3de6a9c0SDavid du Colombier va_end(arg);
325*3de6a9c0SDavid du Colombier panic("sysfatal: %s", err);
326*3de6a9c0SDavid du Colombier }
327*3de6a9c0SDavid du Colombier
328*3de6a9c0SDavid du Colombier void
_assert(char * fmt)329*3de6a9c0SDavid du Colombier _assert(char *fmt)
330*3de6a9c0SDavid du Colombier {
331*3de6a9c0SDavid du Colombier panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
332*3de6a9c0SDavid du Colombier }
333*3de6a9c0SDavid du Colombier
334*3de6a9c0SDavid du Colombier int
pprint(char * fmt,...)335*3de6a9c0SDavid du Colombier pprint(char *fmt, ...)
336*3de6a9c0SDavid du Colombier {
337*3de6a9c0SDavid du Colombier int n;
338*3de6a9c0SDavid du Colombier Chan *c;
339*3de6a9c0SDavid du Colombier va_list arg;
340*3de6a9c0SDavid du Colombier char buf[2*PRINTSIZE];
341*3de6a9c0SDavid du Colombier
342*3de6a9c0SDavid du Colombier if(up == nil || up->fgrp == nil)
343*3de6a9c0SDavid du Colombier return 0;
344*3de6a9c0SDavid du Colombier
345*3de6a9c0SDavid du Colombier c = up->fgrp->fd[2];
346*3de6a9c0SDavid du Colombier if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
347*3de6a9c0SDavid du Colombier return 0;
348*3de6a9c0SDavid du Colombier n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
349*3de6a9c0SDavid du Colombier va_start(arg, fmt);
350*3de6a9c0SDavid du Colombier n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
351*3de6a9c0SDavid du Colombier va_end(arg);
352*3de6a9c0SDavid du Colombier
353*3de6a9c0SDavid du Colombier if(waserror())
354*3de6a9c0SDavid du Colombier return 0;
355*3de6a9c0SDavid du Colombier devtab[c->type]->write(c, buf, n, c->offset);
356*3de6a9c0SDavid du Colombier poperror();
357*3de6a9c0SDavid du Colombier
358*3de6a9c0SDavid du Colombier lock(c);
359*3de6a9c0SDavid du Colombier c->offset += n;
360*3de6a9c0SDavid du Colombier unlock(c);
361*3de6a9c0SDavid du Colombier
362*3de6a9c0SDavid du Colombier return n;
363*3de6a9c0SDavid du Colombier }
364*3de6a9c0SDavid du Colombier
365*3de6a9c0SDavid du Colombier static void
echoscreen(char * buf,int n)366*3de6a9c0SDavid du Colombier echoscreen(char *buf, int n)
367*3de6a9c0SDavid du Colombier {
368*3de6a9c0SDavid du Colombier char *e, *p;
369*3de6a9c0SDavid du Colombier char ebuf[128];
370*3de6a9c0SDavid du Colombier int x;
371*3de6a9c0SDavid du Colombier
372*3de6a9c0SDavid du Colombier p = ebuf;
373*3de6a9c0SDavid du Colombier e = ebuf + sizeof(ebuf) - 4;
374*3de6a9c0SDavid du Colombier while(n-- > 0){
375*3de6a9c0SDavid du Colombier if(p >= e){
376*3de6a9c0SDavid du Colombier screenputs(ebuf, p - ebuf);
377*3de6a9c0SDavid du Colombier p = ebuf;
378*3de6a9c0SDavid du Colombier }
379*3de6a9c0SDavid du Colombier x = *buf++;
380*3de6a9c0SDavid du Colombier if(x == 0x15){
381*3de6a9c0SDavid du Colombier *p++ = '^';
382*3de6a9c0SDavid du Colombier *p++ = 'U';
383*3de6a9c0SDavid du Colombier *p++ = '\n';
384*3de6a9c0SDavid du Colombier } else
385*3de6a9c0SDavid du Colombier *p++ = x;
386*3de6a9c0SDavid du Colombier }
387*3de6a9c0SDavid du Colombier if(p != ebuf)
388*3de6a9c0SDavid du Colombier screenputs(ebuf, p - ebuf);
389*3de6a9c0SDavid du Colombier }
390*3de6a9c0SDavid du Colombier
391*3de6a9c0SDavid du Colombier static void
echoserialoq(char * buf,int n)392*3de6a9c0SDavid du Colombier echoserialoq(char *buf, int n)
393*3de6a9c0SDavid du Colombier {
394*3de6a9c0SDavid du Colombier int x;
395*3de6a9c0SDavid du Colombier char *e, *p;
396*3de6a9c0SDavid du Colombier char ebuf[128];
397*3de6a9c0SDavid du Colombier
398*3de6a9c0SDavid du Colombier p = ebuf;
399*3de6a9c0SDavid du Colombier e = ebuf + sizeof(ebuf) - 4;
400*3de6a9c0SDavid du Colombier while(n-- > 0){
401*3de6a9c0SDavid du Colombier if(p >= e){
402*3de6a9c0SDavid du Colombier qiwrite(serialoq, ebuf, p - ebuf);
403*3de6a9c0SDavid du Colombier p = ebuf;
404*3de6a9c0SDavid du Colombier }
405*3de6a9c0SDavid du Colombier x = *buf++;
406*3de6a9c0SDavid du Colombier if(x == '\n'){
407*3de6a9c0SDavid du Colombier *p++ = '\r';
408*3de6a9c0SDavid du Colombier *p++ = '\n';
409*3de6a9c0SDavid du Colombier } else if(x == 0x15){
410*3de6a9c0SDavid du Colombier *p++ = '^';
411*3de6a9c0SDavid du Colombier *p++ = 'U';
412*3de6a9c0SDavid du Colombier *p++ = '\n';
413*3de6a9c0SDavid du Colombier } else
414*3de6a9c0SDavid du Colombier *p++ = x;
415*3de6a9c0SDavid du Colombier }
416*3de6a9c0SDavid du Colombier if(p != ebuf)
417*3de6a9c0SDavid du Colombier qiwrite(serialoq, ebuf, p - ebuf);
418*3de6a9c0SDavid du Colombier }
419*3de6a9c0SDavid du Colombier
420*3de6a9c0SDavid du Colombier static void
echo(char * buf,int n)421*3de6a9c0SDavid du Colombier echo(char *buf, int n)
422*3de6a9c0SDavid du Colombier {
423*3de6a9c0SDavid du Colombier static int ctrlt, pid;
424*3de6a9c0SDavid du Colombier int x;
425*3de6a9c0SDavid du Colombier char *e, *p;
426*3de6a9c0SDavid du Colombier
427*3de6a9c0SDavid du Colombier if(n == 0)
428*3de6a9c0SDavid du Colombier return;
429*3de6a9c0SDavid du Colombier
430*3de6a9c0SDavid du Colombier e = buf+n;
431*3de6a9c0SDavid du Colombier for(p = buf; p < e; p++){
432*3de6a9c0SDavid du Colombier switch(*p){
433*3de6a9c0SDavid du Colombier case 0x10: /* ^P */
434*3de6a9c0SDavid du Colombier if(cpuserver && !kbd.ctlpoff){
435*3de6a9c0SDavid du Colombier active.exiting = 1;
436*3de6a9c0SDavid du Colombier return;
437*3de6a9c0SDavid du Colombier }
438*3de6a9c0SDavid du Colombier break;
439*3de6a9c0SDavid du Colombier case 0x14: /* ^T */
440*3de6a9c0SDavid du Colombier ctrlt++;
441*3de6a9c0SDavid du Colombier if(ctrlt > 2)
442*3de6a9c0SDavid du Colombier ctrlt = 2;
443*3de6a9c0SDavid du Colombier continue;
444*3de6a9c0SDavid du Colombier }
445*3de6a9c0SDavid du Colombier
446*3de6a9c0SDavid du Colombier if(ctrlt != 2)
447*3de6a9c0SDavid du Colombier continue;
448*3de6a9c0SDavid du Colombier
449*3de6a9c0SDavid du Colombier /* ^T escapes */
450*3de6a9c0SDavid du Colombier ctrlt = 0;
451*3de6a9c0SDavid du Colombier switch(*p){
452*3de6a9c0SDavid du Colombier case 'S':
453*3de6a9c0SDavid du Colombier x = splhi();
454*3de6a9c0SDavid du Colombier dumpstack();
455*3de6a9c0SDavid du Colombier procdump();
456*3de6a9c0SDavid du Colombier splx(x);
457*3de6a9c0SDavid du Colombier return;
458*3de6a9c0SDavid du Colombier case 's':
459*3de6a9c0SDavid du Colombier dumpstack();
460*3de6a9c0SDavid du Colombier return;
461*3de6a9c0SDavid du Colombier case 'x':
462*3de6a9c0SDavid du Colombier xsummary();
463*3de6a9c0SDavid du Colombier ixsummary();
464*3de6a9c0SDavid du Colombier mallocsummary();
465*3de6a9c0SDavid du Colombier // memorysummary();
466*3de6a9c0SDavid du Colombier pagersummary();
467*3de6a9c0SDavid du Colombier return;
468*3de6a9c0SDavid du Colombier case 'd':
469*3de6a9c0SDavid du Colombier if(consdebug == nil)
470*3de6a9c0SDavid du Colombier consdebug = rdb;
471*3de6a9c0SDavid du Colombier else
472*3de6a9c0SDavid du Colombier consdebug = nil;
473*3de6a9c0SDavid du Colombier print("consdebug now %#p\n", consdebug);
474*3de6a9c0SDavid du Colombier return;
475*3de6a9c0SDavid du Colombier case 'D':
476*3de6a9c0SDavid du Colombier if(consdebug == nil)
477*3de6a9c0SDavid du Colombier consdebug = rdb;
478*3de6a9c0SDavid du Colombier consdebug();
479*3de6a9c0SDavid du Colombier return;
480*3de6a9c0SDavid du Colombier case 'p':
481*3de6a9c0SDavid du Colombier x = spllo();
482*3de6a9c0SDavid du Colombier procdump();
483*3de6a9c0SDavid du Colombier splx(x);
484*3de6a9c0SDavid du Colombier return;
485*3de6a9c0SDavid du Colombier case 'q':
486*3de6a9c0SDavid du Colombier scheddump();
487*3de6a9c0SDavid du Colombier return;
488*3de6a9c0SDavid du Colombier case 'k':
489*3de6a9c0SDavid du Colombier killbig("^t ^t k");
490*3de6a9c0SDavid du Colombier return;
491*3de6a9c0SDavid du Colombier case 'r':
492*3de6a9c0SDavid du Colombier exit(0);
493*3de6a9c0SDavid du Colombier return;
494*3de6a9c0SDavid du Colombier }
495*3de6a9c0SDavid du Colombier }
496*3de6a9c0SDavid du Colombier
497*3de6a9c0SDavid du Colombier qproduce(kbdq, buf, n);
498*3de6a9c0SDavid du Colombier if(kbd.raw)
499*3de6a9c0SDavid du Colombier return;
500*3de6a9c0SDavid du Colombier kmesgputs(buf, n);
501*3de6a9c0SDavid du Colombier if(screenputs != nil)
502*3de6a9c0SDavid du Colombier echoscreen(buf, n);
503*3de6a9c0SDavid du Colombier if(serialoq)
504*3de6a9c0SDavid du Colombier echoserialoq(buf, n);
505*3de6a9c0SDavid du Colombier }
506*3de6a9c0SDavid du Colombier
507*3de6a9c0SDavid du Colombier /*
508*3de6a9c0SDavid du Colombier * Called by a uart interrupt for console input.
509*3de6a9c0SDavid du Colombier *
510*3de6a9c0SDavid du Colombier * turn '\r' into '\n' before putting it into the queue.
511*3de6a9c0SDavid du Colombier */
512*3de6a9c0SDavid du Colombier int
kbdcr2nl(Queue *,int ch)513*3de6a9c0SDavid du Colombier kbdcr2nl(Queue*, int ch)
514*3de6a9c0SDavid du Colombier {
515*3de6a9c0SDavid du Colombier char *next;
516*3de6a9c0SDavid du Colombier
517*3de6a9c0SDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
518*3de6a9c0SDavid du Colombier if(ch == '\r' && !kbd.raw)
519*3de6a9c0SDavid du Colombier ch = '\n';
520*3de6a9c0SDavid du Colombier next = kbd.iw+1;
521*3de6a9c0SDavid du Colombier if(next >= kbd.ie)
522*3de6a9c0SDavid du Colombier next = kbd.istage;
523*3de6a9c0SDavid du Colombier if(next != kbd.ir){
524*3de6a9c0SDavid du Colombier *kbd.iw = ch;
525*3de6a9c0SDavid du Colombier kbd.iw = next;
526*3de6a9c0SDavid du Colombier }
527*3de6a9c0SDavid du Colombier iunlock(&kbd.lockputc);
528*3de6a9c0SDavid du Colombier return 0;
529*3de6a9c0SDavid du Colombier }
530*3de6a9c0SDavid du Colombier
531*3de6a9c0SDavid du Colombier /*
532*3de6a9c0SDavid du Colombier * Put character, possibly a rune, into read queue at interrupt time.
533*3de6a9c0SDavid du Colombier * Called at interrupt time to process a character.
534*3de6a9c0SDavid du Colombier */
535*3de6a9c0SDavid du Colombier int
kbdputc(Queue *,int ch)536*3de6a9c0SDavid du Colombier kbdputc(Queue*, int ch)
537*3de6a9c0SDavid du Colombier {
538*3de6a9c0SDavid du Colombier int i, n;
539*3de6a9c0SDavid du Colombier char buf[3];
540*3de6a9c0SDavid du Colombier Rune r;
541*3de6a9c0SDavid du Colombier char *next;
542*3de6a9c0SDavid du Colombier
543*3de6a9c0SDavid du Colombier if(kbd.ir == nil)
544*3de6a9c0SDavid du Colombier return 0; /* in case we're not inited yet */
545*3de6a9c0SDavid du Colombier
546*3de6a9c0SDavid du Colombier ilock(&kbd.lockputc); /* just a mutex */
547*3de6a9c0SDavid du Colombier r = ch;
548*3de6a9c0SDavid du Colombier n = runetochar(buf, &r);
549*3de6a9c0SDavid du Colombier for(i = 0; i < n; i++){
550*3de6a9c0SDavid du Colombier next = kbd.iw+1;
551*3de6a9c0SDavid du Colombier if(next >= kbd.ie)
552*3de6a9c0SDavid du Colombier next = kbd.istage;
553*3de6a9c0SDavid du Colombier if(next == kbd.ir)
554*3de6a9c0SDavid du Colombier break;
555*3de6a9c0SDavid du Colombier *kbd.iw = buf[i];
556*3de6a9c0SDavid du Colombier kbd.iw = next;
557*3de6a9c0SDavid du Colombier }
558*3de6a9c0SDavid du Colombier iunlock(&kbd.lockputc);
559*3de6a9c0SDavid du Colombier return 0;
560*3de6a9c0SDavid du Colombier }
561*3de6a9c0SDavid du Colombier
562*3de6a9c0SDavid du Colombier /*
563*3de6a9c0SDavid du Colombier * we save up input characters till clock time to reduce
564*3de6a9c0SDavid du Colombier * per character interrupt overhead.
565*3de6a9c0SDavid du Colombier */
566*3de6a9c0SDavid du Colombier static void
kbdputcclock(void)567*3de6a9c0SDavid du Colombier kbdputcclock(void)
568*3de6a9c0SDavid du Colombier {
569*3de6a9c0SDavid du Colombier char *iw;
570*3de6a9c0SDavid du Colombier
571*3de6a9c0SDavid du Colombier /* this amortizes cost of qproduce */
572*3de6a9c0SDavid du Colombier if(kbd.iw != kbd.ir){
573*3de6a9c0SDavid du Colombier iw = kbd.iw;
574*3de6a9c0SDavid du Colombier if(iw < kbd.ir){
575*3de6a9c0SDavid du Colombier echo(kbd.ir, kbd.ie-kbd.ir);
576*3de6a9c0SDavid du Colombier kbd.ir = kbd.istage;
577*3de6a9c0SDavid du Colombier }
578*3de6a9c0SDavid du Colombier if(kbd.ir != iw){
579*3de6a9c0SDavid du Colombier echo(kbd.ir, iw-kbd.ir);
580*3de6a9c0SDavid du Colombier kbd.ir = iw;
581*3de6a9c0SDavid du Colombier }
582*3de6a9c0SDavid du Colombier }
583*3de6a9c0SDavid du Colombier }
584*3de6a9c0SDavid du Colombier
585*3de6a9c0SDavid du Colombier enum{
586*3de6a9c0SDavid du Colombier Qdir,
587*3de6a9c0SDavid du Colombier Qbintime,
588*3de6a9c0SDavid du Colombier Qcons,
589*3de6a9c0SDavid du Colombier Qconsctl,
590*3de6a9c0SDavid du Colombier Qcputime,
591*3de6a9c0SDavid du Colombier Qdrivers,
592*3de6a9c0SDavid du Colombier Qkmesg,
593*3de6a9c0SDavid du Colombier Qkprint,
594*3de6a9c0SDavid du Colombier Qhostdomain,
595*3de6a9c0SDavid du Colombier Qhostowner,
596*3de6a9c0SDavid du Colombier Qnull,
597*3de6a9c0SDavid du Colombier Qosversion,
598*3de6a9c0SDavid du Colombier Qpgrpid,
599*3de6a9c0SDavid du Colombier Qpid,
600*3de6a9c0SDavid du Colombier Qppid,
601*3de6a9c0SDavid du Colombier Qrandom,
602*3de6a9c0SDavid du Colombier Qreboot,
603*3de6a9c0SDavid du Colombier Qswap,
604*3de6a9c0SDavid du Colombier Qsysname,
605*3de6a9c0SDavid du Colombier Qsysstat,
606*3de6a9c0SDavid du Colombier Qtime,
607*3de6a9c0SDavid du Colombier Quser,
608*3de6a9c0SDavid du Colombier Qzero,
609*3de6a9c0SDavid du Colombier Qconfig,
610*3de6a9c0SDavid du Colombier };
611*3de6a9c0SDavid du Colombier
612*3de6a9c0SDavid du Colombier enum
613*3de6a9c0SDavid du Colombier {
614*3de6a9c0SDavid du Colombier VLNUMSIZE= 22,
615*3de6a9c0SDavid du Colombier };
616*3de6a9c0SDavid du Colombier
617*3de6a9c0SDavid du Colombier static Dirtab consdir[]={
618*3de6a9c0SDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
619*3de6a9c0SDavid du Colombier "bintime", {Qbintime}, 24, 0664,
620*3de6a9c0SDavid du Colombier "cons", {Qcons}, 0, 0660,
621*3de6a9c0SDavid du Colombier "consctl", {Qconsctl}, 0, 0220,
622*3de6a9c0SDavid du Colombier "cputime", {Qcputime}, 6*NUMSIZE, 0444,
623*3de6a9c0SDavid du Colombier "drivers", {Qdrivers}, 0, 0444,
624*3de6a9c0SDavid du Colombier "hostdomain", {Qhostdomain}, DOMLEN, 0664,
625*3de6a9c0SDavid du Colombier "hostowner", {Qhostowner}, 0, 0664,
626*3de6a9c0SDavid du Colombier "kmesg", {Qkmesg}, 0, 0440,
627*3de6a9c0SDavid du Colombier "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
628*3de6a9c0SDavid du Colombier "null", {Qnull}, 0, 0666,
629*3de6a9c0SDavid du Colombier "osversion", {Qosversion}, 0, 0444,
630*3de6a9c0SDavid du Colombier "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
631*3de6a9c0SDavid du Colombier "pid", {Qpid}, NUMSIZE, 0444,
632*3de6a9c0SDavid du Colombier "ppid", {Qppid}, NUMSIZE, 0444,
633*3de6a9c0SDavid du Colombier "random", {Qrandom}, 0, 0444,
634*3de6a9c0SDavid du Colombier "reboot", {Qreboot}, 0, 0664,
635*3de6a9c0SDavid du Colombier "swap", {Qswap}, 0, 0664,
636*3de6a9c0SDavid du Colombier "sysname", {Qsysname}, 0, 0664,
637*3de6a9c0SDavid du Colombier "sysstat", {Qsysstat}, 0, 0666,
638*3de6a9c0SDavid du Colombier "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
639*3de6a9c0SDavid du Colombier "user", {Quser}, 0, 0666,
640*3de6a9c0SDavid du Colombier "zero", {Qzero}, 0, 0444,
641*3de6a9c0SDavid du Colombier "config", {Qconfig}, 0, 0444,
642*3de6a9c0SDavid du Colombier };
643*3de6a9c0SDavid du Colombier
644*3de6a9c0SDavid du Colombier int
readnum(ulong off,char * buf,ulong n,ulong val,int size)645*3de6a9c0SDavid du Colombier readnum(ulong off, char *buf, ulong n, ulong val, int size)
646*3de6a9c0SDavid du Colombier {
647*3de6a9c0SDavid du Colombier char tmp[64];
648*3de6a9c0SDavid du Colombier
649*3de6a9c0SDavid du Colombier snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
650*3de6a9c0SDavid du Colombier tmp[size-1] = ' ';
651*3de6a9c0SDavid du Colombier if(off >= size)
652*3de6a9c0SDavid du Colombier return 0;
653*3de6a9c0SDavid du Colombier if(off+n > size)
654*3de6a9c0SDavid du Colombier n = size-off;
655*3de6a9c0SDavid du Colombier memmove(buf, tmp+off, n);
656*3de6a9c0SDavid du Colombier return n;
657*3de6a9c0SDavid du Colombier }
658*3de6a9c0SDavid du Colombier
659*3de6a9c0SDavid du Colombier int
readstr(ulong off,char * buf,ulong n,char * str)660*3de6a9c0SDavid du Colombier readstr(ulong off, char *buf, ulong n, char *str)
661*3de6a9c0SDavid du Colombier {
662*3de6a9c0SDavid du Colombier int size;
663*3de6a9c0SDavid du Colombier
664*3de6a9c0SDavid du Colombier size = strlen(str);
665*3de6a9c0SDavid du Colombier if(off >= size)
666*3de6a9c0SDavid du Colombier return 0;
667*3de6a9c0SDavid du Colombier if(off+n > size)
668*3de6a9c0SDavid du Colombier n = size-off;
669*3de6a9c0SDavid du Colombier memmove(buf, str+off, n);
670*3de6a9c0SDavid du Colombier return n;
671*3de6a9c0SDavid du Colombier }
672*3de6a9c0SDavid du Colombier
673*3de6a9c0SDavid du Colombier static void
consinit(void)674*3de6a9c0SDavid du Colombier consinit(void)
675*3de6a9c0SDavid du Colombier {
676*3de6a9c0SDavid du Colombier todinit();
677*3de6a9c0SDavid du Colombier randominit();
678*3de6a9c0SDavid du Colombier /*
679*3de6a9c0SDavid du Colombier * at 115200 baud, the 1024 char buffer takes 56 ms to process,
680*3de6a9c0SDavid du Colombier * processing it every 22 ms should be fine
681*3de6a9c0SDavid du Colombier */
682*3de6a9c0SDavid du Colombier addclock0link(kbdputcclock, 22);
683*3de6a9c0SDavid du Colombier }
684*3de6a9c0SDavid du Colombier
685*3de6a9c0SDavid du Colombier static Chan*
consattach(char * spec)686*3de6a9c0SDavid du Colombier consattach(char *spec)
687*3de6a9c0SDavid du Colombier {
688*3de6a9c0SDavid du Colombier return devattach('c', spec);
689*3de6a9c0SDavid du Colombier }
690*3de6a9c0SDavid du Colombier
691*3de6a9c0SDavid du Colombier static Walkqid*
conswalk(Chan * c,Chan * nc,char ** name,int nname)692*3de6a9c0SDavid du Colombier conswalk(Chan *c, Chan *nc, char **name, int nname)
693*3de6a9c0SDavid du Colombier {
694*3de6a9c0SDavid du Colombier return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
695*3de6a9c0SDavid du Colombier }
696*3de6a9c0SDavid du Colombier
697*3de6a9c0SDavid du Colombier static int
consstat(Chan * c,uchar * dp,int n)698*3de6a9c0SDavid du Colombier consstat(Chan *c, uchar *dp, int n)
699*3de6a9c0SDavid du Colombier {
700*3de6a9c0SDavid du Colombier return devstat(c, dp, n, consdir, nelem(consdir), devgen);
701*3de6a9c0SDavid du Colombier }
702*3de6a9c0SDavid du Colombier
703*3de6a9c0SDavid du Colombier static Chan*
consopen(Chan * c,int omode)704*3de6a9c0SDavid du Colombier consopen(Chan *c, int omode)
705*3de6a9c0SDavid du Colombier {
706*3de6a9c0SDavid du Colombier c->aux = nil;
707*3de6a9c0SDavid du Colombier c = devopen(c, omode, consdir, nelem(consdir), devgen);
708*3de6a9c0SDavid du Colombier switch((ulong)c->qid.path){
709*3de6a9c0SDavid du Colombier case Qconsctl:
710*3de6a9c0SDavid du Colombier incref(&kbd.ctl);
711*3de6a9c0SDavid du Colombier break;
712*3de6a9c0SDavid du Colombier
713*3de6a9c0SDavid du Colombier case Qkprint:
714*3de6a9c0SDavid du Colombier if(tas(&kprintinuse) != 0){
715*3de6a9c0SDavid du Colombier c->flag &= ~COPEN;
716*3de6a9c0SDavid du Colombier error(Einuse);
717*3de6a9c0SDavid du Colombier }
718*3de6a9c0SDavid du Colombier if(kprintoq == nil){
719*3de6a9c0SDavid du Colombier kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
720*3de6a9c0SDavid du Colombier if(kprintoq == nil){
721*3de6a9c0SDavid du Colombier c->flag &= ~COPEN;
722*3de6a9c0SDavid du Colombier error(Enomem);
723*3de6a9c0SDavid du Colombier }
724*3de6a9c0SDavid du Colombier qnoblock(kprintoq, 1);
725*3de6a9c0SDavid du Colombier }else
726*3de6a9c0SDavid du Colombier qreopen(kprintoq);
727*3de6a9c0SDavid du Colombier c->iounit = qiomaxatomic;
728*3de6a9c0SDavid du Colombier break;
729*3de6a9c0SDavid du Colombier }
730*3de6a9c0SDavid du Colombier return c;
731*3de6a9c0SDavid du Colombier }
732*3de6a9c0SDavid du Colombier
733*3de6a9c0SDavid du Colombier static void
consclose(Chan * c)734*3de6a9c0SDavid du Colombier consclose(Chan *c)
735*3de6a9c0SDavid du Colombier {
736*3de6a9c0SDavid du Colombier switch((ulong)c->qid.path){
737*3de6a9c0SDavid du Colombier /* last close of control file turns off raw */
738*3de6a9c0SDavid du Colombier case Qconsctl:
739*3de6a9c0SDavid du Colombier if(c->flag&COPEN){
740*3de6a9c0SDavid du Colombier if(decref(&kbd.ctl) == 0)
741*3de6a9c0SDavid du Colombier kbd.raw = 0;
742*3de6a9c0SDavid du Colombier }
743*3de6a9c0SDavid du Colombier break;
744*3de6a9c0SDavid du Colombier
745*3de6a9c0SDavid du Colombier /* close of kprint allows other opens */
746*3de6a9c0SDavid du Colombier case Qkprint:
747*3de6a9c0SDavid du Colombier if(c->flag & COPEN){
748*3de6a9c0SDavid du Colombier kprintinuse = 0;
749*3de6a9c0SDavid du Colombier qhangup(kprintoq, nil);
750*3de6a9c0SDavid du Colombier }
751*3de6a9c0SDavid du Colombier break;
752*3de6a9c0SDavid du Colombier }
753*3de6a9c0SDavid du Colombier }
754*3de6a9c0SDavid du Colombier
755*3de6a9c0SDavid du Colombier static long
consread(Chan * c,void * buf,long n,vlong off)756*3de6a9c0SDavid du Colombier consread(Chan *c, void *buf, long n, vlong off)
757*3de6a9c0SDavid du Colombier {
758*3de6a9c0SDavid du Colombier ulong l;
759*3de6a9c0SDavid du Colombier Mach *mp;
760*3de6a9c0SDavid du Colombier char *b, *bp, ch;
761*3de6a9c0SDavid du Colombier char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
762*3de6a9c0SDavid du Colombier int i, k, id, send;
763*3de6a9c0SDavid du Colombier vlong offset = off;
764*3de6a9c0SDavid du Colombier extern char configfile[];
765*3de6a9c0SDavid du Colombier
766*3de6a9c0SDavid du Colombier if(n <= 0)
767*3de6a9c0SDavid du Colombier return n;
768*3de6a9c0SDavid du Colombier
769*3de6a9c0SDavid du Colombier switch((ulong)c->qid.path){
770*3de6a9c0SDavid du Colombier case Qdir:
771*3de6a9c0SDavid du Colombier return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
772*3de6a9c0SDavid du Colombier
773*3de6a9c0SDavid du Colombier case Qcons:
774*3de6a9c0SDavid du Colombier qlock(&kbd);
775*3de6a9c0SDavid du Colombier if(waserror()) {
776*3de6a9c0SDavid du Colombier qunlock(&kbd);
777*3de6a9c0SDavid du Colombier nexterror();
778*3de6a9c0SDavid du Colombier }
779*3de6a9c0SDavid du Colombier while(!qcanread(lineq)){
780*3de6a9c0SDavid du Colombier if(qread(kbdq, &ch, 1) == 0)
781*3de6a9c0SDavid du Colombier continue;
782*3de6a9c0SDavid du Colombier send = 0;
783*3de6a9c0SDavid du Colombier if(ch == 0){
784*3de6a9c0SDavid du Colombier /* flush output on rawoff -> rawon */
785*3de6a9c0SDavid du Colombier if(kbd.x > 0)
786*3de6a9c0SDavid du Colombier send = !qcanread(kbdq);
787*3de6a9c0SDavid du Colombier }else if(kbd.raw){
788*3de6a9c0SDavid du Colombier kbd.line[kbd.x++] = ch;
789*3de6a9c0SDavid du Colombier send = !qcanread(kbdq);
790*3de6a9c0SDavid du Colombier }else{
791*3de6a9c0SDavid du Colombier switch(ch){
792*3de6a9c0SDavid du Colombier case '\b':
793*3de6a9c0SDavid du Colombier if(kbd.x > 0)
794*3de6a9c0SDavid du Colombier kbd.x--;
795*3de6a9c0SDavid du Colombier break;
796*3de6a9c0SDavid du Colombier case 0x15: /* ^U */
797*3de6a9c0SDavid du Colombier kbd.x = 0;
798*3de6a9c0SDavid du Colombier break;
799*3de6a9c0SDavid du Colombier case '\n':
800*3de6a9c0SDavid du Colombier case 0x04: /* ^D */
801*3de6a9c0SDavid du Colombier send = 1;
802*3de6a9c0SDavid du Colombier default:
803*3de6a9c0SDavid du Colombier if(ch != 0x04)
804*3de6a9c0SDavid du Colombier kbd.line[kbd.x++] = ch;
805*3de6a9c0SDavid du Colombier break;
806*3de6a9c0SDavid du Colombier }
807*3de6a9c0SDavid du Colombier }
808*3de6a9c0SDavid du Colombier if(send || kbd.x == sizeof kbd.line){
809*3de6a9c0SDavid du Colombier qwrite(lineq, kbd.line, kbd.x);
810*3de6a9c0SDavid du Colombier kbd.x = 0;
811*3de6a9c0SDavid du Colombier }
812*3de6a9c0SDavid du Colombier }
813*3de6a9c0SDavid du Colombier n = qread(lineq, buf, n);
814*3de6a9c0SDavid du Colombier qunlock(&kbd);
815*3de6a9c0SDavid du Colombier poperror();
816*3de6a9c0SDavid du Colombier return n;
817*3de6a9c0SDavid du Colombier
818*3de6a9c0SDavid du Colombier case Qcputime:
819*3de6a9c0SDavid du Colombier k = offset;
820*3de6a9c0SDavid du Colombier if(k >= 6*NUMSIZE)
821*3de6a9c0SDavid du Colombier return 0;
822*3de6a9c0SDavid du Colombier if(k+n > 6*NUMSIZE)
823*3de6a9c0SDavid du Colombier n = 6*NUMSIZE - k;
824*3de6a9c0SDavid du Colombier /* easiest to format in a separate buffer and copy out */
825*3de6a9c0SDavid du Colombier for(i=0; i<6 && NUMSIZE*i<k+n; i++){
826*3de6a9c0SDavid du Colombier l = up->time[i];
827*3de6a9c0SDavid du Colombier if(i == TReal)
828*3de6a9c0SDavid du Colombier l = MACHP(0)->ticks - l;
829*3de6a9c0SDavid du Colombier l = TK2MS(l);
830*3de6a9c0SDavid du Colombier readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
831*3de6a9c0SDavid du Colombier }
832*3de6a9c0SDavid du Colombier memmove(buf, tmp+k, n);
833*3de6a9c0SDavid du Colombier return n;
834*3de6a9c0SDavid du Colombier
835*3de6a9c0SDavid du Colombier case Qkmesg:
836*3de6a9c0SDavid du Colombier /*
837*3de6a9c0SDavid du Colombier * This is unlocked to avoid tying up a process
838*3de6a9c0SDavid du Colombier * that's writing to the buffer. kmesg.n never
839*3de6a9c0SDavid du Colombier * gets smaller, so worst case the reader will
840*3de6a9c0SDavid du Colombier * see a slurred buffer.
841*3de6a9c0SDavid du Colombier */
842*3de6a9c0SDavid du Colombier if(off >= kmesg.n)
843*3de6a9c0SDavid du Colombier n = 0;
844*3de6a9c0SDavid du Colombier else{
845*3de6a9c0SDavid du Colombier if(off+n > kmesg.n)
846*3de6a9c0SDavid du Colombier n = kmesg.n - off;
847*3de6a9c0SDavid du Colombier memmove(buf, kmesg.buf+off, n);
848*3de6a9c0SDavid du Colombier }
849*3de6a9c0SDavid du Colombier return n;
850*3de6a9c0SDavid du Colombier
851*3de6a9c0SDavid du Colombier case Qkprint:
852*3de6a9c0SDavid du Colombier return qread(kprintoq, buf, n);
853*3de6a9c0SDavid du Colombier
854*3de6a9c0SDavid du Colombier case Qpgrpid:
855*3de6a9c0SDavid du Colombier return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
856*3de6a9c0SDavid du Colombier
857*3de6a9c0SDavid du Colombier case Qpid:
858*3de6a9c0SDavid du Colombier return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
859*3de6a9c0SDavid du Colombier
860*3de6a9c0SDavid du Colombier case Qppid:
861*3de6a9c0SDavid du Colombier return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
862*3de6a9c0SDavid du Colombier
863*3de6a9c0SDavid du Colombier case Qtime:
864*3de6a9c0SDavid du Colombier return readtime((ulong)offset, buf, n);
865*3de6a9c0SDavid du Colombier
866*3de6a9c0SDavid du Colombier case Qbintime:
867*3de6a9c0SDavid du Colombier return readbintime(buf, n);
868*3de6a9c0SDavid du Colombier
869*3de6a9c0SDavid du Colombier case Qhostowner:
870*3de6a9c0SDavid du Colombier return readstr((ulong)offset, buf, n, eve);
871*3de6a9c0SDavid du Colombier
872*3de6a9c0SDavid du Colombier case Qhostdomain:
873*3de6a9c0SDavid du Colombier return readstr((ulong)offset, buf, n, hostdomain);
874*3de6a9c0SDavid du Colombier
875*3de6a9c0SDavid du Colombier case Quser:
876*3de6a9c0SDavid du Colombier return readstr((ulong)offset, buf, n, up->user);
877*3de6a9c0SDavid du Colombier
878*3de6a9c0SDavid du Colombier case Qnull:
879*3de6a9c0SDavid du Colombier return 0;
880*3de6a9c0SDavid du Colombier
881*3de6a9c0SDavid du Colombier case Qconfig:
882*3de6a9c0SDavid du Colombier return readstr((ulong)offset, buf, n, configfile);
883*3de6a9c0SDavid du Colombier
884*3de6a9c0SDavid du Colombier case Qsysstat:
885*3de6a9c0SDavid du Colombier b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
886*3de6a9c0SDavid du Colombier bp = b;
887*3de6a9c0SDavid du Colombier for(id = 0; id < 32; id++) {
888*3de6a9c0SDavid du Colombier if(active.machs & (1<<id)) {
889*3de6a9c0SDavid du Colombier mp = MACHP(id);
890*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, id, NUMSIZE);
891*3de6a9c0SDavid du Colombier bp += NUMSIZE;
892*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
893*3de6a9c0SDavid du Colombier bp += NUMSIZE;
894*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
895*3de6a9c0SDavid du Colombier bp += NUMSIZE;
896*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
897*3de6a9c0SDavid du Colombier bp += NUMSIZE;
898*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
899*3de6a9c0SDavid du Colombier bp += NUMSIZE;
900*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
901*3de6a9c0SDavid du Colombier bp += NUMSIZE;
902*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
903*3de6a9c0SDavid du Colombier bp += NUMSIZE;
904*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
905*3de6a9c0SDavid du Colombier bp += NUMSIZE;
906*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE,
907*3de6a9c0SDavid du Colombier (mp->perf.avg_inidle*100)/mp->perf.period,
908*3de6a9c0SDavid du Colombier NUMSIZE);
909*3de6a9c0SDavid du Colombier bp += NUMSIZE;
910*3de6a9c0SDavid du Colombier readnum(0, bp, NUMSIZE,
911*3de6a9c0SDavid du Colombier (mp->perf.avg_inintr*100)/mp->perf.period,
912*3de6a9c0SDavid du Colombier NUMSIZE);
913*3de6a9c0SDavid du Colombier bp += NUMSIZE;
914*3de6a9c0SDavid du Colombier *bp++ = '\n';
915*3de6a9c0SDavid du Colombier }
916*3de6a9c0SDavid du Colombier }
917*3de6a9c0SDavid du Colombier if(waserror()){
918*3de6a9c0SDavid du Colombier free(b);
919*3de6a9c0SDavid du Colombier nexterror();
920*3de6a9c0SDavid du Colombier }
921*3de6a9c0SDavid du Colombier n = readstr((ulong)offset, buf, n, b);
922*3de6a9c0SDavid du Colombier free(b);
923*3de6a9c0SDavid du Colombier poperror();
924*3de6a9c0SDavid du Colombier return n;
925*3de6a9c0SDavid du Colombier
926*3de6a9c0SDavid du Colombier case Qswap:
927*3de6a9c0SDavid du Colombier snprint(tmp, sizeof tmp,
928*3de6a9c0SDavid du Colombier "%lud memory\n"
929*3de6a9c0SDavid du Colombier "%d pagesize\n"
930*3de6a9c0SDavid du Colombier "%lud kernel\n"
931*3de6a9c0SDavid du Colombier "%lud/%lud user\n"
932*3de6a9c0SDavid du Colombier "%lud/%lud swap\n"
933*3de6a9c0SDavid du Colombier "%lud/%lud kernel malloc\n"
934*3de6a9c0SDavid du Colombier "%lud/%lud kernel draw\n",
935*3de6a9c0SDavid du Colombier conf.npage*BY2PG,
936*3de6a9c0SDavid du Colombier BY2PG,
937*3de6a9c0SDavid du Colombier conf.npage-conf.upages,
938*3de6a9c0SDavid du Colombier palloc.user-palloc.freecount, palloc.user,
939*3de6a9c0SDavid du Colombier conf.nswap-swapalloc.free, conf.nswap,
940*3de6a9c0SDavid du Colombier mainmem->cursize, mainmem->maxsize,
941*3de6a9c0SDavid du Colombier imagmem->cursize, imagmem->maxsize);
942*3de6a9c0SDavid du Colombier
943*3de6a9c0SDavid du Colombier return readstr((ulong)offset, buf, n, tmp);
944*3de6a9c0SDavid du Colombier
945*3de6a9c0SDavid du Colombier case Qsysname:
946*3de6a9c0SDavid du Colombier if(sysname == nil)
947*3de6a9c0SDavid du Colombier return 0;
948*3de6a9c0SDavid du Colombier return readstr((ulong)offset, buf, n, sysname);
949*3de6a9c0SDavid du Colombier
950*3de6a9c0SDavid du Colombier case Qrandom:
951*3de6a9c0SDavid du Colombier return randomread(buf, n);
952*3de6a9c0SDavid du Colombier
953*3de6a9c0SDavid du Colombier case Qdrivers:
954*3de6a9c0SDavid du Colombier b = malloc(READSTR);
955*3de6a9c0SDavid du Colombier if(b == nil)
956*3de6a9c0SDavid du Colombier error(Enomem);
957*3de6a9c0SDavid du Colombier k = 0;
958*3de6a9c0SDavid du Colombier for(i = 0; devtab[i] != nil; i++)
959*3de6a9c0SDavid du Colombier k += snprint(b+k, READSTR-k, "#%C %s\n",
960*3de6a9c0SDavid du Colombier devtab[i]->dc, devtab[i]->name);
961*3de6a9c0SDavid du Colombier if(waserror()){
962*3de6a9c0SDavid du Colombier free(b);
963*3de6a9c0SDavid du Colombier nexterror();
964*3de6a9c0SDavid du Colombier }
965*3de6a9c0SDavid du Colombier n = readstr((ulong)offset, buf, n, b);
966*3de6a9c0SDavid du Colombier free(b);
967*3de6a9c0SDavid du Colombier poperror();
968*3de6a9c0SDavid du Colombier return n;
969*3de6a9c0SDavid du Colombier
970*3de6a9c0SDavid du Colombier case Qzero:
971*3de6a9c0SDavid du Colombier memset(buf, 0, n);
972*3de6a9c0SDavid du Colombier return n;
973*3de6a9c0SDavid du Colombier
974*3de6a9c0SDavid du Colombier case Qosversion:
975*3de6a9c0SDavid du Colombier snprint(tmp, sizeof tmp, "2000");
976*3de6a9c0SDavid du Colombier n = readstr((ulong)offset, buf, n, tmp);
977*3de6a9c0SDavid du Colombier return n;
978*3de6a9c0SDavid du Colombier
979*3de6a9c0SDavid du Colombier default:
980*3de6a9c0SDavid du Colombier print("consread %#llux\n", c->qid.path);
981*3de6a9c0SDavid du Colombier error(Egreg);
982*3de6a9c0SDavid du Colombier }
983*3de6a9c0SDavid du Colombier return -1; /* never reached */
984*3de6a9c0SDavid du Colombier }
985*3de6a9c0SDavid du Colombier
986*3de6a9c0SDavid du Colombier static long
conswrite(Chan * c,void * va,long n,vlong off)987*3de6a9c0SDavid du Colombier conswrite(Chan *c, void *va, long n, vlong off)
988*3de6a9c0SDavid du Colombier {
989*3de6a9c0SDavid du Colombier char buf[256], ch;
990*3de6a9c0SDavid du Colombier long l, bp;
991*3de6a9c0SDavid du Colombier char *a;
992*3de6a9c0SDavid du Colombier Mach *mp;
993*3de6a9c0SDavid du Colombier int id, fd;
994*3de6a9c0SDavid du Colombier Chan *swc;
995*3de6a9c0SDavid du Colombier ulong offset;
996*3de6a9c0SDavid du Colombier Cmdbuf *cb;
997*3de6a9c0SDavid du Colombier Cmdtab *ct;
998*3de6a9c0SDavid du Colombier
999*3de6a9c0SDavid du Colombier a = va;
1000*3de6a9c0SDavid du Colombier offset = off;
1001*3de6a9c0SDavid du Colombier
1002*3de6a9c0SDavid du Colombier switch((ulong)c->qid.path){
1003*3de6a9c0SDavid du Colombier case Qcons:
1004*3de6a9c0SDavid du Colombier /*
1005*3de6a9c0SDavid du Colombier * Can't page fault in putstrn, so copy the data locally.
1006*3de6a9c0SDavid du Colombier */
1007*3de6a9c0SDavid du Colombier l = n;
1008*3de6a9c0SDavid du Colombier while(l > 0){
1009*3de6a9c0SDavid du Colombier bp = l;
1010*3de6a9c0SDavid du Colombier if(bp > sizeof buf)
1011*3de6a9c0SDavid du Colombier bp = sizeof buf;
1012*3de6a9c0SDavid du Colombier memmove(buf, a, bp);
1013*3de6a9c0SDavid du Colombier putstrn0(buf, bp, 1);
1014*3de6a9c0SDavid du Colombier a += bp;
1015*3de6a9c0SDavid du Colombier l -= bp;
1016*3de6a9c0SDavid du Colombier }
1017*3de6a9c0SDavid du Colombier break;
1018*3de6a9c0SDavid du Colombier
1019*3de6a9c0SDavid du Colombier case Qconsctl:
1020*3de6a9c0SDavid du Colombier if(n >= sizeof(buf))
1021*3de6a9c0SDavid du Colombier n = sizeof(buf)-1;
1022*3de6a9c0SDavid du Colombier strncpy(buf, a, n);
1023*3de6a9c0SDavid du Colombier buf[n] = 0;
1024*3de6a9c0SDavid du Colombier for(a = buf; a;){
1025*3de6a9c0SDavid du Colombier if(strncmp(a, "rawon", 5) == 0){
1026*3de6a9c0SDavid du Colombier kbd.raw = 1;
1027*3de6a9c0SDavid du Colombier /* clumsy hack - wake up reader */
1028*3de6a9c0SDavid du Colombier ch = 0;
1029*3de6a9c0SDavid du Colombier qwrite(kbdq, &ch, 1);
1030*3de6a9c0SDavid du Colombier } else if(strncmp(a, "rawoff", 6) == 0){
1031*3de6a9c0SDavid du Colombier kbd.raw = 0;
1032*3de6a9c0SDavid du Colombier } else if(strncmp(a, "ctlpon", 6) == 0){
1033*3de6a9c0SDavid du Colombier kbd.ctlpoff = 0;
1034*3de6a9c0SDavid du Colombier } else if(strncmp(a, "ctlpoff", 7) == 0){
1035*3de6a9c0SDavid du Colombier kbd.ctlpoff = 1;
1036*3de6a9c0SDavid du Colombier }
1037*3de6a9c0SDavid du Colombier if(a = strchr(a, ' '))
1038*3de6a9c0SDavid du Colombier a++;
1039*3de6a9c0SDavid du Colombier }
1040*3de6a9c0SDavid du Colombier break;
1041*3de6a9c0SDavid du Colombier
1042*3de6a9c0SDavid du Colombier case Qtime:
1043*3de6a9c0SDavid du Colombier if(!iseve())
1044*3de6a9c0SDavid du Colombier error(Eperm);
1045*3de6a9c0SDavid du Colombier return writetime(a, n);
1046*3de6a9c0SDavid du Colombier
1047*3de6a9c0SDavid du Colombier case Qbintime:
1048*3de6a9c0SDavid du Colombier if(!iseve())
1049*3de6a9c0SDavid du Colombier error(Eperm);
1050*3de6a9c0SDavid du Colombier return writebintime(a, n);
1051*3de6a9c0SDavid du Colombier
1052*3de6a9c0SDavid du Colombier case Qhostowner:
1053*3de6a9c0SDavid du Colombier return hostownerwrite(a, n);
1054*3de6a9c0SDavid du Colombier
1055*3de6a9c0SDavid du Colombier case Qhostdomain:
1056*3de6a9c0SDavid du Colombier return hostdomainwrite(a, n);
1057*3de6a9c0SDavid du Colombier
1058*3de6a9c0SDavid du Colombier case Quser:
1059*3de6a9c0SDavid du Colombier return userwrite(a, n);
1060*3de6a9c0SDavid du Colombier
1061*3de6a9c0SDavid du Colombier case Qnull:
1062*3de6a9c0SDavid du Colombier break;
1063*3de6a9c0SDavid du Colombier
1064*3de6a9c0SDavid du Colombier case Qconfig:
1065*3de6a9c0SDavid du Colombier error(Eperm);
1066*3de6a9c0SDavid du Colombier break;
1067*3de6a9c0SDavid du Colombier
1068*3de6a9c0SDavid du Colombier case Qreboot:
1069*3de6a9c0SDavid du Colombier if(!iseve())
1070*3de6a9c0SDavid du Colombier error(Eperm);
1071*3de6a9c0SDavid du Colombier cb = parsecmd(a, n);
1072*3de6a9c0SDavid du Colombier
1073*3de6a9c0SDavid du Colombier if(waserror()) {
1074*3de6a9c0SDavid du Colombier free(cb);
1075*3de6a9c0SDavid du Colombier nexterror();
1076*3de6a9c0SDavid du Colombier }
1077*3de6a9c0SDavid du Colombier ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
1078*3de6a9c0SDavid du Colombier switch(ct->index) {
1079*3de6a9c0SDavid du Colombier case CMhalt:
1080*3de6a9c0SDavid du Colombier reboot(nil, 0, 0);
1081*3de6a9c0SDavid du Colombier break;
1082*3de6a9c0SDavid du Colombier case CMreboot:
1083*3de6a9c0SDavid du Colombier rebootcmd(cb->nf-1, cb->f+1);
1084*3de6a9c0SDavid du Colombier break;
1085*3de6a9c0SDavid du Colombier case CMpanic:
1086*3de6a9c0SDavid du Colombier *(ulong*)0=0;
1087*3de6a9c0SDavid du Colombier panic("/dev/reboot");
1088*3de6a9c0SDavid du Colombier }
1089*3de6a9c0SDavid du Colombier poperror();
1090*3de6a9c0SDavid du Colombier free(cb);
1091*3de6a9c0SDavid du Colombier break;
1092*3de6a9c0SDavid du Colombier
1093*3de6a9c0SDavid du Colombier case Qsysstat:
1094*3de6a9c0SDavid du Colombier for(id = 0; id < 32; id++) {
1095*3de6a9c0SDavid du Colombier if(active.machs & (1<<id)) {
1096*3de6a9c0SDavid du Colombier mp = MACHP(id);
1097*3de6a9c0SDavid du Colombier mp->cs = 0;
1098*3de6a9c0SDavid du Colombier mp->intr = 0;
1099*3de6a9c0SDavid du Colombier mp->syscall = 0;
1100*3de6a9c0SDavid du Colombier mp->pfault = 0;
1101*3de6a9c0SDavid du Colombier mp->tlbfault = 0;
1102*3de6a9c0SDavid du Colombier mp->tlbpurge = 0;
1103*3de6a9c0SDavid du Colombier }
1104*3de6a9c0SDavid du Colombier }
1105*3de6a9c0SDavid du Colombier break;
1106*3de6a9c0SDavid du Colombier
1107*3de6a9c0SDavid du Colombier case Qswap:
1108*3de6a9c0SDavid du Colombier if(n >= sizeof buf)
1109*3de6a9c0SDavid du Colombier error(Egreg);
1110*3de6a9c0SDavid du Colombier memmove(buf, va, n); /* so we can NUL-terminate */
1111*3de6a9c0SDavid du Colombier buf[n] = 0;
1112*3de6a9c0SDavid du Colombier /* start a pager if not already started */
1113*3de6a9c0SDavid du Colombier if(strncmp(buf, "start", 5) == 0){
1114*3de6a9c0SDavid du Colombier kickpager();
1115*3de6a9c0SDavid du Colombier break;
1116*3de6a9c0SDavid du Colombier }
1117*3de6a9c0SDavid du Colombier if(!iseve())
1118*3de6a9c0SDavid du Colombier error(Eperm);
1119*3de6a9c0SDavid du Colombier if(buf[0]<'0' || '9'<buf[0])
1120*3de6a9c0SDavid du Colombier error(Ebadarg);
1121*3de6a9c0SDavid du Colombier fd = strtoul(buf, 0, 0);
1122*3de6a9c0SDavid du Colombier swc = fdtochan(fd, -1, 1, 1);
1123*3de6a9c0SDavid du Colombier setswapchan(swc);
1124*3de6a9c0SDavid du Colombier break;
1125*3de6a9c0SDavid du Colombier
1126*3de6a9c0SDavid du Colombier case Qsysname:
1127*3de6a9c0SDavid du Colombier if(offset != 0)
1128*3de6a9c0SDavid du Colombier error(Ebadarg);
1129*3de6a9c0SDavid du Colombier if(n <= 0 || n >= sizeof buf)
1130*3de6a9c0SDavid du Colombier error(Ebadarg);
1131*3de6a9c0SDavid du Colombier strncpy(buf, a, n);
1132*3de6a9c0SDavid du Colombier buf[n] = 0;
1133*3de6a9c0SDavid du Colombier if(buf[n-1] == '\n')
1134*3de6a9c0SDavid du Colombier buf[n-1] = 0;
1135*3de6a9c0SDavid du Colombier kstrdup(&sysname, buf);
1136*3de6a9c0SDavid du Colombier break;
1137*3de6a9c0SDavid du Colombier
1138*3de6a9c0SDavid du Colombier default:
1139*3de6a9c0SDavid du Colombier print("conswrite: %#llux\n", c->qid.path);
1140*3de6a9c0SDavid du Colombier error(Egreg);
1141*3de6a9c0SDavid du Colombier }
1142*3de6a9c0SDavid du Colombier return n;
1143*3de6a9c0SDavid du Colombier }
1144*3de6a9c0SDavid du Colombier
1145*3de6a9c0SDavid du Colombier Dev consdevtab = {
1146*3de6a9c0SDavid du Colombier 'c',
1147*3de6a9c0SDavid du Colombier "cons",
1148*3de6a9c0SDavid du Colombier
1149*3de6a9c0SDavid du Colombier devreset,
1150*3de6a9c0SDavid du Colombier consinit,
1151*3de6a9c0SDavid du Colombier devshutdown,
1152*3de6a9c0SDavid du Colombier consattach,
1153*3de6a9c0SDavid du Colombier conswalk,
1154*3de6a9c0SDavid du Colombier consstat,
1155*3de6a9c0SDavid du Colombier consopen,
1156*3de6a9c0SDavid du Colombier devcreate,
1157*3de6a9c0SDavid du Colombier consclose,
1158*3de6a9c0SDavid du Colombier consread,
1159*3de6a9c0SDavid du Colombier devbread,
1160*3de6a9c0SDavid du Colombier conswrite,
1161*3de6a9c0SDavid du Colombier devbwrite,
1162*3de6a9c0SDavid du Colombier devremove,
1163*3de6a9c0SDavid du Colombier devwstat,
1164*3de6a9c0SDavid du Colombier };
1165*3de6a9c0SDavid du Colombier
1166*3de6a9c0SDavid du Colombier static ulong randn;
1167*3de6a9c0SDavid du Colombier
1168*3de6a9c0SDavid du Colombier static void
seedrand(void)1169*3de6a9c0SDavid du Colombier seedrand(void)
1170*3de6a9c0SDavid du Colombier {
1171*3de6a9c0SDavid du Colombier if(!waserror()){
1172*3de6a9c0SDavid du Colombier randomread((void*)&randn, sizeof(randn));
1173*3de6a9c0SDavid du Colombier poperror();
1174*3de6a9c0SDavid du Colombier }
1175*3de6a9c0SDavid du Colombier }
1176*3de6a9c0SDavid du Colombier
1177*3de6a9c0SDavid du Colombier int
nrand(int n)1178*3de6a9c0SDavid du Colombier nrand(int n)
1179*3de6a9c0SDavid du Colombier {
1180*3de6a9c0SDavid du Colombier if(randn == 0)
1181*3de6a9c0SDavid du Colombier seedrand();
1182*3de6a9c0SDavid du Colombier randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
1183*3de6a9c0SDavid du Colombier return (randn>>16) % n;
1184*3de6a9c0SDavid du Colombier }
1185*3de6a9c0SDavid du Colombier
1186*3de6a9c0SDavid du Colombier int
rand(void)1187*3de6a9c0SDavid du Colombier rand(void)
1188*3de6a9c0SDavid du Colombier {
1189*3de6a9c0SDavid du Colombier nrand(1);
1190*3de6a9c0SDavid du Colombier return randn;
1191*3de6a9c0SDavid du Colombier }
1192*3de6a9c0SDavid du Colombier
1193*3de6a9c0SDavid du Colombier static uvlong uvorder = 0x0001020304050607ULL;
1194*3de6a9c0SDavid du Colombier
1195*3de6a9c0SDavid du Colombier static uchar*
le2vlong(vlong * to,uchar * f)1196*3de6a9c0SDavid du Colombier le2vlong(vlong *to, uchar *f)
1197*3de6a9c0SDavid du Colombier {
1198*3de6a9c0SDavid du Colombier uchar *t, *o;
1199*3de6a9c0SDavid du Colombier int i;
1200*3de6a9c0SDavid du Colombier
1201*3de6a9c0SDavid du Colombier t = (uchar*)to;
1202*3de6a9c0SDavid du Colombier o = (uchar*)&uvorder;
1203*3de6a9c0SDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
1204*3de6a9c0SDavid du Colombier t[o[i]] = f[i];
1205*3de6a9c0SDavid du Colombier return f+sizeof(vlong);
1206*3de6a9c0SDavid du Colombier }
1207*3de6a9c0SDavid du Colombier
1208*3de6a9c0SDavid du Colombier static uchar*
vlong2le(uchar * t,vlong from)1209*3de6a9c0SDavid du Colombier vlong2le(uchar *t, vlong from)
1210*3de6a9c0SDavid du Colombier {
1211*3de6a9c0SDavid du Colombier uchar *f, *o;
1212*3de6a9c0SDavid du Colombier int i;
1213*3de6a9c0SDavid du Colombier
1214*3de6a9c0SDavid du Colombier f = (uchar*)&from;
1215*3de6a9c0SDavid du Colombier o = (uchar*)&uvorder;
1216*3de6a9c0SDavid du Colombier for(i = 0; i < sizeof(vlong); i++)
1217*3de6a9c0SDavid du Colombier t[i] = f[o[i]];
1218*3de6a9c0SDavid du Colombier return t+sizeof(vlong);
1219*3de6a9c0SDavid du Colombier }
1220*3de6a9c0SDavid du Colombier
1221*3de6a9c0SDavid du Colombier static long order = 0x00010203;
1222*3de6a9c0SDavid du Colombier
1223*3de6a9c0SDavid du Colombier static uchar*
le2long(long * to,uchar * f)1224*3de6a9c0SDavid du Colombier le2long(long *to, uchar *f)
1225*3de6a9c0SDavid du Colombier {
1226*3de6a9c0SDavid du Colombier uchar *t, *o;
1227*3de6a9c0SDavid du Colombier int i;
1228*3de6a9c0SDavid du Colombier
1229*3de6a9c0SDavid du Colombier t = (uchar*)to;
1230*3de6a9c0SDavid du Colombier o = (uchar*)ℴ
1231*3de6a9c0SDavid du Colombier for(i = 0; i < sizeof(long); i++)
1232*3de6a9c0SDavid du Colombier t[o[i]] = f[i];
1233*3de6a9c0SDavid du Colombier return f+sizeof(long);
1234*3de6a9c0SDavid du Colombier }
1235*3de6a9c0SDavid du Colombier
1236*3de6a9c0SDavid du Colombier static uchar*
long2le(uchar * t,long from)1237*3de6a9c0SDavid du Colombier long2le(uchar *t, long from)
1238*3de6a9c0SDavid du Colombier {
1239*3de6a9c0SDavid du Colombier uchar *f, *o;
1240*3de6a9c0SDavid du Colombier int i;
1241*3de6a9c0SDavid du Colombier
1242*3de6a9c0SDavid du Colombier f = (uchar*)&from;
1243*3de6a9c0SDavid du Colombier o = (uchar*)ℴ
1244*3de6a9c0SDavid du Colombier for(i = 0; i < sizeof(long); i++)
1245*3de6a9c0SDavid du Colombier t[i] = f[o[i]];
1246*3de6a9c0SDavid du Colombier return t+sizeof(long);
1247*3de6a9c0SDavid du Colombier }
1248*3de6a9c0SDavid du Colombier
1249*3de6a9c0SDavid du Colombier char *Ebadtimectl = "bad time control";
1250*3de6a9c0SDavid du Colombier
1251*3de6a9c0SDavid du Colombier /*
1252*3de6a9c0SDavid du Colombier * like the old #c/time but with added info. Return
1253*3de6a9c0SDavid du Colombier *
1254*3de6a9c0SDavid du Colombier * secs nanosecs fastticks fasthz
1255*3de6a9c0SDavid du Colombier */
1256*3de6a9c0SDavid du Colombier static int
readtime(ulong off,char * buf,int n)1257*3de6a9c0SDavid du Colombier readtime(ulong off, char *buf, int n)
1258*3de6a9c0SDavid du Colombier {
1259*3de6a9c0SDavid du Colombier vlong nsec, ticks;
1260*3de6a9c0SDavid du Colombier long sec;
1261*3de6a9c0SDavid du Colombier char str[7*NUMSIZE];
1262*3de6a9c0SDavid du Colombier
1263*3de6a9c0SDavid du Colombier nsec = todget(&ticks);
1264*3de6a9c0SDavid du Colombier if(fasthz == 0LL)
1265*3de6a9c0SDavid du Colombier fastticks((uvlong*)&fasthz);
1266*3de6a9c0SDavid du Colombier sec = nsec/1000000000ULL;
1267*3de6a9c0SDavid du Colombier snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
1268*3de6a9c0SDavid du Colombier NUMSIZE-1, sec,
1269*3de6a9c0SDavid du Colombier VLNUMSIZE-1, nsec,
1270*3de6a9c0SDavid du Colombier VLNUMSIZE-1, ticks,
1271*3de6a9c0SDavid du Colombier VLNUMSIZE-1, fasthz);
1272*3de6a9c0SDavid du Colombier return readstr(off, buf, n, str);
1273*3de6a9c0SDavid du Colombier }
1274*3de6a9c0SDavid du Colombier
1275*3de6a9c0SDavid du Colombier /*
1276*3de6a9c0SDavid du Colombier * set the time in seconds
1277*3de6a9c0SDavid du Colombier */
1278*3de6a9c0SDavid du Colombier static int
writetime(char * buf,int n)1279*3de6a9c0SDavid du Colombier writetime(char *buf, int n)
1280*3de6a9c0SDavid du Colombier {
1281*3de6a9c0SDavid du Colombier char b[13];
1282*3de6a9c0SDavid du Colombier long i;
1283*3de6a9c0SDavid du Colombier vlong now;
1284*3de6a9c0SDavid du Colombier
1285*3de6a9c0SDavid du Colombier if(n >= sizeof(b))
1286*3de6a9c0SDavid du Colombier error(Ebadtimectl);
1287*3de6a9c0SDavid du Colombier strncpy(b, buf, n);
1288*3de6a9c0SDavid du Colombier b[n] = 0;
1289*3de6a9c0SDavid du Colombier i = strtol(b, 0, 0);
1290*3de6a9c0SDavid du Colombier if(i <= 0)
1291*3de6a9c0SDavid du Colombier error(Ebadtimectl);
1292*3de6a9c0SDavid du Colombier now = i*1000000000LL;
1293*3de6a9c0SDavid du Colombier todset(now, 0, 0);
1294*3de6a9c0SDavid du Colombier return n;
1295*3de6a9c0SDavid du Colombier }
1296*3de6a9c0SDavid du Colombier
1297*3de6a9c0SDavid du Colombier /*
1298*3de6a9c0SDavid du Colombier * read binary time info. all numbers are little endian.
1299*3de6a9c0SDavid du Colombier * ticks and nsec are syncronized.
1300*3de6a9c0SDavid du Colombier */
1301*3de6a9c0SDavid du Colombier static int
readbintime(char * buf,int n)1302*3de6a9c0SDavid du Colombier readbintime(char *buf, int n)
1303*3de6a9c0SDavid du Colombier {
1304*3de6a9c0SDavid du Colombier int i;
1305*3de6a9c0SDavid du Colombier vlong nsec, ticks;
1306*3de6a9c0SDavid du Colombier uchar *b = (uchar*)buf;
1307*3de6a9c0SDavid du Colombier
1308*3de6a9c0SDavid du Colombier i = 0;
1309*3de6a9c0SDavid du Colombier if(fasthz == 0LL)
1310*3de6a9c0SDavid du Colombier fastticks((uvlong*)&fasthz);
1311*3de6a9c0SDavid du Colombier nsec = todget(&ticks);
1312*3de6a9c0SDavid du Colombier if(n >= 3*sizeof(uvlong)){
1313*3de6a9c0SDavid du Colombier vlong2le(b+2*sizeof(uvlong), fasthz);
1314*3de6a9c0SDavid du Colombier i += sizeof(uvlong);
1315*3de6a9c0SDavid du Colombier }
1316*3de6a9c0SDavid du Colombier if(n >= 2*sizeof(uvlong)){
1317*3de6a9c0SDavid du Colombier vlong2le(b+sizeof(uvlong), ticks);
1318*3de6a9c0SDavid du Colombier i += sizeof(uvlong);
1319*3de6a9c0SDavid du Colombier }
1320*3de6a9c0SDavid du Colombier if(n >= 8){
1321*3de6a9c0SDavid du Colombier vlong2le(b, nsec);
1322*3de6a9c0SDavid du Colombier i += sizeof(vlong);
1323*3de6a9c0SDavid du Colombier }
1324*3de6a9c0SDavid du Colombier return i;
1325*3de6a9c0SDavid du Colombier }
1326*3de6a9c0SDavid du Colombier
1327*3de6a9c0SDavid du Colombier /*
1328*3de6a9c0SDavid du Colombier * set any of the following
1329*3de6a9c0SDavid du Colombier * - time in nsec
1330*3de6a9c0SDavid du Colombier * - nsec trim applied over some seconds
1331*3de6a9c0SDavid du Colombier * - clock frequency
1332*3de6a9c0SDavid du Colombier */
1333*3de6a9c0SDavid du Colombier static int
writebintime(char * buf,int n)1334*3de6a9c0SDavid du Colombier writebintime(char *buf, int n)
1335*3de6a9c0SDavid du Colombier {
1336*3de6a9c0SDavid du Colombier uchar *p;
1337*3de6a9c0SDavid du Colombier vlong delta;
1338*3de6a9c0SDavid du Colombier long period;
1339*3de6a9c0SDavid du Colombier
1340*3de6a9c0SDavid du Colombier n--;
1341*3de6a9c0SDavid du Colombier p = (uchar*)buf + 1;
1342*3de6a9c0SDavid du Colombier switch(*buf){
1343*3de6a9c0SDavid du Colombier case 'n':
1344*3de6a9c0SDavid du Colombier if(n < sizeof(vlong))
1345*3de6a9c0SDavid du Colombier error(Ebadtimectl);
1346*3de6a9c0SDavid du Colombier le2vlong(&delta, p);
1347*3de6a9c0SDavid du Colombier todset(delta, 0, 0);
1348*3de6a9c0SDavid du Colombier break;
1349*3de6a9c0SDavid du Colombier case 'd':
1350*3de6a9c0SDavid du Colombier if(n < sizeof(vlong)+sizeof(long))
1351*3de6a9c0SDavid du Colombier error(Ebadtimectl);
1352*3de6a9c0SDavid du Colombier p = le2vlong(&delta, p);
1353*3de6a9c0SDavid du Colombier le2long(&period, p);
1354*3de6a9c0SDavid du Colombier todset(-1, delta, period);
1355*3de6a9c0SDavid du Colombier break;
1356*3de6a9c0SDavid du Colombier case 'f':
1357*3de6a9c0SDavid du Colombier if(n < sizeof(uvlong))
1358*3de6a9c0SDavid du Colombier error(Ebadtimectl);
1359*3de6a9c0SDavid du Colombier le2vlong(&fasthz, p);
1360*3de6a9c0SDavid du Colombier if(fasthz <= 0)
1361*3de6a9c0SDavid du Colombier error(Ebadtimectl);
1362*3de6a9c0SDavid du Colombier todsetfreq(fasthz);
1363*3de6a9c0SDavid du Colombier break;
1364*3de6a9c0SDavid du Colombier }
1365*3de6a9c0SDavid du Colombier return n;
1366*3de6a9c0SDavid du Colombier }
1367