Home | History | Annotate | Line # | Download | only in sa11x0
sa11x0_com.c revision 1.1.4.2
      1 /*      $NetBSD: sa11x0_com.c,v 1.1.4.2 2001/10/13 17:42:34 fvdl Exp $        */
      2 
      3 /*-
      4  * Copyright (c) 1998, 1999, 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by IWAMOTO Toshihiro.
      9  *
     10  * This code is derived from software contributed to The NetBSD Foundation
     11  * by Charles M. Hannum.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  * 1. Redistributions of source code must retain the above copyright
     17  *    notice, this list of conditions and the following disclaimer.
     18  * 2. Redistributions in binary form must reproduce the above copyright
     19  *    notice, this list of conditions and the following disclaimer in the
     20  *    documentation and/or other materials provided with the distribution.
     21  * 3. All advertising materials mentioning features or use of this software
     22  *    must display the following acknowledgement:
     23  *        This product includes software developed by the NetBSD
     24  *        Foundation, Inc. and its contributors.
     25  * 4. Neither the name of The NetBSD Foundation nor the names of its
     26  *    contributors may be used to endorse or promote products derived
     27  *    from this software without specific prior written permission.
     28  *
     29  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     39  * POSSIBILITY OF SUCH DAMAGE.
     40  */
     41 
     42 /*
     43  * Copyright (c) 1991 The Regents of the University of California.
     44  * All rights reserved.
     45  *
     46  * Redistribution and use in source and binary forms, with or without
     47  * modification, are permitted provided that the following conditions
     48  * are met:
     49  * 1. Redistributions of source code must retain the above copyright
     50  *    notice, this list of conditions and the following disclaimer.
     51  * 2. Redistributions in binary form must reproduce the above copyright
     52  *    notice, this list of conditions and the following disclaimer in the
     53  *    documentation and/or other materials provided with the distribution.
     54  * 3. All advertising materials mentioning features or use of this software
     55  *    must display the following acknowledgement:
     56  *	This product includes software developed by the University of
     57  *	California, Berkeley and its contributors.
     58  * 4. Neither the name of the University nor the names of its contributors
     59  *    may be used to endorse or promote products derived from this software
     60  *    without specific prior written permission.
     61  *
     62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     72  * SUCH DAMAGE.
     73  *
     74  *	@(#)com.c	7.5 (Berkeley) 5/16/91
     75  */
     76 
     77 #include "opt_com.h"
     78 #include "opt_ddb.h"
     79 #include "opt_ddbparam.h"
     80 #include "opt_kgdb.h"
     81 
     82 #include "rnd.h"
     83 #if NRND > 0 && defined(RND_COM)
     84 #include <sys/rnd.h>
     85 #endif
     86 
     87 #include <sys/param.h>
     88 #include <sys/systm.h>
     89 #include <sys/types.h>
     90 #include <sys/conf.h>
     91 #include <sys/file.h>
     92 #include <sys/device.h>
     93 #include <sys/kernel.h>
     94 #include <sys/malloc.h>
     95 #include <sys/tty.h>
     96 #include <sys/uio.h>
     97 #include <sys/vnode.h>
     98 
     99 #include <dev/cons.h>
    100 
    101 #include <machine/bus.h>
    102 #include <arm/sa11x0/sa11x0_reg.h>
    103 #include <arm/sa11x0/sa11x0_var.h>
    104 #include <arm/sa11x0/sa11x0_comreg.h>
    105 #include <arm/sa11x0/sa11x0_comvar.h>
    106 
    107 #include "sacom.h"
    108 
    109 cdev_decl(sacom);
    110 
    111 static	int	sacom_match(struct device *, struct cfdata *, void *);
    112 static	void	sacom_attach(struct device *, struct device *, void *);
    113 static	void	sacom_filltx(struct sacom_softc *);
    114 static	void	sacom_attach_subr(struct sacom_softc *);
    115 #if defined(DDB) || defined(KGDB)
    116 static	void	sacom_enable_debugport(struct sacom_softc *);
    117 #endif
    118 void		sacom_config(struct sacom_softc *);
    119 void		sacom_shutdown(struct sacom_softc *);
    120 static	u_int	cflag2cr0(tcflag_t);
    121 int		sacomparam(struct tty *, struct termios *);
    122 void		sacomstart(struct tty *);
    123 void		sacomstop(struct tty *, int);
    124 int		sacomhwiflow(struct tty *, int);
    125 
    126 void		sacom_loadchannelregs(struct sacom_softc *);
    127 void		sacom_hwiflow(struct sacom_softc *);
    128 void		sacom_break(struct sacom_softc *, int);
    129 void		sacom_modem(struct sacom_softc *, int);
    130 void		tiocm_to_sacom(struct sacom_softc *, u_long, int);
    131 int		sacom_to_tiocm(struct sacom_softc *);
    132 void		sacom_iflush(struct sacom_softc *);
    133 
    134 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    135 void 		sacomsoft(void *);
    136 #else
    137 void 		sacomsoft(void);
    138 #endif
    139 
    140 static inline void sacom_rxsoft(struct sacom_softc *, struct tty *);
    141 static inline void sacom_txsoft(struct sacom_softc *, struct tty *);
    142 static inline void sacom_stsoft(struct sacom_softc *, struct tty *);
    143 static inline void sacom_schedrx(struct sacom_softc *);
    144 
    145 
    146 #define COMUNIT_MASK	0x7ffff
    147 #define COMDIALOUT_MASK	0x80000
    148 
    149 #define COMUNIT(x)	(minor(x) & COMUNIT_MASK)
    150 #define COMDIALOUT(x)	(minor(x) & COMDIALOUT_MASK)
    151 
    152 #define COM_ISALIVE(sc)	((sc)->enabled != 0 && \
    153 			 ISSET((sc)->sc_dev.dv_flags, DVF_ACTIVE))
    154 
    155 #define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))
    156 #define COM_LOCK(sc)
    157 #define COM_UNLOCK(sc)
    158 
    159 #define SET(t, f)	(t) |= (f)
    160 #define CLR(t, f)	(t) &= ~(f)
    161 #define ISSET(t, f)	((t) & (f))
    162 
    163 int		sacomintr(void *);
    164 int		sacomcngetc(dev_t);
    165 void		sacomcnputc(dev_t, int);
    166 void		sacomcnpollc(dev_t, int);
    167 
    168 void		sacomcnprobe(struct consdev *);
    169 void		sacomcninit(struct consdev *);
    170 
    171 extern struct bus_space sa11x0_bs_tag;
    172 
    173 static bus_space_tag_t sacomconstag;
    174 static bus_space_handle_t sacomconsioh;
    175 static bus_addr_t sacomconsaddr = SACOM3_BASE; /* XXX */
    176 
    177 static int sacomconsattached;
    178 static int sacomconsrate;
    179 static tcflag_t sacomconscflag;
    180 
    181 struct cfattach sacom_ca = {
    182 	sizeof(struct sacom_softc), sacom_match, sacom_attach
    183 };
    184 extern struct cfdriver sacom_cd;
    185 
    186 struct consdev sacomcons = {
    187 	NULL, NULL, sacomcngetc, sacomcnputc, sacomcnpollc, NULL,
    188 	NODEV, CN_NORMAL
    189 };
    190 
    191 #ifndef CONMODE
    192 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    193 #endif
    194 #ifndef CONSPEED
    195 #define CONSPEED 9600
    196 #endif
    197 #ifndef CONADDR
    198 #define CONADDR SACOM3_BASE
    199 #endif
    200 
    201 static int
    202 sacom_match(parent, match, aux)
    203 	struct device *parent;
    204 	struct cfdata *match;
    205 	void *aux;
    206 {
    207 	return (1);
    208 }
    209 
    210 void
    211 sacom_attach(parent, self, aux)
    212 	struct device *parent;
    213 	struct device *self;
    214 	void *aux;
    215 {
    216 	struct sacom_softc *sc = (struct sacom_softc*)self;
    217 	struct sa11x0_attach_args *sa = aux;
    218 
    219 	printf("\n");
    220 
    221 	sc->sc_iot = sa->sa_iot;
    222 	sc->sc_baseaddr = sa->sa_addr;
    223 
    224 	if(bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0,
    225 			&sc->sc_ioh)) {
    226 		printf("%s: unable to map registers\n", sc->sc_dev.dv_xname);
    227 		return;
    228 	}
    229 
    230 	printf("%s: ", sc->sc_dev.dv_xname);
    231 	switch(sc->sc_baseaddr) {
    232 	case 0x80050000:
    233 		printf("SA11x0 UART3\n");
    234 		break;
    235 	case 0x80010000:
    236 		printf("SA11x0 UART1\n");
    237 		break;
    238 	case 0x80030000:
    239 		printf("SA11x0 UART2 (IRDA)\n");
    240 		break;
    241 	default:
    242 		printf("unknown SA11x0 UART\n");
    243 		break;
    244 	}
    245 
    246 	sacom_attach_subr(sc);
    247 
    248 	sa11x0_intr_establish(0, sa->sa_intr, 1, IPL_SERIAL, sacomintr, sc);
    249 }
    250 
    251 void
    252 sacom_attach_subr(sc)
    253 	struct sacom_softc *sc;
    254 {
    255 	bus_addr_t iobase = sc->sc_baseaddr;
    256 	bus_space_tag_t iot = sc->sc_iot;
    257 	struct tty *tp;
    258 
    259 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(COM_MPLOCK)
    260 	simple_lock_init(&sc->sc_lock);
    261 #endif
    262 
    263 	/* XXX Do we need to disable interrupts here? */
    264 
    265 	if (iot == sacomconstag && iobase == sacomconsaddr) {
    266 		sacomconsattached = 1;
    267 		sc->sc_speed = SACOMSPEED(sacomconsrate);
    268 
    269 		/* Make sure the console is always "hardwired". */
    270 		delay(10000);			/* wait for output to finish */
    271 		SET(sc->sc_hwflags, COM_HW_CONSOLE);
    272 		SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
    273 	}
    274 
    275 	tp = ttymalloc();
    276 	tp->t_oproc = sacomstart;
    277 	tp->t_param = sacomparam;
    278 	tp->t_hwiflow = sacomhwiflow;
    279 
    280 	sc->sc_tty = tp;
    281 	sc->sc_rbuf = malloc(SACOM_RING_SIZE << 1, M_DEVBUF, M_NOWAIT);
    282 	sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
    283 	sc->sc_rbavail = SACOM_RING_SIZE;
    284 	if (sc->sc_rbuf == NULL) {
    285 		printf("%s: unable to allocate ring buffer\n",
    286 		    sc->sc_dev.dv_xname);
    287 		return;
    288 	}
    289 	sc->sc_ebuf = sc->sc_rbuf + (SACOM_RING_SIZE << 1);
    290 	sc->sc_tbc = 0;
    291 
    292 	tty_attach(tp);
    293 
    294 	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
    295 		int maj;
    296 
    297 		/* locate the major number */
    298 		for (maj = 0; maj < nchrdev; maj++)
    299 			if (cdevsw[maj].d_open == sacomopen)
    300 				break;
    301 
    302 		cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
    303 
    304 		delay(10000); /* XXX */
    305 		printf("%s: console\n", sc->sc_dev.dv_xname);
    306 		delay(10000); /* XXX */
    307 	}
    308 
    309 
    310 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    311 	sc->sc_si = softintr_establish(IPL_SOFTSERIAL, sacomsoft, sc);
    312 #endif
    313 
    314 #if NRND > 0 && defined(RND_COM)
    315 	rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
    316 			  RND_TYPE_TTY, 0);
    317 #endif
    318 
    319 	/* if there are no enable/disable functions, assume the device
    320 	   is always enabled */
    321 	if (!sc->enable)
    322 		sc->enabled = 1;
    323 
    324 	sacom_config(sc);
    325 
    326 	SET(sc->sc_hwflags, COM_HW_DEV_OK);
    327 }
    328 
    329 /* This is necessary when dynamically changing SAIP configuration. */
    330 int
    331 sacom_detach(self, flags)
    332 	struct device *self;
    333 	int flags;
    334 {
    335 	struct sacom_softc *sc = (struct sacom_softc *)self;
    336 	int maj, mn;
    337 
    338 	/* locate the major number */
    339 	for (maj = 0; maj < nchrdev; maj++)
    340 		if (cdevsw[maj].d_open == sacomopen)
    341 			break;
    342 
    343 	/* Nuke the vnodes for any open instances. */
    344 	mn = self->dv_unit;
    345 	vdevgone(maj, mn, mn, VCHR);
    346 
    347 	mn |= COMDIALOUT_MASK;
    348 	vdevgone(maj, mn, mn, VCHR);
    349 
    350 	/* Free the receive buffer. */
    351 	free(sc->sc_rbuf, M_DEVBUF);
    352 
    353 	/* Detach and free the tty. */
    354 	tty_detach(sc->sc_tty);
    355 	ttyfree(sc->sc_tty);
    356 
    357 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    358 	/* Unhook the soft interrupt handler. */
    359 	softintr_disestablish(sc->sc_si);
    360 #endif
    361 
    362 #if NRND > 0 && defined(RND_COM)
    363 	/* Unhook the entropy source. */
    364 	rnd_detach_source(&sc->rnd_source);
    365 #endif
    366 
    367 	return (0);
    368 }
    369 
    370 void
    371 sacom_config(sc)
    372 	struct sacom_softc *sc;
    373 {
    374 	bus_space_tag_t iot = sc->sc_iot;
    375 	bus_space_handle_t ioh = sc->sc_ioh;
    376 
    377 	/* Disable engine before configuring the device. */
    378 	sc->sc_cr3 = 0;
    379 	bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
    380 
    381 #ifdef DDB
    382 	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
    383 		sacom_enable_debugport(sc);
    384 #endif
    385 }
    386 
    387 #ifdef DDB
    388 static void
    389 sacom_enable_debugport(sc)
    390 	struct sacom_softc *sc;
    391 {
    392 	bus_space_tag_t iot = sc->sc_iot;
    393 	bus_space_handle_t ioh = sc->sc_ioh;
    394 	int s;
    395 
    396 	s = splserial();
    397 	COM_LOCK(sc);
    398 	sc->sc_cr3 = CR3_RXE | CR3_TXE;
    399 	bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
    400 	COM_UNLOCK(sc);
    401 	splx(s);
    402 }
    403 #endif
    404 
    405 int
    406 sacom_activate(self, act)
    407 	struct device *self;
    408 	enum devact act;
    409 {
    410 	struct sacom_softc *sc = (struct sacom_softc *)self;
    411 	int s, rv = 0;
    412 
    413 	s = splserial();
    414 	COM_LOCK(sc);
    415 	switch (act) {
    416 	case DVACT_ACTIVATE:
    417 		rv = EOPNOTSUPP;
    418 		break;
    419 
    420 	case DVACT_DEACTIVATE:
    421 		if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
    422 			rv = EBUSY;
    423 			break;
    424 		}
    425 
    426 		if (sc->disable != NULL && sc->enabled != 0) {
    427 			(*sc->disable)(sc);
    428 			sc->enabled = 0;
    429 		}
    430 		break;
    431 	}
    432 
    433 	COM_UNLOCK(sc);
    434 	splx(s);
    435 	return (rv);
    436 }
    437 
    438 void
    439 sacom_shutdown(sc)
    440 	struct sacom_softc *sc;
    441 {
    442 	struct tty *tp = sc->sc_tty;
    443 	int s;
    444 
    445 	s = splserial();
    446 	COM_LOCK(sc);
    447 
    448 	/* Clear any break condition set with TIOCSBRK. */
    449 	sacom_break(sc, 0);
    450 
    451 	/*
    452 	 * Hang up if necessary.  Wait a bit, so the other side has time to
    453 	 * notice even if we immediately open the port again.
    454 	 * Avoid tsleeping above splhigh().
    455 	 */
    456 	if (ISSET(tp->t_cflag, HUPCL)) {
    457 		sacom_modem(sc, 0);
    458 		COM_UNLOCK(sc);
    459 		splx(s);
    460 		/* XXX tsleep will only timeout */
    461 		(void) tsleep(sc, TTIPRI, ttclos, hz);
    462 		s = splserial();
    463 		COM_LOCK(sc);
    464 	}
    465 
    466 	/* Turn off interrupts. */
    467 	sc->sc_cr3 = 0;
    468 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACOM_CR3, sc->sc_cr3);
    469 
    470 	if (sc->disable) {
    471 #ifdef DIAGNOSTIC
    472 		if (!sc->enabled)
    473 			panic("sacom_shutdown: not enabled?");
    474 #endif
    475 		(*sc->disable)(sc);
    476 		sc->enabled = 0;
    477 	}
    478 	COM_UNLOCK(sc);
    479 	splx(s);
    480 }
    481 
    482 int
    483 sacomopen(devvp, flag, mode, p)
    484 	struct vnode *devvp;
    485 	int flag, mode;
    486 	struct proc *p;
    487 {
    488 	struct sacom_softc *sc;
    489 	struct tty *tp;
    490 	int s, s2;
    491 	int error;
    492 	dev_t dev;
    493 
    494 	dev = vdev_rdev(devvp);
    495 	sc = device_lookup(&sacom_cd, COMUNIT(dev));
    496 	if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
    497 		sc->sc_rbuf == NULL)
    498 		return (ENXIO);
    499 
    500 	if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
    501 		return (ENXIO);
    502 
    503 	vdev_setprivdata(devvp, sc);
    504 
    505 	tp = sc->sc_tty;
    506 
    507 	if (ISSET(tp->t_state, TS_ISOPEN) &&
    508 	    ISSET(tp->t_state, TS_XCLUDE) &&
    509 		p->p_ucred->cr_uid != 0)
    510 		return (EBUSY);
    511 
    512 	s = spltty();
    513 
    514 	/*
    515 	 * Do the following iff this is a first open.
    516 	 */
    517 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
    518 		struct termios t;
    519 
    520 		tp->t_dev = dev;
    521 
    522 		s2 = splserial();
    523 		COM_LOCK(sc);
    524 
    525 		if (sc->enable) {
    526 			if ((*sc->enable)(sc)) {
    527 				COM_UNLOCK(sc);
    528 				splx(s2);
    529 				splx(s);
    530 				printf("%s: device enable failed\n",
    531 				       sc->sc_dev.dv_xname);
    532 				return (EIO);
    533 			}
    534 			sc->enabled = 1;
    535 			sacom_config(sc);
    536 		}
    537 
    538 		/* Turn on interrupts. */
    539 		sc->sc_cr3 = CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE;
    540 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACOM_CR3,
    541 				  sc->sc_cr3);
    542 
    543 
    544 		COM_UNLOCK(sc);
    545 		splx(s2);
    546 
    547 		/*
    548 		 * Initialize the termios status to the defaults.  Add in the
    549 		 * sticky bits from TIOCSFLAGS.
    550 		 */
    551 		t.c_ispeed = 0;
    552 		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
    553 			t.c_ospeed = sacomconsrate;
    554 			t.c_cflag = sacomconscflag;
    555 		} else {
    556 			t.c_ospeed = TTYDEF_SPEED;
    557 			t.c_cflag = TTYDEF_CFLAG;
    558 		}
    559 		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
    560 			SET(t.c_cflag, CLOCAL);
    561 		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
    562 			SET(t.c_cflag, CRTSCTS);
    563 		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
    564 			SET(t.c_cflag, MDMBUF);
    565 		/* Make sure sacomparam() will do something. */
    566 		tp->t_ospeed = 0;
    567 		(void) sacomparam(tp, &t);
    568 		tp->t_iflag = TTYDEF_IFLAG;
    569 		tp->t_oflag = TTYDEF_OFLAG;
    570 		tp->t_lflag = TTYDEF_LFLAG;
    571 		ttychars(tp);
    572 		ttsetwater(tp);
    573 
    574 		s2 = splserial();
    575 		COM_LOCK(sc);
    576 
    577 		/*
    578 		 * Turn on DTR.  We must always do this, even if carrier is not
    579 		 * present, because otherwise we'd have to use TIOCSDTR
    580 		 * immediately after setting CLOCAL, which applications do not
    581 		 * expect.  We always assert DTR while the device is open
    582 		 * unless explicitly requested to deassert it.
    583 		 */
    584 		sacom_modem(sc, 1);
    585 
    586 		/* Clear the input ring, and unblock. */
    587 		sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
    588 		sc->sc_rbavail = SACOM_RING_SIZE;
    589 		sacom_iflush(sc);
    590 		CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
    591 		sacom_hwiflow(sc);
    592 
    593 #ifdef COM_DEBUG
    594 		if (sacom_debug)
    595 			comstatus(sc, "sacomopen  ");
    596 #endif
    597 
    598 		COM_UNLOCK(sc);
    599 		splx(s2);
    600 	}
    601 
    602 	splx(s);
    603 
    604 	error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
    605 	if (error)
    606 		goto bad;
    607 
    608 	error = (*tp->t_linesw->l_open)(devvp, tp);
    609 	if (error)
    610 		goto bad;
    611 
    612 	return (0);
    613 
    614 bad:
    615 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
    616 		/*
    617 		 * We failed to open the device, and nobody else had it opened.
    618 		 * Clean up the state as appropriate.
    619 		 */
    620 		sacom_shutdown(sc);
    621 	}
    622 
    623 	return (error);
    624 }
    625 
    626 int
    627 sacomclose(devvp, flag, mode, p)
    628 	struct vnode *devvp;
    629 	int flag, mode;
    630 	struct proc *p;
    631 {
    632 	struct sacom_softc *sc;
    633 	struct tty *tp;
    634 
    635 	sc = vdev_privdata(devvp);
    636 	tp = sc->sc_tty;
    637 
    638 	/* XXX This is for cons.c. */
    639 	if (!ISSET(tp->t_state, TS_ISOPEN))
    640 		return (0);
    641 
    642 	(*tp->t_linesw->l_close)(tp, flag);
    643 	ttyclose(tp);
    644 
    645 	if (COM_ISALIVE(sc) == 0)
    646 		return (0);
    647 
    648 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
    649 		/*
    650 		 * Although we got a last close, the device may still be in
    651 		 * use; e.g. if this was the dialout node, and there are still
    652 		 * processes waiting for carrier on the non-dialout node.
    653 		 */
    654 		sacom_shutdown(sc);
    655 	}
    656 
    657 	return (0);
    658 }
    659 
    660 int
    661 sacomread(devvp, uio, flag)
    662 	struct vnode *devvp;
    663 	struct uio *uio;
    664 	int flag;
    665 {
    666 	struct sacom_softc *sc;
    667 	struct tty *tp;
    668 
    669 	sc = vdev_privdata(devvp);
    670 	tp = sc->sc_tty;
    671 
    672 	if (COM_ISALIVE(sc) == 0)
    673 		return (EIO);
    674 
    675 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
    676 }
    677 
    678 int
    679 sacomwrite(devvp, uio, flag)
    680 	struct vnode *devvp;
    681 	struct uio *uio;
    682 	int flag;
    683 {
    684 	struct sacom_softc *sc;
    685 	struct tty *tp;
    686 
    687 	sc = vdev_privdata(devvp);
    688 	tp = sc->sc_tty;
    689 
    690 	if (COM_ISALIVE(sc) == 0)
    691 		return (EIO);
    692 
    693 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
    694 }
    695 
    696 int
    697 sacompoll(devvp, events, p)
    698 	struct vnode *devvp;
    699 	int events;
    700 	struct proc *p;
    701 {
    702 	struct sacom_softc *sc;
    703 	struct tty *tp;
    704 
    705 	sc = vdev_privdata(devvp);
    706 	tp = sc->sc_tty;
    707 
    708 	if (COM_ISALIVE(sc) == 0)
    709 		return (EIO);
    710 
    711 	return ((*tp->t_linesw->l_poll)(tp, events, p));
    712 }
    713 
    714 struct tty *
    715 sacomtty(devvp)
    716 	struct vnode *devvp;
    717 {
    718 	struct sacom_softc *sc;
    719 	struct tty *tp;
    720 
    721 	sc = vdev_privdata(devvp);
    722 
    723 	return sc->sc_tty;
    724 }
    725 
    726 int
    727 sacomioctl(devvp, cmd, data, flag, p)
    728 	struct vnode *devvp;
    729 	u_long cmd;
    730 	caddr_t data;
    731 	int flag;
    732 	struct proc *p;
    733 {
    734 	struct sacom_softc *sc;
    735 	struct tty *tp;
    736 	int error;
    737 	int s;
    738 
    739 	sc = vdev_privdata(devvp);
    740 	tp = sc->sc_tty;
    741 
    742 	if (COM_ISALIVE(sc) == 0)
    743 		return (EIO);
    744 
    745 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
    746 	if (error >= 0)
    747 		return (error);
    748 
    749 	error = ttioctl(tp, devvp, cmd, data, flag, p);
    750 	if (error >= 0)
    751 		return (error);
    752 
    753 	error = 0;
    754 
    755 	s = splserial();
    756 	COM_LOCK(sc);
    757 
    758 	switch (cmd) {
    759 	case TIOCSBRK:
    760 		sacom_break(sc, 1);
    761 		break;
    762 
    763 	case TIOCCBRK:
    764 		sacom_break(sc, 0);
    765 		break;
    766 
    767 	case TIOCSDTR:
    768 		sacom_modem(sc, 1);
    769 		break;
    770 
    771 	case TIOCCDTR:
    772 		sacom_modem(sc, 0);
    773 		break;
    774 
    775 	case TIOCGFLAGS:
    776 		*(int *)data = sc->sc_swflags;
    777 		break;
    778 
    779 	case TIOCSFLAGS:
    780 		error = suser(p->p_ucred, &p->p_acflag);
    781 		if (error)
    782 			break;
    783 		sc->sc_swflags = *(int *)data;
    784 		break;
    785 
    786 	case TIOCMSET:
    787 	case TIOCMBIS:
    788 	case TIOCMBIC:
    789 		tiocm_to_sacom(sc, cmd, *(int *)data);
    790 		break;
    791 
    792 	case TIOCMGET:
    793 		*(int *)data = sacom_to_tiocm(sc);
    794 		break;
    795 
    796 	default:
    797 		error = ENOTTY;
    798 		break;
    799 	}
    800 
    801 	COM_UNLOCK(sc);
    802 	splx(s);
    803 
    804 #ifdef COM_DEBUG
    805 	if (sacom_debug)
    806 		comstatus(sc, "comioctl ");
    807 #endif
    808 
    809 	return (error);
    810 }
    811 
    812 static inline void
    813 sacom_schedrx(sc)
    814 	struct sacom_softc *sc;
    815 {
    816 
    817 	sc->sc_rx_ready = 1;
    818 
    819 	/* Wake up the poller. */
    820 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    821 	softintr_schedule(sc->sc_si);
    822 #else
    823 	setsoftserial();
    824 #endif
    825 }
    826 
    827 void
    828 sacom_break(sc, onoff)
    829 	struct sacom_softc *sc;
    830 	int onoff;
    831 {
    832 
    833 	if (onoff)
    834 		SET(sc->sc_cr3, CR3_BRK);
    835 	else
    836 		CLR(sc->sc_cr3, CR3_BRK);
    837 
    838 	if (!sc->sc_heldchange) {
    839 		if (sc->sc_tx_busy) {
    840 			sc->sc_heldtbc = sc->sc_tbc;
    841 			sc->sc_tbc = 0;
    842 			sc->sc_heldchange = 1;
    843 		} else
    844 			sacom_loadchannelregs(sc);
    845 	}
    846 }
    847 
    848 void
    849 sacom_modem(sc, onoff)
    850 	struct sacom_softc *sc;
    851 	int onoff;
    852 {
    853 	if (!sc->sc_heldchange) {
    854 		if (sc->sc_tx_busy) {
    855 			sc->sc_heldtbc = sc->sc_tbc;
    856 			sc->sc_tbc = 0;
    857 			sc->sc_heldchange = 1;
    858 		} else
    859 			sacom_loadchannelregs(sc);
    860 	}
    861 }
    862 
    863 void
    864 tiocm_to_sacom(sc, how, ttybits)
    865 	struct sacom_softc *sc;
    866 	u_long how;
    867 	int ttybits;
    868 {
    869 }
    870 
    871 int
    872 sacom_to_tiocm(sc)
    873 	struct sacom_softc *sc;
    874 {
    875 	int ttybits = 0;
    876 
    877 	if (sc->sc_cr3 != 0)
    878 		SET(ttybits, TIOCM_LE);
    879 
    880 	return (ttybits);
    881 }
    882 
    883 static u_int
    884 cflag2cr0(cflag)
    885 	tcflag_t cflag;
    886 {
    887 	u_int cr0;
    888 
    889 	cr0  = (cflag & PARENB) ? CR0_PE : 0;
    890 	cr0 |= (cflag & PARODD) ? 0 : CR0_OES;
    891 	cr0 |= (cflag & CSTOPB) ? CR0_SBS : 0;
    892 	cr0 |= ((cflag & CSIZE) == CS8) ? CR0_DSS : 0;
    893 
    894 	return (cr0);
    895 }
    896 
    897 int
    898 sacomparam(tp, t)
    899 	struct tty *tp;
    900 	struct termios *t;
    901 {
    902 	struct sacom_softc *sc = device_lookup(&sacom_cd, COMUNIT(tp->t_dev));
    903 	int ospeed = SACOMSPEED(t->c_ospeed);
    904 	u_int cr0;
    905 	int s;
    906 
    907 	if (sc == NULL || COM_ISALIVE(sc) == 0)
    908 		return (EIO);
    909 
    910 	/* Check requested parameters. */
    911 	if (ospeed < 0)
    912 		return (EINVAL);
    913 	if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
    914 		return (EINVAL);
    915 
    916 	/*
    917 	 * For the console, always force CLOCAL and !HUPCL, so that the port
    918 	 * is always active.
    919 	 */
    920 	if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
    921 	    ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
    922 		SET(t->c_cflag, CLOCAL);
    923 		CLR(t->c_cflag, HUPCL);
    924 	}
    925 
    926 	/*
    927 	 * If there were no changes, don't do anything.  This avoids dropping
    928 	 * input and improves performance when all we did was frob things like
    929 	 * VMIN and VTIME.
    930 	 */
    931 	if (tp->t_ospeed == t->c_ospeed &&
    932 	    tp->t_cflag == t->c_cflag)
    933 		return (0);
    934 
    935 	cr0 = cflag2cr0(t->c_cflag);
    936 
    937 	s = splserial();
    938 	COM_LOCK(sc);
    939 
    940 	sc->sc_cr0 = cr0;
    941 
    942 	sc->sc_speed = ospeed;
    943 
    944 	/* And copy to tty. */
    945 	tp->t_ispeed = 0;
    946 	tp->t_ospeed = t->c_ospeed;
    947 	tp->t_cflag = t->c_cflag;
    948 
    949 	if (!sc->sc_heldchange) {
    950 		if (sc->sc_tx_busy) {
    951 			sc->sc_heldtbc = sc->sc_tbc;
    952 			sc->sc_tbc = 0;
    953 			sc->sc_heldchange = 1;
    954 		} else
    955 			sacom_loadchannelregs(sc);
    956 	}
    957 
    958 	if (!ISSET(t->c_cflag, CHWFLOW)) {
    959 		/* Disable the high water mark. */
    960 		if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
    961 			CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
    962 			sacom_schedrx(sc);
    963 		}
    964 		if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
    965 			CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
    966 			sacom_hwiflow(sc);
    967 		}
    968 	}
    969 
    970 	COM_UNLOCK(sc);
    971 	splx(s);
    972 
    973 	(void) (*tp->t_linesw->l_modem)(tp, 1);
    974 
    975 #ifdef COM_DEBUG
    976 	if (sacom_debug)
    977 		comstatus(sc, "comparam ");
    978 #endif
    979 
    980 	return (0);
    981 }
    982 
    983 void
    984 sacom_iflush(sc)
    985 	struct sacom_softc *sc;
    986 {
    987 	bus_space_tag_t iot = sc->sc_iot;
    988 	bus_space_handle_t ioh = sc->sc_ioh;
    989 #ifdef DIAGNOSTIC
    990 	int reg;
    991 #endif
    992 	int timo;
    993 
    994 #ifdef DIAGNOSTIC
    995 	reg = 0xffff;
    996 #endif
    997 	timo = 50;
    998 	/* flush any pending I/O */
    999 	if (sc->sc_cr3 & CR3_RXE) {
   1000 	while (ISSET(bus_space_read_4(iot, ioh, SACOM_SR1), SR1_RNE)
   1001 	    && --timo)
   1002 #ifdef DIAGNOSTIC
   1003 		reg =
   1004 #else
   1005 		    (void)
   1006 #endif
   1007 		    bus_space_read_4(iot, ioh, SACOM_DR);
   1008 	}
   1009 #if 0
   1010 	/* XXX is it good idea to wait TX finish? */
   1011 	if (sc->sc_cr3 & CR3_TXE) {
   1012 	timo = 500;
   1013 	while (ISSET(bus_space_read_4(iot, ioh, SACOM_SR1), SR1_TBY)
   1014 	    && --timo)
   1015 		delay(100);
   1016 	}
   1017 #endif
   1018 #ifdef DIAGNOSTIC
   1019 	if (!timo)
   1020 		printf("%s: sacom_iflush timeout %02x\n", sc->sc_dev.dv_xname,
   1021 		       reg);
   1022 #endif
   1023 }
   1024 
   1025 void
   1026 sacom_loadchannelregs(sc)
   1027 	struct sacom_softc *sc;
   1028 {
   1029 	bus_space_tag_t iot = sc->sc_iot;
   1030 	bus_space_handle_t ioh = sc->sc_ioh;
   1031 
   1032 	/* XXXXX necessary? */
   1033 	sacom_iflush(sc);
   1034 
   1035 	/* Need to stop engines first. */
   1036 	bus_space_write_4(iot, ioh, SACOM_CR3, 0);
   1037 
   1038 	bus_space_write_4(iot, ioh, SACOM_CR1, sc->sc_speed >> 8);
   1039 	bus_space_write_4(iot, ioh, SACOM_CR2, sc->sc_speed & 0xff);
   1040 
   1041 	bus_space_write_4(iot, ioh, SACOM_CR0, sc->sc_cr0);
   1042 	bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
   1043 }
   1044 
   1045 int
   1046 sacomhwiflow(tp, block)
   1047 	struct tty *tp;
   1048 	int block;
   1049 {
   1050 #if 0
   1051 	struct sacom_softc *sc = device_lookup(&sacom_cd, COMUNIT(tp->t_dev));
   1052 	int s;
   1053 
   1054 	if (sc == NULL || COM_ISALIVE(sc) == 0)
   1055 		return (0);
   1056 
   1057 	if (sc->sc_mcr_rts == 0)
   1058 		return (0);
   1059 
   1060 	s = splserial();
   1061 	COM_LOCK(sc);
   1062 
   1063 	if (block) {
   1064 		if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
   1065 			SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
   1066 			sacom_hwiflow(sc);
   1067 		}
   1068 	} else {
   1069 		if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
   1070 			CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
   1071 			sacom_schedrx(sc);
   1072 		}
   1073 		if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
   1074 			CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
   1075 			sacom_hwiflow(sc);
   1076 		}
   1077 	}
   1078 
   1079 	COM_UNLOCK(sc);
   1080 	splx(s);
   1081 #endif
   1082 	return (1);
   1083 }
   1084 
   1085 /*
   1086  * (un)block input via hw flowcontrol
   1087  */
   1088 void
   1089 sacom_hwiflow(sc)
   1090 	struct sacom_softc *sc;
   1091 {
   1092 #if 0
   1093 	bus_space_tag_t iot = sc->sc_iot;
   1094 	bus_space_handle_t ioh = sc->sc_ioh;
   1095 
   1096 	/* XXX implement */
   1097 #endif
   1098 }
   1099 
   1100 
   1101 void
   1102 sacomstart(tp)
   1103 	struct tty *tp;
   1104 {
   1105 	struct sacom_softc *sc = device_lookup(&sacom_cd, COMUNIT(tp->t_dev));
   1106 	bus_space_tag_t iot = sc->sc_iot;
   1107 	bus_space_handle_t ioh = sc->sc_ioh;
   1108 	int s;
   1109 
   1110 	if (sc == NULL || COM_ISALIVE(sc) == 0)
   1111 		return;
   1112 
   1113 	s = spltty();
   1114 	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
   1115 		goto out;
   1116 
   1117 	if (tp->t_outq.c_cc <= tp->t_lowat) {
   1118 		if (ISSET(tp->t_state, TS_ASLEEP)) {
   1119 			CLR(tp->t_state, TS_ASLEEP);
   1120 			wakeup(&tp->t_outq);
   1121 		}
   1122 		selwakeup(&tp->t_wsel);
   1123 		if (tp->t_outq.c_cc == 0)
   1124 			goto out;
   1125 	}
   1126 
   1127 	/* Grab the first contiguous region of buffer space. */
   1128 	{
   1129 		u_char *tba;
   1130 		int tbc;
   1131 
   1132 		tba = tp->t_outq.c_cf;
   1133 		tbc = ndqb(&tp->t_outq, 0);
   1134 
   1135 		(void)splserial();
   1136 		COM_LOCK(sc);
   1137 
   1138 		sc->sc_tba = tba;
   1139 		sc->sc_tbc = tbc;
   1140 	}
   1141 
   1142 	SET(tp->t_state, TS_BUSY);
   1143 	sc->sc_tx_busy = 1;
   1144 
   1145 	/* Enable transmit completion interrupts if necessary. */
   1146 	if (!ISSET(sc->sc_cr3, CR3_TIE)) {
   1147 		SET(sc->sc_cr3, CR3_TIE);
   1148 		bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
   1149 	}
   1150 
   1151 	/* Output the first chunk of the contiguous buffer. */
   1152 	sacom_filltx(sc);
   1153 
   1154 	COM_UNLOCK(sc);
   1155 out:
   1156 	splx(s);
   1157 	return;
   1158 }
   1159 
   1160 void
   1161 sacom_filltx(sc)
   1162 	struct sacom_softc *sc;
   1163 {
   1164 	bus_space_tag_t iot = sc->sc_iot;
   1165 	bus_space_handle_t ioh = sc->sc_ioh;
   1166 	int c, n;
   1167 
   1168 	n = 0;
   1169 	while(bus_space_read_4(sacomconstag, sacomconsioh, SACOM_SR1)
   1170 	      & SR1_TNF) {
   1171 		if (n == SACOM_TXFIFOLEN || n == sc->sc_tbc)
   1172 			break;
   1173 		c = *(sc->sc_tba + n);
   1174 		c &= 0xff;
   1175 		bus_space_write_4(iot, ioh, SACOM_DR, c);
   1176 		n++;
   1177 	}
   1178 	sc->sc_tbc -= n;
   1179 	sc->sc_tba += n;
   1180 }
   1181 
   1182 /*
   1183  * Stop output on a line.
   1184  */
   1185 void
   1186 sacomstop(tp, flag)
   1187 	struct tty *tp;
   1188 	int flag;
   1189 {
   1190 	struct sacom_softc *sc = device_lookup(&sacom_cd, COMUNIT(tp->t_dev));
   1191 	int s;
   1192 
   1193 	s = splserial();
   1194 	COM_LOCK(sc);
   1195 	if (ISSET(tp->t_state, TS_BUSY)) {
   1196 		/* Stop transmitting at the next chunk. */
   1197 		sc->sc_tbc = 0;
   1198 		sc->sc_heldtbc = 0;
   1199 		if (!ISSET(tp->t_state, TS_TTSTOP))
   1200 			SET(tp->t_state, TS_FLUSH);
   1201 	}
   1202 	COM_UNLOCK(sc);
   1203 	splx(s);
   1204 }
   1205 
   1206 static inline void
   1207 sacom_rxsoft(sc, tp)
   1208 	struct sacom_softc *sc;
   1209 	struct tty *tp;
   1210 {
   1211 	int (*rint)(int c, struct tty *tp) = tp->t_linesw->l_rint;
   1212 	u_char *get, *end;
   1213 	u_int cc, scc;
   1214 	u_char sr1;
   1215 	int code;
   1216 	int s;
   1217 
   1218 	end = sc->sc_ebuf;
   1219 	get = sc->sc_rbget;
   1220 	scc = cc = SACOM_RING_SIZE - sc->sc_rbavail;
   1221 
   1222 	while (cc) {
   1223 		code = get[0];
   1224 		sr1 = get[1];
   1225 		if (ISSET(sr1, SR1_FRE))
   1226 			SET(code, TTY_FE);
   1227 		if (ISSET(sr1, SR1_PRE))
   1228 			SET(code, TTY_PE);
   1229 		if ((*rint)(code, tp) == -1) {
   1230 			/*
   1231 			 * The line discipline's buffer is out of space.
   1232 			 */
   1233 			if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
   1234 				/*
   1235 				 * We're either not using flow control, or the
   1236 				 * line discipline didn't tell us to block for
   1237 				 * some reason.  Either way, we have no way to
   1238 				 * know when there's more space available, so
   1239 				 * just drop the rest of the data.
   1240 				 */
   1241 				get += cc << 1;
   1242 				if (get >= end)
   1243 					get -= SACOM_RING_SIZE << 1;
   1244 				cc = 0;
   1245 			} else {
   1246 				/*
   1247 				 * Don't schedule any more receive processing
   1248 				 * until the line discipline tells us there's
   1249 				 * space available (through comhwiflow()).
   1250 				 * Leave the rest of the data in the input
   1251 				 * buffer.
   1252 				 */
   1253 				SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
   1254 			}
   1255 			break;
   1256 		}
   1257 		get += 2;
   1258 		if (get >= end)
   1259 			get = sc->sc_rbuf;
   1260 		cc--;
   1261 	}
   1262 
   1263 	if (cc != scc) {
   1264 		sc->sc_rbget = get;
   1265 		s = splserial();
   1266 		COM_LOCK(sc);
   1267 
   1268 		cc = sc->sc_rbavail += scc - cc;
   1269 		/* Buffers should be ok again, release possible block. */
   1270 		if (cc >= 1) {
   1271 			if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
   1272 				CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
   1273 				SET(sc->sc_cr3, CR3_RIE);
   1274 				bus_space_write_4(sc->sc_iot, sc->sc_ioh,
   1275 						  SACOM_CR3, sc->sc_cr3);
   1276 			}
   1277 		}
   1278 		COM_UNLOCK(sc);
   1279 		splx(s);
   1280 	}
   1281 }
   1282 
   1283 static inline void
   1284 sacom_txsoft(sc, tp)
   1285 	struct sacom_softc *sc;
   1286 	struct tty *tp;
   1287 {
   1288 
   1289 	CLR(tp->t_state, TS_BUSY);
   1290 	if (ISSET(tp->t_state, TS_FLUSH))
   1291 		CLR(tp->t_state, TS_FLUSH);
   1292 	else
   1293 		ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
   1294 	(*tp->t_linesw->l_start)(tp);
   1295 }
   1296 
   1297 static inline void
   1298 sacom_stsoft(sc, tp)
   1299 	struct sacom_softc *sc;
   1300 	struct tty *tp;
   1301 {
   1302 }
   1303 
   1304 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
   1305 void
   1306 sacomsoft(arg)
   1307 	void *arg;
   1308 {
   1309 	struct sacom_softc *sc = arg;
   1310 	struct tty *tp;
   1311 
   1312 	if (COM_ISALIVE(sc) == 0)
   1313 		return;
   1314 
   1315 	{
   1316 #else
   1317 void
   1318 sacomsoft()
   1319 {
   1320 	struct sacom_softc	*sc;
   1321 	struct tty	*tp;
   1322 	int	unit;
   1323 
   1324 	for (unit = 0; unit < sacom_cd.cd_ndevs; unit++) {
   1325 		sc = device_lookup(&sacom_cd, unit);
   1326 		if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK))
   1327 			continue;
   1328 
   1329 		if (COM_ISALIVE(sc) == 0)
   1330 			continue;
   1331 
   1332 		tp = sc->sc_tty;
   1333 		if (tp == NULL)
   1334 			continue;
   1335 		if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0)
   1336 			continue;
   1337 #endif
   1338 		tp = sc->sc_tty;
   1339 
   1340 		if (sc->sc_rx_ready) {
   1341 			sc->sc_rx_ready = 0;
   1342 			sacom_rxsoft(sc, tp);
   1343 		}
   1344 
   1345 		if (sc->sc_st_check) {
   1346 			sc->sc_st_check = 0;
   1347 			sacom_stsoft(sc, tp);
   1348 		}
   1349 
   1350 		if (sc->sc_tx_done) {
   1351 			sc->sc_tx_done = 0;
   1352 			sacom_txsoft(sc, tp);
   1353 		}
   1354 	}
   1355 
   1356 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
   1357 #endif
   1358 }
   1359 
   1360 #ifdef __ALIGN_BRACKET_LEVEL_FOR_CTAGS
   1361 	/* there has got to be a better way to do comsoft() */
   1362 }}
   1363 #endif
   1364 
   1365 int
   1366 sacomintr(arg)
   1367 	void *arg;
   1368 {
   1369 	struct sacom_softc *sc = arg;
   1370 	bus_space_tag_t iot = sc->sc_iot;
   1371 	bus_space_handle_t ioh = sc->sc_ioh;
   1372 	u_char *put, *end;
   1373 	u_int cc;
   1374 	u_int sr0, sr1;
   1375 
   1376 	if (COM_ISALIVE(sc) == 0)
   1377 		return (0);
   1378 
   1379 	COM_LOCK(sc);
   1380 	sr0 = bus_space_read_4(iot, ioh, SACOM_SR0);
   1381 	if (! sr0) {
   1382 		COM_UNLOCK(sc);
   1383 		return (0);
   1384 	}
   1385 	if (ISSET(sr0, SR0_EIF))
   1386 		/* XXX silently discard error bits */
   1387 		bus_space_read_4(iot, ioh, SACOM_DR);
   1388 	if (ISSET(sr0, SR0_RBB))
   1389 		bus_space_write_4(iot, ioh, SACOM_SR0, SR0_RBB);
   1390 	if (ISSET(sr0, SR0_REB)) {
   1391 		bus_space_write_4(iot, ioh, SACOM_SR0, SR0_REB);
   1392 #if defined(DDB) || defined(KGDB)
   1393 #ifndef DDB_BREAK_CHAR
   1394 		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
   1395 			console_debugger();
   1396 		}
   1397 #endif
   1398 #endif /* DDB || KGDB */
   1399 	}
   1400 
   1401 
   1402 	end = sc->sc_ebuf;
   1403 	put = sc->sc_rbput;
   1404 	cc = sc->sc_rbavail;
   1405 
   1406 	sr1 = bus_space_read_4(iot, ioh, SACOM_SR1);
   1407 	if (ISSET(sr0, SR0_RFS | SR0_RID)) {
   1408 		if (! ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
   1409 			while (cc > 0) {
   1410 				if (!ISSET(sr1, SR1_RNE)) {
   1411 					bus_space_write_4(iot, ioh, SACOM_SR0,
   1412 							  SR0_RID);
   1413 					break;
   1414 				}
   1415 				put[0] = bus_space_read_4(iot, ioh, SACOM_DR);
   1416 				put[1] = sr1;
   1417 #if defined(DDB) && defined(DDB_BREAK_CHAR)
   1418 				if (put[0] == DDB_BREAK_CHAR &&
   1419 				    ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
   1420 					console_debugger();
   1421 
   1422 					sr1 = bus_space_read_4(iot, ioh, SACOM_SR1);
   1423 					continue;
   1424 				}
   1425 #endif
   1426 				put += 2;
   1427 				if (put >= end)
   1428 					put = sc->sc_rbuf;
   1429 				cc--;
   1430 
   1431 				sr1 = bus_space_read_4(iot, ioh, SACOM_SR1);
   1432 			}
   1433 
   1434 			/*
   1435 			 * Current string of incoming characters ended because
   1436 			 * no more data was available or we ran out of space.
   1437 			 * Schedule a receive event if any data was received.
   1438 			 * If we're out of space, turn off receive interrupts.
   1439 			 */
   1440 			sc->sc_rbput = put;
   1441 			sc->sc_rbavail = cc;
   1442 			if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
   1443 				sc->sc_rx_ready = 1;
   1444 
   1445 			/* XXX do RX hardware flow control */
   1446 
   1447 			/*
   1448 			 * If we're out of space, disable receive interrupts
   1449 			 * until the queue has drained a bit.
   1450 			 */
   1451 			if (!cc) {
   1452 				SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
   1453 				CLR(sc->sc_cr3, CR3_RIE);
   1454 				bus_space_write_4(iot, ioh, SACOM_CR3,
   1455 						  sc->sc_cr3);
   1456 			}
   1457 		} else {
   1458 #ifdef DIAGNOSTIC
   1459 			panic("sacomintr: we shouldn't reach here\n");
   1460 #endif
   1461 			CLR(sc->sc_cr3, CR3_RIE);
   1462 			bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
   1463 		}
   1464 	}
   1465 
   1466 	/*
   1467 	 * Done handling any receive interrupts. See if data can be
   1468 	 * transmitted as well. Schedule tx done event if no data left
   1469 	 * and tty was marked busy.
   1470 	 */
   1471 	sr0 = bus_space_read_4(iot, ioh, SACOM_SR0);
   1472 	if (ISSET(sr0, SR0_TFS)) {
   1473 		/*
   1474 		 * If we've delayed a parameter change, do it now, and restart
   1475 		 * output.
   1476 		 * XXX sacom_loadchanelregs() waits TX completion,
   1477 		 * XXX resulting in ~0.1s hang (300bps, 4 bytes) in worst case
   1478 		 */
   1479 		if (sc->sc_heldchange) {
   1480 			sacom_loadchannelregs(sc);
   1481 			sc->sc_heldchange = 0;
   1482 			sc->sc_tbc = sc->sc_heldtbc;
   1483 			sc->sc_heldtbc = 0;
   1484 		}
   1485 
   1486 		/* Output the next chunk of the contiguous buffer, if any. */
   1487 		if (sc->sc_tbc > 0) {
   1488 			sacom_filltx(sc);
   1489 		} else {
   1490 			/* Disable transmit completion interrupts if necessary. */
   1491 			if (ISSET(sc->sc_cr3, CR3_TIE)) {
   1492 				CLR(sc->sc_cr3, CR3_TIE);
   1493 				bus_space_write_4(iot, ioh, SACOM_CR3,
   1494 						  sc->sc_cr3);
   1495 			}
   1496 			if (sc->sc_tx_busy) {
   1497 				sc->sc_tx_busy = 0;
   1498 				sc->sc_tx_done = 1;
   1499 			}
   1500 		}
   1501 	}
   1502 	COM_UNLOCK(sc);
   1503 
   1504 	/* Wake up the poller. */
   1505 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
   1506 	softintr_schedule(sc->sc_si);
   1507 #else
   1508 	setsoftserial();
   1509 #endif
   1510 
   1511 #if NRND > 0 && defined(RND_COM)
   1512 	rnd_add_uint32(&sc->rnd_source, iir | lsr);
   1513 #endif
   1514 	return (1);
   1515 }
   1516 
   1517 /* Initialization for serial console */
   1518 int
   1519 sacominit(iot, iobase, baud, cflag, iohp)
   1520 	bus_space_tag_t iot;
   1521 	bus_addr_t iobase;
   1522 	int baud;
   1523 	tcflag_t cflag;
   1524 	bus_space_handle_t *iohp;
   1525 {
   1526 	int brd, cr0;
   1527 
   1528 	if (bus_space_map(iot, iobase, SACOM_NPORTS, 0, iohp))
   1529 		printf("register map failed\n");
   1530 
   1531 	/* wait for the Tx queue to drain and disable the UART */
   1532 	while(bus_space_read_4(iot, *iohp, SACOM_SR1) & SR1_TBY)
   1533 		;
   1534 	bus_space_write_4(iot, *iohp, SACOM_CR3, 0);
   1535 
   1536 	cr0  = cflag2cr0(cflag);
   1537 	bus_space_write_4(iot, *iohp, SACOM_CR0, cr0);
   1538 
   1539 	brd = SACOMSPEED(baud);
   1540 	sacomconsrate = baud;
   1541 	sacomconsaddr = iobase;
   1542 	sacomconscflag = cflag;
   1543 	/* XXX assumes little endian */
   1544 	bus_space_write_4(iot, *iohp, SACOM_CR1, brd >> 8);
   1545 	bus_space_write_4(iot, *iohp, SACOM_CR2, brd & 0xff);
   1546 
   1547 	/* enable the UART */
   1548 	bus_space_write_4(iot, *iohp, SACOM_CR3, CR3_RXE | CR3_TXE);
   1549 
   1550 	return (0);
   1551 }
   1552 
   1553 void
   1554 sacomcnprobe(cp)
   1555 	struct consdev *cp;
   1556 {
   1557 	cp->cn_pri = CN_REMOTE;
   1558 }
   1559 
   1560 void
   1561 sacomcninit(cp)
   1562 	struct consdev *cp;
   1563 {
   1564 	if (cp == NULL) {
   1565 		/* XXX cp == NULL means that MMU is disabled. */
   1566 		sacomconsioh = SACOM3_HW_BASE;
   1567 		sacomconstag = &sa11x0_bs_tag;
   1568 		cn_tab = &sacomcons;
   1569 		return;
   1570 	}
   1571 
   1572 	if (sacominit(&sa11x0_bs_tag, CONADDR, CONSPEED,
   1573 			  CONMODE, &sacomconsioh))
   1574 		panic("can't init serial console @%x", CONADDR);
   1575 	cn_tab = &sacomcons;
   1576 	sacomconstag = &sa11x0_bs_tag;
   1577 }
   1578 
   1579 int
   1580 sacomcngetc(dev)
   1581 	dev_t dev;
   1582 {
   1583 	int c, s;
   1584 
   1585 	s = spltty();	/* XXX do we need this? */
   1586 
   1587 	while(! (bus_space_read_4(sacomconstag, sacomconsioh, SACOM_SR1)
   1588 		 & SR1_RNE)) {
   1589 #if defined(DDB) || defined(KGDB)
   1590 #ifndef DDB_BREAK_CHAR
   1591 		u_int sr0;
   1592 		extern int db_active;
   1593 
   1594 		sr0 = bus_space_read_4(sacomconstag, sacomconsioh, SACOM_SR0);
   1595 		if (ISSET(sr0, SR0_RBB))
   1596 			bus_space_write_4(sacomconstag, sacomconsioh,
   1597 					  SACOM_SR0, SR0_RBB);
   1598 		if (ISSET(sr0, SR0_REB)) {
   1599 			bus_space_write_4(sacomconstag, sacomconsioh,
   1600 					  SACOM_SR0, SR0_REB);
   1601 			if (db_active == 0)
   1602 				console_debugger();
   1603 		}
   1604 #endif
   1605 #endif /* DDB || KGDB */
   1606 	}
   1607 
   1608 	c = bus_space_read_4(sacomconstag, sacomconsioh, SACOM_DR);
   1609 	c &= 0xff;
   1610 	splx(s);
   1611 
   1612 	return (c);
   1613 }
   1614 
   1615 void
   1616 sacomcnputc(dev, c)
   1617 	dev_t dev;
   1618 	int c;
   1619 {
   1620 	int s;
   1621 
   1622 	s = spltty();	/* XXX do we need this? */
   1623 
   1624 	while(! (bus_space_read_4(sacomconstag, sacomconsioh, SACOM_SR1)
   1625 		 & SR1_TNF))
   1626 		;
   1627 
   1628 	bus_space_write_4(sacomconstag, sacomconsioh, SACOM_DR, c);
   1629 	splx(s);
   1630 }
   1631 
   1632 void
   1633 sacomcnpollc(dev, on)
   1634 	dev_t dev;
   1635 	int on;
   1636 {
   1637 
   1638 }
   1639 
   1640 #ifdef DEBUG
   1641 int
   1642 sacomcncharpoll()
   1643 {
   1644 	int c;
   1645 
   1646 	if (! (bus_space_read_4(sacomconstag, sacomconsioh, SACOM_SR1)
   1647 		 & SR1_RNE))
   1648 		return -1;
   1649 
   1650 	c = bus_space_read_4(sacomconstag, sacomconsioh, SACOM_DR);
   1651 	c &= 0xff;
   1652 
   1653 	return (c);
   1654 }
   1655 
   1656 #endif
   1657 
   1658 /* helper function to identify the com ports used by
   1659  console or KGDB (and not yet autoconf attached) */
   1660 int
   1661 sacom_is_console(iot, iobase, ioh)
   1662 	bus_space_tag_t iot;
   1663 	bus_addr_t iobase;
   1664 	bus_space_handle_t *ioh;
   1665 {
   1666 	bus_space_handle_t help;
   1667 
   1668 	if (! sacomconsattached &&
   1669 	    iot == sacomconstag && iobase == sacomconsaddr)
   1670 		help = sacomconsioh;
   1671 	else
   1672 		return (0);
   1673 
   1674 	if (ioh)
   1675 		*ioh = help;
   1676 	return (1);
   1677 }
   1678