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