|
|
1.1 root 1: /* cons.c 4.10 81/05/09 */
2: /* Tahoe version Dec 1982 */
3: /* Minor device 0 is the CP itself.
4: /* No real read/writes can be done to him.
5: /* Minor 1 is the console terminal.
6: /* Minor 2 is the remote line trminal.
7: /**/
8:
9: /*
10: * Tahoe console processor driver
11: *
12: */
13: #include "../h/param.h"
14: #include "../h/conf.h"
15: #include "../h/dir.h"
16: #include "../h/ioctl.h"
17: #include "../h/user.h"
18: #include "../h/tty.h"
19: #include "../h/uio.h"
20: #include "../h/callout.h"
21: #include "../h/systm.h"
22: #include "../machine/cp.h"
23: #include "../machine/mtpr.h"
24:
25: #define FALSE 0
26: #define TRUE 1
27:
28: int cnrestart() ;
29: int timeout() ;
30:
31: struct tty cons[3]; /* One for each unit on CP */
32: struct cons_info {
33: char last_one; /* Last char sent - possibly repeat
34: * If zero, timeout has nothing to do
35: */
36: int active_timeout; /* There is an active timeout for this line
37: * Set by 'cnputc' when a timeout is initiated.
38: * Reset by the routine called at timeout.
39: */
40: int try_later; /* If true, timeout has nothing to do.
41: * Set by 'cnputc' every time a char is sent.
42: * Reset by the timeout arrival. If next time
43: * the timeout comes it's zero, then it may
44: * have something to do.
45: */
46: } cons_info[3];
47: struct cpdcb_o consout[3] = {
48: /* unit, cmd,count, buf */
49: {(char)(CPTAKE | CPDONE),0, 0 },
50: {(char)(CPTAKE | CPDONE),0, 0 },
51: {(char)(CPTAKE | CPDONE),0, 0 }
52: };
53: struct cpdcb_i consin[3] = {
54: /* unit, cmd,count, buf */
55: {(char)(CPTAKE | CPDONE),0, 0 },
56: {(char)(CPTAKE | CPDONE),0, 0 },
57: {(char)(CPTAKE | CPDONE),0, 0 }
58: };
59: struct cphdr *lasthdr;
60:
61: int cnstart();
62: int ttrstrt();
63: char partab[];
64:
65: cnopen(dev, flag)
66: dev_t dev;
67: {
68: register struct cpdcb_i *cin;
69: register struct tty *tp;
70: register int timo;
71:
72: if (minor(dev) > CPREMOT)
73: return EEXIST;
74: tp = &cons[minor(dev)];
75: if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
76: return EBUSY;
77: if (lasthdr != (struct cphdr *)0) {
78: timo = 10000;
79: uncache((char *)&lasthdr->cp_unit);
80: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo )
81: uncache((char *)&lasthdr->cp_unit);
82: } /* Here we give up waiting */
83: cin = &consin[minor(dev)];
84: cin->cp_hdr.cp_unit = (char)(minor(dev));
85: cin->cp_hdr.cp_comm = (char)CPREAD;
86: cin->cp_hdr.cp_count = 1; /* Get ready for input */
87: mtpr (cin, CPMDCB);
88: lasthdr = (struct cphdr *)cin;
89: tp->t_oproc = cnstart;
90: tp->t_dev = dev;
91: if ((tp->t_state&TS_ISOPEN) == 0) {
92: ttychars(tp);
93: tp->t_state = TS_ISOPEN|TS_CARR_ON;
94: tp->t_flags = EVENP|ECHO|XTABS|CRMOD;
95: }
96: (*linesw[tp->t_line].l_open)(dev, tp);
97: }
98:
99: cnclose(dev)
100: dev_t dev;
101: {
102: register struct tty *tp = &cons[minor(dev)];
103:
104: (*linesw[tp->t_line].l_close)(tp);
105: ttyclose(tp);
106: }
107:
108: /*ARGSUSED*/
109: cnread(dev, uio)
110: dev_t dev;
111: struct uio *uio;
112: {
113: register struct tty *tp = &cons[minor(dev)];
114:
115: return ((*linesw[tp->t_line].l_read)(tp, uio));
116: }
117:
118: /*ARGSUSED*/
119: cnwrite(dev, uio)
120: dev_t dev;
121: struct uio *uio;
122: {
123: register struct tty *tp = &cons[minor(dev)];
124:
125: return ((*linesw[tp->t_line].l_write)(tp, uio));
126: }
127:
128: /*
129: * Got a console receive interrupt -
130: * the console processor wants to give us a character.
131: * Catch the character, and see who it goes to.
132: */
133: cnrint(dev)
134: dev_t dev;
135: {
136: register int c, timo;
137: register struct tty *tp;
138:
139: if (intenable == 0) return;
140: /* make sure we dont take it from cache */
141: uncache((char *)&consin[minor(dev)].cpi_buf[0]);
142: c = consin[minor(dev)].cpi_buf[0];
143: /*
144: /* Wait about 5 milli for last CPMDCB to be read by CP,
145: /* otherwise give up
146: /**/
147: timo = 10000;
148: uncache((char *)&lasthdr->cp_unit);
149: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo )
150: uncache((char *)&lasthdr->cp_unit);
151: uncache((char *)&lasthdr->cp_unit);
152: if (lasthdr->cp_unit & CPTAKE)
153: {
154: consin[minor(dev)].cp_hdr.cp_unit = (char)(minor(dev));
155: /* This resets status bits */
156: mtpr (&consin[minor(dev)], CPMDCB); /* Ready for new character */
157: lasthdr = (struct cphdr *)&consin[minor(dev)];
158: tp = &cons[minor(dev)];
159: (*linesw[tp->t_line].l_rint)(c, tp);
160: }
161: }
162:
163: cnioctl(dev, cmd, addr, flag)
164: dev_t dev;
165: caddr_t addr;
166: {
167: register struct tty *tp = &cons[minor(dev)];
168: register error;
169:
170: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
171: if (error >= 0)
172: return error;
173: if ((error = ttioctl(tp, cmd, addr, flag)) < 0)
174: error = ENOTTY;
175: else if(cmd==TIOCSETP || cmd==TIOCSETN)
176: cnparams(tp);
177: return error;
178: }
179:
180: int consintr = 1;
181: /*
182: * Got a console transmission interrupt -
183: * the console processor wants another character.
184: */
185: cnxint(dev)
186: dev_t dev;
187: {
188: register struct tty *tp;
189: register int line_no;
190:
191: if (intenable == 0 || consintr == 0) return;
192: #ifdef CPPERF
193: if (minor(dev)==CPCONS) scope_in(1);
194: else scope_in(2);
195: #endif
196: line_no = minor(dev);
197: tp = &cons[line_no];
198: tp->t_state &= ~TS_BUSY;
199: cons_info[line_no].last_one = (char)0;
200: if (tp->t_line)
201: (*linesw[tp->t_line].l_start)(tp);
202: else
203: cnstart(tp);
204: }
205:
206: cnstart(tp)
207: register struct tty *tp;
208: {
209: register c;
210: register s;
211:
212: #ifdef CPPERF
213: if (minor(tp->t_dev)==CPCONS) scope_in(3);
214: else scope_in(4);
215: #endif
216: s = spl8();
217: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
218: goto out;
219: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
220: if (tp->t_state&TS_ASLEEP) {
221: tp->t_state &= ~TS_ASLEEP;
222: wakeup((caddr_t)&tp->t_outq);
223: }
224: if (tp->t_wsel) {
225: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
226: tp->t_wsel = 0;
227: tp->t_state &= ~TS_WCOLL;
228: }
229: }
230: if (tp->t_outq.c_cc == 0)
231: goto out;
232: c = getc(&tp->t_outq) & 0xff;
233: if (tp->t_flags&(RAW|LITOUT))
234: cnputc(c,tp);
235: else if (c<=0177)
236: cnputc ((c | (partab[c]&0200))&0xff,tp);
237: else {
238: timeout(ttrstrt, (caddr_t)tp, (c&0177));
239: tp->t_state |= TS_TIMEOUT;
240: goto out;
241: }
242: tp->t_state |= TS_BUSY;
243: out:
244: splx(s);
245: }
246:
247: /*
248: * Print a character on console.
249: */
250: cnputc(c,tp)
251: register char c;
252: register struct tty *tp;
253: {
254: register timo , line_no, s;
255: register struct cpdcb_o *current;
256:
257: /* tp == 0 only in system error messages */
258: if (tp == 0) {
259: current = &consout[CPCONS];
260: line_no = CPCONS;
261: if(lasthdr == 0) /* not done anythig yet */
262: lasthdr = (struct cphdr *)current;
263: c |= partab[c&0177]&0200;
264: }
265: else {
266: current = &consout[minor(tp->t_dev)];
267: line_no = minor(tp->t_dev);
268: }
269: timo = 30000;
270: /*
271: * Try waiting for the console tty to come ready,
272: * otherwise give up after a reasonable time.
273: * make sure we dont test this bit in cache!
274: */
275: uncache((char *)¤t->cp_hdr.cp_unit);
276: while ((current->cp_hdr.cp_unit & CPDONE) == 0 && --timo )
277: uncache((char *)¤t->cp_hdr.cp_unit);
278: current->cp_hdr.cp_comm = (char)CPWRITE;
279: current->cp_hdr.cp_count = 1;
280: current->cp_buf[0] = (char)(c & 0xff);
281: timo = 10000;
282: /*
283: * Try waiting for the console tty to come ready,
284: * otherwise give up after a reasonable time.
285: */
286: uncache((char *)&lasthdr->cp_unit);
287: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo )
288: uncache((char *)&lasthdr->cp_unit);
289: /* Reset done bit */
290: current->cp_hdr.cp_unit = (char)line_no;
291: lasthdr = (struct cphdr *)current;
292: #ifdef CPPERF
293: if (intenable != 0) scope_in(5);
294: #endif
295: cons_info[line_no].last_one = c;
296: if ( !cons_info[line_no].active_timeout && clk_enable) {
297: cons_info[line_no].active_timeout = TRUE;
298: timeout (cnrestart, (caddr_t)tp, 10);
299: }
300: cons_info[line_no].try_later = TRUE; /* For timeout-means wait some more */
301: mtpr (current, CPMDCB);
302: }
303:
304: /*
305: * Restart (if necessary) transfer to CP line.
306: * This way, lost 'transmit' interrupts don't break the chain.
307: */
308: cnrestart (tp)
309: struct tty *tp;
310: {
311: register line_no, s;
312:
313: if (tp == 0) {
314: line_no = CPCONS;
315: } else
316: line_no = minor(tp->t_dev);
317: if (cons_info[line_no].try_later) {
318: cons_info[line_no].try_later = FALSE;
319: timeout (cnrestart, (caddr_t)tp, 10);
320: }
321: else {
322: cons_info[line_no].active_timeout = FALSE;
323: if (cons_info[line_no].last_one != (char)0)
324: cnputc (cons_info[line_no].last_one, tp);
325: }
326: }
327:
328: /*
329: * Set line parameters
330: */
331: cnparams(tp)
332: register struct tty *tp;
333: {
334: register timo ;
335: register struct cpdcb_o *current;
336: register struct cpdcb_i *cin;
337:
338: current = &consout[minor(tp->t_dev)];
339: timo = 30000;
340: /*
341: * Try waiting for the console tty to come ready,
342: * otherwise give up after a reasonable time.
343: * make sure we dont test this bit in cache!
344: */
345: uncache((char *)¤t->cp_hdr.cp_unit);
346: while ((current->cp_hdr.cp_unit & CPDONE) == 0 && --timo )
347: uncache((char *)¤t->cp_hdr.cp_unit);
348: current->cp_hdr.cp_comm = (char)CPSTTY;
349: current->cp_hdr.cp_count = 4;
350: current->cp_buf[0] = tp->t_ispeed;
351: /* the rest are defaults */
352: current->cp_buf[1] = 0; /* no parity */
353: current->cp_buf[2] = 0; /* stop bits */
354: current->cp_buf[3] = 8; /* data bits */
355: timo = 10000;
356: /*
357: * Try waiting for the console tty to come ready,
358: * otherwise give up after a reasonable time.
359: */
360: uncache((char *)&lasthdr->cp_unit);
361: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo )
362: uncache((char *)&lasthdr->cp_unit);
363: /* Reset done bit */
364: current->cp_hdr.cp_unit = (char)minor(tp->t_dev);
365: lasthdr = (struct cphdr *)current;
366: mtpr (current, CPMDCB);
367:
368: timo = 10000;
369: uncache((char *)&lasthdr->cp_unit);
370: while ((lasthdr->cp_unit & CPTAKE)==0 && --timo )
371: uncache((char *)&lasthdr->cp_unit);
372: cin = &consin[minor(tp->t_dev)];
373: cin->cp_hdr.cp_unit = (char)(minor(tp->t_dev));
374: cin->cp_hdr.cp_comm = (char)CPREAD;
375: cin->cp_hdr.cp_count = 1; /* Get ready for input */
376: mtpr (cin, CPMDCB);
377: lasthdr = (struct cphdr *)cin;
378:
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.