xref: /openbsd/sys/dev/ic/com.c (revision 07ea8d15)
1 /*	$OpenBSD: com.c,v 1.30 1996/12/10 22:28:28 deraadt Exp $	*/
2 /*	$NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $	*/
3 
4 /*-
5  * Copyright (c) 1993, 1994, 1995, 1996
6  *	Charles M. Hannum.  All rights reserved.
7  * Copyright (c) 1991 The Regents of the University of California.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)com.c	7.5 (Berkeley) 5/16/91
39  */
40 
41 /*
42  * COM driver, based on HP dca driver
43  * uses National Semiconductor NS16450/NS16550AF UART
44  */
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/ioctl.h>
48 #include <sys/select.h>
49 #include <sys/tty.h>
50 #include <sys/proc.h>
51 #include <sys/user.h>
52 #include <sys/conf.h>
53 #include <sys/file.h>
54 #include <sys/uio.h>
55 #include <sys/kernel.h>
56 #include <sys/syslog.h>
57 #include <sys/types.h>
58 #include <sys/device.h>
59 
60 #include <machine/bus.h>
61 #include <machine/intr.h>
62 
63 #include <dev/isa/isavar.h>	/* XXX */
64 
65 #include <dev/ic/comreg.h>
66 #include <dev/ic/comvar.h>
67 #include <dev/ic/ns16550reg.h>
68 #ifdef COM_HAYESP
69 #include <dev/ic/hayespreg.h>
70 #endif
71 #define	com_lcr	com_cfcr
72 
73 #include "com.h"
74 
75 /* XXX: These belong elsewhere */
76 cdev_decl(com);
77 bdev_decl(com);
78 
79 static u_char tiocm_xxx2mcr __P((int));
80 
81 /*
82  * XXX the following two cfattach structs should be different, and possibly
83  * XXX elsewhere.
84  */
85 int	comprobe __P((struct device *, void *, void *));
86 void	comattach __P((struct device *, struct device *, void *));
87 void	comstart_pending __P((void *));
88 
89 #if NCOM_ISA
90 struct cfattach com_isa_ca = {
91 	sizeof(struct com_softc), comprobe, comattach
92 };
93 #endif
94 
95 #if NCOM_COMMULTI
96 struct cfattach com_commulti_ca = {
97 	sizeof(struct com_softc), comprobe, comattach
98 };
99 #endif
100 
101 struct cfdriver com_cd = {
102 	NULL, "com", DV_TTY
103 };
104 
105 #ifndef CONSPEED
106 #define	CONSPEED B9600
107 #endif
108 
109 #ifdef COMCONSOLE
110 int	comdefaultrate = CONSPEED;		/* XXX why set default? */
111 #else
112 int	comdefaultrate = TTYDEF_SPEED;
113 #endif
114 int	comconsaddr;
115 int	comconsinit;
116 int	comconsattached;
117 bus_space_tag_t comconsiot;
118 bus_space_handle_t comconsioh;
119 tcflag_t comconscflag = TTYDEF_CFLAG;
120 
121 int	commajor;
122 int	comsopen = 0;
123 int	comevents = 0;
124 
125 #ifdef KGDB
126 #include <machine/remote-sl.h>
127 extern int kgdb_dev;
128 extern int kgdb_rate;
129 extern int kgdb_debug_init;
130 #endif
131 
132 #define	DEVUNIT(x)	(minor(x) & 0x7f)
133 #define	DEVCUA(x)	(minor(x) & 0x80)
134 
135 /* Macros to clear/set/test flags. */
136 #define	SET(t, f)	(t) |= (f)
137 #define	CLR(t, f)	(t) &= ~(f)
138 #define	ISSET(t, f)	((t) & (f))
139 
140 /*
141  * must be called at spltty() or higher.
142  */
143 void
144 com_absent_notify(sc)
145 	struct com_softc *sc;
146 {
147 	struct tty *tp = sc->sc_tty;
148 
149 	if (tp) {
150 		CLR(tp->t_state, TS_CARR_ON|TS_BUSY);
151 		ttyflush(tp, FREAD|FWRITE);
152 	}
153 }
154 
155 int
156 comspeed(speed)
157 	long speed;
158 {
159 #define	divrnd(n, q)	(((n)*2/(q)+1)/2)	/* divide and round off */
160 
161 	int x, err;
162 
163 	if (speed == 0)
164 		return 0;
165 	if (speed < 0)
166 		return -1;
167 	x = divrnd((COM_FREQ / 16), speed);
168 	if (x <= 0)
169 		return -1;
170 	err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
171 	if (err < 0)
172 		err = -err;
173 	if (err > COM_TOLERANCE)
174 		return -1;
175 	return x;
176 
177 #undef	divrnd(n, q)
178 }
179 
180 int
181 comprobe1(iot, ioh, iobase)
182 	bus_space_tag_t iot;
183 	bus_space_handle_t ioh;
184 	int iobase;
185 {
186 	int i, k;
187 
188 	/* force access to id reg */
189 	bus_space_write_1(iot, ioh, com_lcr, 0);
190 	bus_space_write_1(iot, ioh, com_iir, 0);
191 	for (i = 0; i < 32; i++) {
192 	    k = bus_space_read_1(iot, ioh, com_iir);
193 	    if (k & 0x38) {
194 		bus_space_read_1(iot, ioh, com_data); /* cleanup */
195 	    } else
196 		break;
197 	}
198 	if (i >= 32)
199 	    return 0;
200 
201 	return 1;
202 }
203 
204 #ifdef COM_HAYESP
205 int
206 comprobeHAYESP(hayespioh, sc)
207 	bus_space_handle_t hayespioh;
208 	struct com_softc *sc;
209 {
210 	char	val, dips;
211 	int	combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
212 	bus_space_tag_t iot = sc->sc_iot;
213 
214 	/*
215 	 * Hayes ESP cards have two iobases.  One is for compatibility with
216 	 * 16550 serial chips, and at the same ISA PC base addresses.  The
217 	 * other is for ESP-specific enhanced features, and lies at a
218 	 * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
219 	 */
220 
221 	/* Test for ESP signature */
222 	if ((bus_space_read_1(iot, hayespioh, 0) & 0xf3) == 0)
223 		return 0;
224 
225 	/*
226 	 * ESP is present at ESP enhanced base address; unknown com port
227 	 */
228 
229 	/* Get the dip-switch configurations */
230 	bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
231 	dips = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1);
232 
233 	/* Determine which com port this ESP card services: bits 0,1 of  */
234 	/*  dips is the port # (0-3); combaselist[val] is the com_iobase */
235 	if (sc->sc_iobase != combaselist[dips & 0x03])
236 		return 0;
237 
238 	printf(": ESP");
239 
240  	/* Check ESP Self Test bits. */
241 	/* Check for ESP version 2.0: bits 4,5,6 == 010 */
242 	bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
243 	val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
244 	val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS2);
245 	if ((val & 0x70) < 0x20) {
246 		printf("-old (%o)", val & 0x70);
247 		/* we do not support the necessary features */
248 		return 0;
249 	}
250 
251 	/* Check for ability to emulate 16550: bit 8 == 1 */
252 	if ((dips & 0x80) == 0) {
253 		printf(" slave");
254 		/* XXX Does slave really mean no 16550 support?? */
255 		return 0;
256 	}
257 
258 	/*
259 	 * If we made it this far, we are a full-featured ESP v2.0 (or
260 	 * better), at the correct com port address.
261 	 */
262 
263 	SET(sc->sc_hwflags, COM_HW_HAYESP);
264 	printf(", 1024 byte fifo\n");
265 	return 1;
266 }
267 #endif
268 
269 int
270 comprobe(parent, match, aux)
271 	struct device *parent;
272 	void *match, *aux;
273 {
274 	bus_space_tag_t iot;
275 	bus_space_handle_t ioh;
276 	int iobase, needioh;
277 	int rv = 1;
278 
279 #if NCOM_ISA
280 #define IS_ISA(parent) \
281 	!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
282 #endif
283 	/*
284 	 * XXX should be broken out into functions for isa probe and
285 	 * XXX for commulti probe, with a helper function that contains
286 	 * XXX most of the interesting stuff.
287 	 */
288 #if NCOM_ISA
289 	if (IS_ISA(parent)) {
290 		struct isa_attach_args *ia = aux;
291 
292 		iot = ia->ia_iot;
293 		iobase = ia->ia_iobase;
294 		needioh = 1;
295 	} else
296 #endif
297 #if NCOM_COMMULTI
298 	if (1) {
299 		struct cfdata *cf = match;
300 		struct commulti_attach_args *ca = aux;
301 
302 		if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
303 			return (0);
304 
305 		iot = ca->ca_iot;
306 		iobase = ca->ca_iobase;
307 		ioh = ca->ca_ioh;
308 		needioh = 0;
309 	} else
310 #endif
311 		return(0);			/* This cannot happen */
312 
313 	/* if it's in use as console, it's there. */
314 	if (iobase == comconsaddr && !comconsattached)
315 		goto out;
316 
317 	if (needioh && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
318 		rv = 0;
319 		goto out;
320 	}
321 	rv = comprobe1(iot, ioh, iobase);
322 	if (needioh)
323 		bus_space_unmap(iot, ioh, COM_NPORTS);
324 
325 out:
326 #if NCOM_ISA
327 	if (rv && IS_ISA(parent)) {
328 		struct isa_attach_args *ia = aux;
329 
330 		ia->ia_iosize = COM_NPORTS;
331 		ia->ia_msize = 0;
332 	}
333 #endif
334 	return (rv);
335 }
336 
337 void
338 comattach(parent, self, aux)
339 	struct device *parent, *self;
340 	void *aux;
341 {
342 	struct com_softc *sc = (void *)self;
343 	int iobase, irq;
344 	bus_space_tag_t iot;
345 	bus_space_handle_t ioh;
346 #ifdef COM_HAYESP
347 	int	hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
348 	int	*hayespp;
349 #endif
350 
351 	/*
352 	 * XXX should be broken out into functions for isa attach and
353 	 * XXX for commulti attach, with a helper function that contains
354 	 * XXX most of the interesting stuff.
355 	 */
356 	if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
357 		int s;
358 		s = spltty();
359 		com_absent_notify(sc);
360 		splx(s);
361 	} else
362 	    sc->sc_hwflags = 0;
363 	sc->sc_swflags = 0;
364 #if NCOM_ISA
365 	if (IS_ISA(parent)) {
366 		struct isa_attach_args *ia = aux;
367 
368 		/*
369 		 * We're living on an isa.
370 		 */
371 		iobase = ia->ia_iobase;
372 		iot = ia->ia_iot;
373 	        if (iobase != comconsaddr) {
374 	                if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
375 				panic("comattach: io mapping failed");
376 		} else
377 	                ioh = comconsioh;
378 		irq = ia->ia_irq;
379 	} else
380 #endif
381 #if NCOM_COMMULTI
382 	if (1) {
383 		struct commulti_attach_args *ca = aux;
384 
385 		/*
386 		 * We're living on a commulti.
387 		 */
388 		iobase = ca->ca_iobase;
389 		iot = ca->ca_iot;
390 		ioh = ca->ca_ioh;
391 		irq = IRQUNK;
392 
393 		if (ca->ca_noien)
394 			SET(sc->sc_hwflags, COM_HW_NOIEN);
395 	} else
396 #endif
397 		panic("comattach: impossible");
398 
399 	sc->sc_iot = iot;
400 	sc->sc_ioh = ioh;
401 	sc->sc_iobase = iobase;
402 
403 	if (iobase == comconsaddr) {
404 		comconsattached = 1;
405 
406 		/*
407 		 * Need to reset baud rate, etc. of next print so reset
408 		 * comconsinit.  Also make sure console is always "hardwired".
409 		 */
410 		delay(1000);			/* wait for output to finish */
411 		comconsinit = 0;
412 		SET(sc->sc_hwflags, COM_HW_CONSOLE);
413 		SET(sc->sc_swflags, COM_SW_SOFTCAR);
414 	}
415 
416 #ifdef COM_HAYESP
417 	/* Look for a Hayes ESP board. */
418 	for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
419 		bus_space_handle_t hayespioh;
420 
421 #define	HAYESP_NPORTS	8			/* XXX XXX XXX ??? ??? ??? */
422 		if (bus_space_map(iot, *hayespp, HAYESP_NPORTS, 0, &hayespioh))
423 			continue;
424 		if (comprobeHAYESP(hayespioh, sc)) {
425 			sc->sc_hayespbase = *hayespp;
426 			sc->sc_hayespioh = hayespioh;
427 			break;
428 		}
429 		bus_space_unmap(iot, hayespioh, HAYESP_NPORTS);
430 	}
431 	/* No ESP; look for other things. */
432 	if (*hayespp == 0) {
433 #endif
434 
435 	/* look for a NS 16550AF UART with FIFOs */
436 	bus_space_write_1(iot, ioh, com_fifo,
437 	    FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
438 	delay(100);
439 	if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK) ==
440 	    IIR_FIFO_MASK)
441 		if (ISSET(bus_space_read_1(iot, ioh, com_fifo), FIFO_TRIGGER_14) ==
442 		    FIFO_TRIGGER_14) {
443 			SET(sc->sc_hwflags, COM_HW_FIFO);
444 			printf(": ns16550a, working fifo\n");
445 		} else
446 			printf(": ns16550, broken fifo\n");
447 	else
448 		printf(": ns8250 or ns16450, no fifo\n");
449 	bus_space_write_1(iot, ioh, com_fifo, 0);
450 #ifdef COM_HAYESP
451 	}
452 #endif
453 
454 	/* disable interrupts */
455 	bus_space_write_1(iot, ioh, com_ier, 0);
456 	bus_space_write_1(iot, ioh, com_mcr, 0);
457 
458 	if (irq != IRQUNK) {
459 #if NCOM_ISA
460 		if (IS_ISA(parent)) {
461 			struct isa_attach_args *ia = aux;
462 
463 			sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
464 			    IST_EDGE, IPL_TTY, comintr, sc,
465 			    sc->sc_dev.dv_xname);
466 		} else
467 #endif
468 			panic("comattach: IRQ but can't have one");
469 	}
470 
471 #ifdef KGDB
472 	if (kgdb_dev == makedev(commajor, unit)) {
473 		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
474 			kgdb_dev = -1;	/* can't debug over console port */
475 		else {
476 			cominit(iot, ioh, kgdb_rate);
477 			if (kgdb_debug_init) {
478 				/*
479 				 * Print prefix of device name,
480 				 * let kgdb_connect print the rest.
481 				 */
482 				printf("%s: ", sc->sc_dev.dv_xname);
483 				kgdb_connect(1);
484 			} else
485 				printf("%s: kgdb enabled\n",
486 				    sc->sc_dev.dv_xname);
487 		}
488 	}
489 #endif
490 
491 	/* XXX maybe move up some? */
492 	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
493 		printf("%s: console\n", sc->sc_dev.dv_xname);
494 }
495 
496 int
497 comopen(dev, flag, mode, p)
498 	dev_t dev;
499 	int flag, mode;
500 	struct proc *p;
501 {
502 	int unit = DEVUNIT(dev);
503 	struct com_softc *sc;
504 	bus_space_tag_t iot;
505 	bus_space_handle_t ioh;
506 	struct tty *tp;
507 	int s;
508 	int error = 0;
509 
510 	if (unit >= com_cd.cd_ndevs)
511 		return ENXIO;
512 	sc = com_cd.cd_devs[unit];
513 	if (!sc || ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING))
514 		return ENXIO;
515 
516 	s = spltty();
517 	if (!sc->sc_tty) {
518 		tp = sc->sc_tty = ttymalloc();
519 		tty_attach(tp);
520 	} else
521 		tp = sc->sc_tty;
522 	splx(s);
523 
524 	tp->t_oproc = comstart;
525 	tp->t_param = comparam;
526 	tp->t_dev = dev;
527 	if (!ISSET(tp->t_state, TS_ISOPEN)) {
528 		SET(tp->t_state, TS_WOPEN);
529 		ttychars(tp);
530 		tp->t_iflag = TTYDEF_IFLAG;
531 		tp->t_oflag = TTYDEF_OFLAG;
532 		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
533 			tp->t_cflag = comconscflag;
534 		else
535 			tp->t_cflag = TTYDEF_CFLAG;
536 		if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
537 			SET(tp->t_cflag, CLOCAL);
538 		if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
539 			SET(tp->t_cflag, CRTSCTS);
540 		if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
541 			SET(tp->t_cflag, MDMBUF);
542 		tp->t_lflag = TTYDEF_LFLAG;
543 		tp->t_ispeed = tp->t_ospeed = comdefaultrate;
544 
545 		s = spltty();
546 
547 		sc->sc_initialize = 1;
548 		comparam(tp, &tp->t_termios);
549 		ttsetwater(tp);
550 
551 		if (comsopen++ == 0)
552 			timeout(compoll, NULL, 1);
553 
554 		sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
555 		sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
556 		sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
557 
558 		iot = sc->sc_iot;
559 		ioh = sc->sc_ioh;
560 #ifdef COM_HAYESP
561 		/* Setup the ESP board */
562 		if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
563 			bus_space_handle_t hayespioh = sc->sc_hayespioh;
564 
565 			bus_space_write_1(iot, ioh, com_fifo,
566 			     FIFO_DMA_MODE|FIFO_ENABLE|
567 			     FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
568 
569 			/* Set 16550 compatibility mode */
570 			bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
571 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
572 			     HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
573 			     HAYESP_MODE_SCALE);
574 
575 			/* Set RTS/CTS flow control */
576 			bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
577 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
578 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
579 
580 			/* Set flow control levels */
581 			bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
582 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
583 			     HAYESP_HIBYTE(HAYESP_RXHIWMARK));
584 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
585 			     HAYESP_LOBYTE(HAYESP_RXHIWMARK));
586 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
587 			     HAYESP_HIBYTE(HAYESP_RXLOWMARK));
588 			bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
589 			     HAYESP_LOBYTE(HAYESP_RXLOWMARK));
590 		} else
591 #endif
592 		if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
593 			/*
594 			 * (Re)enable and drain FIFOs.
595 			 *
596 			 * Certain SMC chips cause problems if the FIFOs are
597 			 * enabled while input is ready. Turn off the FIFO
598 			 * if necessary to clear the input. Test the input
599 			 * ready bit after enabling the FIFOs to handle races
600 			 * between enabling and fresh input.
601 			 *
602 			 * Set the FIFO threshold based on the receive speed.
603 			 */
604 			for (;;) {
605 			 	bus_space_write_1(iot, ioh, com_fifo, 0);
606 				delay(100);
607 				(void) bus_space_read_1(iot, ioh, com_data);
608 				bus_space_write_1(iot, ioh, com_fifo,
609 				    FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
610 				    (tp->t_ispeed <= 1200 ?
611 				    FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
612 				delay(100);
613 				if(!ISSET(bus_space_read_1(iot, ioh,
614 				    com_lsr), LSR_RXRDY))
615 				    	break;
616 			}
617 		}
618 
619 		/* flush any pending I/O */
620 		while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
621 			(void) bus_space_read_1(iot, ioh, com_data);
622 		/* you turn me on, baby */
623 		sc->sc_mcr = MCR_DTR | MCR_RTS;
624 		if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
625 			SET(sc->sc_mcr, MCR_IENABLE);
626 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
627 		sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
628 		bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
629 
630 		sc->sc_msr = bus_space_read_1(iot, ioh, com_msr);
631 		if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
632 		    ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
633 			SET(tp->t_state, TS_CARR_ON);
634 		else
635 			CLR(tp->t_state, TS_CARR_ON);
636 	} else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
637 		return EBUSY;
638 	else
639 		s = spltty();
640 
641 	if (DEVCUA(dev)) {
642 		if (ISSET(tp->t_state, TS_ISOPEN)) {
643 			/* Ah, but someone already is dialed in... */
644 			splx(s);
645 			return EBUSY;
646 		}
647 		sc->sc_cua = 1;		/* We go into CUA mode */
648 	}
649 
650 	/* wait for carrier if necessary */
651 	if (ISSET(flag, O_NONBLOCK)) {
652 		if (!DEVCUA(dev) && sc->sc_cua) {
653 			/* Opening TTY non-blocking... but the CUA is busy */
654 			splx(s);
655 			return EBUSY;
656 		}
657 	} else {
658 		while (!(DEVCUA(dev) && sc->sc_cua) &&
659 		    !ISSET(tp->t_cflag, CLOCAL) &&
660 		    !ISSET(tp->t_state, TS_CARR_ON)) {
661 			SET(tp->t_state, TS_WOPEN);
662 			error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
663 			    ttopen, 0);
664 			if (error) {
665 				/* XXX should turn off chip if we're the
666 				   only waiter */
667 				if (DEVCUA(dev))
668 					sc->sc_cua = 0;
669 				CLR(tp->t_state, TS_WOPEN);
670 				splx(s);
671 				return error;
672 			}
673 		}
674 	}
675 	splx(s);
676 
677 	return (*linesw[tp->t_line].l_open)(dev, tp);
678 }
679 
680 int
681 comclose(dev, flag, mode, p)
682 	dev_t dev;
683 	int flag, mode;
684 	struct proc *p;
685 {
686 	int unit = DEVUNIT(dev);
687 	struct com_softc *sc = com_cd.cd_devs[unit];
688 	struct tty *tp = sc->sc_tty;
689 	bus_space_tag_t iot = sc->sc_iot;
690 	bus_space_handle_t ioh = sc->sc_ioh;
691 	int s;
692 
693 	/* XXX This is for cons.c. */
694 	if (!ISSET(tp->t_state, TS_ISOPEN))
695 		return 0;
696 
697 	(*linesw[tp->t_line].l_close)(tp, flag);
698 	s = spltty();
699 	if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
700 		/* can't do any of this stuff .... */
701 		CLR(sc->sc_lcr, LCR_SBREAK);
702 		bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
703 		bus_space_write_1(iot, ioh, com_ier, 0);
704 		if (ISSET(tp->t_cflag, HUPCL) &&
705 		    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
706 			/* XXX perhaps only clear DTR */
707 			bus_space_write_1(iot, ioh, com_mcr, 0);
708 		}
709 	}
710 	CLR(tp->t_state, TS_BUSY | TS_FLUSH);
711 	if (--comsopen == 0)
712 		untimeout(compoll, NULL);
713 	sc->sc_cua = 0;
714 	splx(s);
715 	ttyclose(tp);
716 #ifdef COM_DEBUG
717 	/* mark it ready for more use if reattached earlier */
718 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
719 	    printf("comclose pending cleared\n");
720 	}
721 #endif
722 	CLR(sc->sc_hwflags, COM_HW_ABSENT_PENDING);
723 
724 #ifdef notyet /* XXXX */
725 	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
726 		ttyfree(tp);
727 		sc->sc_tty = 0;
728 	}
729 #endif
730 	return 0;
731 }
732 
733 int
734 comread(dev, uio, flag)
735 	dev_t dev;
736 	struct uio *uio;
737 	int flag;
738 {
739 	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
740 	struct tty *tp = sc->sc_tty;
741 
742 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
743 		int s = spltty();
744 		com_absent_notify(sc);
745 		splx(s);
746 		return EIO;
747 	}
748 
749 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
750 }
751 
752 int
753 comwrite(dev, uio, flag)
754 	dev_t dev;
755 	struct uio *uio;
756 	int flag;
757 {
758 	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
759 	struct tty *tp = sc->sc_tty;
760 
761 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
762 		int s = spltty();
763 		com_absent_notify(sc);
764 		splx(s);
765 		return EIO;
766 	}
767 
768 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
769 }
770 
771 struct tty *
772 comtty(dev)
773 	dev_t dev;
774 {
775 	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
776 	struct tty *tp = sc->sc_tty;
777 
778 	return (tp);
779 }
780 
781 static u_char
782 tiocm_xxx2mcr(data)
783 	int data;
784 {
785 	u_char m = 0;
786 
787 	if (ISSET(data, TIOCM_DTR))
788 		SET(m, MCR_DTR);
789 	if (ISSET(data, TIOCM_RTS))
790 		SET(m, MCR_RTS);
791 	return m;
792 }
793 
794 int
795 comioctl(dev, cmd, data, flag, p)
796 	dev_t dev;
797 	u_long cmd;
798 	caddr_t data;
799 	int flag;
800 	struct proc *p;
801 {
802 	int unit = DEVUNIT(dev);
803 	struct com_softc *sc = com_cd.cd_devs[unit];
804 	struct tty *tp = sc->sc_tty;
805 	bus_space_tag_t iot = sc->sc_iot;
806 	bus_space_handle_t ioh = sc->sc_ioh;
807 	int error;
808 
809 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
810 		int s = spltty();
811 		com_absent_notify(sc);
812 		splx(s);
813 		return EIO;
814 	}
815 
816 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
817 	if (error >= 0)
818 		return error;
819 	error = ttioctl(tp, cmd, data, flag, p);
820 	if (error >= 0)
821 		return error;
822 
823 	switch (cmd) {
824 	case TIOCSBRK:
825 		SET(sc->sc_lcr, LCR_SBREAK);
826 		bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
827 		break;
828 	case TIOCCBRK:
829 		CLR(sc->sc_lcr, LCR_SBREAK);
830 		bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
831 		break;
832 	case TIOCSDTR:
833 		SET(sc->sc_mcr, sc->sc_dtr);
834 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
835 		break;
836 	case TIOCCDTR:
837 		CLR(sc->sc_mcr, sc->sc_dtr);
838 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
839 		break;
840 	case TIOCMSET:
841 		CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
842 	case TIOCMBIS:
843 		SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
844 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
845 		break;
846 	case TIOCMBIC:
847 		CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
848 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
849 		break;
850 	case TIOCMGET: {
851 		u_char m;
852 		int bits = 0;
853 
854 		m = sc->sc_mcr;
855 		if (ISSET(m, MCR_DTR))
856 			SET(bits, TIOCM_DTR);
857 		if (ISSET(m, MCR_RTS))
858 			SET(bits, TIOCM_RTS);
859 		m = sc->sc_msr;
860 		if (ISSET(m, MSR_DCD))
861 			SET(bits, TIOCM_CD);
862 		if (ISSET(m, MSR_CTS))
863 			SET(bits, TIOCM_CTS);
864 		if (ISSET(m, MSR_DSR))
865 			SET(bits, TIOCM_DSR);
866 		if (ISSET(m, MSR_RI | MSR_TERI))
867 			SET(bits, TIOCM_RI);
868 		if (bus_space_read_1(iot, ioh, com_ier))
869 			SET(bits, TIOCM_LE);
870 		*(int *)data = bits;
871 		break;
872 	}
873 	case TIOCGFLAGS: {
874 		int driverbits, userbits = 0;
875 
876 		driverbits = sc->sc_swflags;
877 		if (ISSET(driverbits, COM_SW_SOFTCAR))
878 			SET(userbits, TIOCFLAG_SOFTCAR);
879 		if (ISSET(driverbits, COM_SW_CLOCAL))
880 			SET(userbits, TIOCFLAG_CLOCAL);
881 		if (ISSET(driverbits, COM_SW_CRTSCTS))
882 			SET(userbits, TIOCFLAG_CRTSCTS);
883 		if (ISSET(driverbits, COM_SW_MDMBUF))
884 			SET(userbits, TIOCFLAG_MDMBUF);
885 
886 		*(int *)data = userbits;
887 		break;
888 	}
889 	case TIOCSFLAGS: {
890 		int userbits, driverbits = 0;
891 
892 		error = suser(p->p_ucred, &p->p_acflag);
893 		if (error != 0)
894 			return(EPERM);
895 
896 		userbits = *(int *)data;
897 		if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
898 		    ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
899 			SET(driverbits, COM_SW_SOFTCAR);
900 		if (ISSET(userbits, TIOCFLAG_CLOCAL))
901 			SET(driverbits, COM_SW_CLOCAL);
902 		if (ISSET(userbits, TIOCFLAG_CRTSCTS))
903 			SET(driverbits, COM_SW_CRTSCTS);
904 		if (ISSET(userbits, TIOCFLAG_MDMBUF))
905 			SET(driverbits, COM_SW_MDMBUF);
906 
907 		sc->sc_swflags = driverbits;
908 		break;
909 	}
910 	default:
911 		return ENOTTY;
912 	}
913 
914 	return 0;
915 }
916 
917 int
918 comparam(tp, t)
919 	struct tty *tp;
920 	struct termios *t;
921 {
922 	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
923 	bus_space_tag_t iot = sc->sc_iot;
924 	bus_space_handle_t ioh = sc->sc_ioh;
925 	int ospeed = comspeed(t->c_ospeed);
926 	u_char lcr;
927 	tcflag_t oldcflag;
928 	int s;
929 
930 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
931 		int s = spltty();
932 		com_absent_notify(sc);
933 		splx(s);
934 		return EIO;
935 	}
936 
937 	/* check requested parameters */
938 	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
939 		return EINVAL;
940 
941 	lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
942 
943 	switch (ISSET(t->c_cflag, CSIZE)) {
944 	case CS5:
945 		SET(lcr, LCR_5BITS);
946 		break;
947 	case CS6:
948 		SET(lcr, LCR_6BITS);
949 		break;
950 	case CS7:
951 		SET(lcr, LCR_7BITS);
952 		break;
953 	case CS8:
954 		SET(lcr, LCR_8BITS);
955 		break;
956 	}
957 	if (ISSET(t->c_cflag, PARENB)) {
958 		SET(lcr, LCR_PENAB);
959 		if (!ISSET(t->c_cflag, PARODD))
960 			SET(lcr, LCR_PEVEN);
961 	}
962 	if (ISSET(t->c_cflag, CSTOPB))
963 		SET(lcr, LCR_STOPB);
964 
965 	sc->sc_lcr = lcr;
966 
967 	s = spltty();
968 
969 	if (ospeed == 0) {
970 		CLR(sc->sc_mcr, MCR_DTR);
971 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
972 	}
973 
974 	/*
975 	 * Set the FIFO threshold based on the receive speed, if we are
976 	 * changing it.
977 	 */
978 	if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
979 		sc->sc_initialize = 0;
980 
981 		if (ospeed != 0) {
982 			/*
983 			 * Make sure the transmit FIFO is empty before
984 			 * proceeding.  If we don't do this, some revisions
985 			 * of the UART will hang.  Interestingly enough,
986 			 * even if we do this will the last character is
987 			 * still being pushed out, they don't hang.  This
988 			 * seems good enough.
989 			 */
990 			while (ISSET(tp->t_state, TS_BUSY)) {
991 				int error;
992 
993 				++sc->sc_halt;
994 				error = ttysleep(tp, &tp->t_outq,
995 				    TTOPRI | PCATCH, "comprm", 0);
996 				--sc->sc_halt;
997 				if (error) {
998 					splx(s);
999 					comstart(tp);
1000 					return (error);
1001 				}
1002 			}
1003 
1004 			bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
1005 			bus_space_write_1(iot, ioh, com_dlbl, ospeed);
1006 			bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8);
1007 			bus_space_write_1(iot, ioh, com_lcr, lcr);
1008 			SET(sc->sc_mcr, MCR_DTR);
1009 			bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1010 		} else
1011 			bus_space_write_1(iot, ioh, com_lcr, lcr);
1012 
1013 		if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
1014 		    ISSET(sc->sc_hwflags, COM_HW_FIFO))
1015 			bus_space_write_1(iot, ioh, com_fifo,
1016 			    FIFO_ENABLE |
1017 			    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
1018 	} else
1019 		bus_space_write_1(iot, ioh, com_lcr, lcr);
1020 
1021 	/* When not using CRTSCTS, RTS follows DTR. */
1022 	if (!ISSET(t->c_cflag, CRTSCTS)) {
1023 		if (ISSET(sc->sc_mcr, MCR_DTR)) {
1024 			if (!ISSET(sc->sc_mcr, MCR_RTS)) {
1025 				SET(sc->sc_mcr, MCR_RTS);
1026 				bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1027 			}
1028 		} else {
1029 			if (ISSET(sc->sc_mcr, MCR_RTS)) {
1030 				CLR(sc->sc_mcr, MCR_RTS);
1031 				bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1032 			}
1033 		}
1034 		sc->sc_dtr = MCR_DTR | MCR_RTS;
1035 	} else
1036 		sc->sc_dtr = MCR_DTR;
1037 
1038 	/* and copy to tty */
1039 	tp->t_ispeed = t->c_ispeed;
1040 	tp->t_ospeed = t->c_ospeed;
1041 	oldcflag = tp->t_cflag;
1042 	tp->t_cflag = t->c_cflag;
1043 
1044 	/*
1045 	 * If DCD is off and MDMBUF is changed, ask the tty layer if we should
1046 	 * stop the device.
1047 	 */
1048 	if (!ISSET(sc->sc_msr, MSR_DCD) &&
1049 	    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
1050 	    ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
1051 	    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
1052 		CLR(sc->sc_mcr, sc->sc_dtr);
1053 		bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1054 	}
1055 
1056 	/* Just to be sure... */
1057 	splx(s);
1058 	comstart(tp);
1059 	return 0;
1060 }
1061 
1062 void
1063 comstart_pending(arg)
1064 	void *arg;
1065 {
1066 	struct com_softc *sc = arg;
1067 	int s;
1068 
1069 	s = spltty();
1070 	com_absent_notify(sc);
1071 	splx(s);
1072 }
1073 
1074 void
1075 comstart(tp)
1076 	struct tty *tp;
1077 {
1078 	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
1079 	bus_space_tag_t iot = sc->sc_iot;
1080 	bus_space_handle_t ioh = sc->sc_ioh;
1081 	int s;
1082 
1083 	s = spltty();
1084 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
1085 		/*
1086 		 * not quite good enough: if caller is ttywait() it will
1087 		 * go to sleep immediately, so hang out a bit and then
1088 		 * prod caller again.
1089 		 */
1090 		com_absent_notify(sc);
1091 		timeout(comstart_pending, sc, 1);
1092 		goto out;
1093 	}
1094 	if (ISSET(tp->t_state, TS_BUSY))
1095 		goto out;
1096 	if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
1097 	    sc->sc_halt > 0)
1098 		goto stopped;
1099 	if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
1100 		goto stopped;
1101 	if (tp->t_outq.c_cc <= tp->t_lowat) {
1102 		if (ISSET(tp->t_state, TS_ASLEEP)) {
1103 			CLR(tp->t_state, TS_ASLEEP);
1104 			wakeup(&tp->t_outq);
1105 		}
1106 		if (tp->t_outq.c_cc == 0)
1107 			goto stopped;
1108 		selwakeup(&tp->t_wsel);
1109 	}
1110 	SET(tp->t_state, TS_BUSY);
1111 
1112 	if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
1113 		SET(sc->sc_ier, IER_ETXRDY);
1114 		bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1115 	}
1116 #ifdef COM_HAYESP
1117 	if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
1118 		u_char buffer[1024], *cp = buffer;
1119 		int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
1120 		do
1121 			bus_space_write_1(iot, ioh, com_data, *cp++);
1122 		while (--n);
1123 	}
1124 	else
1125 #endif
1126 	if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
1127 		u_char buffer[16], *cp = buffer;
1128 		int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
1129 		do {
1130 			bus_space_write_1(iot, ioh, com_data, *cp++);
1131 		} while (--n);
1132 	} else
1133 		bus_space_write_1(iot, ioh, com_data, getc(&tp->t_outq));
1134 out:
1135 	splx(s);
1136 	return;
1137 stopped:
1138 	if (ISSET(sc->sc_ier, IER_ETXRDY)) {
1139 		CLR(sc->sc_ier, IER_ETXRDY);
1140 		bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1141 	}
1142 	splx(s);
1143 }
1144 
1145 /*
1146  * Stop output on a line.
1147  */
1148 int
1149 comstop(tp, flag)
1150 	struct tty *tp;
1151 	int flag;
1152 {
1153 	int s;
1154 
1155 	s = spltty();
1156 	if (ISSET(tp->t_state, TS_BUSY))
1157 		if (!ISSET(tp->t_state, TS_TTSTOP))
1158 			SET(tp->t_state, TS_FLUSH);
1159 	splx(s);
1160 	return 0;
1161 }
1162 
1163 void
1164 comdiag(arg)
1165 	void *arg;
1166 {
1167 	struct com_softc *sc = arg;
1168 	int overflows, floods;
1169 	int s;
1170 
1171 	s = spltty();
1172 	sc->sc_errors = 0;
1173 	overflows = sc->sc_overflows;
1174 	sc->sc_overflows = 0;
1175 	floods = sc->sc_floods;
1176 	sc->sc_floods = 0;
1177 	splx(s);
1178 
1179 	log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
1180 	    sc->sc_dev.dv_xname,
1181 	    overflows, overflows == 1 ? "" : "s",
1182 	    floods, floods == 1 ? "" : "s");
1183 }
1184 
1185 void
1186 compoll(arg)
1187 	void *arg;
1188 {
1189 	int unit;
1190 	struct com_softc *sc;
1191 	struct tty *tp;
1192 	register u_char *ibufp;
1193 	u_char *ibufend;
1194 	register int c;
1195 	int s;
1196 	static int lsrmap[8] = {
1197 		0,      TTY_PE,
1198 		TTY_FE, TTY_PE|TTY_FE,
1199 		TTY_FE, TTY_PE|TTY_FE,
1200 		TTY_FE, TTY_PE|TTY_FE
1201 	};
1202 
1203 	s = spltty();
1204 	if (comevents == 0) {
1205 		splx(s);
1206 		goto out;
1207 	}
1208 	comevents = 0;
1209 	splx(s);
1210 
1211 	for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
1212 		sc = com_cd.cd_devs[unit];
1213 		if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
1214 			continue;
1215 
1216 		tp = sc->sc_tty;
1217 
1218 		s = spltty();
1219 
1220 		ibufp = sc->sc_ibuf;
1221 		ibufend = sc->sc_ibufp;
1222 
1223 		if (ibufp == ibufend) {
1224 			splx(s);
1225 			continue;
1226 		}
1227 
1228 		sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
1229 					     sc->sc_ibufs[1] : sc->sc_ibufs[0];
1230 		sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
1231 		sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
1232 
1233 		if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) {
1234 			splx(s);
1235 			continue;
1236 		}
1237 
1238 		if (ISSET(tp->t_cflag, CRTSCTS) &&
1239 		    !ISSET(sc->sc_mcr, MCR_RTS)) {
1240 			/* XXX */
1241 			SET(sc->sc_mcr, MCR_RTS);
1242 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr,
1243 			    sc->sc_mcr);
1244 		}
1245 
1246 		splx(s);
1247 
1248 		while (ibufp < ibufend) {
1249 			c = *ibufp++;
1250 			if (*ibufp & LSR_OE) {
1251 				sc->sc_overflows++;
1252 				if (sc->sc_errors++ == 0)
1253 					timeout(comdiag, sc, 60 * hz);
1254 			}
1255 			/* This is ugly, but fast. */
1256 			c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
1257 			(*linesw[tp->t_line].l_rint)(c, tp);
1258 		}
1259 	}
1260 
1261 out:
1262 	timeout(compoll, NULL, 1);
1263 }
1264 
1265 int
1266 comintr(arg)
1267 	void *arg;
1268 {
1269 	struct com_softc *sc = arg;
1270 	bus_space_tag_t iot = sc->sc_iot;
1271 	bus_space_handle_t ioh = sc->sc_ioh;
1272 	struct tty *tp;
1273 	u_char lsr, data, msr, delta;
1274 #ifdef COM_DEBUG
1275 	int n;
1276 	struct {
1277 		u_char iir, lsr, msr;
1278 	} iter[32];
1279 #endif
1280 
1281 	if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
1282 		return 0;		/* can't do squat. */
1283 
1284 #ifdef COM_DEBUG
1285 	n = 0;
1286 	if (ISSET(iter[n].iir = bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1287 		return (0);
1288 #else
1289 	if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1290 		return (0);
1291 #endif
1292 
1293 	tp = sc->sc_tty;
1294 
1295 	for (;;) {
1296 #ifdef COM_DEBUG
1297 		iter[n].lsr =
1298 #endif
1299 		lsr = bus_space_read_1(iot, ioh, com_lsr);
1300 
1301 		if (ISSET(lsr, LSR_RXRDY)) {
1302 			register u_char *p = sc->sc_ibufp;
1303 
1304 			comevents = 1;
1305 			do {
1306 				data = bus_space_read_1(iot, ioh, com_data);
1307 				if (ISSET(lsr, LSR_BI)) {
1308 #ifdef notdef
1309 					printf("break %02x %02x %02x %02x\n",
1310 					    sc->sc_msr, sc->sc_mcr, sc->sc_lcr,
1311 					    sc->sc_dtr);
1312 #endif
1313 #ifdef DDB
1314 					if (ISSET(sc->sc_hwflags,
1315 					    COM_HW_CONSOLE)) {
1316 						Debugger();
1317 						goto next;
1318 					}
1319 #endif
1320 					data = 0;
1321 				}
1322 				if (p >= sc->sc_ibufend) {
1323 					sc->sc_floods++;
1324 					if (sc->sc_errors++ == 0)
1325 						timeout(comdiag, sc, 60 * hz);
1326 				} else {
1327 					*p++ = data;
1328 					*p++ = lsr;
1329 					if (p == sc->sc_ibufhigh &&
1330 					    ISSET(tp->t_cflag, CRTSCTS)) {
1331 						/* XXX */
1332 						CLR(sc->sc_mcr, MCR_RTS);
1333 						bus_space_write_1(iot, ioh, com_mcr,
1334 						    sc->sc_mcr);
1335 					}
1336 				}
1337 #ifdef DDB
1338 			next:
1339 #endif
1340 #ifdef COM_DEBUG
1341 				if (++n >= 32)
1342 					goto ohfudge;
1343 				iter[n].lsr =
1344 #endif
1345 				lsr = bus_space_read_1(iot, ioh, com_lsr);
1346 			} while (ISSET(lsr, LSR_RXRDY));
1347 
1348 			sc->sc_ibufp = p;
1349 		}
1350 #ifdef COM_DEBUG
1351 		else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
1352 			printf("weird lsr %02x\n", lsr);
1353 #endif
1354 
1355 #ifdef COM_DEBUG
1356 		iter[n].msr =
1357 #endif
1358 		msr = bus_space_read_1(iot, ioh, com_msr);
1359 
1360 		if (msr != sc->sc_msr) {
1361 			delta = msr ^ sc->sc_msr;
1362 			sc->sc_msr = msr;
1363 			if (ISSET(delta, MSR_DCD) &&
1364 			    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
1365 			    (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
1366 				CLR(sc->sc_mcr, sc->sc_dtr);
1367 				bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1368 			}
1369 			if (ISSET(delta & msr, MSR_CTS) &&
1370 			    ISSET(tp->t_cflag, CRTSCTS)) {
1371 				/* the line is up and we want to do rts/cts flow control */
1372 				(*linesw[tp->t_line].l_start)(tp);
1373 			}
1374 		}
1375 
1376 		if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
1377 			CLR(tp->t_state, TS_BUSY | TS_FLUSH);
1378 			if (sc->sc_halt > 0)
1379 				wakeup(&tp->t_outq);
1380 			(*linesw[tp->t_line].l_start)(tp);
1381 		}
1382 
1383 #ifdef COM_DEBUG
1384 		if (++n >= 32)
1385 			goto ohfudge;
1386 		if (ISSET(iter[n].iir = bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1387 			return (1);
1388 #else
1389 		if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1390 			return (1);
1391 #endif
1392 	}
1393 #ifdef COM_DEBUG
1394 ohfudge:
1395 	printf("comintr: too many iterations");
1396 	for (n = 0; n < 32; n++) {
1397 		if ((n % 4) == 0)
1398 			printf("\ncomintr: iter[%02d]", n);
1399 		printf("  %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr);
1400 	}
1401 	printf("\n");
1402 	printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n",
1403 	    sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier);
1404 	printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state,
1405 	    sc->sc_tty->t_outq.c_cc);
1406 #endif
1407 }
1408 
1409 /*
1410  * Following are all routines needed for COM to act as console
1411  */
1412 #include <dev/cons.h>
1413 
1414 void
1415 comcnprobe(cp)
1416 	struct consdev *cp;
1417 {
1418 	/* XXX NEEDS TO BE FIXED XXX */
1419 	bus_space_tag_t iot = 0;
1420 	bus_space_handle_t ioh;
1421 	int found;
1422 #if NCOM_PICA
1423 	/* XXX */
1424 #include <arc/arc/arctype.h>
1425 	extern int cputype;
1426 
1427 	if(cputype != ACER_PICA_61)
1428 		return;
1429 #endif
1430 
1431 	if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh)) {
1432 		cp->cn_pri = CN_DEAD;
1433 		return;
1434 	}
1435 	found = comprobe1(iot, ioh, CONADDR);
1436 	bus_space_unmap(iot, ioh, COM_NPORTS);
1437 	if (!found) {
1438 		cp->cn_pri = CN_DEAD;
1439 		return;
1440 	}
1441 
1442 	/* locate the major number */
1443 	for (commajor = 0; commajor < nchrdev; commajor++)
1444 		if (cdevsw[commajor].d_open == comopen)
1445 			break;
1446 
1447 	/* initialize required fields */
1448 	cp->cn_dev = makedev(commajor, CONUNIT);
1449 #ifdef	COMCONSOLE
1450 	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
1451 #else
1452 	cp->cn_pri = CN_NORMAL;
1453 #endif
1454 }
1455 
1456 void
1457 comcninit(cp)
1458 	struct consdev *cp;
1459 {
1460 
1461 #if 0
1462 	XXX NEEDS TO BE FIXED XXX
1463 	comconsiot = ???;
1464 #endif
1465 	if (bus_space_map(comconsiot, CONADDR, COM_NPORTS, 0, &comconsioh))
1466 		panic("comcninit: mapping failed");
1467 
1468 	cominit(comconsiot, comconsioh, comdefaultrate);
1469 	comconsaddr = CONADDR;
1470 	comconsinit = 0;
1471 }
1472 
1473 void
1474 cominit(iot, ioh, rate)
1475 	bus_space_tag_t iot;
1476 	bus_space_handle_t ioh;
1477 	int rate;
1478 {
1479 	int s = splhigh();
1480 	u_char stat;
1481 
1482 	bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
1483 	rate = comspeed(comdefaultrate);
1484 	bus_space_write_1(iot, ioh, com_dlbl, rate);
1485 	bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
1486 	bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
1487 	bus_space_write_1(iot, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
1488 	bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
1489 	stat = bus_space_read_1(iot, ioh, com_iir);
1490 	splx(s);
1491 }
1492 
1493 int
1494 comcngetc(dev)
1495 	dev_t dev;
1496 {
1497 	int s = splhigh();
1498 	bus_space_tag_t iot = comconsiot;
1499 	bus_space_handle_t ioh = comconsioh;
1500 	u_char stat, c;
1501 
1502 	while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
1503 		;
1504 	c = bus_space_read_1(iot, ioh, com_data);
1505 	stat = bus_space_read_1(iot, ioh, com_iir);
1506 	splx(s);
1507 	return c;
1508 }
1509 
1510 /*
1511  * Console kernel output character routine.
1512  */
1513 void
1514 comcnputc(dev, c)
1515 	dev_t dev;
1516 	int c;
1517 {
1518 	int s = splhigh();
1519 	bus_space_tag_t iot = comconsiot;
1520 	bus_space_handle_t ioh = comconsioh;
1521 	u_char stat;
1522 	register int timo;
1523 
1524 #ifdef KGDB
1525 	if (dev != kgdb_dev)
1526 #endif
1527 	if (comconsinit == 0) {
1528 		cominit(iot, ioh, comdefaultrate);
1529 		comconsinit = 1;
1530 	}
1531 	/* wait for any pending transmission to finish */
1532 	timo = 50000;
1533 	while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
1534 		;
1535 	bus_space_write_1(iot, ioh, com_data, c);
1536 	/* wait for this transmission to complete */
1537 	timo = 1500000;
1538 	while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
1539 		;
1540 	/* clear any interrupts generated by this transmission */
1541 	stat = bus_space_read_1(iot, ioh, com_iir);
1542 	splx(s);
1543 }
1544 
1545 void
1546 comcnpollc(dev, on)
1547 	dev_t dev;
1548 	int on;
1549 {
1550 
1551 }
1552