|
|
1.1 root 1: /* ttyold.c 4.1 11/9/80 */
2:
3: /*
4: * general TTY subroutines
5: */
6: #include "../h/param.h"
7: #include "../h/systm.h"
8: #include "../h/dir.h"
9: #include "../h/user.h"
10: #include "../h/tty.h"
11: #include "../h/proc.h"
12: #include "../h/mx.h"
13: #include "../h/inode.h"
14: #include "../h/file.h"
15: #include "../h/reg.h"
16: #include "../h/conf.h"
17: #include "../h/buf.h"
18: #include "../h/dk.h"
19:
20: char partab[];
21:
22: /*
23: * When running dz's using only SAE (silo alarm) on input
24: * it is necessary to call dzrint() at clock interrupt time.
25: * This is unsafe unless spl5()s in tty code are changed to
26: * spl6()s to block clock interrupts. Note that the dh driver
27: * currently in use works the same way as the dz, even though
28: * we could try to more intelligently manage its silo.
29: * Thus don't take this out if you have no dz's unless you
30: * change clock.c and dhtimer().
31: */
32: #define spl5 spl6
33:
34: /*
35: * Input mapping table-- if an entry is non-zero, when the
36: * corresponding character is typed preceded by "\" the escape
37: * sequence is replaced by the table value. Mostly used for
38: * upper-case only terminals.
39: */
40: char maptab[];
41:
42: #define OBUFSIZ 100
43:
44: /*
45: * routine called on first teletype open.
46: * establishes a process group for distribution
47: * of quits and interrupts from the tty.
48: */
49: ttyopen(dev, tp)
50: dev_t dev;
51: register struct tty *tp;
52: {
53: register struct proc *pp;
54:
55: pp = u.u_procp;
56: tp->t_dev = dev;
57: if(pp->p_pgrp == 0) {
58: u.u_ttyp = tp;
59: u.u_ttyd = dev;
60: if (tp->t_pgrp == 0)
61: tp->t_pgrp = pp->p_pid;
62: pp->p_pgrp = tp->t_pgrp;
63: }
64: tp->t_state &= ~WOPEN;
65: tp->t_state |= ISOPEN;
66: tp->t_line = 0; /* conservative */
67: }
68:
69: /*
70: * clean tp on last close
71: */
72: ttyclose(tp)
73: register struct tty *tp;
74: {
75:
76: tp->t_pgrp = 0;
77: wflushtty(tp);
78: tp->t_state = 0;
79: tp->t_line = 0;
80: }
81:
82: /*
83: * transfer raw input list to canonical list,
84: * doing erase-kill processing and handling escapes.
85: * It waits until a full line has been typed in cooked mode,
86: * or until any character has been typed in raw mode.
87: */
88: canon(tp)
89: register struct tty *tp;
90: {
91: register char *bp;
92: char *bp1;
93: register int c;
94: int mc;
95: int s;
96:
97: if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0
98: || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) {
99: return(-1);
100: }
101: s = spl0();
102: loop:
103: bp = &canonb[2];
104: while ((c=getc(&tp->t_rawq)) >= 0) {
105: if ((tp->t_flags&(RAW|CBREAK))==0) {
106: if (c==0377) {
107: tp->t_delct--;
108: break;
109: }
110: if (bp[-1]!='\\') {
111: if (c==tp->t_erase) {
112: if (bp > &canonb[2])
113: bp--;
114: continue;
115: }
116: if (c==tp->t_kill)
117: goto loop;
118: if (c==tun.t_eofc)
119: continue;
120: } else {
121: mc = maptab[c];
122: if (c==tp->t_erase || c==tp->t_kill)
123: mc = c;
124: if (mc && (mc==c || (tp->t_flags&LCASE))) {
125: if (bp[-2] != '\\')
126: c = mc;
127: bp--;
128: }
129: }
130: }
131: *bp++ = c;
132: if (bp>=canonb+CANBSIZ)
133: break;
134: }
135: bp1 = &canonb[2];
136: (void) b_to_q(bp1, bp-bp1, &tp->t_canq);
137:
138: if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
139: if (putc(tun.t_startc, &tp->t_outq)==0) {
140: tp->t_state &= ~TBLOCK;
141: ttstart(tp);
142: }
143: tp->t_char = 0;
144: }
145:
146: splx(s);
147: return(0);
148: }
149:
150:
151: /*
152: * block transfer input handler.
153: */
154: ttyrend(tp, pb, pe)
155: register struct tty *tp;
156: register char *pb, *pe;
157: {
158: int tandem;
159:
160: tandem = tp->t_flags&TANDEM;
161: if (tp->t_flags&RAW) {
162: (void) b_to_q(pb, pe-pb, &tp->t_rawq);
163: if (tp->t_chan)
164: (void) sdata(tp->t_chan); else
165: wakeup((caddr_t)&tp->t_rawq);
166: } else {
167: tp->t_flags &= ~TANDEM;
168: while (pb < pe)
169: ttyinput(*pb++, tp);
170: tp->t_flags |= tandem;
171: }
172: if (tandem)
173: ttyblock(tp);
174: }
175:
176: /*
177: * Place a character on raw TTY input queue, putting in delimiters
178: * and waking up top half as needed.
179: * Also echo if required.
180: * The arguments are the character and the appropriate
181: * tty structure.
182: */
183: ttyinput(c, tp)
184: register c;
185: register struct tty *tp;
186: {
187: register int t_flags;
188: register struct chan *cp;
189:
190: tk_nin += 1;
191: c &= 0377;
192: t_flags = tp->t_flags;
193: if (t_flags&TANDEM)
194: ttyblock(tp);
195: if ((t_flags&RAW)==0) {
196: c &= 0177;
197: if (tp->t_state&TTSTOP) {
198: if (c==tun.t_startc) {
199: tp->t_state &= ~TTSTOP;
200: ttstart(tp);
201: return;
202: }
203: if (c==tun.t_stopc)
204: return;
205: tp->t_state &= ~TTSTOP;
206: ttstart(tp);
207: } else {
208: if (c==tun.t_stopc) {
209: tp->t_state |= TTSTOP;
210: (*cdevsw[major(tp->t_dev)].d_stop)(tp);
211: return;
212: }
213: if (c==tun.t_startc)
214: return;
215: }
216: if (c==tun.t_quitc || c==tun.t_intrc) {
217: flushtty(tp, FREAD|FWRITE);
218: c = (c==tun.t_intrc) ? SIGINT:SIGQUIT;
219: if (tp->t_chan)
220: scontrol(tp->t_chan, M_SIG, c);
221: else
222: gsignal(tp->t_pgrp, c);
223: return;
224: }
225: if (c=='\r' && t_flags&CRMOD)
226: c = '\n';
227: }
228: if (tp->t_rawq.c_cc>TTYHOG) {
229: flushtty(tp, FREAD|FWRITE);
230: return;
231: }
232: if (t_flags&LCASE && c>='A' && c<='Z')
233: c += 'a'-'A';
234: (void) putc(c, &tp->t_rawq);
235: if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
236: if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
237: tp->t_delct++;
238: if ((cp=tp->t_chan)!=NULL)
239: (void) sdata(cp); else
240: wakeup((caddr_t)&tp->t_rawq);
241: }
242: if (t_flags&ECHO) {
243: ttyoutput(c, tp);
244: if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0)
245: ttyoutput('\n', tp);
246: ttstart(tp);
247: }
248: }
249:
250: /*
251: * put character on TTY output queue, adding delays,
252: * expanding tabs, and handling the CR/NL bit.
253: * It is called both from the top half for output, and from
254: * interrupt level for echoing.
255: * The arguments are the character and the tty structure.
256: */
257: ttyoutput(c, tp)
258: register c;
259: register struct tty *tp;
260: {
261: register char *colp;
262: register ctype;
263:
264: /*
265: * Ignore EOT in normal mode to avoid hanging up
266: * certain terminals.
267: * In raw mode dump the char unchanged.
268: */
269: if ((tp->t_flags&RAW)==0) {
270: c &= 0177;
271: if ((tp->t_flags&CBREAK)==0 && c==CEOT)
272: return;
273: } else {
274: tk_nout++;
275: (void) putc(c, &tp->t_outq);
276: return;
277: }
278:
279: /*
280: * Turn tabs to spaces as required
281: */
282: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
283: c = 8 - (tp->t_col & 7);
284: (void) b_to_q(" ", c, &tp->t_outq);
285: tp->t_col += c;
286: tk_nout += c;
287: return;
288: }
289: tk_nout++;
290: /*
291: * for upper-case-only terminals,
292: * generate escapes.
293: */
294: if (tp->t_flags&LCASE) {
295: colp = "({)}!|^~'`";
296: while(*colp++)
297: if(c == *colp++) {
298: ttyoutput('\\', tp);
299: c = colp[-2];
300: break;
301: }
302: if ('a'<=c && c<='z')
303: c += 'A' - 'a';
304: }
305: /*
306: * turn <nl> to <cr><lf> if desired.
307: */
308: if (c=='\n' && tp->t_flags&CRMOD)
309: ttyoutput('\r', tp);
310: (void) putc(c, &tp->t_outq);
311: /*
312: * Calculate delays.
313: * The numbers here represent clock ticks
314: * and are not necessarily optimal for all terminals.
315: * The delays are indicated by characters above 0200.
316: * In raw mode there are no delays and the
317: * transmission path is 8 bits wide.
318: */
319: colp = &tp->t_col;
320: ctype = partab[c];
321: c = 0;
322: switch (ctype&077) {
323:
324: /* ordinary */
325: case 0:
326: (*colp)++;
327:
328: /* non-printing */
329: case 1:
330: break;
331:
332: /* backspace */
333: case 2:
334: if (*colp)
335: (*colp)--;
336: break;
337:
338: /* newline */
339: case 3:
340: ctype = (tp->t_flags >> 8) & 03;
341: if(ctype == 1) { /* tty 37 */
342: if (*colp)
343: c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
344: } else
345: if(ctype == 2) { /* vt05 */
346: c = 6;
347: }
348: *colp = 0;
349: break;
350:
351: /* tab */
352: case 4:
353: ctype = (tp->t_flags >> 10) & 03;
354: if(ctype == 1) { /* tty 37 */
355: c = 1 - (*colp | ~07);
356: if(c < 5)
357: c = 0;
358: }
359: *colp |= 07;
360: (*colp)++;
361: break;
362:
363: /* vertical motion */
364: case 5:
365: if(tp->t_flags & VTDELAY) /* tty 37 */
366: c = 0177;
367: break;
368:
369: /* carriage return */
370: case 6:
371: ctype = (tp->t_flags >> 12) & 03;
372: if(ctype == 1) { /* tn 300 */
373: c = 5;
374: } else if(ctype == 2) { /* ti 700 */
375: c = 10;
376: } else if(ctype == 3) { /* concept 100 */
377: int i;
378: if ((i = *colp) >= 0)
379: for (; i<9; i++)
380: (void) putc(0177, &tp->t_outq);
381: }
382: *colp = 0;
383: }
384: if(c)
385: (void) putc(c|0200, &tp->t_outq);
386: }
387:
388: /*
389: * Called from device's read routine after it has
390: * calculated the tty-structure given as argument.
391: */
392: ttread(tp)
393: register struct tty *tp;
394: {
395: register s;
396:
397: if ((tp->t_state&CARR_ON)==0)
398: return(-1);
399: s = spl5();
400: if (tp->t_canq.c_cc==0)
401: while (canon(tp)<0)
402: if (tp->t_chan==NULL) {
403: sleep((caddr_t)&tp->t_rawq, TTIPRI);
404: } else {
405: splx(s);
406: return(0);
407: }
408: splx(s);
409: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0)
410: ;
411: return(tp->t_rawq.c_cc+tp->t_canq.c_cc);
412: }
413:
414: /*
415: * Called from the device's write routine after it has
416: * calculated the tty-structure given as argument.
417: */
418: caddr_t
419: ttwrite(tp)
420: register struct tty *tp;
421: {
422: /*
423: * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
424: * AND MUST NOT BE CHANGED WITHOUT PATCHING
425: * THE 'ASM' INLINES BELOW. WATCH OUT.
426: */
427: register char *cp;
428: register int cc, ce;
429: register i;
430: char obuf[OBUFSIZ];
431: int hiwat = TTHIWAT(tp);
432:
433: if ((tp->t_state&CARR_ON)==0)
434: return(NULL);
435: while (u.u_count) {
436: cc = MIN(u.u_count, OBUFSIZ);
437: cp = obuf;
438: iomove(cp, (unsigned)cc, B_WRITE);
439: if (u.u_error)
440: break;
441: (void) spl5();
442: while (tp->t_outq.c_cc > hiwat) {
443: ttstart(tp);
444: tp->t_state |= ASLEEP;
445: if (tp->t_chan) {
446: u.u_base -= cc;
447: u.u_offset -= cc;
448: u.u_count += cc;
449: (void) spl0();
450: return((caddr_t)&tp->t_outq);
451: }
452: sleep((caddr_t)&tp->t_outq, TTOPRI);
453: }
454: (void) spl0();
455: if (tp->t_flags&LCASE) {
456: while (cc--)
457: ttyoutput(*cp++,tp);
458: continue;
459: }
460: while (cc) {
461: if (tp->t_flags&RAW)
462: ce=cc;
463: else {
464: #ifdef VAX
465: asm(" scanc r9,(r10),_partab,$077");
466: asm(" subl3 r0,r9,r8");
467: #else
468: ce=0;
469: while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
470: ce++;
471: #endif
472: if (ce==0) {
473: ttyoutput(*cp++,tp);
474: cc--;
475: goto check;
476: }
477: }
478: i=b_to_q(cp,ce,&tp->t_outq);
479: ce-=i;
480: tk_nout+=ce;
481: tp->t_col+=ce;
482: cp+=ce;
483: cc-=ce;
484: check:
485: if (tp->t_outq.c_cc > hiwat) {
486: (void) spl5();
487: while (tp->t_outq.c_cc > hiwat) {
488: ttstart(tp);
489: tp->t_state |= ASLEEP;
490: sleep((caddr_t)&tp->t_outq, TTOPRI);
491: }
492: (void) spl0();
493: }
494: }
495: }
496: ttstart(tp);
497: return(NULL);
498: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.