diff options
Diffstat (limited to 'sys/arch/vax/vxt')
-rw-r--r-- | sys/arch/vax/vxt/if_ze_vxtbus.c | 95 | ||||
-rw-r--r-- | sys/arch/vax/vxt/qsc.c | 1078 | ||||
-rw-r--r-- | sys/arch/vax/vxt/qsckbd.c | 290 | ||||
-rw-r--r-- | sys/arch/vax/vxt/qscms.c | 167 | ||||
-rw-r--r-- | sys/arch/vax/vxt/qscreg.h | 173 | ||||
-rw-r--r-- | sys/arch/vax/vxt/qscvar.h | 115 | ||||
-rw-r--r-- | sys/arch/vax/vxt/vxtbus.c | 156 | ||||
-rw-r--r-- | sys/arch/vax/vxt/vxtbusvar.h | 28 |
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 *); |