xref: /csrg-svn/sys/hp/dev/dca.c (revision 41480)
1*41480Smckusick /*
2*41480Smckusick  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3*41480Smckusick  * All rights reserved.
4*41480Smckusick  *
5*41480Smckusick  * %sccs.include.redist.c%
6*41480Smckusick  *
7*41480Smckusick  *	@(#)dca.c	7.1 (Berkeley) 05/08/90
8*41480Smckusick  */
9*41480Smckusick 
10*41480Smckusick #include "dca.h"
11*41480Smckusick #if NDCA > 0
12*41480Smckusick /*
13*41480Smckusick  *  98626/98644/internal serial interface
14*41480Smckusick  */
15*41480Smckusick #include "param.h"
16*41480Smckusick #include "systm.h"
17*41480Smckusick #include "ioctl.h"
18*41480Smckusick #include "tty.h"
19*41480Smckusick #include "user.h"
20*41480Smckusick #include "conf.h"
21*41480Smckusick #include "file.h"
22*41480Smckusick #include "uio.h"
23*41480Smckusick #include "kernel.h"
24*41480Smckusick #include "syslog.h"
25*41480Smckusick 
26*41480Smckusick #include "device.h"
27*41480Smckusick #include "dcareg.h"
28*41480Smckusick #include "machine/cpu.h"
29*41480Smckusick #include "machine/isr.h"
30*41480Smckusick 
31*41480Smckusick int	dcaprobe();
32*41480Smckusick struct	driver dcadriver = {
33*41480Smckusick 	dcaprobe, "dca",
34*41480Smckusick };
35*41480Smckusick 
36*41480Smckusick int	dcastart(), dcaparam(), dcaintr();
37*41480Smckusick int	dcasoftCAR;
38*41480Smckusick int	dca_active;
39*41480Smckusick int	ndca = NDCA;
40*41480Smckusick int	dcaconsole = -1;
41*41480Smckusick int	dcadefaultrate = TTYDEF_SPEED;
42*41480Smckusick struct	dcadevice *dca_addr[NDCA];
43*41480Smckusick struct	tty dca_tty[NDCA];
44*41480Smckusick struct	isr dcaisr[NDCA];
45*41480Smckusick 
46*41480Smckusick struct speedtab dcaspeedtab[] = {
47*41480Smckusick 	0,	0,
48*41480Smckusick 	50,	DCABRD(50),
49*41480Smckusick 	75,	DCABRD(75),
50*41480Smckusick 	110,	DCABRD(110),
51*41480Smckusick 	134,	DCABRD(134),
52*41480Smckusick 	150,	DCABRD(150),
53*41480Smckusick 	200,	DCABRD(200),
54*41480Smckusick 	300,	DCABRD(300),
55*41480Smckusick 	600,	DCABRD(600),
56*41480Smckusick 	1200,	DCABRD(1200),
57*41480Smckusick 	1800,	DCABRD(1800),
58*41480Smckusick 	2400,	DCABRD(2400),
59*41480Smckusick 	4800,	DCABRD(4800),
60*41480Smckusick 	9600,	DCABRD(9600),
61*41480Smckusick 	19200,	DCABRD(19200),
62*41480Smckusick 	38400,	DCABRD(38400),
63*41480Smckusick 	-1,	-1
64*41480Smckusick };
65*41480Smckusick 
66*41480Smckusick extern	struct tty *constty;
67*41480Smckusick #ifdef KGDB
68*41480Smckusick extern int kgdb_dev;
69*41480Smckusick extern int kgdb_rate;
70*41480Smckusick extern int kgdb_debug_init;
71*41480Smckusick #endif
72*41480Smckusick 
73*41480Smckusick #define	UNIT(x)		minor(x)
74*41480Smckusick 
75*41480Smckusick dcaprobe(hd)
76*41480Smckusick 	register struct hp_device *hd;
77*41480Smckusick {
78*41480Smckusick 	register struct dcadevice *dca;
79*41480Smckusick 	register int unit;
80*41480Smckusick 
81*41480Smckusick 	dca = (struct dcadevice *)hd->hp_addr;
82*41480Smckusick 	if (dca->dca_irid != DCAID0 &&
83*41480Smckusick 	    dca->dca_irid != DCAREMID0 &&
84*41480Smckusick 	    dca->dca_irid != DCAID1 &&
85*41480Smckusick 	    dca->dca_irid != DCAREMID1)
86*41480Smckusick 		return (0);
87*41480Smckusick 	unit = hd->hp_unit;
88*41480Smckusick 	if (unit == dcaconsole)
89*41480Smckusick 		DELAY(100000);
90*41480Smckusick 	dca->dca_irid = 0xFF;
91*41480Smckusick 	DELAY(100);
92*41480Smckusick 
93*41480Smckusick 	hd->hp_ipl = DCAIPL(dca->dca_ic);
94*41480Smckusick 	dcaisr[unit].isr_ipl = hd->hp_ipl;
95*41480Smckusick 	dcaisr[unit].isr_arg = unit;
96*41480Smckusick 	dcaisr[unit].isr_intr = dcaintr;
97*41480Smckusick 	dca_addr[unit] = dca;
98*41480Smckusick 	dca_active |= 1 << unit;
99*41480Smckusick 	dcasoftCAR = hd->hp_flags;
100*41480Smckusick 	isrlink(&dcaisr[unit]);
101*41480Smckusick #ifdef KGDB
102*41480Smckusick 	if (kgdb_dev == makedev(1, unit)) {
103*41480Smckusick 		if (dcaconsole == unit)
104*41480Smckusick 			kgdb_dev = -1;	/* can't debug over console port */
105*41480Smckusick 		else {
106*41480Smckusick 			(void) dcainit(unit);
107*41480Smckusick 			dcaconsole = -2; /* XXX */
108*41480Smckusick 			if (kgdb_debug_init) {
109*41480Smckusick 				printf("dca%d: kgdb waiting...", unit);
110*41480Smckusick 				/* trap into kgdb */
111*41480Smckusick 				asm("trap #15;");
112*41480Smckusick 				printf("connected.\n");
113*41480Smckusick 			} else
114*41480Smckusick 				printf("dca%d: kgdb enabled\n", unit);
115*41480Smckusick 		}
116*41480Smckusick 	}
117*41480Smckusick #endif
118*41480Smckusick 	dca->dca_ic = IC_IE;
119*41480Smckusick 	/*
120*41480Smckusick 	 * Need to reset baud rate, etc. of next print so reset dcaconsole.
121*41480Smckusick 	 * Also make sure console is always "hardwired"
122*41480Smckusick 	 */
123*41480Smckusick 	if (unit == dcaconsole) {
124*41480Smckusick 		dcaconsole = -1;
125*41480Smckusick 		dcasoftCAR |= (1 << unit);
126*41480Smckusick 	}
127*41480Smckusick 	return (1);
128*41480Smckusick }
129*41480Smckusick 
130*41480Smckusick dcaopen(dev, flag)
131*41480Smckusick 	dev_t dev;
132*41480Smckusick {
133*41480Smckusick 	register struct tty *tp;
134*41480Smckusick 	register int unit;
135*41480Smckusick 
136*41480Smckusick 	unit = UNIT(dev);
137*41480Smckusick 	if (unit >= NDCA || (dca_active & (1 << unit)) == 0)
138*41480Smckusick 		return (ENXIO);
139*41480Smckusick 	tp = &dca_tty[unit];
140*41480Smckusick 	tp->t_oproc = dcastart;
141*41480Smckusick 	tp->t_param = dcaparam;
142*41480Smckusick 	tp->t_dev = dev;
143*41480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
144*41480Smckusick 		ttychars(tp);
145*41480Smckusick 		tp->t_iflag = TTYDEF_IFLAG;
146*41480Smckusick 		tp->t_oflag = TTYDEF_OFLAG;
147*41480Smckusick 		tp->t_cflag = TTYDEF_CFLAG;
148*41480Smckusick 		tp->t_lflag = TTYDEF_LFLAG;
149*41480Smckusick 		tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
150*41480Smckusick 		dcaparam(tp, &tp->t_termios);
151*41480Smckusick 		ttsetwater(tp);
152*41480Smckusick 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
153*41480Smckusick 		return (EBUSY);
154*41480Smckusick 	(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
155*41480Smckusick 	if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
156*41480Smckusick 		tp->t_state |= TS_CARR_ON;
157*41480Smckusick 	(void) spltty();
158*41480Smckusick 	while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
159*41480Smckusick 	       (tp->t_state & TS_CARR_ON) == 0) {
160*41480Smckusick 		tp->t_state |= TS_WOPEN;
161*41480Smckusick 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
162*41480Smckusick 	}
163*41480Smckusick 	(void) spl0();
164*41480Smckusick 	return ((*linesw[tp->t_line].l_open)(dev, tp));
165*41480Smckusick }
166*41480Smckusick 
167*41480Smckusick /*ARGSUSED*/
168*41480Smckusick dcaclose(dev, flag)
169*41480Smckusick 	dev_t dev;
170*41480Smckusick {
171*41480Smckusick 	register struct tty *tp;
172*41480Smckusick 	register struct dcadevice *dca;
173*41480Smckusick 	register int unit;
174*41480Smckusick 
175*41480Smckusick 	unit = UNIT(dev);
176*41480Smckusick 	dca = dca_addr[unit];
177*41480Smckusick 	tp = &dca_tty[unit];
178*41480Smckusick 	(*linesw[tp->t_line].l_close)(tp);
179*41480Smckusick 	dca->dca_cfcr &= ~CFCR_SBREAK;
180*41480Smckusick #ifdef KGDB
181*41480Smckusick 	/* do not disable interrupts if debugging */
182*41480Smckusick 	if (kgdb_dev != makedev(1, unit))
183*41480Smckusick #endif
184*41480Smckusick 	dca->dca_ier = 0;
185*41480Smckusick 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
186*41480Smckusick 	    (tp->t_state&TS_ISOPEN) == 0)
187*41480Smckusick 		(void) dcamctl(dev, 0, DMSET);
188*41480Smckusick 	ttyclose(tp);
189*41480Smckusick 	return(0);
190*41480Smckusick }
191*41480Smckusick 
192*41480Smckusick dcaread(dev, uio, flag)
193*41480Smckusick 	dev_t dev;
194*41480Smckusick 	struct uio *uio;
195*41480Smckusick {
196*41480Smckusick 	register struct tty *tp = &dca_tty[UNIT(dev)];
197*41480Smckusick 
198*41480Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
199*41480Smckusick }
200*41480Smckusick 
201*41480Smckusick dcawrite(dev, uio, flag)
202*41480Smckusick 	dev_t dev;
203*41480Smckusick 	struct uio *uio;
204*41480Smckusick {
205*41480Smckusick 	int unit = UNIT(dev);
206*41480Smckusick 	register struct tty *tp = &dca_tty[unit];
207*41480Smckusick 
208*41480Smckusick 	if (unit == dcaconsole && constty &&
209*41480Smckusick 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
210*41480Smckusick 		tp = constty;
211*41480Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
212*41480Smckusick }
213*41480Smckusick 
214*41480Smckusick dcaintr(unit)
215*41480Smckusick 	register int unit;
216*41480Smckusick {
217*41480Smckusick 	register struct dcadevice *dca;
218*41480Smckusick 	register int code;
219*41480Smckusick 
220*41480Smckusick 	dca = dca_addr[unit];
221*41480Smckusick 	if ((dca->dca_ic & IC_IR) == 0)
222*41480Smckusick 		return(0);
223*41480Smckusick 	while (((code = dca->dca_iir) & IIR_NOPEND) == 0) {
224*41480Smckusick 		code &= IIR_IMASK;
225*41480Smckusick 		if (code == IIR_RLS)
226*41480Smckusick 			dcaeint(unit, dca);
227*41480Smckusick 		else if (code == IIR_RXRDY)
228*41480Smckusick 			dcarint(unit, dca);
229*41480Smckusick 		else if (code == IIR_TXRDY)
230*41480Smckusick 			dcaxint(unit, dca);
231*41480Smckusick 		else
232*41480Smckusick 			dcamint(unit, dca);
233*41480Smckusick 	}
234*41480Smckusick 	return(1);
235*41480Smckusick }
236*41480Smckusick 
237*41480Smckusick dcaeint(unit, dca)
238*41480Smckusick 	register int unit;
239*41480Smckusick 	register struct dcadevice *dca;
240*41480Smckusick {
241*41480Smckusick 	register struct tty *tp;
242*41480Smckusick 	register int stat, c;
243*41480Smckusick 
244*41480Smckusick 	tp = &dca_tty[unit];
245*41480Smckusick 	stat = dca->dca_lsr;
246*41480Smckusick 	c = dca->dca_data & 0xff;
247*41480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
248*41480Smckusick #ifdef KGDB
249*41480Smckusick 		/* we don't care about parity errors */
250*41480Smckusick 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
251*41480Smckusick 		    kgdb_dev == makedev(1, unit) && c == '!') {
252*41480Smckusick 			printf("kgdb trap from dca%d\n", unit);
253*41480Smckusick 			/* trap into kgdb */
254*41480Smckusick 			asm("trap #15;");
255*41480Smckusick 		}
256*41480Smckusick #endif
257*41480Smckusick 		return;
258*41480Smckusick 	}
259*41480Smckusick 	if (stat & (LSR_BI | LSR_FE))
260*41480Smckusick 		c |= TTY_FE;
261*41480Smckusick 	else if (stat & LSR_PE)
262*41480Smckusick 		c |= TTY_PE;
263*41480Smckusick 	else if (stat & LSR_OE)
264*41480Smckusick 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
265*41480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
266*41480Smckusick }
267*41480Smckusick 
268*41480Smckusick dcarint(unit, dca)
269*41480Smckusick 	int unit;
270*41480Smckusick 	register struct dcadevice *dca;
271*41480Smckusick {
272*41480Smckusick 	register struct tty *tp;
273*41480Smckusick 	register int c;
274*41480Smckusick 
275*41480Smckusick 	tp = &dca_tty[unit];
276*41480Smckusick 	c = dca->dca_data;
277*41480Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
278*41480Smckusick #ifdef KGDB
279*41480Smckusick 		if (kgdb_dev == makedev(1, unit) && c == '!') {
280*41480Smckusick 			printf("kgdb trap from dca%d\n", unit);
281*41480Smckusick 			/* trap into kgdb */
282*41480Smckusick 			asm("trap #15;");
283*41480Smckusick 		}
284*41480Smckusick #endif
285*41480Smckusick 		return;
286*41480Smckusick 	}
287*41480Smckusick 	(*linesw[tp->t_line].l_rint)(c, tp);
288*41480Smckusick }
289*41480Smckusick 
290*41480Smckusick /*ARGSUSED*/
291*41480Smckusick dcaxint(unit, dca)
292*41480Smckusick 	int unit;
293*41480Smckusick 	struct dcadevice *dca;
294*41480Smckusick {
295*41480Smckusick 	register struct tty *tp;
296*41480Smckusick 
297*41480Smckusick 	tp = &dca_tty[unit];
298*41480Smckusick 	tp->t_state &= ~TS_BUSY;
299*41480Smckusick 	if (tp->t_state & TS_FLUSH)
300*41480Smckusick 		tp->t_state &= ~TS_FLUSH;
301*41480Smckusick 	if (tp->t_line)
302*41480Smckusick 		(*linesw[tp->t_line].l_start)(tp);
303*41480Smckusick 	else
304*41480Smckusick 		dcastart(tp);
305*41480Smckusick }
306*41480Smckusick 
307*41480Smckusick dcamint(unit, dca)
308*41480Smckusick 	register int unit;
309*41480Smckusick 	register struct dcadevice *dca;
310*41480Smckusick {
311*41480Smckusick 	register struct tty *tp;
312*41480Smckusick 	register int stat;
313*41480Smckusick 
314*41480Smckusick 	tp = &dca_tty[unit];
315*41480Smckusick 	stat = dca->dca_msr;
316*41480Smckusick 	if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) {
317*41480Smckusick 		if (stat & MSR_DCD)
318*41480Smckusick 			(void) (*linesw[tp->t_line].l_modem)(tp, 1);
319*41480Smckusick 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
320*41480Smckusick 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
321*41480Smckusick 	}
322*41480Smckusick }
323*41480Smckusick 
324*41480Smckusick dcaioctl(dev, cmd, data, flag)
325*41480Smckusick 	dev_t dev;
326*41480Smckusick 	caddr_t data;
327*41480Smckusick {
328*41480Smckusick 	register struct tty *tp;
329*41480Smckusick 	register int unit = UNIT(dev);
330*41480Smckusick 	register struct dcadevice *dca;
331*41480Smckusick 	register int error;
332*41480Smckusick 
333*41480Smckusick 	tp = &dca_tty[unit];
334*41480Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
335*41480Smckusick 	if (error >= 0)
336*41480Smckusick 		return (error);
337*41480Smckusick 	error = ttioctl(tp, cmd, data, flag);
338*41480Smckusick 	if (error >= 0)
339*41480Smckusick 		return (error);
340*41480Smckusick 
341*41480Smckusick 	dca = dca_addr[unit];
342*41480Smckusick 	switch (cmd) {
343*41480Smckusick 
344*41480Smckusick 	case TIOCSBRK:
345*41480Smckusick 		dca->dca_cfcr |= CFCR_SBREAK;
346*41480Smckusick 		break;
347*41480Smckusick 
348*41480Smckusick 	case TIOCCBRK:
349*41480Smckusick 		dca->dca_cfcr &= ~CFCR_SBREAK;
350*41480Smckusick 		break;
351*41480Smckusick 
352*41480Smckusick 	case TIOCSDTR:
353*41480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
354*41480Smckusick 		break;
355*41480Smckusick 
356*41480Smckusick 	case TIOCCDTR:
357*41480Smckusick 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
358*41480Smckusick 		break;
359*41480Smckusick 
360*41480Smckusick 	case TIOCMSET:
361*41480Smckusick 		(void) dcamctl(dev, *(int *)data, DMSET);
362*41480Smckusick 		break;
363*41480Smckusick 
364*41480Smckusick 	case TIOCMBIS:
365*41480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIS);
366*41480Smckusick 		break;
367*41480Smckusick 
368*41480Smckusick 	case TIOCMBIC:
369*41480Smckusick 		(void) dcamctl(dev, *(int *)data, DMBIC);
370*41480Smckusick 		break;
371*41480Smckusick 
372*41480Smckusick 	case TIOCMGET:
373*41480Smckusick 		*(int *)data = dcamctl(dev, 0, DMGET);
374*41480Smckusick 		break;
375*41480Smckusick 
376*41480Smckusick 	default:
377*41480Smckusick 		return (ENOTTY);
378*41480Smckusick 	}
379*41480Smckusick 	return (0);
380*41480Smckusick }
381*41480Smckusick 
382*41480Smckusick dcaparam(tp, t)
383*41480Smckusick 	register struct tty *tp;
384*41480Smckusick 	register struct termios *t;
385*41480Smckusick {
386*41480Smckusick 	register struct dcadevice *dca;
387*41480Smckusick 	register int cfcr, cflag = t->c_cflag;
388*41480Smckusick 	int unit = UNIT(tp->t_dev);
389*41480Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
390*41480Smckusick 
391*41480Smckusick 	/* check requested parameters */
392*41480Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
393*41480Smckusick                 return(EINVAL);
394*41480Smckusick         /* and copy to tty */
395*41480Smckusick         tp->t_ispeed = t->c_ispeed;
396*41480Smckusick         tp->t_ospeed = t->c_ospeed;
397*41480Smckusick         tp->t_cflag = cflag;
398*41480Smckusick 
399*41480Smckusick 	dca = dca_addr[unit];
400*41480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
401*41480Smckusick 	if (ospeed == 0) {
402*41480Smckusick 		(void) dcamctl(unit, 0, DMSET);	/* hang up line */
403*41480Smckusick 		return(0);
404*41480Smckusick 	}
405*41480Smckusick 	dca->dca_cfcr |= CFCR_DLAB;
406*41480Smckusick 	dca->dca_data = ospeed & 0xFF;
407*41480Smckusick 	dca->dca_ier = ospeed >> 8;
408*41480Smckusick 	switch (cflag&CSIZE) {
409*41480Smckusick 	case CS5:
410*41480Smckusick 		cfcr = CFCR_5BITS; break;
411*41480Smckusick 	case CS6:
412*41480Smckusick 		cfcr = CFCR_6BITS; break;
413*41480Smckusick 	case CS7:
414*41480Smckusick 		cfcr = CFCR_7BITS; break;
415*41480Smckusick 	case CS8:
416*41480Smckusick 		cfcr = CFCR_8BITS; break;
417*41480Smckusick 	}
418*41480Smckusick 	if (cflag&PARENB) {
419*41480Smckusick 		cfcr |= CFCR_PENAB;
420*41480Smckusick 		if ((cflag&PARODD) == 0)
421*41480Smckusick 			cfcr |= CFCR_PEVEN;
422*41480Smckusick 	}
423*41480Smckusick 	if (cflag&CSTOPB)
424*41480Smckusick 		cfcr |= CFCR_STOPB;
425*41480Smckusick 	dca->dca_cfcr = cfcr;
426*41480Smckusick 	return(0);
427*41480Smckusick }
428*41480Smckusick 
429*41480Smckusick dcastart(tp)
430*41480Smckusick 	register struct tty *tp;
431*41480Smckusick {
432*41480Smckusick 	register struct dcadevice *dca;
433*41480Smckusick 	int s, unit, c;
434*41480Smckusick 
435*41480Smckusick 	unit = UNIT(tp->t_dev);
436*41480Smckusick 	dca = dca_addr[unit];
437*41480Smckusick 	s = spltty();
438*41480Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
439*41480Smckusick 		goto out;
440*41480Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
441*41480Smckusick 		if (tp->t_state&TS_ASLEEP) {
442*41480Smckusick 			tp->t_state &= ~TS_ASLEEP;
443*41480Smckusick 			wakeup((caddr_t)&tp->t_outq);
444*41480Smckusick 		}
445*41480Smckusick 		if (tp->t_wsel) {
446*41480Smckusick 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
447*41480Smckusick 			tp->t_wsel = 0;
448*41480Smckusick 			tp->t_state &= ~TS_WCOLL;
449*41480Smckusick 		}
450*41480Smckusick 	}
451*41480Smckusick 	if (tp->t_outq.c_cc == 0)
452*41480Smckusick 		goto out;
453*41480Smckusick 	c = getc(&tp->t_outq);
454*41480Smckusick 	tp->t_state |= TS_BUSY;
455*41480Smckusick 	dca->dca_data = c;
456*41480Smckusick out:
457*41480Smckusick 	splx(s);
458*41480Smckusick }
459*41480Smckusick 
460*41480Smckusick /*
461*41480Smckusick  * Stop output on a line.
462*41480Smckusick  */
463*41480Smckusick /*ARGSUSED*/
464*41480Smckusick dcastop(tp, flag)
465*41480Smckusick 	register struct tty *tp;
466*41480Smckusick {
467*41480Smckusick 	register int s;
468*41480Smckusick 
469*41480Smckusick 	s = spltty();
470*41480Smckusick 	if (tp->t_state & TS_BUSY) {
471*41480Smckusick 		if ((tp->t_state&TS_TTSTOP)==0)
472*41480Smckusick 			tp->t_state |= TS_FLUSH;
473*41480Smckusick 	}
474*41480Smckusick 	splx(s);
475*41480Smckusick }
476*41480Smckusick 
477*41480Smckusick dcamctl(dev, bits, how)
478*41480Smckusick 	dev_t dev;
479*41480Smckusick 	int bits, how;
480*41480Smckusick {
481*41480Smckusick 	register struct dcadevice *dca;
482*41480Smckusick 	register int unit;
483*41480Smckusick 	int s;
484*41480Smckusick 
485*41480Smckusick 	unit = UNIT(dev);
486*41480Smckusick 	dca = dca_addr[unit];
487*41480Smckusick 	s = spltty();
488*41480Smckusick 	switch (how) {
489*41480Smckusick 
490*41480Smckusick 	case DMSET:
491*41480Smckusick 		dca->dca_mcr = bits;
492*41480Smckusick 		break;
493*41480Smckusick 
494*41480Smckusick 	case DMBIS:
495*41480Smckusick 		dca->dca_mcr |= bits;
496*41480Smckusick 		break;
497*41480Smckusick 
498*41480Smckusick 	case DMBIC:
499*41480Smckusick 		dca->dca_mcr &= ~bits;
500*41480Smckusick 		break;
501*41480Smckusick 
502*41480Smckusick 	case DMGET:
503*41480Smckusick 		bits = dca->dca_msr;
504*41480Smckusick 		break;
505*41480Smckusick 	}
506*41480Smckusick 	(void) splx(s);
507*41480Smckusick 	return(bits);
508*41480Smckusick }
509*41480Smckusick 
510*41480Smckusick /*
511*41480Smckusick  * Following are all routines needed for DCA to act as console
512*41480Smckusick  */
513*41480Smckusick #include "machine/cons.h"
514*41480Smckusick 
515*41480Smckusick dcacnprobe(cp)
516*41480Smckusick 	struct consdev *cp;
517*41480Smckusick {
518*41480Smckusick 	int unit, i;
519*41480Smckusick 	extern int dcaopen();
520*41480Smckusick 
521*41480Smckusick 	/* XXX: ick */
522*41480Smckusick 	unit = CONUNIT;
523*41480Smckusick 	dca_addr[CONUNIT] = CONADDR;
524*41480Smckusick 
525*41480Smckusick 	/* make sure hardware exists */
526*41480Smckusick 	if (badaddr((short *)dca_addr[unit])) {
527*41480Smckusick 		cp->cn_pri = CN_DEAD;
528*41480Smckusick 		return;
529*41480Smckusick 	}
530*41480Smckusick 
531*41480Smckusick 	/* locate the major number */
532*41480Smckusick 	for (i = 0; i < nchrdev; i++)
533*41480Smckusick 		if (cdevsw[i].d_open == dcaopen)
534*41480Smckusick 			break;
535*41480Smckusick 
536*41480Smckusick 	/* initialize required fields */
537*41480Smckusick 	cp->cn_dev = makedev(i, unit);
538*41480Smckusick 	cp->cn_tp = &dca_tty[unit];
539*41480Smckusick 	switch (dca_addr[unit]->dca_irid) {
540*41480Smckusick 	case DCAID0:
541*41480Smckusick 	case DCAID1:
542*41480Smckusick 		cp->cn_pri = CN_NORMAL;
543*41480Smckusick 		break;
544*41480Smckusick 	case DCAREMID0:
545*41480Smckusick 	case DCAREMID1:
546*41480Smckusick 		cp->cn_pri = CN_REMOTE;
547*41480Smckusick 		break;
548*41480Smckusick 	default:
549*41480Smckusick 		cp->cn_pri = CN_DEAD;
550*41480Smckusick 		break;
551*41480Smckusick 	}
552*41480Smckusick }
553*41480Smckusick 
554*41480Smckusick dcacninit(cp)
555*41480Smckusick 	struct consdev *cp;
556*41480Smckusick {
557*41480Smckusick 	int unit = UNIT(cp->cn_dev);
558*41480Smckusick 
559*41480Smckusick 	dcainit(unit);
560*41480Smckusick 	dcaconsole = unit;
561*41480Smckusick }
562*41480Smckusick 
563*41480Smckusick dcainit(unit)
564*41480Smckusick 	int unit;
565*41480Smckusick {
566*41480Smckusick 	register struct dcadevice *dca;
567*41480Smckusick 	int s, rate;
568*41480Smckusick 	short stat;
569*41480Smckusick 
570*41480Smckusick #ifdef lint
571*41480Smckusick 	stat = unit; if (stat) return;
572*41480Smckusick #endif
573*41480Smckusick 	dca = dca_addr[unit];
574*41480Smckusick 	s = splhigh();
575*41480Smckusick 	dca->dca_irid = 0xFF;
576*41480Smckusick 	DELAY(100);
577*41480Smckusick 	dca->dca_ic = IC_IE;
578*41480Smckusick 	dca->dca_cfcr = CFCR_DLAB;
579*41480Smckusick 	rate = ttspeedtab(dcadefaultrate, dcaspeedtab);
580*41480Smckusick 	dca->dca_data = rate & 0xFF;
581*41480Smckusick 	dca->dca_ier = rate >> 8;
582*41480Smckusick 	dca->dca_cfcr = CFCR_8BITS;
583*41480Smckusick 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
584*41480Smckusick 	stat = dca->dca_iir;
585*41480Smckusick 	splx(s);
586*41480Smckusick }
587*41480Smckusick 
588*41480Smckusick dcacngetc(dev)
589*41480Smckusick {
590*41480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
591*41480Smckusick 	short stat;
592*41480Smckusick 	int c, s;
593*41480Smckusick 
594*41480Smckusick #ifdef lint
595*41480Smckusick 	stat = dev; if (stat) return(0);
596*41480Smckusick #endif
597*41480Smckusick 	s = splhigh();
598*41480Smckusick 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
599*41480Smckusick 		;
600*41480Smckusick 	c = dca->dca_data;
601*41480Smckusick 	stat = dca->dca_iir;
602*41480Smckusick 	splx(s);
603*41480Smckusick 	return(c);
604*41480Smckusick }
605*41480Smckusick 
606*41480Smckusick /*
607*41480Smckusick  * Console kernel output character routine.
608*41480Smckusick  */
609*41480Smckusick dcacnputc(dev, c)
610*41480Smckusick 	dev_t dev;
611*41480Smckusick 	register int c;
612*41480Smckusick {
613*41480Smckusick 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
614*41480Smckusick 	register int timo;
615*41480Smckusick 	short stat;
616*41480Smckusick 	int s = splhigh();
617*41480Smckusick 
618*41480Smckusick #ifdef lint
619*41480Smckusick 	stat = dev; if (stat) return;
620*41480Smckusick #endif
621*41480Smckusick 	if (dcaconsole == -1) {
622*41480Smckusick 		(void) dcainit(UNIT(dev));
623*41480Smckusick 		dcaconsole = UNIT(dev);
624*41480Smckusick 	}
625*41480Smckusick 	/* wait for any pending transmission to finish */
626*41480Smckusick 	timo = 50000;
627*41480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
628*41480Smckusick 		;
629*41480Smckusick 	dca->dca_data = c;
630*41480Smckusick 	/* wait for this transmission to complete */
631*41480Smckusick 	timo = 1500000;
632*41480Smckusick 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
633*41480Smckusick 		;
634*41480Smckusick 	/* clear any interrupts generated by this transmission */
635*41480Smckusick 	stat = dca->dca_iir;
636*41480Smckusick 	splx(s);
637*41480Smckusick }
638*41480Smckusick #endif
639