xref: /csrg-svn/sys/pmax/dev/dc.c (revision 67477)
156819Sralph /*-
263205Sbostic  * Copyright (c) 1992, 1993
363205Sbostic  *	The Regents of the University of California.  All rights reserved.
452130Smckusick  *
552130Smckusick  * This code is derived from software contributed to Berkeley by
656819Sralph  * Ralph Campbell and Rick Macklem.
756819Sralph  *
856819Sralph  * %sccs.include.redist.c%
956819Sralph  *
10*67477Smckusick  *	@(#)dc.c	8.3 (Berkeley) 07/03/94
1152693Sralph  */
1252693Sralph 
1352693Sralph /*
1452130Smckusick  * devDC7085.c --
1552130Smckusick  *
1652130Smckusick  *     	This file contains machine-dependent routines that handle the
1752130Smckusick  *	output queue for the serial lines.
1852130Smckusick  *
1952130Smckusick  *	Copyright (C) 1989 Digital Equipment Corporation.
2052130Smckusick  *	Permission to use, copy, modify, and distribute this software and
2152130Smckusick  *	its documentation for any purpose and without fee is hereby granted,
2252130Smckusick  *	provided that the above copyright notice appears in all copies.
2352130Smckusick  *	Digital Equipment Corporation makes no representations about the
2452130Smckusick  *	suitability of this software for any purpose.  It is provided "as is"
2552130Smckusick  *	without express or implied warranty.
2652130Smckusick  *
2752130Smckusick  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c,
2852130Smckusick  *	v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)";
2952130Smckusick  */
3052130Smckusick 
3156819Sralph #include <dc.h>
3252130Smckusick #if NDC > 0
3352130Smckusick /*
3452130Smckusick  * DC7085 (DZ-11 look alike) Driver
3552130Smckusick  */
3656522Sbostic #include <sys/param.h>
3756522Sbostic #include <sys/systm.h>
3856522Sbostic #include <sys/ioctl.h>
3956522Sbostic #include <sys/tty.h>
4056522Sbostic #include <sys/proc.h>
4156522Sbostic #include <sys/map.h>
4256522Sbostic #include <sys/buf.h>
4356522Sbostic #include <sys/conf.h>
4456522Sbostic #include <sys/file.h>
4556522Sbostic #include <sys/uio.h>
4656522Sbostic #include <sys/kernel.h>
4756522Sbostic #include <sys/syslog.h>
4852130Smckusick 
4956522Sbostic #include <machine/dc7085cons.h>
5056819Sralph #include <machine/pmioctl.h>
5152130Smckusick 
5256819Sralph #include <pmax/pmax/pmaxtype.h>
5356819Sralph #include <pmax/pmax/cons.h>
5456819Sralph 
5556525Sbostic #include <pmax/dev/device.h>
5656525Sbostic #include <pmax/dev/pdma.h>
5756819Sralph #include <pmax/dev/fbreg.h>
5852130Smckusick 
5956819Sralph extern int pmax_boardtype;
6056819Sralph extern struct consdev cn_tab;
6156819Sralph 
6252130Smckusick /*
6352130Smckusick  * Driver information for auto-configuration stuff.
6452130Smckusick  */
6552130Smckusick int	dcprobe();
6652693Sralph void	dcintr();
6752130Smckusick struct	driver dcdriver = {
6852693Sralph 	"dc", dcprobe, 0, 0, dcintr,
6952130Smckusick };
7052130Smckusick 
7152130Smckusick #define	NDCLINE 	(NDC*4)
7252130Smckusick 
7356819Sralph void dcstart	__P((struct tty *));
7456819Sralph void dcxint	__P((struct tty *));
7556819Sralph void dcPutc	__P((dev_t, int));
7656819Sralph void dcscan	__P((void *));
7756226Sralph extern void ttrstrt __P((void *));
7856819Sralph int dcGetc	__P((dev_t));
7956819Sralph int dcparam	__P((struct tty *, struct termios *));
8052130Smckusick 
8152130Smckusick struct	tty dc_tty[NDCLINE];
8252130Smckusick int	dc_cnt = NDCLINE;
8352863Sralph void	(*dcDivertXInput)();	/* X windows keyboard input routine */
8452863Sralph void	(*dcMouseEvent)();	/* X windows mouse motion event routine */
8552863Sralph void	(*dcMouseButtons)();	/* X windows mouse buttons event routine */
8652130Smckusick #ifdef DEBUG
8752130Smckusick int	debugChar;
8852130Smckusick #endif
8952130Smckusick 
9052130Smckusick /*
9152130Smckusick  * Software copy of brk register since it isn't readable
9252130Smckusick  */
9352130Smckusick int	dc_brk[NDC];
9452130Smckusick char	dcsoftCAR[NDC];		/* mask of dc's with carrier on (DSR) */
9552130Smckusick 
9652130Smckusick /*
9752130Smckusick  * The DC7085 doesn't interrupt on carrier transitions, so
9852130Smckusick  * we have to use a timer to watch it.
9952130Smckusick  */
10052130Smckusick int	dc_timer;		/* true if timer started */
10152130Smckusick 
10252130Smckusick /*
10352130Smckusick  * Pdma structures for fast output code
10452130Smckusick  */
10552130Smckusick struct	pdma dcpdma[NDCLINE];
10652130Smckusick 
10752130Smckusick struct speedtab dcspeedtab[] = {
10852130Smckusick 	0,	0,
10952130Smckusick 	50,	LPR_B50,
11052130Smckusick 	75,	LPR_B75,
11152130Smckusick 	110,	LPR_B110,
11252130Smckusick 	134,	LPR_B134,
11352130Smckusick 	150,	LPR_B150,
11452130Smckusick 	300,	LPR_B300,
11552130Smckusick 	600,	LPR_B600,
11652130Smckusick 	1200,	LPR_B1200,
11752130Smckusick 	1800,	LPR_B1800,
11852130Smckusick 	2400,	LPR_B2400,
11952130Smckusick 	4800,	LPR_B4800,
12052130Smckusick 	9600,	LPR_B9600,
12152693Sralph 	19200,	LPR_B19200,
12252130Smckusick 	-1,	-1
12352130Smckusick };
12452130Smckusick 
12552130Smckusick #ifndef	PORTSELECTOR
12652130Smckusick #define	ISPEED	TTYDEF_SPEED
12752130Smckusick #define	LFLAG	TTYDEF_LFLAG
12852130Smckusick #else
12952130Smckusick #define	ISPEED	B4800
13052130Smckusick #define	LFLAG	(TTYDEF_LFLAG & ~ECHO)
13152130Smckusick #endif
13252130Smckusick 
13352130Smckusick /*
13452130Smckusick  * Test to see if device is present.
13552130Smckusick  * Return true if found and initialized ok.
13652130Smckusick  */
13752130Smckusick dcprobe(cp)
13852130Smckusick 	register struct pmax_ctlr *cp;
13952130Smckusick {
14052130Smckusick 	register dcregs *dcaddr;
14152130Smckusick 	register struct pdma *pdp;
14252130Smckusick 	register struct tty *tp;
14352130Smckusick 	register int cntr;
14456819Sralph 	int s;
14552130Smckusick 
14652130Smckusick 	if (cp->pmax_unit >= NDC)
14752130Smckusick 		return (0);
14852130Smckusick 	if (badaddr(cp->pmax_addr, 2))
14952130Smckusick 		return (0);
15052130Smckusick 
15157234Sralph 	/*
15257234Sralph 	 * For a remote console, wait a while for previous output to
15357234Sralph 	 * complete.
15457234Sralph 	 */
15557234Sralph 	if (major(cn_tab.cn_dev) == DCDEV && cp->pmax_unit == 0 &&
15657234Sralph 		cn_tab.cn_screen == 0)
15757234Sralph 		DELAY(10000);
15857234Sralph 
15952130Smckusick 	/* reset chip */
16052130Smckusick 	dcaddr = (dcregs *)cp->pmax_addr;
16152130Smckusick 	dcaddr->dc_csr = CSR_CLR;
16252130Smckusick 	MachEmptyWriteBuffer();
16352130Smckusick 	while (dcaddr->dc_csr & CSR_CLR)
16452130Smckusick 		;
16552130Smckusick 	dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE;
16652130Smckusick 
16752130Smckusick 	/* init pseudo DMA structures */
16852130Smckusick 	pdp = &dcpdma[cp->pmax_unit * 4];
16952130Smckusick 	tp = &dc_tty[cp->pmax_unit * 4];
17052130Smckusick 	for (cntr = 0; cntr < 4; cntr++) {
17156819Sralph 		pdp->p_addr = (void *)dcaddr;
17252130Smckusick 		pdp->p_arg = (int)tp;
17352130Smckusick 		pdp->p_fcn = dcxint;
17452130Smckusick 		pdp++, tp++;
17552130Smckusick 	}
17652130Smckusick 	dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB;
17752130Smckusick 
17852130Smckusick 	if (dc_timer == 0) {
17952130Smckusick 		dc_timer = 1;
18055744Sralph 		timeout(dcscan, (void *)0, hz);
18152130Smckusick 	}
18256819Sralph 
18356819Sralph 	/*
18456819Sralph 	 * Special handling for consoles.
18556819Sralph 	 */
18652130Smckusick 	if (cp->pmax_unit == 0) {
18756819Sralph 		if (cn_tab.cn_screen) {
18856819Sralph 			s = spltty();
18956819Sralph 			dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
19056819Sralph 				LPR_B4800 | DCKBD_PORT;
19158975Sralph 			MachEmptyWriteBuffer();
19256819Sralph 			dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
19356819Sralph 				LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT;
19456819Sralph 			MachEmptyWriteBuffer();
19557234Sralph 			DELAY(1000);
19656819Sralph 			KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc);
19756819Sralph 			MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc);
19856819Sralph 			splx(s);
19956819Sralph 		} else if (major(cn_tab.cn_dev) == DCDEV) {
20056819Sralph 			s = spltty();
20156819Sralph 			dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
20256819Sralph 				LPR_B9600 | minor(cn_tab.cn_dev);
20356819Sralph 			MachEmptyWriteBuffer();
20457234Sralph 			DELAY(1000);
20556819Sralph 			cn_tab.cn_disabled = 0;
20656819Sralph 			splx(s);
20756819Sralph 		}
20852130Smckusick 	}
20957234Sralph 	printf("dc%d at nexus0 csr 0x%x priority %d\n",
21057234Sralph 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
21152130Smckusick 	return (1);
21252130Smckusick }
21352130Smckusick 
21454146Sralph dcopen(dev, flag, mode, p)
21552130Smckusick 	dev_t dev;
21654146Sralph 	int flag, mode;
21754146Sralph 	struct proc *p;
21852130Smckusick {
21952130Smckusick 	register struct tty *tp;
22052130Smckusick 	register int unit;
22152130Smckusick 	int s, error = 0;
22252130Smckusick 
22352130Smckusick 	unit = minor(dev);
22456819Sralph 	if (unit >= dc_cnt || dcpdma[unit].p_addr == (void *)0)
22552130Smckusick 		return (ENXIO);
22652130Smckusick 	tp = &dc_tty[unit];
22752130Smckusick 	tp->t_oproc = dcstart;
22852130Smckusick 	tp->t_param = dcparam;
22952130Smckusick 	tp->t_dev = dev;
23052130Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
23152130Smckusick 		tp->t_state |= TS_WOPEN;
23252130Smckusick 		ttychars(tp);
23352130Smckusick #ifndef PORTSELECTOR
23452130Smckusick 		if (tp->t_ispeed == 0) {
23552130Smckusick #endif
23652130Smckusick 			tp->t_iflag = TTYDEF_IFLAG;
23752130Smckusick 			tp->t_oflag = TTYDEF_OFLAG;
23852130Smckusick 			tp->t_cflag = TTYDEF_CFLAG;
23952130Smckusick 			tp->t_lflag = LFLAG;
24052130Smckusick 			tp->t_ispeed = tp->t_ospeed = ISPEED;
24152130Smckusick #ifdef PORTSELECTOR
24252130Smckusick 			tp->t_cflag |= HUPCL;
24352130Smckusick #else
24452130Smckusick 		}
24552130Smckusick #endif
24652130Smckusick 		(void) dcparam(tp, &tp->t_termios);
24752130Smckusick 		ttsetwater(tp);
24852130Smckusick 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
24952130Smckusick 		return (EBUSY);
250*67477Smckusick 	(void) dcmctl(dev, DML_DTR | DML_RTS, DMSET);
25152130Smckusick 	s = spltty();
25252130Smckusick 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
25352130Smckusick 	       !(tp->t_state & TS_CARR_ON)) {
25452130Smckusick 		tp->t_state |= TS_WOPEN;
25552130Smckusick 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
25652130Smckusick 		    ttopen, 0))
25752130Smckusick 			break;
25852130Smckusick 	}
25952130Smckusick 	splx(s);
26052130Smckusick 	if (error)
26152130Smckusick 		return (error);
26252130Smckusick 	return ((*linesw[tp->t_line].l_open)(dev, tp));
26352130Smckusick }
26452130Smckusick 
26552130Smckusick /*ARGSUSED*/
26654146Sralph dcclose(dev, flag, mode, p)
26752130Smckusick 	dev_t dev;
26854146Sralph 	int flag, mode;
26954146Sralph 	struct proc *p;
27052130Smckusick {
27152130Smckusick 	register struct tty *tp;
27252130Smckusick 	register int unit, bit;
27352130Smckusick 
27452130Smckusick 	unit = minor(dev);
27552130Smckusick 	tp = &dc_tty[unit];
27652130Smckusick 	bit = 1 << ((unit & 03) + 8);
27752130Smckusick 	if (dc_brk[unit >> 2] & bit) {
27852130Smckusick 		dc_brk[unit >> 2] &= ~bit;
27952130Smckusick 		ttyoutput(0, tp);
28052130Smckusick 	}
28154146Sralph 	(*linesw[tp->t_line].l_close)(tp, flag);
28252130Smckusick 	if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
28352130Smckusick 	    !(tp->t_state & TS_ISOPEN))
28452130Smckusick 		(void) dcmctl(dev, 0, DMSET);
28552130Smckusick 	return (ttyclose(tp));
28652130Smckusick }
28752130Smckusick 
28852130Smckusick dcread(dev, uio, flag)
28952130Smckusick 	dev_t dev;
29052130Smckusick 	struct uio *uio;
29152130Smckusick {
29252130Smckusick 	register struct tty *tp;
29352130Smckusick 
29452130Smckusick 	tp = &dc_tty[minor(dev)];
295*67477Smckusick 	if ((tp->t_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK) &&
296*67477Smckusick 	    tp->t_rawq.c_cc < TTYHOG/5) {
297*67477Smckusick 		tp->t_state &= ~TS_TBLOCK;
298*67477Smckusick 		(void) dcmctl(dev, DML_RTS, DMBIS);
299*67477Smckusick 	}
30052130Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
30152130Smckusick }
30252130Smckusick 
30352130Smckusick dcwrite(dev, uio, flag)
30452130Smckusick 	dev_t dev;
30552130Smckusick 	struct uio *uio;
30652130Smckusick {
30752130Smckusick 	register struct tty *tp;
30852130Smckusick 
30952130Smckusick 	tp = &dc_tty[minor(dev)];
31052130Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
31152130Smckusick }
31252130Smckusick 
31352130Smckusick /*ARGSUSED*/
31454146Sralph dcioctl(dev, cmd, data, flag, p)
31552130Smckusick 	dev_t dev;
31656819Sralph 	int cmd;
31752130Smckusick 	caddr_t data;
31854146Sralph 	int flag;
31954146Sralph 	struct proc *p;
32052130Smckusick {
32152130Smckusick 	register struct tty *tp;
32252130Smckusick 	register int unit = minor(dev);
32352130Smckusick 	register int dc = unit >> 2;
32452130Smckusick 	int error;
32552130Smckusick 
32652130Smckusick 	tp = &dc_tty[unit];
32754146Sralph 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
32852130Smckusick 	if (error >= 0)
32952130Smckusick 		return (error);
33052130Smckusick 	error = ttioctl(tp, cmd, data, flag);
33152130Smckusick 	if (error >= 0)
33252130Smckusick 		return (error);
33352130Smckusick 
33452130Smckusick 	switch (cmd) {
33552130Smckusick 
33652130Smckusick 	case TIOCSBRK:
33752130Smckusick 		dc_brk[dc] |= 1 << ((unit & 03) + 8);
33852130Smckusick 		ttyoutput(0, tp);
33952130Smckusick 		break;
34052130Smckusick 
34152130Smckusick 	case TIOCCBRK:
34252130Smckusick 		dc_brk[dc] &= ~(1 << ((unit & 03) + 8));
34352130Smckusick 		ttyoutput(0, tp);
34452130Smckusick 		break;
34552130Smckusick 
34652130Smckusick 	case TIOCSDTR:
347*67477Smckusick 		(void) dcmctl(dev, DML_DTR | DML_RTS, DMBIS);
34852130Smckusick 		break;
34952130Smckusick 
35052130Smckusick 	case TIOCCDTR:
351*67477Smckusick 		(void) dcmctl(dev, DML_DTR | DML_RTS, DMBIC);
35252130Smckusick 		break;
35352130Smckusick 
35452130Smckusick 	case TIOCMSET:
35552130Smckusick 		(void) dcmctl(dev, *(int *)data, DMSET);
35652130Smckusick 		break;
35752130Smckusick 
35852130Smckusick 	case TIOCMBIS:
35952130Smckusick 		(void) dcmctl(dev, *(int *)data, DMBIS);
36052130Smckusick 		break;
36152130Smckusick 
36252130Smckusick 	case TIOCMBIC:
36352130Smckusick 		(void) dcmctl(dev, *(int *)data, DMBIC);
36452130Smckusick 		break;
36552130Smckusick 
36652130Smckusick 	case TIOCMGET:
36752130Smckusick 		*(int *)data = dcmctl(dev, 0, DMGET);
36852130Smckusick 		break;
36952130Smckusick 
37052130Smckusick 	default:
37152130Smckusick 		return (ENOTTY);
37252130Smckusick 	}
37352130Smckusick 	return (0);
37452130Smckusick }
37552130Smckusick 
37652130Smckusick dcparam(tp, t)
37752130Smckusick 	register struct tty *tp;
37852130Smckusick 	register struct termios *t;
37952130Smckusick {
38052130Smckusick 	register dcregs *dcaddr;
38152130Smckusick 	register int lpr;
38252130Smckusick 	register int cflag = t->c_cflag;
38352130Smckusick 	int unit = minor(tp->t_dev);
38452130Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab);
38552130Smckusick 
38652130Smckusick 	/* check requested parameters */
38752130Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
38856819Sralph             (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 ||
38956819Sralph 	    (pmax_boardtype == DS_PMAX && t->c_ospeed == 19200))
39052130Smckusick                 return (EINVAL);
39152130Smckusick         /* and copy to tty */
39252130Smckusick         tp->t_ispeed = t->c_ispeed;
39352130Smckusick         tp->t_ospeed = t->c_ospeed;
39452130Smckusick         tp->t_cflag = cflag;
39552130Smckusick 
39656819Sralph 	dcaddr = (dcregs *)dcpdma[unit].p_addr;
39756819Sralph 
39856819Sralph 	/*
39956819Sralph 	 * Handle console cases specially.
40056819Sralph 	 */
40156819Sralph 	if (cn_tab.cn_screen) {
40256819Sralph 		if (unit == DCKBD_PORT) {
40356819Sralph 			dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
40456819Sralph 				LPR_B4800 | DCKBD_PORT;
40556819Sralph 			MachEmptyWriteBuffer();
40656819Sralph 			return (0);
40756819Sralph 		} else if (unit == DCMOUSE_PORT) {
40856819Sralph 			dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
40956819Sralph 				LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT;
41056819Sralph 			MachEmptyWriteBuffer();
41156819Sralph 			return (0);
41256819Sralph 		}
41356819Sralph 	} else if (tp->t_dev == cn_tab.cn_dev) {
41456819Sralph 		dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
41556819Sralph 			LPR_B9600 | unit;
41652130Smckusick 		MachEmptyWriteBuffer();
41752130Smckusick 		return (0);
41852130Smckusick 	}
41952130Smckusick 	if (ospeed == 0) {
42052130Smckusick 		(void) dcmctl(unit, 0, DMSET);	/* hang up line */
42152130Smckusick 		return (0);
42252130Smckusick 	}
42352130Smckusick 	lpr = LPR_RXENAB | ospeed | (unit & 03);
42452130Smckusick 	if ((cflag & CSIZE) == CS7)
42552130Smckusick 		lpr |= LPR_7_BIT_CHAR;
42652130Smckusick 	else
42752130Smckusick 		lpr |= LPR_8_BIT_CHAR;
42852130Smckusick 	if (cflag & PARENB)
42952130Smckusick 		lpr |= LPR_PARENB;
43052130Smckusick 	if (cflag & PARODD)
43152130Smckusick 		lpr |= LPR_OPAR;
43252130Smckusick 	if (cflag & CSTOPB)
43352130Smckusick 		lpr |= LPR_2_STOP;
43452130Smckusick 	dcaddr->dc_lpr = lpr;
43552130Smckusick 	MachEmptyWriteBuffer();
43658975Sralph 	DELAY(10);
43752130Smckusick 	return (0);
43852130Smckusick }
43952130Smckusick 
44052693Sralph /*
44152693Sralph  * Check for interrupts from all devices.
44252693Sralph  */
44352693Sralph void
44452693Sralph dcintr(unit)
44552693Sralph 	register int unit;
44652693Sralph {
44752693Sralph 	register dcregs *dcaddr;
44852693Sralph 	register unsigned csr;
44952693Sralph 
45052693Sralph 	unit <<= 2;
45156819Sralph 	dcaddr = (dcregs *)dcpdma[unit].p_addr;
45252693Sralph 	while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) {
45352693Sralph 		if (csr & CSR_RDONE)
45452693Sralph 			dcrint(unit);
45552693Sralph 		if (csr & CSR_TRDY)
45652693Sralph 			dcxint(&dc_tty[unit + ((csr >> 8) & 03)]);
45752693Sralph 	}
45852693Sralph }
45952693Sralph 
46052693Sralph dcrint(unit)
46152693Sralph 	register int unit;
46252693Sralph {
46352693Sralph 	register dcregs *dcaddr;
46452693Sralph 	register struct tty *tp;
46552693Sralph 	register int c, cc;
46652693Sralph 	register struct tty *tp0;
46752693Sralph 	int overrun = 0;
46852693Sralph 
46956819Sralph 	dcaddr = (dcregs *)dcpdma[unit].p_addr;
47052693Sralph 	tp0 = &dc_tty[unit];
47152693Sralph 	while ((c = dcaddr->dc_rbuf) < 0) {	/* char present */
47252693Sralph 		cc = c & 0xff;
47352693Sralph 		tp = tp0 + ((c >> 8) & 03);
47452693Sralph 		if ((c & RBUF_OERR) && overrun == 0) {
47552693Sralph 			log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2,
47652693Sralph 				(c >> 8) & 03);
47752693Sralph 			overrun = 1;
47852693Sralph 		}
47952693Sralph 		/* the keyboard requires special translation */
48056819Sralph 		if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) {
48152693Sralph #ifdef KADB
48252693Sralph 			if (cc == LK_DO) {
48352693Sralph 				spl0();
48452693Sralph 				kdbpanic();
48552693Sralph 				return;
48652693Sralph 			}
48752693Sralph #endif
48852693Sralph #ifdef DEBUG
48952693Sralph 			debugChar = cc;
49052693Sralph #endif
49152693Sralph 			if (dcDivertXInput) {
49252863Sralph 				(*dcDivertXInput)(cc);
49352693Sralph 				return;
49452693Sralph 			}
49556819Sralph 			if ((cc = kbdMapChar(cc)) < 0)
49652693Sralph 				return;
49756819Sralph 		} else if (tp == &dc_tty[DCMOUSE_PORT] && dcMouseButtons) {
49852863Sralph 			register MouseReport *mrp;
49952693Sralph 			static MouseReport currentRep;
50052693Sralph 
50152863Sralph 			mrp = &currentRep;
50252863Sralph 			mrp->byteCount++;
50352693Sralph 			if (cc & MOUSE_START_FRAME) {
50452693Sralph 				/*
50552693Sralph 				 * The first mouse report byte (button state).
50652693Sralph 				 */
50752863Sralph 				mrp->state = cc;
50852863Sralph 				if (mrp->byteCount > 1)
50952863Sralph 					mrp->byteCount = 1;
51052863Sralph 			} else if (mrp->byteCount == 2) {
51152693Sralph 				/*
51252693Sralph 				 * The second mouse report byte (delta x).
51352693Sralph 				 */
51452863Sralph 				mrp->dx = cc;
51552863Sralph 			} else if (mrp->byteCount == 3) {
51652693Sralph 				/*
51752693Sralph 				 * The final mouse report byte (delta y).
51852693Sralph 				 */
51952863Sralph 				mrp->dy = cc;
52052863Sralph 				mrp->byteCount = 0;
52152863Sralph 				if (mrp->dx != 0 || mrp->dy != 0) {
52252693Sralph 					/*
52352693Sralph 					 * If the mouse moved,
52452693Sralph 					 * post a motion event.
52552693Sralph 					 */
52652863Sralph 					(*dcMouseEvent)(mrp);
52752693Sralph 				}
52852863Sralph 				(*dcMouseButtons)(mrp);
52952693Sralph 			}
53052693Sralph 			return;
53152693Sralph 		}
53252693Sralph 		if (!(tp->t_state & TS_ISOPEN)) {
53352693Sralph 			wakeup((caddr_t)&tp->t_rawq);
53452693Sralph #ifdef PORTSELECTOR
53552693Sralph 			if (!(tp->t_state & TS_WOPEN))
53652693Sralph #endif
53752693Sralph 				return;
53852693Sralph 		}
53952693Sralph 		if (c & RBUF_FERR)
54052693Sralph 			cc |= TTY_FE;
54152693Sralph 		if (c & RBUF_PERR)
54252693Sralph 			cc |= TTY_PE;
543*67477Smckusick 		if ((tp->t_cflag & CRTS_IFLOW) && !(tp->t_state & TS_TBLOCK) &&
544*67477Smckusick 		    tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
545*67477Smckusick 			tp->t_state &= ~TS_TBLOCK;
546*67477Smckusick 			(void) dcmctl(tp->t_dev, DML_RTS, DMBIC);
547*67477Smckusick 		}
54852693Sralph 		(*linesw[tp->t_line].l_rint)(cc, tp);
54952693Sralph 	}
55052693Sralph 	DELAY(10);
55152693Sralph }
55252693Sralph 
55352755Sralph void
55452130Smckusick dcxint(tp)
55552130Smckusick 	register struct tty *tp;
55652130Smckusick {
55752130Smckusick 	register struct pdma *dp;
55852130Smckusick 	register dcregs *dcaddr;
559*67477Smckusick 	int unit;
56052130Smckusick 
561*67477Smckusick 	dp = &dcpdma[unit = minor(tp->t_dev)];
56252130Smckusick 	if (dp->p_mem < dp->p_end) {
56356819Sralph 		dcaddr = (dcregs *)dp->p_addr;
564*67477Smckusick 		/* check for hardware flow control of output */
565*67477Smckusick 		if ((tp->t_cflag & CCTS_OFLOW) && pmax_boardtype != DS_PMAX) {
566*67477Smckusick 			switch (unit) {
567*67477Smckusick 			case DCCOMM_PORT:
568*67477Smckusick 				if (dcaddr->dc_msr & MSR_CTS2)
569*67477Smckusick 					break;
570*67477Smckusick 				goto stop;
571*67477Smckusick 
572*67477Smckusick 			case DCPRINTER_PORT:
573*67477Smckusick 				if (dcaddr->dc_msr & MSR_CTS3)
574*67477Smckusick 					break;
575*67477Smckusick 			stop:
576*67477Smckusick 				tp->t_state &= ~TS_BUSY;
577*67477Smckusick 				tp->t_state |= TS_TTSTOP;
578*67477Smckusick 				ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
579*67477Smckusick 				dp->p_end = dp->p_mem = tp->t_outq.c_cf;
580*67477Smckusick 				dcaddr->dc_tcr &= ~(1 << unit);
581*67477Smckusick 				MachEmptyWriteBuffer();
582*67477Smckusick 				DELAY(10);
583*67477Smckusick 				return;
584*67477Smckusick 			}
585*67477Smckusick 		}
586*67477Smckusick 		dcaddr->dc_tdr = dc_brk[unit >> 2] | *dp->p_mem++;
58752130Smckusick 		MachEmptyWriteBuffer();
58852130Smckusick 		DELAY(10);
58952130Smckusick 		return;
59052130Smckusick 	}
59152130Smckusick 	tp->t_state &= ~TS_BUSY;
59252130Smckusick 	if (tp->t_state & TS_FLUSH)
59352130Smckusick 		tp->t_state &= ~TS_FLUSH;
59452130Smckusick 	else {
595*67477Smckusick 		ndflush(&tp->t_outq, dp->p_mem - tp->t_outq.c_cf);
59652130Smckusick 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
59752130Smckusick 	}
59852130Smckusick 	if (tp->t_line)
59952130Smckusick 		(*linesw[tp->t_line].l_start)(tp);
60052130Smckusick 	else
60152130Smckusick 		dcstart(tp);
60252130Smckusick 	if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
60358975Sralph 		dcaddr = (dcregs *)dp->p_addr;
604*67477Smckusick 		dcaddr->dc_tcr &= ~(1 << (unit & 03));
60552130Smckusick 		MachEmptyWriteBuffer();
60652130Smckusick 		DELAY(10);
60752130Smckusick 	}
60852130Smckusick }
60952130Smckusick 
61052755Sralph void
61152130Smckusick dcstart(tp)
61252130Smckusick 	register struct tty *tp;
61352130Smckusick {
61452130Smckusick 	register struct pdma *dp;
61552130Smckusick 	register dcregs *dcaddr;
61652130Smckusick 	register int cc;
617*67477Smckusick 	int unit, s;
61852130Smckusick 
619*67477Smckusick 	dp = &dcpdma[unit = minor(tp->t_dev)];
62056819Sralph 	dcaddr = (dcregs *)dp->p_addr;
62152130Smckusick 	s = spltty();
62252130Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
62352130Smckusick 		goto out;
62452130Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
62552130Smckusick 		if (tp->t_state & TS_ASLEEP) {
62652130Smckusick 			tp->t_state &= ~TS_ASLEEP;
62752130Smckusick 			wakeup((caddr_t)&tp->t_outq);
62852130Smckusick 		}
62952674Smckusick 		selwakeup(&tp->t_wsel);
63052130Smckusick 	}
63152130Smckusick 	if (tp->t_outq.c_cc == 0)
63252130Smckusick 		goto out;
63352130Smckusick 	/* handle console specially */
63456819Sralph 	if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) {
63552130Smckusick 		while (tp->t_outq.c_cc > 0) {
63652130Smckusick 			cc = getc(&tp->t_outq) & 0x7f;
63752863Sralph 			cnputc(cc);
63852130Smckusick 		}
63952130Smckusick 		/*
64052130Smckusick 		 * After we flush the output queue we may need to wake
64152130Smckusick 		 * up the process that made the output.
64252130Smckusick 		 */
64352130Smckusick 		if (tp->t_outq.c_cc <= tp->t_lowat) {
64452130Smckusick 			if (tp->t_state & TS_ASLEEP) {
64552130Smckusick 				tp->t_state &= ~TS_ASLEEP;
64652130Smckusick 				wakeup((caddr_t)&tp->t_outq);
64752130Smckusick 			}
64852674Smckusick 			selwakeup(&tp->t_wsel);
64952130Smckusick 		}
65052130Smckusick 		goto out;
65152130Smckusick 	}
652*67477Smckusick 	cc = ndqb(&tp->t_outq, 0);
65352130Smckusick 	tp->t_state |= TS_BUSY;
65452130Smckusick 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
65552130Smckusick 	dp->p_end += cc;
656*67477Smckusick 	dcaddr->dc_tcr |= 1 << (unit & 03);
65752130Smckusick 	MachEmptyWriteBuffer();
65852130Smckusick out:
65952130Smckusick 	splx(s);
66052130Smckusick }
66152130Smckusick 
66252130Smckusick /*
66352130Smckusick  * Stop output on a line.
66452130Smckusick  */
66552130Smckusick /*ARGSUSED*/
66652130Smckusick dcstop(tp, flag)
66752130Smckusick 	register struct tty *tp;
66852130Smckusick {
66952130Smckusick 	register struct pdma *dp;
67052130Smckusick 	register int s;
67152130Smckusick 
67264978Smckusick 	dp = &dcpdma[minor(tp->t_dev)];
67352130Smckusick 	s = spltty();
67452130Smckusick 	if (tp->t_state & TS_BUSY) {
67552130Smckusick 		dp->p_end = dp->p_mem;
67652130Smckusick 		if (!(tp->t_state & TS_TTSTOP))
67752130Smckusick 			tp->t_state |= TS_FLUSH;
67852130Smckusick 	}
67952130Smckusick 	splx(s);
68052130Smckusick }
68152130Smckusick 
68252130Smckusick dcmctl(dev, bits, how)
68352130Smckusick 	dev_t dev;
68452130Smckusick 	int bits, how;
68552130Smckusick {
68652130Smckusick 	register dcregs *dcaddr;
68752130Smckusick 	register int unit, mbits;
68852130Smckusick 	int b, s;
689*67477Smckusick 	register int tcr, msr;
69052130Smckusick 
69152130Smckusick 	unit = minor(dev);
69252130Smckusick 	b = 1 << (unit & 03);
69356819Sralph 	dcaddr = (dcregs *)dcpdma[unit].p_addr;
69452130Smckusick 	s = spltty();
695*67477Smckusick 	/* only channel 2 has modem control on a DECstation 2100/3100 */
696*67477Smckusick 	mbits = DML_DTR | DML_RTS | DML_DSR | DML_CAR;
69752693Sralph 	switch (unit & 03) {
69852693Sralph 	case 2:
69952130Smckusick 		mbits = 0;
700*67477Smckusick 		tcr = dcaddr->dc_tcr;
701*67477Smckusick 		if (tcr & TCR_DTR2)
70252130Smckusick 			mbits |= DML_DTR;
703*67477Smckusick 		if (pmax_boardtype != DS_PMAX && (tcr & TCR_RTS2))
704*67477Smckusick 			mbits |= DML_RTS;
70552693Sralph 		msr = dcaddr->dc_msr;
70652693Sralph 		if (msr & MSR_CD2)
70752693Sralph 			mbits |= DML_CAR;
70856819Sralph 		if (msr & MSR_DSR2) {
70956819Sralph 			if (pmax_boardtype == DS_PMAX)
71056819Sralph 				mbits |= DML_CAR | DML_DSR;
71156819Sralph 			else
71256819Sralph 				mbits |= DML_DSR;
71356819Sralph 		}
71452693Sralph 		break;
71552693Sralph 
71652693Sralph 	case 3:
71756819Sralph 		if (pmax_boardtype != DS_PMAX) {
71856819Sralph 			mbits = 0;
719*67477Smckusick 			tcr = dcaddr->dc_tcr;
720*67477Smckusick 			if (tcr & TCR_DTR3)
72156819Sralph 				mbits |= DML_DTR;
722*67477Smckusick 			if (tcr & TCR_RTS3)
723*67477Smckusick 				mbits |= DML_RTS;
72456819Sralph 			msr = dcaddr->dc_msr;
72556819Sralph 			if (msr & MSR_CD3)
72656819Sralph 				mbits |= DML_CAR;
72756819Sralph 			if (msr & MSR_DSR3)
72856819Sralph 				mbits |= DML_DSR;
72956819Sralph 		}
73052693Sralph 	}
73152130Smckusick 	switch (how) {
73252130Smckusick 	case DMSET:
73352130Smckusick 		mbits = bits;
73452130Smckusick 		break;
73552130Smckusick 
73652130Smckusick 	case DMBIS:
73752130Smckusick 		mbits |= bits;
73852130Smckusick 		break;
73952130Smckusick 
74052130Smckusick 	case DMBIC:
74152130Smckusick 		mbits &= ~bits;
74252130Smckusick 		break;
74352130Smckusick 
74452130Smckusick 	case DMGET:
74552130Smckusick 		(void) splx(s);
74652130Smckusick 		return (mbits);
74752130Smckusick 	}
74852693Sralph 	switch (unit & 03) {
74952693Sralph 	case 2:
750*67477Smckusick 		tcr = dcaddr->dc_tcr;
75152130Smckusick 		if (mbits & DML_DTR)
752*67477Smckusick 			tcr |= TCR_DTR2;
75352130Smckusick 		else
754*67477Smckusick 			tcr &= ~TCR_DTR2;
755*67477Smckusick 		if (pmax_boardtype != DS_PMAX) {
756*67477Smckusick 			if (mbits & DML_RTS)
757*67477Smckusick 				tcr |= TCR_RTS2;
758*67477Smckusick 			else
759*67477Smckusick 				tcr &= ~TCR_RTS2;
760*67477Smckusick 		}
761*67477Smckusick 		dcaddr->dc_tcr = tcr;
76252693Sralph 		break;
76352693Sralph 
76452693Sralph 	case 3:
76556819Sralph 		if (pmax_boardtype != DS_PMAX) {
766*67477Smckusick 			tcr = dcaddr->dc_tcr;
76756819Sralph 			if (mbits & DML_DTR)
768*67477Smckusick 				tcr |= TCR_DTR3;
76956819Sralph 			else
770*67477Smckusick 				tcr &= ~TCR_DTR3;
771*67477Smckusick 			if (mbits & DML_RTS)
772*67477Smckusick 				tcr |= TCR_RTS3;
773*67477Smckusick 			else
774*67477Smckusick 				tcr &= ~TCR_RTS3;
775*67477Smckusick 			dcaddr->dc_tcr = tcr;
77656819Sralph 		}
77752130Smckusick 	}
77852130Smckusick 	if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b))
77952130Smckusick 		dc_tty[unit].t_state |= TS_CARR_ON;
78052130Smckusick 	(void) splx(s);
78152130Smckusick 	return (mbits);
78252130Smckusick }
78352130Smckusick 
78452130Smckusick /*
78552130Smckusick  * This is called by timeout() periodically.
78652130Smckusick  * Check to see if modem status bits have changed.
78752130Smckusick  */
78856819Sralph void
78955744Sralph dcscan(arg)
79055744Sralph 	void *arg;
79152130Smckusick {
79252130Smckusick 	register dcregs *dcaddr;
79352130Smckusick 	register struct tty *tp;
794*67477Smckusick 	register int unit, limit, dtr, dsr;
79552130Smckusick 	int s;
79652130Smckusick 
797*67477Smckusick 	/* only channel 2 has modem control on a DECstation 2100/3100 */
798*67477Smckusick 	dtr = TCR_DTR2;
799*67477Smckusick 	dsr = MSR_DSR2;
800*67477Smckusick 	limit = (pmax_boardtype == DS_PMAX) ? 2 : 3;
80152130Smckusick 	s = spltty();
802*67477Smckusick 	for (unit = 2; unit <= limit; unit++, dtr >>= 2, dsr >>= 8) {
803*67477Smckusick 		tp = &dc_tty[unit];
804*67477Smckusick 		dcaddr = (dcregs *)dcpdma[unit].p_addr;
805*67477Smckusick 		if (dcaddr->dc_msr & dsr) {
806*67477Smckusick 			/* carrier present */
807*67477Smckusick 			if (!(tp->t_state & TS_CARR_ON))
808*67477Smckusick 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
809*67477Smckusick 		} else if ((tp->t_state & TS_CARR_ON) &&
810*67477Smckusick 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
811*67477Smckusick 			dcaddr->dc_tcr &= ~dtr;
812*67477Smckusick 		/*
813*67477Smckusick 		 * If we are using hardware flow control and output is stopped,
814*67477Smckusick 		 * then resume transmit.
815*67477Smckusick 		 */
816*67477Smckusick 		if ((tp->t_cflag & CCTS_OFLOW) && (tp->t_state & TS_TTSTOP) &&
817*67477Smckusick 		    pmax_boardtype != DS_PMAX) {
818*67477Smckusick 			switch (unit) {
819*67477Smckusick 			case DCCOMM_PORT:
820*67477Smckusick 				if (dcaddr->dc_msr & MSR_CTS2)
821*67477Smckusick 					break;
822*67477Smckusick 				continue;
823*67477Smckusick 
824*67477Smckusick 			case DCPRINTER_PORT:
825*67477Smckusick 				if (dcaddr->dc_msr & MSR_CTS3)
826*67477Smckusick 					break;
827*67477Smckusick 				continue;
828*67477Smckusick 			}
829*67477Smckusick 			tp->t_state &= ~TS_TTSTOP;
830*67477Smckusick 			dcstart(tp);
831*67477Smckusick 		}
832*67477Smckusick 	}
83352130Smckusick 	splx(s);
83455744Sralph 	timeout(dcscan, (void *)0, hz);
83552130Smckusick }
83652130Smckusick 
83752130Smckusick /*
83852130Smckusick  * ----------------------------------------------------------------------------
83952130Smckusick  *
84056819Sralph  * dcGetc --
84152130Smckusick  *
84256819Sralph  *	Read a character from a serial line.
84352130Smckusick  *
84452130Smckusick  * Results:
84556819Sralph  *	A character read from the serial port.
84652130Smckusick  *
84752130Smckusick  * Side effects:
84852130Smckusick  *	None.
84952130Smckusick  *
85052130Smckusick  * ----------------------------------------------------------------------------
85152130Smckusick  */
85252130Smckusick int
85356819Sralph dcGetc(dev)
85456819Sralph 	dev_t dev;
85552130Smckusick {
85652130Smckusick 	register dcregs *dcaddr;
85752130Smckusick 	register int c;
85854146Sralph 	int s;
85952130Smckusick 
86056819Sralph 	dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr;
86152130Smckusick 	if (!dcaddr)
86252130Smckusick 		return (0);
86354146Sralph 	s = spltty();
86452693Sralph 	for (;;) {
86552693Sralph 		if (!(dcaddr->dc_csr & CSR_RDONE))
86652693Sralph 			continue;
86752693Sralph 		c = dcaddr->dc_rbuf;
86852693Sralph 		DELAY(10);
86956819Sralph 		if (((c >> 8) & 03) == (minor(dev) & 03))
87052693Sralph 			break;
87152693Sralph 	}
87252693Sralph 	splx(s);
87356819Sralph 	return (c & 0xff);
87452693Sralph }
87552693Sralph 
87652693Sralph /*
87756819Sralph  * Send a char on a port, non interrupt driven.
87852693Sralph  */
87952130Smckusick void
88056819Sralph dcPutc(dev, c)
88156819Sralph 	dev_t dev;
88252130Smckusick 	int c;
88352130Smckusick {
88452130Smckusick 	register dcregs *dcaddr;
88552130Smckusick 	register u_short tcr;
88652130Smckusick 	register int timeout;
88756819Sralph 	int s, line;
88852130Smckusick 
88956819Sralph 	s = spltty();
89056819Sralph 
89156819Sralph 	dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr;
89252130Smckusick 	tcr = dcaddr->dc_tcr;
89356819Sralph 	dcaddr->dc_tcr = tcr | (1 << minor(dev));
89452130Smckusick 	MachEmptyWriteBuffer();
89552130Smckusick 	DELAY(10);
89652130Smckusick 	while (1) {
89752130Smckusick 		/*
89852130Smckusick 		 * Wait for transmitter to be not busy.
89952130Smckusick 		 */
90052130Smckusick 		timeout = 1000000;
90152130Smckusick 		while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
90252130Smckusick 			timeout--;
90352130Smckusick 		if (timeout == 0) {
90456819Sralph 			printf("dcPutc: timeout waiting for CSR_TRDY\n");
90552130Smckusick 			break;
90652130Smckusick 		}
90752130Smckusick 		line = (dcaddr->dc_csr >> 8) & 3;
90852130Smckusick 		/*
90952130Smckusick 		 * Check to be sure its the right port.
91052130Smckusick 		 */
91156819Sralph 		if (line != minor(dev)) {
91252130Smckusick 			tcr |= 1 << line;
91352130Smckusick 			dcaddr->dc_tcr &= ~(1 << line);
91452130Smckusick 			MachEmptyWriteBuffer();
91552130Smckusick 			DELAY(10);
91652130Smckusick 			continue;
91752130Smckusick 		}
91852130Smckusick 		/*
91952130Smckusick 		 * Start sending the character.
92052130Smckusick 		 */
92152130Smckusick 		dcaddr->dc_tdr = dc_brk[0] | (c & 0xff);
92252130Smckusick 		MachEmptyWriteBuffer();
92352130Smckusick 		DELAY(10);
92452130Smckusick 		/*
92552130Smckusick 		 * Wait for character to be sent.
92652130Smckusick 		 */
92752130Smckusick 		while (1) {
92852130Smckusick 			/*
92952130Smckusick 			 * cc -O bug: this code produces and infinite loop!
93052130Smckusick 			 * while (!(dcaddr->dc_csr & CSR_TRDY))
93152130Smckusick 			 *	;
93252130Smckusick 			 */
93352130Smckusick 			timeout = 1000000;
93452130Smckusick 			while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
93552130Smckusick 				timeout--;
93652130Smckusick 			line = (dcaddr->dc_csr >> 8) & 3;
93756819Sralph 			if (line != minor(dev)) {
93852130Smckusick 				tcr |= 1 << line;
93952130Smckusick 				dcaddr->dc_tcr &= ~(1 << line);
94052130Smckusick 				MachEmptyWriteBuffer();
94152130Smckusick 				DELAY(10);
94252130Smckusick 				continue;
94352130Smckusick 			}
94456819Sralph 			dcaddr->dc_tcr &= ~(1 << minor(dev));
94552130Smckusick 			MachEmptyWriteBuffer();
94652130Smckusick 			DELAY(10);
94752130Smckusick 			break;
94852130Smckusick 		}
94952130Smckusick 		break;
95052130Smckusick 	}
95152130Smckusick 	/*
95252130Smckusick 	 * Enable interrupts for other lines which became ready.
95352130Smckusick 	 */
95452130Smckusick 	if (tcr & 0xF) {
95552130Smckusick 		dcaddr->dc_tcr = tcr;
95652130Smckusick 		MachEmptyWriteBuffer();
95752130Smckusick 		DELAY(10);
95852130Smckusick 	}
95952130Smckusick 
96056819Sralph 	splx(s);
96152130Smckusick }
96252130Smckusick #endif /* NDC */
963