summaryrefslogtreecommitdiff
path: root/sys/arch/vax/vxt
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/vax/vxt')
-rw-r--r--sys/arch/vax/vxt/if_ze_vxtbus.c95
-rw-r--r--sys/arch/vax/vxt/qsc.c1078
-rw-r--r--sys/arch/vax/vxt/qsckbd.c290
-rw-r--r--sys/arch/vax/vxt/qscms.c167
-rw-r--r--sys/arch/vax/vxt/qscreg.h173
-rw-r--r--sys/arch/vax/vxt/qscvar.h115
-rw-r--r--sys/arch/vax/vxt/vxtbus.c156
-rw-r--r--sys/arch/vax/vxt/vxtbusvar.h28
8 files changed, 2102 insertions, 0 deletions
diff --git a/sys/arch/vax/vxt/if_ze_vxtbus.c b/sys/arch/vax/vxt/if_ze_vxtbus.c
new file mode 100644
index 00000000000..ee4e4ed08e1
--- /dev/null
+++ b/sys/arch/vax/vxt/if_ze_vxtbus.c
@@ -0,0 +1,95 @@
+/* $OpenBSD: if_ze_vxtbus.c,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/*
+ * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/nexus.h>
+
+#include <vax/if/sgecreg.h>
+#include <vax/if/sgecvar.h>
+
+#include <vax/vxt/vxtbusvar.h>
+
+int ze_vxt_match(struct device *, void *, void *);
+void ze_vxt_attach(struct device *, struct device *, void *);
+
+struct cfattach ze_vxtbus_ca = {
+ sizeof(struct ze_softc), ze_vxt_match, ze_vxt_attach
+};
+
+int
+ze_vxt_match(struct device *parent, void *vcf, void *aux)
+{
+ struct bp_conf *bp = aux;
+
+ if (strcmp(bp->type, "sgec") == 0)
+ return (1);
+ return (0);
+}
+
+void
+ze_vxt_attach(struct device *parent, struct device *self, void *aux)
+{
+ extern struct vax_bus_dma_tag vax_bus_dma_tag;
+ struct ze_softc *sc = (void *)self;
+ int *ea, i;
+
+ /*
+ * Map in SGEC registers.
+ */
+ sc->sc_ioh = vax_map_physmem(SGECADDR_VXT, 1);
+ sc->sc_iot = 0; /* :-) */
+ sc->sc_dmat = &vax_bus_dma_tag;
+
+ sc->sc_intvec = VXT_INTRVEC;
+ vxtbus_intr_establish(self->dv_xname, IPL_NET,
+ (int (*)(void *))sgec_intr, sc);
+
+ /*
+ * Map in, read and release ethernet rom address.
+ */
+ ea = (int *)vax_map_physmem(NISA_ROM_VXT, 1);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->sc_ac.ac_enaddr[i] = ea[i] & 0xff;
+ vax_unmap_physmem((vaddr_t)ea, 1);
+
+ sgec_attach(sc);
+}
diff --git a/sys/arch/vax/vxt/qsc.c b/sys/arch/vax/vxt/qsc.c
new file mode 100644
index 00000000000..ce8a1e65bfd
--- /dev/null
+++ b/sys/arch/vax/vxt/qsc.c
@@ -0,0 +1,1078 @@
+/* $OpenBSD: qsc.c,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * 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 <sys/conf.h>
+
+#include <machine/bus.h>
+#include <machine/nexus.h>
+#include <machine/sid.h>
+
+#include <dev/cons.h>
+
+#include <vax/vxt/vxtbusvar.h>
+
+#include <vax/vxt/qscreg.h>
+#include <vax/vxt/qscvar.h>
+
+#ifdef DDB
+#include <machine/cpu.h>
+#include <ddb/db_var.h>
+#endif
+
+#include "qsckbd.h"
+#include "qscms.h"
+
+struct cfdriver qsc_cd = {
+ NULL, "qsc", DV_TTY
+};
+
+/* console storage */
+struct qsc_sv_reg qsccn_sv;
+
+/* prototypes */
+cdev_decl(qsc);
+cons_decl(qsc);
+int qscintr(void *);
+int qscparam(struct tty *, struct termios *);
+void qscrint(struct qscsoftc *, u_int);
+int qscspeed(int);
+void qscstart(struct tty *);
+struct tty *qsctty(dev_t);
+void qscxint(struct qscsoftc *, u_int);
+
+/*
+ * Registers are mapped as the least-significant byte of 32-bit
+ * addresses. The following macros hide this.
+ */
+
+#define qsc_readp(sc, reg) \
+ bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, 4 * (reg))
+#define qsc_read(sc, line, reg) \
+ bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, \
+ (sc)->sc_regaddr[line][reg])
+#define qsc_writep(sc, reg, val) \
+ bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, 4 * (reg), (val))
+#define qsc_write(sc, line, reg, val) \
+ bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, \
+ (sc)->sc_regaddr[line][reg], (val))
+
+#define SC_LINE(dev) (minor(dev))
+
+/*
+ * Attachment glue.
+ */
+
+int qsc_match(struct device *parent, void *self, void *aux);
+void qsc_attach(struct device *parent, struct device *self, void *aux);
+int qsc_print(void *, const char *);
+
+struct cfattach qsc_ca = {
+ sizeof(struct qscsoftc), qsc_match, qsc_attach
+};
+
+int
+qsc_match(struct device *parent, void *cf, void *aux)
+{
+ struct bp_conf *bp = aux;
+
+ if (strcmp(bp->type, qsc_cd.cd_name) == 0)
+ return (1);
+ return (0);
+}
+
+void
+qsc_attach(struct device *parent, struct device *self, void *aux)
+{
+ extern struct vax_bus_space vax_mem_bus_space;
+ struct qscsoftc *sc = (struct qscsoftc *)self;
+ bus_space_handle_t ioh;
+ u_int line, pair, reg;
+#if NQSCKBD > 0 || NQSCMS > 0
+ struct qsc_attach_args qa;
+#endif
+
+ sc->sc_iot = &vax_mem_bus_space;
+ if (bus_space_map(sc->sc_iot, QSCADDR, VAX_NBPG, 0, &ioh) != 0) {
+ printf(": can't map registers!\n");
+ return;
+ }
+ sc->sc_ioh = ioh;
+
+ if (cn_tab->cn_putc == qsccnputc) {
+ sc->sc_console = 1;
+ printf(": console");
+ }
+
+ /*
+ * Initialize line-specific data (register addresses)
+ */
+
+ for (line = 0; line < SC_NLINES; line++) {
+ sc->sc_regaddr[line][SC_MR] = line * 8 + SC_MRA;
+ sc->sc_regaddr[line][SC_CSR] = line * 8 + SC_CSRA;
+ sc->sc_regaddr[line][SC_CR] = line * 8 + SC_CRA;
+ sc->sc_regaddr[line][SC_TXFIFO] = line * 8 + SC_TXFIFOA;
+
+ sc->sc_regaddr[line][SC_IOPCR] = (line < 2 ? 0 : 0x10) +
+ (line & 1) + SC_IOPCRA;
+
+ sc->sc_regaddr[line][SC_ACR] = (line < 2 ? 0 : 0x10) + SC_ACRAB;
+ sc->sc_regaddr[line][SC_IMR] = (line < 2 ? 0 : 0x10) + SC_IMRAB;
+ sc->sc_regaddr[line][SC_OPR] = (line < 2 ? 0 : 0x10) + SC_OPRAB;
+ }
+ for (line = 0; line < SC_NLINES; line++)
+ for (reg = 0; reg < SC_LOGICAL; reg++)
+ sc->sc_regaddr[line][reg] =
+ 0 + 4 * sc->sc_regaddr[line][reg];
+
+ /*
+ * Initialize all lines.
+ */
+ sc->sc_sv_reg = sc->sc_console ? &qsccn_sv : &sc->sc_sv_reg_storage;
+ for (line = 0; line < SC_NLINES; line++) {
+ /* do not reinitialize the console line... */
+ if (sc->sc_console && line == QSC_LINE_SERIAL)
+ continue;
+
+ sc->sc_sv_reg->sv_mr1[line] =
+ (line == 3 ? ODDPAR | PAREN : PARDIS) | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[line] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[line] = line < 2 ? BD9600 : BD4800;
+ sc->sc_sv_reg->sv_cr[line] = TXEN | RXEN;
+
+ pair = line >> 1;
+
+ if (sc->sc_console && pair == (QSC_LINE_SERIAL >> 1))
+ continue;
+
+ /* Start out with Tx and RX interrupts disabled */
+ sc->sc_sv_reg->sv_imr[pair] = 0;
+ }
+
+ for (line = 0; line < SC_NLINES; line++) {
+ /* do not reset the console line... */
+ if (sc->sc_console && line == QSC_LINE_SERIAL)
+ continue;
+
+ qsc_write(sc, line, SC_CR, RXRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_write(sc, line, SC_CR, TXRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_write(sc, line, SC_CR, ERRRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_write(sc, line, SC_CR, BRKINTRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_write(sc, line, SC_CR, MRZERO | TXDIS | RXDIS);
+ DELAY(1);
+
+ qsc_write(sc, line, SC_MR, 0);
+ qsc_write(sc, line, SC_MR, sc->sc_sv_reg->sv_mr1[line]);
+ qsc_write(sc, line, SC_MR, sc->sc_sv_reg->sv_mr2[line]);
+ qsc_write(sc, line, SC_CSR, sc->sc_sv_reg->sv_csr[line]);
+ qsc_write(sc, line, SC_CR, sc->sc_sv_reg->sv_cr[line]);
+ DELAY(1);
+ }
+
+ for (pair = 0; pair < SC_NLINES / 2; pair++)
+ qsc_write(sc, pair << 1, SC_IMR,
+ sc->sc_sv_reg->sv_imr[pair]);
+
+ for (line = 0; line < SC_NLINES; line++) {
+ sc->sc_tty[line] = NULL;
+ sc->sc_swflags[line] = 0;
+ }
+ if (sc->sc_console)
+ sc->sc_swflags[QSC_LINE_SERIAL] |= TIOCFLAG_SOFTCAR;
+
+ printf("\n");
+
+ /*
+ * Configure interrupts. We are bidding in 2681 mode for now.
+ */
+
+ qsc_writep(sc, SC_ICR, 0x00);
+ for (line = SC_BIDCRA; line <= SC_BIDCRD; line++)
+ qsc_writep(sc, line, 0x00);
+ qsc_writep(sc, SC_IVR, VXT_INTRVEC >> 2);
+
+ vxtbus_intr_establish(self->dv_xname, IPL_TTY, qscintr, sc);
+
+ /*
+ * Attach subdevices, and enable RX and TX interrupts on their lines
+ * if successful.
+ */
+#if NQSCKBD > 0
+ /* keyboard */
+ qa.qa_line = QSC_LINE_KEYBOARD;
+ qa.qa_console = !sc->sc_console;
+ qa.qa_hook = &sc->sc_hook[QSC_LINE_KEYBOARD];
+ if (config_found(self, &qa, qsc_print) != NULL)
+ sc->sc_sv_reg->sv_imr[QSC_LINE_KEYBOARD >> 1] |= IRXRDYA;
+#endif
+#if NQSCMS > 0
+ /* mouse */
+ qa.qa_line = QSC_LINE_MOUSE;
+ qa.qa_console = 0;
+ qa.qa_hook = &sc->sc_hook[QSC_LINE_MOUSE];
+ if (config_found(self, &qa, qsc_print) != NULL)
+ sc->sc_sv_reg->sv_imr[QSC_LINE_MOUSE >> 1] |= IRXRDYB;
+#endif
+
+ for (pair = 0; pair < SC_NLINES / 2; pair++)
+ qsc_write(sc, pair << 1, SC_IMR,
+ sc->sc_sv_reg->sv_imr[pair]);
+
+ sc->sc_rdy = 1;
+}
+
+/* speed tables */
+const struct qsc_s {
+ int kspeed;
+ int dspeed;
+} qsc_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
+qscspeed(int speed)
+{
+ const struct qsc_s *ds;
+
+ for (ds = qsc_speeds; ds->kspeed != -1; ds++)
+ if (ds->kspeed == speed)
+ return ds->dspeed;
+
+ return NOBAUD;
+}
+
+struct tty *
+qsctty(dev_t dev)
+{
+ u_int line;
+ struct qscsoftc *sc;
+
+ line = SC_LINE(dev);
+ if (qsc_cd.cd_ndevs == 0 || line >= SC_NLINES)
+ return (NULL);
+
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+ if (sc == NULL)
+ return (NULL);
+
+ return sc->sc_tty[line];
+}
+
+void
+qscstart(struct tty *tp)
+{
+ struct qscsoftc *sc;
+ dev_t dev;
+ int s;
+ u_int line;
+ int c, tries;
+
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ return;
+
+ dev = tp->t_dev;
+ line = SC_LINE(dev);
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+
+ 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 (qsc_read(sc, line, SC_SR) & TXRDY)
+ break;
+
+ if (tries == 0) {
+ timeout_add(&tp->t_rstrt_to, 1);
+ tp->t_state |= TS_TIMEOUT;
+ break;
+ } else {
+ c = getc(&tp->t_outq);
+
+ qsc_write(sc, line, SC_TXFIFO, c & 0xff);
+
+ sc->sc_sv_reg->sv_imr[line >> 1] |=
+ line & 1 ? ITXRDYB : ITXRDYA;
+ qsc_write(sc, line, SC_IMR,
+ sc->sc_sv_reg->sv_imr[line >> 1]);
+ }
+ }
+ tp->t_state &= ~TS_BUSY;
+
+bail:
+ splx(s);
+}
+
+int
+qscstop(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;
+}
+
+int
+qscioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ int error;
+ u_int line;
+ struct tty *tp;
+ struct qscsoftc *sc;
+
+ line = SC_LINE(dev);
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+
+ tp = sc->sc_tty[line];
+ 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 TIOCGFLAGS:
+ *(int *)data = sc->sc_swflags[line];
+ break;
+ case TIOCSFLAGS:
+ error = suser(p, 0);
+ if (error != 0)
+ return (EPERM);
+
+ sc->sc_swflags[line] = *(int *)data &
+ /* only allow valid flags */
+ (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
+ break;
+ default:
+ return (ENOTTY);
+ }
+
+ return (0);
+}
+
+int
+qscparam(struct tty *tp, struct termios *t)
+{
+ int flags;
+ u_int line, pair;
+ int speeds;
+ u_int8_t mr1, mr2;
+ struct qscsoftc *sc;
+ dev_t dev;
+
+ dev = tp->t_dev;
+ line = SC_LINE(dev);
+ pair = line >> 1;
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+
+ flags = tp->t_flags;
+
+ /* disable Tx and Rx */
+ if (sc->sc_console == 0 || line != QSC_LINE_SERIAL) {
+ if (line & 1)
+ sc->sc_sv_reg->sv_imr[pair] &= ~(ITXRDYB | IRXRDYB);
+ else
+ sc->sc_sv_reg->sv_imr[pair] &= ~(ITXRDYA | IRXRDYA);
+ qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
+
+ /* set baudrate */
+ speeds = qscspeed(tp->t_ispeed);
+ if (speeds == NOBAUD)
+ speeds = DEFBAUD;
+ qsc_write(sc, line, SC_CSR, speeds);
+ sc->sc_sv_reg->sv_csr[line] = speeds;
+
+ /* get saved mode registers and clear set up parameters */
+ mr1 = sc->sc_sv_reg->sv_mr1[line];
+ mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
+
+ mr2 = sc->sc_sv_reg->sv_mr2[line];
+ 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[line] != mr1 ||
+ sc->sc_sv_reg->sv_mr2[line] != mr2) {
+ /* write mode registers to duart */
+ qsc_write(sc, line, SC_CR, MRONE);
+ DELAY(1);
+ qsc_write(sc, line, SC_MR, mr1);
+ qsc_write(sc, line, SC_MR, mr2);
+
+ /* save changed mode registers */
+ sc->sc_sv_reg->sv_mr1[line] = mr1;
+ sc->sc_sv_reg->sv_mr2[line] = mr2;
+ }
+ }
+
+ /* enable transmitter? */
+ if (tp->t_state & TS_BUSY) {
+ sc->sc_sv_reg->sv_imr[pair] |= line & 1 ? ITXRDYB : ITXRDYA;
+ }
+
+ /* re-enable the receiver */
+ sc->sc_sv_reg->sv_imr[pair] |= line & 1 ? IRXRDYB : IRXRDYA;
+ qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
+
+ return (0);
+}
+
+int
+qscopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ int s;
+ u_int line;
+ struct qscsoftc *sc;
+ struct tty *tp;
+
+ line = SC_LINE(dev);
+ if (qsc_cd.cd_ndevs == 0 || line >= SC_NLINES)
+ return (ENXIO);
+ /* Line B is not wired... */
+ if (line == QSC_LINE_DEAD)
+ return (ENXIO);
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+ if (sc == NULL)
+ return (ENXIO);
+
+ /* if some other device is using the line, it's not available */
+ if (sc->sc_hook[line].fn != NULL)
+ return (ENXIO);
+
+ s = spltty();
+ if (sc->sc_tty[line] != NULL)
+ tp = sc->sc_tty[line];
+ else
+ tp = sc->sc_tty[line] = ttymalloc();
+
+ tp->t_oproc = qscstart;
+ tp->t_param = qscparam;
+ 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 && line == QSC_LINE_SERIAL) {
+ /* console is 8N1 */
+ tp->t_cflag = (CREAD | CS8 | HUPCL);
+ } else {
+ tp->t_cflag = TTYDEF_CFLAG;
+ }
+ }
+
+ if (sc->sc_swflags[line] & TIOCFLAG_CLOCAL)
+ tp->t_cflag |= CLOCAL;
+ if (sc->sc_swflags[line] & TIOCFLAG_CRTSCTS)
+ tp->t_cflag |= CRTSCTS;
+ if (sc->sc_swflags[line] & TIOCFLAG_MDMBUF)
+ tp->t_cflag |= MDMBUF;
+
+ qscparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ 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
+qscclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct tty *tp;
+ struct qscsoftc *sc;
+ u_int line;
+
+ line = SC_LINE(dev);
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+
+ tp = sc->sc_tty[line];
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+
+ return (0);
+}
+
+int
+qscread(dev_t dev, struct uio *uio, int flag)
+{
+ u_int line;
+ struct tty *tp;
+ struct qscsoftc *sc;
+
+ line = SC_LINE(dev);
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+
+ tp = sc->sc_tty[line];
+ if (tp == NULL)
+ return (ENXIO);
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+qscwrite(dev_t dev, struct uio *uio, int flag)
+{
+ u_int line;
+ struct tty *tp;
+ struct qscsoftc *sc;
+
+ line = SC_LINE(dev);
+ sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
+
+ tp = sc->sc_tty[line];
+ if (tp == NULL)
+ return (ENXIO);
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+void
+qscrint(struct qscsoftc *sc, u_int line)
+{
+ struct tty *tp;
+ int data;
+ unsigned char sr;
+ int overrun = 0;
+
+ tp = sc->sc_tty[line];
+
+ /* read status reg */
+ while ((sr = qsc_read(sc, line, SC_SR)) & RXRDY) {
+ /* read data and reset receiver */
+ data = qsc_read(sc, line, SC_RXFIFO);
+
+ if (sr & RBRK) {
+ /* clear break state */
+ qsc_write(sc, line, SC_CR, BRKINTRESET);
+ DELAY(1);
+ qsc_write(sc, line, SC_CR, ERRRESET);
+ DELAY(1);
+ continue;
+ }
+
+ if ((sr & ROVRN) && cold == 0 && overrun == 0) {
+ log(LOG_WARNING, "%s line %d: receiver overrun\n",
+ sc->sc_dev.dv_xname, line);
+ overrun = 1;
+ }
+
+ if (sr & FRERR)
+ data |= TTY_FE;
+ if (sr & PERR)
+ data |= TTY_PE;
+
+ /* clear error state */
+ if (sr & (ROVRN | FRERR | PERR)) {
+ qsc_write(sc, line, SC_CR, ERRRESET);
+ DELAY(1);
+ }
+
+ if (sc->sc_hook[line].fn != NULL) {
+ if ((data & TTY_ERRORMASK) != 0 ||
+ (*sc->sc_hook[line].fn)(sc->sc_hook[line].arg, data))
+ continue;
+ }
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 &&
+ (sc->sc_console == 0 || line != QSC_LINE_SERIAL)) {
+ continue;
+ }
+
+ /* no errors */
+#if defined(DDB)
+ if (tp->t_dev == cn_tab->cn_dev) {
+ int j = kdbrint(data);
+
+ if (j == 1)
+ continue;
+
+ if (j == 2)
+ (*linesw[tp->t_line].l_rint)(27, tp);
+ }
+#endif
+ (*linesw[tp->t_line].l_rint)(data, tp);
+ }
+}
+
+void
+qscxint(struct qscsoftc *sc, u_int line)
+{
+ struct tty *tp;
+ u_int pair;
+
+ tp = sc->sc_tty[line];
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
+ goto out;
+
+ if (tp->t_state & TS_BUSY) {
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+ qscstart(tp);
+ if (tp->t_state & TS_BUSY) {
+ /* do not disable transmitter, yet */
+ return;
+ }
+ }
+out:
+
+ /* disable transmitter */
+ pair = line >> 1;
+ sc->sc_sv_reg->sv_imr[pair] &= line & 1 ? ~ITXRDYB : ~ITXRDYA;
+ qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
+}
+
+int
+qscintr(void *arg)
+{
+ struct qscsoftc *sc = arg;
+ u_int8_t isr[SC_NLINES >> 1], curisr;
+ u_int pair, line;
+ int rc = 0;
+
+ for (pair = 0; pair < SC_NLINES >> 1; pair++) {
+ line = pair << 1;
+
+ /* read interrupt status register and mask with imr */
+ isr[pair] = curisr = qsc_read(sc, line, SC_ISR);
+ curisr &= sc->sc_sv_reg->sv_imr[pair];
+ if (curisr == 0)
+ continue;
+
+ rc = 1;
+
+ if (curisr & IRXRDYA)
+ qscrint(sc, line);
+ if (curisr & ITXRDYA)
+ qscxint(sc, line);
+ if (curisr & IBRKA) {
+ qsc_write(sc, line, SC_CR, BRKINTRESET);
+ DELAY(1);
+ }
+
+ if (curisr & IRXRDYB)
+ qscrint(sc, line + 1);
+ if (curisr & ITXRDYB)
+ qscxint(sc, line + 1);
+ if (curisr & IBRKB) {
+ qsc_write(sc, line + 1, SC_CR, BRKINTRESET);
+ DELAY(1);
+ }
+ }
+
+ return (rc);
+}
+
+/*
+ * Console interface routines.
+ */
+
+vaddr_t qsc_cnregs;
+#define qsc_cnread(reg) \
+ *(volatile u_int8_t *)(qsc_cnregs + 4 * (reg))
+#define qsc_cnwrite(reg, val) \
+ *(volatile u_int8_t *)(qsc_cnregs + 4 * (reg)) = (val)
+
+void
+qsccnprobe(struct consdev *cp)
+{
+ int maj;
+ extern int getmajor(void *);
+ extern vaddr_t iospace;
+
+ if (vax_boardtype != VAX_BTYP_VXT)
+ return;
+
+ /* locate the major number */
+ if ((maj = getmajor(qscopen)) < 0)
+ return;
+
+ qsc_cnregs = iospace;
+ ioaccess(iospace, QSCADDR, 1);
+
+ cp->cn_dev = makedev(maj, QSC_LINE_SERIAL);
+ cp->cn_pri = vax_confdata & 2 ? CN_NORMAL : CN_REMOTE;
+}
+
+void
+qsccninit(cp)
+ struct consdev *cp;
+{
+ qsccn_sv.sv_mr1[QSC_LINE_SERIAL] = PARDIS | RXRTS | CL8;
+ qsccn_sv.sv_mr2[QSC_LINE_SERIAL] = /* TXCTS | */ SB1;
+ qsccn_sv.sv_csr[QSC_LINE_SERIAL] = BD9600;
+ qsccn_sv.sv_cr[QSC_LINE_SERIAL] = TXEN | RXEN;
+ qsccn_sv.sv_imr[QSC_LINE_SERIAL] = 0;
+
+ qsc_cnwrite(SC_CRA, RXRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_cnwrite(SC_CRA, TXRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_cnwrite(SC_CRA, ERRRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_cnwrite(SC_CRA, BRKINTRESET | TXDIS | RXDIS);
+ DELAY(1);
+ qsc_cnwrite(SC_CRA, MRZERO | TXDIS | RXDIS);
+ DELAY(1);
+
+ qsc_cnwrite(SC_MRA, 0);
+ qsc_cnwrite(SC_MRA, qsccn_sv.sv_mr1[QSC_LINE_SERIAL]);
+ qsc_cnwrite(SC_MRA, qsccn_sv.sv_mr2[QSC_LINE_SERIAL]);
+ qsc_cnwrite(SC_CSRA, qsccn_sv.sv_csr[QSC_LINE_SERIAL]);
+ qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
+ DELAY(1);
+
+ qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
+ qsc_cnwrite(SC_IMRCD, 0);
+}
+
+int
+qsccngetc(dev_t dev)
+{
+ unsigned char sr; /* status reg of line a/b */
+ u_char c; /* received character */
+ int s;
+
+ s = spltty();
+
+ /* disable interrupts for this line and enable receiver */
+ qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL] & ~ITXRDYA);
+ qsc_cnwrite(SC_CRA, RXEN);
+ DELAY(1);
+
+ for (;;) {
+ /* read status reg */
+ sr = qsc_cnread(SC_SRA);
+
+ /* receiver interrupt handler*/
+ if (sr & RXRDY) {
+ /* read character from line */
+ c = qsc_cnread(SC_RXFIFOA);
+
+ /* check break condition */
+ if (sr & RBRK) {
+ /* clear break state */
+ qsc_cnwrite(SC_CRA, BRKINTRESET);
+ DELAY(1);
+ qsc_cnwrite(SC_CRA, ERRRESET);
+ DELAY(1);
+ break;
+ }
+
+ if (sr & (FRERR | PERR | ROVRN)) {
+ /* clear error state */
+ qsc_cnwrite(SC_CRA, ERRRESET);
+ DELAY(1);
+ } else {
+ break;
+ }
+ }
+ }
+
+ /* restore the previous state */
+ qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
+ qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
+
+ splx(s);
+
+ return ((int)c);
+}
+
+void
+qsccnputc(dev_t dev, int c)
+{
+ int s;
+
+ if (mfpr(PR_MAPEN) == 0)
+ return;
+
+ s = spltty();
+
+ /* disable interrupts for this line and enable transmitter */
+ qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL] & ~ITXRDYA);
+ qsc_cnwrite(SC_CRA, TXEN);
+ DELAY(1);
+
+ while ((qsc_cnread(SC_SRA) & TXRDY) == 0)
+ ;
+ qsc_cnwrite(SC_TXFIFOA, c);
+
+ /* wait for transmitter to empty */
+ while ((qsc_cnread(SC_SRA) & TXEMT) == 0)
+ ;
+
+ /* restore the previous state */
+ qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
+ qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
+ DELAY(1);
+
+ splx(s);
+}
+
+void
+qsccnpollc(dev, pollflag)
+ dev_t dev;
+ int pollflag;
+{
+}
+
+/*
+ * Keyboard and mouse helper routines
+ */
+
+#if NQSCKBD > 0 || NQSCMS > 0
+int
+qsc_print(void *aux, const char *name)
+{
+ struct qsc_attach_args *qa = aux;
+
+ if (name != NULL)
+ printf(qa->qa_line == QSC_LINE_KEYBOARD ?
+ "lkkbd at %s" : "lkms at %s", name);
+ else
+ printf(" line %d", qa->qa_line);
+
+ return (UNCONF);
+}
+
+int
+qscgetc(u_int line)
+{
+ bus_addr_t craddr;
+ struct qscsoftc *sc = NULL;
+ int s;
+ u_int8_t sr, imr, imrmask, cr, c;
+
+ s = spltty();
+
+ craddr = line == QSC_LINE_KEYBOARD ? SC_CRC : SC_CRD;
+ imrmask = line & 1 ? ~IRXRDYB : ~IRXRDYA;
+ imr = sc != NULL ? sc->sc_sv_reg->sv_imr[line / 2] : 0;
+ cr = sc != NULL ? sc->sc_sv_reg->sv_cr[line] : 0;
+
+ /* disable interrupts for this line and enable receiver */
+ qsc_cnwrite(SC_IMRCD, imr & imrmask);
+ qsc_cnwrite(craddr, RXEN);
+ DELAY(1);
+
+ for (;;) {
+ /* read status reg */
+ sr = qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD);
+
+ /* receiver interrupt handler*/
+ if (sr & RXRDY) {
+ /* read character from line */
+ c = qsc_cnread(line == QSC_LINE_KEYBOARD ?
+ SC_RXFIFOC : SC_RXFIFOD);
+
+ /* check break condition */
+ if (sr & RBRK) {
+ /* clear break state */
+ qsc_cnwrite(craddr, BRKINTRESET);
+ DELAY(1);
+ qsc_cnwrite(craddr, ERRRESET);
+ DELAY(1);
+ break;
+ }
+
+ if (sr & (FRERR | PERR | ROVRN)) {
+ /* clear error state */
+ qsc_cnwrite(craddr, ERRRESET);
+ DELAY(1);
+ } else {
+ break;
+ }
+ }
+ }
+
+ /* restore the previous state */
+ qsc_cnwrite(SC_IMRCD, imr);
+ qsc_cnwrite(craddr, cr);
+ DELAY(1);
+
+ splx(s);
+
+ return ((int)c);
+}
+
+void
+qscputc(u_int line, int c)
+{
+ bus_addr_t craddr;
+ struct qscsoftc *sc = NULL;
+ int s;
+ u_int8_t imr, imrmask, cr;
+
+ s = spltty();
+
+ if (qsc_cd.cd_ndevs != 0 &&
+ (sc = (struct qscsoftc *)qsc_cd.cd_devs[0]) != NULL)
+ if (sc->sc_rdy == 0)
+ sc = NULL;
+
+ craddr = line == QSC_LINE_KEYBOARD ? SC_CRC : SC_CRD;
+ imrmask = line & 1 ? ~ITXRDYB : ~ITXRDYA;
+ imr = sc != NULL ? sc->sc_sv_reg->sv_imr[line / 2] : 0;
+ cr = sc != NULL ? sc->sc_sv_reg->sv_cr[line] : 0;
+
+ /* disable interrupts for this line and enable transmitter */
+ qsc_cnwrite(SC_IMRCD, imr & imrmask);
+ qsc_cnwrite(craddr, TXEN);
+ DELAY(1);
+
+ while ((qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD) &
+ TXRDY) == 0)
+ ;
+ qsc_cnwrite(line == QSC_LINE_KEYBOARD ? SC_TXFIFOC : SC_TXFIFOD, c);
+
+ /* wait for transmitter to empty */
+ while ((qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD) &
+ TXEMT) == 0)
+ ;
+
+ /* restore the previous state */
+ qsc_cnwrite(SC_IMRCD, imr);
+ qsc_cnwrite(craddr, cr);
+ DELAY(1);
+
+ splx(s);
+}
+#endif
diff --git a/sys/arch/vax/vxt/qsckbd.c b/sys/arch/vax/vxt/qsckbd.c
new file mode 100644
index 00000000000..bf9f54ade79
--- /dev/null
+++ b/sys/arch/vax/vxt/qsckbd.c
@@ -0,0 +1,290 @@
+/* $OpenBSD: qsckbd.c,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/* from OpenBSD: dzkbd.c,v 1.11 2006/08/05 22:05:55 miod Exp */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kbd.c 8.2 (Berkeley) 10/30/93
+ */
+
+/*
+ * LK200/LK400 keyboard attached to line C of the SC26C94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <sys/timeout.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+#include <vax/dec/wskbdmap_lk201.h>
+
+#include <machine/bus.h>
+
+#include <vax/dec/lk201reg.h>
+#include <vax/dec/lk201var.h>
+
+#include <vax/vxt/qscvar.h>
+
+struct qsckbd_internal {
+ u_int dzi_line;
+ struct lk201_state dzi_ks;
+};
+
+struct qsckbd_internal qsckbd_console_internal;
+
+struct qsckbd_softc {
+ struct device qsckbd_dev; /* required first: base device */
+
+ struct qsckbd_internal *sc_itl;
+ int sc_enabled;
+ struct device *sc_wskbddev;
+};
+
+int qsckbd_match(struct device *, void *, void *);
+void qsckbd_attach(struct device *, struct device *, void *);
+
+struct cfattach qsckbd_ca = {
+ sizeof(struct qsckbd_softc), qsckbd_match, qsckbd_attach,
+};
+
+int qsckbd_enable(void *, int);
+void qsckbd_set_leds(void *, int);
+int qsckbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
+
+const struct wskbd_accessops qsckbd_accessops = {
+ qsckbd_enable,
+ qsckbd_set_leds,
+ qsckbd_ioctl,
+};
+
+void qsckbd_cngetc(void *, u_int *, int *);
+void qsckbd_cnpollc(void *, int);
+
+const struct wskbd_consops qsckbd_consops = {
+ qsckbd_cngetc,
+ qsckbd_cnpollc,
+};
+
+const struct wskbd_mapdata qsckbd_keymapdata = {
+ lkkbd_keydesctab,
+#ifdef LKKBD_LAYOUT
+ LKKBD_LAYOUT,
+#else
+ KB_US,
+#endif
+};
+
+int qsckbd_input(void *, int);
+int qsckbd_sendchar(void *, int);
+
+int
+qsckbd_match(struct device *parent, void *vcf, void *aux)
+{
+ struct qsc_attach_args *qa = aux;
+ struct cfdata *cf = vcf;
+
+ if (cf->cf_loc[0] == qa->qa_line)
+ return 1;
+
+ return 0;
+}
+
+void
+qsckbd_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct qsckbd_softc *sc = (void *)self;
+ struct qsc_attach_args *qa = aux;
+ struct qsckbd_internal *dzi;
+ struct wskbddev_attach_args a;
+ int isconsole;
+
+ qa->qa_hook->fn = qsckbd_input;
+ qa->qa_hook->arg = self;
+
+ isconsole = qa->qa_console;
+
+ if (isconsole) {
+ dzi = &qsckbd_console_internal;
+ sc->sc_enabled = 1;
+ } else {
+ dzi = malloc(sizeof(struct qsckbd_internal), M_DEVBUF, M_NOWAIT);
+ if (dzi == NULL) {
+ printf(": out of memory\n");
+ return;
+ }
+ dzi->dzi_ks.attmt.sendchar = qsckbd_sendchar;
+ dzi->dzi_ks.attmt.cookie = (void *)qa->qa_line;
+ }
+ dzi->dzi_ks.device = self;
+ dzi->dzi_line = qa->qa_line;
+ sc->sc_itl = dzi;
+
+ printf("\n");
+
+ if (!isconsole)
+ lk201_init(&dzi->dzi_ks);
+
+ a.console = dzi == &qsckbd_console_internal;
+ a.keymap = &qsckbd_keymapdata;
+ a.accessops = &qsckbd_accessops;
+ a.accesscookie = sc;
+
+ sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
+}
+
+int
+qsckbd_cnattach(u_int line)
+{
+
+ qsckbd_console_internal.dzi_ks.attmt.sendchar = qsckbd_sendchar;
+ qsckbd_console_internal.dzi_ks.attmt.cookie = (void *)line;
+ lk201_init(&qsckbd_console_internal.dzi_ks);
+ qsckbd_console_internal.dzi_line = line;
+
+ wskbd_cnattach(&qsckbd_consops, &qsckbd_console_internal,
+ &qsckbd_keymapdata);
+
+ return 0;
+}
+
+int
+qsckbd_enable(void *v, int on)
+{
+ struct qsckbd_softc *sc = v;
+
+ sc->sc_enabled = on;
+ return 0;
+}
+
+void
+qsckbd_cngetc(void *v, u_int *type, int *data)
+{
+ struct qsckbd_internal *dzi = v;
+ int c;
+
+ do {
+ c = qscgetc(dzi->dzi_line);
+ } while (lk201_decode(&dzi->dzi_ks, 1, 0, c, type, data) == LKD_NODATA);
+}
+
+void
+qsckbd_cnpollc(void *v, int on)
+{
+}
+
+void
+qsckbd_set_leds(void *v, int leds)
+{
+ struct qsckbd_softc *sc = (struct qsckbd_softc *)v;
+
+ lk201_set_leds(&sc->sc_itl->dzi_ks, leds);
+}
+
+int
+qsckbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ struct qsckbd_softc *sc = (struct qsckbd_softc *)v;
+
+ switch (cmd) {
+ case WSKBDIO_GTYPE:
+ *(int *)data = lk201_get_type(&sc->sc_itl->dzi_ks);
+ return 0;
+ case WSKBDIO_SETLEDS:
+ lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data);
+ return 0;
+ case WSKBDIO_GETLEDS:
+ *(int *)data = lk201_get_leds(&sc->sc_itl->dzi_ks);
+ return 0;
+ case WSKBDIO_COMPLEXBELL:
+ lk201_bell(&sc->sc_itl->dzi_ks,
+ (struct wskbd_bell_data *)data);
+ return 0;
+ }
+ return -1;
+}
+
+int
+qsckbd_input(void *v, int data)
+{
+ struct qsckbd_softc *sc = (struct qsckbd_softc *)v;
+ u_int type;
+ int val;
+ int decode;
+
+ /*
+ * We want to run through lk201_decode always, so that a late plugged
+ * keyboard will get configured correctly.
+ */
+ do {
+ decode = lk201_decode(&sc->sc_itl->dzi_ks, sc->sc_enabled, 1,
+ data, &type, &val);
+ if (decode != LKD_NODATA)
+ wskbd_input(sc->sc_wskbddev, type, val);
+ } while (decode == LKD_MORE);
+
+ return(1);
+}
+
+int
+qsckbd_sendchar(void *v, int c)
+{
+ qscputc((u_int)v, c);
+ return (0);
+}
diff --git a/sys/arch/vax/vxt/qscms.c b/sys/arch/vax/vxt/qscms.c
new file mode 100644
index 00000000000..6ec2bd21265
--- /dev/null
+++ b/sys/arch/vax/vxt/qscms.c
@@ -0,0 +1,167 @@
+/* $OpenBSD: qscms.c,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/* from OpenBSD: qscms.c,v 1.6 2006/07/31 18:50:13 miod Exp */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ms.c 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * VSXXX mice attached to line D of the SC26C94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+
+#include <machine/bus.h>
+
+#include <vax/qbus/dzreg.h>
+#include <vax/qbus/dzvar.h>
+
+#include <vax/vxt/qscvar.h>
+#include <vax/dec/vsmsvar.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+struct qscms_softc {
+ struct lkms_softc sc_base;
+ u_int sc_line;
+};
+
+int qscms_match(struct device *, void *, void *);
+void qscms_attach(struct device *, struct device *, void *);
+
+struct cfattach qscms_ca = {
+ sizeof(struct qscms_softc), qscms_match, qscms_attach,
+};
+
+int qscms_enable(void *);
+void qscms_disable(void *);
+
+const struct wsmouse_accessops qscms_accessops = {
+ qscms_enable,
+ lkms_ioctl,
+ qscms_disable,
+};
+
+int
+qscms_match(struct device *parent, void *vcf, void *aux)
+{
+ struct qsc_attach_args *qa = aux;
+ struct cfdata *cf = vcf;
+
+ if (cf->cf_loc[0] == qa->qa_line)
+ return 1;
+
+ return 0;
+}
+
+void
+qscms_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct qscms_softc *qscms = (void *)self;
+ struct lkms_softc *sc = (void *)self;
+ struct qsc_attach_args *qa = aux;
+ struct wsmousedev_attach_args a;
+
+ qa->qa_hook->fn = lkms_input;
+ qa->qa_hook->arg = self;
+ qscms->sc_line = qa->qa_line;
+
+ printf("\n");
+
+ a.accessops = &qscms_accessops;
+ a.accesscookie = qscms;
+
+ sc->sc_enabled = 0;
+ sc->sc_selftest = 0;
+ sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+}
+
+int
+qscms_enable(void *v)
+{
+ struct qscms_softc *qscms = v;
+ struct lkms_softc *sc = v;
+
+ if (sc->sc_enabled)
+ return EBUSY;
+
+ sc->sc_selftest = 4; /* wait for 4 byte reply upto 1/2 sec */
+ qscputc(qscms->sc_line, MOUSE_SELF_TEST);
+ (void)tsleep(&sc->sc_enabled, TTIPRI, "qscmsopen", hz / 2);
+ if (sc->sc_selftest != 0) {
+ sc->sc_selftest = 0;
+ return ENXIO;
+ }
+ DELAY(150);
+ qscputc(qscms->sc_line, MOUSE_INCREMENTAL);
+ sc->sc_enabled = 1;
+ sc->inputstate = 0;
+ return 0;
+}
+
+void
+qscms_disable(void *v)
+{
+ struct lkms_softc *sc = v;
+
+ sc->sc_enabled = 0;
+}
diff --git a/sys/arch/vax/vxt/qscreg.h b/sys/arch/vax/vxt/qscreg.h
new file mode 100644
index 00000000000..bb15a4a84c1
--- /dev/null
+++ b/sys/arch/vax/vxt/qscreg.h
@@ -0,0 +1,173 @@
+/* $OpenBSD: qscreg.h,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * SC26C94 registers
+ */
+
+#define SC_MRA 0x00 /* R/W Mode Register A */
+#define SC_SRA 0x01 /* R Status Register A */
+#define SC_CSRA 0x01 /* W Clock Select Register A */
+#define SC_CRA 0x02 /* W Command Register A */
+#define SC_RXFIFOA 0x03 /* R Receive Holding Register A */
+#define SC_TXFIFOA 0x03 /* W Transmit Holding Register A */
+#define SC_IPCRAB 0x04 /* R Input Port Change Register AB */
+#define SC_ACRAB 0x04 /* W Auxiliary Control Register AB */
+#define SC_ISRAB 0x05 /* R Interrupt Status Register AB */
+#define SC_IMRAB 0x05 /* W Interrupt Mask Register AB */
+#define SC_CTURAB 0x06 /* R/W Counter/Timer Upper Register AB */
+#define SC_CTLRAB 0x07 /* R/W Counter/Timer Lower Register AB */
+#define SC_MRB 0x08 /* R/W Mode Register A */
+#define SC_SRB 0x09 /* R Status Register A */
+#define SC_CSRB 0x09 /* W Clock Select Register A */
+#define SC_CRB 0x0a /* W Command Register A */
+#define SC_RXFIFOB 0x0b /* R Receive Holding Register A */
+#define SC_TXFIFOB 0x0b /* W Transmit Holding Register A */
+#define SC_OPRAB 0x0c /* R/W Output Port Register AB */
+#define SC_IPRAB 0x0d /* R Input Port Register AB */
+#define SC_IOPCRA 0x0d /* W I/O Port Control Register A */
+#define SC_IOPCRB 0x0e /* W I/O Port Control Register A */
+#define SC_CTSTARTAB 0x0e /* R Start Counter AB */
+#define SC_CTSTOPAB 0x0f /* R Start Counter AB */
+
+#define SC_MRC 0x10 /* R/W Mode Register C */
+#define SC_SRC 0x11 /* R Status Register C */
+#define SC_CSRC 0x11 /* W Clock Select Register C */
+#define SC_CRC 0x12 /* W Command Register C */
+#define SC_RXFIFOC 0x13 /* R Receive Holding Register C */
+#define SC_TXFIFOC 0x13 /* W Transmit Holding Register C */
+#define SC_IPCRCD 0x14 /* R Input Port Change Register CD */
+#define SC_ACRCD 0x14 /* W Auxiliary Control Register CD */
+#define SC_ISRCD 0x15 /* R Interrupt Status Register CD */
+#define SC_IMRCD 0x15 /* W Interrupt Mask Register CD */
+#define SC_CTURCD 0x16 /* R/W Counter/Timer Upper Register CD */
+#define SC_CTLRCD 0x17 /* R/W Counter/Timer Lower Register CD */
+#define SC_MRD 0x18 /* R/W Mode Register C */
+#define SC_SRD 0x19 /* R Status Register C */
+#define SC_CSRD 0x19 /* W Clock Select Register C */
+#define SC_CRD 0x1a /* W Command Register C */
+#define SC_RXFIFOD 0x1b /* R Receive Holding Register C */
+#define SC_TXFIFOD 0x1b /* W Transmit Holding Register C */
+#define SC_OPRCD 0x1c /* R/W Output Port Register CD */
+#define SC_IPRCD 0x1d /* R Input Port Register CD */
+#define SC_IOPCRC 0x1d /* W I/O Port Control Register C */
+#define SC_IOPCRD 0x1e /* W I/O Port Control Register C */
+#define SC_CTSTARTCD 0x1e /* R Start Counter CD */
+#define SC_CTSTOPCD 0x1f /* R Start Counter CD */
+
+#define SC_BIDCRA 0x20 /* R/W Bidding Control Register A */
+#define SC_BIDCRB 0x21 /* R/W Bidding Control Register B */
+#define SC_BIDCRC 0x22 /* R/W Bidding Control Register C */
+#define SC_BIDCRD 0x23 /* R/W Bidding Control Register D */
+#define SC_POWERDOWN 0x24 /* W Power Down */
+#define SC_POWERUP 0x25 /* W Power Up */
+#define SC_DDACKN 0x26 /* W Disable DACKN */
+#define SC_EDACKN 0x27 /* W Enable DACKN */
+
+#define SC_CIR 0x28 /* R Current Interrupt Register */
+#define SC_GICR 0x29 /* R Global Interrupting Channel Register */
+#define SC_IVR 0x29 /* W Interrupt Vector Register */
+#define SC_GBICR 0x2a /* R Global Int Byte Count Register */
+#define SC_UCIR 0x2a /* W Update CIR */
+#define SC_GRXFIFO 0x2b /* R Global Receive Holding Register */
+#define SC_GTXFIFO 0x2b /* W Global Transmit Holding Register */
+#define SC_ICR 0x2c /* R/W Interrupt Control Register */
+#define SC_BRGRATE 0x2d /* W BRG Rate */
+#define SC_X1DIV2 0x2e /* W Set X1/CLK divide by two */
+#define SC_X1NORM 0x2f /* W Set X1/CLK normal */
+
+/* mode register 1: MR1x operations */
+#define RXRTS 0x80 /* enable receiver RTS */
+#define PAREN 0x00 /* with parity */
+#define PARDIS 0x10 /* no parity */
+#define EVENPAR 0x00 /* even parity */
+#define ODDPAR 0x04 /* odd parity */
+#define CL5 0x00 /* 5 bits per char */
+#define CL6 0x01 /* 6 bits per char */
+#define CL7 0x02 /* 7 bits per char */
+#define CL8 0x03 /* 8 bits per char */
+#define PARMODEMASK 0x18 /* parity mode mask */
+#define PARTYPEMASK 0x04 /* parity type mask */
+#define CLMASK 0x03 /* character length mask */
+
+/* mode register 2: MR2x operations */
+#define TXRTS 0x20 /* enable transmitter RTS */
+#define TXCTS 0x10 /* enable transmitter CTS */
+#define SB2 0x0f /* 2 stop bits */
+#define SB1 0x07 /* 1 stop bit */
+#define SB1L5 0x00 /* 1 stop bit at 5 bits per character */
+
+#define SBMASK 0x0f /* stop bit mask */
+
+/* clock-select register: CSRx operations */
+#define NOBAUD -1 /* 50 and 200 baud are not possible */
+/* they are not in Baud register set 2 */
+#define BD75 0x00 /* 75 baud */
+#define BD110 0x11 /* 110 baud */
+#define BD134 0x22 /* 134.5 baud */
+#define BD150 0x33 /* 150 baud */
+#define BD300 0x44 /* 300 baud */
+#define BD600 0x55 /* 600 baud */
+#define BD1200 0x66 /* 1200 baud */
+#define BD1800 0xaa /* 1800 baud */
+#define BD2400 0x88 /* 2400 baud */
+#define BD4800 0x99 /* 4800 baud */
+#define BD9600 0xbb /* 9600 baud */
+#define BD19200 0xcc /* 19200 baud */
+
+#define DEFBAUD BD9600 /* default value if baudrate is not possible */
+
+/* channel command register: CRx operations */
+#define MRONE 0x10 /* reset mr pointer to mr1 */
+#define RXRESET 0x20 /* reset receiver */
+#define TXRESET 0x30 /* reset transmitter */
+#define ERRRESET 0x40 /* reset error status */
+#define BRKINTRESET 0x50 /* reset channel's break interrupt */
+#define BRKSTART 0x60 /* start break */
+#define BRKSTOP 0x70 /* stop break */
+#define MRZERO 0xb0 /* reset mr pointer to mr0 */
+#define TXDIS 0x08 /* disable transmitter */
+#define TXEN 0x04 /* enable transmitter */
+#define RXDIS 0x02 /* disable receiver */
+#define RXEN 0x01 /* enable receiver */
+
+/* status register: SRx status */
+#define RBRK 0x80 /* received break */
+#define FRERR 0x40 /* frame error */
+#define PERR 0x20 /* parity error */
+#define ROVRN 0x10 /* receiver overrun error */
+#define TXEMT 0x08 /* transmitter empty */
+#define TXRDY 0x04 /* transmitter ready */
+#define FFULL 0x02 /* receiver FIFO full */
+#define RXRDY 0x01 /* receiver ready */
+
+/* auxiliary control register: ACR operations */
+#define BDSET1 0x00 /* baudrate generator set 1 */
+#define BDSET2 0x80 /* baudrate generator set 2 */
+#define CCLK1 0x60 /* timer clock: external rate. TA */
+#define CCLK16 0x30 /* counter clock: x1 clk divided by 16 */
+
+/* interrupt status and mask register: ISR status and IMR mask */
+#define IIPCHG 0x80 /* I/O Port Change */
+#define IBRKB 0x40 /* delta break b */
+#define IRXRDYB 0x20 /* receiver ready b */
+#define ITXRDYB 0x10 /* transmitter ready b */
+#define ITIMER 0x08 /* Counter Ready */
+#define IBRKA 0x04 /* delta break a */
+#define IRXRDYA 0x02 /* receiver ready a */
+#define ITXRDYA 0x01 /* transmitter ready a */
diff --git a/sys/arch/vax/vxt/qscvar.h b/sys/arch/vax/vxt/qscvar.h
new file mode 100644
index 00000000000..4b13fbcd1a0
--- /dev/null
+++ b/sys/arch/vax/vxt/qscvar.h
@@ -0,0 +1,115 @@
+/* $OpenBSD: qscvar.h,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * 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.
+ */
+
+/*
+ * Logical, per port, registers (serial functions only)
+ */
+
+#define SC_MR 0x00 /* R/W Mode Register */
+#define SC_SR 0x01 /* R Status Register */
+#define SC_CSR 0x01 /* W Clock Select Register */
+#define SC_CR 0x02 /* W Command Register */
+#define SC_RXFIFO 0x03 /* R Receive Holding Register */
+#define SC_TXFIFO 0x03 /* W Transmit Holding Register */
+#define SC_IPCR 0x04 /* R Input Port Change Register */
+#define SC_ACR 0x04 /* W Auxiliary Control Register */
+#define SC_ISR 0x05 /* R Interrupt Status Register */
+#define SC_IMR 0x05 /* W Interrupt Mask Register */
+#define SC_OPR 0x06 /* R/W Output Port Register */
+#define SC_IPR 0x07 /* R Input Port Register */
+#define SC_IOPCR 0x07 /* W I/O Port Control Register */
+#define SC_LOGICAL 0x08
+
+#define SC_NLINES 4
+
+/* saved registers */
+struct qsc_sv_reg {
+ u_int8_t sv_mr1[SC_NLINES];
+ u_int8_t sv_mr2[SC_NLINES];
+ u_int8_t sv_csr[SC_NLINES];
+ u_int8_t sv_cr[SC_NLINES];
+ u_int8_t sv_imr[SC_NLINES / 2];
+};
+
+struct qsc_input_hook {
+ int (*fn)(void *, int);
+ void *arg;
+};
+
+struct qscsoftc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_addr_t sc_regaddr[SC_NLINES][SC_LOGICAL];
+
+ int sc_console;
+ int sc_rdy;
+
+ struct qsc_sv_reg *sc_sv_reg;
+ struct qsc_sv_reg sc_sv_reg_storage;
+
+ struct tty *sc_tty[SC_NLINES];
+ u_int sc_swflags[SC_NLINES];
+
+ struct qsc_input_hook sc_hook[SC_NLINES];
+};
+
+/*
+ * Line assignments on the VXT2000
+ */
+
+#define QSC_LINE_SERIAL 0
+#define QSC_LINE_DEAD 1
+#define QSC_LINE_KEYBOARD 2
+#define QSC_LINE_MOUSE 3
+
+struct qsc_attach_args {
+ u_int qa_line;
+ int qa_console; /* for keyboard attachment */
+ struct qsc_input_hook *qa_hook;
+};
+
+int qscgetc(u_int);
+void qscputc(u_int, int);
+
+int qsckbd_cnattach(u_int);
diff --git a/sys/arch/vax/vxt/vxtbus.c b/sys/arch/vax/vxt/vxtbus.c
new file mode 100644
index 00000000000..1749ca364f3
--- /dev/null
+++ b/sys/arch/vax/vxt/vxtbus.c
@@ -0,0 +1,156 @@
+/* $OpenBSD: vxtbus.c,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/evcount.h>
+#include <sys/queue.h>
+
+#include <machine/cpu.h>
+#include <machine/nexus.h>
+#include <machine/scb.h>
+
+#include <vax/vxt/vxtbusvar.h>
+
+struct vxtbus_softc {
+ struct device sc_dev;
+ LIST_HEAD(, vxtbus_ih) sc_intrlist;
+ struct evcount sc_intrcnt; /* unused */
+};
+
+void vxtbus_attach(struct device *, struct device *, void *);
+int vxtbus_match(struct device *, void*, void *);
+
+struct cfdriver vxtbus_cd = {
+ NULL, "vxtbus", DV_DULL
+};
+
+struct cfattach vxtbus_ca = {
+ sizeof(struct vxtbus_softc), vxtbus_match, vxtbus_attach
+};
+
+void vxtbus_intr(void *);
+int vxtbus_print(void *, const char *);
+
+int
+vxtbus_match(struct device *parent, void *vcf, void *aux)
+{
+ struct mainbus_attach_args *maa = aux;
+
+ return (maa->maa_bustype == VAX_VXTBUS ? 1 : 0);
+}
+
+void
+vxtbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct vxtbus_softc *sc = (void *)self;
+ struct bp_conf bp;
+
+ LIST_INIT(&sc->sc_intrlist);
+ scb_vecalloc(VXT_INTRVEC, vxtbus_intr, sc, SCB_ISTACK, &sc->sc_intrcnt);
+
+ printf("\n");
+
+ bp.type = "sgec";
+ config_found(self, &bp, vxtbus_print);
+
+ bp.type = "qsc";
+ config_found(self, &bp, vxtbus_print);
+
+ bp.type = "lcspx";
+ config_found(self, &bp, vxtbus_print);
+}
+
+int
+vxtbus_print(void *aux, const char *name)
+{
+ struct bp_conf *bp = aux;
+
+ if (name)
+ printf("%s at %s", bp->type, name);
+
+ return (UNCONF);
+}
+
+/*
+ * VXT2000 interrupt code.
+ *
+ * All device interrupts end up on the same vector, which is controllable
+ * by the SC26C94 chip.
+ *
+ * The following routines implement shared interrupts for vxtbus subdevices.
+ */
+
+struct vxtbus_ih {
+ LIST_ENTRY(vxtbus_ih) ih_link;
+ int (*ih_fn)(void *);
+ void * ih_arg;
+ int ih_vec;
+ struct evcount ih_cnt;
+};
+
+void
+vxtbus_intr_establish(const char *name, int ipl, int (*fn)(void *), void *arg)
+{
+ struct vxtbus_softc *sc = (void *)vxtbus_cd.cd_devs[0];
+ struct vxtbus_ih *ih;
+
+ ih = (struct vxtbus_ih *)malloc(sizeof(*ih), M_DEVBUF, M_WAITOK);
+
+ ih->ih_fn = fn;
+ ih->ih_arg = arg;
+ ih->ih_vec = VXT_INTRVEC;
+ evcount_attach(&ih->ih_cnt, name, (void *)&ih->ih_vec, &evcount_intr);
+
+ LIST_INSERT_HEAD(&sc->sc_intrlist, ih, ih_link);
+}
+
+void
+vxtbus_intr(void *arg)
+{
+ struct vxtbus_softc *sc = arg;
+ struct vxtbus_ih *ih;
+ int rc;
+#ifdef DIAGNOSTIC
+ int handled = 0;
+ static int strayintr = 0;
+#endif
+
+ LIST_FOREACH(ih, &sc->sc_intrlist, ih_link) {
+ rc = (*ih->ih_fn)(ih->ih_arg);
+ if (rc != 0) {
+#ifdef DIAGNOSTIC
+ handled = 1;
+#endif
+ ih->ih_cnt.ec_count++;
+ if (rc > 0)
+ break;
+ }
+ }
+
+#ifdef DIAGNOSTIC
+ if (handled == 0) {
+ if (++strayintr == 10)
+ panic("too many stray interrupts");
+ else
+ printf("stray interrupt");
+ }
+#endif
+}
diff --git a/sys/arch/vax/vxt/vxtbusvar.h b/sys/arch/vax/vxt/vxtbusvar.h
new file mode 100644
index 00000000000..64e5e9543fc
--- /dev/null
+++ b/sys/arch/vax/vxt/vxtbusvar.h
@@ -0,0 +1,28 @@
+/* $OpenBSD: vxtbusvar.h,v 1.1 2006/08/27 16:55:41 miod Exp $ */
+/*
+ * Copyright (c) 2006 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * VXT2000 Hardware addresses
+ */
+#define SGECADDR_VXT 0x20008000
+#define QSCADDR 0x200a0000
+#define NISA_ROM_VXT 0x200c4000
+
+#define VXT_INTRVEC 0x200
+
+void vxtbus_intr_establish(const char *, int, int (*)(void *), void *);