summaryrefslogtreecommitdiff
path: root/sys/arch/aviion/dev/dart.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/aviion/dev/dart.c')
-rw-r--r--sys/arch/aviion/dev/dart.c1039
1 files changed, 1039 insertions, 0 deletions
diff --git a/sys/arch/aviion/dev/dart.c b/sys/arch/aviion/dev/dart.c
new file mode 100644
index 00000000000..ccbca07b568
--- /dev/null
+++ b/sys/arch/aviion/dev/dart.c
@@ -0,0 +1,1039 @@
+/* $OpenBSD: dart.c,v 1.1 2006/05/09 18:13:32 miod Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/syslog.h>
+
+#include <machine/autoconf.h>
+#include <machine/conf.h>
+#include <machine/cpu.h>
+
+#include <dev/cons.h>
+
+#include <machine/av400.h>
+#include <aviion/dev/sysconreg.h>
+#include <aviion/dev/dartreg.h>
+#include <aviion/dev/dartvar.h>
+
+#ifdef DDB
+#include <ddb/db_var.h>
+#endif
+
+struct cfdriver dart_cd = {
+ NULL, "dart", DV_TTY
+};
+
+/* console is on the first port */
+#define CONS_PORT A_PORT
+#ifdef USE_PROM_CONSOLE
+#define dartcn_sv sc->sc_sv_reg_storage
+#else
+struct dart_sv_reg dartcn_sv;
+#endif
+
+/* prototypes */
+cons_decl(dart);
+int dart_speed(int);
+struct tty *darttty(dev_t);
+void dartstart(struct tty *);
+int dartmctl(struct dartsoftc *, int, int, int);
+int dartparam(struct tty *, struct termios *);
+void dartmodemtrans(struct dartsoftc *, unsigned int, unsigned int);
+void dartrint(struct dartsoftc *, int);
+void dartxint(struct dartsoftc *, int);
+
+/*
+ * DUART registers are mapped as the least-significant byte of 32-bit
+ * addresses. The following macros hide this.
+ */
+
+#define dart_read(sc, reg) \
+ bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, 3 + ((reg) << 2))
+#define dart_write(sc, reg, val) \
+ bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, 3 + ((reg) << 2), (val))
+
+#define DART_CHIP(dev) (minor(dev) >> 1)
+#define DART_PORT(dev) (minor(dev) & 1)
+
+void
+dart_common_attach(struct dartsoftc *sc)
+{
+ if (sc->sc_console) {
+ sc->sc_sv_reg = &dartcn_sv;
+
+ if (A_PORT != CONS_PORT) {
+ sc->sc_sv_reg->sv_mr1[A_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[A_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[A_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[A_PORT] = TXEN | RXEN;
+ sc->sc_sv_reg->sv_opr |= OPDTRA | OPRTSA;
+ } else {
+ sc->sc_sv_reg->sv_mr1[B_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[B_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[B_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[B_PORT] = TXEN | RXEN;
+ sc->sc_sv_reg->sv_opr |= OPDTRB | OPRTSB;
+ }
+ } else {
+ sc->sc_sv_reg = &sc->sc_sv_reg_storage;
+
+ sc->sc_sv_reg->sv_mr1[A_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[A_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[A_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[A_PORT] = TXEN | RXEN;
+
+ sc->sc_sv_reg->sv_mr1[B_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[B_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[B_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[B_PORT] = TXEN | RXEN;
+
+ sc->sc_sv_reg->sv_opr = OPDTRA | OPRTSA | OPDTRB | OPRTSB;
+
+ /* Start out with Tx and RX interrupts disabled */
+ /* Enable input port change interrupt */
+ sc->sc_sv_reg->sv_imr = IIPCHG;
+ }
+
+ /* reset port a */
+ if (sc->sc_console == 0 || CONS_PORT != A_PORT) {
+ dart_write(sc, DART_CRA, RXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, TXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, ERRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, BRKINTRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, MRRESET | TXDIS | RXDIS);
+#if 0
+ DELAY_CR;
+#endif
+
+ dart_write(sc, DART_MR1A, sc->sc_sv_reg->sv_mr1[A_PORT]);
+ dart_write(sc, DART_MR2A, sc->sc_sv_reg->sv_mr2[A_PORT]);
+ dart_write(sc, DART_CSRA, sc->sc_sv_reg->sv_csr[A_PORT]);
+ dart_write(sc, DART_CRA, sc->sc_sv_reg->sv_cr[A_PORT]);
+ }
+
+ /* reset port b */
+ if (sc->sc_console == 0 || CONS_PORT != B_PORT) {
+ dart_write(sc, DART_CRB, RXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, TXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, ERRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, BRKINTRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, MRRESET | TXDIS | RXDIS);
+#if 0
+ DELAY_CR;
+#endif
+
+ dart_write(sc, DART_MR1B, sc->sc_sv_reg->sv_mr1[B_PORT]);
+ dart_write(sc, DART_MR2B, sc->sc_sv_reg->sv_mr2[B_PORT]);
+ dart_write(sc, DART_CSRB, sc->sc_sv_reg->sv_csr[B_PORT]);
+ dart_write(sc, DART_CRB, sc->sc_sv_reg->sv_cr[B_PORT]);
+ }
+
+ /* initialize common register of a DUART */
+ dart_write(sc, DART_OPRS, sc->sc_sv_reg->sv_opr);
+
+#if 0
+ dart_write(sc, DART_CTUR, SLCTIM >> 8);
+ dart_write(sc, DART_CTLR, SLCTIM & 0xff);
+ dart_write(sc, DART_ACR, BDSET2 | CCLK16 | IPDCDIB | IPDCDIA);
+#endif
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+#if 0
+ dart_write(sc, DART_OPCR, OPSET);
+#endif
+#if 0
+ dart_write(sc, DART_IVR, SYSCON_VECT + SYSCV_SCC);
+#endif
+
+ sc->sc_dart[A_PORT].tty = sc->sc_dart[B_PORT].tty = NULL;
+ sc->sc_dart[A_PORT].dart_swflags = sc->sc_dart[B_PORT].dart_swflags = 0;
+ if (sc->sc_console)
+ sc->sc_dart[CONS_PORT].dart_swflags |= TIOCFLAG_SOFTCAR;
+
+ printf("\n");
+}
+
+/* speed tables */
+const struct dart_s {
+ int kspeed;
+ int dspeed;
+} dart_speeds[] = {
+ { B0, 0 }, /* 0 baud, special HUP condition */
+ { B50, NOBAUD }, /* 50 baud, not implemented */
+ { B75, BD75 }, /* 75 baud */
+ { B110, BD110 }, /* 110 baud */
+ { B134, BD134 }, /* 134.5 baud */
+ { B150, BD150 }, /* 150 baud */
+ { B200, NOBAUD }, /* 200 baud, not implemented */
+ { B300, BD300 }, /* 300 baud */
+ { B600, BD600 }, /* 600 baud */
+ { B1200, BD1200 }, /* 1200 baud */
+ { B1800, BD1800 }, /* 1800 baud */
+ { B2400, BD2400 }, /* 2400 baud */
+ { B4800, BD4800 }, /* 4800 baud */
+ { B9600, BD9600 }, /* 9600 baud */
+ { B19200, BD19200 }, /* 19200 baud */
+ { -1, NOBAUD }, /* anything more is uncivilized */
+};
+
+int
+dart_speed(int speed)
+{
+ const struct dart_s *ds;
+
+ for (ds = dart_speeds; ds->kspeed != -1; ds++)
+ if (ds->kspeed == speed)
+ return ds->dspeed;
+
+ return NOBAUD;
+}
+
+struct tty *
+darttty(dev_t dev)
+{
+ u_int port, chip;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ if (dart_cd.cd_ndevs <= chip || port >= NDARTPORTS)
+ return (NULL);
+
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ if (sc == NULL)
+ return (NULL);
+
+ return sc->sc_dart[port].tty;
+}
+
+void
+dartstart(struct tty *tp)
+{
+ struct dartsoftc *sc;
+ dev_t dev;
+ int s;
+ u_int port, chip;
+ int c, tries;
+ bus_addr_t ptaddr;
+
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ return;
+
+ dev = tp->t_dev;
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ s = spltty();
+
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto bail;
+
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ if (tp->t_outq.c_cc == 0)
+ goto bail;
+ }
+
+ tp->t_state |= TS_BUSY;
+ while (tp->t_outq.c_cc != 0) {
+
+ /* load transmitter until it is full */
+ for (tries = 10000; tries != 0; tries --)
+ if (dart_read(sc, ptaddr + DART_SRA) & TXRDY)
+ break;
+
+ if (tries == 0) {
+ timeout_add(&tp->t_rstrt_to, 1);
+ tp->t_state |= TS_TIMEOUT;
+ break;
+ } else {
+ c = getc(&tp->t_outq);
+
+ dart_write(sc, ptaddr + DART_TBA, c & 0xff);
+
+ sc->sc_sv_reg->sv_imr |=
+ port == A_PORT ? ITXRDYA : ITXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+ }
+ }
+ tp->t_state &= ~TS_BUSY;
+
+bail:
+ splx(s);
+}
+
+int
+dartstop(struct tty *tp, int flag)
+{
+ int s;
+
+ s = spltty();
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * To be called at spltty - tty already locked.
+ * Returns status of carrier.
+ */
+int
+dartmctl(struct dartsoftc *sc, int port, int flags, int how)
+{
+ int newflags, flagsmask;
+ struct dart_info *dart;
+ int s;
+
+ dart = &sc->sc_dart[port];
+
+ s = spltty();
+
+ flagsmask = port == A_PORT ? (OPDTRA | OPRTSA) : (OPDTRB | OPRTSB);
+ newflags = (flags & TIOCM_DTR ? (OPDTRA | OPDTRB) : 0) |
+ (flags & TIOCM_RTS ? (OPRTSA | OPRTSB) : 0);
+ newflags &= flagsmask; /* restrict to the port we are acting on */
+
+ switch (how) {
+ case DMSET:
+ dart_write(sc, DART_OPRS, newflags);
+ dart_write(sc, DART_OPRR, ~newflags);
+ /* only replace the sv_opr bits for the port we are acting on */
+ sc->sc_sv_reg->sv_opr &= ~flagsmask;
+ sc->sc_sv_reg->sv_opr |= newflags;
+ break;
+ case DMBIS:
+ dart_write(sc, DART_OPRS, newflags);
+ sc->sc_sv_reg->sv_opr |= newflags;
+ break;
+ case DMBIC:
+ dart_write(sc, DART_OPRR, newflags);
+ sc->sc_sv_reg->sv_opr &= ~newflags;
+ break;
+ case DMGET:
+ flags = 0;
+ if (port == A_PORT) {
+ if (sc->sc_sv_reg->sv_opr & OPDTRA)
+ flags |= TIOCM_DTR;
+ if (sc->sc_sv_reg->sv_opr & OPRTSA)
+ flags |= TIOCM_RTS;
+ } else {
+ if (sc->sc_sv_reg->sv_opr & OPDTRB)
+ flags |= TIOCM_DTR;
+ if (sc->sc_sv_reg->sv_opr & OPRTSB)
+ flags |= TIOCM_RTS;
+ }
+ break;
+ }
+
+ splx(s);
+ return (flags);
+}
+
+int
+dartioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ int error;
+ u_int port, chip;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (tp == NULL)
+ return (ENXIO);
+
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return(error);
+
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return(error);
+
+ switch (cmd) {
+ case TIOCSBRK:
+ case TIOCCBRK:
+ break;
+ case TIOCSDTR:
+ (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMBIS);
+ break;
+ case TIOCCDTR:
+ (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMBIC);
+ break;
+ case TIOCMSET:
+ (void)dartmctl(sc, port, *(int *) data, DMSET);
+ break;
+ case TIOCMBIS:
+ (void)dartmctl(sc, port, *(int *) data, DMBIS);
+ break;
+ case TIOCMBIC:
+ (void)dartmctl(sc, port, *(int *) data, DMBIC);
+ break;
+ case TIOCMGET:
+ *(int *)data = dartmctl(sc, port, 0, DMGET);
+ break;
+ case TIOCGFLAGS:
+ *(int *)data = dart->dart_swflags;
+ break;
+ case TIOCSFLAGS:
+ error = suser(p, 0);
+ if (error != 0)
+ return (EPERM);
+
+ dart->dart_swflags = *(int *)data;
+ dart->dart_swflags &= /* only allow valid flags */
+ (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
+ break;
+ default:
+ return (ENOTTY);
+ }
+
+ return (0);
+}
+
+int
+dartparam(struct tty *tp, struct termios *t)
+{
+ int flags;
+ u_int port, chip;
+ int speeds;
+ unsigned char mr1, mr2;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ dev_t dev;
+ bus_addr_t ptaddr;
+
+ dev = tp->t_dev;
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+
+ flags = tp->t_flags;
+
+ /* Reset to make global changes*/
+ /* disable Tx and Rx */
+
+ if (sc->sc_console == 0 || CONS_PORT != port) {
+ if (port == A_PORT)
+ sc->sc_sv_reg->sv_imr &= ~(ITXRDYA | IRXRDYA);
+ else
+ sc->sc_sv_reg->sv_imr &= ~(ITXRDYB | IRXRDYB);
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+
+ /* hang up on zero baud rate */
+ if (tp->t_ispeed == 0) {
+ dartmctl(sc, port, HUPCL, DMSET);
+ return (0);
+ } else {
+ /* set baudrate */
+ speeds = dart_speed(tp->t_ispeed);
+ if (speeds == NOBAUD)
+ speeds = sc->sc_sv_reg->sv_csr[port];
+ dart_write(sc, ptaddr + DART_CSRA, speeds);
+ sc->sc_sv_reg->sv_csr[port] = speeds;
+ }
+
+ /* get saved mode registers and clear set up parameters */
+ mr1 = sc->sc_sv_reg->sv_mr1[port];
+ mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
+
+ mr2 = sc->sc_sv_reg->sv_mr2[port];
+ mr2 &= ~SBMASK;
+
+ /* set up character size */
+ switch (t->c_cflag & CSIZE) {
+ case CL8:
+ mr1 |= CL8;
+ break;
+ case CL7:
+ mr1 |= CL7;
+ break;
+ case CL6:
+ mr1 |= CL6;
+ break;
+ case CL5:
+ mr1 |= CL5;
+ break;
+ }
+
+ /* set up stop bits */
+ if (tp->t_ospeed == B110)
+ mr2 |= SB2;
+ else
+ mr2 |= SB1;
+
+ /* set up parity */
+ if (t->c_cflag & PARENB) {
+ mr1 |= PAREN;
+ if (t->c_cflag & PARODD)
+ mr1 |= ODDPAR;
+ else
+ mr1 |= EVENPAR;
+ } else
+ mr1 |= PARDIS;
+
+ if (sc->sc_sv_reg->sv_mr1[port] != mr1 ||
+ sc->sc_sv_reg->sv_mr2[port] != mr2) {
+ /* write mode registers to duart */
+ dart_write(sc, ptaddr + DART_CRA, MRRESET);
+ dart_write(sc, ptaddr + DART_MR1A, mr1);
+ dart_write(sc, ptaddr + DART_MR2A, mr2);
+
+ /* save changed mode registers */
+ sc->sc_sv_reg->sv_mr1[port] = mr1;
+ sc->sc_sv_reg->sv_mr2[port] = mr2;
+ }
+ }
+
+ /* enable transmitter? */
+ if (tp->t_state & TS_BUSY) {
+ sc->sc_sv_reg->sv_imr |= port == A_PORT ? ITXRDYA : ITXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+ }
+
+ /* re-enable the receiver */
+#if 0
+ DELAY_CR;
+#endif
+ sc->sc_sv_reg->sv_imr |= port == A_PORT ? IRXRDYA : IRXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+
+ return (0);
+}
+
+void
+dartmodemtrans(struct dartsoftc *sc, unsigned int ip, unsigned int ipcr)
+{
+ unsigned int dcdstate;
+ struct tty *tp;
+ int port;
+ struct dart_info *dart;
+
+ /* input is inverted at port!!! */
+ if (ipcr & IPCRDCDA) {
+ port = A_PORT;
+ dcdstate = !(ip & IPDCDA);
+ } else if (ipcr & IPCRDCDB) {
+ port = B_PORT;
+ dcdstate = !(ip & IPDCDB);
+ } else {
+#ifdef DIAGNOSTIC
+ printf("dartmodemtrans: unknown transition ip=0x%x ipcr=0x%x\n",
+ ip, ipcr);
+#endif
+ return;
+ }
+
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+ if (tp != NULL)
+ ttymodem(tp, dcdstate);
+}
+
+int
+dartopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ int s;
+ u_int port, chip;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ struct tty *tp;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ if (dart_cd.cd_ndevs <= chip || port >= NDARTPORTS)
+ return (ENODEV);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ if (sc == NULL)
+ return (ENODEV);
+ dart = &sc->sc_dart[port];
+
+ s = spltty();
+ if (dart->tty != NULL)
+ tp = dart->tty;
+ else
+ tp = dart->tty = ttymalloc();
+
+ tp->t_oproc = dartstart;
+ tp->t_param = dartparam;
+ tp->t_dev = dev;
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+
+ if (tp->t_ispeed == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = B9600;
+ if (sc->sc_console && port == CONS_PORT) {
+ /* console is 8N1 */
+ tp->t_cflag = (CREAD | CS8 | HUPCL);
+ } else {
+ tp->t_cflag = TTYDEF_CFLAG;
+ }
+ }
+
+ if (dart->dart_swflags & TIOCFLAG_CLOCAL)
+ tp->t_cflag |= CLOCAL;
+ if (dart->dart_swflags & TIOCFLAG_CRTSCTS)
+ tp->t_cflag |= CRTSCTS;
+ if (dart->dart_swflags & TIOCFLAG_MDMBUF)
+ tp->t_cflag |= MDMBUF;
+
+ dartparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMSET);
+ tp->t_state |= TS_CARR_ON;
+ } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+ splx(s);
+ return (EBUSY);
+ }
+
+ /*
+ * Reset the tty pointer, as there could have been a dialout
+ * use of the tty with a dialin open waiting.
+ */
+ tp->t_dev = dev;
+ splx(s);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+int
+dartclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ u_int port, chip;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+
+ return (0);
+}
+
+int
+dartread(dev_t dev, struct uio *uio, int flag)
+{
+ u_int port, chip;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (tp == NULL)
+ return (ENXIO);
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+dartwrite(dev_t dev, struct uio *uio, int flag)
+{
+ u_int port, chip;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (tp == NULL)
+ return (ENXIO);
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+void
+dartrint(struct dartsoftc *sc, int port)
+{
+ struct tty *tp;
+ unsigned char data, sr;
+ struct dart_info *dart;
+ bus_addr_t ptaddr;
+
+ dart = &sc->sc_dart[port];
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+ tp = dart->tty;
+
+ /* read status reg */
+ while ((sr = dart_read(sc, ptaddr + DART_SRA)) & RXRDY) {
+ /* read data and reset receiver */
+ data = dart_read(sc, ptaddr + DART_RBA);
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 &&
+ (sc->sc_console == 0 || CONS_PORT != port)) {
+ return;
+ }
+
+ if (sr & RBRK) {
+ /* clear break state */
+ dart_write(sc, ptaddr + DART_CRA, BRKINTRESET);
+ DELAY_CR;
+ dart_write(sc, ptaddr + DART_CRA, ERRRESET);
+
+#if defined(DDB)
+ if (db_console != 0 &&
+ sc->sc_console && port == CONS_PORT)
+ Debugger();
+#endif
+ } else {
+ if (sr & (FRERR | PERR | ROVRN)) { /* errors */
+ if (sr & ROVRN)
+ log(LOG_WARNING, "%s port %c: "
+ "receiver overrun\n",
+ sc->sc_dev.dv_xname, 'A' + port);
+ if (sr & FRERR)
+ log(LOG_WARNING, "%s port %c: "
+ "framing error\n",
+ sc->sc_dev.dv_xname, 'A' + port);
+ if (sr & PERR)
+ log(LOG_WARNING, "%s port %c: "
+ "parity error\n",
+ sc->sc_dev.dv_xname, 'A' + port);
+ /* clear error state */
+ dart_write(sc, ptaddr + DART_CRA, ERRRESET);
+ } else {
+ /* no errors */
+ (*linesw[tp->t_line].l_rint)(data,tp);
+ }
+ }
+ }
+}
+
+void
+dartxint(struct dartsoftc *sc, int port)
+{
+ struct tty *tp;
+ struct dart_info *dart;
+
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
+ goto out;
+
+ if (tp->t_state & TS_BUSY) {
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+ dartstart(tp);
+ if (tp->t_state & TS_BUSY) {
+ /* do not disable transmitter, yet */
+ return;
+ }
+ }
+out:
+
+ /* disable transmitter */
+ sc->sc_sv_reg->sv_imr &= port == A_PORT ? ~ITXRDYA : ~ITXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+}
+
+int
+dartintr(void *arg)
+{
+ struct dartsoftc *sc = arg;
+ unsigned char isr, imr;
+ int port;
+
+ /* read interrupt status register and mask with imr */
+ isr = dart_read(sc, DART_ISR);
+ imr = sc->sc_sv_reg->sv_imr;
+
+ if ((isr & imr) == 0) {
+ /*
+ * We got an interrupt on a disabled condition (such as TX
+ * ready change on a disabled port). This should not happen,
+ * but we have to claim the interrupt anyway.
+ */
+#ifdef DIAGNOSTIC
+ printf("%s: spurious interrupt, isr %x imr %x\n",
+ sc->sc_dev.dv_xname, isr, imr);
+#endif
+ return (1);
+ }
+ isr &= imr;
+
+ if (isr & IIPCHG) {
+ unsigned int ip, ipcr;
+
+ ip = dart_read(sc, DART_IP);
+ ipcr = dart_read(sc, DART_IPCR);
+ dartmodemtrans(sc, ip, ipcr);
+ return (1);
+ }
+
+ if (isr & (IRXRDYA | ITXRDYA))
+ port = 0;
+#ifdef DIAGNOSTIC
+ else if ((isr & (IRXRDYB | ITXRDYB)) == 0) {
+ printf("%s: spurious interrupt, isr %x\n",
+ sc->sc_dev.dv_xname, isr);
+ return (1); /* claim it anyway */
+ }
+#endif
+ else
+ port = 1;
+
+ if (isr & (IRXRDYA | IRXRDYB))
+ dartrint(sc, port);
+ if (isr & (ITXRDYA | ITXRDYB))
+ dartxint(sc, port);
+ if (isr & (port == A_PORT ? IBRKA : IBRKB))
+ dart_write(sc, port == A_PORT ? DART_CRA : DART_CRB,
+ BRKINTRESET);
+
+ return (1);
+}
+
+/*
+ * Console interface routines.
+#ifdef USE_PROM_CONSOLE
+ * Since we select the actual console after all devices are attached,
+ * we can safely pick the appropriate softc and use its information.
+#endif
+ */
+
+#ifdef USE_PROM_CONSOLE
+#define dart_cnread(reg) dart_read(sc, (reg))
+#define dart_cnwrite(reg, val) dart_write(sc, (reg), (val))
+#else
+#define dart_cnread(reg) \
+ *(volatile u_int8_t *)(DART_BASE + 3 + ((reg) << 2))
+#define dart_cnwrite(reg, val) \
+ *(volatile u_int8_t *)(DART_BASE + 3 + ((reg) << 2)) = (val)
+#endif
+
+void
+dartcnprobe(struct consdev *cp)
+{
+ int maj;
+
+ if (badaddr(DART_BASE, 4) != 0)
+ return;
+
+#ifdef USE_PROM_CONSOLE
+ /* do not attach as console if dart has been disabled */
+ if (dart_cd.cd_ndevs == 0 || dart_cd.cd_devs[0] == NULL)
+ return;
+#endif
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == dartopen)
+ break;
+ if (maj == nchrdev)
+ return;
+
+ cp->cn_dev = makedev(maj, CONS_PORT);
+ cp->cn_pri = CN_NORMAL;
+}
+
+void
+dartcninit(cp)
+ struct consdev *cp;
+{
+#ifndef USE_PROM_CONSOLE
+ dartcn_sv.sv_mr1[CONS_PORT] = PARDIS | RXRTS | CL8;
+ dartcn_sv.sv_mr2[CONS_PORT] = /* TXCTS | */ SB1;
+ dartcn_sv.sv_csr[CONS_PORT] = BD9600;
+ dartcn_sv.sv_cr[CONS_PORT] = TXEN | RXEN;
+ dartcn_sv.sv_opr = CONS_PORT == A_PORT ? (OPDTRA | OPRTSA) :
+ (OPDTRB | OPRTSB);
+ dartcn_sv.sv_imr = IIPCHG;
+
+ dart_cnwrite(DART_CRA, RXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, TXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, ERRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, BRKINTRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, MRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+
+ dart_cnwrite(DART_MR1A, dartcn_sv.sv_mr1[CONS_PORT]);
+ dart_cnwrite(DART_MR2A, dartcn_sv.sv_mr2[CONS_PORT]);
+ dart_cnwrite(DART_CSRA, dartcn_sv.sv_csr[CONS_PORT]);
+ dart_cnwrite(DART_CRA, dartcn_sv.sv_cr[CONS_PORT]);
+
+ dart_cnwrite(DART_OPRS, dartcn_sv.sv_opr);
+
+ dart_cnwrite(DART_IMR, dartcn_sv.sv_imr);
+#endif
+}
+
+void
+dartcnputc(dev_t dev, int c)
+{
+#ifdef USE_PROM_CONSOLE
+ struct dartsoftc *sc;
+#endif
+ int s;
+ u_int port;
+ bus_addr_t ptaddr;
+
+#ifdef USE_PROM_CONSOLE
+ sc = (struct dartsoftc *)dart_cd.cd_devs[0];
+ port = DART_PORT(dev);
+#else
+ port = CONS_PORT;
+#endif
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ s = spltty();
+
+ /* inhibit interrupts on the chip */
+ dart_cnwrite(DART_IMR, dartcn_sv.sv_imr &
+ (CONS_PORT == A_PORT ? ~ITXRDYA : ~ITXRDYB));
+ /* make sure transmitter is enabled */
+#if 0
+ DELAY_CR;
+#endif
+ dart_cnwrite(ptaddr + DART_CRA, TXEN);
+
+ while ((dart_cnread(ptaddr + DART_SRA) & TXRDY) == 0)
+ ;
+ dart_cnwrite(ptaddr + DART_TBA, c);
+
+ /* wait for transmitter to empty */
+ while ((dart_cnread(ptaddr + DART_SRA) & TXEMT) == 0)
+ ;
+
+ /* restore the previous state */
+ dart_cnwrite(DART_IMR, dartcn_sv.sv_imr);
+#if 0
+ DELAY_CR;
+#endif
+ dart_cnwrite(ptaddr + DART_CRA, dartcn_sv.sv_cr[0]);
+
+ splx(s);
+}
+
+int
+dartcngetc(dev_t dev)
+{
+#ifdef USE_PROM_CONSOLE
+ struct dartsoftc *sc;
+#endif
+ unsigned char sr; /* status reg of port a/b */
+ u_char c; /* received character */
+ int s;
+ u_int port;
+ bus_addr_t ptaddr;
+
+#ifdef USE_PROM_CONSOLE
+ sc = (struct dartsoftc *)dart_cd.cd_devs[0];
+ port = DART_PORT(dev);
+#else
+ port = CONS_PORT;
+#endif
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ s = spltty();
+
+ /* enable receiver */
+ dart_cnwrite(ptaddr + DART_CRA, RXEN);
+
+ for (;;) {
+ /* read status reg */
+ sr = dart_cnread(ptaddr + DART_SRA);
+
+ /* receiver interrupt handler*/
+ if (sr & RXRDY) {
+ /* read character from port */
+ c = dart_cnread(ptaddr + DART_RBA);
+
+ /* check break condition */
+ if (sr & RBRK) {
+ /* clear break state */
+ dart_cnwrite(ptaddr + DART_CRA, BRKINTRESET);
+ DELAY_CR;
+ dart_cnwrite(ptaddr + DART_CRA, ERRRESET);
+ break;
+ }
+
+ if (sr & (FRERR | PERR | ROVRN)) {
+ /* clear error state */
+ dart_cnwrite(ptaddr + DART_CRA, ERRRESET);
+ } else {
+ break;
+ }
+ }
+ }
+ splx(s);
+
+ return ((int)c);
+}