* Datakit terminal driver
* SCCSID[] = "@(#)dktty.c 1.8 Garage 84/05/14"
* "@(#)dktty.c 1.6 (Berkeley) %G%"
#include "../include/pte.h"
extern struct dkdev dkdev
[];
struct tty dkt
[NDATAKIT
];
caddr_t dktibuf
[NDATAKIT
]; /* Input buffer pointers */
int dktpaused
[NDATAKIT
]; /* delays for no output mbuf */
speeds aren
't used, don't bother
int dktdelay
[] = { /* Time to wait on close before dropping line */
4, 15, 15, 15, 15, 15, 15, 8, /* B0-B300 */
static char dkt_tmr
[16] = {
15, 15, 15, 15, 15, 15, 15, 15,
15, 9, 6, 4, 2, 1, 15, 15
#define DEBUG (dkdebug < 512)
#define devDEBUG (minor(dev) >= dkdebug)
#define chanDEBUG (chan >= dkdebug)
#define tpDEBUG ((tp - dkt) >= dkdebug)
register struct dkdev
*dv
;
if (DEBUG
) log(LOG_ERR
, "dkt_open(%d) error\n", dev
);
if ((tp
->t_state
&TS_XCLUDE
) && u
.u_uid
!=0)
mb
= m_get(M_WAIT
, DKMT_ITTY
);
if (mb
== NULL
) return ENOBUFS
;
dktibuf
[d
] = mtod(mb
, caddr_t
);
if ((chan
= dk_open(d
, (int (*)()) NULL
)) < 0) {
tp
->t_state
|= (TS_WOPEN
|TS_CARR_ON
);
if ((tp
->t_state
&TS_ISOPEN
) == 0) {
tp
->t_iflag
= TTYDEF_IFLAG
;
tp
->t_oflag
= TTYDEF_OFLAG
;
tp
->t_lflag
= TTYDEF_LFLAG
;
tp
->t_cflag
= TTYDEF_CFLAG
;
tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
if (devDEBUG
) log(LOG_ERR
, "DKT_open(%x,%o)\n",dev
,flag
);
if (devDEBUG
) log(LOG_ERR
, "DKT_open(%x, %x) ok\n", dev
, tp
);
return (*linesw
[tp
->t_line
].l_open
)(dev
, tp
);
register struct dkdev
*dv
;
extern int dktcflush(), dktrcv(), wakeup();
* If called from exit(), give output 30 seconds to drain.
* Otherwise let output drain first.
if(u
.u_signal
[SIGKILL
] == SIG_IGN
){
timeout(dktcflush
, (caddr_t
) tp
, 30*hz
);
untimeout(dktcflush
, (caddr_t
) tp
);
tp
->t_state
&= ~TS_CARR_ON
;
if(dv
->d_prot
== DpTTY
) /* no other protocols open */
(*linesw
[tp
->t_line
].l_close
)(tp
, flag
);
if (devDEBUG
) log(LOG_ERR
, "DKT_clos(%x)\n",dev
);
tp
->t_state
&= ~TS_CARR_ON
;
/* Wait for output to drain on far end */
if (dktdelay
[tp
->t_ispeed
] > 0) {
timeout(wakeup
, (caddr_t
) tp
, dktdelay
[tp
->t_ispeed
] * hz
);
sleep((caddr_t
) tp
, TTIPRI
);
else (void) dk_rabort(d
, dktrcv
, (caddr_t
) tp
);
(void) m_free(dtom(dktibuf
[d
]));
ttyflush(tp
, (FREAD
|FWRITE
)) ;
if (devDEBUG
) log(LOG_ERR
, "dktread(%x) %d\n", dev
, uio
->uio_resid
) ;
err
= (*linesw
[tp
->t_line
].l_read
)(tp
, uio
, flag
);
log(LOG_ERR
, "dktread done(%x) %d err=%d\n", dev
, uio
->uio_resid
, err
) ;
if (devDEBUG
) log(LOG_ERR
, "dktwrite(%x)\n",dev
);
return (*linesw
[tp
->t_line
].l_write
)(tp
, uio
, flag
);
dktrcv(tp
, chan
, resid
, rmode
, rctl
)
register struct tty
*tp
;
if ((rmode
& DKR_ABORT
) || (dk_status(chan
) & DK_RESET
)) {
if (tp
->t_state
&TS_ISOPEN
) {
/* Should really do parity checking... */
(*linesw
[tp
->t_line
].l_rint
)((*cp
++)&0377, tp
) ;
if ((c
= (rctl
& 0377)) != 0) {
if (chanDEBUG
) log(LOG_ERR
, "DKT_ctl 0%o on %d\n",c
,chan
);
(*linesw
[tp
->t_line
].l_rint
)(TTY_FE
, tp
) ;
* Input flow control: queue another receive unless to many chars waiting
register int d
= tp
- dkt
;
if ((dk_status(d
) & (DK_RCV
|DK_OPEN
)) != DK_OPEN
)
if (dktibuf
[d
] == NULL
) return;
x
= tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
;
if (x
>= TTYHOG
/2 && (!(tp
->t_lflag
&ICANON
) || tp
->t_canq
.c_cc
))
(void) dk_recv(d
, dktibuf
[d
], MLEN
,
DKR_BLOCK
| DKR_TIME
| (dkt_tmr
[tp
->t_ispeed
]<<8),
DKR_BLOCK
| DKR_TIME
| (1<<8),
dktioctl(dev
, cmd
, data
, flag
)
error
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, data
, flag
);
error
= ttioctl(tp
, cmd
, data
, flag
);
dktxpack(tp
-dkt
, D_BREAK
) ;
* Start (restart) transmission on the given DKT line.
if (dk_status(d
) & DK_SPND
)
if (tp
->t_state
& (TS_BUSY
|TS_TTSTOP
|TS_TIMEOUT
))
* If the writer was sleeping on output overflow,
* wake the process when low tide is reached.
if (tp
->t_outq
.c_cc
<=tp
->t_lowat
) {
if (tp
->t_state
&TS_ASLEEP
) {
tp
->t_state
&= ~TS_ASLEEP
;
wakeup((caddr_t
)&tp
->t_outq
);
selwakeup(tp
->t_wsel
, tp
->t_state
& TS_WCOLL
);
tp
->t_state
&= ~TS_WCOLL
;
* Now restart transmission unless the output queue is
if (tp
->t_outq
.c_cc
== 0)
m
= m_get(M_DONTWAIT
, DKMT_OTTY
);
/* No buffers; arrange to retry in .5 seconds */
tp
->t_state
|= TS_TIMEOUT
;
timeout(ttrstrt
, (caddr_t
) tp
, hz
/2);
if (1 || !(tp
->t_oflag
&OPOST
))
nch
= ndqb(&tp
->t_outq
, 0);
nch
= ndqb(&tp
->t_outq
, 0200);
* If first thing on queue is a delay process it.
c
= MIN((nch
& 0xff) + 6, 0x7f);
log(LOG_ERR
, "DKT_delay %d\n", c
) ;
if (dk_xmit(d
, (struct mbuf
*) NULL
, 1, delay
, dktxdun
, (caddr_t
) 0))
* If characters to transmit, restart transmission.
bcopy((caddr_t
)tp
->t_outq
.c_cf
, mtod(m
, caddr_t
), (unsigned) nch
);
if (dk_xmit(d
, m
, 1, 0, dktxdun
, (caddr_t
) nch
))
(void) dk_xmit(chan
, (struct mbuf
*) NULL
, 1, cmd
, (int (*)()) 0, (caddr_t
) 0);
if (chanDEBUG
) log(LOG_ERR
, "DKT_sent %o on %d\n",cmd
&0377,chan
);
if (tp
->t_state
& TS_BUSY
) {
if ((tp
->t_state
& TS_TTSTOP
) == 0) {
if (tpDEBUG
) log(LOG_ERR
, "dktshut %d\n", tp
-dkt
);
if ((tp
->t_state
&TS_ISOPEN
) && (tp
->t_state
&TS_CARR_ON
))
(void)(*linesw
[tp
->t_line
].l_modem
)(tp
, 0);
tp
->t_state
&= ~TS_CARR_ON
;
ttyflush(tp
, (FREAD
|FWRITE
)) ;
dk_cmd((tp
- dkt
), DKC_FLUSH
);
register struct tty
*tp
;
if (tp
->t_state
& TS_FLUSH
) tp
->t_state
&= ~TS_FLUSH
;
else ndflush(&tp
->t_outq
, cnt
);
(*linesw
[tp
->t_line
].l_start
)(tp
);