Home | History | Annotate | Line # | Download | only in dev
siotty.c revision 1.8.8.5
      1  1.8.8.5  nathanw /* $NetBSD: siotty.c,v 1.8.8.5 2002/11/11 21:59:28 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.5  nathanw __KERNEL_RCSID(0, "$NetBSD: siotty.c,v 1.8.8.5 2002/11/11 21:59:28 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 static void siostart __P((struct tty *));
     91  1.8.8.2  nathanw static int  sioparam __P((struct tty *, struct termios *));
     92  1.8.8.2  nathanw static void siottyintr __P((int));
     93  1.8.8.2  nathanw static int  siomctl __P((struct siotty_softc *, int, int));
     94  1.8.8.2  nathanw 
     95  1.8.8.2  nathanw static int  siotty_match __P((struct device *, struct cfdata *, void *));
     96  1.8.8.2  nathanw static void siotty_attach __P((struct device *, struct device *, void *));
     97  1.8.8.2  nathanw 
     98  1.8.8.4  nathanw CFATTACH_DECL(siotty, sizeof(struct siotty_softc),
     99  1.8.8.4  nathanw     siotty_match, siotty_attach, NULL, NULL);
    100  1.8.8.2  nathanw extern struct cfdriver siotty_cd;
    101  1.8.8.2  nathanw 
    102  1.8.8.3  nathanw dev_type_open(sioopen);
    103  1.8.8.3  nathanw dev_type_close(sioclose);
    104  1.8.8.3  nathanw dev_type_read(sioread);
    105  1.8.8.3  nathanw dev_type_write(siowrite);
    106  1.8.8.3  nathanw dev_type_ioctl(sioioctl);
    107  1.8.8.3  nathanw dev_type_stop(siostop);
    108  1.8.8.3  nathanw dev_type_tty(siotty);
    109  1.8.8.3  nathanw dev_type_poll(siopoll);
    110  1.8.8.3  nathanw 
    111  1.8.8.3  nathanw const struct cdevsw siotty_cdevsw = {
    112  1.8.8.3  nathanw 	sioopen, sioclose, sioread, siowrite, sioioctl,
    113  1.8.8.5  nathanw 	siostop, siotty, siopoll, nommap, ttykqfilter, D_TTY
    114  1.8.8.3  nathanw };
    115  1.8.8.3  nathanw 
    116  1.8.8.2  nathanw static int
    117  1.8.8.2  nathanw siotty_match(parent, cf, aux)
    118  1.8.8.2  nathanw 	struct device *parent;
    119  1.8.8.2  nathanw 	struct cfdata *cf;
    120  1.8.8.2  nathanw 	void   *aux;
    121  1.8.8.2  nathanw {
    122  1.8.8.2  nathanw 	struct sio_attach_args *args = aux;
    123  1.8.8.2  nathanw 
    124  1.8.8.2  nathanw 	if (args->channel != 0) /* XXX allow tty on Ch.B XXX */
    125  1.8.8.2  nathanw 		return 0;
    126  1.8.8.2  nathanw 	return 1;
    127  1.8.8.2  nathanw }
    128  1.8.8.2  nathanw 
    129  1.8.8.2  nathanw static void
    130  1.8.8.2  nathanw siotty_attach(parent, self, aux)
    131  1.8.8.2  nathanw 	struct device *parent, *self;
    132  1.8.8.2  nathanw 	void *aux;
    133  1.8.8.2  nathanw {
    134  1.8.8.2  nathanw 	struct sio_softc *scp = (void *)parent;
    135  1.8.8.2  nathanw 	struct siotty_softc *sc = (void *)self;
    136  1.8.8.2  nathanw 	struct sio_attach_args *args = aux;
    137  1.8.8.2  nathanw 
    138  1.8.8.2  nathanw 	sc->sc_ctl = (struct sioreg *)scp->scp_ctl + args->channel;
    139  1.8.8.2  nathanw 	bcopy(ch0_regs, sc->sc_wr, sizeof(ch0_regs));
    140  1.8.8.2  nathanw 	scp->scp_intr[args->channel] = siottyintr;
    141  1.8.8.2  nathanw 
    142  1.8.8.2  nathanw 	if (args->hwflags == 1) {
    143  1.8.8.2  nathanw 		printf(" (console)");
    144  1.8.8.2  nathanw 		sc->sc_flags = TIOCFLAG_SOFTCAR;
    145  1.8.8.2  nathanw 	}
    146  1.8.8.2  nathanw 	else {
    147  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR0, WR0_CHANRST);
    148  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR2A, WR2_VEC86 | WR2_INTR_1);
    149  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR2B, 0);
    150  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
    151  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
    152  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
    153  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
    154  1.8.8.2  nathanw 		setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
    155  1.8.8.2  nathanw 	}
    156  1.8.8.2  nathanw 	setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); /* now interrupt driven */
    157  1.8.8.2  nathanw 
    158  1.8.8.2  nathanw 	printf("\n");
    159  1.8.8.2  nathanw }
    160  1.8.8.2  nathanw 
    161  1.8.8.2  nathanw /*--------------------  low level routine --------------------*/
    162  1.8.8.2  nathanw 
    163  1.8.8.2  nathanw static void
    164  1.8.8.2  nathanw siottyintr(chan)
    165  1.8.8.2  nathanw 	int chan;
    166  1.8.8.2  nathanw {
    167  1.8.8.2  nathanw 	struct siotty_softc *sc;
    168  1.8.8.2  nathanw 	struct sioreg *sio;
    169  1.8.8.2  nathanw 	struct tty *tp;
    170  1.8.8.2  nathanw 	unsigned int code;
    171  1.8.8.2  nathanw 	int rr;
    172  1.8.8.2  nathanw 
    173  1.8.8.2  nathanw 	if (chan >= siotty_cd.cd_ndevs)
    174  1.8.8.2  nathanw 		return;
    175  1.8.8.2  nathanw 	sc = siotty_cd.cd_devs[chan];
    176  1.8.8.2  nathanw 	tp = sc->sc_tty;
    177  1.8.8.2  nathanw 	sio = sc->sc_ctl;
    178  1.8.8.2  nathanw 	rr = getsiocsr(sio);
    179  1.8.8.2  nathanw 	if (rr & RR_RXRDY) {
    180  1.8.8.2  nathanw 		do {
    181  1.8.8.2  nathanw 			code = sio->sio_data;
    182  1.8.8.2  nathanw 			if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
    183  1.8.8.2  nathanw 				sio->sio_cmd = WR0_ERRRST;
    184  1.8.8.2  nathanw 				if (sio->sio_stat & RR_FRAMING)
    185  1.8.8.2  nathanw 					code |= TTY_FE;
    186  1.8.8.2  nathanw 				else if (sio->sio_stat & RR_PARITY)
    187  1.8.8.2  nathanw 					code |= TTY_PE;
    188  1.8.8.2  nathanw 			}
    189  1.8.8.2  nathanw 			if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
    190  1.8.8.2  nathanw 				continue;
    191  1.8.8.2  nathanw #if 0 && defined(DDB) /* ?!?! fails to resume ?!?! */
    192  1.8.8.2  nathanw 			if ((rr & RR_BREAK) && tp->t_dev == cn_tab->cn_dev) {
    193  1.8.8.2  nathanw 				cpu_Debugger();
    194  1.8.8.2  nathanw 				return;
    195  1.8.8.2  nathanw 			}
    196  1.8.8.2  nathanw #endif
    197  1.8.8.2  nathanw 			(*tp->t_linesw->l_rint)(code, tp);
    198  1.8.8.2  nathanw 		} while ((rr = getsiocsr(sio)) & RR_RXRDY);
    199  1.8.8.2  nathanw 	}
    200  1.8.8.2  nathanw 	if (rr & RR_TXRDY) {
    201  1.8.8.2  nathanw 		sio->sio_cmd = WR0_RSTPEND;
    202  1.8.8.2  nathanw 		if (tp != NULL) {
    203  1.8.8.2  nathanw 			tp->t_state &= ~(TS_BUSY|TS_FLUSH);
    204  1.8.8.2  nathanw 			(*tp->t_linesw->l_start)(tp);
    205  1.8.8.2  nathanw 		}
    206  1.8.8.2  nathanw 	}
    207  1.8.8.2  nathanw }
    208  1.8.8.2  nathanw 
    209  1.8.8.2  nathanw static void
    210  1.8.8.2  nathanw siostart(tp)
    211  1.8.8.2  nathanw 	struct tty *tp;
    212  1.8.8.2  nathanw {
    213  1.8.8.2  nathanw 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
    214  1.8.8.2  nathanw 	int s, c;
    215  1.8.8.2  nathanw 
    216  1.8.8.2  nathanw 	s = spltty();
    217  1.8.8.2  nathanw 	if (tp->t_state & (TS_BUSY|TS_TIMEOUT|TS_TTSTOP))
    218  1.8.8.2  nathanw 		goto out;
    219  1.8.8.2  nathanw 	if (tp->t_outq.c_cc <= tp->t_lowat) {
    220  1.8.8.2  nathanw 		if (tp->t_state & TS_ASLEEP) {
    221  1.8.8.2  nathanw 			tp->t_state &= ~TS_ASLEEP;
    222  1.8.8.2  nathanw 			wakeup((caddr_t)&tp->t_outq);
    223  1.8.8.2  nathanw 		}
    224  1.8.8.2  nathanw 		selwakeup(&tp->t_wsel);
    225  1.8.8.2  nathanw 	}
    226  1.8.8.2  nathanw 	if (tp->t_outq.c_cc == 0)
    227  1.8.8.2  nathanw 		goto out;
    228  1.8.8.2  nathanw 
    229  1.8.8.2  nathanw 	tp->t_state |= TS_BUSY;
    230  1.8.8.2  nathanw 	while (getsiocsr(sc->sc_ctl) & RR_TXRDY) {
    231  1.8.8.2  nathanw 		if ((c = getc(&tp->t_outq)) == -1)
    232  1.8.8.2  nathanw 			break;
    233  1.8.8.2  nathanw 		sc->sc_ctl->sio_data = c;
    234  1.8.8.2  nathanw 	}
    235  1.8.8.2  nathanw out:
    236  1.8.8.2  nathanw 	splx(s);
    237  1.8.8.2  nathanw }
    238  1.8.8.2  nathanw 
    239  1.8.8.2  nathanw void
    240  1.8.8.2  nathanw siostop(tp, flag)
    241  1.8.8.2  nathanw 	struct tty *tp;
    242  1.8.8.2  nathanw 	int flag;
    243  1.8.8.2  nathanw {
    244  1.8.8.2  nathanw 	int s;
    245  1.8.8.2  nathanw 
    246  1.8.8.2  nathanw         s = spltty();
    247  1.8.8.2  nathanw         if (TS_BUSY == (tp->t_state & (TS_BUSY|TS_TTSTOP))) {
    248  1.8.8.2  nathanw                 /*
    249  1.8.8.2  nathanw                  * Device is transmitting; must stop it.
    250  1.8.8.2  nathanw                  */
    251  1.8.8.2  nathanw 		tp->t_state |= TS_FLUSH;
    252  1.8.8.2  nathanw         }
    253  1.8.8.2  nathanw         splx(s);
    254  1.8.8.2  nathanw }
    255  1.8.8.2  nathanw 
    256  1.8.8.2  nathanw static int
    257  1.8.8.2  nathanw sioparam(tp, t)
    258  1.8.8.2  nathanw 	struct tty *tp;
    259  1.8.8.2  nathanw 	struct termios *t;
    260  1.8.8.2  nathanw {
    261  1.8.8.2  nathanw 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
    262  1.8.8.2  nathanw 	int wr4, s;
    263  1.8.8.2  nathanw 
    264  1.8.8.2  nathanw 	if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
    265  1.8.8.2  nathanw 		return EINVAL;
    266  1.8.8.2  nathanw 	wr4 = ttspeedtab(t->c_ospeed, siospeedtab);
    267  1.8.8.2  nathanw 	if (wr4 < 0)
    268  1.8.8.2  nathanw 		return EINVAL;
    269  1.8.8.2  nathanw 
    270  1.8.8.2  nathanw 	if (sc->sc_flags & TIOCFLAG_SOFTCAR) {
    271  1.8.8.2  nathanw 		t->c_cflag |= CLOCAL;
    272  1.8.8.2  nathanw 		t->c_cflag &= ~HUPCL;
    273  1.8.8.2  nathanw 	}
    274  1.8.8.2  nathanw 	if (sc->sc_flags & TIOCFLAG_CLOCAL)
    275  1.8.8.2  nathanw 		t->c_cflag |= CLOCAL;
    276  1.8.8.2  nathanw 
    277  1.8.8.2  nathanw 	/*
    278  1.8.8.2  nathanw 	 * If there were no changes, don't do anything.  This avoids dropping
    279  1.8.8.2  nathanw 	 * input and improves performance when all we did was frob things like
    280  1.8.8.2  nathanw 	 * VMIN and VTIME.
    281  1.8.8.2  nathanw 	 */
    282  1.8.8.2  nathanw 	if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag)
    283  1.8.8.2  nathanw 		return 0;
    284  1.8.8.2  nathanw 
    285  1.8.8.2  nathanw 	tp->t_ispeed = t->c_ispeed;
    286  1.8.8.2  nathanw 	tp->t_ospeed = t->c_ospeed;
    287  1.8.8.2  nathanw 	tp->t_cflag = t->c_cflag;
    288  1.8.8.2  nathanw 
    289  1.8.8.2  nathanw 	sc->sc_wr[WR3] &= 0x3f;
    290  1.8.8.2  nathanw 	sc->sc_wr[WR5] &= 0x9f;
    291  1.8.8.2  nathanw 	switch (tp->t_cflag & CSIZE) {
    292  1.8.8.2  nathanw 	case CS7:
    293  1.8.8.2  nathanw 		sc->sc_wr[WR3] |= WR3_RX7BIT; sc->sc_wr[WR5] |= WR5_TX7BIT;
    294  1.8.8.2  nathanw 		break;
    295  1.8.8.2  nathanw 	case CS8:
    296  1.8.8.2  nathanw 		sc->sc_wr[WR3] |= WR3_RX8BIT; sc->sc_wr[WR5] |= WR5_TX8BIT;
    297  1.8.8.2  nathanw 		break;
    298  1.8.8.2  nathanw 	}
    299  1.8.8.2  nathanw 	if (tp->t_cflag & PARENB) {
    300  1.8.8.2  nathanw 		wr4 |= WR4_PARENAB;
    301  1.8.8.2  nathanw 		if ((tp->t_cflag & PARODD) == 0)
    302  1.8.8.2  nathanw 			wr4 |= WR4_EPARITY;
    303  1.8.8.2  nathanw 	}
    304  1.8.8.2  nathanw 	wr4 |= (tp->t_cflag & CSTOPB) ? WR4_STOP2 : WR4_STOP1;
    305  1.8.8.2  nathanw 	sc->sc_wr[WR4] = wr4;
    306  1.8.8.2  nathanw 
    307  1.8.8.2  nathanw 	s = spltty();
    308  1.8.8.2  nathanw 	setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
    309  1.8.8.2  nathanw 	setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
    310  1.8.8.2  nathanw 	setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
    311  1.8.8.2  nathanw 	splx(s);
    312  1.8.8.2  nathanw 
    313  1.8.8.2  nathanw 	return 0;
    314  1.8.8.2  nathanw }
    315  1.8.8.2  nathanw 
    316  1.8.8.2  nathanw static int
    317  1.8.8.2  nathanw siomctl(sc, control, op)
    318  1.8.8.2  nathanw 	struct siotty_softc *sc;
    319  1.8.8.2  nathanw 	int control, op;
    320  1.8.8.2  nathanw {
    321  1.8.8.2  nathanw 	int val, s, wr5, rr;
    322  1.8.8.2  nathanw 
    323  1.8.8.2  nathanw 	val = 0;
    324  1.8.8.2  nathanw 	if (control & TIOCM_BREAK)
    325  1.8.8.2  nathanw 		val |= WR5_BREAK;
    326  1.8.8.2  nathanw 	if (control & TIOCM_DTR)
    327  1.8.8.2  nathanw 		val |= WR5_DTR;
    328  1.8.8.2  nathanw 	if (control & TIOCM_RTS)
    329  1.8.8.2  nathanw 		val |= WR5_RTS;
    330  1.8.8.2  nathanw 	s = spltty();
    331  1.8.8.2  nathanw 	wr5 = sc->sc_wr[WR5];
    332  1.8.8.2  nathanw 	switch (op) {
    333  1.8.8.2  nathanw 	case DMSET:
    334  1.8.8.2  nathanw 		wr5 &= ~(WR5_BREAK|WR5_DTR|WR5_RTS);
    335  1.8.8.2  nathanw 		/* FALLTHRU */
    336  1.8.8.2  nathanw 	case DMBIS:
    337  1.8.8.2  nathanw 		wr5 |= val;
    338  1.8.8.2  nathanw 		break;
    339  1.8.8.2  nathanw 	case DMBIC:
    340  1.8.8.2  nathanw 		wr5 &= ~val;
    341  1.8.8.2  nathanw 		break;
    342  1.8.8.2  nathanw 	case DMGET:
    343  1.8.8.2  nathanw 		val = 0;
    344  1.8.8.2  nathanw 		rr = getsiocsr(sc->sc_ctl);
    345  1.8.8.2  nathanw 		if (wr5 & WR5_DTR)
    346  1.8.8.2  nathanw 			val |= TIOCM_DTR;
    347  1.8.8.2  nathanw 		if (wr5 & WR5_RTS)
    348  1.8.8.2  nathanw 			val |= TIOCM_RTS;
    349  1.8.8.2  nathanw 		if (rr & RR_CTS)
    350  1.8.8.2  nathanw 			val |= TIOCM_CTS;
    351  1.8.8.2  nathanw 		if (rr & RR_DCD)
    352  1.8.8.2  nathanw 			val |= TIOCM_CD;
    353  1.8.8.2  nathanw 		goto done;
    354  1.8.8.2  nathanw 	}
    355  1.8.8.2  nathanw 	sc->sc_wr[WR5] = wr5;
    356  1.8.8.2  nathanw 	setsioreg(sc->sc_ctl, WR5, wr5);
    357  1.8.8.2  nathanw 	val = 0;
    358  1.8.8.2  nathanw   done:
    359  1.8.8.2  nathanw 	splx(s);
    360  1.8.8.2  nathanw 	return val;
    361  1.8.8.2  nathanw }
    362  1.8.8.2  nathanw 
    363  1.8.8.2  nathanw /*--------------------  cdevsw[] interface --------------------*/
    364  1.8.8.2  nathanw 
    365  1.8.8.2  nathanw int
    366  1.8.8.2  nathanw sioopen(dev, flag, mode, p)
    367  1.8.8.2  nathanw 	dev_t dev;
    368  1.8.8.2  nathanw 	int flag, mode;
    369  1.8.8.2  nathanw 	struct proc *p;
    370  1.8.8.2  nathanw {
    371  1.8.8.2  nathanw 	struct siotty_softc *sc;
    372  1.8.8.2  nathanw 	struct tty *tp;
    373  1.8.8.2  nathanw 	int error;
    374  1.8.8.2  nathanw 
    375  1.8.8.2  nathanw 	if ((sc = siotty_cd.cd_devs[minor(dev)]) == NULL)
    376  1.8.8.2  nathanw 		return ENXIO;
    377  1.8.8.2  nathanw 	if ((tp = sc->sc_tty) == NULL) {
    378  1.8.8.2  nathanw 		tp = sc->sc_tty = ttymalloc();
    379  1.8.8.2  nathanw 		tty_attach(tp);
    380  1.8.8.2  nathanw 	}
    381  1.8.8.2  nathanw 	else if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE)
    382  1.8.8.2  nathanw 	    && p->p_ucred->cr_uid != 0)
    383  1.8.8.2  nathanw 		return EBUSY;
    384  1.8.8.2  nathanw 
    385  1.8.8.2  nathanw 	tp->t_oproc = siostart;
    386  1.8.8.2  nathanw 	tp->t_param = sioparam;
    387  1.8.8.2  nathanw 	tp->t_hwiflow = NULL /* XXX siohwiflow XXX */;
    388  1.8.8.2  nathanw 	tp->t_dev = dev;
    389  1.8.8.2  nathanw 	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
    390  1.8.8.2  nathanw 		struct termios t;
    391  1.8.8.2  nathanw 
    392  1.8.8.2  nathanw 		t.c_ispeed = t.c_ospeed = TTYDEF_SPEED;
    393  1.8.8.2  nathanw 		t.c_cflag = TTYDEF_CFLAG;
    394  1.8.8.2  nathanw 		tp->t_ospeed = 0; /* force register update */
    395  1.8.8.2  nathanw 		(void)sioparam(tp, &t);
    396  1.8.8.2  nathanw 		tp->t_iflag = TTYDEF_IFLAG;
    397  1.8.8.2  nathanw 		tp->t_oflag = TTYDEF_OFLAG;
    398  1.8.8.2  nathanw 		tp->t_lflag = TTYDEF_LFLAG;
    399  1.8.8.2  nathanw 		ttychars(tp);
    400  1.8.8.2  nathanw 		ttsetwater(tp);
    401  1.8.8.2  nathanw 		/* raise RTS and DTR here; but, DTR lead is not wired */
    402  1.8.8.2  nathanw 		/* then check DCD condition; but, DCD lead is not wired */
    403  1.8.8.2  nathanw 		tp->t_state |= TS_CARR_ON; /* assume detected all the time */
    404  1.8.8.2  nathanw #if 0
    405  1.8.8.2  nathanw 		if ((sc->sc_flags & TIOCFLAG_SOFTCAR)
    406  1.8.8.2  nathanw 		    || (tp->t_cflag & MDMBUF)
    407  1.8.8.2  nathanw 		    || (getsiocsr(sc->sc_ctl) & RR_DCD))
    408  1.8.8.2  nathanw 			tp->t_state |= TS_CARR_ON;
    409  1.8.8.2  nathanw 		else
    410  1.8.8.2  nathanw 			tp->t_state &= ~TS_CARR_ON;
    411  1.8.8.2  nathanw #endif
    412  1.8.8.2  nathanw 	}
    413  1.8.8.2  nathanw 
    414  1.8.8.2  nathanw 	error = ttyopen(tp, 0, (flag & O_NONBLOCK));
    415  1.8.8.2  nathanw 	if (error > 0)
    416  1.8.8.2  nathanw 		return error;
    417  1.8.8.2  nathanw 	return (*tp->t_linesw->l_open)(dev, tp);
    418  1.8.8.2  nathanw }
    419  1.8.8.2  nathanw 
    420  1.8.8.2  nathanw int
    421  1.8.8.2  nathanw sioclose(dev, flag, mode, p)
    422  1.8.8.2  nathanw 	dev_t dev;
    423  1.8.8.2  nathanw 	int flag, mode;
    424  1.8.8.2  nathanw 	struct proc *p;
    425  1.8.8.2  nathanw {
    426  1.8.8.2  nathanw 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    427  1.8.8.2  nathanw 	struct tty *tp = sc->sc_tty;
    428  1.8.8.2  nathanw 	int s;
    429  1.8.8.2  nathanw 
    430  1.8.8.2  nathanw 	(*tp->t_linesw->l_close)(tp, flag);
    431  1.8.8.2  nathanw 
    432  1.8.8.2  nathanw 	s = spltty();
    433  1.8.8.2  nathanw 	siomctl(sc, TIOCM_BREAK, DMBIC);
    434  1.8.8.2  nathanw #if 0 /* because unable to feed DTR signal */
    435  1.8.8.2  nathanw 	if ((tp->t_cflag & HUPCL)
    436  1.8.8.2  nathanw 	    || tp->t_wopen || (tp->t_state & TS_ISOPEN) == 0) {
    437  1.8.8.2  nathanw 		siomctl(sc, TIOCM_DTR, DMBIC);
    438  1.8.8.2  nathanw 		/* Yield CPU time to others for 1 second, then ... */
    439  1.8.8.2  nathanw 		siomctl(sc, TIOCM_DTR, DMBIS);
    440  1.8.8.2  nathanw 	}
    441  1.8.8.2  nathanw #endif
    442  1.8.8.2  nathanw 	splx(s);
    443  1.8.8.2  nathanw 	return ttyclose(tp);
    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 sioread(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_read)(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 siowrite(dev, uio, flag)
    460  1.8.8.2  nathanw 	dev_t dev;
    461  1.8.8.2  nathanw 	struct uio *uio;
    462  1.8.8.2  nathanw 	int flag;
    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_write)(tp, uio, flag);
    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 siopoll(dev, events, p)
    472  1.8.8.2  nathanw 	dev_t dev;
    473  1.8.8.2  nathanw 	int events;
    474  1.8.8.2  nathanw 	struct proc *p;
    475  1.8.8.2  nathanw {
    476  1.8.8.2  nathanw 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    477  1.8.8.2  nathanw 	struct tty *tp = sc->sc_tty;
    478  1.8.8.2  nathanw 
    479  1.8.8.2  nathanw 	return ((*tp->t_linesw->l_poll)(tp, events, p));
    480  1.8.8.2  nathanw }
    481  1.8.8.2  nathanw 
    482  1.8.8.2  nathanw int
    483  1.8.8.2  nathanw sioioctl(dev, cmd, data, flag, p)
    484  1.8.8.2  nathanw 	dev_t dev;
    485  1.8.8.2  nathanw 	u_long cmd;
    486  1.8.8.2  nathanw 	caddr_t data;
    487  1.8.8.2  nathanw 	int flag;
    488  1.8.8.2  nathanw 	struct proc *p;
    489  1.8.8.2  nathanw {
    490  1.8.8.2  nathanw 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    491  1.8.8.2  nathanw 	struct tty *tp = sc->sc_tty;
    492  1.8.8.2  nathanw 	int error;
    493  1.8.8.2  nathanw 
    494  1.8.8.2  nathanw 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
    495  1.8.8.2  nathanw 	if (error != EPASSTHROUGH)
    496  1.8.8.2  nathanw 		return error;
    497  1.8.8.2  nathanw 
    498  1.8.8.2  nathanw 	error = ttioctl(tp, cmd, data, flag, p);
    499  1.8.8.2  nathanw 	if (error != EPASSTHROUGH)
    500  1.8.8.2  nathanw 		return error;
    501  1.8.8.2  nathanw 
    502  1.8.8.2  nathanw 	/* the last resort for TIOC ioctl tranversing */
    503  1.8.8.2  nathanw 	switch (cmd) {
    504  1.8.8.2  nathanw 	case TIOCSBRK: /* Set the hardware into BREAK condition */
    505  1.8.8.2  nathanw 		siomctl(sc, TIOCM_BREAK, DMBIS);
    506  1.8.8.2  nathanw 		break;
    507  1.8.8.2  nathanw 	case TIOCCBRK: /* Clear the hardware BREAK condition */
    508  1.8.8.2  nathanw 		siomctl(sc, TIOCM_BREAK, DMBIC);
    509  1.8.8.2  nathanw 		break;
    510  1.8.8.2  nathanw 	case TIOCSDTR: /* Assert DTR signal */
    511  1.8.8.2  nathanw 		siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIS);
    512  1.8.8.2  nathanw 		break;
    513  1.8.8.2  nathanw 	case TIOCCDTR: /* Clear DTR signal */
    514  1.8.8.2  nathanw 		siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIC);
    515  1.8.8.2  nathanw 		break;
    516  1.8.8.2  nathanw 	case TIOCMSET: /* Set modem state replacing current one */
    517  1.8.8.2  nathanw 		siomctl(sc, *(int *)data, DMSET);
    518  1.8.8.2  nathanw 		break;
    519  1.8.8.2  nathanw 	case TIOCMGET: /* Return current modem state */
    520  1.8.8.2  nathanw 		*(int *)data = siomctl(sc, 0, DMGET);
    521  1.8.8.2  nathanw 		break;
    522  1.8.8.2  nathanw 	case TIOCMBIS: /* Set individual bits of modem state */
    523  1.8.8.2  nathanw 		siomctl(sc, *(int *)data, DMBIS);
    524  1.8.8.2  nathanw 		break;
    525  1.8.8.2  nathanw 	case TIOCMBIC: /* Clear individual bits of modem state */
    526  1.8.8.2  nathanw 		siomctl(sc, *(int *)data, DMBIC);
    527  1.8.8.2  nathanw 		break;
    528  1.8.8.2  nathanw 	case TIOCSFLAGS: /* Instruct how serial port behaves */
    529  1.8.8.2  nathanw 		sc->sc_flags = *(int *)data;
    530  1.8.8.2  nathanw 		break;
    531  1.8.8.2  nathanw 	case TIOCGFLAGS: /* Return current serial port state */
    532  1.8.8.2  nathanw 		*(int *)data = sc->sc_flags;
    533  1.8.8.2  nathanw 		break;
    534  1.8.8.2  nathanw 	default:
    535  1.8.8.2  nathanw 		return EPASSTHROUGH;
    536  1.8.8.2  nathanw 	}
    537  1.8.8.2  nathanw 	return 0;
    538  1.8.8.2  nathanw }
    539  1.8.8.2  nathanw 
    540  1.8.8.2  nathanw /* ARSGUSED */
    541  1.8.8.2  nathanw struct tty *
    542  1.8.8.2  nathanw siotty(dev)
    543  1.8.8.2  nathanw 	dev_t dev;
    544  1.8.8.2  nathanw {
    545  1.8.8.2  nathanw 	struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
    546  1.8.8.2  nathanw 
    547  1.8.8.2  nathanw 	return sc->sc_tty;
    548  1.8.8.2  nathanw }
    549  1.8.8.2  nathanw 
    550  1.8.8.2  nathanw /*--------------------  miscelleneous routine --------------------*/
    551  1.8.8.2  nathanw 
    552  1.8.8.2  nathanw /* EXPORT */ void
    553  1.8.8.2  nathanw setsioreg(sio, regno, val)
    554  1.8.8.2  nathanw 	struct sioreg *sio;
    555  1.8.8.2  nathanw 	int regno, val;
    556  1.8.8.2  nathanw {
    557  1.8.8.2  nathanw 	if (regno != 0)
    558  1.8.8.2  nathanw 		sio->sio_cmd = regno;	/* DELAY(); */
    559  1.8.8.2  nathanw 	sio->sio_cmd = val;		/* DELAY(); */
    560  1.8.8.2  nathanw }
    561  1.8.8.2  nathanw 
    562  1.8.8.2  nathanw /* EXPORT */ int
    563  1.8.8.2  nathanw getsiocsr(sio)
    564  1.8.8.2  nathanw 	struct sioreg *sio;
    565  1.8.8.2  nathanw {
    566  1.8.8.2  nathanw 	int val;
    567  1.8.8.2  nathanw 
    568  1.8.8.2  nathanw 	val = sio->sio_stat << 8;	/* DELAY(); */
    569  1.8.8.2  nathanw 	sio->sio_cmd = 1;		/* DELAY(); */
    570  1.8.8.2  nathanw 	val |= sio->sio_stat;		/* DELAY(); */
    571  1.8.8.2  nathanw 	return val;
    572  1.8.8.2  nathanw }
    573  1.8.8.2  nathanw 
    574  1.8.8.2  nathanw /*---------------------  console interface ----------------------*/
    575  1.8.8.2  nathanw 
    576  1.8.8.2  nathanw void syscnattach __P((int));
    577  1.8.8.2  nathanw int  syscngetc __P((dev_t));
    578  1.8.8.2  nathanw void syscnputc __P((dev_t, int));
    579  1.8.8.2  nathanw 
    580  1.8.8.2  nathanw struct consdev syscons = {
    581  1.8.8.2  nathanw 	NULL,
    582  1.8.8.2  nathanw 	NULL,
    583  1.8.8.2  nathanw 	syscngetc,
    584  1.8.8.2  nathanw 	syscnputc,
    585  1.8.8.2  nathanw 	nullcnpollc,
    586  1.8.8.2  nathanw 	NULL,
    587  1.8.8.2  nathanw 	NODEV,
    588  1.8.8.2  nathanw 	CN_REMOTE,
    589  1.8.8.2  nathanw };
    590  1.8.8.2  nathanw 
    591  1.8.8.2  nathanw /* EXPORT */ void
    592  1.8.8.2  nathanw syscnattach(channel)
    593  1.8.8.2  nathanw 	int channel;
    594  1.8.8.2  nathanw {
    595  1.8.8.2  nathanw /*
    596  1.8.8.2  nathanw  * Channel A is immediately initialized with 9600N1 right after cold
    597  1.8.8.2  nathanw  * boot/reset/poweron.  ROM monitor emits one line message on CH.A.
    598  1.8.8.2  nathanw  */
    599  1.8.8.2  nathanw 	struct sioreg *sio;
    600  1.8.8.2  nathanw 	sio = (struct sioreg *)0x51000000 + channel;
    601  1.8.8.2  nathanw 
    602  1.8.8.3  nathanw 	syscons.cn_dev = makedev(cdevsw_lookup_major(&siotty_cdevsw),
    603  1.8.8.3  nathanw 				 channel);
    604  1.8.8.2  nathanw 	cn_tab = &syscons;
    605  1.8.8.2  nathanw 
    606  1.8.8.2  nathanw 	setsioreg(sio, WR0, WR0_CHANRST);
    607  1.8.8.2  nathanw 	setsioreg(sio, WR2A, WR2_VEC86 | WR2_INTR_1);
    608  1.8.8.2  nathanw 	setsioreg(sio, WR2B, 0);
    609  1.8.8.2  nathanw 	setsioreg(sio, WR0, ch0_regs[WR0]);
    610  1.8.8.2  nathanw 	setsioreg(sio, WR4, ch0_regs[WR4]);
    611  1.8.8.2  nathanw 	setsioreg(sio, WR3, ch0_regs[WR3]);
    612  1.8.8.2  nathanw 	setsioreg(sio, WR5, ch0_regs[WR5]);
    613  1.8.8.2  nathanw 	setsioreg(sio, WR0, ch0_regs[WR0]);
    614  1.8.8.2  nathanw }
    615  1.8.8.2  nathanw 
    616  1.8.8.2  nathanw /* EXPORT */ int
    617  1.8.8.2  nathanw syscngetc(dev)
    618  1.8.8.2  nathanw 	dev_t dev;
    619  1.8.8.2  nathanw {
    620  1.8.8.2  nathanw 	struct sioreg *sio;
    621  1.8.8.2  nathanw 	int s, c;
    622  1.8.8.2  nathanw 
    623  1.8.8.2  nathanw 	sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
    624  1.8.8.2  nathanw 	s = splhigh();
    625  1.8.8.2  nathanw 	while ((getsiocsr(sio) & RR_RXRDY) == 0)
    626  1.8.8.2  nathanw 		;
    627  1.8.8.2  nathanw 	c = sio->sio_data;
    628  1.8.8.2  nathanw 	splx(s);
    629  1.8.8.2  nathanw 
    630  1.8.8.2  nathanw 	return c;
    631  1.8.8.2  nathanw }
    632  1.8.8.2  nathanw 
    633  1.8.8.2  nathanw /* EXPORT */ void
    634  1.8.8.2  nathanw syscnputc(dev, c)
    635  1.8.8.2  nathanw 	dev_t dev;
    636  1.8.8.2  nathanw 	int c;
    637  1.8.8.2  nathanw {
    638  1.8.8.2  nathanw 	struct sioreg *sio;
    639  1.8.8.2  nathanw 	int s;
    640  1.8.8.2  nathanw 
    641  1.8.8.2  nathanw 	sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
    642  1.8.8.2  nathanw 	s = splhigh();
    643  1.8.8.2  nathanw 	while ((getsiocsr(sio) & RR_TXRDY) == 0)
    644  1.8.8.2  nathanw 		;
    645  1.8.8.2  nathanw 	sio->sio_cmd = WR0_RSTPEND;
    646  1.8.8.2  nathanw 	sio->sio_data = c;
    647  1.8.8.2  nathanw 	splx(s);
    648  1.8.8.2  nathanw }
    649