counter in dz code
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
6fdc0335 1/* tty.c 3.6 %H% */
89dc6dfb
BJ
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
19char partab[];
20
d3ebf5ee
BJ
21/*
22 * When running dz's using only SAE (silo alarm) on input
23 * it is necessary to call dzrint() at clock interrupt time.
24 * This is unsafe unless spl5()s in tty code are changed to
25 * spl6()s to block clock interrupts. Note that the dh driver
26 * currently in use works the same way as the dz, even though
27 * we could try to more intelligently manage its silo.
28 * Thus don't take this out if you have no dz's unless you
29 * change clock.c and dhtimer().
30 */
31#define spl5 spl6
89dc6dfb
BJ
32
33/*
34 * Input mapping table-- if an entry is non-zero, when the
35 * corresponding character is typed preceded by "\" the escape
36 * sequence is replaced by the table value. Mostly used for
37 * upper-case only terminals.
38 */
39
40char maptab[] ={
41 000,000,000,000,000,000,000,000,
42 000,000,000,000,000,000,000,000,
43 000,000,000,000,000,000,000,000,
44 000,000,000,000,000,000,000,000,
45 000,'|',000,000,000,000,000,'`',
46 '{','}',000,000,000,000,000,000,
47 000,000,000,000,000,000,000,000,
48 000,000,000,000,000,000,000,000,
49 000,000,000,000,000,000,000,000,
50 000,000,000,000,000,000,000,000,
51 000,000,000,000,000,000,000,000,
52 000,000,000,000,000,000,'~',000,
53 000,'A','B','C','D','E','F','G',
54 'H','I','J','K','L','M','N','O',
55 'P','Q','R','S','T','U','V','W',
56 'X','Y','Z',000,000,000,000,000,
57};
58
59
60/*
61 * shorthand
62 */
63#define q1 tp->t_rawq
64#define q2 tp->t_canq
65#define q3 tp->t_outq
66#define q4 tp->t_un.t_ctlq
67
68#define OBUFSIZ 100
69
70/*
71 * routine called on first teletype open.
72 * establishes a process group for distribution
73 * of quits and interrupts from the tty.
74 */
75ttyopen(dev, tp)
76dev_t dev;
77register struct tty *tp;
78{
79 register struct proc *pp;
80
81 pp = u.u_procp;
82 tp->t_dev = dev;
83 if(pp->p_pgrp == 0) {
84 u.u_ttyp = tp;
85 u.u_ttyd = dev;
6fdc0335
BJ
86 if (tp->t_pgrp == 0)
87 tp->t_pgrp = pp->p_pid;
89dc6dfb
BJ
88 pp->p_pgrp = tp->t_pgrp;
89 }
90 tp->t_state &= ~WOPEN;
91 tp->t_state |= ISOPEN;
8062c8a7 92 tp->t_line = 0; /* conservative */
89dc6dfb
BJ
93}
94
89dc6dfb
BJ
95/*
96 * set default control characters.
97 */
98ttychars(tp)
99register struct tty *tp;
100{
8062c8a7 101
89dc6dfb
BJ
102 tun.t_intrc = CINTR;
103 tun.t_quitc = CQUIT;
104 tun.t_startc = CSTART;
105 tun.t_stopc = CSTOP;
106 tun.t_eofc = CEOT;
107 tun.t_brkc = CBRK;
108 tp->t_erase = CERASE;
109 tp->t_kill = CKILL;
8062c8a7 110/* begin local */
6fdc0335
BJ
111 tlun.t_suspc = CTRL(z);
112 tlun.t_dsuspc = CTRL(y);
8062c8a7
BJ
113 tlun.t_rprntc = CTRL(r);
114 tlun.t_flushc = CTRL(o);
115 tlun.t_werasc = CTRL(w);
116 tlun.t_lnextc = CTRL(v);
117 tlun.t_lintr = CTRL(c);
118 tlun.t_lerase = CTRL(h);
119 tlun.t_lkill = CTRL(u);
120 tp->t_local = 0;
121 tp->t_lstate = 0;
122/* end local */
89dc6dfb
BJ
123}
124
125/*
126 * clean tp on last close
127 */
128ttyclose(tp)
129register struct tty *tp;
130{
131
132 tp->t_pgrp = 0;
133 wflushtty(tp);
134 tp->t_state = 0;
8062c8a7 135 tp->t_line = 0;
89dc6dfb
BJ
136}
137
138/*
139 * stty/gtty writearound
140 */
141stty()
142{
143 u.u_arg[2] = u.u_arg[1];
144 u.u_arg[1] = TIOCSETP;
145 ioctl();
146}
147
148gtty()
149{
150 u.u_arg[2] = u.u_arg[1];
151 u.u_arg[1] = TIOCGETP;
152 ioctl();
153}
154
101ba270
BJ
155/*
156 * Do nothing specific version of line
157 * discipline specific ioctl command.
158 */
de857265 159/*ARGSUSED*/
101ba270
BJ
160nullioctl(tp, cmd, addr)
161register struct tty *tp;
162caddr_t addr;
163{
164
165 return (cmd);
166}
167
89dc6dfb
BJ
168/*
169 * ioctl system call
170 * Check legality, execute common code, and switch out to individual
171 * device routine.
172 */
173ioctl()
174{
175 register struct file *fp;
176 register struct inode *ip;
177 register struct a {
178 int fdes;
179 int cmd;
180 caddr_t cmarg;
181 } *uap;
182 register dev_t dev;
183 register fmt;
184
185 uap = (struct a *)u.u_ap;
186 if ((fp = getf(uap->fdes)) == NULL)
187 return;
188 if (uap->cmd==FIOCLEX) {
189 u.u_pofile[uap->fdes] |= EXCLOSE;
190 return;
191 }
192 if (uap->cmd==FIONCLEX) {
193 u.u_pofile[uap->fdes] &= ~EXCLOSE;
194 return;
195 }
196 ip = fp->f_inode;
197 fmt = ip->i_mode & IFMT;
198 if (fmt != IFCHR && fmt != IFMPC) {
8062c8a7
BJ
199/* begin local */
200 if (uap->cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
201 off_t nread = ip->i_size - fp->f_un.f_offset;
202
203 if (copyout((caddr_t)&nread, uap->cmarg, sizeof(off_t)))
204 u.u_error = EFAULT;
205 } else
206/* end local */
207 u.u_error = ENOTTY;
89dc6dfb
BJ
208 return;
209 }
210 dev = ip->i_un.i_rdev;
211 u.u_r.r_val1 = 0;
212 (*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, fp->f_flag);
213}
214
215/*
216 * Common code for several tty ioctl commands
217 */
218ttioccomm(com, tp, addr, dev)
219register struct tty *tp;
220caddr_t addr;
221{
222 unsigned t;
8062c8a7 223 struct sgttyb iocb;
de857265 224 struct clist tq;
89dc6dfb
BJ
225 extern int nldisp;
226
227 switch(com) {
228
229 /*
230 * get discipline number
231 */
232 case TIOCGETD:
233 t = tp->t_line;
234 if (copyout((caddr_t)&t, addr, sizeof(t)))
235 u.u_error = EFAULT;
236 break;
237
238 /*
239 * set line discipline
240 */
241 case TIOCSETD:
242 if (copyin(addr, (caddr_t)&t, sizeof(t))) {
243 u.u_error = EFAULT;
244 break;
245 }
246 if (t >= nldisp) {
247 u.u_error = ENXIO;
248 break;
249 }
8062c8a7 250 (void) spl5();
89dc6dfb
BJ
251 if (tp->t_line)
252 (*linesw[tp->t_line].l_close)(tp);
253 if (t)
254 (*linesw[t].l_open)(dev, tp, addr);
255 if (u.u_error==0)
256 tp->t_line = t;
8062c8a7 257 (void) spl0();
89dc6dfb
BJ
258 break;
259
260 /*
261 * prevent more opens on channel
262 */
263 case TIOCEXCL:
264 tp->t_state |= XCLUDE;
265 break;
266
267 case TIOCNXCL:
268 tp->t_state &= ~XCLUDE;
269 break;
270
271 /*
272 * Set new parameters
273 */
274 case TIOCSETP:
de857265 275 case TIOCSETN:
89dc6dfb
BJ
276 if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
277 u.u_error = EFAULT;
278 return(1);
279 }
101ba270 280 (void) spl5();
8062c8a7
BJ
281 if (tp->t_line == 0) {
282 if (com == TIOCSETP)
283 wflushtty(tp);
284 while (canon(tp)>=0)
285 ;
286 } else if (tp->t_line == NTTYDISC) {
287 if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
288 com == TIOCSETP)
289 wflushtty(tp);
290 else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
291 if (iocb.sg_flags & CBREAK) {
292 catq(&tp->t_rawq, &tp->t_canq);
293 tq = tp->t_rawq;
294 tp->t_rawq = tp->t_canq;
295 tp->t_canq = tq;
296 } else {
297 tp->t_local |= LPENDIN;
298 if (tp->t_canq.c_cc)
299 panic("ioccom canq");
300 if (tp->t_chan)
301 (void) sdata(tp->t_chan);
302 else
303 wakeup((caddr_t)&tp->t_rawq);
304 }
305 }
306 }
89dc6dfb 307 if ((tp->t_state&SPEEDS)==0) {
8062c8a7
BJ
308 tp->t_ispeed = iocb.sg_ispeed;
309 tp->t_ospeed = iocb.sg_ospeed;
89dc6dfb 310 }
8062c8a7
BJ
311 tp->t_erase = iocb.sg_erase;
312 tp->t_kill = iocb.sg_kill;
313 tp->t_flags = iocb.sg_flags;
101ba270 314 (void) spl0();
89dc6dfb
BJ
315 break;
316
317 /*
318 * send current parameters to user
319 */
320 case TIOCGETP:
8062c8a7
BJ
321 iocb.sg_ispeed = tp->t_ispeed;
322 iocb.sg_ospeed = tp->t_ospeed;
323 iocb.sg_erase = tp->t_erase;
324 iocb.sg_kill = tp->t_kill;
325 iocb.sg_flags = tp->t_flags;
89dc6dfb
BJ
326 if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
327 u.u_error = EFAULT;
328 break;
329
330 /*
331 * Hang up line on last close
332 */
333
334 case TIOCHPCL:
335 tp->t_state |= HUPCLS;
336 break;
337
338 case TIOCFLUSH:
339 flushtty(tp);
340 break;
341
342 /*
343 * ioctl entries to line discipline
344 */
345 case DIOCSETP:
346 case DIOCGETP:
101ba270
BJ
347 if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
348 u.u_error = ENOTTY;
89dc6dfb
BJ
349 break;
350
351 /*
352 * set and fetch special characters
353 */
354 case TIOCSETC:
8062c8a7 355 if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
89dc6dfb
BJ
356 u.u_error = EFAULT;
357 break;
358
359 case TIOCGETC:
8062c8a7
BJ
360 if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
361 u.u_error = EFAULT;
362 break;
363
364/* local ioctls */
365 case TIOCSLTC:
366 if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
367 u.u_error = EFAULT;
368 break;
369
370 case TIOCGLTC:
371 if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
372 u.u_error = EFAULT;
373 break;
374
375 case FIONREAD: {
376 off_t nread = tp->t_canq.c_cc;
377
378 if (tp->t_flags & (RAW|CBREAK))
379 nread += tp->t_rawq.c_cc;
380 if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
381 u.u_error = EFAULT;
382 break;
383 }
384
385 /*
386 * Should allow SPGRP and GPGRP only if tty open for reading.
387 */
388 case TIOCSPGRP:
389 tp->t_pgrp = (int)addr;
390 break;
391
392 case TIOCGPGRP:
393 if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
394 u.u_error = EFAULT;
395 break;
396
397 /*
398 * Modify local mode word.
399 */
400 case TIOCLBIS:
401 tp->t_local |= (int)addr;
402 break;
403
404 case TIOCLBIC:
405 tp->t_local &= ~(int)addr;
406 break;
407
408 case TIOCLSET:
409 tp->t_local = (int)addr;
410 break;
411
412 case TIOCLGET:
413 if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
89dc6dfb
BJ
414 u.u_error = EFAULT;
415 break;
416
8062c8a7 417/* end of locals */
89dc6dfb
BJ
418 default:
419 return(0);
420 }
421 return(1);
422}
423
424/*
425 * Wait for output to drain, then flush input waiting.
426 */
427wflushtty(tp)
428register struct tty *tp;
429{
430
101ba270 431 (void) spl5();
89dc6dfb
BJ
432 while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
433 (*tp->t_oproc)(tp);
434 tp->t_state |= ASLEEP;
435 sleep((caddr_t)&tp->t_outq, TTOPRI);
436 }
437 flushtty(tp);
101ba270 438 (void) spl0();
89dc6dfb
BJ
439}
440
441/*
442 * flush all TTY queues
443 */
444flushtty(tp)
445register struct tty *tp;
446{
447 register s;
448
101ba270 449 s = spl6();
89dc6dfb
BJ
450 while (getc(&tp->t_canq) >= 0)
451 ;
452 wakeup((caddr_t)&tp->t_rawq);
453 wakeup((caddr_t)&tp->t_outq);
89dc6dfb
BJ
454 tp->t_state &= ~TTSTOP;
455 (*cdevsw[major(tp->t_dev)].d_stop)(tp);
456 while (getc(&tp->t_outq) >= 0)
457 ;
458 while (getc(&tp->t_rawq) >= 0)
459 ;
460 tp->t_delct = 0;
8062c8a7 461 tp->t_rocount = 0; /* local */
6fdc0335 462 tp->t_lstate = 0;
89dc6dfb
BJ
463 splx(s);
464}
465
466
467
468/*
469 * transfer raw input list to canonical list,
470 * doing erase-kill processing and handling escapes.
471 * It waits until a full line has been typed in cooked mode,
472 * or until any character has been typed in raw mode.
473 */
474canon(tp)
475register struct tty *tp;
476{
477 register char *bp;
478 char *bp1;
479 register int c;
480 int mc;
481 int s;
482
483 if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0
484 || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) {
485 return(-1);
486 }
487 s = spl0();
488loop:
489 bp = &canonb[2];
490 while ((c=getc(&tp->t_rawq)) >= 0) {
491 if ((tp->t_flags&(RAW|CBREAK))==0) {
492 if (c==0377) {
493 tp->t_delct--;
494 break;
495 }
496 if (bp[-1]!='\\') {
497 if (c==tp->t_erase) {
498 if (bp > &canonb[2])
499 bp--;
500 continue;
501 }
502 if (c==tp->t_kill)
503 goto loop;
504 if (c==tun.t_eofc)
505 continue;
506 } else {
507 mc = maptab[c];
508 if (c==tp->t_erase || c==tp->t_kill)
509 mc = c;
510 if (mc && (mc==c || (tp->t_flags&LCASE))) {
511 if (bp[-2] != '\\')
512 c = mc;
513 bp--;
514 }
515 }
516 }
517 *bp++ = c;
518 if (bp>=canonb+CANBSIZ)
519 break;
520 }
521 bp1 = &canonb[2];
101ba270 522 (void) b_to_q(bp1, bp-bp1, &tp->t_canq);
89dc6dfb
BJ
523
524 if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
525 if (putc(tun.t_startc, &tp->t_outq)==0) {
526 tp->t_state &= ~TBLOCK;
527 ttstart(tp);
528 }
529 tp->t_char = 0;
530 }
531
532 splx(s);
533 return(0);
534}
535
536
537/*
538 * block transfer input handler.
539 */
540ttyrend(tp, pb, pe)
541register struct tty *tp;
542register char *pb, *pe;
543{
544 int tandem;
545
546 tandem = tp->t_flags&TANDEM;
547 if (tp->t_flags&RAW) {
101ba270 548 (void) b_to_q(pb, pe-pb, &tp->t_rawq);
89dc6dfb 549 if (tp->t_chan)
101ba270 550 (void) sdata(tp->t_chan); else
89dc6dfb
BJ
551 wakeup((caddr_t)&tp->t_rawq);
552 } else {
553 tp->t_flags &= ~TANDEM;
554 while (pb < pe)
555 ttyinput(*pb++, tp);
556 tp->t_flags |= tandem;
557 }
558 if (tandem)
559 ttyblock(tp);
560}
561
562/*
563 * Place a character on raw TTY input queue, putting in delimiters
564 * and waking up top half as needed.
565 * Also echo if required.
566 * The arguments are the character and the appropriate
567 * tty structure.
568 */
569ttyinput(c, tp)
570register c;
571register struct tty *tp;
572{
573 register int t_flags;
574 register struct chan *cp;
575
576 tk_nin += 1;
577 c &= 0377;
578 t_flags = tp->t_flags;
579 if (t_flags&TANDEM)
580 ttyblock(tp);
581 if ((t_flags&RAW)==0) {
582 c &= 0177;
583 if (tp->t_state&TTSTOP) {
584 if (c==tun.t_startc) {
585 tp->t_state &= ~TTSTOP;
586 ttstart(tp);
587 return;
588 }
589 if (c==tun.t_stopc)
590 return;
591 tp->t_state &= ~TTSTOP;
592 ttstart(tp);
593 } else {
594 if (c==tun.t_stopc) {
595 tp->t_state |= TTSTOP;
596 (*cdevsw[major(tp->t_dev)].d_stop)(tp);
597 return;
598 }
599 if (c==tun.t_startc)
600 return;
601 }
602 if (c==tun.t_quitc || c==tun.t_intrc) {
603 flushtty(tp);
604 c = (c==tun.t_intrc) ? SIGINT:SIGQUIT;
605 if (tp->t_chan)
606 scontrol(tp->t_chan, M_SIG, c);
607 else
8062c8a7 608 gsignal(tp->t_pgrp, c);
89dc6dfb
BJ
609 return;
610 }
611 if (c=='\r' && t_flags&CRMOD)
612 c = '\n';
613 }
614 if (tp->t_rawq.c_cc>TTYHOG) {
615 flushtty(tp);
616 return;
617 }
618 if (t_flags&LCASE && c>='A' && c<='Z')
619 c += 'a'-'A';
101ba270 620 (void) putc(c, &tp->t_rawq);
89dc6dfb
BJ
621 if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
622 if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
623 tp->t_delct++;
624 if ((cp=tp->t_chan)!=NULL)
101ba270 625 (void) sdata(cp); else
89dc6dfb
BJ
626 wakeup((caddr_t)&tp->t_rawq);
627 }
628 if (t_flags&ECHO) {
629 ttyoutput(c, tp);
630 if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0)
631 ttyoutput('\n', tp);
632 ttstart(tp);
633 }
634}
635
636
637/*
638 * Send stop character on input overflow.
639 */
640ttyblock(tp)
641register struct tty *tp;
642{
643 register x;
644 x = q1.c_cc + q2.c_cc;
645 if (q1.c_cc > TTYHOG) {
646 flushtty(tp);
647 tp->t_state &= ~TBLOCK;
648 }
649 if (x >= TTYHOG/2) {
650 if (putc(tun.t_stopc, &tp->t_outq)==0) {
651 tp->t_state |= TBLOCK;
652 tp->t_char++;
653 ttstart(tp);
654 }
655 }
656}
657
658/*
659 * put character on TTY output queue, adding delays,
660 * expanding tabs, and handling the CR/NL bit.
661 * It is called both from the top half for output, and from
662 * interrupt level for echoing.
663 * The arguments are the character and the tty structure.
664 */
665ttyoutput(c, tp)
666register c;
667register struct tty *tp;
668{
669 register char *colp;
670 register ctype;
671
89dc6dfb
BJ
672 /*
673 * Ignore EOT in normal mode to avoid hanging up
674 * certain terminals.
675 * In raw mode dump the char unchanged.
676 */
89dc6dfb
BJ
677 if ((tp->t_flags&RAW)==0) {
678 c &= 0177;
679 if ((tp->t_flags&CBREAK)==0 && c==CEOT)
680 return;
681 } else {
101ba270
BJ
682 tk_nout++;
683 (void) putc(c, &tp->t_outq);
89dc6dfb
BJ
684 return;
685 }
686
687 /*
688 * Turn tabs to spaces as required
689 */
690 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
101ba270
BJ
691 c = 8 - (tp->t_col & 7);
692 (void) b_to_q(" ", c, &tp->t_outq);
693 tp->t_col += c;
694 tk_nout += c;
89dc6dfb
BJ
695 return;
696 }
101ba270 697 tk_nout++;
89dc6dfb
BJ
698 /*
699 * for upper-case-only terminals,
700 * generate escapes.
701 */
702 if (tp->t_flags&LCASE) {
703 colp = "({)}!|^~'`";
704 while(*colp++)
705 if(c == *colp++) {
706 ttyoutput('\\', tp);
707 c = colp[-2];
708 break;
709 }
710 if ('a'<=c && c<='z')
711 c += 'A' - 'a';
712 }
713 /*
714 * turn <nl> to <cr><lf> if desired.
715 */
716 if (c=='\n' && tp->t_flags&CRMOD)
717 ttyoutput('\r', tp);
101ba270 718 (void) putc(c, &tp->t_outq);
89dc6dfb
BJ
719 /*
720 * Calculate delays.
721 * The numbers here represent clock ticks
722 * and are not necessarily optimal for all terminals.
723 * The delays are indicated by characters above 0200.
724 * In raw mode there are no delays and the
725 * transmission path is 8 bits wide.
726 */
727 colp = &tp->t_col;
728 ctype = partab[c];
729 c = 0;
730 switch (ctype&077) {
731
732 /* ordinary */
733 case 0:
734 (*colp)++;
735
736 /* non-printing */
737 case 1:
738 break;
739
740 /* backspace */
741 case 2:
742 if (*colp)
743 (*colp)--;
744 break;
745
746 /* newline */
747 case 3:
748 ctype = (tp->t_flags >> 8) & 03;
749 if(ctype == 1) { /* tty 37 */
750 if (*colp)
751 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
752 } else
753 if(ctype == 2) { /* vt05 */
754 c = 6;
755 }
756 *colp = 0;
757 break;
758
759 /* tab */
760 case 4:
761 ctype = (tp->t_flags >> 10) & 03;
762 if(ctype == 1) { /* tty 37 */
763 c = 1 - (*colp | ~07);
764 if(c < 5)
765 c = 0;
766 }
767 *colp |= 07;
768 (*colp)++;
769 break;
770
771 /* vertical motion */
772 case 5:
773 if(tp->t_flags & VTDELAY) /* tty 37 */
774 c = 0177;
775 break;
776
777 /* carriage return */
778 case 6:
779 ctype = (tp->t_flags >> 12) & 03;
780 if(ctype == 1) { /* tn 300 */
781 c = 5;
782 } else if(ctype == 2) { /* ti 700 */
783 c = 10;
784 } else if(ctype == 3) { /* concept 100 */
785 int i;
786 for (i= *colp; i<9; i++)
101ba270 787 (void) putc(0177, &tp->t_outq);
89dc6dfb
BJ
788 }
789 *colp = 0;
790 }
791 if(c)
101ba270 792 (void) putc(c|0200, &tp->t_outq);
89dc6dfb
BJ
793}
794
795/*
796 * Restart typewriter output following a delay
797 * timeout.
798 * The name of the routine is passed to the timeout
799 * subroutine and it is called during a clock interrupt.
800 */
801ttrstrt(tp)
802register struct tty *tp;
803{
804
805 tp->t_state &= ~TIMEOUT;
806 ttstart(tp);
807}
808
809/*
810 * Start output on the typewriter. It is used from the top half
811 * after some characters have been put on the output queue,
812 * from the interrupt routine to transmit the next
813 * character, and after a timeout has finished.
814 */
815ttstart(tp)
816register struct tty *tp;
817{
818 register s;
819
820 s = spl5();
821 if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
822 (*tp->t_oproc)(tp);
823 splx(s);
824}
825
826/*
827 * Called from device's read routine after it has
828 * calculated the tty-structure given as argument.
829 */
830ttread(tp)
831register struct tty *tp;
832{
833register s;
834
835 if ((tp->t_state&CARR_ON)==0)
836 return(-1);
837 s = spl5();
838 if (tp->t_canq.c_cc==0)
839 while (canon(tp)<0)
840 if (tp->t_chan==NULL) {
841 sleep((caddr_t)&tp->t_rawq, TTIPRI);
842 } else {
843 splx(s);
844 return(0);
845 }
846 splx(s);
847 while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0)
848 ;
849 return(tp->t_rawq.c_cc+tp->t_canq.c_cc);
850}
851
852/*
853 * Called from the device's write routine after it has
854 * calculated the tty-structure given as argument.
855 */
856caddr_t
857ttwrite(tp)
858register struct tty *tp;
859{
860 /*
861 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
862 * AND MUST NOT BE CHANGED WITHOUT PATCHING
863 * THE 'ASM' INLINES BELOW. WATCH OUT.
864 */
865 register char *cp;
866 register int cc, ce;
867 register i;
868 char obuf[OBUFSIZ];
869
870 if ((tp->t_state&CARR_ON)==0)
871 return(NULL);
872 while (u.u_count) {
873 cc = MIN(u.u_count, OBUFSIZ);
874 cp = obuf;
875 iomove(cp, (unsigned)cc, B_WRITE);
876 if (u.u_error)
877 break;
101ba270 878 (void) spl5();
89dc6dfb
BJ
879 while (tp->t_outq.c_cc > TTHIWAT) {
880 ttstart(tp);
881 tp->t_state |= ASLEEP;
882 if (tp->t_chan) {
883 u.u_base -= cc;
884 u.u_offset -= cc;
885 u.u_count += cc;
101ba270 886 (void) spl0();
89dc6dfb
BJ
887 return((caddr_t)&tp->t_outq);
888 }
889 sleep((caddr_t)&tp->t_outq, TTOPRI);
890 }
101ba270 891 (void) spl0();
89dc6dfb
BJ
892 if (tp->t_flags&LCASE) {
893 while (cc--)
894 ttyoutput(*cp++,tp);
895 continue;
896 }
897 while (cc) {
898 if (tp->t_flags&RAW)
899 ce=cc;
900 else {
901#ifdef VAX
902 asm(" scanc r9,(r10),_partab,$077");
903 asm(" subl3 r0,r9,r8");
904#else
905 ce=0;
906 while(((partab[*(cp+ce)]&077)==0)&&(ce<cc))
907 ce++;
908#endif
909 if (ce==0) {
910 ttyoutput(*cp++,tp);
911 cc--;
101ba270 912 goto check;
89dc6dfb
BJ
913 }
914 }
915 i=b_to_q(cp,ce,&tp->t_outq);
916 ce-=i;
917 tk_nout+=ce;
918 tp->t_col+=ce;
919 cp+=ce;
920 cc-=ce;
101ba270
BJ
921check:
922 if (tp->t_outq.c_cc > TTHIWAT) {
923 (void) spl5();
89dc6dfb
BJ
924 while (tp->t_outq.c_cc > TTHIWAT) {
925 ttstart(tp);
926 tp->t_state |= ASLEEP;
927 sleep((caddr_t)&tp->t_outq, TTOPRI);
928 }
101ba270 929 (void) spl0();
89dc6dfb
BJ
930 }
931 }
932 }
933 ttstart(tp);
934 return(NULL);
935}