Home | History | Annotate | Line # | Download | only in dev
siotty.c revision 1.6.2.3
      1  1.6.2.3  bouyer /* $NetBSD: siotty.c,v 1.6.2.3 2000/11/22 16:00:31 bouyer Exp $ */
      2  1.6.2.2  bouyer 
      3  1.6.2.2  bouyer /*-
      4  1.6.2.2  bouyer  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  1.6.2.2  bouyer  * All rights reserved.
      6  1.6.2.2  bouyer  *
      7  1.6.2.2  bouyer  * This code is derived from software contributed to The NetBSD Foundation
      8  1.6.2.2  bouyer  * by Tohru Nishimura.
      9  1.6.2.2  bouyer  *
     10  1.6.2.2  bouyer  * Redistribution and use in source and binary forms, with or without
     11  1.6.2.2  bouyer  * modification, are permitted provided that the following conditions
     12  1.6.2.2  bouyer  * are met:
     13  1.6.2.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     14  1.6.2.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     15  1.6.2.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.6.2.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     17  1.6.2.2  bouyer  *    documentation and/or other materials provided with the distribution.
     18  1.6.2.2  bouyer  * 3. All advertising materials mentioning features or use of this software
     19  1.6.2.2  bouyer  *    must display the following acknowledgement:
     20  1.6.2.2  bouyer  *	This product includes software developed by the NetBSD
     21  1.6.2.2  bouyer  *	Foundation, Inc. and its contributors.
     22  1.6.2.2  bouyer  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.6.2.2  bouyer  *    contributors may be used to endorse or promote products derived
     24  1.6.2.2  bouyer  *    from this software without specific prior written permission.
     25  1.6.2.2  bouyer  *
     26  1.6.2.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.6.2.2  bouyer  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.6.2.2  bouyer  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.6.2.2  bouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.6.2.2  bouyer  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.6.2.2  bouyer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.6.2.2  bouyer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.6.2.2  bouyer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.6.2.2  bouyer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.6.2.2  bouyer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.6.2.2  bouyer  * POSSIBILITY OF SUCH DAMAGE.
     37  1.6.2.2  bouyer  */
     38  1.6.2.2  bouyer 
     39  1.6.2.2  bouyer #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     40  1.6.2.2  bouyer 
     41  1.6.2.3  bouyer __KERNEL_RCSID(0, "$NetBSD: siotty.c,v 1.6.2.3 2000/11/22 16:00:31 bouyer Exp $");
     42  1.6.2.2  bouyer 
     43  1.6.2.2  bouyer #include "opt_ddb.h"
     44  1.6.2.2  bouyer 
     45  1.6.2.2  bouyer #include <sys/param.h>
     46  1.6.2.2  bouyer #include <sys/systm.h>
     47  1.6.2.2  bouyer #include <sys/device.h>
     48  1.6.2.2  bouyer #include <sys/conf.h>
     49  1.6.2.2  bouyer #include <sys/ioctl.h>
     50  1.6.2.2  bouyer #include <sys/proc.h>
     51  1.6.2.2  bouyer #include <sys/user.h>
     52  1.6.2.2  bouyer #include <sys/tty.h>
     53  1.6.2.2  bouyer #include <sys/uio.h>
     54  1.6.2.2  bouyer #include <sys/callout.h>
     55  1.6.2.2  bouyer #include <sys/fcntl.h>
     56  1.6.2.2  bouyer #include <dev/cons.h>
     57  1.6.2.2  bouyer 
     58  1.6.2.2  bouyer #include <machine/cpu.h>
     59  1.6.2.2  bouyer 
     60  1.6.2.2  bouyer #include <luna68k/dev/sioreg.h>
     61  1.6.2.2  bouyer #include <luna68k/dev/siovar.h>
     62  1.6.2.2  bouyer 
     63  1.6.2.2  bouyer #define	TIOCM_BREAK 01000 /* non standard use */
     64  1.6.2.2  bouyer 
     65  1.6.2.2  bouyer static const u_int8_t ch0_regs[6] = {
     66  1.6.2.2  bouyer 	WR0_RSTINT,				/* reset E/S interrupt */
     67  1.6.2.2  bouyer 	WR1_RXALLS | WR1_TXENBL,	 	/* Rx per char, Tx */
     68  1.6.2.2  bouyer 	0,					/* */
     69  1.6.2.2  bouyer 	WR3_RX8BIT | WR3_RXENBL,		/* Rx */
     70  1.6.2.2  bouyer 	WR4_BAUD96 | WR4_STOP1,			/* Tx/Rx */
     71  1.6.2.2  bouyer 	WR5_TX8BIT | WR5_TXENBL | WR5_DTR | WR5_RTS, /* Tx */
     72  1.6.2.2  bouyer };
     73  1.6.2.2  bouyer 
     74  1.6.2.2  bouyer static struct speedtab siospeedtab[] = {
     75  1.6.2.2  bouyer 	{ 2400,	WR4_BAUD24, },
     76  1.6.2.2  bouyer 	{ 4800,	WR4_BAUD48, },
     77  1.6.2.2  bouyer 	{ 9600,	WR4_BAUD96, },
     78  1.6.2.2  bouyer 	{ -1,	0, },
     79  1.6.2.2  bouyer };
     80  1.6.2.2  bouyer 
     81  1.6.2.2  bouyer struct siotty_softc {
     82  1.6.2.2  bouyer 	struct device	sc_dev;
     83  1.6.2.2  bouyer 	struct tty	*sc_tty;
     84  1.6.2.2  bouyer 	struct sioreg	*sc_ctl;
     85  1.6.2.2  bouyer 	u_int 		sc_flags;
     86  1.6.2.2  bouyer 	u_int8_t	sc_wr[6];
     87  1.6.2.2  bouyer };
     88  1.6.2.2  bouyer 
     89  1.6.2.2  bouyer #include "siotty.h"
     90  1.6.2.2  bouyer cdev_decl(sio);
     91  1.6.2.2  bouyer static void siostart __P((struct tty *));
     92  1.6.2.2  bouyer static int  sioparam __P((struct tty *, struct termios *));
     93  1.6.2.2  bouyer static void siottyintr __P((int));
     94  1.6.2.2  bouyer static int  siomctl __P((struct siotty_softc *, int, int));
     95  1.6.2.2  bouyer 
     96  1.6.2.2  bouyer static int  siotty_match __P((struct device *, struct cfdata *, void *));
     97  1.6.2.2  bouyer static void siotty_attach __P((struct device *, struct device *, void *));
     98  1.6.2.2  bouyer 
     99  1.6.2.2  bouyer const struct cfattach siotty_ca = {
    100  1.6.2.2  bouyer 	sizeof(struct siotty_softc), siotty_match, siotty_attach
    101  1.6.2.2  bouyer };
    102  1.6.2.2  bouyer extern struct cfdriver siotty_cd;
    103  1.6.2.2  bouyer 
    104  1.6.2.2  bouyer static int
    105  1.6.2.2  bouyer siotty_match(parent, cf, aux)
    106  1.6.2.2  bouyer 	struct device *parent;
    107  1.6.2.2  bouyer 	struct cfdata *cf;
    108  1.6.2.2  bouyer 	void   *aux;
    109  1.6.2.2  bouyer {
    110  1.6.2.2  bouyer 	struct sio_attach_args *args = aux;
    111  1.6.2.2  bouyer 
    112  1.6.2.2  bouyer 	if (args->channel != 0) /* XXX allow tty on Ch.B XXX */
    113  1.6.2.2  bouyer 		return 0;
    114  1.6.2.2  bouyer 	return 1;
    115  1.6.2.2  bouyer }
    116  1.6.2.2  bouyer 
    117  1.6.2.2  bouyer static void
    118  1.6.2.2  bouyer siotty_attach(parent, self, aux)
    119  1.6.2.2  bouyer 	struct device *parent, *self;
    120  1.6.2.2  bouyer 	void *aux;
    121  1.6.2.2  bouyer {
    122  1.6.2.2  bouyer 	struct sio_softc *scp = (void *)parent;
    123  1.6.2.2  bouyer 	struct siotty_softc *sc = (void *)self;
    124  1.6.2.2  bouyer 	struct sio_attach_args *args = aux;
    125  1.6.2.2  bouyer 
    126  1.6.2.2  bouyer 	sc->sc_ctl = (struct sioreg *)scp->scp_ctl + args->channel;
    127  1.6.2.2  bouyer 	bcopy(ch0_regs, sc->sc_wr, sizeof(ch0_regs));
    128  1.6.2.2  bouyer 	scp->scp_intr[args->channel] = siottyintr;
    129  1.6.2.2  bouyer 
    130  1.6.2.2  bouyer 	if (args->hwflags == 1) {
    131  1.6.2.2  bouyer 		printf(" (console)");
    132  1.6.2.2  bouyer 		sc->sc_flags = TIOCFLAG_SOFTCAR;
    133  1.6.2.2  bouyer 	}
    134  1.6.2.2  bouyer 	else {
    135  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR0, WR0_CHANRST);
    136  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR2A, WR2_VEC86 | WR2_INTR_1);
    137  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR2B, 0);
    138  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
    139  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
    140  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
    141  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
    142  1.6.2.2  bouyer 		setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
    143  1.6.2.2  bouyer 	}
    144  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); /* now interrupt driven */
    145  1.6.2.2  bouyer 
    146  1.6.2.2  bouyer 	printf("\n");
    147  1.6.2.2  bouyer }
    148  1.6.2.2  bouyer 
    149  1.6.2.2  bouyer /*--------------------  low level routine --------------------*/
    150  1.6.2.2  bouyer 
    151  1.6.2.2  bouyer static void
    152  1.6.2.2  bouyer siottyintr(chan)
    153  1.6.2.2  bouyer 	int chan;
    154  1.6.2.2  bouyer {
    155  1.6.2.2  bouyer 	struct siotty_softc *sc;
    156  1.6.2.2  bouyer 	struct sioreg *sio;
    157  1.6.2.2  bouyer 	struct tty *tp;
    158  1.6.2.2  bouyer 	unsigned int code;
    159  1.6.2.2  bouyer 	int rr;
    160  1.6.2.2  bouyer 
    161  1.6.2.2  bouyer 	if (chan >= siotty_cd.cd_ndevs)
    162  1.6.2.2  bouyer 		return;
    163  1.6.2.2  bouyer 	sc = siotty_cd.cd_devs[chan];
    164  1.6.2.2  bouyer 	tp = sc->sc_tty;
    165  1.6.2.2  bouyer 	sio = sc->sc_ctl;
    166  1.6.2.2  bouyer 	rr = getsiocsr(sio);
    167  1.6.2.2  bouyer 	if (rr & RR_RXRDY) {
    168  1.6.2.2  bouyer 		do {
    169  1.6.2.2  bouyer 			code = sio->sio_data;
    170  1.6.2.2  bouyer 			if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
    171  1.6.2.2  bouyer 				sio->sio_cmd = WR0_ERRRST;
    172  1.6.2.2  bouyer 				if (sio->sio_stat & RR_FRAMING)
    173  1.6.2.2  bouyer 					code |= TTY_FE;
    174  1.6.2.2  bouyer 				else if (sio->sio_stat & RR_PARITY)
    175  1.6.2.2  bouyer 					code |= TTY_PE;
    176  1.6.2.2  bouyer 			}
    177  1.6.2.2  bouyer 			if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
    178  1.6.2.2  bouyer 				continue;
    179  1.6.2.2  bouyer #if 0 && defined(DDB) /* ?!?! fails to resume ?!?! */
    180  1.6.2.2  bouyer 			if ((rr & RR_BREAK) && tp->t_dev == cn_tab->cn_dev) {
    181  1.6.2.2  bouyer 				cpu_Debugger();
    182  1.6.2.2  bouyer 				return;
    183  1.6.2.2  bouyer 			}
    184  1.6.2.2  bouyer #endif
    185  1.6.2.3  bouyer 			(*tp->t_linesw->l_rint)(code, tp);
    186  1.6.2.2  bouyer 		} while ((rr = getsiocsr(sio)) & RR_RXRDY);
    187  1.6.2.2  bouyer 	}
    188  1.6.2.2  bouyer 	if (rr & RR_TXRDY) {
    189  1.6.2.2  bouyer 		sio->sio_cmd = WR0_RSTPEND;
    190  1.6.2.2  bouyer 		if (tp != NULL) {
    191  1.6.2.2  bouyer 			tp->t_state &= ~(TS_BUSY|TS_FLUSH);
    192  1.6.2.3  bouyer 			if (tp->t_linesw)
    193  1.6.2.3  bouyer 				(*tp->t_linesw->l_start)(tp);
    194  1.6.2.2  bouyer 			else
    195  1.6.2.2  bouyer 				siostart(tp);
    196  1.6.2.2  bouyer 		}
    197  1.6.2.2  bouyer 	}
    198  1.6.2.2  bouyer }
    199  1.6.2.2  bouyer 
    200  1.6.2.2  bouyer static void
    201  1.6.2.2  bouyer siostart(tp)
    202  1.6.2.2  bouyer 	struct tty *tp;
    203  1.6.2.2  bouyer {
    204  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
    205  1.6.2.2  bouyer 	int s, c;
    206  1.6.2.2  bouyer 
    207  1.6.2.2  bouyer 	s = spltty();
    208  1.6.2.2  bouyer 	if (tp->t_state & (TS_BUSY|TS_TIMEOUT|TS_TTSTOP))
    209  1.6.2.2  bouyer 		goto out;
    210  1.6.2.2  bouyer 	if (tp->t_outq.c_cc <= tp->t_lowat) {
    211  1.6.2.2  bouyer 		if (tp->t_state & TS_ASLEEP) {
    212  1.6.2.2  bouyer 			tp->t_state &= ~TS_ASLEEP;
    213  1.6.2.2  bouyer 			wakeup((caddr_t)&tp->t_outq);
    214  1.6.2.2  bouyer 		}
    215  1.6.2.2  bouyer 		selwakeup(&tp->t_wsel);
    216  1.6.2.2  bouyer 	}
    217  1.6.2.2  bouyer 	if (tp->t_outq.c_cc == 0)
    218  1.6.2.2  bouyer 		goto out;
    219  1.6.2.2  bouyer 
    220  1.6.2.2  bouyer 	tp->t_state |= TS_BUSY;
    221  1.6.2.2  bouyer 	while (getsiocsr(sc->sc_ctl) & RR_TXRDY) {
    222  1.6.2.2  bouyer 		if ((c = getc(&tp->t_outq)) == -1)
    223  1.6.2.2  bouyer 			break;
    224  1.6.2.2  bouyer 		sc->sc_ctl->sio_data = c;
    225  1.6.2.2  bouyer 	}
    226  1.6.2.2  bouyer out:
    227  1.6.2.2  bouyer 	splx(s);
    228  1.6.2.2  bouyer }
    229  1.6.2.2  bouyer 
    230  1.6.2.2  bouyer void
    231  1.6.2.2  bouyer siostop(tp, flag)
    232  1.6.2.2  bouyer 	struct tty *tp;
    233  1.6.2.2  bouyer 	int flag;
    234  1.6.2.2  bouyer {
    235  1.6.2.2  bouyer 	int s;
    236  1.6.2.2  bouyer 
    237  1.6.2.2  bouyer         s = spltty();
    238  1.6.2.2  bouyer         if (TS_BUSY == (tp->t_state & (TS_BUSY|TS_TTSTOP))) {
    239  1.6.2.2  bouyer                 /*
    240  1.6.2.2  bouyer                  * Device is transmitting; must stop it.
    241  1.6.2.2  bouyer                  */
    242  1.6.2.2  bouyer 		tp->t_state |= TS_FLUSH;
    243  1.6.2.2  bouyer         }
    244  1.6.2.2  bouyer         splx(s);
    245  1.6.2.2  bouyer }
    246  1.6.2.2  bouyer 
    247  1.6.2.2  bouyer static int
    248  1.6.2.2  bouyer sioparam(tp, t)
    249  1.6.2.2  bouyer 	struct tty *tp;
    250  1.6.2.2  bouyer 	struct termios *t;
    251  1.6.2.2  bouyer {
    252  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
    253  1.6.2.2  bouyer 	int wr4, s;
    254  1.6.2.2  bouyer 
    255  1.6.2.2  bouyer 	if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
    256  1.6.2.2  bouyer 		return EINVAL;
    257  1.6.2.2  bouyer 	wr4 = ttspeedtab(t->c_ospeed, siospeedtab);
    258  1.6.2.2  bouyer 	if (wr4 < 0)
    259  1.6.2.2  bouyer 		return EINVAL;
    260  1.6.2.2  bouyer 
    261  1.6.2.2  bouyer 	if (sc->sc_flags & TIOCFLAG_SOFTCAR) {
    262  1.6.2.2  bouyer 		t->c_cflag |= CLOCAL;
    263  1.6.2.2  bouyer 		t->c_cflag &= ~HUPCL;
    264  1.6.2.2  bouyer 	}
    265  1.6.2.2  bouyer 	if (sc->sc_flags & TIOCFLAG_CLOCAL)
    266  1.6.2.2  bouyer 		t->c_cflag |= CLOCAL;
    267  1.6.2.2  bouyer 
    268  1.6.2.2  bouyer 	/*
    269  1.6.2.2  bouyer 	 * If there were no changes, don't do anything.  This avoids dropping
    270  1.6.2.2  bouyer 	 * input and improves performance when all we did was frob things like
    271  1.6.2.2  bouyer 	 * VMIN and VTIME.
    272  1.6.2.2  bouyer 	 */
    273  1.6.2.2  bouyer 	if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag)
    274  1.6.2.2  bouyer 		return 0;
    275  1.6.2.2  bouyer 
    276  1.6.2.2  bouyer 	tp->t_ispeed = t->c_ispeed;
    277  1.6.2.2  bouyer 	tp->t_ospeed = t->c_ospeed;
    278  1.6.2.2  bouyer 	tp->t_cflag = t->c_cflag;
    279  1.6.2.2  bouyer 
    280  1.6.2.2  bouyer 	sc->sc_wr[WR3] &= 0x3f;
    281  1.6.2.2  bouyer 	sc->sc_wr[WR5] &= 0x9f;
    282  1.6.2.2  bouyer 	switch (tp->t_cflag & CSIZE) {
    283  1.6.2.2  bouyer 	case CS7:
    284  1.6.2.2  bouyer 		sc->sc_wr[WR3] |= WR3_RX7BIT; sc->sc_wr[WR5] |= WR5_TX7BIT;
    285  1.6.2.2  bouyer 		break;
    286  1.6.2.2  bouyer 	case CS8:
    287  1.6.2.2  bouyer 		sc->sc_wr[WR3] |= WR3_RX8BIT; sc->sc_wr[WR5] |= WR5_TX8BIT;
    288  1.6.2.2  bouyer 		break;
    289  1.6.2.2  bouyer 	}
    290  1.6.2.2  bouyer 	if (tp->t_cflag & PARENB) {
    291  1.6.2.2  bouyer 		wr4 |= WR4_PARENAB;
    292  1.6.2.2  bouyer 		if ((tp->t_cflag & PARODD) == 0)
    293  1.6.2.2  bouyer 			wr4 |= WR4_EPARITY;
    294  1.6.2.2  bouyer 	}
    295  1.6.2.2  bouyer 	wr4 |= (tp->t_cflag & CSTOPB) ? WR4_STOP2 : WR4_STOP1;
    296  1.6.2.2  bouyer 	sc->sc_wr[WR4] = wr4;
    297  1.6.2.2  bouyer 
    298  1.6.2.2  bouyer 	s = spltty();
    299  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
    300  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
    301  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
    302  1.6.2.2  bouyer 	splx(s);
    303  1.6.2.2  bouyer 
    304  1.6.2.2  bouyer 	return 0;
    305  1.6.2.2  bouyer }
    306  1.6.2.2  bouyer 
    307  1.6.2.2  bouyer static int
    308  1.6.2.2  bouyer siomctl(sc, control, op)
    309  1.6.2.2  bouyer 	struct siotty_softc *sc;
    310  1.6.2.2  bouyer 	int control, op;
    311  1.6.2.2  bouyer {
    312  1.6.2.2  bouyer 	int val, s, wr5, rr;
    313  1.6.2.2  bouyer 
    314  1.6.2.2  bouyer 	val = 0;
    315  1.6.2.2  bouyer 	if (control & TIOCM_BREAK)
    316  1.6.2.2  bouyer 		val |= WR5_BREAK;
    317  1.6.2.2  bouyer 	if (control & TIOCM_DTR)
    318  1.6.2.2  bouyer 		val |= WR5_DTR;
    319  1.6.2.2  bouyer 	if (control & TIOCM_RTS)
    320  1.6.2.2  bouyer 		val |= WR5_RTS;
    321  1.6.2.2  bouyer 	s = spltty();
    322  1.6.2.2  bouyer 	wr5 = sc->sc_wr[WR5];
    323  1.6.2.2  bouyer 	switch (op) {
    324  1.6.2.2  bouyer 	case DMSET:
    325  1.6.2.2  bouyer 		wr5 &= ~(WR5_BREAK|WR5_DTR|WR5_RTS);
    326  1.6.2.2  bouyer 		/* FALLTHRU */
    327  1.6.2.2  bouyer 	case DMBIS:
    328  1.6.2.2  bouyer 		wr5 |= val;
    329  1.6.2.2  bouyer 		break;
    330  1.6.2.2  bouyer 	case DMBIC:
    331  1.6.2.2  bouyer 		wr5 &= ~val;
    332  1.6.2.2  bouyer 		break;
    333  1.6.2.2  bouyer 	case DMGET:
    334  1.6.2.2  bouyer 		val = 0;
    335  1.6.2.2  bouyer 		rr = getsiocsr(sc->sc_ctl);
    336  1.6.2.2  bouyer 		if (wr5 & WR5_DTR)
    337  1.6.2.2  bouyer 			val |= TIOCM_DTR;
    338  1.6.2.2  bouyer 		if (wr5 & WR5_RTS)
    339  1.6.2.2  bouyer 			val |= TIOCM_RTS;
    340  1.6.2.2  bouyer 		if (rr & RR_CTS)
    341  1.6.2.2  bouyer 			val |= TIOCM_CTS;
    342  1.6.2.2  bouyer 		if (rr & RR_DCD)
    343  1.6.2.2  bouyer 			val |= TIOCM_CD;
    344  1.6.2.2  bouyer 		goto done;
    345  1.6.2.2  bouyer 	}
    346  1.6.2.2  bouyer 	sc->sc_wr[WR5] = wr5;
    347  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR5, wr5);
    348  1.6.2.2  bouyer 	val = 0;
    349  1.6.2.2  bouyer   done:
    350  1.6.2.2  bouyer 	splx(s);
    351  1.6.2.2  bouyer 	return val;
    352  1.6.2.2  bouyer }
    353  1.6.2.2  bouyer 
    354  1.6.2.2  bouyer /*--------------------  cdevsw[] interface --------------------*/
    355  1.6.2.2  bouyer 
    356  1.6.2.2  bouyer int
    357  1.6.2.2  bouyer sioopen(dev, flag, mode, p)
    358  1.6.2.2  bouyer 	dev_t dev;
    359  1.6.2.2  bouyer 	int flag, mode;
    360  1.6.2.2  bouyer 	struct proc *p;
    361  1.6.2.2  bouyer {
    362  1.6.2.2  bouyer 	struct siotty_softc *sc;
    363  1.6.2.2  bouyer 	struct tty *tp;
    364  1.6.2.2  bouyer 	int error;
    365  1.6.2.2  bouyer 
    366  1.6.2.2  bouyer 	if ((sc = siotty_cd.cd_devs[minor(dev)]) == NULL)
    367  1.6.2.2  bouyer 		return ENXIO;
    368  1.6.2.2  bouyer 	if ((tp = sc->sc_tty) == NULL) {
    369  1.6.2.2  bouyer 		tp = sc->sc_tty = ttymalloc();
    370  1.6.2.2  bouyer 		tty_attach(tp);
    371  1.6.2.2  bouyer 	}
    372  1.6.2.2  bouyer 	else if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE)
    373  1.6.2.2  bouyer 	    && p->p_ucred->cr_uid != 0)
    374  1.6.2.2  bouyer 		return EBUSY;
    375  1.6.2.2  bouyer 
    376  1.6.2.2  bouyer 	tp->t_oproc = siostart;
    377  1.6.2.2  bouyer 	tp->t_param = sioparam;
    378  1.6.2.2  bouyer 	tp->t_hwiflow = NULL /* XXX siohwiflow XXX */;
    379  1.6.2.2  bouyer 	tp->t_dev = dev;
    380  1.6.2.2  bouyer 	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
    381  1.6.2.2  bouyer 		struct termios t;
    382  1.6.2.2  bouyer 
    383  1.6.2.2  bouyer 		t.c_ispeed = t.c_ospeed = TTYDEF_SPEED;
    384  1.6.2.2  bouyer 		t.c_cflag = TTYDEF_CFLAG;
    385  1.6.2.2  bouyer 		tp->t_ospeed = 0; /* force register update */
    386  1.6.2.2  bouyer 		(void)sioparam(tp, &t);
    387  1.6.2.2  bouyer 		tp->t_iflag = TTYDEF_IFLAG;
    388  1.6.2.2  bouyer 		tp->t_oflag = TTYDEF_OFLAG;
    389  1.6.2.2  bouyer 		tp->t_lflag = TTYDEF_LFLAG;
    390  1.6.2.2  bouyer 		ttychars(tp);
    391  1.6.2.2  bouyer 		ttsetwater(tp);
    392  1.6.2.2  bouyer 		/* raise RTS and DTR here; but, DTR lead is not wired */
    393  1.6.2.2  bouyer 		/* then check DCD condition; but, DCD lead is not wired */
    394  1.6.2.2  bouyer 		tp->t_state |= TS_CARR_ON; /* assume detected all the time */
    395  1.6.2.2  bouyer #if 0
    396  1.6.2.2  bouyer 		if ((sc->sc_flags & TIOCFLAG_SOFTCAR)
    397  1.6.2.2  bouyer 		    || (tp->t_cflag & MDMBUF)
    398  1.6.2.2  bouyer 		    || (getsiocsr(sc->sc_ctl) & RR_DCD))
    399  1.6.2.2  bouyer 			tp->t_state |= TS_CARR_ON;
    400  1.6.2.2  bouyer 		else
    401  1.6.2.2  bouyer 			tp->t_state &= ~TS_CARR_ON;
    402  1.6.2.2  bouyer #endif
    403  1.6.2.2  bouyer 	}
    404  1.6.2.2  bouyer 
    405  1.6.2.2  bouyer 	error = ttyopen(tp, 0, (flag & O_NONBLOCK));
    406  1.6.2.2  bouyer 	if (error > 0)
    407  1.6.2.2  bouyer 		return error;
    408  1.6.2.3  bouyer 	return (*tp->t_linesw->l_open)(dev, tp);
    409  1.6.2.2  bouyer }
    410  1.6.2.2  bouyer 
    411  1.6.2.2  bouyer int
    412  1.6.2.2  bouyer sioclose(dev, flag, mode, p)
    413  1.6.2.2  bouyer 	dev_t dev;
    414  1.6.2.2  bouyer 	int flag, mode;
    415  1.6.2.2  bouyer 	struct proc *p;
    416  1.6.2.2  bouyer {
    417  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    418  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    419  1.6.2.2  bouyer 	int s;
    420  1.6.2.2  bouyer 
    421  1.6.2.3  bouyer 	(*tp->t_linesw->l_close)(tp, flag);
    422  1.6.2.2  bouyer 
    423  1.6.2.2  bouyer 	s = spltty();
    424  1.6.2.2  bouyer 	siomctl(sc, TIOCM_BREAK, DMBIC);
    425  1.6.2.2  bouyer #if 0 /* because unable to feed DTR signal */
    426  1.6.2.2  bouyer 	if ((tp->t_cflag & HUPCL)
    427  1.6.2.2  bouyer 	    || tp->t_wopen || (tp->t_state & TS_ISOPEN) == 0) {
    428  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR, DMBIC);
    429  1.6.2.2  bouyer 		/* Yield CPU time to others for 1 second, then ... */
    430  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR, DMBIS);
    431  1.6.2.2  bouyer 	}
    432  1.6.2.2  bouyer #endif
    433  1.6.2.2  bouyer 	splx(s);
    434  1.6.2.2  bouyer 	return ttyclose(tp);
    435  1.6.2.2  bouyer }
    436  1.6.2.2  bouyer 
    437  1.6.2.2  bouyer int
    438  1.6.2.2  bouyer sioread(dev, uio, flag)
    439  1.6.2.2  bouyer 	dev_t dev;
    440  1.6.2.2  bouyer 	struct uio *uio;
    441  1.6.2.2  bouyer 	int flag;
    442  1.6.2.2  bouyer {
    443  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    444  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    445  1.6.2.2  bouyer 
    446  1.6.2.3  bouyer 	return (*tp->t_linesw->l_read)(tp, uio, flag);
    447  1.6.2.2  bouyer }
    448  1.6.2.2  bouyer 
    449  1.6.2.2  bouyer int
    450  1.6.2.2  bouyer siowrite(dev, uio, flag)
    451  1.6.2.2  bouyer 	dev_t dev;
    452  1.6.2.2  bouyer 	struct uio *uio;
    453  1.6.2.2  bouyer 	int flag;
    454  1.6.2.2  bouyer {
    455  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    456  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    457  1.6.2.2  bouyer 
    458  1.6.2.3  bouyer 	return (*tp->t_linesw->l_write)(tp, uio, flag);
    459  1.6.2.2  bouyer }
    460  1.6.2.2  bouyer 
    461  1.6.2.2  bouyer int
    462  1.6.2.2  bouyer sioioctl(dev, cmd, data, flag, p)
    463  1.6.2.2  bouyer 	dev_t dev;
    464  1.6.2.2  bouyer 	u_long cmd;
    465  1.6.2.2  bouyer 	caddr_t data;
    466  1.6.2.2  bouyer 	int flag;
    467  1.6.2.2  bouyer 	struct proc *p;
    468  1.6.2.2  bouyer {
    469  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    470  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    471  1.6.2.2  bouyer 	int error;
    472  1.6.2.2  bouyer 
    473  1.6.2.3  bouyer 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
    474  1.6.2.2  bouyer 	if (error >= 0)
    475  1.6.2.2  bouyer 		return error;
    476  1.6.2.2  bouyer 	error = ttioctl(tp, cmd, data, flag, p);
    477  1.6.2.2  bouyer 	if (error >= 0)
    478  1.6.2.2  bouyer 		return error;
    479  1.6.2.2  bouyer 
    480  1.6.2.2  bouyer 	/* the last resort for TIOC ioctl tranversing */
    481  1.6.2.2  bouyer 	switch (cmd) {
    482  1.6.2.2  bouyer 	case TIOCSBRK: /* Set the hardware into BREAK condition */
    483  1.6.2.2  bouyer 		siomctl(sc, TIOCM_BREAK, DMBIS);
    484  1.6.2.2  bouyer 		break;
    485  1.6.2.2  bouyer 	case TIOCCBRK: /* Clear the hardware BREAK condition */
    486  1.6.2.2  bouyer 		siomctl(sc, TIOCM_BREAK, DMBIC);
    487  1.6.2.2  bouyer 		break;
    488  1.6.2.2  bouyer 	case TIOCSDTR: /* Assert DTR signal */
    489  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIS);
    490  1.6.2.2  bouyer 		break;
    491  1.6.2.2  bouyer 	case TIOCCDTR: /* Clear DTR signal */
    492  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIC);
    493  1.6.2.2  bouyer 		break;
    494  1.6.2.2  bouyer 	case TIOCMSET: /* Set modem state replacing current one */
    495  1.6.2.2  bouyer 		siomctl(sc, *(int *)data, DMSET);
    496  1.6.2.2  bouyer 		break;
    497  1.6.2.2  bouyer 	case TIOCMGET: /* Return current modem state */
    498  1.6.2.2  bouyer 		*(int *)data = siomctl(sc, 0, DMGET);
    499  1.6.2.2  bouyer 		break;
    500  1.6.2.2  bouyer 	case TIOCMBIS: /* Set individual bits of modem state */
    501  1.6.2.2  bouyer 		siomctl(sc, *(int *)data, DMBIS);
    502  1.6.2.2  bouyer 		break;
    503  1.6.2.2  bouyer 	case TIOCMBIC: /* Clear individual bits of modem state */
    504  1.6.2.2  bouyer 		siomctl(sc, *(int *)data, DMBIC);
    505  1.6.2.2  bouyer 		break;
    506  1.6.2.2  bouyer 	case TIOCSFLAGS: /* Instruct how serial port behaves */
    507  1.6.2.2  bouyer 		sc->sc_flags = *(int *)data;
    508  1.6.2.2  bouyer 		break;
    509  1.6.2.2  bouyer 	case TIOCGFLAGS: /* Return current serial port state */
    510  1.6.2.2  bouyer 		*(int *)data = sc->sc_flags;
    511  1.6.2.2  bouyer 		break;
    512  1.6.2.2  bouyer 	default:
    513  1.6.2.2  bouyer 		return ENOTTY;
    514  1.6.2.2  bouyer 	}
    515  1.6.2.2  bouyer 	return 0;
    516  1.6.2.2  bouyer }
    517  1.6.2.2  bouyer 
    518  1.6.2.2  bouyer /* ARSGUSED */
    519  1.6.2.2  bouyer struct tty *
    520  1.6.2.2  bouyer siotty(dev)
    521  1.6.2.2  bouyer 	dev_t dev;
    522  1.6.2.2  bouyer {
    523  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    524  1.6.2.2  bouyer 
    525  1.6.2.2  bouyer 	return sc->sc_tty;
    526  1.6.2.2  bouyer }
    527  1.6.2.2  bouyer 
    528  1.6.2.2  bouyer /*--------------------  miscelleneous routine --------------------*/
    529  1.6.2.2  bouyer 
    530  1.6.2.2  bouyer /* EXPORT */ void
    531  1.6.2.2  bouyer setsioreg(sio, regno, val)
    532  1.6.2.2  bouyer 	struct sioreg *sio;
    533  1.6.2.2  bouyer 	int regno, val;
    534  1.6.2.2  bouyer {
    535  1.6.2.2  bouyer 	if (regno != 0)
    536  1.6.2.2  bouyer 		sio->sio_cmd = regno;	/* DELAY(); */
    537  1.6.2.2  bouyer 	sio->sio_cmd = val;		/* DELAY(); */
    538  1.6.2.2  bouyer }
    539  1.6.2.2  bouyer 
    540  1.6.2.2  bouyer /* EXPORT */ int
    541  1.6.2.2  bouyer getsiocsr(sio)
    542  1.6.2.2  bouyer 	struct sioreg *sio;
    543  1.6.2.2  bouyer {
    544  1.6.2.2  bouyer 	int val;
    545  1.6.2.2  bouyer 
    546  1.6.2.2  bouyer 	val = sio->sio_stat << 8;	/* DELAY(); */
    547  1.6.2.2  bouyer 	sio->sio_cmd = 1;		/* DELAY(); */
    548  1.6.2.2  bouyer 	val |= sio->sio_stat;		/* DELAY(); */
    549  1.6.2.2  bouyer 	return val;
    550  1.6.2.2  bouyer }
    551  1.6.2.2  bouyer 
    552  1.6.2.2  bouyer /*---------------------  console interface ----------------------*/
    553  1.6.2.2  bouyer 
    554  1.6.2.2  bouyer void syscnattach __P((int));
    555  1.6.2.2  bouyer int  syscngetc __P((dev_t));
    556  1.6.2.2  bouyer void syscnputc __P((dev_t, int));
    557  1.6.2.2  bouyer 
    558  1.6.2.2  bouyer struct consdev syscons = {
    559  1.6.2.2  bouyer 	NULL,
    560  1.6.2.2  bouyer 	NULL,
    561  1.6.2.2  bouyer 	syscngetc,
    562  1.6.2.2  bouyer 	syscnputc,
    563  1.6.2.2  bouyer 	nullcnpollc,
    564  1.6.2.2  bouyer 	NULL,
    565  1.6.2.2  bouyer 	NODEV,
    566  1.6.2.2  bouyer 	CN_REMOTE,
    567  1.6.2.2  bouyer };
    568  1.6.2.2  bouyer 
    569  1.6.2.2  bouyer /* EXPORT */ void
    570  1.6.2.2  bouyer syscnattach(channel)
    571  1.6.2.2  bouyer 	int channel;
    572  1.6.2.2  bouyer {
    573  1.6.2.2  bouyer /*
    574  1.6.2.2  bouyer  * Channel A is immediately initialized with 9600N1 right after cold
    575  1.6.2.2  bouyer  * boot/reset/poweron.  ROM monitor emits one line message on CH.A.
    576  1.6.2.2  bouyer  */
    577  1.6.2.2  bouyer 	struct sioreg *sio;
    578  1.6.2.2  bouyer 	sio = (struct sioreg *)0x51000000 + channel;
    579  1.6.2.2  bouyer 
    580  1.6.2.2  bouyer 	syscons.cn_dev = makedev(7, channel);
    581  1.6.2.2  bouyer 	cn_tab = &syscons;
    582  1.6.2.2  bouyer 
    583  1.6.2.2  bouyer 	setsioreg(sio, WR0, WR0_CHANRST);
    584  1.6.2.2  bouyer 	setsioreg(sio, WR2A, WR2_VEC86 | WR2_INTR_1);
    585  1.6.2.2  bouyer 	setsioreg(sio, WR2B, 0);
    586  1.6.2.2  bouyer 	setsioreg(sio, WR0, ch0_regs[WR0]);
    587  1.6.2.2  bouyer 	setsioreg(sio, WR4, ch0_regs[WR4]);
    588  1.6.2.2  bouyer 	setsioreg(sio, WR3, ch0_regs[WR3]);
    589  1.6.2.2  bouyer 	setsioreg(sio, WR5, ch0_regs[WR5]);
    590  1.6.2.2  bouyer 	setsioreg(sio, WR0, ch0_regs[WR0]);
    591  1.6.2.2  bouyer }
    592  1.6.2.2  bouyer 
    593  1.6.2.2  bouyer /* EXPORT */ int
    594  1.6.2.2  bouyer syscngetc(dev)
    595  1.6.2.2  bouyer 	dev_t dev;
    596  1.6.2.2  bouyer {
    597  1.6.2.2  bouyer 	struct sioreg *sio;
    598  1.6.2.2  bouyer 	int s, c;
    599  1.6.2.2  bouyer 
    600  1.6.2.2  bouyer 	sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
    601  1.6.2.2  bouyer 	s = splhigh();
    602  1.6.2.2  bouyer 	while ((getsiocsr(sio) & RR_RXRDY) == 0)
    603  1.6.2.2  bouyer 		;
    604  1.6.2.2  bouyer 	c = sio->sio_data;
    605  1.6.2.2  bouyer 	splx(s);
    606  1.6.2.2  bouyer 
    607  1.6.2.2  bouyer 	return c;
    608  1.6.2.2  bouyer }
    609  1.6.2.2  bouyer 
    610  1.6.2.2  bouyer /* EXPORT */ void
    611  1.6.2.2  bouyer syscnputc(dev, c)
    612  1.6.2.2  bouyer 	dev_t dev;
    613  1.6.2.2  bouyer 	int c;
    614  1.6.2.2  bouyer {
    615  1.6.2.2  bouyer 	struct sioreg *sio;
    616  1.6.2.2  bouyer 	int s;
    617  1.6.2.2  bouyer 
    618  1.6.2.2  bouyer 	sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
    619  1.6.2.2  bouyer 	s = splhigh();
    620  1.6.2.2  bouyer 	while ((getsiocsr(sio) & RR_TXRDY) == 0)
    621  1.6.2.2  bouyer 		;
    622  1.6.2.2  bouyer 	sio->sio_cmd = WR0_RSTPEND;
    623  1.6.2.2  bouyer 	sio->sio_data = c;
    624  1.6.2.2  bouyer 	splx(s);
    625  1.6.2.2  bouyer }
    626