xref: /csrg-svn/sys/vax/datakit/dktty.c (revision 49756)
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