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