xref: /csrg-svn/sys/i386/isa/com.c (revision 47752)
1*47752Swilliam /*-
2*47752Swilliam  * Copyright (c) 1982, 1986, 1990, 1991 The Regents of the University of
3*47752Swilliam  * California. All rights reserved.
4*47752Swilliam  *
5*47752Swilliam  * This code is derived from software contributed to Berkeley by
6*47752Swilliam  * the University of Utah and William Jolitz.
7*47752Swilliam  *
8*47752Swilliam  * %sccs.include.redist.c%
9*47752Swilliam  *
10*47752Swilliam  *	@(#)com.c	7.1 (Berkeley) 04/03/91
11*47752Swilliam  */
12*47752Swilliam 
13*47752Swilliam #include "dca.h"
14*47752Swilliam #if NDCA > 0
15*47752Swilliam /*
16*47752Swilliam  * COM driver, from hp300 dca.c 98626/98644/internal serial interface
17*47752Swilliam  */
18*47752Swilliam #include "sys/param.h"
19*47752Swilliam #include "sys/systm.h"
20*47752Swilliam #include "sys/ioctl.h"
21*47752Swilliam #include "sys/tty.h"
22*47752Swilliam #include "sys/user.h"
23*47752Swilliam #include "sys/conf.h"
24*47752Swilliam #include "sys/file.h"
25*47752Swilliam #include "sys/uio.h"
26*47752Swilliam #include "sys/kernel.h"
27*47752Swilliam #include "sys/syslog.h"
28*47752Swilliam 
29*47752Swilliam #include "i386/isa/isa_device.h"
30*47752Swilliam #include "i386/isa/comreg.h"
31*47752Swilliam #include "i386/isa/ic/ns16450.h"
32*47752Swilliam 
33*47752Swilliam int 	comprobe(), comattach(), comintr(), comstart(), comparam();
34*47752Swilliam 
35*47752Swilliam struct	isa_driver comdriver = {
36*47752Swilliam 	comprobe, comattach, "com"
37*47752Swilliam };
38*47752Swilliam 
39*47752Swilliam int	comsoftCAR;
40*47752Swilliam int	com_active;
41*47752Swilliam int	ncom = NDCA;
42*47752Swilliam int	comconsole = -1;
43*47752Swilliam int	comdefaultrate = TTYDEF_SPEED;
44*47752Swilliam short com_addr[NDCA];
45*47752Swilliam struct	tty com_tty[NDCA];
46*47752Swilliam 
47*47752Swilliam struct speedtab comspeedtab[] = {
48*47752Swilliam 	0,	0,
49*47752Swilliam 	50,	COMBRD(50),
50*47752Swilliam 	75,	COMBRD(75),
51*47752Swilliam 	110,	COMBRD(110),
52*47752Swilliam 	134,	COMBRD(134),
53*47752Swilliam 	150,	COMBRD(150),
54*47752Swilliam 	200,	COMBRD(200),
55*47752Swilliam 	300,	COMBRD(300),
56*47752Swilliam 	600,	COMBRD(600),
57*47752Swilliam 	1200,	COMBRD(1200),
58*47752Swilliam 	1800,	COMBRD(1800),
59*47752Swilliam 	2400,	COMBRD(2400),
60*47752Swilliam 	4800,	COMBRD(4800),
61*47752Swilliam 	9600,	COMBRD(9600),
62*47752Swilliam 	19200,	COMBRD(19200),
63*47752Swilliam 	38400,	COMBRD(38400),
64*47752Swilliam 	57600,	COMBRD(57600),
65*47752Swilliam 	-1,	-1
66*47752Swilliam };
67*47752Swilliam 
68*47752Swilliam extern	struct tty *constty;
69*47752Swilliam #ifdef KGDB
70*47752Swilliam extern int kgdb_dev;
71*47752Swilliam extern int kgdb_rate;
72*47752Swilliam extern int kgdb_debug_init;
73*47752Swilliam #endif
74*47752Swilliam 
75*47752Swilliam #define	UNIT(x)		minor(x)
76*47752Swilliam 
77*47752Swilliam comprobe(dev)
78*47752Swilliam struct isa_device *dev;
79*47752Swilliam {
80*47752Swilliam 	if ((inb(dev->id_iobase+com_iir) & 0xf8) == 0)
81*47752Swilliam 		return(1);
82*47752Swilliam 	return(0);
83*47752Swilliam 
84*47752Swilliam }
85*47752Swilliam 
86*47752Swilliam 
87*47752Swilliam int
88*47752Swilliam comattach(isdp)
89*47752Swilliam struct isa_device *isdp;
90*47752Swilliam {
91*47752Swilliam 	struct	tty	*tp;
92*47752Swilliam 	u_char		unit;
93*47752Swilliam 	int		port = isdp->id_iobase;
94*47752Swilliam 
95*47752Swilliam 	if (unit == comconsole)
96*47752Swilliam 		DELAY(100000);
97*47752Swilliam 	unit = isdp->id_unit;
98*47752Swilliam 	com_addr[unit] = port;
99*47752Swilliam 	com_active |= 1 << unit;
100*47752Swilliam 	/* comsoftCAR = isdp->id_flags; */
101*47752Swilliam 	outb(port+com_ier, 0);
102*47752Swilliam 	outb(port+com_mcr, 0 | MCR_IENABLE);
103*47752Swilliam #ifdef KGDB
104*47752Swilliam 	if (kgdb_dev == makedev(1, unit)) {
105*47752Swilliam 		if (comconsole == unit)
106*47752Swilliam 			kgdb_dev = -1;	/* can't debug over console port */
107*47752Swilliam 		else {
108*47752Swilliam 			(void) cominit(unit);
109*47752Swilliam 			comconsole = -2; /* XXX */
110*47752Swilliam 			if (kgdb_debug_init) {
111*47752Swilliam 				printf("com%d: kgdb waiting...", unit);
112*47752Swilliam 				/* trap into kgdb */
113*47752Swilliam 				asm("trap #15;");
114*47752Swilliam 				printf("connected.\n");
115*47752Swilliam 			} else
116*47752Swilliam 				printf("com%d: kgdb enabled\n", unit);
117*47752Swilliam 		}
118*47752Swilliam 	}
119*47752Swilliam #endif
120*47752Swilliam 	/*
121*47752Swilliam 	 * Need to reset baud rate, etc. of next print so reset comconsole.
122*47752Swilliam 	 * Also make sure console is always "hardwired"
123*47752Swilliam 	 */
124*47752Swilliam 	if (unit == comconsole) {
125*47752Swilliam 		comconsole = -1;
126*47752Swilliam 		comsoftCAR |= (1 << unit);
127*47752Swilliam 	}
128*47752Swilliam comsoftCAR |= (1 << unit);
129*47752Swilliam 	return (1);
130*47752Swilliam }
131*47752Swilliam 
132*47752Swilliam comopen(dev, flag)
133*47752Swilliam 	dev_t dev;
134*47752Swilliam {
135*47752Swilliam 	register struct tty *tp;
136*47752Swilliam 	register int unit;
137*47752Swilliam 	int error = 0;
138*47752Swilliam 
139*47752Swilliam 	unit = UNIT(dev);
140*47752Swilliam 	if (unit >= NDCA || (com_active & (1 << unit)) == 0)
141*47752Swilliam 		return (ENXIO);
142*47752Swilliam 	tp = &com_tty[unit];
143*47752Swilliam 	tp->t_oproc = comstart;
144*47752Swilliam 	tp->t_param = comparam;
145*47752Swilliam 	tp->t_dev = dev;
146*47752Swilliam 	if ((tp->t_state & TS_ISOPEN) == 0) {
147*47752Swilliam 		tp->t_state |= TS_WOPEN;
148*47752Swilliam 		ttychars(tp);
149*47752Swilliam 		tp->t_iflag = TTYDEF_IFLAG;
150*47752Swilliam 		tp->t_oflag = TTYDEF_OFLAG;
151*47752Swilliam 		tp->t_cflag = TTYDEF_CFLAG;
152*47752Swilliam 		tp->t_lflag = TTYDEF_LFLAG;
153*47752Swilliam 		tp->t_ispeed = tp->t_ospeed = comdefaultrate;
154*47752Swilliam 		comparam(tp, &tp->t_termios);
155*47752Swilliam 		ttsetwater(tp);
156*47752Swilliam 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
157*47752Swilliam 		return (EBUSY);
158*47752Swilliam 	(void) spltty();
159*47752Swilliam 	(void) commctl(dev, MCR_DTR | MCR_RTS, DMSET);
160*47752Swilliam 	if ((comsoftCAR & (1 << unit)) || (commctl(dev, 0, DMGET) & MSR_DCD))
161*47752Swilliam 		tp->t_state |= TS_CARR_ON;
162*47752Swilliam 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
163*47752Swilliam 	       (tp->t_state & TS_CARR_ON) == 0) {
164*47752Swilliam 		tp->t_state |= TS_WOPEN;
165*47752Swilliam 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
166*47752Swilliam 		    ttopen, 0))
167*47752Swilliam 			break;
168*47752Swilliam 	}
169*47752Swilliam 	(void) spl0();
170*47752Swilliam 	if (error == 0)
171*47752Swilliam 		error = (*linesw[tp->t_line].l_open)(dev, tp);
172*47752Swilliam 	return (error);
173*47752Swilliam }
174*47752Swilliam 
175*47752Swilliam /*ARGSUSED*/
176*47752Swilliam comclose(dev, flag)
177*47752Swilliam 	dev_t dev;
178*47752Swilliam {
179*47752Swilliam 	register struct tty *tp;
180*47752Swilliam 	register com;
181*47752Swilliam 	register int unit;
182*47752Swilliam 
183*47752Swilliam 	unit = UNIT(dev);
184*47752Swilliam 	com = com_addr[unit];
185*47752Swilliam 	tp = &com_tty[unit];
186*47752Swilliam 	(*linesw[tp->t_line].l_close)(tp);
187*47752Swilliam 	outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK);
188*47752Swilliam #ifdef KGDB
189*47752Swilliam 	/* do not disable interrupts if debugging */
190*47752Swilliam 	if (kgdb_dev != makedev(1, unit))
191*47752Swilliam #endif
192*47752Swilliam 	outb(com+com_ier, 0);
193*47752Swilliam 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
194*47752Swilliam 	    (tp->t_state&TS_ISOPEN) == 0)
195*47752Swilliam 		(void) commctl(dev, 0, DMSET);
196*47752Swilliam 	ttyclose(tp);
197*47752Swilliam 	return(0);
198*47752Swilliam }
199*47752Swilliam 
200*47752Swilliam comread(dev, uio, flag)
201*47752Swilliam 	dev_t dev;
202*47752Swilliam 	struct uio *uio;
203*47752Swilliam {
204*47752Swilliam 	register struct tty *tp = &com_tty[UNIT(dev)];
205*47752Swilliam 
206*47752Swilliam 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
207*47752Swilliam }
208*47752Swilliam 
209*47752Swilliam comwrite(dev, uio, flag)
210*47752Swilliam 	dev_t dev;
211*47752Swilliam 	struct uio *uio;
212*47752Swilliam {
213*47752Swilliam 	int unit = UNIT(dev);
214*47752Swilliam 	register struct tty *tp = &com_tty[unit];
215*47752Swilliam 
216*47752Swilliam #ifdef notyet
217*47752Swilliam 	/*
218*47752Swilliam 	 * (XXX) We disallow virtual consoles if the physical console is
219*47752Swilliam 	 * a serial port.  This is in case there is a display attached that
220*47752Swilliam 	 * is not the console.  In that situation we don't need/want the X
221*47752Swilliam 	 * server taking over the console.
222*47752Swilliam 	 */
223*47752Swilliam 	if (constty && unit == comconsole)
224*47752Swilliam 		constty = NULL;
225*47752Swilliam #endif
226*47752Swilliam 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
227*47752Swilliam }
228*47752Swilliam 
229*47752Swilliam comintr(unit)
230*47752Swilliam 	register int unit;
231*47752Swilliam {
232*47752Swilliam 	register com;
233*47752Swilliam 	register u_char code;
234*47752Swilliam 	register struct tty *tp;
235*47752Swilliam 
236*47752Swilliam 	com = com_addr[unit];
237*47752Swilliam 	while (1) {
238*47752Swilliam 		code = inb(com+com_iir);
239*47752Swilliam 		switch (code) {
240*47752Swilliam 		case IIR_NOPEND:
241*47752Swilliam 			return (1);
242*47752Swilliam 		case IIR_RXRDY:
243*47752Swilliam 			/* do time-critical read in-line */
244*47752Swilliam 			tp = &com_tty[unit];
245*47752Swilliam 			code = inb(com+com_data);
246*47752Swilliam 			if ((tp->t_state & TS_ISOPEN) == 0) {
247*47752Swilliam #ifdef KGDB
248*47752Swilliam 				if (kgdb_dev == makedev(1, unit) &&
249*47752Swilliam 				    code == '!') {
250*47752Swilliam 					printf("kgdb trap from com%d\n", unit);
251*47752Swilliam 					/* trap into kgdb */
252*47752Swilliam 					asm("trap #15;");
253*47752Swilliam 				}
254*47752Swilliam #endif
255*47752Swilliam 			} else
256*47752Swilliam 				(*linesw[tp->t_line].l_rint)(code, tp);
257*47752Swilliam 			break;
258*47752Swilliam 		case IIR_TXRDY:
259*47752Swilliam 			tp = &com_tty[unit];
260*47752Swilliam 			tp->t_state &=~ (TS_BUSY|TS_FLUSH);
261*47752Swilliam 			if (tp->t_line)
262*47752Swilliam 				(*linesw[tp->t_line].l_start)(tp);
263*47752Swilliam 			else
264*47752Swilliam 				comstart(tp);
265*47752Swilliam 			break;
266*47752Swilliam 		case IIR_RLS:
267*47752Swilliam 			comeint(unit, com);
268*47752Swilliam 			break;
269*47752Swilliam 		default:
270*47752Swilliam 			if (code & IIR_NOPEND)
271*47752Swilliam 				return (1);
272*47752Swilliam 			log(LOG_WARNING, "com%d: weird interrupt: 0x%x\n",
273*47752Swilliam 			    unit, code);
274*47752Swilliam 			/* fall through */
275*47752Swilliam 		case IIR_MLSC:
276*47752Swilliam 			commint(unit, com);
277*47752Swilliam 			break;
278*47752Swilliam 		}
279*47752Swilliam 	}
280*47752Swilliam }
281*47752Swilliam 
282*47752Swilliam comeint(unit, com)
283*47752Swilliam 	register int unit;
284*47752Swilliam 	register com;
285*47752Swilliam {
286*47752Swilliam 	register struct tty *tp;
287*47752Swilliam 	register int stat, c;
288*47752Swilliam 
289*47752Swilliam 	tp = &com_tty[unit];
290*47752Swilliam 	stat = inb(com+com_lsr);
291*47752Swilliam 	c = inb(com+com_data);
292*47752Swilliam 	if ((tp->t_state & TS_ISOPEN) == 0) {
293*47752Swilliam #ifdef KGDB
294*47752Swilliam 		/* we don't care about parity errors */
295*47752Swilliam 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
296*47752Swilliam 		    kgdb_dev == makedev(1, unit) && c == '!') {
297*47752Swilliam 			printf("kgdb trap from com%d\n", unit);
298*47752Swilliam 			/* trap into kgdb */
299*47752Swilliam 			asm("trap #15;");
300*47752Swilliam 		}
301*47752Swilliam #endif
302*47752Swilliam 		return;
303*47752Swilliam 	}
304*47752Swilliam 	if (stat & (LSR_BI | LSR_FE))
305*47752Swilliam 		c |= TTY_FE;
306*47752Swilliam 	else if (stat & LSR_PE)
307*47752Swilliam 		c |= TTY_PE;
308*47752Swilliam 	else if (stat & LSR_OE)
309*47752Swilliam 		log(LOG_WARNING, "com%d: silo overflow\n", unit);
310*47752Swilliam 	(*linesw[tp->t_line].l_rint)(c, tp);
311*47752Swilliam }
312*47752Swilliam 
313*47752Swilliam commint(unit, com)
314*47752Swilliam 	register int unit;
315*47752Swilliam 	register com;
316*47752Swilliam {
317*47752Swilliam 	register struct tty *tp;
318*47752Swilliam 	register int stat;
319*47752Swilliam 
320*47752Swilliam 	tp = &com_tty[unit];
321*47752Swilliam 	stat = inb(com+com_msr);
322*47752Swilliam 	if ((stat & MSR_DDCD) && (comsoftCAR & (1 << unit)) == 0) {
323*47752Swilliam 		if (stat & MSR_DCD)
324*47752Swilliam 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
325*47752Swilliam 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
326*47752Swilliam 			outb(com+com_mcr,
327*47752Swilliam 				inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE);
328*47752Swilliam 	} else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
329*47752Swilliam 		   (tp->t_flags & CRTSCTS)) {
330*47752Swilliam 		/* the line is up and we want to do rts/cts flow control */
331*47752Swilliam 		if (stat & MSR_CTS) {
332*47752Swilliam 			tp->t_state &=~ TS_TTSTOP;
333*47752Swilliam 			ttstart(tp);
334*47752Swilliam 		} else
335*47752Swilliam 			tp->t_state |= TS_TTSTOP;
336*47752Swilliam 	}
337*47752Swilliam }
338*47752Swilliam 
339*47752Swilliam comioctl(dev, cmd, data, flag)
340*47752Swilliam 	dev_t dev;
341*47752Swilliam 	caddr_t data;
342*47752Swilliam {
343*47752Swilliam 	register struct tty *tp;
344*47752Swilliam 	register int unit = UNIT(dev);
345*47752Swilliam 	register com;
346*47752Swilliam 	register int error;
347*47752Swilliam 
348*47752Swilliam 	tp = &com_tty[unit];
349*47752Swilliam 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
350*47752Swilliam 	if (error >= 0)
351*47752Swilliam 		return (error);
352*47752Swilliam 	error = ttioctl(tp, cmd, data, flag);
353*47752Swilliam 	if (error >= 0)
354*47752Swilliam 		return (error);
355*47752Swilliam 
356*47752Swilliam 	com = com_addr[unit];
357*47752Swilliam 	switch (cmd) {
358*47752Swilliam 
359*47752Swilliam 	case TIOCSBRK:
360*47752Swilliam 		outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_SBREAK);
361*47752Swilliam 		break;
362*47752Swilliam 
363*47752Swilliam 	case TIOCCBRK:
364*47752Swilliam 		outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK);
365*47752Swilliam 		break;
366*47752Swilliam 
367*47752Swilliam 	case TIOCSDTR:
368*47752Swilliam 		(void) commctl(dev, MCR_DTR | MCR_RTS, DMBIS);
369*47752Swilliam 		break;
370*47752Swilliam 
371*47752Swilliam 	case TIOCCDTR:
372*47752Swilliam 		(void) commctl(dev, MCR_DTR | MCR_RTS, DMBIC);
373*47752Swilliam 		break;
374*47752Swilliam 
375*47752Swilliam 	case TIOCMSET:
376*47752Swilliam 		(void) commctl(dev, *(int *)data, DMSET);
377*47752Swilliam 		break;
378*47752Swilliam 
379*47752Swilliam 	case TIOCMBIS:
380*47752Swilliam 		(void) commctl(dev, *(int *)data, DMBIS);
381*47752Swilliam 		break;
382*47752Swilliam 
383*47752Swilliam 	case TIOCMBIC:
384*47752Swilliam 		(void) commctl(dev, *(int *)data, DMBIC);
385*47752Swilliam 		break;
386*47752Swilliam 
387*47752Swilliam 	case TIOCMGET:
388*47752Swilliam 		*(int *)data = commctl(dev, 0, DMGET);
389*47752Swilliam 		break;
390*47752Swilliam 
391*47752Swilliam 	default:
392*47752Swilliam 		return (ENOTTY);
393*47752Swilliam 	}
394*47752Swilliam 	return (0);
395*47752Swilliam }
396*47752Swilliam 
397*47752Swilliam comparam(tp, t)
398*47752Swilliam 	register struct tty *tp;
399*47752Swilliam 	register struct termios *t;
400*47752Swilliam {
401*47752Swilliam 	register com;
402*47752Swilliam 	register int cfcr, cflag = t->c_cflag;
403*47752Swilliam 	int unit = UNIT(tp->t_dev);
404*47752Swilliam 	int ospeed = ttspeedtab(t->c_ospeed, comspeedtab);
405*47752Swilliam 
406*47752Swilliam 	/* check requested parameters */
407*47752Swilliam         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
408*47752Swilliam                 return(EINVAL);
409*47752Swilliam         /* and copy to tty */
410*47752Swilliam         tp->t_ispeed = t->c_ispeed;
411*47752Swilliam         tp->t_ospeed = t->c_ospeed;
412*47752Swilliam         tp->t_cflag = cflag;
413*47752Swilliam 
414*47752Swilliam 	com = com_addr[unit];
415*47752Swilliam 	outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS /*| IER_EMSC*/);
416*47752Swilliam 	if (ospeed == 0) {
417*47752Swilliam 		(void) commctl(unit, 0, DMSET);	/* hang up line */
418*47752Swilliam 		return(0);
419*47752Swilliam 	}
420*47752Swilliam 	outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_DLAB);
421*47752Swilliam 	outb(com+com_data, ospeed & 0xFF);
422*47752Swilliam 	outb(com+com_ier, ospeed >> 8);
423*47752Swilliam 	switch (cflag&CSIZE) {
424*47752Swilliam 	case CS5:
425*47752Swilliam 		cfcr = CFCR_5BITS; break;
426*47752Swilliam 	case CS6:
427*47752Swilliam 		cfcr = CFCR_6BITS; break;
428*47752Swilliam 	case CS7:
429*47752Swilliam 		cfcr = CFCR_7BITS; break;
430*47752Swilliam 	case CS8:
431*47752Swilliam 		cfcr = CFCR_8BITS; break;
432*47752Swilliam 	}
433*47752Swilliam 	if (cflag&PARENB) {
434*47752Swilliam 		cfcr |= CFCR_PENAB;
435*47752Swilliam 		if ((cflag&PARODD) == 0)
436*47752Swilliam 			cfcr |= CFCR_PEVEN;
437*47752Swilliam 	}
438*47752Swilliam 	if (cflag&CSTOPB)
439*47752Swilliam 		cfcr |= CFCR_STOPB;
440*47752Swilliam 	outb(com+com_cfcr, cfcr);
441*47752Swilliam 	return(0);
442*47752Swilliam }
443*47752Swilliam 
444*47752Swilliam comstart(tp)
445*47752Swilliam 	register struct tty *tp;
446*47752Swilliam {
447*47752Swilliam 	register com;
448*47752Swilliam 	int s, unit, c;
449*47752Swilliam 
450*47752Swilliam 	unit = UNIT(tp->t_dev);
451*47752Swilliam 	com = com_addr[unit];
452*47752Swilliam 	s = spltty();
453*47752Swilliam 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
454*47752Swilliam 		goto out;
455*47752Swilliam 	if (tp->t_outq.c_cc <= tp->t_lowat) {
456*47752Swilliam 		if (tp->t_state&TS_ASLEEP) {
457*47752Swilliam 			tp->t_state &= ~TS_ASLEEP;
458*47752Swilliam 			wakeup((caddr_t)&tp->t_outq);
459*47752Swilliam 		}
460*47752Swilliam 		if (tp->t_wsel) {
461*47752Swilliam 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
462*47752Swilliam 			tp->t_wsel = 0;
463*47752Swilliam 			tp->t_state &= ~TS_WCOLL;
464*47752Swilliam 		}
465*47752Swilliam 	}
466*47752Swilliam 	if (tp->t_outq.c_cc == 0)
467*47752Swilliam 		goto out;
468*47752Swilliam 	if (inb(com+com_lsr) & LSR_TXRDY) {
469*47752Swilliam 		c = getc(&tp->t_outq);
470*47752Swilliam 		tp->t_state |= TS_BUSY;
471*47752Swilliam 		outb(com+com_data, c);
472*47752Swilliam 	}
473*47752Swilliam out:
474*47752Swilliam 	splx(s);
475*47752Swilliam }
476*47752Swilliam 
477*47752Swilliam /*
478*47752Swilliam  * Stop output on a line.
479*47752Swilliam  */
480*47752Swilliam /*ARGSUSED*/
481*47752Swilliam comstop(tp, flag)
482*47752Swilliam 	register struct tty *tp;
483*47752Swilliam {
484*47752Swilliam 	register int s;
485*47752Swilliam 
486*47752Swilliam 	s = spltty();
487*47752Swilliam 	if (tp->t_state & TS_BUSY) {
488*47752Swilliam 		if ((tp->t_state&TS_TTSTOP)==0)
489*47752Swilliam 			tp->t_state |= TS_FLUSH;
490*47752Swilliam 	}
491*47752Swilliam 	splx(s);
492*47752Swilliam }
493*47752Swilliam 
494*47752Swilliam commctl(dev, bits, how)
495*47752Swilliam 	dev_t dev;
496*47752Swilliam 	int bits, how;
497*47752Swilliam {
498*47752Swilliam 	register com;
499*47752Swilliam 	register int unit;
500*47752Swilliam 	int s;
501*47752Swilliam 
502*47752Swilliam 	unit = UNIT(dev);
503*47752Swilliam 	com = com_addr[unit];
504*47752Swilliam 	s = spltty();
505*47752Swilliam 	switch (how) {
506*47752Swilliam 
507*47752Swilliam 	case DMSET:
508*47752Swilliam 		outb(com+com_mcr, bits | MCR_IENABLE);
509*47752Swilliam 		break;
510*47752Swilliam 
511*47752Swilliam 	case DMBIS:
512*47752Swilliam 		outb(com+com_mcr, inb(com+com_mcr) | bits | MCR_IENABLE);
513*47752Swilliam 		break;
514*47752Swilliam 
515*47752Swilliam 	case DMBIC:
516*47752Swilliam 		outb(com+com_mcr, inb(com+com_mcr) & ~bits | MCR_IENABLE);
517*47752Swilliam 		break;
518*47752Swilliam 
519*47752Swilliam 	case DMGET:
520*47752Swilliam 		bits = inb(com+com_msr);
521*47752Swilliam 		break;
522*47752Swilliam 	}
523*47752Swilliam 	(void) splx(s);
524*47752Swilliam 	return(bits);
525*47752Swilliam }
526*47752Swilliam #endif
527