|
|
1.1 root 1: /* cons.c 7.5 90/01/17 */
2:
3: /*
4: * Tahoe console processor driver
5: *
6: * Minor device 0 is the CP itself.
7: * No real read/writes can be done to him.
8: * Minor 1 is the console terminal.
9: * Minor 2 is the remote line trminal.
10: */
11: #include "param.h"
12: #include "conf.h"
13: #include "ioctl.h"
14: #include "user.h"
15: #include "proc.h"
16: #include "tty.h"
17: #include "callout.h"
18: #include "systm.h"
19: #include "kernel.h"
20: #include "syslog.h"
21:
22: #include "../tahoe/cp.h"
23: #include "../tahoe/cpu.h"
24: #include "../tahoe/mtpr.h"
25:
26: int cnrestart();
27: int timeout();
28:
29: struct tty CPtty;
30: struct tty cons;
31: struct tty RLtty;
32: struct tty *cntty[3] = { &CPtty, &cons, &RLtty };
33:
34: struct tty *constty = 0; /* virtual console */
35:
36: struct consoftc {
37: char cs_flags;
38: #define CSF_ACTIVE 0x1 /* timeout active */
39: #define CSF_POLLING 0x2 /* polling for input */
40: char cs_lastc; /* last char sent */
41: int cs_timo; /* timeouts since interrupt */
42: u_long cs_wedgecnt; /* times restarted */
43: } consoftc[3];
44:
45: struct speedtab cnspeedtab[] = {
46: 9600, 13,
47: 4800, 12,
48: 2400, 11,
49: 1800, 10,
50: 1200, 9,
51: 600, 8,
52: 300, 7,
53: 200, 6,
54: 150, 5,
55: 134, 4,
56: 110, 3,
57: 75, 2,
58: 50, 1,
59: 0, 13,
60: -1, -1,
61: };
62:
63: /*
64: * We check the console periodically to make sure
65: * that it hasn't wedged. Unfortunately, if an XOFF
66: * is typed on the console, that can't be distinguished
67: * from more catastrophic failure.
68: */
69: #define CN_TIMERVAL (hz) /* frequency at which to check cons */
70: #define CN_TIMO (2*60) /* intervals to allow for output char */
71:
72: struct cpdcb_o consout[3] = {
73: { CPTAKE|CPDONE }, { CPTAKE|CPDONE }, { CPTAKE|CPDONE }
74: };
75: struct cpdcb_i consin[3] = {
76: { CPTAKE|CPDONE }, { CPTAKE|CPDONE }, { CPTAKE|CPDONE }
77: };
78: struct cphdr *cnlast;
79:
80: int cnstart();
81: int ttrstrt();
82: char partab[];
83:
84: /*
85: * Wait for CP to accept last CP command sent
86: * before setting up next command.
87: */
88: #define waitforlast(timo) { \
89: if (cnlast) { \
90: (timo) = 10000; \
91: do \
92: uncache((char *)&cnlast->cp_unit); \
93: while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \
94: } \
95: }
96:
97: /*ARGSUSED*/
98: cnopen(dev, flag)
99: dev_t dev;
100: {
101: register struct tty *tp;
102: int unit = minor(dev);
103: int cnparams();
104:
105: if (unit > CPREMOT)
106: return (ENXIO);
107: tp = cntty[unit];
108: if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
109: return (EBUSY);
110: cnpostread(unit); /* post request for input */
111: tp->t_oproc = cnstart;
112: tp->t_param = cnparams;
113: tp->t_dev = dev;
114: if ((tp->t_state&TS_ISOPEN) == 0) {
115: ttychars(tp);
116: tp->t_iflag = TTYDEF_IFLAG|ICRNL;
117: tp->t_oflag = TTYDEF_OFLAG|OPOST|ONLCR;
118: tp->t_lflag = TTYDEF_LFLAG;
119: tp->t_cflag = CS8|CREAD;
120: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
121: tp->t_state = TS_ISOPEN|TS_CARR_ON;
122: cnparams(tp, &tp->t_termios);
123: ttsetwater(tp);
124: }
125: return ((*linesw[tp->t_line].l_open)(dev, tp));
126: }
127:
128: cnpostread(unit)
129: int unit;
130: {
131: register struct cpdcb_i *cin;
132: register int timo;
133:
134: waitforlast(timo);
135: cin = &consin[unit];
136: cin->cp_hdr.cp_unit = unit;
137: cin->cp_hdr.cp_comm = CPREAD;
138: cin->cp_hdr.cp_count = 1; /* Get ready for input */
139: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)cin));
140: cnlast = &cin->cp_hdr;
141: }
142:
143: cnclose(dev)
144: dev_t dev;
145: {
146: register struct tty *tp = cntty[minor(dev)];
147:
148: (*linesw[tp->t_line].l_close)(tp);
149: ttyclose(tp);
150: }
151:
152: /*ARGSUSED*/
153: cnread(dev, uio, flag)
154: dev_t dev;
155: struct uio *uio;
156: {
157: struct tty *tp = cntty[minor(dev)];
158:
159: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
160: }
161:
162: /*ARGSUSED*/
163: cnwrite(dev, uio, flag)
164: dev_t dev;
165: struct uio *uio;
166: {
167: register struct tty *tp = cntty[minor(dev)];
168:
169: if (tp == &cons && constty &&
170: (constty->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
171: (TS_CARR_ON | TS_ISOPEN))
172: tp = constty;
173: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
174: }
175:
176: /*
177: * Got a console receive interrupt -
178: * the console processor wants to give us a character.
179: * Catch the character, and see who it goes to.
180: */
181: cnrint(dev)
182: dev_t dev;
183: {
184: register int unit, timo;
185: register struct tty *tp;
186: int c;
187:
188: unit = minor(dev);
189: if (!intenable || consoftc[unit].cs_flags&CSF_POLLING)
190: return;
191: /* make sure we dont take it from cache */
192: uncache(&consin[unit].cpi_buf[0]);
193: c = consin[unit].cpi_buf[0];
194: waitforlast(timo);
195: /* This resets status bits */
196: consin[unit].cp_hdr.cp_unit = unit;
197: /* Ready for new character */
198: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&consin[unit]));
199: cnlast = &consin[unit].cp_hdr;
200:
201: tp = cntty[unit];
202: if ((tp->t_cflag&CSIZE) != CS8)
203: c &= 0177;
204: #ifdef KADB
205: if (unit == CPCONS && kdbrintr(c, tp))
206: return;
207: #endif
208: (*linesw[tp->t_line].l_rint)(c & 0377, tp);
209: }
210:
211: cnioctl(dev, cmd, addr, flag)
212: dev_t dev;
213: caddr_t addr;
214: {
215: register struct tty *tp = cntty[minor(dev)];
216: register error;
217:
218: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
219: if (error >= 0)
220: return error;
221: if ((error = ttioctl(tp, cmd, addr, flag)) < 0)
222: error = ENOTTY;
223: return (error);
224: }
225:
226: int consintr = 1;
227: /*
228: * Got a console transmission interrupt -
229: * the console processor wants another character.
230: */
231: cnxint(dev)
232: dev_t dev;
233: {
234: register struct tty *tp;
235: register int unit;
236:
237: if (!intenable || !consintr)
238: return;
239: unit = minor(dev);
240: #ifdef CPPERF
241: scope_in(unit == CPCONS ? 1 : 2);
242: #endif
243: tp = cntty[unit];
244: tp->t_state &= ~TS_BUSY;
245: consoftc[unit].cs_timo = 0;
246: if (tp->t_line)
247: (*linesw[tp->t_line].l_start)(tp);
248: else
249: cnstart(tp);
250: }
251:
252: cnstart(tp)
253: register struct tty *tp;
254: {
255: register c, s;
256:
257: #ifdef CPPERF
258: scope_in(minor(tp->t_dev) == CPCONS ? 3 : 4);
259: #endif
260: s = spl8();
261: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
262: goto out;
263: if (tp->t_outq.c_cc <= tp->t_lowat) {
264: if (tp->t_state&TS_ASLEEP) {
265: tp->t_state &= ~TS_ASLEEP;
266: wakeup((caddr_t)&tp->t_outq);
267: }
268: if (tp->t_wsel) {
269: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
270: tp->t_wsel = 0;
271: tp->t_state &= ~TS_WCOLL;
272: }
273: }
274: if (tp->t_outq.c_cc == 0)
275: goto out;
276: c = getc(&tp->t_outq) & 0xff;
277: if (tp->t_cflag&PARENB && ((tp->t_cflag&CSIZE)==CS7)) {
278: c &= 0177;
279: c |= (tp->t_cflag&PARODD ? ~partab[c] : partab[c]) & 0200;
280: }
281: cnputchar(c, tp);
282: tp->t_state |= TS_BUSY;
283: out:
284: splx(s);
285: }
286:
287: cnputc(c)
288: char c;
289: {
290:
291: if (c == '\n')
292: cnputchar('\r', (struct tty *)0);
293: cnputchar(c, (struct tty *)0);
294: }
295:
296: /*
297: * Print a character on console.
298: */
299: cnputchar(c, tp)
300: char c;
301: register struct tty *tp;
302: {
303: register timo;
304: register struct cpdcb_o *current;
305: register struct consoftc *cs;
306: int unit;
307:
308: /* tp == 0 only in system error messages */
309: if (tp == 0) {
310: tp = &cons;
311: tp->t_dev = CPCONS; /* may not be open */
312: c |= partab[c&0177]&0200;
313: }
314: unit = minor(tp->t_dev);
315: current = &consout[unit];
316: timo = 30000;
317: /*
318: * Try waiting for the console tty to finish previous command
319: * on this unit, otherwise give up after a reasonable time.
320: */
321: do
322: uncache(¤t->cp_hdr.cp_unit);
323: while ((current->cp_hdr.cp_unit&CPDONE) == 0 && --timo);
324:
325: current->cp_hdr.cp_comm = CPWRITE;
326: current->cp_hdr.cp_count = 1;
327: current->cp_buf[0] = c;
328: /*
329: * Try waiting for the console tty
330: * to accept previous command.
331: */
332: waitforlast(timo);
333:
334: /* Reset done bit */
335: current->cp_hdr.cp_unit = (char)unit;
336: #ifdef CPPERF
337: if (intenable != 0)
338: scope_in(5);
339: #endif
340: cs = &consoftc[unit];
341: cs->cs_lastc = c;
342: cs->cs_timo = CN_TIMO;
343: if ((cs->cs_flags&CSF_ACTIVE) == 0 && clk_enable) {
344: cs->cs_flags |= CSF_ACTIVE;
345: timeout(cnrestart, (caddr_t)tp, CN_TIMERVAL);
346: }
347: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
348: cnlast = ¤t->cp_hdr;
349: }
350:
351: #if defined(KADB) || defined(GENERIC)
352: cngetc()
353: {
354: register int c, s;
355:
356: s = spl8(); /* block cnrint while we poll */
357: c = cngetchar(&cons);
358: if (c == '\r')
359: c = '\n';
360: splx(s);
361: return (c);
362: }
363:
364: cngetchar(tp)
365: register struct tty *tp;
366: {
367: register timo, unit;
368: register struct cpdcb_i *current;
369: char c;
370:
371: unit = minor(tp->t_dev);
372: current = &consin[unit];
373: waitforlast(timo);
374: current->cp_hdr.cp_unit = unit; /* Resets done bit */
375: current->cp_hdr.cp_comm = CPREAD;
376: current->cp_hdr.cp_count = 1;
377: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
378: while ((current->cp_hdr.cp_unit&CPDONE) == 0)
379: uncache(¤t->cp_hdr.cp_unit);
380: uncache(¤t->cpi_buf[0]);
381: c = current->cpi_buf[0] & 0x7f;
382: cnlast = ¤t->cp_hdr;
383: return (c);
384: }
385: #endif
386:
387: /*
388: * Restart (if necessary) transfer to CP line.
389: * This way, lost transmit interrupts don't wedge output.
390: */
391: cnrestart(tp)
392: struct tty *tp;
393: {
394: register struct consoftc *cs;
395:
396: cs = &consoftc[minor(tp->t_dev)];
397: cs->cs_flags &= ~CSF_ACTIVE;
398: if (cs->cs_timo) {
399: if (--cs->cs_timo == 0) {
400: cs->cs_wedgecnt++;
401: cnreset(tp);
402: cnputchar(cs->cs_lastc, tp);
403: } else {
404: cs->cs_flags |= CSF_ACTIVE;
405: timeout(cnrestart, (caddr_t)tp, CN_TIMERVAL);
406: }
407: }
408: }
409:
410: /*
411: * Reset console.
412: */
413: cnreset(tp)
414: register struct tty *tp;
415: {
416: register timo;
417: register struct cpdcb_o *current;
418: register unit;
419: static int failed;
420:
421: unit = minor(tp->t_dev);
422: current = &consout[unit];
423: current->cp_hdr.cp_comm = CPRESET;
424: current->cp_hdr.cp_count = 0;
425: current->cp_hdr.cp_unit = unit;
426: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
427: cnlast = ¤t->cp_hdr;
428: timo = 10000;
429: do
430: uncache(¤t->cp_hdr.cp_unit);
431: while ((current->cp_hdr.cp_unit&CPTAKE) == 0 && --timo);
432: if (current->cp_hdr.cp_unit & CPTAKE) {
433: cnparams(tp, &tp->t_termios);
434: failed = 0;
435: } else if (failed++ == 0)
436: log(LOG_ERR, "Console wedged, reset failed.\n");
437: }
438:
439: /*
440: * Set line parameters
441: */
442: cnparams(tp, t)
443: register struct tty *tp;
444: register struct termios *t;
445: {
446: register timo = 30000;
447: int unit = minor(tp->t_dev);
448: register struct cpdcb_o *current = &consout[unit];
449: register cflag = t->c_cflag;
450: int speedcode, csize;
451:
452: if (((speedcode == ttspeedtab(t->c_ospeed, cnspeedtab)) < 0) ||
453: (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
454: ((csize = (cflag&CSIZE)) != CS7 && csize != CS8))
455: return (EINVAL);
456: /*XXX*/return (0);
457: /*
458: * Try waiting for the console tty to finish any output,
459: * otherwise give up after a reasonable time.
460: */
461: do
462: uncache(¤t->cp_hdr.cp_unit);
463: while ((current->cp_hdr.cp_unit&CPDONE) == 0 && --timo);
464: current->cp_hdr.cp_comm = CPSTTY;
465: current->cp_hdr.cp_count = 4;
466: current->cp_buf[0] = speedcode;
467: #ifdef notyet
468: /* parity */
469: current->cp_buf[1] = (cflag&PARENB) ? ((cflag&PARODD) ? 2 : 1) : 0;
470: /* stop bits */
471: current->cp_buf[2] = (cflag&CSTOPB) ? 2 : 0;
472: /* data bits */
473: current->cp_buf[3] = (csize==CS8) ? 8 : 7;
474: #else
475: current->cp_buf[1] = 0; /* no parity */
476: current->cp_buf[2] = 0; /* stop bits */
477: current->cp_buf[3] = 8; /* data bits */
478: #endif
479:
480: /* Reset done bit */
481: current->cp_hdr.cp_unit = unit;
482:
483: waitforlast(timo);
484: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
485: cnlast = ¤t->cp_hdr;
486: cnpostread(unit);
487: return (0);
488: }
489:
490: #ifdef KADB
491: /*
492: * Turn input polling on/off (used by debugger).
493: */
494: cnpoll(onoff)
495: int onoff;
496: {
497:
498: if (!onoff) {
499: consoftc[CPCONS].cs_flags &= ~CSF_POLLING;
500: cnpostread(CPCONS); /* restart input */
501: } else
502: consoftc[CPCONS].cs_flags |= CSF_POLLING;
503: }
504: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.