* general TTY subroutines
* 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.
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,'|',000,000,000,000,000,'`',
'{','}',000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,'~',000,
000,'A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O',
'P','Q','R','S','T','U','V','W',
'X','Y','Z',000,000,000,000,000,
#define q4 tp->t_un.t_ctlq
* routine called on first teletype open.
* establishes a process group for distribution
* of quits and interrupts from the tty.
register struct proc
*pp
;
tp
->t_line
= 0; /* conservative */
* set default control characters.
* Do nothing specific version of line
* discipline specific ioctl command.
* Check legality, execute common code, and switch out to individual
register struct file
*fp
;
register struct inode
*ip
;
uap
= (struct a
*)u
.u_ap
;
if ((fp
= getf(uap
->fdes
)) == NULL
)
u
.u_pofile
[uap
->fdes
] |= EXCLOSE
;
if (uap
->cmd
==FIONCLEX
) {
u
.u_pofile
[uap
->fdes
] &= ~EXCLOSE
;
if (fmt
!= IFCHR
&& fmt
!= IFMPC
) {
if (uap
->cmd
==FIONREAD
&& (fmt
== IFREG
|| fmt
== IFDIR
)) {
off_t nread
= ip
->i_size
- fp
->f_un
.f_offset
;
if (copyout((caddr_t
)&nread
, uap
->cmarg
, sizeof(off_t
)))
(*cdevsw
[major(dev
)].d_ioctl
)(dev
, uap
->cmd
, uap
->cmarg
, fp
->f_flag
);
* Common code for several tty ioctl commands
ttioccomm(com
, tp
, addr
, dev
)
if (copyout((caddr_t
)&t
, addr
, sizeof(t
)))
if (copyin(addr
, (caddr_t
)&t
, sizeof(t
))) {
(*linesw
[tp
->t_line
].l_close
)(tp
);
(*linesw
[t
].l_open
)(dev
, tp
, addr
);
* prevent more opens on channel
if (copyin(addr
, (caddr_t
)&iocb
, sizeof(iocb
))) {
} else if (tp
->t_line
== NTTYDISC
) {
if (tp
->t_flags
&RAW
|| iocb
.sg_flags
&RAW
||
else if ((tp
->t_flags
&CBREAK
) != (iocb
.sg_flags
&CBREAK
)) {
if (iocb
.sg_flags
& CBREAK
) {
catq(&tp
->t_rawq
, &tp
->t_canq
);
(void) sdata(tp
->t_chan
);
wakeup((caddr_t
)&tp
->t_rawq
);
if ((tp
->t_state
&SPEEDS
)==0) {
tp
->t_ispeed
= iocb
.sg_ispeed
;
tp
->t_ospeed
= iocb
.sg_ospeed
;
tp
->t_erase
= iocb
.sg_erase
;
tp
->t_kill
= iocb
.sg_kill
;
tp
->t_flags
= iocb
.sg_flags
;
* send current parameters to user
iocb
.sg_ispeed
= tp
->t_ispeed
;
iocb
.sg_ospeed
= tp
->t_ospeed
;
iocb
.sg_erase
= tp
->t_erase
;
iocb
.sg_kill
= tp
->t_kill
;
iocb
.sg_flags
= tp
->t_flags
;
if (copyout((caddr_t
)&iocb
, addr
, sizeof(iocb
)))
* Hang up line on last close
* ioctl entries to line discipline
if ((*linesw
[tp
->t_line
].l_ioctl
)(com
, tp
, addr
))
* set and fetch special characters
if (copyin(addr
, (caddr_t
)&tun
, sizeof(struct tchars
)))
if (copyout((caddr_t
)&tun
, addr
, sizeof(struct tchars
)))
if (copyin(addr
, (caddr_t
)&tlun
, sizeof (struct ltchars
)))
if (copyout((caddr_t
)&tlun
, addr
, sizeof (struct ltchars
)))
off_t nread
= tp
->t_canq
.c_cc
;
if (tp
->t_flags
& (RAW
|CBREAK
))
nread
+= tp
->t_rawq
.c_cc
;
if (copyout((caddr_t
)&nread
, addr
, sizeof (off_t
)))
* Should allow SPGRP and GPGRP only if tty open for reading.
if (copyout((caddr_t
)&tp
->t_pgrp
, addr
, sizeof(tp
->t_pgrp
)))
* Modify local mode word.
tp
->t_local
|= (int)addr
;
tp
->t_local
&= ~(int)addr
;
if (copyout((caddr_t
)&tp
->t_local
, addr
, sizeof(tp
->t_local
)))
if (copyout((caddr_t
)&tp
->t_outq
.c_cc
, addr
, sizeof(tp
->t_outq
.c_cc
)))
* Wait for output to drain, then flush input waiting.
while (tp
->t_outq
.c_cc
&& tp
->t_state
&CARR_ON
) {
sleep((caddr_t
)&tp
->t_outq
, TTOPRI
);
while (getc(&tp
->t_canq
) >= 0)
wakeup((caddr_t
)&tp
->t_rawq
);
wakeup((caddr_t
)&tp
->t_outq
);
(*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
);
while (getc(&tp
->t_outq
) >= 0)
while (getc(&tp
->t_rawq
) >= 0)
tp
->t_rocount
= 0; /* local */
* transfer raw input list to canonical list,
* doing erase-kill processing and handling escapes.
* It waits until a full line has been typed in cooked mode,
* or until any character has been typed in raw mode.
if ((tp
->t_flags
&(RAW
|CBREAK
))==0 && tp
->t_delct
==0
|| (tp
->t_flags
&(RAW
|CBREAK
))!=0 && tp
->t_rawq
.c_cc
==0) {
while ((c
=getc(&tp
->t_rawq
)) >= 0) {
if ((tp
->t_flags
&(RAW
|CBREAK
))==0) {
if (c
==tp
->t_erase
|| c
==tp
->t_kill
)
if (mc
&& (mc
==c
|| (tp
->t_flags
&LCASE
))) {
(void) b_to_q(bp1
, bp
-bp1
, &tp
->t_canq
);
if (tp
->t_state
&TBLOCK
&& tp
->t_rawq
.c_cc
< TTYHOG
/5) {
if (putc(tun
.t_startc
, &tp
->t_outq
)==0) {
* block transfer input handler.
tandem
= tp
->t_flags
&TANDEM
;
(void) b_to_q(pb
, pe
-pb
, &tp
->t_rawq
);
(void) sdata(tp
->t_chan
); else
wakeup((caddr_t
)&tp
->t_rawq
);
* 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
register struct chan
*cp
;
if (tp
->t_state
&TTSTOP
) {
(*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
);
if (c
==tun
.t_quitc
|| c
==tun
.t_intrc
) {
c
= (c
==tun
.t_intrc
) ? SIGINT
:SIGQUIT
;
scontrol(tp
->t_chan
, M_SIG
, c
);
if (c
=='\r' && t_flags
&CRMOD
)
if (tp
->t_rawq
.c_cc
>TTYHOG
) {
if (t_flags
&LCASE
&& c
>='A' && c
<='Z')
(void) putc(c
, &tp
->t_rawq
);
if (t_flags
&(RAW
|CBREAK
)||(c
=='\n'||c
==tun
.t_eofc
||c
==tun
.t_brkc
)) {
if ((t_flags
&(RAW
|CBREAK
))==0 && putc(0377, &tp
->t_rawq
)==0)
if ((cp
=tp
->t_chan
)!=NULL
)
wakeup((caddr_t
)&tp
->t_rawq
);
if (c
==tp
->t_kill
&& (t_flags
&(RAW
|CBREAK
))==0)
* Send stop character on input overflow.
if (putc(tun
.t_stopc
, &tp
->t_outq
)==0) {
* 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.
* Ignore EOT in normal mode to avoid hanging up
* In raw mode dump the char unchanged.
if ((tp
->t_flags
&RAW
)==0) {
if ((tp
->t_flags
&CBREAK
)==0 && c
==CEOT
)
(void) putc(c
, &tp
->t_outq
);
* Turn tabs to spaces as required
if (c
=='\t' && (tp
->t_flags
&TBDELAY
)==XTABS
) {
(void) b_to_q(" ", c
, &tp
->t_outq
);
* for upper-case-only terminals,
* turn <nl> to <cr><lf> if desired.
if (c
=='\n' && tp
->t_flags
&CRMOD
)
(void) 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
);
(void) putc(c
|0200, &tp
->t_outq
);
* Restart typewriter output following a delay
* The name of the routine is passed to the timeout
* subroutine and it is called during a clock interrupt.
* Start output on the typewriter. It is used from the top half
* after some characters have been put on the output queue,
* from the interrupt routine to transmit the next
* character, and after a timeout has finished.
if((tp
->t_state
&(TIMEOUT
|TTSTOP
|BUSY
)) == 0)
* Called from device's read routine after it has
* calculated the tty-structure given as argument.
if ((tp
->t_state
&CARR_ON
)==0)
sleep((caddr_t
)&tp
->t_rawq
, TTIPRI
);
while (tp
->t_canq
.c_cc
&& passc(getc(&tp
->t_canq
))>=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)
cc
= MIN(u
.u_count
, OBUFSIZ
);
iomove(cp
, (unsigned)cc
, B_WRITE
);
while (tp
->t_outq
.c_cc
> TTHIWAT
) {
return((caddr_t
)&tp
->t_outq
);
sleep((caddr_t
)&tp
->t_outq
, TTOPRI
);
asm(" scanc r9,(r10),_partab,$077");
while(((partab
[*(cp
+ce
)]&077)==0)&&(ce
<cc
))
i
=b_to_q(cp
,ce
,&tp
->t_outq
);
if (tp
->t_outq
.c_cc
> TTHIWAT
) {
while (tp
->t_outq
.c_cc
> TTHIWAT
) {
sleep((caddr_t
)&tp
->t_outq
, TTOPRI
);