xref: /csrg-svn/sys/hp/dev/dca.c (revision 42946)
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*42946Smarc  *	@(#)dca.c	7.3 (Berkeley) 06/06/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) {
14541480Smckusick 		ttychars(tp);
14641480Smckusick 		tp->t_iflag = TTYDEF_IFLAG;
14741480Smckusick 		tp->t_oflag = TTYDEF_OFLAG;
14841480Smckusick 		tp->t_cflag = TTYDEF_CFLAG;
14941480Smckusick 		tp->t_lflag = TTYDEF_LFLAG;
15041480Smckusick 		tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
15141480Smckusick 		dcaparam(tp, &tp->t_termios);
15241480Smckusick 		ttsetwater(tp);
15341480Smckusick 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
15441480Smckusick 		return (EBUSY);
15541480Smckusick 	(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
15641480Smckusick 	if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
15741480Smckusick 		tp->t_state |= TS_CARR_ON;
15841480Smckusick 	(void) spltty();
15941480Smckusick 	while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
16041480Smckusick 	       (tp->t_state & TS_CARR_ON) == 0) {
16141480Smckusick 		tp->t_state |= TS_WOPEN;
162*42946Smarc 		if ((error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
163*42946Smarc 				   ttopen, 0)) ||
164*42946Smarc 		    (error = ttclosed(tp))) {
16542353Smckusick 			tp->t_state &= ~TS_WOPEN;
16642353Smckusick 			(void) spl0();
16742353Smckusick 			return (error);
16842353Smckusick 		}
16941480Smckusick 	}
17041480Smckusick 	(void) spl0();
17141480Smckusick 	return ((*linesw[tp->t_line].l_open)(dev, tp));
17241480Smckusick }
17341480Smckusick 
17441480Smckusick /*ARGSUSED*/
17541480Smckusick dcaclose(dev, flag)
17641480Smckusick 	dev_t dev;
17741480Smckusick {
17841480Smckusick 	register struct tty *tp;
17941480Smckusick 	register struct dcadevice *dca;
18041480Smckusick 	register int unit;
18141480Smckusick 
18241480Smckusick 	unit = UNIT(dev);
18341480Smckusick 	dca = dca_addr[unit];
18441480Smckusick 	tp = &dca_tty[unit];
18541480Smckusick 	(*linesw[tp->t_line].l_close)(tp);
18641480Smckusick 	dca->dca_cfcr &= ~CFCR_SBREAK;
18741480Smckusick #ifdef KGDB
18841480Smckusick 	/* do not disable interrupts if debugging */
18941480Smckusick 	if (kgdb_dev != makedev(1, unit))
19041480Smckusick #endif
19141480Smckusick 	dca->dca_ier = 0;
19241480Smckusick 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
19341480Smckusick 	    (tp->t_state&TS_ISOPEN) == 0)
19441480Smckusick 		(void) dcamctl(dev, 0, DMSET);
19541480Smckusick 	ttyclose(tp);
19641480Smckusick 	return(0);
19741480Smckusick }
19841480Smckusick 
19941480Smckusick dcaread(dev, uio, flag)
20041480Smckusick 	dev_t dev;
20141480Smckusick 	struct uio *uio;
20241480Smckusick {
20341480Smckusick 	register struct tty *tp = &dca_tty[UNIT(dev)];
20441480Smckusick 
20541480Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
20641480Smckusick }
20741480Smckusick 
20841480Smckusick dcawrite(dev, uio, flag)
20941480Smckusick 	dev_t dev;
21041480Smckusick 	struct uio *uio;
21141480Smckusick {
21241480Smckusick 	int unit = UNIT(dev);
21341480Smckusick 	register struct tty *tp = &dca_tty[unit];
21441480Smckusick 
21542353Smckusick 	/*
21642353Smckusick 	 * (XXX) We disallow virtual consoles if the physical console is
21742353Smckusick 	 * a serial port.  This is in case there is a display attached that
21842353Smckusick 	 * is not the console.  In that situation we don't need/want the X
21942353Smckusick 	 * server taking over the console.
22042353Smckusick 	 */
22142353Smckusick 	if (constty && unit == dcaconsole)
22242353Smckusick 		constty = NULL;
22341480Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
22441480Smckusick }
22541480Smckusick 
22641480Smckusick dcaintr(unit)
22741480Smckusick 	register int unit;
22841480Smckusick {
22941480Smckusick 	register struct dcadevice *dca;
23041480Smckusick 	register int code;
23141480Smckusick 
23241480Smckusick 	dca = dca_addr[unit];
23341480Smckusick 	if ((dca->dca_ic & IC_IR) == 0)
23441480Smckusick 		return(0);
23541480Smckusick 	while (((code = dca->dca_iir) & IIR_NOPEND) == 0) {
23641480Smckusick 		code &= IIR_IMASK;
23741480Smckusick 		if (code == IIR_RLS)
23841480Smckusick 			dcaeint(unit, dca);
23941480Smckusick 		else if (code == IIR_RXRDY)
24041480Smckusick 			dcarint(unit, dca);
24141480Smckusick 		else if (code == IIR_TXRDY)
24241480Smckusick 			dcaxint(unit, dca);
24341480Smckusick 		else
24441480Smckusick 			dcamint(unit, dca);
24541480Smckusick 	}
24641480Smckusick 	return(1);
24741480Smckusick }
24841480Smckusick 
24941480Smckusick dcaeint(unit, dca)
25041480Smckusick 	register int unit;
25141480Smckusick 	register struct dcadevice *dca;
25241480Smckusick {
25341480Smckusick 	register struct tty *tp;
25441480Smckusick 	register int stat, c;
25541480Smckusick 
25641480Smckusick 	tp = &dca_tty[unit];
25741480Smckusick 	stat = dca->dca_lsr;
25841480Smckusick 	c = dca->dca_data & 0xff;
25941480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
26041480Smckusick #ifdef KGDB
26141480Smckusick 		/* we don't care about parity errors */
26241480Smckusick 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
26341480Smckusick 		    kgdb_dev == makedev(1, unit) && c == '!') {
26441480Smckusick 			printf("kgdb trap from dca%d\n", unit);
26541480Smckusick 			/* trap into kgdb */
26641480Smckusick 			asm("trap #15;");
26741480Smckusick 		}
26841480Smckusick #endif
26941480Smckusick 		return;
27041480Smckusick 	}
27141480Smckusick 	if (stat & (LSR_BI | LSR_FE))
27241480Smckusick 		c |= TTY_FE;
27341480Smckusick 	else if (stat & LSR_PE)
27441480Smckusick 		c |= TTY_PE;
27541480Smckusick 	else if (stat & LSR_OE)
27641480Smckusick 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
27741480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
27841480Smckusick }
27941480Smckusick 
28041480Smckusick dcarint(unit, dca)
28141480Smckusick 	int unit;
28241480Smckusick 	register struct dcadevice *dca;
28341480Smckusick {
28441480Smckusick 	register struct tty *tp;
28541480Smckusick 	register int c;
28641480Smckusick 
28741480Smckusick 	tp = &dca_tty[unit];
28841480Smckusick 	c = dca->dca_data;
28941480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
29041480Smckusick #ifdef KGDB
29141480Smckusick 		if (kgdb_dev == makedev(1, unit) && c == '!') {
29241480Smckusick 			printf("kgdb trap from dca%d\n", unit);
29341480Smckusick 			/* trap into kgdb */
29441480Smckusick 			asm("trap #15;");
29541480Smckusick 		}
29641480Smckusick #endif
29741480Smckusick 		return;
29841480Smckusick 	}
29941480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
30041480Smckusick }
30141480Smckusick 
30241480Smckusick /*ARGSUSED*/
30341480Smckusick dcaxint(unit, dca)
30441480Smckusick 	int unit;
30541480Smckusick 	struct dcadevice *dca;
30641480Smckusick {
30741480Smckusick 	register struct tty *tp;
30841480Smckusick 
30941480Smckusick 	tp = &dca_tty[unit];
31041480Smckusick 	tp->t_state &= ~TS_BUSY;
31141480Smckusick 	if (tp->t_state & TS_FLUSH)
31241480Smckusick 		tp->t_state &= ~TS_FLUSH;
31341480Smckusick 	if (tp->t_line)
31441480Smckusick 		(*linesw[tp->t_line].l_start)(tp);
31541480Smckusick 	else
31641480Smckusick 		dcastart(tp);
31741480Smckusick }
31841480Smckusick 
31941480Smckusick dcamint(unit, dca)
32041480Smckusick 	register int unit;
32141480Smckusick 	register struct dcadevice *dca;
32241480Smckusick {
32341480Smckusick 	register struct tty *tp;
32441480Smckusick 	register int stat;
32541480Smckusick 
32641480Smckusick 	tp = &dca_tty[unit];
32741480Smckusick 	stat = dca->dca_msr;
32841480Smckusick 	if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) {
32941480Smckusick 		if (stat & MSR_DCD)
33041480Smckusick 			(void) (*linesw[tp->t_line].l_modem)(tp, 1);
33141480Smckusick 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
33241480Smckusick 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
33341480Smckusick 	}
33441480Smckusick }
33541480Smckusick 
33641480Smckusick dcaioctl(dev, cmd, data, flag)
33741480Smckusick 	dev_t dev;
33841480Smckusick 	caddr_t data;
33941480Smckusick {
34041480Smckusick 	register struct tty *tp;
34141480Smckusick 	register int unit = UNIT(dev);
34241480Smckusick 	register struct dcadevice *dca;
34341480Smckusick 	register int error;
34441480Smckusick 
34541480Smckusick 	tp = &dca_tty[unit];
34641480Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
34741480Smckusick 	if (error >= 0)
34841480Smckusick 		return (error);
34941480Smckusick 	error = ttioctl(tp, cmd, data, flag);
35041480Smckusick 	if (error >= 0)
35141480Smckusick 		return (error);
35241480Smckusick 
35341480Smckusick 	dca = dca_addr[unit];
35441480Smckusick 	switch (cmd) {
35541480Smckusick 
35641480Smckusick 	case TIOCSBRK:
35741480Smckusick 		dca->dca_cfcr |= CFCR_SBREAK;
35841480Smckusick 		break;
35941480Smckusick 
36041480Smckusick 	case TIOCCBRK:
36141480Smckusick 		dca->dca_cfcr &= ~CFCR_SBREAK;
36241480Smckusick 		break;
36341480Smckusick 
36441480Smckusick 	case TIOCSDTR:
36541480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
36641480Smckusick 		break;
36741480Smckusick 
36841480Smckusick 	case TIOCCDTR:
36941480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
37041480Smckusick 		break;
37141480Smckusick 
37241480Smckusick 	case TIOCMSET:
37341480Smckusick 		(void) dcamctl(dev, *(int *)data, DMSET);
37441480Smckusick 		break;
37541480Smckusick 
37641480Smckusick 	case TIOCMBIS:
37741480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIS);
37841480Smckusick 		break;
37941480Smckusick 
38041480Smckusick 	case TIOCMBIC:
38141480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIC);
38241480Smckusick 		break;
38341480Smckusick 
38441480Smckusick 	case TIOCMGET:
38541480Smckusick 		*(int *)data = dcamctl(dev, 0, DMGET);
38641480Smckusick 		break;
38741480Smckusick 
38841480Smckusick 	default:
38941480Smckusick 		return (ENOTTY);
39041480Smckusick 	}
39141480Smckusick 	return (0);
39241480Smckusick }
39341480Smckusick 
39441480Smckusick dcaparam(tp, t)
39541480Smckusick 	register struct tty *tp;
39641480Smckusick 	register struct termios *t;
39741480Smckusick {
39841480Smckusick 	register struct dcadevice *dca;
39941480Smckusick 	register int cfcr, cflag = t->c_cflag;
40041480Smckusick 	int unit = UNIT(tp->t_dev);
40141480Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
40241480Smckusick 
40341480Smckusick 	/* check requested parameters */
40441480Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
40541480Smckusick                 return(EINVAL);
40641480Smckusick         /* and copy to tty */
40741480Smckusick         tp->t_ispeed = t->c_ispeed;
40841480Smckusick         tp->t_ospeed = t->c_ospeed;
40941480Smckusick         tp->t_cflag = cflag;
41041480Smckusick 
41141480Smckusick 	dca = dca_addr[unit];
41241480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
41341480Smckusick 	if (ospeed == 0) {
41441480Smckusick 		(void) dcamctl(unit, 0, DMSET);	/* hang up line */
41541480Smckusick 		return(0);
41641480Smckusick 	}
41741480Smckusick 	dca->dca_cfcr |= CFCR_DLAB;
41841480Smckusick 	dca->dca_data = ospeed & 0xFF;
41941480Smckusick 	dca->dca_ier = ospeed >> 8;
42041480Smckusick 	switch (cflag&CSIZE) {
42141480Smckusick 	case CS5:
42241480Smckusick 		cfcr = CFCR_5BITS; break;
42341480Smckusick 	case CS6:
42441480Smckusick 		cfcr = CFCR_6BITS; break;
42541480Smckusick 	case CS7:
42641480Smckusick 		cfcr = CFCR_7BITS; break;
42741480Smckusick 	case CS8:
42841480Smckusick 		cfcr = CFCR_8BITS; break;
42941480Smckusick 	}
43041480Smckusick 	if (cflag&PARENB) {
43141480Smckusick 		cfcr |= CFCR_PENAB;
43241480Smckusick 		if ((cflag&PARODD) == 0)
43341480Smckusick 			cfcr |= CFCR_PEVEN;
43441480Smckusick 	}
43541480Smckusick 	if (cflag&CSTOPB)
43641480Smckusick 		cfcr |= CFCR_STOPB;
43741480Smckusick 	dca->dca_cfcr = cfcr;
43841480Smckusick 	return(0);
43941480Smckusick }
44041480Smckusick 
44141480Smckusick dcastart(tp)
44241480Smckusick 	register struct tty *tp;
44341480Smckusick {
44441480Smckusick 	register struct dcadevice *dca;
44541480Smckusick 	int s, unit, c;
44641480Smckusick 
44741480Smckusick 	unit = UNIT(tp->t_dev);
44841480Smckusick 	dca = dca_addr[unit];
44941480Smckusick 	s = spltty();
45041480Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
45141480Smckusick 		goto out;
45241480Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
45341480Smckusick 		if (tp->t_state&TS_ASLEEP) {
45441480Smckusick 			tp->t_state &= ~TS_ASLEEP;
45541480Smckusick 			wakeup((caddr_t)&tp->t_outq);
45641480Smckusick 		}
45741480Smckusick 		if (tp->t_wsel) {
45841480Smckusick 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
45941480Smckusick 			tp->t_wsel = 0;
46041480Smckusick 			tp->t_state &= ~TS_WCOLL;
46141480Smckusick 		}
46241480Smckusick 	}
46341480Smckusick 	if (tp->t_outq.c_cc == 0)
46441480Smckusick 		goto out;
46541480Smckusick 	c = getc(&tp->t_outq);
46641480Smckusick 	tp->t_state |= TS_BUSY;
46741480Smckusick 	dca->dca_data = c;
46841480Smckusick out:
46941480Smckusick 	splx(s);
47041480Smckusick }
47141480Smckusick 
47241480Smckusick /*
47341480Smckusick  * Stop output on a line.
47441480Smckusick  */
47541480Smckusick /*ARGSUSED*/
47641480Smckusick dcastop(tp, flag)
47741480Smckusick 	register struct tty *tp;
47841480Smckusick {
47941480Smckusick 	register int s;
48041480Smckusick 
48141480Smckusick 	s = spltty();
48241480Smckusick 	if (tp->t_state & TS_BUSY) {
48341480Smckusick 		if ((tp->t_state&TS_TTSTOP)==0)
48441480Smckusick 			tp->t_state |= TS_FLUSH;
48541480Smckusick 	}
48641480Smckusick 	splx(s);
48741480Smckusick }
48841480Smckusick 
48941480Smckusick dcamctl(dev, bits, how)
49041480Smckusick 	dev_t dev;
49141480Smckusick 	int bits, how;
49241480Smckusick {
49341480Smckusick 	register struct dcadevice *dca;
49441480Smckusick 	register int unit;
49541480Smckusick 	int s;
49641480Smckusick 
49741480Smckusick 	unit = UNIT(dev);
49841480Smckusick 	dca = dca_addr[unit];
49941480Smckusick 	s = spltty();
50041480Smckusick 	switch (how) {
50141480Smckusick 
50241480Smckusick 	case DMSET:
50341480Smckusick 		dca->dca_mcr = bits;
50441480Smckusick 		break;
50541480Smckusick 
50641480Smckusick 	case DMBIS:
50741480Smckusick 		dca->dca_mcr |= bits;
50841480Smckusick 		break;
50941480Smckusick 
51041480Smckusick 	case DMBIC:
51141480Smckusick 		dca->dca_mcr &= ~bits;
51241480Smckusick 		break;
51341480Smckusick 
51441480Smckusick 	case DMGET:
51541480Smckusick 		bits = dca->dca_msr;
51641480Smckusick 		break;
51741480Smckusick 	}
51841480Smckusick 	(void) splx(s);
51941480Smckusick 	return(bits);
52041480Smckusick }
52141480Smckusick 
52241480Smckusick /*
52341480Smckusick  * Following are all routines needed for DCA to act as console
52441480Smckusick  */
52541480Smckusick #include "machine/cons.h"
52641480Smckusick 
52741480Smckusick dcacnprobe(cp)
52841480Smckusick 	struct consdev *cp;
52941480Smckusick {
53041480Smckusick 	int unit, i;
53141480Smckusick 	extern int dcaopen();
53241480Smckusick 
53341480Smckusick 	/* XXX: ick */
53441480Smckusick 	unit = CONUNIT;
53541480Smckusick 	dca_addr[CONUNIT] = CONADDR;
53641480Smckusick 
53741480Smckusick 	/* make sure hardware exists */
53841480Smckusick 	if (badaddr((short *)dca_addr[unit])) {
53941480Smckusick 		cp->cn_pri = CN_DEAD;
54041480Smckusick 		return;
54141480Smckusick 	}
54241480Smckusick 
54341480Smckusick 	/* locate the major number */
54441480Smckusick 	for (i = 0; i < nchrdev; i++)
54541480Smckusick 		if (cdevsw[i].d_open == dcaopen)
54641480Smckusick 			break;
54741480Smckusick 
54841480Smckusick 	/* initialize required fields */
54941480Smckusick 	cp->cn_dev = makedev(i, unit);
55041480Smckusick 	cp->cn_tp = &dca_tty[unit];
55141480Smckusick 	switch (dca_addr[unit]->dca_irid) {
55241480Smckusick 	case DCAID0:
55341480Smckusick 	case DCAID1:
55441480Smckusick 		cp->cn_pri = CN_NORMAL;
55541480Smckusick 		break;
55641480Smckusick 	case DCAREMID0:
55741480Smckusick 	case DCAREMID1:
55841480Smckusick 		cp->cn_pri = CN_REMOTE;
55941480Smckusick 		break;
56041480Smckusick 	default:
56141480Smckusick 		cp->cn_pri = CN_DEAD;
56241480Smckusick 		break;
56341480Smckusick 	}
56441480Smckusick }
56541480Smckusick 
56641480Smckusick dcacninit(cp)
56741480Smckusick 	struct consdev *cp;
56841480Smckusick {
56941480Smckusick 	int unit = UNIT(cp->cn_dev);
57041480Smckusick 
57141480Smckusick 	dcainit(unit);
57241480Smckusick 	dcaconsole = unit;
57341480Smckusick }
57441480Smckusick 
57541480Smckusick dcainit(unit)
57641480Smckusick 	int unit;
57741480Smckusick {
57841480Smckusick 	register struct dcadevice *dca;
57941480Smckusick 	int s, rate;
58041480Smckusick 	short stat;
58141480Smckusick 
58241480Smckusick #ifdef lint
58341480Smckusick 	stat = unit; if (stat) return;
58441480Smckusick #endif
58541480Smckusick 	dca = dca_addr[unit];
58641480Smckusick 	s = splhigh();
58741480Smckusick 	dca->dca_irid = 0xFF;
58841480Smckusick 	DELAY(100);
58941480Smckusick 	dca->dca_ic = IC_IE;
59041480Smckusick 	dca->dca_cfcr = CFCR_DLAB;
59141480Smckusick 	rate = ttspeedtab(dcadefaultrate, dcaspeedtab);
59241480Smckusick 	dca->dca_data = rate & 0xFF;
59341480Smckusick 	dca->dca_ier = rate >> 8;
59441480Smckusick 	dca->dca_cfcr = CFCR_8BITS;
59541480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
59641480Smckusick 	stat = dca->dca_iir;
59741480Smckusick 	splx(s);
59841480Smckusick }
59941480Smckusick 
60041480Smckusick dcacngetc(dev)
60141480Smckusick {
60241480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
60341480Smckusick 	short stat;
60441480Smckusick 	int c, s;
60541480Smckusick 
60641480Smckusick #ifdef lint
60741480Smckusick 	stat = dev; if (stat) return(0);
60841480Smckusick #endif
60941480Smckusick 	s = splhigh();
61041480Smckusick 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
61141480Smckusick 		;
61241480Smckusick 	c = dca->dca_data;
61341480Smckusick 	stat = dca->dca_iir;
61441480Smckusick 	splx(s);
61541480Smckusick 	return(c);
61641480Smckusick }
61741480Smckusick 
61841480Smckusick /*
61941480Smckusick  * Console kernel output character routine.
62041480Smckusick  */
62141480Smckusick dcacnputc(dev, c)
62241480Smckusick 	dev_t dev;
62341480Smckusick 	register int c;
62441480Smckusick {
62541480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
62641480Smckusick 	register int timo;
62741480Smckusick 	short stat;
62841480Smckusick 	int s = splhigh();
62941480Smckusick 
63041480Smckusick #ifdef lint
63141480Smckusick 	stat = dev; if (stat) return;
63241480Smckusick #endif
63341480Smckusick 	if (dcaconsole == -1) {
63441480Smckusick 		(void) dcainit(UNIT(dev));
63541480Smckusick 		dcaconsole = UNIT(dev);
63641480Smckusick 	}
63741480Smckusick 	/* wait for any pending transmission to finish */
63841480Smckusick 	timo = 50000;
63941480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
64041480Smckusick 		;
64141480Smckusick 	dca->dca_data = c;
64241480Smckusick 	/* wait for this transmission to complete */
64341480Smckusick 	timo = 1500000;
64441480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
64541480Smckusick 		;
64641480Smckusick 	/* clear any interrupts generated by this transmission */
64741480Smckusick 	stat = dca->dca_iir;
64841480Smckusick 	splx(s);
64941480Smckusick }
65041480Smckusick #endif
651