/* ttynew.c 4.3 11/9/80 */
* New version of tty driver, supported
* as NTTYDISC. Adapted from a tty.c written
* by J.E.Kulp of IIASA, Austria (jekulp@mc)
* When running dz's using only SAE (silo alarm) on input
* it is necessary to call dzrint() at clock interrupt time.
* This is unsafe unless spl5()s in tty code are changed to
* spl6()s to block clock interrupts. Note that the dh driver
* currently in use works the same way as the dz, even though
* we could try to more intelligently manage its silo.
* Thus don't take this out if you have no dz's unless you
* change clock.c and dhtimer().
* Input mapping table-- if an entry is non-zero, when the
* corresponding character is typed preceded by "\" the escape
* sequence is replaced by the table value. Mostly used for
* upper-case only terminals.
char maptab
[]; /* see tty.c */
#define q4 tp->t_un.t_ctlq
* routine called on opens while tp->t_line == NTTYDISC
* establishes a process group for distribution of
* quits and interrupts from the tty.
* (actually, pp->p_pgrp can't be 0 when this routine
* is called since NTTYDISC is not the default discipline)
register struct proc
*pp
;
if (tp
->t_line
!= NTTYDISC
)
/* let ttyclose do the work if we are really closing */
* block transfer input handler.
tandem
= tp
->t_flags
&TANDEM
;
(void) b_to_q(pb
, pe
-pb
, &tp
->t_rawq
);
(void) sdata(tp
->t_chan
);
wakeup((caddr_t
)&tp
->t_rawq
);
* reinput pending characters after state switch
tp
->t_rawq
.c_cf
= tp
->t_rawq
.c_cl
= 0;
while ((c
= getc(&tq
)) >= 0)
tp
->t_lstate
&= ~LSTYPEN
;
* Place a character on raw TTY input queue, putting in delimiters
* and waking up top half as needed.
* The arguments are the character and the appropriate
if ((tp
->t_lstate
&LSTYPEN
) == 0)
/* check for literal nexting very first */
if (tp
->t_lstate
&LSLNCH
) {
/* check for output control functions */
} else if (c
==tun
.t_stopc
) {
if ((tp
->t_state
&TTSTOP
)==0) {
(*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
);
} else if (c
==tun
.t_startc
)
/* check for input interrupts (and flushed output) */
else if (c
==tlun
.t_flushc
) {
if (tp
->t_local
& LFLUSHO
)
if (tp
->t_rawq
.c_cc
+tp
->t_canq
.c_cc
)
} else if (c
==tlun
.t_suspc
|| c
==tun
.t_intrc
||
flushtty(tp
, c
==tlun
.t_suspc
? FREAD
: FREAD
|FWRITE
);
c
= c
==tun
.t_intrc
? SIGINT
:
((c
==tun
.t_quitc
) ? SIGQUIT
: SIGTSTP
);
scontrol(tp
->t_chan
, M_SIG
, c
);
/* check for buffer editing functions - cooked mode */
} else if ((t_flags
&CBREAK
) == 0) {
if ((tp
->t_lstate
&LSQUOT
) &&
(c
==tp
->t_erase
||c
==tp
->t_kill
)) {
ntyrub(unputc(&tp
->t_rawq
), tp
);
ntyrub(unputc(&tp
->t_rawq
), tp
);
} else if (c
==tp
->t_kill
) {
if (tp
->t_local
&LCRTKIL
&&
tp
->t_rawq
.c_cc
== tp
->t_rocount
) {
ntyrub(unputc(&tp
->t_rawq
), tp
);
while (getc(&tp
->t_rawq
) > 0)
} else if (c
==tlun
.t_werasc
) {
if (tp
->t_rawq
.c_cc
== 0)
if (c
!= ' ' && c
!= '\t')
} while (tp
->t_rawq
.c_cc
);
if (tp
->t_rawq
.c_cc
== 0)
} while (c
!= ' ' && c
!= '\t');
(void) putc(c
, &tp
->t_rawq
);
} else if (c
==tlun
.t_rprntc
) {
/* check for cooked mode input buffer overflow */
} else if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
> TTYHOG
) {
/* we should start a timeout that flushes the
buffer if it stays full - same in CBREAK */
if (tp
->t_outq
.c_cc
< TTHIWAT(tp
))
(void) ntyoutput(CTRL(g
), tp
);
/* put data char in q for user and wakeup if a break char */
} else if (putc(c
, &tp
->t_rawq
) >= 0) {
if (tp
->t_rocount
++ == 0)
catq(&tp
->t_rawq
, &tp
->t_canq
);
(void) sdata(tp
->t_chan
);
wakeup((caddr_t
)&tp
->t_rawq
);
gsignal(tp
->t_pgrp
, SIGTINT
);
if (tp
->t_lstate
&LSERASE
) {
tp
->t_lstate
&= ~LSERASE
;
(void) ntyoutput('/', tp
);
if (c
==tun
.t_eofc
&& tp
->t_flags
&ECHO
) {
i
= MIN(2, tp
->t_col
- i
);
(void) ntyoutput('\b', tp
);
} else if (tp
->t_rawq
.c_cc
> TTYHOG
) {
if (tp
->t_outq
.c_cc
< TTHIWAT(tp
))
(void) ntyoutput(CTRL(g
), tp
);
} else if (putc(c
, &tp
->t_rawq
) >= 0) {
gsignal(tp
->t_pgrp
, SIGTINT
);
(void) sdata(tp
->t_chan
);
wakeup((caddr_t
)&tp
->t_rawq
);
} else if (tp
->t_rawq
.c_cc
> TTYHOG
)
flushtty(tp
, FREAD
|FWRITE
);
else if (putc(c
, &tp
->t_rawq
) >= 0) {
gsignal(tp
->t_pgrp
, SIGTINT
);
(void) sdata(tp
->t_chan
);
wakeup((caddr_t
)&tp
->t_rawq
);
* put character on TTY output queue, adding delays,
* expanding tabs, and handling the CR/NL bit.
* It is called both from the top half for output, and from
* interrupt level for echoing.
* The arguments are the character and the tty structure.
* Returns < 0 if putc succeeds, otherwise returns char to resend
if (tp
->t_flags
&RAW
|| tp
->t_local
&LLITOUT
) {
if (putc(c
, &tp
->t_outq
))
* Ignore EOT in normal mode to avoid hanging up
if (c
==CEOT
&& (tp
->t_flags
&CBREAK
)==0)
* Turn tabs to spaces as required
if (c
=='\t' && (tp
->t_flags
&TBDELAY
)==XTABS
) {
if ((tp
->t_local
&LFLUSHO
) == 0) {
s
= spl5(); /* don't interrupt tabs */
c
-= b_to_q(" ", c
, &tp
->t_outq
);
* for upper-case-only terminals,
if (ntyoutput('\\', tp
) >= 0)
if (ntyoutput('\\', tp
) >= 0)
} else if ('a'<=c
&& c
<='z')
* turn <nl> to <cr><lf> if desired.
if (c
=='\n' && tp
->t_flags
&CRMOD
)
if (ntyoutput('\r', tp
) >= 0)
if (c
=='~' && tp
->t_local
<ILDE
)
if ((tp
->t_local
&LFLUSHO
) == 0 && putc(c
, &tp
->t_outq
))
* The numbers here represent clock ticks
* and are not necessarily optimal for all terminals.
* The delays are indicated by characters above 0200.
* In raw mode there are no delays and the
* transmission path is 8 bits wide.
ctype
= (tp
->t_flags
>> 8) & 03;
if(ctype
== 1) { /* tty 37 */
c
= max(((unsigned)*colp
>>4) + 3, (unsigned)6);
if(ctype
== 2) { /* vt05 */
ctype
= (tp
->t_flags
>> 10) & 03;
if(ctype
== 1) { /* tty 37 */
if(tp
->t_flags
& VTDELAY
) /* tty 37 */
ctype
= (tp
->t_flags
>> 12) & 03;
if(ctype
== 1) { /* tn 300 */
} else if(ctype
== 2) { /* ti 700 */
} else if(ctype
== 3) { /* concept 100 */
(void) putc(0177, &tp
->t_outq
);
if(c
&& (tp
->t_local
&LFLUSHO
) == 0)
(void) putc(c
|0200, &tp
->t_outq
);
* Called from device's read routine after it has
* calculated the tty-structure given as argument.
register struct clist
*qp
;
if ((tp
->t_state
&CARR_ON
)==0)
while (tp
== u
.u_ttyp
&& u
.u_procp
->p_pgrp
!= tp
->t_pgrp
) {
if (u
.u_signal
[SIGTTIN
] == SIG_IGN
||
u
.u_signal
[SIGTTIN
] == SIG_HOLD
||
(u
.u_procp
->p_flag
&SDETACH
) ||
u
.u_procp
->p_flag
&SVFORK
)
gsignal(u
.u_procp
->p_pgrp
, SIGTTIN
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
if (tp
->t_rawq
.c_cc
<= 0) {
if ((tp
->t_state
&CARR_ON
)==0 || tp
->t_chan
!=NULL
) {
if (tp
->t_local
&LINTRUP
&&
u
.u_signal
[SIGTINT
] != SIG_DFL
) {
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
while (tp
->t_rawq
.c_cc
&& passc(getc(&tp
->t_rawq
))>=0)
qp
= tp
->t_flags
& CBREAK
? &tp
->t_rawq
: &tp
->t_canq
;
if ((tp
->t_state
&CARR_ON
)==0 || tp
->t_chan
!=NULL
) {
if (tp
->t_local
&LINTRUP
&&
u
.u_signal
[SIGTINT
] != SIG_DFL
) {
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
while ((c
= getc(qp
)) >= 0) {
if (tp
->t_flags
&CRMOD
&& c
== '\r')
if (tp
->t_flags
&LCASE
&& c
<= 0177)
if (tp
->t_lstate
&LSBKSL
) {
} else if (c
>= 'A' && c
<= 'Z')
if (c
== tlun
.t_dsuspc
) {
gsignal(tp
->t_pgrp
, SIGTSTP
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
if (c
== tun
.t_eofc
&& (tp
->t_flags
&CBREAK
)==0)
if ((tp
->t_flags
&CBREAK
)==0 && ntbreakc(c
, tp
))
if (tp
->t_state
&TBLOCK
&& tp
->t_rawq
.c_cc
< TTYHOG
/5) {
if (putc(tun
.t_startc
, &tp
->t_outq
)==0) {
return (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
);
* Called from the device's write routine after it has
* calculated the tty-structure given as argument.
* THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
* AND MUST NOT BE CHANGED WITHOUT PATCHING
* THE 'ASM' INLINES BELOW. WATCH OUT.
if ((tp
->t_state
&CARR_ON
)==0)
while (u
.u_procp
->p_pgrp
!= tp
->t_pgrp
&& tp
== u
.u_ttyp
&&
(tp
->t_local
<OSTOP
) && (u
.u_procp
->p_flag
&SVFORK
)==0 &&
u
.u_signal
[SIGTTOU
] != SIG_IGN
&&
u
.u_signal
[SIGTTOU
] != SIG_HOLD
&&
(u
.u_procp
->p_flag
&SDETACH
)==0) {
gsignal(u
.u_procp
->p_pgrp
, SIGTTOU
);
sleep((caddr_t
)&lbolt
, TTIPRI
);
cc
= MIN(u
.u_count
, OBUFSIZ
);
iomove(cp
, (unsigned)cc
, B_WRITE
);
if (tp
->t_outq
.c_cc
> hiwat
)
if (tp
->t_flags
&LCASE
|| tp
->t_local
<ILDE
) {
while((c
= ntyoutput(c
, tp
)) >= 0) {
/* out of clists, wait a bit */
sleep((caddr_t
)&lbolt
, TTOPRI
);
if (tp
->t_outq
.c_cc
> hiwat
)
if (tp
->t_flags
&RAW
|| tp
->t_local
&LLITOUT
)
asm(" scanc r9,(r10),_partab,$077");
while(((partab
[*(unsigned char *)(cp
+ce
)]&077)==0)&&(ce
<cc
))
if (ntyoutput(*cp
, tp
) >= 0) {
sleep((caddr_t
)&lbolt
, TTOPRI
);
if (tp
->t_outq
.c_cc
> hiwat
)
i
=b_to_q(cp
,ce
,&tp
->t_outq
);
sleep((caddr_t
)&lbolt
, TTOPRI
);
if (ce
|| tp
->t_outq
.c_cc
> hiwat
)
if (tp
->t_outq
.c_cc
<= hiwat
) {
return ((caddr_t
)&tp
->t_outq
);
sleep((caddr_t
)&tp
->t_outq
, TTOPRI
);
* Rubout one character from the rawq of tp
* as cleanly as possible.
if ((tp
->t_flags
&ECHO
)==0)
if (tp
->t_local
&LCRTBS
) {
if (tp
->t_rocount
== 0) {
* Screwed by ttwrite; retype
if (c
==('\t'|0200) || c
==('\n'|0200))
else switch(partab
[c
&=0177] & 0177) {
if (tp
->t_flags
&LCASE
&& c
>= 'A' && c
<= 'Z')
if (tp
->t_local
& LCTLECH
)
if (tp
->t_rocount
< tp
->t_rawq
.c_cc
) {
for (cp
= tp
->t_rawq
.c_cf
; cp
; cp
= nextc(&tp
->t_rawq
, cp
))
tp
->t_lstate
&= ~LSCNTTB
;
* savecol will now be length of the tab
savecol
= 8; /* overflow screw */
(void) ntyoutput('\b', tp
);
} else if (tp
->t_local
&LPRTERA
) {
if ((tp
->t_lstate
&LSERASE
) == 0) {
(void) ntyoutput('\\', tp
);
ntyecho(tp
->t_erase
, tp
);
* Crt back over cnt chars perhaps
ntyout(tp
->t_local
&LCRTERA
? "\b \b" : "\b", tp
);
* We assume c_cc has already been checked.
if (tlun
.t_rprntc
!= 0377)
ntyecho(tlun
.t_rprntc
, tp
);
(void) ntyoutput('\n', tp
);
for (cp
= tp
->t_canq
.c_cf
; cp
; cp
= nextc(&tp
->t_canq
, cp
))
for (cp
= tp
->t_rawq
.c_cf
; cp
; cp
= nextc(&tp
->t_rawq
, cp
))
tp
->t_lstate
&= ~LSERASE
;
tp
->t_rocount
= tp
->t_rawq
.c_cc
;
* Echo a typed character to the terminal
if ((tp
->t_lstate
& LSCNTTB
) == 0)
if (c
== '\r' && tp
->t_flags
&CRMOD
)
if (tp
->t_local
&LCTLECH
) {
if ((c
&0177) <= 037 && c
!='\t' && c
!='\n' || (c
&0177)==0177) {
(void) ntyoutput('^', tp
);
else if (tp
->t_flags
&LCASE
)
(void) ntyoutput(c
& 0177, tp
);
* Is c a break char for tp?
return (c
== '\n' || c
== tun
.t_eofc
|| c
== tun
.t_brkc
||
c
== '\r' && (tp
->t_flags
&CRMOD
));