xref: /csrg-svn/sys/hp/dev/dca.c (revision 45788)
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*45788Sbostic  *	@(#)dca.c	7.8 (Berkeley) 12/16/90
841480Smckusick  */
941480Smckusick 
1041480Smckusick #include "dca.h"
1141480Smckusick #if NDCA > 0
1241480Smckusick /*
1341480Smckusick  *  98626/98644/internal serial interface
1441480Smckusick  */
15*45788Sbostic #include "sys/param.h"
16*45788Sbostic #include "sys/systm.h"
17*45788Sbostic #include "sys/ioctl.h"
18*45788Sbostic #include "sys/tty.h"
19*45788Sbostic #include "sys/user.h"
20*45788Sbostic #include "sys/conf.h"
21*45788Sbostic #include "sys/file.h"
22*45788Sbostic #include "sys/uio.h"
23*45788Sbostic #include "sys/kernel.h"
24*45788Sbostic #include "sys/syslog.h"
2541480Smckusick 
2641480Smckusick #include "device.h"
2741480Smckusick #include "dcareg.h"
28*45788Sbostic #include "../include/cpu.h"
29*45788Sbostic #include "../hp300/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;
13544762Skarels 	int error = 0;
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();
16044295Shibler 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
16141480Smckusick 	       (tp->t_state & TS_CARR_ON) == 0) {
16241480Smckusick 		tp->t_state |= TS_WOPEN;
16344295Shibler 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
16444295Shibler 		    ttopen, 0))
16544295Shibler 			break;
16641480Smckusick 	}
16741480Smckusick 	(void) spl0();
16844295Shibler 	if (error == 0)
16944295Shibler 		error = (*linesw[tp->t_line].l_open)(dev, tp);
17044295Shibler 	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;
22944318Shibler 	register u_char code;
23044318Shibler 	register struct tty *tp;
23141480Smckusick 
23241480Smckusick 	dca = dca_addr[unit];
23341480Smckusick 	if ((dca->dca_ic & IC_IR) == 0)
23441480Smckusick 		return(0);
23544318Shibler 	while (1) {
23644318Shibler 		code = dca->dca_iir;
23744318Shibler 		switch (code) {
23844318Shibler 		case IIR_NOPEND:
23944318Shibler 			return (1);
24044318Shibler 		case IIR_RXRDY:
24144318Shibler 			/* do time-critical read in-line */
24244318Shibler 			tp = &dca_tty[unit];
24344318Shibler 			code = dca->dca_data;
24444318Shibler 			if ((tp->t_state & TS_ISOPEN) == 0) {
24544318Shibler #ifdef KGDB
24644318Shibler 				if (kgdb_dev == makedev(1, unit) &&
24744318Shibler 				    code == '!') {
24844318Shibler 					printf("kgdb trap from dca%d\n", unit);
24944318Shibler 					/* trap into kgdb */
25044318Shibler 					asm("trap #15;");
25144318Shibler 				}
25244318Shibler #endif
25344318Shibler 			} else
25444318Shibler 				(*linesw[tp->t_line].l_rint)(code, tp);
25544318Shibler 			break;
25644318Shibler 		case IIR_TXRDY:
25744318Shibler 			tp = &dca_tty[unit];
25844318Shibler 			tp->t_state &=~ (TS_BUSY|TS_FLUSH);
25944318Shibler 			if (tp->t_line)
26044318Shibler 				(*linesw[tp->t_line].l_start)(tp);
26144318Shibler 			else
26244318Shibler 				dcastart(tp);
26344318Shibler 			break;
26444318Shibler 		case IIR_RLS:
26541480Smckusick 			dcaeint(unit, dca);
26644318Shibler 			break;
26744318Shibler 		default:
26844318Shibler 			if (code & IIR_NOPEND)
26944318Shibler 				return (1);
27044318Shibler 			log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n",
27144318Shibler 			    unit, code);
27244318Shibler 			/* fall through */
27344318Shibler 		case IIR_MLSC:
27441480Smckusick 			dcamint(unit, dca);
27544318Shibler 			break;
27644318Shibler 		}
27741480Smckusick 	}
27841480Smckusick }
27941480Smckusick 
28041480Smckusick dcaeint(unit, dca)
28141480Smckusick 	register int unit;
28241480Smckusick 	register struct dcadevice *dca;
28341480Smckusick {
28441480Smckusick 	register struct tty *tp;
28541480Smckusick 	register int stat, c;
28641480Smckusick 
28741480Smckusick 	tp = &dca_tty[unit];
28841480Smckusick 	stat = dca->dca_lsr;
28944318Shibler 	c = dca->dca_data;
29041480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
29141480Smckusick #ifdef KGDB
29241480Smckusick 		/* we don't care about parity errors */
29341480Smckusick 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
29441480Smckusick 		    kgdb_dev == makedev(1, unit) && c == '!') {
29541480Smckusick 			printf("kgdb trap from dca%d\n", unit);
29641480Smckusick 			/* trap into kgdb */
29741480Smckusick 			asm("trap #15;");
29841480Smckusick 		}
29941480Smckusick #endif
30041480Smckusick 		return;
30141480Smckusick 	}
30241480Smckusick 	if (stat & (LSR_BI | LSR_FE))
30341480Smckusick 		c |= TTY_FE;
30441480Smckusick 	else if (stat & LSR_PE)
30541480Smckusick 		c |= TTY_PE;
30641480Smckusick 	else if (stat & LSR_OE)
30741480Smckusick 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
30841480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
30941480Smckusick }
31041480Smckusick 
31141480Smckusick dcamint(unit, dca)
31241480Smckusick 	register int unit;
31341480Smckusick 	register struct dcadevice *dca;
31441480Smckusick {
31541480Smckusick 	register struct tty *tp;
31641480Smckusick 	register int stat;
31741480Smckusick 
31841480Smckusick 	tp = &dca_tty[unit];
31941480Smckusick 	stat = dca->dca_msr;
32044318Shibler 	if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) {
32141480Smckusick 		if (stat & MSR_DCD)
32244318Shibler 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
32341480Smckusick 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
32441480Smckusick 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
32544318Shibler 	} else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
32644318Shibler 		   (tp->t_flags & CRTSCTS)) {
32744318Shibler 		/* the line is up and we want to do rts/cts flow control */
32844318Shibler 		if (stat & MSR_CTS) {
32944318Shibler 			tp->t_state &=~ TS_TTSTOP;
33044318Shibler 			ttstart(tp);
33144318Shibler 		} else
33244318Shibler 			tp->t_state |= TS_TTSTOP;
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();
45044318Shibler 	if (tp->t_state & (TS_TIMEOUT|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;
46544318Shibler 	if (dca->dca_lsr & LSR_TXRDY) {
46644318Shibler 		c = getc(&tp->t_outq);
46744318Shibler 		tp->t_state |= TS_BUSY;
46844318Shibler 		dca->dca_data = c;
46944318Shibler 	}
47041480Smckusick out:
47141480Smckusick 	splx(s);
47241480Smckusick }
47341480Smckusick 
47441480Smckusick /*
47541480Smckusick  * Stop output on a line.
47641480Smckusick  */
47741480Smckusick /*ARGSUSED*/
47841480Smckusick dcastop(tp, flag)
47941480Smckusick 	register struct tty *tp;
48041480Smckusick {
48141480Smckusick 	register int s;
48241480Smckusick 
48341480Smckusick 	s = spltty();
48441480Smckusick 	if (tp->t_state & TS_BUSY) {
48541480Smckusick 		if ((tp->t_state&TS_TTSTOP)==0)
48641480Smckusick 			tp->t_state |= TS_FLUSH;
48741480Smckusick 	}
48841480Smckusick 	splx(s);
48941480Smckusick }
49041480Smckusick 
49141480Smckusick dcamctl(dev, bits, how)
49241480Smckusick 	dev_t dev;
49341480Smckusick 	int bits, how;
49441480Smckusick {
49541480Smckusick 	register struct dcadevice *dca;
49641480Smckusick 	register int unit;
49741480Smckusick 	int s;
49841480Smckusick 
49941480Smckusick 	unit = UNIT(dev);
50041480Smckusick 	dca = dca_addr[unit];
50141480Smckusick 	s = spltty();
50241480Smckusick 	switch (how) {
50341480Smckusick 
50441480Smckusick 	case DMSET:
50541480Smckusick 		dca->dca_mcr = bits;
50641480Smckusick 		break;
50741480Smckusick 
50841480Smckusick 	case DMBIS:
50941480Smckusick 		dca->dca_mcr |= bits;
51041480Smckusick 		break;
51141480Smckusick 
51241480Smckusick 	case DMBIC:
51341480Smckusick 		dca->dca_mcr &= ~bits;
51441480Smckusick 		break;
51541480Smckusick 
51641480Smckusick 	case DMGET:
51741480Smckusick 		bits = dca->dca_msr;
51841480Smckusick 		break;
51941480Smckusick 	}
52041480Smckusick 	(void) splx(s);
52141480Smckusick 	return(bits);
52241480Smckusick }
52341480Smckusick 
52441480Smckusick /*
52541480Smckusick  * Following are all routines needed for DCA to act as console
52641480Smckusick  */
527*45788Sbostic #include "../hp300/cons.h"
52841480Smckusick 
52941480Smckusick dcacnprobe(cp)
53041480Smckusick 	struct consdev *cp;
53141480Smckusick {
53241480Smckusick 	int unit, i;
53341480Smckusick 	extern int dcaopen();
53441480Smckusick 
53541480Smckusick 	/* XXX: ick */
53641480Smckusick 	unit = CONUNIT;
53741480Smckusick 	dca_addr[CONUNIT] = CONADDR;
53841480Smckusick 
53941480Smckusick 	/* make sure hardware exists */
54041480Smckusick 	if (badaddr((short *)dca_addr[unit])) {
54141480Smckusick 		cp->cn_pri = CN_DEAD;
54241480Smckusick 		return;
54341480Smckusick 	}
54441480Smckusick 
54541480Smckusick 	/* locate the major number */
54641480Smckusick 	for (i = 0; i < nchrdev; i++)
54741480Smckusick 		if (cdevsw[i].d_open == dcaopen)
54841480Smckusick 			break;
54941480Smckusick 
55041480Smckusick 	/* initialize required fields */
55141480Smckusick 	cp->cn_dev = makedev(i, unit);
55241480Smckusick 	cp->cn_tp = &dca_tty[unit];
55341480Smckusick 	switch (dca_addr[unit]->dca_irid) {
55441480Smckusick 	case DCAID0:
55541480Smckusick 	case DCAID1:
55641480Smckusick 		cp->cn_pri = CN_NORMAL;
55741480Smckusick 		break;
55841480Smckusick 	case DCAREMID0:
55941480Smckusick 	case DCAREMID1:
56041480Smckusick 		cp->cn_pri = CN_REMOTE;
56141480Smckusick 		break;
56241480Smckusick 	default:
56341480Smckusick 		cp->cn_pri = CN_DEAD;
56441480Smckusick 		break;
56541480Smckusick 	}
56641480Smckusick }
56741480Smckusick 
56841480Smckusick dcacninit(cp)
56941480Smckusick 	struct consdev *cp;
57041480Smckusick {
57141480Smckusick 	int unit = UNIT(cp->cn_dev);
57241480Smckusick 
57341480Smckusick 	dcainit(unit);
57441480Smckusick 	dcaconsole = unit;
57541480Smckusick }
57641480Smckusick 
57741480Smckusick dcainit(unit)
57841480Smckusick 	int unit;
57941480Smckusick {
58041480Smckusick 	register struct dcadevice *dca;
58141480Smckusick 	int s, rate;
58241480Smckusick 	short stat;
58341480Smckusick 
58441480Smckusick #ifdef lint
58541480Smckusick 	stat = unit; if (stat) return;
58641480Smckusick #endif
58741480Smckusick 	dca = dca_addr[unit];
58841480Smckusick 	s = splhigh();
58941480Smckusick 	dca->dca_irid = 0xFF;
59041480Smckusick 	DELAY(100);
59141480Smckusick 	dca->dca_ic = IC_IE;
59241480Smckusick 	dca->dca_cfcr = CFCR_DLAB;
59341480Smckusick 	rate = ttspeedtab(dcadefaultrate, dcaspeedtab);
59441480Smckusick 	dca->dca_data = rate & 0xFF;
59541480Smckusick 	dca->dca_ier = rate >> 8;
59641480Smckusick 	dca->dca_cfcr = CFCR_8BITS;
59741480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
59841480Smckusick 	stat = dca->dca_iir;
59941480Smckusick 	splx(s);
60041480Smckusick }
60141480Smckusick 
60241480Smckusick dcacngetc(dev)
60341480Smckusick {
60441480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
60541480Smckusick 	short stat;
60641480Smckusick 	int c, s;
60741480Smckusick 
60841480Smckusick #ifdef lint
60941480Smckusick 	stat = dev; if (stat) return(0);
61041480Smckusick #endif
61141480Smckusick 	s = splhigh();
61241480Smckusick 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
61341480Smckusick 		;
61441480Smckusick 	c = dca->dca_data;
61541480Smckusick 	stat = dca->dca_iir;
61641480Smckusick 	splx(s);
61741480Smckusick 	return(c);
61841480Smckusick }
61941480Smckusick 
62041480Smckusick /*
62141480Smckusick  * Console kernel output character routine.
62241480Smckusick  */
62341480Smckusick dcacnputc(dev, c)
62441480Smckusick 	dev_t dev;
62541480Smckusick 	register int c;
62641480Smckusick {
62741480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
62841480Smckusick 	register int timo;
62941480Smckusick 	short stat;
63041480Smckusick 	int s = splhigh();
63141480Smckusick 
63241480Smckusick #ifdef lint
63341480Smckusick 	stat = dev; if (stat) return;
63441480Smckusick #endif
63541480Smckusick 	if (dcaconsole == -1) {
63641480Smckusick 		(void) dcainit(UNIT(dev));
63741480Smckusick 		dcaconsole = UNIT(dev);
63841480Smckusick 	}
63941480Smckusick 	/* wait for any pending transmission to finish */
64041480Smckusick 	timo = 50000;
64141480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
64241480Smckusick 		;
64341480Smckusick 	dca->dca_data = c;
64441480Smckusick 	/* wait for this transmission to complete */
64541480Smckusick 	timo = 1500000;
64641480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
64741480Smckusick 		;
64841480Smckusick 	/* clear any interrupts generated by this transmission */
64941480Smckusick 	stat = dca->dca_iir;
65041480Smckusick 	splx(s);
65141480Smckusick }
65241480Smckusick #endif
653