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