Home | History | Annotate | Line # | Download | only in dev
siotty.c revision 1.6.2.4
      1  1.6.2.4  bouyer /* $NetBSD: siotty.c,v 1.6.2.4 2001/04/21 17:53:54 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.4  bouyer __KERNEL_RCSID(0, "$NetBSD: siotty.c,v 1.6.2.4 2001/04/21 17:53:54 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.4  bouyer 			(*tp->t_linesw->l_start)(tp);
    193  1.6.2.2  bouyer 		}
    194  1.6.2.2  bouyer 	}
    195  1.6.2.2  bouyer }
    196  1.6.2.2  bouyer 
    197  1.6.2.2  bouyer static void
    198  1.6.2.2  bouyer siostart(tp)
    199  1.6.2.2  bouyer 	struct tty *tp;
    200  1.6.2.2  bouyer {
    201  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
    202  1.6.2.2  bouyer 	int s, c;
    203  1.6.2.2  bouyer 
    204  1.6.2.2  bouyer 	s = spltty();
    205  1.6.2.2  bouyer 	if (tp->t_state & (TS_BUSY|TS_TIMEOUT|TS_TTSTOP))
    206  1.6.2.2  bouyer 		goto out;
    207  1.6.2.2  bouyer 	if (tp->t_outq.c_cc <= tp->t_lowat) {
    208  1.6.2.2  bouyer 		if (tp->t_state & TS_ASLEEP) {
    209  1.6.2.2  bouyer 			tp->t_state &= ~TS_ASLEEP;
    210  1.6.2.2  bouyer 			wakeup((caddr_t)&tp->t_outq);
    211  1.6.2.2  bouyer 		}
    212  1.6.2.2  bouyer 		selwakeup(&tp->t_wsel);
    213  1.6.2.2  bouyer 	}
    214  1.6.2.2  bouyer 	if (tp->t_outq.c_cc == 0)
    215  1.6.2.2  bouyer 		goto out;
    216  1.6.2.2  bouyer 
    217  1.6.2.2  bouyer 	tp->t_state |= TS_BUSY;
    218  1.6.2.2  bouyer 	while (getsiocsr(sc->sc_ctl) & RR_TXRDY) {
    219  1.6.2.2  bouyer 		if ((c = getc(&tp->t_outq)) == -1)
    220  1.6.2.2  bouyer 			break;
    221  1.6.2.2  bouyer 		sc->sc_ctl->sio_data = c;
    222  1.6.2.2  bouyer 	}
    223  1.6.2.2  bouyer out:
    224  1.6.2.2  bouyer 	splx(s);
    225  1.6.2.2  bouyer }
    226  1.6.2.2  bouyer 
    227  1.6.2.2  bouyer void
    228  1.6.2.2  bouyer siostop(tp, flag)
    229  1.6.2.2  bouyer 	struct tty *tp;
    230  1.6.2.2  bouyer 	int flag;
    231  1.6.2.2  bouyer {
    232  1.6.2.2  bouyer 	int s;
    233  1.6.2.2  bouyer 
    234  1.6.2.2  bouyer         s = spltty();
    235  1.6.2.2  bouyer         if (TS_BUSY == (tp->t_state & (TS_BUSY|TS_TTSTOP))) {
    236  1.6.2.2  bouyer                 /*
    237  1.6.2.2  bouyer                  * Device is transmitting; must stop it.
    238  1.6.2.2  bouyer                  */
    239  1.6.2.2  bouyer 		tp->t_state |= TS_FLUSH;
    240  1.6.2.2  bouyer         }
    241  1.6.2.2  bouyer         splx(s);
    242  1.6.2.2  bouyer }
    243  1.6.2.2  bouyer 
    244  1.6.2.2  bouyer static int
    245  1.6.2.2  bouyer sioparam(tp, t)
    246  1.6.2.2  bouyer 	struct tty *tp;
    247  1.6.2.2  bouyer 	struct termios *t;
    248  1.6.2.2  bouyer {
    249  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
    250  1.6.2.2  bouyer 	int wr4, s;
    251  1.6.2.2  bouyer 
    252  1.6.2.2  bouyer 	if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
    253  1.6.2.2  bouyer 		return EINVAL;
    254  1.6.2.2  bouyer 	wr4 = ttspeedtab(t->c_ospeed, siospeedtab);
    255  1.6.2.2  bouyer 	if (wr4 < 0)
    256  1.6.2.2  bouyer 		return EINVAL;
    257  1.6.2.2  bouyer 
    258  1.6.2.2  bouyer 	if (sc->sc_flags & TIOCFLAG_SOFTCAR) {
    259  1.6.2.2  bouyer 		t->c_cflag |= CLOCAL;
    260  1.6.2.2  bouyer 		t->c_cflag &= ~HUPCL;
    261  1.6.2.2  bouyer 	}
    262  1.6.2.2  bouyer 	if (sc->sc_flags & TIOCFLAG_CLOCAL)
    263  1.6.2.2  bouyer 		t->c_cflag |= CLOCAL;
    264  1.6.2.2  bouyer 
    265  1.6.2.2  bouyer 	/*
    266  1.6.2.2  bouyer 	 * If there were no changes, don't do anything.  This avoids dropping
    267  1.6.2.2  bouyer 	 * input and improves performance when all we did was frob things like
    268  1.6.2.2  bouyer 	 * VMIN and VTIME.
    269  1.6.2.2  bouyer 	 */
    270  1.6.2.2  bouyer 	if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag)
    271  1.6.2.2  bouyer 		return 0;
    272  1.6.2.2  bouyer 
    273  1.6.2.2  bouyer 	tp->t_ispeed = t->c_ispeed;
    274  1.6.2.2  bouyer 	tp->t_ospeed = t->c_ospeed;
    275  1.6.2.2  bouyer 	tp->t_cflag = t->c_cflag;
    276  1.6.2.2  bouyer 
    277  1.6.2.2  bouyer 	sc->sc_wr[WR3] &= 0x3f;
    278  1.6.2.2  bouyer 	sc->sc_wr[WR5] &= 0x9f;
    279  1.6.2.2  bouyer 	switch (tp->t_cflag & CSIZE) {
    280  1.6.2.2  bouyer 	case CS7:
    281  1.6.2.2  bouyer 		sc->sc_wr[WR3] |= WR3_RX7BIT; sc->sc_wr[WR5] |= WR5_TX7BIT;
    282  1.6.2.2  bouyer 		break;
    283  1.6.2.2  bouyer 	case CS8:
    284  1.6.2.2  bouyer 		sc->sc_wr[WR3] |= WR3_RX8BIT; sc->sc_wr[WR5] |= WR5_TX8BIT;
    285  1.6.2.2  bouyer 		break;
    286  1.6.2.2  bouyer 	}
    287  1.6.2.2  bouyer 	if (tp->t_cflag & PARENB) {
    288  1.6.2.2  bouyer 		wr4 |= WR4_PARENAB;
    289  1.6.2.2  bouyer 		if ((tp->t_cflag & PARODD) == 0)
    290  1.6.2.2  bouyer 			wr4 |= WR4_EPARITY;
    291  1.6.2.2  bouyer 	}
    292  1.6.2.2  bouyer 	wr4 |= (tp->t_cflag & CSTOPB) ? WR4_STOP2 : WR4_STOP1;
    293  1.6.2.2  bouyer 	sc->sc_wr[WR4] = wr4;
    294  1.6.2.2  bouyer 
    295  1.6.2.2  bouyer 	s = spltty();
    296  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
    297  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
    298  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
    299  1.6.2.2  bouyer 	splx(s);
    300  1.6.2.2  bouyer 
    301  1.6.2.2  bouyer 	return 0;
    302  1.6.2.2  bouyer }
    303  1.6.2.2  bouyer 
    304  1.6.2.2  bouyer static int
    305  1.6.2.2  bouyer siomctl(sc, control, op)
    306  1.6.2.2  bouyer 	struct siotty_softc *sc;
    307  1.6.2.2  bouyer 	int control, op;
    308  1.6.2.2  bouyer {
    309  1.6.2.2  bouyer 	int val, s, wr5, rr;
    310  1.6.2.2  bouyer 
    311  1.6.2.2  bouyer 	val = 0;
    312  1.6.2.2  bouyer 	if (control & TIOCM_BREAK)
    313  1.6.2.2  bouyer 		val |= WR5_BREAK;
    314  1.6.2.2  bouyer 	if (control & TIOCM_DTR)
    315  1.6.2.2  bouyer 		val |= WR5_DTR;
    316  1.6.2.2  bouyer 	if (control & TIOCM_RTS)
    317  1.6.2.2  bouyer 		val |= WR5_RTS;
    318  1.6.2.2  bouyer 	s = spltty();
    319  1.6.2.2  bouyer 	wr5 = sc->sc_wr[WR5];
    320  1.6.2.2  bouyer 	switch (op) {
    321  1.6.2.2  bouyer 	case DMSET:
    322  1.6.2.2  bouyer 		wr5 &= ~(WR5_BREAK|WR5_DTR|WR5_RTS);
    323  1.6.2.2  bouyer 		/* FALLTHRU */
    324  1.6.2.2  bouyer 	case DMBIS:
    325  1.6.2.2  bouyer 		wr5 |= val;
    326  1.6.2.2  bouyer 		break;
    327  1.6.2.2  bouyer 	case DMBIC:
    328  1.6.2.2  bouyer 		wr5 &= ~val;
    329  1.6.2.2  bouyer 		break;
    330  1.6.2.2  bouyer 	case DMGET:
    331  1.6.2.2  bouyer 		val = 0;
    332  1.6.2.2  bouyer 		rr = getsiocsr(sc->sc_ctl);
    333  1.6.2.2  bouyer 		if (wr5 & WR5_DTR)
    334  1.6.2.2  bouyer 			val |= TIOCM_DTR;
    335  1.6.2.2  bouyer 		if (wr5 & WR5_RTS)
    336  1.6.2.2  bouyer 			val |= TIOCM_RTS;
    337  1.6.2.2  bouyer 		if (rr & RR_CTS)
    338  1.6.2.2  bouyer 			val |= TIOCM_CTS;
    339  1.6.2.2  bouyer 		if (rr & RR_DCD)
    340  1.6.2.2  bouyer 			val |= TIOCM_CD;
    341  1.6.2.2  bouyer 		goto done;
    342  1.6.2.2  bouyer 	}
    343  1.6.2.2  bouyer 	sc->sc_wr[WR5] = wr5;
    344  1.6.2.2  bouyer 	setsioreg(sc->sc_ctl, WR5, wr5);
    345  1.6.2.2  bouyer 	val = 0;
    346  1.6.2.2  bouyer   done:
    347  1.6.2.2  bouyer 	splx(s);
    348  1.6.2.2  bouyer 	return val;
    349  1.6.2.2  bouyer }
    350  1.6.2.2  bouyer 
    351  1.6.2.2  bouyer /*--------------------  cdevsw[] interface --------------------*/
    352  1.6.2.2  bouyer 
    353  1.6.2.2  bouyer int
    354  1.6.2.2  bouyer sioopen(dev, flag, mode, p)
    355  1.6.2.2  bouyer 	dev_t dev;
    356  1.6.2.2  bouyer 	int flag, mode;
    357  1.6.2.2  bouyer 	struct proc *p;
    358  1.6.2.2  bouyer {
    359  1.6.2.2  bouyer 	struct siotty_softc *sc;
    360  1.6.2.2  bouyer 	struct tty *tp;
    361  1.6.2.2  bouyer 	int error;
    362  1.6.2.2  bouyer 
    363  1.6.2.2  bouyer 	if ((sc = siotty_cd.cd_devs[minor(dev)]) == NULL)
    364  1.6.2.2  bouyer 		return ENXIO;
    365  1.6.2.2  bouyer 	if ((tp = sc->sc_tty) == NULL) {
    366  1.6.2.2  bouyer 		tp = sc->sc_tty = ttymalloc();
    367  1.6.2.2  bouyer 		tty_attach(tp);
    368  1.6.2.2  bouyer 	}
    369  1.6.2.2  bouyer 	else if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE)
    370  1.6.2.2  bouyer 	    && p->p_ucred->cr_uid != 0)
    371  1.6.2.2  bouyer 		return EBUSY;
    372  1.6.2.2  bouyer 
    373  1.6.2.2  bouyer 	tp->t_oproc = siostart;
    374  1.6.2.2  bouyer 	tp->t_param = sioparam;
    375  1.6.2.2  bouyer 	tp->t_hwiflow = NULL /* XXX siohwiflow XXX */;
    376  1.6.2.2  bouyer 	tp->t_dev = dev;
    377  1.6.2.2  bouyer 	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
    378  1.6.2.2  bouyer 		struct termios t;
    379  1.6.2.2  bouyer 
    380  1.6.2.2  bouyer 		t.c_ispeed = t.c_ospeed = TTYDEF_SPEED;
    381  1.6.2.2  bouyer 		t.c_cflag = TTYDEF_CFLAG;
    382  1.6.2.2  bouyer 		tp->t_ospeed = 0; /* force register update */
    383  1.6.2.2  bouyer 		(void)sioparam(tp, &t);
    384  1.6.2.2  bouyer 		tp->t_iflag = TTYDEF_IFLAG;
    385  1.6.2.2  bouyer 		tp->t_oflag = TTYDEF_OFLAG;
    386  1.6.2.2  bouyer 		tp->t_lflag = TTYDEF_LFLAG;
    387  1.6.2.2  bouyer 		ttychars(tp);
    388  1.6.2.2  bouyer 		ttsetwater(tp);
    389  1.6.2.2  bouyer 		/* raise RTS and DTR here; but, DTR lead is not wired */
    390  1.6.2.2  bouyer 		/* then check DCD condition; but, DCD lead is not wired */
    391  1.6.2.2  bouyer 		tp->t_state |= TS_CARR_ON; /* assume detected all the time */
    392  1.6.2.2  bouyer #if 0
    393  1.6.2.2  bouyer 		if ((sc->sc_flags & TIOCFLAG_SOFTCAR)
    394  1.6.2.2  bouyer 		    || (tp->t_cflag & MDMBUF)
    395  1.6.2.2  bouyer 		    || (getsiocsr(sc->sc_ctl) & RR_DCD))
    396  1.6.2.2  bouyer 			tp->t_state |= TS_CARR_ON;
    397  1.6.2.2  bouyer 		else
    398  1.6.2.2  bouyer 			tp->t_state &= ~TS_CARR_ON;
    399  1.6.2.2  bouyer #endif
    400  1.6.2.2  bouyer 	}
    401  1.6.2.2  bouyer 
    402  1.6.2.2  bouyer 	error = ttyopen(tp, 0, (flag & O_NONBLOCK));
    403  1.6.2.2  bouyer 	if (error > 0)
    404  1.6.2.2  bouyer 		return error;
    405  1.6.2.3  bouyer 	return (*tp->t_linesw->l_open)(dev, tp);
    406  1.6.2.2  bouyer }
    407  1.6.2.2  bouyer 
    408  1.6.2.2  bouyer int
    409  1.6.2.2  bouyer sioclose(dev, flag, mode, p)
    410  1.6.2.2  bouyer 	dev_t dev;
    411  1.6.2.2  bouyer 	int flag, mode;
    412  1.6.2.2  bouyer 	struct proc *p;
    413  1.6.2.2  bouyer {
    414  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    415  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    416  1.6.2.2  bouyer 	int s;
    417  1.6.2.2  bouyer 
    418  1.6.2.3  bouyer 	(*tp->t_linesw->l_close)(tp, flag);
    419  1.6.2.2  bouyer 
    420  1.6.2.2  bouyer 	s = spltty();
    421  1.6.2.2  bouyer 	siomctl(sc, TIOCM_BREAK, DMBIC);
    422  1.6.2.2  bouyer #if 0 /* because unable to feed DTR signal */
    423  1.6.2.2  bouyer 	if ((tp->t_cflag & HUPCL)
    424  1.6.2.2  bouyer 	    || tp->t_wopen || (tp->t_state & TS_ISOPEN) == 0) {
    425  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR, DMBIC);
    426  1.6.2.2  bouyer 		/* Yield CPU time to others for 1 second, then ... */
    427  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR, DMBIS);
    428  1.6.2.2  bouyer 	}
    429  1.6.2.2  bouyer #endif
    430  1.6.2.2  bouyer 	splx(s);
    431  1.6.2.2  bouyer 	return ttyclose(tp);
    432  1.6.2.2  bouyer }
    433  1.6.2.2  bouyer 
    434  1.6.2.2  bouyer int
    435  1.6.2.2  bouyer sioread(dev, uio, flag)
    436  1.6.2.2  bouyer 	dev_t dev;
    437  1.6.2.2  bouyer 	struct uio *uio;
    438  1.6.2.2  bouyer 	int flag;
    439  1.6.2.2  bouyer {
    440  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    441  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    442  1.6.2.2  bouyer 
    443  1.6.2.3  bouyer 	return (*tp->t_linesw->l_read)(tp, uio, flag);
    444  1.6.2.2  bouyer }
    445  1.6.2.2  bouyer 
    446  1.6.2.2  bouyer int
    447  1.6.2.2  bouyer siowrite(dev, uio, flag)
    448  1.6.2.2  bouyer 	dev_t dev;
    449  1.6.2.2  bouyer 	struct uio *uio;
    450  1.6.2.2  bouyer 	int flag;
    451  1.6.2.2  bouyer {
    452  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    453  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    454  1.6.2.2  bouyer 
    455  1.6.2.3  bouyer 	return (*tp->t_linesw->l_write)(tp, uio, flag);
    456  1.6.2.2  bouyer }
    457  1.6.2.2  bouyer 
    458  1.6.2.2  bouyer int
    459  1.6.2.2  bouyer sioioctl(dev, cmd, data, flag, p)
    460  1.6.2.2  bouyer 	dev_t dev;
    461  1.6.2.2  bouyer 	u_long cmd;
    462  1.6.2.2  bouyer 	caddr_t data;
    463  1.6.2.2  bouyer 	int flag;
    464  1.6.2.2  bouyer 	struct proc *p;
    465  1.6.2.2  bouyer {
    466  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    467  1.6.2.2  bouyer 	struct tty *tp = sc->sc_tty;
    468  1.6.2.2  bouyer 	int error;
    469  1.6.2.2  bouyer 
    470  1.6.2.3  bouyer 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
    471  1.6.2.2  bouyer 	if (error >= 0)
    472  1.6.2.2  bouyer 		return error;
    473  1.6.2.2  bouyer 	error = ttioctl(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 
    477  1.6.2.2  bouyer 	/* the last resort for TIOC ioctl tranversing */
    478  1.6.2.2  bouyer 	switch (cmd) {
    479  1.6.2.2  bouyer 	case TIOCSBRK: /* Set the hardware into BREAK condition */
    480  1.6.2.2  bouyer 		siomctl(sc, TIOCM_BREAK, DMBIS);
    481  1.6.2.2  bouyer 		break;
    482  1.6.2.2  bouyer 	case TIOCCBRK: /* Clear the hardware BREAK condition */
    483  1.6.2.2  bouyer 		siomctl(sc, TIOCM_BREAK, DMBIC);
    484  1.6.2.2  bouyer 		break;
    485  1.6.2.2  bouyer 	case TIOCSDTR: /* Assert DTR signal */
    486  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIS);
    487  1.6.2.2  bouyer 		break;
    488  1.6.2.2  bouyer 	case TIOCCDTR: /* Clear DTR signal */
    489  1.6.2.2  bouyer 		siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIC);
    490  1.6.2.2  bouyer 		break;
    491  1.6.2.2  bouyer 	case TIOCMSET: /* Set modem state replacing current one */
    492  1.6.2.2  bouyer 		siomctl(sc, *(int *)data, DMSET);
    493  1.6.2.2  bouyer 		break;
    494  1.6.2.2  bouyer 	case TIOCMGET: /* Return current modem state */
    495  1.6.2.2  bouyer 		*(int *)data = siomctl(sc, 0, DMGET);
    496  1.6.2.2  bouyer 		break;
    497  1.6.2.2  bouyer 	case TIOCMBIS: /* Set individual bits of modem state */
    498  1.6.2.2  bouyer 		siomctl(sc, *(int *)data, DMBIS);
    499  1.6.2.2  bouyer 		break;
    500  1.6.2.2  bouyer 	case TIOCMBIC: /* Clear individual bits of modem state */
    501  1.6.2.2  bouyer 		siomctl(sc, *(int *)data, DMBIC);
    502  1.6.2.2  bouyer 		break;
    503  1.6.2.2  bouyer 	case TIOCSFLAGS: /* Instruct how serial port behaves */
    504  1.6.2.2  bouyer 		sc->sc_flags = *(int *)data;
    505  1.6.2.2  bouyer 		break;
    506  1.6.2.2  bouyer 	case TIOCGFLAGS: /* Return current serial port state */
    507  1.6.2.2  bouyer 		*(int *)data = sc->sc_flags;
    508  1.6.2.2  bouyer 		break;
    509  1.6.2.2  bouyer 	default:
    510  1.6.2.2  bouyer 		return ENOTTY;
    511  1.6.2.2  bouyer 	}
    512  1.6.2.2  bouyer 	return 0;
    513  1.6.2.2  bouyer }
    514  1.6.2.2  bouyer 
    515  1.6.2.2  bouyer /* ARSGUSED */
    516  1.6.2.2  bouyer struct tty *
    517  1.6.2.2  bouyer siotty(dev)
    518  1.6.2.2  bouyer 	dev_t dev;
    519  1.6.2.2  bouyer {
    520  1.6.2.2  bouyer 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    521  1.6.2.2  bouyer 
    522  1.6.2.2  bouyer 	return sc->sc_tty;
    523  1.6.2.2  bouyer }
    524  1.6.2.2  bouyer 
    525  1.6.2.2  bouyer /*--------------------  miscelleneous routine --------------------*/
    526  1.6.2.2  bouyer 
    527  1.6.2.2  bouyer /* EXPORT */ void
    528  1.6.2.2  bouyer setsioreg(sio, regno, val)
    529  1.6.2.2  bouyer 	struct sioreg *sio;
    530  1.6.2.2  bouyer 	int regno, val;
    531  1.6.2.2  bouyer {
    532  1.6.2.2  bouyer 	if (regno != 0)
    533  1.6.2.2  bouyer 		sio->sio_cmd = regno;	/* DELAY(); */
    534  1.6.2.2  bouyer 	sio->sio_cmd = val;		/* DELAY(); */
    535  1.6.2.2  bouyer }
    536  1.6.2.2  bouyer 
    537  1.6.2.2  bouyer /* EXPORT */ int
    538  1.6.2.2  bouyer getsiocsr(sio)
    539  1.6.2.2  bouyer 	struct sioreg *sio;
    540  1.6.2.2  bouyer {
    541  1.6.2.2  bouyer 	int val;
    542  1.6.2.2  bouyer 
    543  1.6.2.2  bouyer 	val = sio->sio_stat << 8;	/* DELAY(); */
    544  1.6.2.2  bouyer 	sio->sio_cmd = 1;		/* DELAY(); */
    545  1.6.2.2  bouyer 	val |= sio->sio_stat;		/* DELAY(); */
    546  1.6.2.2  bouyer 	return val;
    547  1.6.2.2  bouyer }
    548  1.6.2.2  bouyer 
    549  1.6.2.2  bouyer /*---------------------  console interface ----------------------*/
    550  1.6.2.2  bouyer 
    551  1.6.2.2  bouyer void syscnattach __P((int));
    552  1.6.2.2  bouyer int  syscngetc __P((dev_t));
    553  1.6.2.2  bouyer void syscnputc __P((dev_t, int));
    554  1.6.2.2  bouyer 
    555  1.6.2.2  bouyer struct consdev syscons = {
    556  1.6.2.2  bouyer 	NULL,
    557  1.6.2.2  bouyer 	NULL,
    558  1.6.2.2  bouyer 	syscngetc,
    559  1.6.2.2  bouyer 	syscnputc,
    560  1.6.2.2  bouyer 	nullcnpollc,
    561  1.6.2.2  bouyer 	NULL,
    562  1.6.2.2  bouyer 	NODEV,
    563  1.6.2.2  bouyer 	CN_REMOTE,
    564  1.6.2.2  bouyer };
    565  1.6.2.2  bouyer 
    566  1.6.2.2  bouyer /* EXPORT */ void
    567  1.6.2.2  bouyer syscnattach(channel)
    568  1.6.2.2  bouyer 	int channel;
    569  1.6.2.2  bouyer {
    570  1.6.2.2  bouyer /*
    571  1.6.2.2  bouyer  * Channel A is immediately initialized with 9600N1 right after cold
    572  1.6.2.2  bouyer  * boot/reset/poweron.  ROM monitor emits one line message on CH.A.
    573  1.6.2.2  bouyer  */
    574  1.6.2.2  bouyer 	struct sioreg *sio;
    575  1.6.2.2  bouyer 	sio = (struct sioreg *)0x51000000 + channel;
    576  1.6.2.2  bouyer 
    577  1.6.2.2  bouyer 	syscons.cn_dev = makedev(7, channel);
    578  1.6.2.2  bouyer 	cn_tab = &syscons;
    579  1.6.2.2  bouyer 
    580  1.6.2.2  bouyer 	setsioreg(sio, WR0, WR0_CHANRST);
    581  1.6.2.2  bouyer 	setsioreg(sio, WR2A, WR2_VEC86 | WR2_INTR_1);
    582  1.6.2.2  bouyer 	setsioreg(sio, WR2B, 0);
    583  1.6.2.2  bouyer 	setsioreg(sio, WR0, ch0_regs[WR0]);
    584  1.6.2.2  bouyer 	setsioreg(sio, WR4, ch0_regs[WR4]);
    585  1.6.2.2  bouyer 	setsioreg(sio, WR3, ch0_regs[WR3]);
    586  1.6.2.2  bouyer 	setsioreg(sio, WR5, ch0_regs[WR5]);
    587  1.6.2.2  bouyer 	setsioreg(sio, WR0, ch0_regs[WR0]);
    588  1.6.2.2  bouyer }
    589  1.6.2.2  bouyer 
    590  1.6.2.2  bouyer /* EXPORT */ int
    591  1.6.2.2  bouyer syscngetc(dev)
    592  1.6.2.2  bouyer 	dev_t dev;
    593  1.6.2.2  bouyer {
    594  1.6.2.2  bouyer 	struct sioreg *sio;
    595  1.6.2.2  bouyer 	int s, c;
    596  1.6.2.2  bouyer 
    597  1.6.2.2  bouyer 	sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
    598  1.6.2.2  bouyer 	s = splhigh();
    599  1.6.2.2  bouyer 	while ((getsiocsr(sio) & RR_RXRDY) == 0)
    600  1.6.2.2  bouyer 		;
    601  1.6.2.2  bouyer 	c = sio->sio_data;
    602  1.6.2.2  bouyer 	splx(s);
    603  1.6.2.2  bouyer 
    604  1.6.2.2  bouyer 	return c;
    605  1.6.2.2  bouyer }
    606  1.6.2.2  bouyer 
    607  1.6.2.2  bouyer /* EXPORT */ void
    608  1.6.2.2  bouyer syscnputc(dev, c)
    609  1.6.2.2  bouyer 	dev_t dev;
    610  1.6.2.2  bouyer 	int c;
    611  1.6.2.2  bouyer {
    612  1.6.2.2  bouyer 	struct sioreg *sio;
    613  1.6.2.2  bouyer 	int s;
    614  1.6.2.2  bouyer 
    615  1.6.2.2  bouyer 	sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
    616  1.6.2.2  bouyer 	s = splhigh();
    617  1.6.2.2  bouyer 	while ((getsiocsr(sio) & RR_TXRDY) == 0)
    618  1.6.2.2  bouyer 		;
    619  1.6.2.2  bouyer 	sio->sio_cmd = WR0_RSTPEND;
    620  1.6.2.2  bouyer 	sio->sio_data = c;
    621  1.6.2.2  bouyer 	splx(s);
    622  1.6.2.2  bouyer }
    623