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