138624Skarels /*
238624Skarels * Datakit terminal driver
338624Skarels * SCCSID[] = "@(#)dktty.c 1.8 Garage 84/05/14"
4*49756Smarc * "@(#)dktty.c 1.6 (Berkeley) 05/16/91"
538624Skarels */
638624Skarels
738624Skarels #include "dktty.h"
838624Skarels #if NDKTTY>0
938624Skarels #include "datakit.h"
1038624Skarels
1145800Sbostic #include "../include/pte.h"
1245800Sbostic #include "sys/param.h"
1345800Sbostic #include "sys/syslog.h"
1445800Sbostic #include "sys/errno.h"
1545800Sbostic #include "sys/signal.h"
1645800Sbostic #include "sys/conf.h"
1745800Sbostic #include "sys/user.h"
1845800Sbostic #include "sys/proc.h"
1945800Sbostic #include "sys/ioctl.h"
2045800Sbostic #include "sys/tty.h"
2145800Sbostic #include "sys/file.h"
2245800Sbostic #include "sys/mbuf.h"
2345800Sbostic #include "sys/uio.h"
2445800Sbostic #include "sys/kernel.h"
2538624Skarels #include "dkit.h"
2638624Skarels #include "dk.h"
2738624Skarels #include "dkdev.h"
2838624Skarels
2938624Skarels extern int dk_nchan;
3038624Skarels extern struct dkdev dkdev[];
3138624Skarels
3238624Skarels struct tty dkt[NDATAKIT];
3338624Skarels caddr_t dktibuf[NDATAKIT]; /* Input buffer pointers */
3438624Skarels int dktpaused[NDATAKIT]; /* delays for no output mbuf */
3545182Skarels
3645182Skarels #ifdef notdef
3745182Skarels speeds aren't used, don't bother
3838624Skarels int dktdelay[] = { /* Time to wait on close before dropping line */
3938624Skarels 4, 15, 15, 15, 15, 15, 15, 8, /* B0-B300 */
4038624Skarels 4, 2, 2, 2, 1, 1, 1, 1
4138624Skarels };
4238624Skarels static char dkt_tmr[16] = {
4338624Skarels 15, 15, 15, 15, 15, 15, 15, 15,
4438624Skarels 15, 9, 6, 4, 2, 1, 15, 15
4538624Skarels } ;
4645182Skarels #endif
4738624Skarels
4845182Skarels int dktstart();
4938624Skarels
5045182Skarels
5138624Skarels /*
5238624Skarels * DKT control messages
5338624Skarels */
5438624Skarels #define D_BREAK 0110
5538624Skarels #define D_DELAY 0100
5638624Skarels
5738624Skarels extern int dkdebug ;
5838624Skarels
5938624Skarels #define DEBUG (dkdebug < 512)
6038624Skarels #define devDEBUG (minor(dev) >= dkdebug)
6138624Skarels #define chanDEBUG (chan >= dkdebug)
6238624Skarels #define tpDEBUG ((tp - dkt) >= dkdebug)
6338624Skarels
6438624Skarels /*
6538624Skarels * Open a DKT line.
6638624Skarels */
dktopen(dev,flag)6738624Skarels dktopen(dev, flag)
6838624Skarels {
6938624Skarels register struct tty *tp;
7038624Skarels register struct dkdev *dv;
7138624Skarels register d;
7238624Skarels int chan;
7338624Skarels
7438624Skarels d = minor(dev);
7538624Skarels if (d >= dk_nchan) {
7638624Skarels if (DEBUG) log(LOG_ERR, "dkt_open(%d) error\n", dev);
7738624Skarels return ENXIO;
7838624Skarels }
7938624Skarels tp = &dkt[d];
8038624Skarels if ((tp->t_state&TS_XCLUDE) && u.u_uid!=0)
8138624Skarels return (EBUSY);
8238624Skarels if (!dktibuf[d]) {
8338624Skarels struct mbuf *mb;
8438624Skarels mb = m_get(M_WAIT, DKMT_ITTY);
8538624Skarels if (mb == NULL) return ENOBUFS;
8638624Skarels dktibuf[d] = mtod(mb, caddr_t);
8738624Skarels }
8838624Skarels if ((chan = dk_open(d, (int (*)()) NULL)) < 0) {
8938624Skarels return -chan;
9038624Skarels }
9138624Skarels
9238624Skarels tp->t_oproc = dktstart;
9338624Skarels tp->t_state |= (TS_WOPEN|TS_CARR_ON);
9438624Skarels dv = &dkdev[d];
9538624Skarels if ((tp->t_state&TS_ISOPEN) == 0) {
9638624Skarels ttychars(tp) ;
9738624Skarels if (tp->t_ispeed == 0) {
9845182Skarels tp->t_iflag = TTYDEF_IFLAG;
9945182Skarels tp->t_oflag = TTYDEF_OFLAG;
10045182Skarels tp->t_lflag = TTYDEF_LFLAG;
10145182Skarels tp->t_cflag = TTYDEF_CFLAG;
10245182Skarels tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
10345182Skarels ttsetwater(tp);
10438624Skarels }
10538624Skarels if (devDEBUG) log(LOG_ERR, "DKT_open(%x,%o)\n",dev,flag);
10638624Skarels }
10738624Skarels dktfcon(tp);
10838624Skarels if (devDEBUG) log(LOG_ERR, "DKT_open(%x, %x) ok\n", dev, tp);
10938624Skarels dv->d_prot |= DpTTY;
11038624Skarels return (*linesw[tp->t_line].l_open)(dev, tp);
11138624Skarels }
11238624Skarels
11338624Skarels /*
11438624Skarels * Close a DKT line.
11538624Skarels */
11638624Skarels /*ARGSUSED*/
dktclose(dev,flag)11738624Skarels dktclose(dev, flag)
11838624Skarels dev_t dev;
11938624Skarels int flag;
12038624Skarels {
12138624Skarels register struct tty *tp;
12238624Skarels register struct dkdev *dv;
12338624Skarels register int d, s;
12438624Skarels extern int dktcflush(), dktrcv(), wakeup();
12538624Skarels
12638624Skarels d = minor(dev);
12738624Skarels tp = &dkt[d];
12838624Skarels dv = &dkdev[d];
12938624Skarels /*
13038624Skarels * If called from exit(), give output 30 seconds to drain.
13138624Skarels * Otherwise let output drain first.
13238624Skarels */
13338624Skarels if(u.u_signal[SIGKILL] == SIG_IGN){
13438624Skarels s = spl5();
13538624Skarels timeout(dktcflush, (caddr_t) tp, 30*hz);
13638624Skarels ttywflush(tp) ;
13738624Skarels untimeout(dktcflush, (caddr_t) tp);
13838624Skarels tp->t_state &= ~TS_CARR_ON;
13938624Skarels if(dv->d_prot == DpTTY) /* no other protocols open */
14038624Skarels dk_reset(d);
14138624Skarels splx(s);
14238624Skarels }
14338624Skarels
144*49756Smarc (*linesw[tp->t_line].l_close)(tp, flag);
14538624Skarels if (devDEBUG) log(LOG_ERR, "DKT_clos(%x)\n",dev);
14638624Skarels dv->d_prot &= ~DpTTY;
14738624Skarels tp->t_state &= ~TS_CARR_ON;
14845182Skarels #ifdef notdef
14938624Skarels /* Wait for output to drain on far end */
15038624Skarels if (dktdelay[tp->t_ispeed] > 0) {
15138624Skarels timeout(wakeup, (caddr_t) tp, dktdelay[tp->t_ispeed] * hz);
15238624Skarels sleep((caddr_t) tp, TTIPRI);
15338624Skarels }
15445182Skarels #endif
15538624Skarels if(!dv->d_prot){
15638624Skarels (void) dk_close(d);
15738624Skarels (void) dk_takedown(d);
15838624Skarels dv->d_state = 0;
15938624Skarels }
16038624Skarels else (void) dk_rabort(d, dktrcv, (caddr_t) tp);
16138624Skarels ttyclose(tp);
16238624Skarels s = spl5();
16338624Skarels if (dktibuf[d]) {
16438624Skarels (void) m_free(dtom(dktibuf[d]));
16538624Skarels dktibuf[d] = NULL;
16638624Skarels }
16738624Skarels splx(s);
16845184Skarels return (0);
16938624Skarels }
17038624Skarels
17138624Skarels static
17238624Skarels dktcflush(tp)
17338624Skarels struct tty *tp;
17438624Skarels {
17538624Skarels ttyflush(tp, (FREAD|FWRITE)) ;
17638624Skarels }
17738624Skarels
17838624Skarels /*
17938624Skarels * Read from a DKT line.
18038624Skarels */
dktread(dev,uio,flag)18145182Skarels dktread(dev, uio, flag)
18245182Skarels dev_t dev;
18338624Skarels struct uio *uio;
18438624Skarels {
18538624Skarels register struct tty *tp;
18638624Skarels int err;
18738624Skarels
18838624Skarels if (devDEBUG) log(LOG_ERR, "dktread(%x) %d\n", dev, uio->uio_resid) ;
18938624Skarels tp = &dkt[minor(dev)];
19045182Skarels err = (*linesw[tp->t_line].l_read)(tp, uio, flag);
19138624Skarels if (devDEBUG)
19238624Skarels log(LOG_ERR, "dktread done(%x) %d err=%d\n", dev, uio->uio_resid, err) ;
19338624Skarels dktfcon(tp);
19438624Skarels return err;
19538624Skarels }
19638624Skarels
19738624Skarels /*
19838624Skarels * Write on a DKT line
19938624Skarels */
dktwrite(dev,uio,flag)20045182Skarels dktwrite(dev, uio, flag)
20145182Skarels dev_t dev;
20238624Skarels struct uio *uio;
20338624Skarels {
20438624Skarels register struct tty *tp;
20538624Skarels
20638624Skarels if (devDEBUG) log(LOG_ERR, "dktwrite(%x)\n",dev);
20738624Skarels tp = &dkt[minor(dev)];
20845182Skarels return (*linesw[tp->t_line].l_write)(tp, uio, flag);
20938624Skarels }
21038624Skarels
21138624Skarels /*
21238624Skarels * Receive a packet
21338624Skarels */
21438624Skarels /*ARGSUSED*/
dktrcv(tp,chan,resid,rmode,rctl)21538624Skarels dktrcv(tp, chan, resid, rmode, rctl)
21638624Skarels register struct tty *tp ;
21738624Skarels {
21838624Skarels register c ;
21938624Skarels register char *cp ;
22038624Skarels register count ;
22138624Skarels
22238624Skarels if ((rmode & DKR_ABORT) || (dk_status(chan) & DK_RESET)) {
22338624Skarels dktshut(tp) ;
22438624Skarels return ;
22538624Skarels }
22638624Skarels /* Process input data */
22738624Skarels if (tp->t_state&TS_ISOPEN) {
22838624Skarels cp = dktibuf[tp-dkt];
22938624Skarels count = MLEN - resid ;
23038624Skarels if (count) {
23138624Skarels do {
23238624Skarels /* Should really do parity checking... */
23338624Skarels (*linesw[tp->t_line].l_rint)((*cp++)&0377, tp) ;
23438624Skarels } while (--count);
23538624Skarels }
23638624Skarels if ((c = (rctl & 0377)) != 0) {
23738624Skarels if (chanDEBUG) log(LOG_ERR, "DKT_ctl 0%o on %d\n",c,chan);
23845182Skarels if (c==D_BREAK)
23945182Skarels (*linesw[tp->t_line].l_rint)(TTY_FE, tp) ;
24038624Skarels }
24138624Skarels }
24238624Skarels dktfcon(tp) ;
24338624Skarels }
24438624Skarels
24538624Skarels
24638624Skarels /*
24738624Skarels * Input flow control: queue another receive unless to many chars waiting
24838624Skarels */
dktfcon(tp)24938624Skarels dktfcon(tp)
25038624Skarels register struct tty *tp;
25138624Skarels {
25238624Skarels register int d = tp - dkt;
25338624Skarels register x;
25438624Skarels
25538624Skarels if ((dk_status(d) & (DK_RCV|DK_OPEN)) != DK_OPEN)
25638624Skarels return ;
25738624Skarels if (dktibuf[d] == NULL) return;
25838624Skarels x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
25945182Skarels if (x >= TTYHOG/2 && (!(tp->t_lflag&ICANON) || tp->t_canq.c_cc))
26038624Skarels return;
26138624Skarels (void) dk_recv(d, dktibuf[d], MLEN,
26245182Skarels #ifdef notdef
26338624Skarels DKR_BLOCK | DKR_TIME | (dkt_tmr[tp->t_ispeed]<<8),
26445182Skarels #endif
26545182Skarels DKR_BLOCK | DKR_TIME | (1<<8),
26638624Skarels dktrcv, (caddr_t) tp) ;
26738624Skarels }
26838624Skarels
26938624Skarels /*
27038624Skarels * stty/gtty for DKT
27138624Skarels */
dktioctl(dev,cmd,data,flag)27238624Skarels dktioctl(dev, cmd, data, flag)
27338624Skarels caddr_t data;
27438624Skarels {
27538624Skarels register struct tty *tp;
27638624Skarels int error;
27738624Skarels
27838624Skarels tp = &dkt[minor(dev)];
27938624Skarels error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
28038624Skarels if (error >= 0)
28138624Skarels return error;
28238624Skarels error = ttioctl(tp, cmd, data, flag);
28345184Skarels if (error >= 0)
28438624Skarels return (error);
28538624Skarels
28638624Skarels switch(cmd) {
28738624Skarels case TIOCSBRK:
28838624Skarels dktxpack(tp-dkt, D_BREAK) ;
28938624Skarels return 0;
29038624Skarels case TIOCCBRK:
29138624Skarels return 0;
29238624Skarels }
29338624Skarels return ENOTTY;
29438624Skarels }
29538624Skarels
29638624Skarels /*
29738624Skarels * Start (restart) transmission on the given DKT line.
29838624Skarels */
dktstart(tp)29938624Skarels dktstart(tp)
30038624Skarels register struct tty *tp;
30138624Skarels {
30238624Skarels register d;
30338624Skarels char delay;
30438624Skarels extern dktxdun() ;
30538624Skarels int s, c;
30638624Skarels register int nch;
30738624Skarels register struct mbuf *m;
30838624Skarels extern ttrstrt();
30938624Skarels
31038624Skarels d = tp - dkt;
31138624Skarels s = spl5() ;
31238624Skarels
31338624Skarels #ifdef notdef
31438624Skarels if (dk_status(d) & DK_SPND)
31538624Skarels dk_cmd(d, DKC_RSME) ;
31638624Skarels #endif
31738624Skarels
31838624Skarels if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT))
31938624Skarels goto out;
32038624Skarels
32138624Skarels /*
32238624Skarels * If the writer was sleeping on output overflow,
32338624Skarels * wake the process when low tide is reached.
32438624Skarels */
32545182Skarels if (tp->t_outq.c_cc<=tp->t_lowat) {
32638624Skarels if (tp->t_state&TS_ASLEEP) {
32738624Skarels tp->t_state &= ~TS_ASLEEP;
32838624Skarels wakeup((caddr_t)&tp->t_outq);
32938624Skarels }
33038624Skarels if (tp->t_wsel) {
33138624Skarels selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
33238624Skarels tp->t_wsel = 0;
33338624Skarels tp->t_state &= ~TS_WCOLL;
33438624Skarels }
33538624Skarels }
33638624Skarels /*
33738624Skarels * Now restart transmission unless the output queue is
33838624Skarels * empty.
33938624Skarels */
34038624Skarels if (tp->t_outq.c_cc == 0)
34138624Skarels goto out;
34238624Skarels
34338624Skarels m = m_get(M_DONTWAIT, DKMT_OTTY);
34438624Skarels if (m == NULL) {
34538624Skarels /* No buffers; arrange to retry in .5 seconds */
34638624Skarels dktpaused[d]++;
34738624Skarels tp->t_state |= TS_TIMEOUT;
34838624Skarels timeout(ttrstrt, (caddr_t) tp, hz/2);
34938624Skarels goto out;
35038624Skarels }
35145182Skarels if (1 || !(tp->t_oflag&OPOST))
35238624Skarels nch = ndqb(&tp->t_outq, 0);
35338624Skarels else {
35438624Skarels nch = ndqb(&tp->t_outq, 0200);
35538624Skarels /*
35638624Skarels * If first thing on queue is a delay process it.
35738624Skarels */
35838624Skarels if (nch == 0) {
35938624Skarels nch = getc(&tp->t_outq);
36038624Skarels c = MIN((nch & 0xff) + 6, 0x7f);
36138624Skarels delay = D_DELAY;
36238624Skarels if (tpDEBUG)
36338624Skarels log(LOG_ERR, "DKT_delay %d\n", c) ;
36438624Skarels while (c) {
36538624Skarels delay++;
36638624Skarels c >>= 1;
36738624Skarels }
36838624Skarels if (dk_xmit(d, (struct mbuf *) NULL, 1, delay, dktxdun, (caddr_t) 0))
36938624Skarels tp->t_state |= TS_BUSY;
37038624Skarels (void) m_free(m);
37138624Skarels goto out;
37238624Skarels }
37338624Skarels }
37438624Skarels /*
37538624Skarels * If characters to transmit, restart transmission.
37638624Skarels */
37738624Skarels if (nch) {
37838624Skarels bcopy((caddr_t)tp->t_outq.c_cf, mtod(m, caddr_t), (unsigned) nch);
37938624Skarels m->m_len = nch;
38038624Skarels if (dk_xmit(d, m, 1, 0, dktxdun, (caddr_t) nch))
38138624Skarels tp->t_state |= TS_BUSY;
38238624Skarels }
38338624Skarels else (void) m_free(m);
38438624Skarels out: ;
38538624Skarels splx(s) ;
38638624Skarels }
38738624Skarels
dktxpack(chan,cmd)38838624Skarels dktxpack(chan, cmd)
38938624Skarels char cmd;
39038624Skarels {
39138624Skarels (void) dk_xmit(chan, (struct mbuf *) NULL, 1, cmd, (int (*)()) 0, (caddr_t) 0);
39238624Skarels if (chanDEBUG) log(LOG_ERR, "DKT_sent %o on %d\n",cmd&0377,chan);
39338624Skarels }
39438624Skarels
39538624Skarels /*ARGSUSED*/
dktstop(tp,rw)39638624Skarels dktstop(tp, rw)
39738624Skarels register struct tty *tp;
39838624Skarels {
39938624Skarels register int s, d;
40038624Skarels
40138624Skarels d = tp - dkt;
40238624Skarels s = spl5();
40338624Skarels if (tp->t_state & TS_BUSY) {
40438624Skarels #ifdef notdef
40538624Skarels dk_cmd(d, DKC_SPND);
40638624Skarels #endif
40738624Skarels if ((tp->t_state & TS_TTSTOP) == 0) {
40838624Skarels tp->t_state |= TS_FLUSH;
40938624Skarels dk_cmd(d, DKC_FLUSH);
41038624Skarels }
41138624Skarels }
41238624Skarels splx(s);
41338624Skarels }
41438624Skarels
dktshut(tp)41538624Skarels dktshut(tp)
41638624Skarels register struct tty *tp;
41738624Skarels {
41838624Skarels if (tpDEBUG) log(LOG_ERR, "dktshut %d\n", tp-dkt);
41945184Skarels if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_CARR_ON))
42045184Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0);
42138624Skarels tp->t_state &= ~TS_CARR_ON;
42238624Skarels ttyflush(tp, (FREAD|FWRITE)) ;
42338624Skarels dk_cmd((tp - dkt), DKC_FLUSH);
42438624Skarels }
42538624Skarels
42638624Skarels
dktxdun(cnt,chan)42738624Skarels dktxdun(cnt, chan)
42838624Skarels {
42938624Skarels register struct tty *tp ;
43038624Skarels
43138624Skarels tp = &dkt[chan];
43238624Skarels if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH;
43338624Skarels else ndflush(&tp->t_outq, cnt);
43438624Skarels tp->t_state &= ~TS_BUSY;
43538624Skarels if (tp->t_line)
43638624Skarels (*linesw[tp->t_line].l_start)(tp);
43738624Skarels else
43838624Skarels dktstart(tp);
43938624Skarels }
44038624Skarels #endif
441