xref: /csrg-svn/sys/vax/uba/dmx.c (revision 49759)
138627Smarc /*
238627Smarc  * Copyright (c) 1982, 1986 Regents of the University of California.
338627Smarc  * All rights reserved.  The Berkeley software License Agreement
438627Smarc  * specifies the terms and conditions for redistribution.
538627Smarc  *
6*49759Smarc  *	@(#)dmx.c	7.7 (Berkeley) 05/16/91
738627Smarc  */
838627Smarc 
938627Smarc /*
1038627Smarc  * Common code for DMF32 and DMZ32 drivers
1138627Smarc  */
1238627Smarc #include "dmf.h"
1338627Smarc #include "dmz.h"
1438627Smarc #if NDMF + NDMZ > 0
1538627Smarc 
1645804Sbostic #include "../include/pte.h"
1738627Smarc 
1845804Sbostic #include "sys/param.h"
1938627Smarc #include "uba.h"
2045804Sbostic #include "sys/conf.h"
2145804Sbostic #include "sys/user.h"
2245804Sbostic #include "sys/proc.h"
2345804Sbostic #include "sys/ioctl.h"
2445804Sbostic #include "sys/tty.h"
2545804Sbostic #include "sys/map.h"
2645804Sbostic #include "sys/buf.h"
2745804Sbostic #include "sys/vm.h"
2845804Sbostic #include "sys/clist.h"
2945804Sbostic #include "sys/file.h"
3045804Sbostic #include "sys/uio.h"
3145804Sbostic #include "sys/kernel.h"
3245804Sbostic #include "sys/syslog.h"
3338627Smarc 
3438627Smarc #include "dmx.h"
3538627Smarc #include "ubareg.h"
3638627Smarc #include "ubavar.h"
3738627Smarc #include "dmxreg.h"
3838627Smarc #include "dmreg.h"
3938627Smarc 
4038627Smarc #ifndef	PORTSELECTOR
4139061Smarc #define	ISPEED	TTYDEF_SPEED
4239061Smarc #define	LFLAG	TTYDEF_LFLAG
4338627Smarc #else
4438627Smarc #define	ISPEED	B4800
4539061Smarc #define	IFLAGS	(TTYDEF_LFLAG&~ECHO)
4638627Smarc #endif
4738627Smarc 
4838627Smarc #ifndef DMX_TIMEOUT
4938627Smarc #define DMX_TIMEOUT	10
5038627Smarc #endif
5138627Smarc int	dmx_timeout = DMX_TIMEOUT;		/* silo timeout, in ms */
5238627Smarc int	dmx_mindma = 4;			/* don't dma below this point */
5338627Smarc 
5438627Smarc struct speedtab dmxspeedtab[] = {
5538627Smarc 	0,	0,
5638627Smarc 	75,	1,
5738627Smarc 	110,	2,
5838627Smarc 	134,	3,
5938627Smarc 	150,	4,
6038627Smarc 	300,	5,
6138627Smarc 	600,	6,
6238627Smarc 	1200,	7,
6338627Smarc 	1800,	010,
6438627Smarc 	2400,	012,
6538627Smarc 	4800,	014,
6638627Smarc 	9600,	016,
6738627Smarc 	19200,	017,
6838627Smarc 	EXTA,	017,
6938627Smarc 	-1,	-1
7038627Smarc };
7138627Smarc /*
7238627Smarc  * The clist space is mapped by the drivers onto each UNIBUS.
7338627Smarc  * The UBACVT macro converts a clist space address for unibus uban
7438627Smarc  * into an I/O space address for the DMA routine.
7538627Smarc  */
7638627Smarc int	cbase[NUBA];			/* base address in unibus map */
7738627Smarc #define	UBACVT(x, uban)		(cbase[uban] + ((x)-(char *)cfree))
7838627Smarc 
7938627Smarc int	ttrstrt();
8038627Smarc 
8138627Smarc /*
8238627Smarc  * DMF/DMZ open common code
8338627Smarc  */
dmxopen(tp,sc,flag)8439061Smarc dmxopen(tp, sc, flag)
8538627Smarc 	register struct tty *tp;
8638627Smarc 	register struct dmx_softc *sc;
8738627Smarc {
8840731Skarels 	int s, unit, error = 0;
8938627Smarc 	int dmxparam();
9038627Smarc 
9138627Smarc 	s = spltty();
9238627Smarc 	if ((sc->dmx_flags & DMX_ACTIVE) == 0) {
9338627Smarc 		sc->dmx_octet->csr |= DMF_IE;
9438627Smarc 		sc->dmx_flags |= DMX_ACTIVE;
9538627Smarc 		sc->dmx_octet->rsp = dmx_timeout;
9638627Smarc 	}
9738627Smarc 	splx(s);
9838627Smarc 	if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
9938627Smarc 		return (EBUSY);
10038627Smarc 	/*
10138627Smarc 	 * If this is first open, initialize tty state to default.
10238627Smarc 	 */
10338627Smarc 	if ((tp->t_state&TS_ISOPEN) == 0) {
10444393Smarc 		tp->t_state |= TS_WOPEN;
10538627Smarc 		ttychars(tp);
10638627Smarc #ifndef PORTSELECTOR
10738627Smarc 		if (tp->t_ispeed == 0) {
10839061Smarc #endif
10939061Smarc 			tp->t_iflag = TTYDEF_IFLAG;
11039061Smarc                         tp->t_oflag = TTYDEF_OFLAG;
11139061Smarc                         tp->t_cflag = TTYDEF_CFLAG;
11239061Smarc                         tp->t_lflag = LFLAG;
11339061Smarc                         tp->t_ispeed = tp->t_ospeed = ISPEED;
11439061Smarc #ifdef PORTSELECTOR
11539061Smarc 			tp->t_cflag |= HUPCL;
11638627Smarc #else
11738627Smarc 		}
11839061Smarc #endif
11938627Smarc 	}
12039061Smarc 	dmxparam(tp, &tp->t_termios);
12138627Smarc 
12238627Smarc 	unit = minor(tp->t_dev) & 07;
12338627Smarc 	/*
12438627Smarc 	 * Wait for carrier, then process line discipline specific open.
12538627Smarc 	 */
12638627Smarc 	s = spltty();
12738627Smarc 	for (;;) {
12838627Smarc 		if ((dmxmctl(tp, DMF_ON, DMSET) & DMF_CAR) ||
12938627Smarc 		    (sc->dmx_softCAR & (1 << unit)))
13038627Smarc 			tp->t_state |= TS_CARR_ON;
13139061Smarc 		if (tp->t_state&TS_CARR_ON || flag&O_NONBLOCK ||
13239061Smarc 		    tp->t_cflag&CLOCAL)
13338627Smarc 			break;
13438627Smarc 		tp->t_state |= TS_WOPEN;
13544393Smarc 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
13644393Smarc 		    ttopen, 0))
13740731Skarels 			break;
13838627Smarc 	}
13938627Smarc 	splx(s);
14040731Skarels 	if (error)
14140731Skarels 		return (error);
14238627Smarc 	return ((*linesw[tp->t_line].l_open)(tp->t_dev, tp));
14338627Smarc }
14438627Smarc 
145*49759Smarc dmxclose(tp, flag)
146*49759Smarc 	struct tty *tp;
147*49759Smarc 	int flag;
14838627Smarc {
14938627Smarc 
150*49759Smarc 	(*linesw[tp->t_line].l_close)(tp, flag);
15138627Smarc 	(void) dmxmctl(tp, DMF_BRK, DMBIC);
15239061Smarc 	if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0)
15338627Smarc 		(void) dmxmctl(tp, DMF_OFF, DMSET);
15440731Skarels 	return (ttyclose(tp));
15538627Smarc }
15638627Smarc 
dmxrint(sc)15738627Smarc dmxrint(sc)
15838627Smarc 	register struct dmx_softc *sc;
15938627Smarc {
16039061Smarc 	register c, cc;
16138627Smarc 	register struct tty *tp;
16238627Smarc 	register struct dmx_octet *addr;
16338627Smarc 	int unit;
16438627Smarc 	int overrun = 0;
16538627Smarc 
16638627Smarc 	addr = (struct dmx_octet *)sc->dmx_octet;
16738627Smarc 	/*
16838627Smarc 	 * Loop fetching characters from the silo for this
16938627Smarc 	 * octet until there are no more in the silo.
17038627Smarc 	 */
17138627Smarc 	while ((c = addr->rbuf) < 0) {
17239061Smarc 		cc = c&0xff;
17338627Smarc 		unit = (c >> 8) & 07;
17438627Smarc 		tp = sc->dmx_tty + unit;
17538627Smarc 		if (c & DMF_DSC) {
17638627Smarc 			addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
17738627Smarc 			if (addr->rmstsc & DMF_CAR)
17838627Smarc 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
17938627Smarc 			else if ((sc->dmx_softCAR & (1 << unit)) == 0 &&
18038627Smarc 			    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
18138627Smarc 				addr->csr = DMF_IE | DMFIR_LCR | unit;
18238627Smarc 				addr->lctms = DMF_ENA;
18338627Smarc 			}
18438627Smarc 			continue;
18538627Smarc 		}
18638627Smarc 		if ((tp->t_state&TS_ISOPEN) == 0) {
18738627Smarc 			wakeup((caddr_t)&tp->t_rawq);
18838627Smarc #ifdef PORTSELECTOR
18938627Smarc 			if ((tp->t_state & TS_WOPEN) == 0)
19038627Smarc #endif
19138627Smarc 				continue;
19238627Smarc 		}
19338627Smarc 		if (c & (DMF_PE|DMF_DO|DMF_FE)) {
19438627Smarc 			if (c & DMF_PE)
19539061Smarc 				cc |= TTY_PE;
19638627Smarc 			if ((c & DMF_DO) && overrun == 0) {
19738627Smarc 				log(LOG_WARNING,
19838627Smarc 				    "dm%c%d: silo overflow, line %d\n",
19938627Smarc 				    sc->dmx_type, sc->dmx_unit,
20038627Smarc 				    sc->dmx_unit0 + unit);
20138627Smarc 				overrun = 1;
20238627Smarc 			}
20338627Smarc 			if (c & DMF_FE)
20439061Smarc 				cc |= TTY_FE;
20538627Smarc 		}
20639061Smarc 		(*linesw[tp->t_line].l_rint)(cc, tp);
20738627Smarc 	}
20838627Smarc }
20938627Smarc 
dmxioctl(tp,cmd,data,flag)21038627Smarc dmxioctl(tp, cmd, data, flag)
21138627Smarc 	register struct tty *tp;
21238627Smarc 	caddr_t data;
21338627Smarc {
21438627Smarc 	int error;
21538627Smarc 
21638627Smarc 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
21738627Smarc 	if (error >= 0)
21838627Smarc 		return (error);
21938627Smarc 	error = ttioctl(tp, cmd, data, flag);
22039061Smarc 	if (error >= 0)
22138627Smarc 		return (error);
22239061Smarc 
22338627Smarc 	switch (cmd) {
22438627Smarc 
22538627Smarc 	case TIOCSBRK:
22638627Smarc 		(void) dmxmctl(tp, DMF_BRK, DMBIS);
22738627Smarc 		break;
22838627Smarc 
22938627Smarc 	case TIOCCBRK:
23038627Smarc 		(void) dmxmctl(tp, DMF_BRK, DMBIC);
23138627Smarc 		break;
23238627Smarc 
23338627Smarc 	case TIOCSDTR:
23438627Smarc 		(void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIS);
23538627Smarc 		break;
23638627Smarc 
23738627Smarc 	case TIOCCDTR:
23838627Smarc 		(void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIC);
23938627Smarc 		break;
24038627Smarc 
24138627Smarc 	case TIOCMSET:
24238627Smarc 		(void) dmxmctl(tp, dmtodmx(*(int *)data), DMSET);
24338627Smarc 		break;
24438627Smarc 
24538627Smarc 	case TIOCMBIS:
24638627Smarc 		(void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIS);
24738627Smarc 		break;
24838627Smarc 
24938627Smarc 	case TIOCMBIC:
25038627Smarc 		(void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIC);
25138627Smarc 		break;
25238627Smarc 
25338627Smarc 	case TIOCMGET:
25438627Smarc 		*(int *)data = dmxmctl(tp, 0, DMGET);
25538627Smarc 		break;
25638627Smarc 
25738627Smarc 	default:
25838627Smarc 		return (ENOTTY);
25938627Smarc 	}
26038627Smarc 	return (0);
26138627Smarc }
26238627Smarc 
26338627Smarc /*
26438627Smarc  * modem control
26538627Smarc  * "bits" are dmf/dmz lcr format;
26638627Smarc  * return of DMGET is DM11 format.
26738627Smarc  */
26838627Smarc dmxmctl(tp, bits, how)
26938627Smarc 	struct tty *tp;
27038627Smarc 	int bits, how;
27138627Smarc {
27238627Smarc 	register struct dmx_octet *addr;
27338627Smarc 	register int unit, mbits, lcr;
27438627Smarc 	int s;
27538627Smarc 
27638627Smarc 	unit = minor(tp->t_dev) & 07;
27738627Smarc 	addr = (struct dmx_octet *)(tp->t_addr);
27838627Smarc 
27938627Smarc 	s = spltty();
28038627Smarc 	addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
28138627Smarc 	mbits = addr->rmstsc & 0xff00;
28238627Smarc 	addr->csr = DMF_IE | DMFIR_LCR | unit;
28338627Smarc 	lcr = addr->lctms;
28438627Smarc 
28538627Smarc 	switch (how) {
28638627Smarc 	case DMSET:
28738627Smarc 		lcr = bits;
28838627Smarc 		break;
28938627Smarc 
29038627Smarc 	case DMBIS:
29138627Smarc 		lcr |= bits;
29238627Smarc 		break;
29338627Smarc 
29438627Smarc 	case DMBIC:
29538627Smarc 		lcr &= ~bits;
29638627Smarc 		break;
29738627Smarc 
29838627Smarc 	case DMGET:
29938627Smarc 		splx(s);
30038627Smarc 		return (dmxtodm(mbits, lcr));
30138627Smarc 	}
30238627Smarc 	addr->lctms = lcr;
30338627Smarc 	(void) splx(s);
30438627Smarc 	return (mbits);
30538627Smarc }
30638627Smarc 
30738627Smarc /*
30838627Smarc  * Routine to convert modem status from dm to dmf/dmz lctmr format.
30938627Smarc  */
dmtodmx(bits)31038627Smarc dmtodmx(bits)
31138627Smarc 	register int bits;
31238627Smarc {
31338627Smarc 	register int lcr = DMF_ENA;
31438627Smarc 
31538627Smarc 	if (bits & DML_DTR)
31638627Smarc 		lcr |= DMF_DTR;
31738627Smarc 	if (bits & DML_RTS)
31838627Smarc 		lcr |= DMF_RTS;
31938627Smarc 	if (bits & DML_ST)
32038627Smarc 		lcr |= DMF_SRTS;
32138627Smarc 	if (bits & DML_USR)
32238627Smarc 		lcr |= DMF_USRW;
32338627Smarc 	return (lcr);
32438627Smarc }
32538627Smarc 
32638627Smarc /*
32738627Smarc  * Routine to convert modem status from dmf/dmz receive modem status
32838627Smarc  * and line control register to dm format.
32938627Smarc  * If dmf/dmz user modem read bit set, set DML_USR.
33038627Smarc  */
dmxtodm(mstat,lcr)33138627Smarc dmxtodm(mstat, lcr)
33238627Smarc 	register int mstat, lcr;
33338627Smarc {
33438627Smarc 
33538627Smarc 	mstat = ((mstat & (DMF_DSR|DMF_RNG|DMF_CAR|DMF_CTS|DMF_SR)) >> 7) |
33638627Smarc 		((mstat & DMF_USRR) >> 1) | DML_LE;
33738627Smarc 	if (lcr & DMF_DTR)
33838627Smarc 		mstat |= DML_DTR;
33938627Smarc 	if (lcr & DMF_SRTS)
34038627Smarc 		mstat |= DML_ST;
34138627Smarc 	if (lcr & DMF_RTS)
34238627Smarc 		mstat |= DML_RTS;
34338627Smarc 	return (mstat);
34438627Smarc }
34538627Smarc 
34638627Smarc 
34738627Smarc /*
34838627Smarc  * Set parameters from open or ioctl into the hardware registers.
34938627Smarc  */
dmxparam(tp,t)35039061Smarc dmxparam(tp, t)
35138627Smarc 	register struct tty *tp;
35239061Smarc 	register struct termios *t;
35338627Smarc {
35438627Smarc 	register struct dmx_octet *addr;
35538627Smarc 	register int lpar, lcr;
35639061Smarc 	register int cflag = t->c_cflag;
35738627Smarc 	int s, unit;
35839061Smarc 	int ispeed = ttspeedtab(t->c_ispeed, dmxspeedtab);
35939061Smarc         int ospeed = ttspeedtab(t->c_ospeed, dmxspeedtab);
36038627Smarc 
36139061Smarc         /* check requested parameters */
36239061Smarc         if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5)
36339061Smarc                 return(EINVAL);
36439061Smarc         if (ispeed == 0)
36539061Smarc                 ispeed = ospeed;
36639061Smarc         /* and copy to tty */
36739061Smarc         tp->t_ispeed = t->c_ispeed;
36839061Smarc         tp->t_ospeed = t->c_ospeed;
36939061Smarc         tp->t_cflag = cflag;
37039061Smarc 
37138627Smarc 	addr = (struct dmx_octet *)tp->t_addr;
37238627Smarc 	unit = minor(tp->t_dev) & 07;
37338627Smarc 	/*
37438627Smarc 	 * Block interrupts so parameters will be set
37538627Smarc 	 * before the line interrupts.
37638627Smarc 	 */
37738627Smarc 	s = spltty();
37838627Smarc 	addr->csr = unit | DMFIR_LCR | DMF_IE;
37939061Smarc 	if (ospeed == 0) {
38039061Smarc 		tp->t_cflag |= HUPCL;
38138627Smarc 		(void) dmxmctl(tp, DMF_OFF, DMSET);
38238627Smarc 		splx(s);
38338627Smarc 		return;
38438627Smarc 	}
38539061Smarc 	lpar = (ospeed<<12) | (ispeed<<8);
38638627Smarc 	lcr = DMF_ENA;
38739061Smarc 	switch (cflag&CSIZE) {
38839061Smarc         case CS6:       lpar |= BITS6; break;
38939061Smarc         case CS7:       lpar |= BITS7; break;
39039061Smarc         case CS8:       lpar |= BITS8; break;
39139061Smarc         }
39239061Smarc         if (cflag&PARENB)
39339061Smarc                 lpar |= PENABLE;
39439061Smarc         if (!(cflag&PARODD))
39539061Smarc                 lpar |= EPAR;
39639061Smarc         if (cflag&CSTOPB)
39739061Smarc                 lpar |= TWOSB;
39839061Smarc 
39938627Smarc 	lpar |= (unit&07);
40038627Smarc 	addr->lpr = lpar;
40138627Smarc 	addr->lctms = (addr->lctms &~ 0xff) | lcr;
40238627Smarc 	splx(s);
40339061Smarc 	return 0;
40438627Smarc }
40538627Smarc 
40638627Smarc /*
40738627Smarc  * Process a transmit interrupt on an octet.
40838627Smarc  */
dmxxint(sc)40938627Smarc dmxxint(sc)
41038627Smarc 	register struct dmx_softc *sc;
41138627Smarc {
41238627Smarc 	register struct tty *tp;
41338627Smarc 	register struct dmx_octet *addr;
41438627Smarc 	register int t;
41538627Smarc 
41638627Smarc 	addr = (struct dmx_octet *)sc->dmx_octet;
41738627Smarc 	while ((t = addr->csr) & DMF_TI) {
41838627Smarc 		if (t & DMF_NXM)
41938627Smarc 			/* SHOULD RESTART OR SOMETHING... */
42038627Smarc 			printf("dm%c%d: NXM line %d\n", sc->dmx_type,
42138627Smarc 			    sc->dmx_unit, sc->dmx_unit0 + (t >> 8 & 7));
42238627Smarc 		t = t >> 8 & 7;
42338627Smarc 		tp = sc->dmx_tty + t;
42438627Smarc 		tp->t_state &= ~TS_BUSY;
42538627Smarc 		if (tp->t_state & TS_FLUSH)
42638627Smarc 			tp->t_state &= ~TS_FLUSH;
42738627Smarc #define new
42838627Smarc #ifndef new
42938627Smarc 		else if (sc->dmx_dmacount[t]) {
43038627Smarc 			short cntr;
43138627Smarc 
43238627Smarc 			/*
43338627Smarc 			 * Do arithmetic in a short to make up
43438627Smarc 			 * for lost 16&17 bits.
43538627Smarc 			 */
43638627Smarc 			addr->csr = DMFIR_TBA | DMF_IE | t;
43738627Smarc 			cntr = addr->tba -
43838627Smarc 			    UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
43938627Smarc 			ndflush(&tp->t_outq, (int)cntr);
44038627Smarc 		}
44138627Smarc #else
44238627Smarc 		else if (sc->dmx_dmacount[t])
44338627Smarc 			ndflush(&tp->t_outq, sc->dmx_dmacount[t]);
44438627Smarc 		sc->dmx_dmacount[t] = 0;
44538627Smarc #endif
44638627Smarc 		(*linesw[tp->t_line].l_start)(tp);
44738627Smarc 	}
44838627Smarc }
44938627Smarc 
dmxstart(tp,sc)45038627Smarc dmxstart(tp, sc)
45138627Smarc 	register struct tty *tp;
45238627Smarc 	struct dmx_softc *sc;
45338627Smarc {
45438627Smarc 	register struct dmx_octet *addr;
45538627Smarc 	register int unit, nch;
45638627Smarc 	int s;
45738627Smarc 
45838627Smarc 	unit = minor(tp->t_dev) & 07;
45938627Smarc 	addr = (struct dmx_octet *)tp->t_addr;
46038627Smarc 
46138627Smarc 	/*
46238627Smarc 	 * Must hold interrupts in following code to prevent
46338627Smarc 	 * state of the tp from changing.
46438627Smarc 	 */
46538627Smarc 	s = spltty();
46638627Smarc 	/*
46738627Smarc 	 * If it's currently active, or delaying, no need to do anything.
46838627Smarc 	 */
46938627Smarc 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
47038627Smarc 		goto out;
47138627Smarc 	/*
47238627Smarc 	 * If there are still characters to dma or in the silo,
47338627Smarc 	 * just reenable the transmitter.
47438627Smarc 	 */
47538627Smarc 	addr->csr = DMF_IE | DMFIR_TBUF | unit;
47638627Smarc #ifdef new
47738627Smarc 	if (addr->tsc || sc->dmx_dmacount[unit]) {
47838627Smarc #else
47938627Smarc 	if (addr->tsc) {
48038627Smarc #endif
48138627Smarc 		addr->csr = DMF_IE | DMFIR_LCR | unit;
48238627Smarc 		addr->lctms = addr->lctms | DMF_TE;
48338627Smarc 		tp->t_state |= TS_BUSY;
48438627Smarc 		goto out;
48538627Smarc 	}
48638627Smarc 	/*
48738627Smarc 	 * If there are sleepers, and output has drained below low
48838627Smarc 	 * water mark, wake up the sleepers.
48938627Smarc 	 */
49039061Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
49138627Smarc 		if (tp->t_state & TS_ASLEEP) {
49238627Smarc 			tp->t_state &= ~TS_ASLEEP;
49338627Smarc 			wakeup((caddr_t)&tp->t_outq);
49438627Smarc 		}
49538627Smarc 		if (tp->t_wsel) {
49638627Smarc 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
49738627Smarc 			tp->t_wsel = 0;
49838627Smarc 			tp->t_state &= ~TS_WCOLL;
49938627Smarc 		}
50038627Smarc 	}
50138627Smarc 	/*
50238627Smarc 	 * Now restart transmission unless the output queue is
50338627Smarc 	 * empty.
50438627Smarc 	 */
50538627Smarc 	if (tp->t_outq.c_cc == 0)
50638627Smarc 		goto out;
50739061Smarc 	if (1 || !(tp->t_oflag&OPOST))	/*XXX*/
50838627Smarc 		nch = ndqb(&tp->t_outq, 0);
50938627Smarc 	else {
51038627Smarc 		if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
51138627Smarc 			/*
51238627Smarc 		 	* If first thing on queue is a delay process it.
51338627Smarc 		 	*/
51438627Smarc 			nch = getc(&tp->t_outq);
51538627Smarc 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
51638627Smarc 			tp->t_state |= TS_TIMEOUT;
51738627Smarc 			goto out;
51838627Smarc 		}
51938627Smarc 	}
52038627Smarc 	/*
52138627Smarc 	 * If characters to transmit, restart transmission.
52238627Smarc 	 */
52338627Smarc 	if (nch >= dmx_mindma) {
52438627Smarc 		register car;
52538627Smarc 
52638627Smarc 		sc->dmx_dmacount[unit] = nch;
52738627Smarc 		addr->csr = DMF_IE | DMFIR_LCR | unit;
52838627Smarc 		addr->lctms = addr->lctms | DMF_TE;
52938627Smarc 		car = UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
53038627Smarc 		addr->csr = DMF_IE | DMFIR_TBA | unit;
53138627Smarc 		addr->tba = car;
53238627Smarc 		addr->tcc = ((car >> 2) & 0xc000) | nch;
53338627Smarc 		tp->t_state |= TS_BUSY;
53438627Smarc 	} else if (nch) {
53538627Smarc 		register char *cp = tp->t_outq.c_cf;
53638627Smarc 		register int i;
53738627Smarc 
53838627Smarc #ifndef new
53938627Smarc 		sc->dmx_dmacount[unit] = 0;
54038627Smarc #endif
54138627Smarc 		nch = MIN(nch, DMF_SILOCNT);
54238627Smarc 		addr->csr = DMF_IE | DMFIR_LCR | unit;
54338627Smarc 		addr->lctms = addr->lctms | DMF_TE;
54438627Smarc 		addr->csr = DMF_IE | DMFIR_TBUF | unit;
54538627Smarc 		for (i = 0; i < nch; i++)
54638627Smarc 			addr->tbuf = *cp++;
54738627Smarc 		ndflush(&tp->t_outq, nch);
54838627Smarc 		tp->t_state |= TS_BUSY;
54938627Smarc 	}
55038627Smarc out:
55138627Smarc 	splx(s);
55238627Smarc }
55338627Smarc 
dmxstop(tp,sc,flag)55438627Smarc dmxstop(tp, sc, flag)
55538627Smarc 	register struct tty *tp;
55638627Smarc 	struct dmx_softc *sc;
55738627Smarc {
55838627Smarc 	register struct dmx_octet *addr;
55938627Smarc 	register unit = minor(tp->t_dev) & 7;
56038627Smarc 	int s;
56138627Smarc 
56238627Smarc 	addr = (struct dmx_octet *)tp->t_addr;
56338627Smarc 	/*
56438627Smarc 	 * Block input/output interrupts while messing with state.
56538627Smarc 	 */
56638627Smarc 	s = spltty();
56738627Smarc 	if (flag) {
56838627Smarc 		addr->csr = DMF_IE | DMFIR_TBUF | unit;
56938627Smarc 		if (addr->tsc) {
57038627Smarc 			/*
57138627Smarc 			 * Flush regardless of whether we're transmitting
57238627Smarc 			 * (TS_BUSY), if the silo contains untransmitted
57338627Smarc 			 * characters.
57438627Smarc 			 */
57538627Smarc 			addr->csr = DMFIR_LCR | unit | DMF_IE;
57638627Smarc 			addr->lctms = addr->lctms | DMF_TE | DMF_FLUSH;
57738627Smarc 			/* this will interrupt so let dmxxint handle the rest */
57838627Smarc 			tp->t_state |= TS_FLUSH|TS_BUSY;
57938627Smarc 		}
58038627Smarc /*#ifdef new*/
58138627Smarc 		sc->dmx_dmacount[unit] = 0;
58238627Smarc /*#endif*/
58338627Smarc 	} else {
58438627Smarc 		/*
58538627Smarc 		 * Stop transmission by disabling
58638627Smarc 		 * the transmitter.  We'll pick up where we
58738627Smarc 		 * left off by reenabling in dmxstart.
58838627Smarc 		 */
58938627Smarc 		addr->csr = DMFIR_LCR | unit | DMF_IE;
59038627Smarc 		addr->lctms = addr->lctms &~ DMF_TE;
59138627Smarc 		/* no interrupt here */
59238627Smarc 		tp->t_state &= ~TS_BUSY;
59338627Smarc 	}
59438627Smarc 	splx(s);
59538627Smarc }
59638627Smarc #endif NDMF + NDMZ
597