xref: /csrg-svn/sys/hp/dev/dca.c (revision 49130)
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*49130Skarels  *	@(#)dca.c	7.9 (Berkeley) 05/04/91
841480Smckusick  */
941480Smckusick 
1041480Smckusick #include "dca.h"
1141480Smckusick #if NDCA > 0
1241480Smckusick /*
1341480Smckusick  *  98626/98644/internal serial interface
1441480Smckusick  */
1545788Sbostic #include "sys/param.h"
1645788Sbostic #include "sys/systm.h"
1745788Sbostic #include "sys/ioctl.h"
1845788Sbostic #include "sys/tty.h"
19*49130Skarels #include "sys/proc.h"
2045788Sbostic #include "sys/conf.h"
2145788Sbostic #include "sys/file.h"
2245788Sbostic #include "sys/uio.h"
2345788Sbostic #include "sys/kernel.h"
2445788Sbostic #include "sys/syslog.h"
2541480Smckusick 
2641480Smckusick #include "device.h"
2741480Smckusick #include "dcareg.h"
28*49130Skarels #include "machine/cpu.h"
2945788Sbostic #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;
40*49130Skarels #ifdef DCACONSOLE
41*49130Skarels int	dcaconsole = DCACONSOLE;
42*49130Skarels #else
4341480Smckusick int	dcaconsole = -1;
44*49130Skarels #endif
45*49130Skarels int	dcaconsinit;
4641480Smckusick int	dcadefaultrate = TTYDEF_SPEED;
47*49130Skarels int	dcamajor;
4841480Smckusick struct	dcadevice *dca_addr[NDCA];
4941480Smckusick struct	tty dca_tty[NDCA];
5041480Smckusick struct	isr dcaisr[NDCA];
5141480Smckusick 
5241480Smckusick struct speedtab dcaspeedtab[] = {
5341480Smckusick 	0,	0,
5441480Smckusick 	50,	DCABRD(50),
5541480Smckusick 	75,	DCABRD(75),
5641480Smckusick 	110,	DCABRD(110),
5741480Smckusick 	134,	DCABRD(134),
5841480Smckusick 	150,	DCABRD(150),
5941480Smckusick 	200,	DCABRD(200),
6041480Smckusick 	300,	DCABRD(300),
6141480Smckusick 	600,	DCABRD(600),
6241480Smckusick 	1200,	DCABRD(1200),
6341480Smckusick 	1800,	DCABRD(1800),
6441480Smckusick 	2400,	DCABRD(2400),
6541480Smckusick 	4800,	DCABRD(4800),
6641480Smckusick 	9600,	DCABRD(9600),
6741480Smckusick 	19200,	DCABRD(19200),
6841480Smckusick 	38400,	DCABRD(38400),
6941480Smckusick 	-1,	-1
7041480Smckusick };
7141480Smckusick 
7241480Smckusick extern	struct tty *constty;
7341480Smckusick #ifdef KGDB
74*49130Skarels #include "machine/remote-sl.h"
75*49130Skarels 
7641480Smckusick extern int kgdb_dev;
7741480Smckusick extern int kgdb_rate;
7841480Smckusick extern int kgdb_debug_init;
7941480Smckusick #endif
8041480Smckusick 
8141480Smckusick #define	UNIT(x)		minor(x)
8241480Smckusick 
8341480Smckusick dcaprobe(hd)
8441480Smckusick 	register struct hp_device *hd;
8541480Smckusick {
8641480Smckusick 	register struct dcadevice *dca;
8741480Smckusick 	register int unit;
8841480Smckusick 
8941480Smckusick 	dca = (struct dcadevice *)hd->hp_addr;
9041480Smckusick 	if (dca->dca_irid != DCAID0 &&
9141480Smckusick 	    dca->dca_irid != DCAREMID0 &&
9241480Smckusick 	    dca->dca_irid != DCAID1 &&
9341480Smckusick 	    dca->dca_irid != DCAREMID1)
9441480Smckusick 		return (0);
9541480Smckusick 	unit = hd->hp_unit;
9641480Smckusick 	if (unit == dcaconsole)
9741480Smckusick 		DELAY(100000);
9841480Smckusick 	dca->dca_irid = 0xFF;
9941480Smckusick 	DELAY(100);
10041480Smckusick 
10141480Smckusick 	hd->hp_ipl = DCAIPL(dca->dca_ic);
10241480Smckusick 	dcaisr[unit].isr_ipl = hd->hp_ipl;
10341480Smckusick 	dcaisr[unit].isr_arg = unit;
10441480Smckusick 	dcaisr[unit].isr_intr = dcaintr;
10541480Smckusick 	dca_addr[unit] = dca;
10641480Smckusick 	dca_active |= 1 << unit;
10741480Smckusick 	dcasoftCAR = hd->hp_flags;
10841480Smckusick 	isrlink(&dcaisr[unit]);
10941480Smckusick #ifdef KGDB
110*49130Skarels 	if (kgdb_dev == makedev(dcamajor, unit)) {
11141480Smckusick 		if (dcaconsole == unit)
11241480Smckusick 			kgdb_dev = -1;	/* can't debug over console port */
11341480Smckusick 		else {
114*49130Skarels 			(void) dcainit(unit, kgdb_rate);
11541480Smckusick 			if (kgdb_debug_init) {
116*49130Skarels 				/*
117*49130Skarels 				 * Print prefix of device name,
118*49130Skarels 				 * let kgdb_connect print the rest.
119*49130Skarels 				 */
120*49130Skarels 				printf("dca%d: ", unit);
121*49130Skarels 				kgdb_connect(1);
12241480Smckusick 			} else
12341480Smckusick 				printf("dca%d: kgdb enabled\n", unit);
12441480Smckusick 		}
12541480Smckusick 	}
12641480Smckusick #endif
12741480Smckusick 	dca->dca_ic = IC_IE;
12841480Smckusick 	/*
129*49130Skarels 	 * Need to reset baud rate, etc. of next print so reset dcaconsinit.
130*49130Skarels 	 * Also make sure console is always "hardwired."
13141480Smckusick 	 */
13241480Smckusick 	if (unit == dcaconsole) {
133*49130Skarels 		dcaconsinit = 0;
13441480Smckusick 		dcasoftCAR |= (1 << unit);
13541480Smckusick 	}
13641480Smckusick 	return (1);
13741480Smckusick }
13841480Smckusick 
139*49130Skarels /* ARGSUSED */
140*49130Skarels #ifdef __STDC__
141*49130Skarels dcaopen(dev_t dev, int flag, int mode, struct proc *p)
142*49130Skarels #else
143*49130Skarels dcaopen(dev, flag, mode, p)
14441480Smckusick 	dev_t dev;
145*49130Skarels 	int flag, mode;
146*49130Skarels 	struct proc *p;
147*49130Skarels #endif
14841480Smckusick {
14941480Smckusick 	register struct tty *tp;
15041480Smckusick 	register int unit;
15144762Skarels 	int error = 0;
15241480Smckusick 
15341480Smckusick 	unit = UNIT(dev);
15441480Smckusick 	if (unit >= NDCA || (dca_active & (1 << unit)) == 0)
15541480Smckusick 		return (ENXIO);
15641480Smckusick 	tp = &dca_tty[unit];
15741480Smckusick 	tp->t_oproc = dcastart;
15841480Smckusick 	tp->t_param = dcaparam;
15941480Smckusick 	tp->t_dev = dev;
16041480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
16142950Smarc 		tp->t_state |= TS_WOPEN;
16241480Smckusick 		ttychars(tp);
163*49130Skarels 		if (tp->t_ispeed == 0) {
164*49130Skarels 			tp->t_iflag = TTYDEF_IFLAG;
165*49130Skarels 			tp->t_oflag = TTYDEF_OFLAG;
166*49130Skarels 			tp->t_cflag = TTYDEF_CFLAG;
167*49130Skarels 			tp->t_lflag = TTYDEF_LFLAG;
168*49130Skarels 			tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
169*49130Skarels 		}
17041480Smckusick 		dcaparam(tp, &tp->t_termios);
17141480Smckusick 		ttsetwater(tp);
172*49130Skarels 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
17341480Smckusick 		return (EBUSY);
17441480Smckusick 	(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
17541480Smckusick 	if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
17641480Smckusick 		tp->t_state |= TS_CARR_ON;
17741480Smckusick 	(void) spltty();
17844295Shibler 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
17941480Smckusick 	       (tp->t_state & TS_CARR_ON) == 0) {
18041480Smckusick 		tp->t_state |= TS_WOPEN;
18144295Shibler 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
18244295Shibler 		    ttopen, 0))
18344295Shibler 			break;
18441480Smckusick 	}
18541480Smckusick 	(void) spl0();
18644295Shibler 	if (error == 0)
18744295Shibler 		error = (*linesw[tp->t_line].l_open)(dev, tp);
18844295Shibler 	return (error);
18941480Smckusick }
19041480Smckusick 
19141480Smckusick /*ARGSUSED*/
19241480Smckusick dcaclose(dev, flag)
19341480Smckusick 	dev_t dev;
19441480Smckusick {
19541480Smckusick 	register struct tty *tp;
19641480Smckusick 	register struct dcadevice *dca;
19741480Smckusick 	register int unit;
19841480Smckusick 
19941480Smckusick 	unit = UNIT(dev);
20041480Smckusick 	dca = dca_addr[unit];
20141480Smckusick 	tp = &dca_tty[unit];
20241480Smckusick 	(*linesw[tp->t_line].l_close)(tp);
20341480Smckusick 	dca->dca_cfcr &= ~CFCR_SBREAK;
20441480Smckusick #ifdef KGDB
20541480Smckusick 	/* do not disable interrupts if debugging */
206*49130Skarels 	if (dev != kgdb_dev)
20741480Smckusick #endif
20841480Smckusick 	dca->dca_ier = 0;
209*49130Skarels 	(void) dcamctl(dev, 0, DMSET);
210*49130Skarels 	if (tp->t_state & TS_HUPCLS)
211*49130Skarels 		(*linesw[tp->t_line].l_modem)(tp, 0);
21241480Smckusick 	ttyclose(tp);
21341480Smckusick 	return(0);
21441480Smckusick }
21541480Smckusick 
21641480Smckusick dcaread(dev, uio, flag)
21741480Smckusick 	dev_t dev;
21841480Smckusick 	struct uio *uio;
21941480Smckusick {
22041480Smckusick 	register struct tty *tp = &dca_tty[UNIT(dev)];
22141480Smckusick 
22241480Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
22341480Smckusick }
22441480Smckusick 
22541480Smckusick dcawrite(dev, uio, flag)
22641480Smckusick 	dev_t dev;
22741480Smckusick 	struct uio *uio;
22841480Smckusick {
22941480Smckusick 	int unit = UNIT(dev);
23041480Smckusick 	register struct tty *tp = &dca_tty[unit];
23141480Smckusick 
23242353Smckusick 	/*
23342353Smckusick 	 * (XXX) We disallow virtual consoles if the physical console is
23442353Smckusick 	 * a serial port.  This is in case there is a display attached that
23542353Smckusick 	 * is not the console.  In that situation we don't need/want the X
23642353Smckusick 	 * server taking over the console.
23742353Smckusick 	 */
23842353Smckusick 	if (constty && unit == dcaconsole)
23942353Smckusick 		constty = NULL;
24041480Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24141480Smckusick }
24241480Smckusick 
24341480Smckusick dcaintr(unit)
24441480Smckusick 	register int unit;
24541480Smckusick {
24641480Smckusick 	register struct dcadevice *dca;
24744318Shibler 	register u_char code;
24844318Shibler 	register struct tty *tp;
24941480Smckusick 
25041480Smckusick 	dca = dca_addr[unit];
25141480Smckusick 	if ((dca->dca_ic & IC_IR) == 0)
25241480Smckusick 		return(0);
25344318Shibler 	while (1) {
25444318Shibler 		code = dca->dca_iir;
25544318Shibler 		switch (code) {
25644318Shibler 		case IIR_NOPEND:
25744318Shibler 			return (1);
25844318Shibler 		case IIR_RXRDY:
25944318Shibler 			/* do time-critical read in-line */
26044318Shibler 			tp = &dca_tty[unit];
26144318Shibler 			code = dca->dca_data;
26244318Shibler 			if ((tp->t_state & TS_ISOPEN) == 0) {
26344318Shibler #ifdef KGDB
264*49130Skarels 				if (kgdb_dev == makedev(dcamajor, unit) &&
265*49130Skarels 				    code == FRAME_END)
266*49130Skarels 					kgdb_connect(0); /* trap into kgdb */
26744318Shibler #endif
26844318Shibler 			} else
26944318Shibler 				(*linesw[tp->t_line].l_rint)(code, tp);
27044318Shibler 			break;
27144318Shibler 		case IIR_TXRDY:
27244318Shibler 			tp = &dca_tty[unit];
27344318Shibler 			tp->t_state &=~ (TS_BUSY|TS_FLUSH);
27444318Shibler 			if (tp->t_line)
27544318Shibler 				(*linesw[tp->t_line].l_start)(tp);
27644318Shibler 			else
27744318Shibler 				dcastart(tp);
27844318Shibler 			break;
27944318Shibler 		case IIR_RLS:
28041480Smckusick 			dcaeint(unit, dca);
28144318Shibler 			break;
28244318Shibler 		default:
28344318Shibler 			if (code & IIR_NOPEND)
28444318Shibler 				return (1);
28544318Shibler 			log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n",
28644318Shibler 			    unit, code);
28744318Shibler 			/* fall through */
28844318Shibler 		case IIR_MLSC:
28941480Smckusick 			dcamint(unit, dca);
29044318Shibler 			break;
29144318Shibler 		}
29241480Smckusick 	}
29341480Smckusick }
29441480Smckusick 
29541480Smckusick dcaeint(unit, dca)
29641480Smckusick 	register int unit;
29741480Smckusick 	register struct dcadevice *dca;
29841480Smckusick {
29941480Smckusick 	register struct tty *tp;
30041480Smckusick 	register int stat, c;
30141480Smckusick 
30241480Smckusick 	tp = &dca_tty[unit];
30341480Smckusick 	stat = dca->dca_lsr;
30444318Shibler 	c = dca->dca_data;
30541480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
30641480Smckusick #ifdef KGDB
30741480Smckusick 		/* we don't care about parity errors */
30841480Smckusick 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
309*49130Skarels 		    kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END)
310*49130Skarels 			kgdb_connect(0); /* trap into kgdb */
31141480Smckusick #endif
31241480Smckusick 		return;
31341480Smckusick 	}
31441480Smckusick 	if (stat & (LSR_BI | LSR_FE))
31541480Smckusick 		c |= TTY_FE;
31641480Smckusick 	else if (stat & LSR_PE)
31741480Smckusick 		c |= TTY_PE;
31841480Smckusick 	else if (stat & LSR_OE)
31941480Smckusick 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
32041480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
32141480Smckusick }
32241480Smckusick 
32341480Smckusick dcamint(unit, dca)
32441480Smckusick 	register int unit;
32541480Smckusick 	register struct dcadevice *dca;
32641480Smckusick {
32741480Smckusick 	register struct tty *tp;
32841480Smckusick 	register int stat;
32941480Smckusick 
33041480Smckusick 	tp = &dca_tty[unit];
33141480Smckusick 	stat = dca->dca_msr;
33244318Shibler 	if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) {
33341480Smckusick 		if (stat & MSR_DCD)
33444318Shibler 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
33541480Smckusick 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
33641480Smckusick 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
33744318Shibler 	} else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
33844318Shibler 		   (tp->t_flags & CRTSCTS)) {
33944318Shibler 		/* the line is up and we want to do rts/cts flow control */
34044318Shibler 		if (stat & MSR_CTS) {
34144318Shibler 			tp->t_state &=~ TS_TTSTOP;
34244318Shibler 			ttstart(tp);
34344318Shibler 		} else
34444318Shibler 			tp->t_state |= TS_TTSTOP;
34541480Smckusick 	}
34641480Smckusick }
34741480Smckusick 
34841480Smckusick dcaioctl(dev, cmd, data, flag)
34941480Smckusick 	dev_t dev;
35041480Smckusick 	caddr_t data;
35141480Smckusick {
35241480Smckusick 	register struct tty *tp;
35341480Smckusick 	register int unit = UNIT(dev);
35441480Smckusick 	register struct dcadevice *dca;
35541480Smckusick 	register int error;
35641480Smckusick 
35741480Smckusick 	tp = &dca_tty[unit];
35841480Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
35941480Smckusick 	if (error >= 0)
36041480Smckusick 		return (error);
36141480Smckusick 	error = ttioctl(tp, cmd, data, flag);
36241480Smckusick 	if (error >= 0)
36341480Smckusick 		return (error);
36441480Smckusick 
36541480Smckusick 	dca = dca_addr[unit];
36641480Smckusick 	switch (cmd) {
36741480Smckusick 
36841480Smckusick 	case TIOCSBRK:
36941480Smckusick 		dca->dca_cfcr |= CFCR_SBREAK;
37041480Smckusick 		break;
37141480Smckusick 
37241480Smckusick 	case TIOCCBRK:
37341480Smckusick 		dca->dca_cfcr &= ~CFCR_SBREAK;
37441480Smckusick 		break;
37541480Smckusick 
37641480Smckusick 	case TIOCSDTR:
37741480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
37841480Smckusick 		break;
37941480Smckusick 
38041480Smckusick 	case TIOCCDTR:
38141480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
38241480Smckusick 		break;
38341480Smckusick 
38441480Smckusick 	case TIOCMSET:
38541480Smckusick 		(void) dcamctl(dev, *(int *)data, DMSET);
38641480Smckusick 		break;
38741480Smckusick 
38841480Smckusick 	case TIOCMBIS:
38941480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIS);
39041480Smckusick 		break;
39141480Smckusick 
39241480Smckusick 	case TIOCMBIC:
39341480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIC);
39441480Smckusick 		break;
39541480Smckusick 
39641480Smckusick 	case TIOCMGET:
39741480Smckusick 		*(int *)data = dcamctl(dev, 0, DMGET);
39841480Smckusick 		break;
39941480Smckusick 
40041480Smckusick 	default:
40141480Smckusick 		return (ENOTTY);
40241480Smckusick 	}
40341480Smckusick 	return (0);
40441480Smckusick }
40541480Smckusick 
40641480Smckusick dcaparam(tp, t)
40741480Smckusick 	register struct tty *tp;
40841480Smckusick 	register struct termios *t;
40941480Smckusick {
41041480Smckusick 	register struct dcadevice *dca;
41141480Smckusick 	register int cfcr, cflag = t->c_cflag;
41241480Smckusick 	int unit = UNIT(tp->t_dev);
41341480Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
41441480Smckusick 
41541480Smckusick 	/* check requested parameters */
41641480Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
41741480Smckusick                 return(EINVAL);
41841480Smckusick         /* and copy to tty */
41941480Smckusick         tp->t_ispeed = t->c_ispeed;
42041480Smckusick         tp->t_ospeed = t->c_ospeed;
42141480Smckusick         tp->t_cflag = cflag;
42241480Smckusick 
42341480Smckusick 	dca = dca_addr[unit];
42441480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
42541480Smckusick 	if (ospeed == 0) {
42641480Smckusick 		(void) dcamctl(unit, 0, DMSET);	/* hang up line */
42741480Smckusick 		return(0);
42841480Smckusick 	}
42941480Smckusick 	dca->dca_cfcr |= CFCR_DLAB;
43041480Smckusick 	dca->dca_data = ospeed & 0xFF;
43141480Smckusick 	dca->dca_ier = ospeed >> 8;
43241480Smckusick 	switch (cflag&CSIZE) {
43341480Smckusick 	case CS5:
43441480Smckusick 		cfcr = CFCR_5BITS; break;
43541480Smckusick 	case CS6:
43641480Smckusick 		cfcr = CFCR_6BITS; break;
43741480Smckusick 	case CS7:
43841480Smckusick 		cfcr = CFCR_7BITS; break;
43941480Smckusick 	case CS8:
44041480Smckusick 		cfcr = CFCR_8BITS; break;
44141480Smckusick 	}
44241480Smckusick 	if (cflag&PARENB) {
44341480Smckusick 		cfcr |= CFCR_PENAB;
44441480Smckusick 		if ((cflag&PARODD) == 0)
44541480Smckusick 			cfcr |= CFCR_PEVEN;
44641480Smckusick 	}
44741480Smckusick 	if (cflag&CSTOPB)
44841480Smckusick 		cfcr |= CFCR_STOPB;
44941480Smckusick 	dca->dca_cfcr = cfcr;
45041480Smckusick 	return(0);
45141480Smckusick }
45241480Smckusick 
45341480Smckusick dcastart(tp)
45441480Smckusick 	register struct tty *tp;
45541480Smckusick {
45641480Smckusick 	register struct dcadevice *dca;
45741480Smckusick 	int s, unit, c;
45841480Smckusick 
45941480Smckusick 	unit = UNIT(tp->t_dev);
46041480Smckusick 	dca = dca_addr[unit];
46141480Smckusick 	s = spltty();
46244318Shibler 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
46341480Smckusick 		goto out;
46441480Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
46541480Smckusick 		if (tp->t_state&TS_ASLEEP) {
46641480Smckusick 			tp->t_state &= ~TS_ASLEEP;
46741480Smckusick 			wakeup((caddr_t)&tp->t_outq);
46841480Smckusick 		}
46941480Smckusick 		if (tp->t_wsel) {
47041480Smckusick 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
47141480Smckusick 			tp->t_wsel = 0;
47241480Smckusick 			tp->t_state &= ~TS_WCOLL;
47341480Smckusick 		}
47441480Smckusick 	}
47541480Smckusick 	if (tp->t_outq.c_cc == 0)
47641480Smckusick 		goto out;
47744318Shibler 	if (dca->dca_lsr & LSR_TXRDY) {
47844318Shibler 		c = getc(&tp->t_outq);
47944318Shibler 		tp->t_state |= TS_BUSY;
48044318Shibler 		dca->dca_data = c;
48144318Shibler 	}
48241480Smckusick out:
48341480Smckusick 	splx(s);
48441480Smckusick }
48541480Smckusick 
48641480Smckusick /*
48741480Smckusick  * Stop output on a line.
48841480Smckusick  */
48941480Smckusick /*ARGSUSED*/
49041480Smckusick dcastop(tp, flag)
49141480Smckusick 	register struct tty *tp;
49241480Smckusick {
49341480Smckusick 	register int s;
49441480Smckusick 
49541480Smckusick 	s = spltty();
49641480Smckusick 	if (tp->t_state & TS_BUSY) {
49741480Smckusick 		if ((tp->t_state&TS_TTSTOP)==0)
49841480Smckusick 			tp->t_state |= TS_FLUSH;
49941480Smckusick 	}
50041480Smckusick 	splx(s);
50141480Smckusick }
50241480Smckusick 
50341480Smckusick dcamctl(dev, bits, how)
50441480Smckusick 	dev_t dev;
50541480Smckusick 	int bits, how;
50641480Smckusick {
50741480Smckusick 	register struct dcadevice *dca;
50841480Smckusick 	register int unit;
50941480Smckusick 	int s;
51041480Smckusick 
51141480Smckusick 	unit = UNIT(dev);
51241480Smckusick 	dca = dca_addr[unit];
51341480Smckusick 	s = spltty();
51441480Smckusick 	switch (how) {
51541480Smckusick 
51641480Smckusick 	case DMSET:
51741480Smckusick 		dca->dca_mcr = bits;
51841480Smckusick 		break;
51941480Smckusick 
52041480Smckusick 	case DMBIS:
52141480Smckusick 		dca->dca_mcr |= bits;
52241480Smckusick 		break;
52341480Smckusick 
52441480Smckusick 	case DMBIC:
52541480Smckusick 		dca->dca_mcr &= ~bits;
52641480Smckusick 		break;
52741480Smckusick 
52841480Smckusick 	case DMGET:
52941480Smckusick 		bits = dca->dca_msr;
53041480Smckusick 		break;
53141480Smckusick 	}
53241480Smckusick 	(void) splx(s);
53341480Smckusick 	return(bits);
53441480Smckusick }
53541480Smckusick 
53641480Smckusick /*
53741480Smckusick  * Following are all routines needed for DCA to act as console
53841480Smckusick  */
53945788Sbostic #include "../hp300/cons.h"
54041480Smckusick 
54141480Smckusick dcacnprobe(cp)
54241480Smckusick 	struct consdev *cp;
54341480Smckusick {
54441480Smckusick 	int unit, i;
54541480Smckusick 
546*49130Skarels 	/* locate the major number */
547*49130Skarels 	for (dcamajor = 0; dcamajor < nchrdev; dcamajor++)
548*49130Skarels 		if (cdevsw[dcamajor].d_open == dcaopen)
549*49130Skarels 			break;
550*49130Skarels 
55141480Smckusick 	/* XXX: ick */
55241480Smckusick 	unit = CONUNIT;
55341480Smckusick 	dca_addr[CONUNIT] = CONADDR;
55441480Smckusick 
55541480Smckusick 	/* make sure hardware exists */
55641480Smckusick 	if (badaddr((short *)dca_addr[unit])) {
55741480Smckusick 		cp->cn_pri = CN_DEAD;
55841480Smckusick 		return;
55941480Smckusick 	}
56041480Smckusick 
56141480Smckusick 	/* initialize required fields */
562*49130Skarels 	cp->cn_dev = makedev(dcamajor, unit);
56341480Smckusick 	cp->cn_tp = &dca_tty[unit];
56441480Smckusick 	switch (dca_addr[unit]->dca_irid) {
56541480Smckusick 	case DCAID0:
56641480Smckusick 	case DCAID1:
56741480Smckusick 		cp->cn_pri = CN_NORMAL;
56841480Smckusick 		break;
56941480Smckusick 	case DCAREMID0:
57041480Smckusick 	case DCAREMID1:
57141480Smckusick 		cp->cn_pri = CN_REMOTE;
57241480Smckusick 		break;
57341480Smckusick 	default:
57441480Smckusick 		cp->cn_pri = CN_DEAD;
57541480Smckusick 		break;
57641480Smckusick 	}
577*49130Skarels 	/*
578*49130Skarels 	 * If dcmconsole is initialized, raise our priority.
579*49130Skarels 	 */
580*49130Skarels 	if (dcaconsole == unit)
581*49130Skarels 		cp->cn_pri = CN_REMOTE;
582*49130Skarels 	if (major(kgdb_dev) == 1)			/* XXX */
583*49130Skarels 		kgdb_dev = makedev(dcamajor, minor(kgdb_dev));
58441480Smckusick }
58541480Smckusick 
58641480Smckusick dcacninit(cp)
58741480Smckusick 	struct consdev *cp;
58841480Smckusick {
58941480Smckusick 	int unit = UNIT(cp->cn_dev);
59041480Smckusick 
591*49130Skarels 	dcainit(unit, dcadefaultrate);
59241480Smckusick 	dcaconsole = unit;
593*49130Skarels 	dcaconsinit = 1;
59441480Smckusick }
59541480Smckusick 
596*49130Skarels dcainit(unit, rate)
597*49130Skarels 	int unit, rate;
59841480Smckusick {
59941480Smckusick 	register struct dcadevice *dca;
600*49130Skarels 	int s;
60141480Smckusick 	short stat;
60241480Smckusick 
60341480Smckusick #ifdef lint
60441480Smckusick 	stat = unit; if (stat) return;
60541480Smckusick #endif
60641480Smckusick 	dca = dca_addr[unit];
60741480Smckusick 	s = splhigh();
60841480Smckusick 	dca->dca_irid = 0xFF;
60941480Smckusick 	DELAY(100);
61041480Smckusick 	dca->dca_ic = IC_IE;
61141480Smckusick 	dca->dca_cfcr = CFCR_DLAB;
612*49130Skarels 	rate = ttspeedtab(rate, dcaspeedtab);
61341480Smckusick 	dca->dca_data = rate & 0xFF;
61441480Smckusick 	dca->dca_ier = rate >> 8;
61541480Smckusick 	dca->dca_cfcr = CFCR_8BITS;
61641480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
61741480Smckusick 	stat = dca->dca_iir;
61841480Smckusick 	splx(s);
61941480Smckusick }
62041480Smckusick 
62141480Smckusick dcacngetc(dev)
62241480Smckusick {
62341480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
62441480Smckusick 	short stat;
62541480Smckusick 	int c, s;
62641480Smckusick 
62741480Smckusick #ifdef lint
62841480Smckusick 	stat = dev; if (stat) return(0);
62941480Smckusick #endif
63041480Smckusick 	s = splhigh();
63141480Smckusick 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
63241480Smckusick 		;
63341480Smckusick 	c = dca->dca_data;
63441480Smckusick 	stat = dca->dca_iir;
63541480Smckusick 	splx(s);
63641480Smckusick 	return(c);
63741480Smckusick }
63841480Smckusick 
63941480Smckusick /*
64041480Smckusick  * Console kernel output character routine.
64141480Smckusick  */
64241480Smckusick dcacnputc(dev, c)
64341480Smckusick 	dev_t dev;
64441480Smckusick 	register int c;
64541480Smckusick {
64641480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
64741480Smckusick 	register int timo;
64841480Smckusick 	short stat;
64941480Smckusick 	int s = splhigh();
65041480Smckusick 
65141480Smckusick #ifdef lint
65241480Smckusick 	stat = dev; if (stat) return;
65341480Smckusick #endif
654*49130Skarels #ifdef KGDB
655*49130Skarels 	if (dev != kgdb_dev)
656*49130Skarels #endif
657*49130Skarels 	if (dcaconsinit == 0) {
658*49130Skarels 		(void) dcainit(UNIT(dev), dcadefaultrate);
659*49130Skarels 		dcaconsinit = 1;
66041480Smckusick 	}
66141480Smckusick 	/* wait for any pending transmission to finish */
66241480Smckusick 	timo = 50000;
66341480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
66441480Smckusick 		;
66541480Smckusick 	dca->dca_data = c;
66641480Smckusick 	/* wait for this transmission to complete */
66741480Smckusick 	timo = 1500000;
66841480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
66941480Smckusick 		;
67041480Smckusick 	/* clear any interrupts generated by this transmission */
67141480Smckusick 	stat = dca->dca_iir;
67241480Smckusick 	splx(s);
67341480Smckusick }
67441480Smckusick #endif
675