xref: /csrg-svn/sys/hp/dev/dca.c (revision 44295)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
341480Smckusick  * All rights reserved.
441480Smckusick  *
541480Smckusick  * %sccs.include.redist.c%
641480Smckusick  *
7*44295Shibler  *	@(#)dca.c	7.5 (Berkeley) 06/26/90
841480Smckusick  */
941480Smckusick 
1041480Smckusick #include "dca.h"
1141480Smckusick #if NDCA > 0
1241480Smckusick /*
1341480Smckusick  *  98626/98644/internal serial interface
1441480Smckusick  */
1541480Smckusick #include "param.h"
1641480Smckusick #include "systm.h"
1741480Smckusick #include "ioctl.h"
1841480Smckusick #include "tty.h"
1941480Smckusick #include "user.h"
2041480Smckusick #include "conf.h"
2141480Smckusick #include "file.h"
2241480Smckusick #include "uio.h"
2341480Smckusick #include "kernel.h"
2441480Smckusick #include "syslog.h"
2541480Smckusick 
2641480Smckusick #include "device.h"
2741480Smckusick #include "dcareg.h"
2841480Smckusick #include "machine/cpu.h"
2941480Smckusick #include "machine/isr.h"
3041480Smckusick 
3141480Smckusick int	dcaprobe();
3241480Smckusick struct	driver dcadriver = {
3341480Smckusick 	dcaprobe, "dca",
3441480Smckusick };
3541480Smckusick 
3641480Smckusick int	dcastart(), dcaparam(), dcaintr();
3741480Smckusick int	dcasoftCAR;
3841480Smckusick int	dca_active;
3941480Smckusick int	ndca = NDCA;
4041480Smckusick int	dcaconsole = -1;
4141480Smckusick int	dcadefaultrate = TTYDEF_SPEED;
4241480Smckusick struct	dcadevice *dca_addr[NDCA];
4341480Smckusick struct	tty dca_tty[NDCA];
4441480Smckusick struct	isr dcaisr[NDCA];
4541480Smckusick 
4641480Smckusick struct speedtab dcaspeedtab[] = {
4741480Smckusick 	0,	0,
4841480Smckusick 	50,	DCABRD(50),
4941480Smckusick 	75,	DCABRD(75),
5041480Smckusick 	110,	DCABRD(110),
5141480Smckusick 	134,	DCABRD(134),
5241480Smckusick 	150,	DCABRD(150),
5341480Smckusick 	200,	DCABRD(200),
5441480Smckusick 	300,	DCABRD(300),
5541480Smckusick 	600,	DCABRD(600),
5641480Smckusick 	1200,	DCABRD(1200),
5741480Smckusick 	1800,	DCABRD(1800),
5841480Smckusick 	2400,	DCABRD(2400),
5941480Smckusick 	4800,	DCABRD(4800),
6041480Smckusick 	9600,	DCABRD(9600),
6141480Smckusick 	19200,	DCABRD(19200),
6241480Smckusick 	38400,	DCABRD(38400),
6341480Smckusick 	-1,	-1
6441480Smckusick };
6541480Smckusick 
6641480Smckusick extern	struct tty *constty;
6741480Smckusick #ifdef KGDB
6841480Smckusick extern int kgdb_dev;
6941480Smckusick extern int kgdb_rate;
7041480Smckusick extern int kgdb_debug_init;
7141480Smckusick #endif
7241480Smckusick 
7341480Smckusick #define	UNIT(x)		minor(x)
7441480Smckusick 
7541480Smckusick dcaprobe(hd)
7641480Smckusick 	register struct hp_device *hd;
7741480Smckusick {
7841480Smckusick 	register struct dcadevice *dca;
7941480Smckusick 	register int unit;
8041480Smckusick 
8141480Smckusick 	dca = (struct dcadevice *)hd->hp_addr;
8241480Smckusick 	if (dca->dca_irid != DCAID0 &&
8341480Smckusick 	    dca->dca_irid != DCAREMID0 &&
8441480Smckusick 	    dca->dca_irid != DCAID1 &&
8541480Smckusick 	    dca->dca_irid != DCAREMID1)
8641480Smckusick 		return (0);
8741480Smckusick 	unit = hd->hp_unit;
8841480Smckusick 	if (unit == dcaconsole)
8941480Smckusick 		DELAY(100000);
9041480Smckusick 	dca->dca_irid = 0xFF;
9141480Smckusick 	DELAY(100);
9241480Smckusick 
9341480Smckusick 	hd->hp_ipl = DCAIPL(dca->dca_ic);
9441480Smckusick 	dcaisr[unit].isr_ipl = hd->hp_ipl;
9541480Smckusick 	dcaisr[unit].isr_arg = unit;
9641480Smckusick 	dcaisr[unit].isr_intr = dcaintr;
9741480Smckusick 	dca_addr[unit] = dca;
9841480Smckusick 	dca_active |= 1 << unit;
9941480Smckusick 	dcasoftCAR = hd->hp_flags;
10041480Smckusick 	isrlink(&dcaisr[unit]);
10141480Smckusick #ifdef KGDB
10241480Smckusick 	if (kgdb_dev == makedev(1, unit)) {
10341480Smckusick 		if (dcaconsole == unit)
10441480Smckusick 			kgdb_dev = -1;	/* can't debug over console port */
10541480Smckusick 		else {
10641480Smckusick 			(void) dcainit(unit);
10741480Smckusick 			dcaconsole = -2; /* XXX */
10841480Smckusick 			if (kgdb_debug_init) {
10941480Smckusick 				printf("dca%d: kgdb waiting...", unit);
11041480Smckusick 				/* trap into kgdb */
11141480Smckusick 				asm("trap #15;");
11241480Smckusick 				printf("connected.\n");
11341480Smckusick 			} else
11441480Smckusick 				printf("dca%d: kgdb enabled\n", unit);
11541480Smckusick 		}
11641480Smckusick 	}
11741480Smckusick #endif
11841480Smckusick 	dca->dca_ic = IC_IE;
11941480Smckusick 	/*
12041480Smckusick 	 * Need to reset baud rate, etc. of next print so reset dcaconsole.
12141480Smckusick 	 * Also make sure console is always "hardwired"
12241480Smckusick 	 */
12341480Smckusick 	if (unit == dcaconsole) {
12441480Smckusick 		dcaconsole = -1;
12541480Smckusick 		dcasoftCAR |= (1 << unit);
12641480Smckusick 	}
12741480Smckusick 	return (1);
12841480Smckusick }
12941480Smckusick 
13041480Smckusick dcaopen(dev, flag)
13141480Smckusick 	dev_t dev;
13241480Smckusick {
13341480Smckusick 	register struct tty *tp;
13441480Smckusick 	register int unit;
13542353Smckusick 	int error;
13641480Smckusick 
13741480Smckusick 	unit = UNIT(dev);
13841480Smckusick 	if (unit >= NDCA || (dca_active & (1 << unit)) == 0)
13941480Smckusick 		return (ENXIO);
14041480Smckusick 	tp = &dca_tty[unit];
14141480Smckusick 	tp->t_oproc = dcastart;
14241480Smckusick 	tp->t_param = dcaparam;
14341480Smckusick 	tp->t_dev = dev;
14441480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
14542950Smarc 		tp->t_state |= TS_WOPEN;
14641480Smckusick 		ttychars(tp);
14741480Smckusick 		tp->t_iflag = TTYDEF_IFLAG;
14841480Smckusick 		tp->t_oflag = TTYDEF_OFLAG;
14941480Smckusick 		tp->t_cflag = TTYDEF_CFLAG;
15041480Smckusick 		tp->t_lflag = TTYDEF_LFLAG;
15141480Smckusick 		tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
15241480Smckusick 		dcaparam(tp, &tp->t_termios);
15341480Smckusick 		ttsetwater(tp);
15441480Smckusick 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
15541480Smckusick 		return (EBUSY);
15641480Smckusick 	(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
15741480Smckusick 	if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
15841480Smckusick 		tp->t_state |= TS_CARR_ON;
15941480Smckusick 	(void) spltty();
160*44295Shibler 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
16141480Smckusick 	       (tp->t_state & TS_CARR_ON) == 0) {
16241480Smckusick 		tp->t_state |= TS_WOPEN;
163*44295Shibler 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
164*44295Shibler 		    ttopen, 0))
165*44295Shibler 			break;
16641480Smckusick 	}
16741480Smckusick 	(void) spl0();
168*44295Shibler 	if (error == 0)
169*44295Shibler 		error = (*linesw[tp->t_line].l_open)(dev, tp);
170*44295Shibler 	return (error);
17141480Smckusick }
17241480Smckusick 
17341480Smckusick /*ARGSUSED*/
17441480Smckusick dcaclose(dev, flag)
17541480Smckusick 	dev_t dev;
17641480Smckusick {
17741480Smckusick 	register struct tty *tp;
17841480Smckusick 	register struct dcadevice *dca;
17941480Smckusick 	register int unit;
18041480Smckusick 
18141480Smckusick 	unit = UNIT(dev);
18241480Smckusick 	dca = dca_addr[unit];
18341480Smckusick 	tp = &dca_tty[unit];
18441480Smckusick 	(*linesw[tp->t_line].l_close)(tp);
18541480Smckusick 	dca->dca_cfcr &= ~CFCR_SBREAK;
18641480Smckusick #ifdef KGDB
18741480Smckusick 	/* do not disable interrupts if debugging */
18841480Smckusick 	if (kgdb_dev != makedev(1, unit))
18941480Smckusick #endif
19041480Smckusick 	dca->dca_ier = 0;
19141480Smckusick 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
19241480Smckusick 	    (tp->t_state&TS_ISOPEN) == 0)
19341480Smckusick 		(void) dcamctl(dev, 0, DMSET);
19441480Smckusick 	ttyclose(tp);
19541480Smckusick 	return(0);
19641480Smckusick }
19741480Smckusick 
19841480Smckusick dcaread(dev, uio, flag)
19941480Smckusick 	dev_t dev;
20041480Smckusick 	struct uio *uio;
20141480Smckusick {
20241480Smckusick 	register struct tty *tp = &dca_tty[UNIT(dev)];
20341480Smckusick 
20441480Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
20541480Smckusick }
20641480Smckusick 
20741480Smckusick dcawrite(dev, uio, flag)
20841480Smckusick 	dev_t dev;
20941480Smckusick 	struct uio *uio;
21041480Smckusick {
21141480Smckusick 	int unit = UNIT(dev);
21241480Smckusick 	register struct tty *tp = &dca_tty[unit];
21341480Smckusick 
21442353Smckusick 	/*
21542353Smckusick 	 * (XXX) We disallow virtual consoles if the physical console is
21642353Smckusick 	 * a serial port.  This is in case there is a display attached that
21742353Smckusick 	 * is not the console.  In that situation we don't need/want the X
21842353Smckusick 	 * server taking over the console.
21942353Smckusick 	 */
22042353Smckusick 	if (constty && unit == dcaconsole)
22142353Smckusick 		constty = NULL;
22241480Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
22341480Smckusick }
22441480Smckusick 
22541480Smckusick dcaintr(unit)
22641480Smckusick 	register int unit;
22741480Smckusick {
22841480Smckusick 	register struct dcadevice *dca;
22941480Smckusick 	register int code;
23041480Smckusick 
23141480Smckusick 	dca = dca_addr[unit];
23241480Smckusick 	if ((dca->dca_ic & IC_IR) == 0)
23341480Smckusick 		return(0);
23441480Smckusick 	while (((code = dca->dca_iir) & IIR_NOPEND) == 0) {
23541480Smckusick 		code &= IIR_IMASK;
23641480Smckusick 		if (code == IIR_RLS)
23741480Smckusick 			dcaeint(unit, dca);
23841480Smckusick 		else if (code == IIR_RXRDY)
23941480Smckusick 			dcarint(unit, dca);
24041480Smckusick 		else if (code == IIR_TXRDY)
24141480Smckusick 			dcaxint(unit, dca);
24241480Smckusick 		else
24341480Smckusick 			dcamint(unit, dca);
24441480Smckusick 	}
24541480Smckusick 	return(1);
24641480Smckusick }
24741480Smckusick 
24841480Smckusick dcaeint(unit, dca)
24941480Smckusick 	register int unit;
25041480Smckusick 	register struct dcadevice *dca;
25141480Smckusick {
25241480Smckusick 	register struct tty *tp;
25341480Smckusick 	register int stat, c;
25441480Smckusick 
25541480Smckusick 	tp = &dca_tty[unit];
25641480Smckusick 	stat = dca->dca_lsr;
25741480Smckusick 	c = dca->dca_data & 0xff;
25841480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
25941480Smckusick #ifdef KGDB
26041480Smckusick 		/* we don't care about parity errors */
26141480Smckusick 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
26241480Smckusick 		    kgdb_dev == makedev(1, unit) && c == '!') {
26341480Smckusick 			printf("kgdb trap from dca%d\n", unit);
26441480Smckusick 			/* trap into kgdb */
26541480Smckusick 			asm("trap #15;");
26641480Smckusick 		}
26741480Smckusick #endif
26841480Smckusick 		return;
26941480Smckusick 	}
27041480Smckusick 	if (stat & (LSR_BI | LSR_FE))
27141480Smckusick 		c |= TTY_FE;
27241480Smckusick 	else if (stat & LSR_PE)
27341480Smckusick 		c |= TTY_PE;
27441480Smckusick 	else if (stat & LSR_OE)
27541480Smckusick 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
27641480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
27741480Smckusick }
27841480Smckusick 
27941480Smckusick dcarint(unit, dca)
28041480Smckusick 	int unit;
28141480Smckusick 	register struct dcadevice *dca;
28241480Smckusick {
28341480Smckusick 	register struct tty *tp;
28441480Smckusick 	register int c;
28541480Smckusick 
28641480Smckusick 	tp = &dca_tty[unit];
28741480Smckusick 	c = dca->dca_data;
28841480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
28941480Smckusick #ifdef KGDB
29041480Smckusick 		if (kgdb_dev == makedev(1, unit) && c == '!') {
29141480Smckusick 			printf("kgdb trap from dca%d\n", unit);
29241480Smckusick 			/* trap into kgdb */
29341480Smckusick 			asm("trap #15;");
29441480Smckusick 		}
29541480Smckusick #endif
29641480Smckusick 		return;
29741480Smckusick 	}
29841480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
29941480Smckusick }
30041480Smckusick 
30141480Smckusick /*ARGSUSED*/
30241480Smckusick dcaxint(unit, dca)
30341480Smckusick 	int unit;
30441480Smckusick 	struct dcadevice *dca;
30541480Smckusick {
30641480Smckusick 	register struct tty *tp;
30741480Smckusick 
30841480Smckusick 	tp = &dca_tty[unit];
30941480Smckusick 	tp->t_state &= ~TS_BUSY;
31041480Smckusick 	if (tp->t_state & TS_FLUSH)
31141480Smckusick 		tp->t_state &= ~TS_FLUSH;
31241480Smckusick 	if (tp->t_line)
31341480Smckusick 		(*linesw[tp->t_line].l_start)(tp);
31441480Smckusick 	else
31541480Smckusick 		dcastart(tp);
31641480Smckusick }
31741480Smckusick 
31841480Smckusick dcamint(unit, dca)
31941480Smckusick 	register int unit;
32041480Smckusick 	register struct dcadevice *dca;
32141480Smckusick {
32241480Smckusick 	register struct tty *tp;
32341480Smckusick 	register int stat;
32441480Smckusick 
32541480Smckusick 	tp = &dca_tty[unit];
32641480Smckusick 	stat = dca->dca_msr;
32741480Smckusick 	if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) {
32841480Smckusick 		if (stat & MSR_DCD)
32941480Smckusick 			(void) (*linesw[tp->t_line].l_modem)(tp, 1);
33041480Smckusick 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
33141480Smckusick 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
33241480Smckusick 	}
33341480Smckusick }
33441480Smckusick 
33541480Smckusick dcaioctl(dev, cmd, data, flag)
33641480Smckusick 	dev_t dev;
33741480Smckusick 	caddr_t data;
33841480Smckusick {
33941480Smckusick 	register struct tty *tp;
34041480Smckusick 	register int unit = UNIT(dev);
34141480Smckusick 	register struct dcadevice *dca;
34241480Smckusick 	register int error;
34341480Smckusick 
34441480Smckusick 	tp = &dca_tty[unit];
34541480Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
34641480Smckusick 	if (error >= 0)
34741480Smckusick 		return (error);
34841480Smckusick 	error = ttioctl(tp, cmd, data, flag);
34941480Smckusick 	if (error >= 0)
35041480Smckusick 		return (error);
35141480Smckusick 
35241480Smckusick 	dca = dca_addr[unit];
35341480Smckusick 	switch (cmd) {
35441480Smckusick 
35541480Smckusick 	case TIOCSBRK:
35641480Smckusick 		dca->dca_cfcr |= CFCR_SBREAK;
35741480Smckusick 		break;
35841480Smckusick 
35941480Smckusick 	case TIOCCBRK:
36041480Smckusick 		dca->dca_cfcr &= ~CFCR_SBREAK;
36141480Smckusick 		break;
36241480Smckusick 
36341480Smckusick 	case TIOCSDTR:
36441480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
36541480Smckusick 		break;
36641480Smckusick 
36741480Smckusick 	case TIOCCDTR:
36841480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
36941480Smckusick 		break;
37041480Smckusick 
37141480Smckusick 	case TIOCMSET:
37241480Smckusick 		(void) dcamctl(dev, *(int *)data, DMSET);
37341480Smckusick 		break;
37441480Smckusick 
37541480Smckusick 	case TIOCMBIS:
37641480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIS);
37741480Smckusick 		break;
37841480Smckusick 
37941480Smckusick 	case TIOCMBIC:
38041480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIC);
38141480Smckusick 		break;
38241480Smckusick 
38341480Smckusick 	case TIOCMGET:
38441480Smckusick 		*(int *)data = dcamctl(dev, 0, DMGET);
38541480Smckusick 		break;
38641480Smckusick 
38741480Smckusick 	default:
38841480Smckusick 		return (ENOTTY);
38941480Smckusick 	}
39041480Smckusick 	return (0);
39141480Smckusick }
39241480Smckusick 
39341480Smckusick dcaparam(tp, t)
39441480Smckusick 	register struct tty *tp;
39541480Smckusick 	register struct termios *t;
39641480Smckusick {
39741480Smckusick 	register struct dcadevice *dca;
39841480Smckusick 	register int cfcr, cflag = t->c_cflag;
39941480Smckusick 	int unit = UNIT(tp->t_dev);
40041480Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
40141480Smckusick 
40241480Smckusick 	/* check requested parameters */
40341480Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
40441480Smckusick                 return(EINVAL);
40541480Smckusick         /* and copy to tty */
40641480Smckusick         tp->t_ispeed = t->c_ispeed;
40741480Smckusick         tp->t_ospeed = t->c_ospeed;
40841480Smckusick         tp->t_cflag = cflag;
40941480Smckusick 
41041480Smckusick 	dca = dca_addr[unit];
41141480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
41241480Smckusick 	if (ospeed == 0) {
41341480Smckusick 		(void) dcamctl(unit, 0, DMSET);	/* hang up line */
41441480Smckusick 		return(0);
41541480Smckusick 	}
41641480Smckusick 	dca->dca_cfcr |= CFCR_DLAB;
41741480Smckusick 	dca->dca_data = ospeed & 0xFF;
41841480Smckusick 	dca->dca_ier = ospeed >> 8;
41941480Smckusick 	switch (cflag&CSIZE) {
42041480Smckusick 	case CS5:
42141480Smckusick 		cfcr = CFCR_5BITS; break;
42241480Smckusick 	case CS6:
42341480Smckusick 		cfcr = CFCR_6BITS; break;
42441480Smckusick 	case CS7:
42541480Smckusick 		cfcr = CFCR_7BITS; break;
42641480Smckusick 	case CS8:
42741480Smckusick 		cfcr = CFCR_8BITS; break;
42841480Smckusick 	}
42941480Smckusick 	if (cflag&PARENB) {
43041480Smckusick 		cfcr |= CFCR_PENAB;
43141480Smckusick 		if ((cflag&PARODD) == 0)
43241480Smckusick 			cfcr |= CFCR_PEVEN;
43341480Smckusick 	}
43441480Smckusick 	if (cflag&CSTOPB)
43541480Smckusick 		cfcr |= CFCR_STOPB;
43641480Smckusick 	dca->dca_cfcr = cfcr;
43741480Smckusick 	return(0);
43841480Smckusick }
43941480Smckusick 
44041480Smckusick dcastart(tp)
44141480Smckusick 	register struct tty *tp;
44241480Smckusick {
44341480Smckusick 	register struct dcadevice *dca;
44441480Smckusick 	int s, unit, c;
44541480Smckusick 
44641480Smckusick 	unit = UNIT(tp->t_dev);
44741480Smckusick 	dca = dca_addr[unit];
44841480Smckusick 	s = spltty();
44941480Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
45041480Smckusick 		goto out;
45141480Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
45241480Smckusick 		if (tp->t_state&TS_ASLEEP) {
45341480Smckusick 			tp->t_state &= ~TS_ASLEEP;
45441480Smckusick 			wakeup((caddr_t)&tp->t_outq);
45541480Smckusick 		}
45641480Smckusick 		if (tp->t_wsel) {
45741480Smckusick 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
45841480Smckusick 			tp->t_wsel = 0;
45941480Smckusick 			tp->t_state &= ~TS_WCOLL;
46041480Smckusick 		}
46141480Smckusick 	}
46241480Smckusick 	if (tp->t_outq.c_cc == 0)
46341480Smckusick 		goto out;
46441480Smckusick 	c = getc(&tp->t_outq);
46541480Smckusick 	tp->t_state |= TS_BUSY;
46641480Smckusick 	dca->dca_data = c;
46741480Smckusick out:
46841480Smckusick 	splx(s);
46941480Smckusick }
47041480Smckusick 
47141480Smckusick /*
47241480Smckusick  * Stop output on a line.
47341480Smckusick  */
47441480Smckusick /*ARGSUSED*/
47541480Smckusick dcastop(tp, flag)
47641480Smckusick 	register struct tty *tp;
47741480Smckusick {
47841480Smckusick 	register int s;
47941480Smckusick 
48041480Smckusick 	s = spltty();
48141480Smckusick 	if (tp->t_state & TS_BUSY) {
48241480Smckusick 		if ((tp->t_state&TS_TTSTOP)==0)
48341480Smckusick 			tp->t_state |= TS_FLUSH;
48441480Smckusick 	}
48541480Smckusick 	splx(s);
48641480Smckusick }
48741480Smckusick 
48841480Smckusick dcamctl(dev, bits, how)
48941480Smckusick 	dev_t dev;
49041480Smckusick 	int bits, how;
49141480Smckusick {
49241480Smckusick 	register struct dcadevice *dca;
49341480Smckusick 	register int unit;
49441480Smckusick 	int s;
49541480Smckusick 
49641480Smckusick 	unit = UNIT(dev);
49741480Smckusick 	dca = dca_addr[unit];
49841480Smckusick 	s = spltty();
49941480Smckusick 	switch (how) {
50041480Smckusick 
50141480Smckusick 	case DMSET:
50241480Smckusick 		dca->dca_mcr = bits;
50341480Smckusick 		break;
50441480Smckusick 
50541480Smckusick 	case DMBIS:
50641480Smckusick 		dca->dca_mcr |= bits;
50741480Smckusick 		break;
50841480Smckusick 
50941480Smckusick 	case DMBIC:
51041480Smckusick 		dca->dca_mcr &= ~bits;
51141480Smckusick 		break;
51241480Smckusick 
51341480Smckusick 	case DMGET:
51441480Smckusick 		bits = dca->dca_msr;
51541480Smckusick 		break;
51641480Smckusick 	}
51741480Smckusick 	(void) splx(s);
51841480Smckusick 	return(bits);
51941480Smckusick }
52041480Smckusick 
52141480Smckusick /*
52241480Smckusick  * Following are all routines needed for DCA to act as console
52341480Smckusick  */
52441480Smckusick #include "machine/cons.h"
52541480Smckusick 
52641480Smckusick dcacnprobe(cp)
52741480Smckusick 	struct consdev *cp;
52841480Smckusick {
52941480Smckusick 	int unit, i;
53041480Smckusick 	extern int dcaopen();
53141480Smckusick 
53241480Smckusick 	/* XXX: ick */
53341480Smckusick 	unit = CONUNIT;
53441480Smckusick 	dca_addr[CONUNIT] = CONADDR;
53541480Smckusick 
53641480Smckusick 	/* make sure hardware exists */
53741480Smckusick 	if (badaddr((short *)dca_addr[unit])) {
53841480Smckusick 		cp->cn_pri = CN_DEAD;
53941480Smckusick 		return;
54041480Smckusick 	}
54141480Smckusick 
54241480Smckusick 	/* locate the major number */
54341480Smckusick 	for (i = 0; i < nchrdev; i++)
54441480Smckusick 		if (cdevsw[i].d_open == dcaopen)
54541480Smckusick 			break;
54641480Smckusick 
54741480Smckusick 	/* initialize required fields */
54841480Smckusick 	cp->cn_dev = makedev(i, unit);
54941480Smckusick 	cp->cn_tp = &dca_tty[unit];
55041480Smckusick 	switch (dca_addr[unit]->dca_irid) {
55141480Smckusick 	case DCAID0:
55241480Smckusick 	case DCAID1:
55341480Smckusick 		cp->cn_pri = CN_NORMAL;
55441480Smckusick 		break;
55541480Smckusick 	case DCAREMID0:
55641480Smckusick 	case DCAREMID1:
55741480Smckusick 		cp->cn_pri = CN_REMOTE;
55841480Smckusick 		break;
55941480Smckusick 	default:
56041480Smckusick 		cp->cn_pri = CN_DEAD;
56141480Smckusick 		break;
56241480Smckusick 	}
56341480Smckusick }
56441480Smckusick 
56541480Smckusick dcacninit(cp)
56641480Smckusick 	struct consdev *cp;
56741480Smckusick {
56841480Smckusick 	int unit = UNIT(cp->cn_dev);
56941480Smckusick 
57041480Smckusick 	dcainit(unit);
57141480Smckusick 	dcaconsole = unit;
57241480Smckusick }
57341480Smckusick 
57441480Smckusick dcainit(unit)
57541480Smckusick 	int unit;
57641480Smckusick {
57741480Smckusick 	register struct dcadevice *dca;
57841480Smckusick 	int s, rate;
57941480Smckusick 	short stat;
58041480Smckusick 
58141480Smckusick #ifdef lint
58241480Smckusick 	stat = unit; if (stat) return;
58341480Smckusick #endif
58441480Smckusick 	dca = dca_addr[unit];
58541480Smckusick 	s = splhigh();
58641480Smckusick 	dca->dca_irid = 0xFF;
58741480Smckusick 	DELAY(100);
58841480Smckusick 	dca->dca_ic = IC_IE;
58941480Smckusick 	dca->dca_cfcr = CFCR_DLAB;
59041480Smckusick 	rate = ttspeedtab(dcadefaultrate, dcaspeedtab);
59141480Smckusick 	dca->dca_data = rate & 0xFF;
59241480Smckusick 	dca->dca_ier = rate >> 8;
59341480Smckusick 	dca->dca_cfcr = CFCR_8BITS;
59441480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
59541480Smckusick 	stat = dca->dca_iir;
59641480Smckusick 	splx(s);
59741480Smckusick }
59841480Smckusick 
59941480Smckusick dcacngetc(dev)
60041480Smckusick {
60141480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
60241480Smckusick 	short stat;
60341480Smckusick 	int c, s;
60441480Smckusick 
60541480Smckusick #ifdef lint
60641480Smckusick 	stat = dev; if (stat) return(0);
60741480Smckusick #endif
60841480Smckusick 	s = splhigh();
60941480Smckusick 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
61041480Smckusick 		;
61141480Smckusick 	c = dca->dca_data;
61241480Smckusick 	stat = dca->dca_iir;
61341480Smckusick 	splx(s);
61441480Smckusick 	return(c);
61541480Smckusick }
61641480Smckusick 
61741480Smckusick /*
61841480Smckusick  * Console kernel output character routine.
61941480Smckusick  */
62041480Smckusick dcacnputc(dev, c)
62141480Smckusick 	dev_t dev;
62241480Smckusick 	register int c;
62341480Smckusick {
62441480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
62541480Smckusick 	register int timo;
62641480Smckusick 	short stat;
62741480Smckusick 	int s = splhigh();
62841480Smckusick 
62941480Smckusick #ifdef lint
63041480Smckusick 	stat = dev; if (stat) return;
63141480Smckusick #endif
63241480Smckusick 	if (dcaconsole == -1) {
63341480Smckusick 		(void) dcainit(UNIT(dev));
63441480Smckusick 		dcaconsole = UNIT(dev);
63541480Smckusick 	}
63641480Smckusick 	/* wait for any pending transmission to finish */
63741480Smckusick 	timo = 50000;
63841480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
63941480Smckusick 		;
64041480Smckusick 	dca->dca_data = c;
64141480Smckusick 	/* wait for this transmission to complete */
64241480Smckusick 	timo = 1500000;
64341480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
64441480Smckusick 		;
64541480Smckusick 	/* clear any interrupts generated by this transmission */
64641480Smckusick 	stat = dca->dca_iir;
64741480Smckusick 	splx(s);
64841480Smckusick }
64941480Smckusick #endif
650