diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2005-04-22 11:59:12 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2005-04-22 11:59:12 +0000 |
commit | 45d66f70648de09cb68227f7bc36df4b3c144a6d (patch) | |
tree | 6b3e10f3990bb400d467dcadb21cf4f03b7aa764 /sys/arch/hp300/dev | |
parent | 2859385583ab340f0cbf668de9bb48e8553d3e76 (diff) |
Driver for the Apollo Domain keyboard and mouse, for the HP 9000/4xx series.
Claims the console keyboard if a keyboard is detected at boot time,
otherwise HIL is preferred (but due to wsmux both can be used simultaneously).
Diffstat (limited to 'sys/arch/hp300/dev')
-rw-r--r-- | sys/arch/hp300/dev/apci.c | 55 | ||||
-rw-r--r-- | sys/arch/hp300/dev/apci.c.orig | 1042 | ||||
-rw-r--r-- | sys/arch/hp300/dev/apci_subr.c | 126 | ||||
-rw-r--r-- | sys/arch/hp300/dev/apcivar.h | 72 | ||||
-rw-r--r-- | sys/arch/hp300/dev/dnkbd.c | 881 | ||||
-rw-r--r-- | sys/arch/hp300/dev/dnkbdmap.c | 293 | ||||
-rw-r--r-- | sys/arch/hp300/dev/dnkbdmap.h | 28 |
7 files changed, 2447 insertions, 50 deletions
diff --git a/sys/arch/hp300/dev/apci.c b/sys/arch/hp300/dev/apci.c index cd0dddfb1e3..091ff57066a 100644 --- a/sys/arch/hp300/dev/apci.c +++ b/sys/arch/hp300/dev/apci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apci.c,v 1.22 2005/02/27 22:08:39 miod Exp $ */ +/* $OpenBSD: apci.c,v 1.23 2005/04/22 11:59:11 miod Exp $ */ /* $NetBSD: apci.c,v 1.9 2000/11/02 00:35:05 eeh Exp $ */ /*- @@ -115,6 +115,7 @@ #include <hp300/dev/frodoreg.h> #include <hp300/dev/frodovar.h> #include <hp300/dev/apcireg.h> +#include <hp300/dev/apcivar.h> #include <hp300/dev/dcareg.h> /* register bit definitions */ #ifdef DDB @@ -157,7 +158,6 @@ void apcimint(struct apci_softc *, u_char); int apciparam(struct tty *, struct termios *); void apcistart(struct tty *); int apcimctl(struct apci_softc *, int, int); -void apciinit(struct apciregs *, int); void apcitimeout(void *); cdev_decl(apci); @@ -167,26 +167,6 @@ cdev_decl(apci); int apcidefaultrate = TTYDEF_SPEED; -const struct speedtab apcispeedtab[] = { - { 0, 0 }, - { 50, APCIBRD(50) }, - { 75, APCIBRD(75) }, - { 110, APCIBRD(110) }, - { 134, APCIBRD(134) }, - { 150, APCIBRD(150) }, - { 200, APCIBRD(200) }, - { 300, APCIBRD(300) }, - { 600, APCIBRD(600) }, - { 1200, APCIBRD(1200) }, - { 1800, APCIBRD(1800) }, - { 2400, APCIBRD(2400) }, - { 4800, APCIBRD(4800) }, - { 9600, APCIBRD(9600) }, - { 19200, APCIBRD(19200) }, - { 38400, APCIBRD(38400) }, - { -1, -1 }, -}; - /* * Console support. */ @@ -318,7 +298,7 @@ apciopen(dev, flag, mode, p) * The chip might be left in an inconsistent state * if it is read inadventently. */ - apciinit(apci, apcidefaultrate); + apciinit(apci, apcidefaultrate, CFCR_8BITS); tp->t_state |= TS_WOPEN; ttychars(tp); @@ -863,31 +843,6 @@ apcimctl(sc, bits, how) } void -apciinit(apci, rate) - struct apciregs *apci; - int rate; -{ - int s; - short stat; - - s = splhigh(); - - rate = ttspeedtab(rate, apcispeedtab); - - apci->ap_cfcr = CFCR_DLAB; - apci->ap_data = rate & 0xff; - apci->ap_ier = (rate >> 8) & 0xff; - apci->ap_cfcr = CFCR_8BITS; - apci->ap_ier = IER_ERXRDY | IER_ETXRDY; - apci->ap_fifo = - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1; - apci->ap_mcr = MCR_DTR | MCR_RTS; - delay(100); - stat = apci->ap_iir; - splx(s); -} - -void apcitimeout(arg) void *arg; { @@ -984,7 +939,7 @@ apcicninit(cp) return; apci_cn = (struct apciregs *)IIOV(FRODO_BASE + FRODO_APCI_OFFSET(1)); - apciinit(apci_cn, apcidefaultrate); + apciinit(apci_cn, apcidefaultrate, CFCR_8BITS); apciconsinit = 1; } @@ -1020,7 +975,7 @@ apcicnputc(dev, c) s = splhigh(); if (apciconsinit == 0) { - apciinit(apci_cn, apcidefaultrate); + apciinit(apci_cn, apcidefaultrate, CFCR_8BITS); apciconsinit = 1; } diff --git a/sys/arch/hp300/dev/apci.c.orig b/sys/arch/hp300/dev/apci.c.orig new file mode 100644 index 00000000000..2f29f253f47 --- /dev/null +++ b/sys/arch/hp300/dev/apci.c.orig @@ -0,0 +1,1042 @@ +/* $OpenBSD: apci.c.orig,v 1.1 2005/04/22 11:59:11 miod Exp $ */ +/* $NetBSD: apci.c,v 1.9 2000/11/02 00:35:05 eeh Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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 by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright (c) 1997 Michael Smith. All rights reserved. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. 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. 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. + * + * @(#)dca.c 8.2 (Berkeley) 1/12/94 + */ + +/* + * Device driver for the APCI 8250-like UARTs found on the Apollo + * Utility Chip on HP 9000/400-series workstations. + * + * There are 4 APCI UARTs on the Frodo ASIC. The first one + * is used to communicate with the Domain keyboard. The second + * one is the serial console port when the firmware is in Domain/OS + * mode, and is mapped to select code 9 by the HP-UX firmware (except + * on 425e models). + * + * We don't bother attaching a tty to the first UART; it lacks modem/flow + * control, and is directly connected to the keyboard connector anyhow. + */ + +/* + * XXX This driver is very similar to the dca driver, and much + * XXX more code could be shared. (Currently, no code is shared.) + * XXX FIXME! + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/tty.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/timeout.h> + +#include <machine/autoconf.h> +#include <machine/cpu.h> +#include <machine/hp300spu.h> + +#include <dev/cons.h> + +#include <hp300/dev/dioreg.h> /* to check for dca at 9 */ +#include <hp300/dev/diovar.h> +#include <hp300/dev/diodevs.h> + +#include <hp300/dev/frodoreg.h> +#include <hp300/dev/frodovar.h> +#include <hp300/dev/apcireg.h> +#include <hp300/dev/dcareg.h> /* register bit definitions */ + +#ifdef DDB +#include <ddb/db_var.h> +#endif + +struct apci_softc { + struct device sc_dev; /* generic device glue */ + struct isr sc_isr; + struct apciregs *sc_apci; /* device registers */ + struct tty *sc_tty; /* tty glue */ + struct timeout sc_timeout; /* timeout */ + int sc_ferr, + sc_perr, + sc_oflow, + sc_toterr; /* stats */ + int sc_flags; + u_char sc_cua; /* callout mode */ +}; + +/* sc_flags */ +#define APCI_HASFIFO 0x01 /* unit has a fifo */ +#define APCI_ISCONSOLE 0x02 /* unit is console */ +#define APCI_SOFTCAR 0x04 /* soft carrier */ + +int apcimatch(struct device *, void *, void *); +void apciattach(struct device *, struct device *, void *); + +struct cfattach apci_ca = { + sizeof(struct apci_softc), apcimatch, apciattach +}; + +struct cfdriver apci_cd = { + NULL, "apci", DV_TTY +}; + +int apciintr(void *); +void apcieint(struct apci_softc *, int); +void apcimint(struct apci_softc *, u_char); +int apciparam(struct tty *, struct termios *); +void apcistart(struct tty *); +int apcimctl(struct apci_softc *, int, int); +void apciinit(struct apciregs *, int); +void apcitimeout(void *); + +cdev_decl(apci); + +#define APCIUNIT(x) (minor(x) & 0x7f) +#define APCICUA(x) (minor(x) & 0x80) + +int apcidefaultrate = TTYDEF_SPEED; + +const struct speedtab apcispeedtab[] = { + { 0, 0 }, + { 50, APCIBRD(50) }, + { 75, APCIBRD(75) }, + { 110, APCIBRD(110) }, + { 134, APCIBRD(134) }, + { 150, APCIBRD(150) }, + { 200, APCIBRD(200) }, + { 300, APCIBRD(300) }, + { 600, APCIBRD(600) }, + { 1200, APCIBRD(1200) }, + { 1800, APCIBRD(1800) }, + { 2400, APCIBRD(2400) }, + { 4800, APCIBRD(4800) }, + { 9600, APCIBRD(9600) }, + { 19200, APCIBRD(19200) }, + { 38400, APCIBRD(38400) }, + { -1, -1 }, +}; + +/* + * Console support. + */ +struct apciregs *apci_cn = NULL; /* console hardware */ +int apciconsinit; /* has been initialized */ +int apcimajor; /* our major number */ + +cons_decl(apci); + +int +apcimatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct frodo_attach_args *fa = aux; + + /* Looking for an apci? */ + if (strcmp(fa->fa_name, apci_cd.cd_name) != 0) + return (0); + + /* Are we checking a valid APCI offset? */ + switch (fa->fa_offset) { + case FRODO_APCI_OFFSET(1): + case FRODO_APCI_OFFSET(2): + case FRODO_APCI_OFFSET(3): + /* Yup, we exist! */ + return (1); + } + + return (0); +} + +void +apciattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct apci_softc *sc = (struct apci_softc *)self; + struct apciregs *apci; + struct frodo_attach_args *fa = aux; + + sc->sc_apci = apci = + (struct apciregs *)IIOV(FRODO_BASE + fa->fa_offset); + sc->sc_flags = 0; + + /* Initialize timeout structure */ + timeout_set(&sc->sc_timeout, apcitimeout, sc); + + /* Are we the console? */ + if (apci == apci_cn) { + sc->sc_flags |= APCI_ISCONSOLE; + delay(100000); + + /* + * We didn't know which unit this would be during + * the console probe, so we have to fixup cn_dev here. + */ + cn_tab->cn_dev = makedev(apcimajor, self->dv_unit); + } + + /* Look for a FIFO. */ + apci->ap_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; + delay(100); + if ((apci->ap_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) + sc->sc_flags |= APCI_HASFIFO; + + /* Establish our interrupt handler. */ + sc->sc_isr.isr_func = apciintr; + sc->sc_isr.isr_arg = sc; + sc->sc_isr.isr_priority = + (sc->sc_flags & APCI_HASFIFO) ? IPL_TTY : IPL_TTYNOBUF; + frodo_intr_establish(parent, fa->fa_line, &sc->sc_isr, self->dv_xname); + + /* Set soft carrier if requested by operator. */ + if (self->dv_cfdata->cf_flags) + sc->sc_flags |= APCI_SOFTCAR; + + /* + * Need to reset baud rate, etc. of next print, so reset apciconsinit. + * Also make sure console is always "hardwired". + */ + if (sc->sc_flags & APCI_ISCONSOLE) { + apciconsinit = 0; + sc->sc_flags |= APCI_SOFTCAR; + printf(": console, "); + } else + printf(": "); + + if (sc->sc_flags & APCI_HASFIFO) + printf("working fifo\n"); + else + printf("no fifo\n"); +} + +/* ARGSUSED */ +int +apciopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = APCIUNIT(dev); + struct apci_softc *sc; + struct tty *tp; + struct apciregs *apci; + u_char code; + int s, error = 0; + + if (unit >= apci_cd.cd_ndevs || + (sc = apci_cd.cd_devs[unit]) == NULL) + return (ENXIO); + + apci = sc->sc_apci; + + s = spltty(); + if (sc->sc_tty == NULL) { + tp = sc->sc_tty = ttymalloc(); + } else + tp = sc->sc_tty; + splx(s); + + tp->t_oproc = apcistart; + tp->t_param = apciparam; + tp->t_dev = dev; + + if ((tp->t_state & TS_ISOPEN) == 0) { + /* + * Sanity clause: reset the chip on first open. + * The chip might be left in an inconsistent state + * if it is read inadventently. + */ + apciinit(apci, apcidefaultrate); + + tp->t_state |= TS_WOPEN; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = apcidefaultrate; + + s = spltty(); + + apciparam(tp, &tp->t_termios); + ttsetwater(tp); + + /* Set the FIFO threshold based on the receive speed. */ + if (sc->sc_flags & APCI_HASFIFO) + apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST | + FIFO_XMT_RST | + (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : + FIFO_TRIGGER_14); + + /* Flush any pending I/O. */ + while ((apci->ap_iir & IIR_IMASK) == IIR_RXRDY) + code = apci->ap_data; + } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) + return (EBUSY); + else + s = spltty(); + + /* Set the modem control state. */ + (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMSET); + + /* Set soft-carrier if so configured. */ + if ((sc->sc_flags & APCI_SOFTCAR) || APCICUA(dev) || + (apcimctl(sc, 0, DMGET) & MSR_DCD)) + tp->t_state |= TS_CARR_ON; + + if (APCICUA(dev)) { + if (tp->t_state & TS_ISOPEN) { + /* Ah, but someone already is dialed in... */ + splx(s); + return (EBUSY); + } + sc->sc_cua = 1; /* We go into CUA mode */ + } + + /* Wait for carrier if necessary. */ + if (flag & O_NONBLOCK) { + if (!APCICUA(dev) && sc->sc_cua) { + /* Opening TTY non-blocking... but the CUA is busy */ + splx(s); + return (EBUSY); + } + } else { + while (sc->sc_cua || + ((tp->t_cflag & CLOCAL) == 0 && + (tp->t_state & TS_CARR_ON) == 0)) { + tp->t_state |= TS_WOPEN; + error = ttysleep(tp, (caddr_t)&tp->t_rawq, + TTIPRI | PCATCH, ttopen, 0); + if (!APCICUA(dev) && sc->sc_cua && error == EINTR) + continue; + if (error) { + if (APCICUA(dev)) + sc->sc_cua = 0; + splx(s); + return (error); + } + if (!APCICUA(dev) && sc->sc_cua) + continue; + } + } + + splx(s); + + if (error == 0) + error = (*linesw[tp->t_line].l_open)(dev, tp); + + if (error == 0) { + /* clear errors, start timeout */ + sc->sc_ferr = sc->sc_perr = sc->sc_oflow = sc->sc_toterr = 0; + timeout_add(&sc->sc_timeout, hz); + } + + return (error); +} + +/* ARGSUSED */ +int +apciclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + struct apci_softc *sc; + struct tty *tp; + struct apciregs *apci; + int unit = APCIUNIT(dev); + int s; + + sc = apci_cd.cd_devs[unit]; + apci = sc->sc_apci; + tp = sc->sc_tty; + + (*linesw[tp->t_line].l_close)(tp, flag); + + s = spltty(); + + apci->ap_cfcr &= ~CFCR_SBREAK; + apci->ap_ier = 0; + if (tp->t_cflag & HUPCL && (sc->sc_flags & APCI_SOFTCAR) == 0) { + /* XXX perhaps only clear DTR */ + (void) apcimctl(sc, 0, DMSET); + } + tp->t_state &= ~(TS_BUSY | TS_FLUSH); + sc->sc_cua = 0; + splx(s); + ttyclose(tp); +#if 0 + ttyfree(tp); + sc->sc_tty = NULL; +#endif + return (0); +} + +int +apciread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +apciwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +struct tty * +apcitty(dev) + dev_t dev; +{ + struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; + + return (sc->sc_tty); +} + +int +apciintr(arg) + void *arg; +{ + struct apci_softc *sc = arg; + struct apciregs *apci = sc->sc_apci; + struct tty *tp = sc->sc_tty; + u_char iir, lsr, c; + int iflowdone = 0, claimed = 0; + +#define RCVBYTE() \ + c = apci->ap_data; \ + if (tp != NULL && (tp->t_state & TS_ISOPEN) != 0) \ + (*linesw[tp->t_line].l_rint)(c, tp) + + for (;;) { + iir = apci->ap_iir; /* get UART status */ + + switch (iir & IIR_IMASK) { + case IIR_RLS: + apcieint(sc, apci->ap_lsr); + break; + + case IIR_RXRDY: + case IIR_RXTOUT: + RCVBYTE(); + if (sc->sc_flags & APCI_HASFIFO) { + while ((lsr = apci->ap_lsr) & LSR_RCV_MASK) { + if (lsr == LSR_RXRDY) { + RCVBYTE(); + } else + apcieint(sc, lsr); + } + } + if (iflowdone == 0 && tp != NULL && + (tp->t_cflag & CRTS_IFLOW) && + tp->t_rawq.c_cc > (TTYHOG / 2)) { + apci->ap_mcr &= ~MCR_RTS; + iflowdone = 1; + } + break; + + case IIR_TXRDY: + if (tp != NULL) { + tp->t_state &=~ (TS_BUSY|TS_FLUSH); + if (tp->t_line) + (*linesw[tp->t_line].l_start)(tp); + else + apcistart(tp); + } + break; + + default: + if (iir & IIR_NOPEND) + return (claimed); + log(LOG_WARNING, "%s: weird interrupt: 0x%x\n", + sc->sc_dev.dv_xname, iir); + /* FALLTHROUGH */ + + case IIR_MLSC: + apcimint(sc, apci->ap_msr); + break; + } + + claimed = 1; + } +} + +void +apcieint(sc, stat) + struct apci_softc *sc; + int stat; +{ + struct tty *tp = sc->sc_tty; + struct apciregs *apci = sc->sc_apci; + int c; + + c = apci->ap_data; + +#ifdef DDB + if ((sc->sc_flags & APCI_ISCONSOLE) && db_console && (stat & LSR_BI)) { + Debugger(); + return; + } +#endif + + if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) + return; + + if (stat & (LSR_BI | LSR_FE)) { + c |= TTY_FE; + sc->sc_ferr++; + } else if (stat & LSR_PE) { + c |= TTY_PE; + sc->sc_perr++; + } else if (stat & LSR_OE) + sc->sc_oflow++; + (*linesw[tp->t_line].l_rint)(c, tp); +} + +void +apcimint(sc, stat) + struct apci_softc *sc; + u_char stat; +{ + struct tty *tp = sc->sc_tty; + struct apciregs *apci = sc->sc_apci; + + if (tp == NULL) + return; + + if ((stat & MSR_DDCD) && + (sc->sc_flags & APCI_SOFTCAR) == 0) { + if (stat & MSR_DCD) + (void)(*linesw[tp->t_line].l_modem)(tp, 1); + else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) + apci->ap_mcr &= ~(MCR_DTR | MCR_RTS); + } + + /* + * CTS change. + * If doing HW output flow control, start/stop output as appropriate. + */ + if ((stat & MSR_DCTS) && + (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) { + if (stat & MSR_CTS) { + tp->t_state &=~ TS_TTSTOP; + apcistart(tp); + } else + tp->t_state |= TS_TTSTOP; + } +} + +int +apciioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)]; + struct tty *tp = sc->sc_tty; + struct apciregs *apci = sc->sc_apci; + int error; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + switch (cmd) { + case TIOCSBRK: + apci->ap_cfcr |= CFCR_SBREAK; + break; + + case TIOCCBRK: + apci->ap_cfcr &= ~CFCR_SBREAK; + break; + + case TIOCSDTR: + (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIS); + break; + + case TIOCCDTR: + (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIC); + break; + + case TIOCMSET: + (void) apcimctl(sc, *(int *)data, DMSET); + break; + + case TIOCMBIS: + (void) apcimctl(sc, *(int *)data, DMBIS); + break; + + case TIOCMBIC: + (void) apcimctl(sc, *(int *)data, DMBIC); + break; + + case TIOCMGET: + *(int *)data = apcimctl(sc, 0, DMGET); + break; + + case TIOCGFLAGS: { + int bits = 0; + + if (sc->sc_flags & APCI_SOFTCAR) + bits |= TIOCFLAG_SOFTCAR; + + if (tp->t_cflag & CLOCAL) + bits |= TIOCFLAG_CLOCAL; + + *(int *)data = bits; + break; + } + + case TIOCSFLAGS: { + int userbits; + + error = suser(p, 0); + if (error) + return (EPERM); + + userbits = *(int *)data; + + if ((userbits & TIOCFLAG_SOFTCAR) || + (sc->sc_flags & APCI_ISCONSOLE)) + sc->sc_flags |= APCI_SOFTCAR; + + if (userbits & TIOCFLAG_CLOCAL) + tp->t_cflag |= CLOCAL; + + break; + } + + default: + return (ENOTTY); + } + return (0); +} + +int +apciparam(tp, t) + struct tty *tp; + struct termios *t; +{ + struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(tp->t_dev)]; + struct apciregs *apci = sc->sc_apci; + int cfcr, cflag = t->c_cflag; + int ospeed = ttspeedtab(t->c_ospeed, apcispeedtab); + int s; + + /* check requested parameters */ + if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) + return (EINVAL); + + switch (cflag & CSIZE) { + case CS5: + cfcr = CFCR_5BITS; + break; + + case CS6: + cfcr = CFCR_6BITS; + break; + + case CS7: + cfcr = CFCR_7BITS; + break; + + case CS8: + default: /* XXX gcc whines about cfcr being uninitialized... */ + cfcr = CFCR_8BITS; + break; + } + if (cflag & PARENB) { + cfcr |= CFCR_PENAB; + if ((cflag & PARODD) == 0) + cfcr |= CFCR_PEVEN; + } + if (cflag & CSTOPB) + cfcr |= CFCR_STOPB; + + s = spltty(); + + if (ospeed == 0) + (void) apcimctl(sc, 0, DMSET); /* hang up line */ + + /* + * Set the FIFO threshold based on the receive speed, if we + * are changing it. + */ + if (tp->t_ispeed != t->c_ispeed) { + if (sc->sc_flags & APCI_HASFIFO) + apci->ap_fifo = FIFO_ENABLE | + (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : + FIFO_TRIGGER_14); + } + + if (ospeed != 0) { + apci->ap_cfcr |= CFCR_DLAB; + apci->ap_data = ospeed & 0xff; + apci->ap_ier = (ospeed >> 8) & 0xff; + apci->ap_cfcr = cfcr; + } else + apci->ap_cfcr = cfcr; + + /* and copy to tty */ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = cflag; + + apci->ap_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; + + splx(s); + return (0); +} + +void +apcistart(tp) + struct tty *tp; +{ + struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(tp->t_dev)]; + struct apciregs *apci = sc->sc_apci; + int s, c; + + s = spltty(); + + if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) + goto out; + 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); + } + if (tp->t_outq.c_cc == 0) + goto out; + selwakeup(&tp->t_wsel); + } + if (apci->ap_lsr & LSR_TXRDY) { + tp->t_state |= TS_BUSY; + if (sc->sc_flags & APCI_HASFIFO) { + for (c = 0; c < 16 && tp->t_outq.c_cc; ++c) + apci->ap_data = getc(&tp->t_outq); + } else + apci->ap_data = getc(&tp->t_outq); + } + + out: + splx(s); +} + +/* + * Stop output on a line. + */ +/* ARGSUSED */ +int +apcistop(tp, flag) + 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 +apcimctl(sc, bits, how) + struct apci_softc *sc; + int bits, how; +{ + struct apciregs *apci = sc->sc_apci; + int s; + + s = spltty(); + + switch (how) { + case DMSET: + apci->ap_mcr = bits; + break; + + case DMBIS: + apci->ap_mcr |= bits; + break; + + case DMBIC: + apci->ap_mcr &= ~bits; + break; + + case DMGET: + bits = apci->ap_msr; + break; + } + + splx(s); + return (bits); +} + +void +apciinit(apci, rate) + struct apciregs *apci; + int rate; +{ + int s; + short stat; + + s = splhigh(); + + rate = ttspeedtab(rate, apcispeedtab); + + apci->ap_cfcr = CFCR_DLAB; + apci->ap_data = rate & 0xff; + apci->ap_ier = (rate >> 8) & 0xff; + apci->ap_cfcr = CFCR_8BITS; + apci->ap_ier = IER_ERXRDY | IER_ETXRDY; + apci->ap_fifo = + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1; + apci->ap_mcr = MCR_DTR | MCR_RTS; + delay(100); + stat = apci->ap_iir; + splx(s); +} + +void +apcitimeout(arg) + void *arg; +{ + struct apci_softc *sc = arg; + int ferr, perr, oflow, s; + + if (sc->sc_tty == NULL || + (sc->sc_tty->t_state & TS_ISOPEN) == 0) + return; + + /* Log any errors. */ + if (sc->sc_ferr || sc->sc_perr || sc->sc_oflow) { + s = spltty(); /* XXX necessary? */ + ferr = sc->sc_ferr; + perr = sc->sc_perr; + oflow = sc->sc_oflow; + sc->sc_ferr = sc->sc_perr = sc->sc_oflow = 0; + splx(s); + sc->sc_toterr += ferr + perr + oflow; + log(LOG_WARNING, + "%s: %d frame, %d parity, %d overflow, %d total errors\n", + sc->sc_dev.dv_xname, ferr, perr, oflow, sc->sc_toterr); + } + + timeout_add(&sc->sc_timeout, hz); +} + +/* + * The following routines are required for the APCI to act as the console. + */ + +void +apcicnprobe(cp) + struct consdev *cp; +{ + volatile u_int8_t *frodoregs; + + /* locate the major number */ + for (apcimajor = 0; apcimajor < nchrdev; apcimajor++) + if (cdevsw[apcimajor].d_open == apciopen) + break; + + /* initialize the required fields */ + cp->cn_dev = makedev(apcimajor, 0); /* XXX */ + cp->cn_pri = CN_DEAD; + + /* Abort early if console is already forced. */ + if (conforced) + return; + + /* + * The APCI can only be a console on a 425e; on other 4xx + * models, the "first" serial port is mapped to the DCA + * at select code 9. See frodo.c for the autoconfiguration + * version of this check. + */ + if (machineid != HP_425 || mmuid != MMUID_425_E) + return; + + /* + * Check the service switch. On the 425e, this is a physical + * switch, unlike other frodo-based machines, so we can use it + * as a serial vs internal video selector, since the PROM can not + * be configured for serial console. + */ + frodoregs = (volatile u_int8_t *)IIOV(FRODO_BASE); + if (badaddr((caddr_t)frodoregs) == 0 && + !ISSET(frodoregs[FRODO_IISR], FRODO_IISR_SERVICE)) { + cp->cn_pri = CN_REMOTE; + conforced = 1; + conscode = -2; /* XXX */ + } else { + cp->cn_pri = CN_NORMAL; + } + + /* + * If our priority is higher than the currently-remembered + * console, install ourselves. + */ + if (((cn_tab == NULL) || (cp->cn_pri > cn_tab->cn_pri)) || conforced) + cn_tab = cp; +} + +/* ARGSUSED */ +void +apcicninit(cp) + struct consdev *cp; +{ + + /* + * We are not interested by the second console pass. + */ + if (consolepass != 0) + return; + + apci_cn = (struct apciregs *)IIOV(FRODO_BASE + FRODO_APCI_OFFSET(1)); + apciinit(apci_cn, apcidefaultrate); + apciconsinit = 1; +} + +/* ARGSUSED */ +int +apcicngetc(dev) + dev_t dev; +{ + u_char stat; + int c, s; + + s = splhigh(); + while (((stat = apci_cn->ap_lsr) & LSR_RXRDY) == 0) + ; + c = apci_cn->ap_data; + + /* clear any interrupts generated by this transmission */ + stat = apci_cn->ap_iir; + splx(s); + return (c); +} + +/* ARGSUSED */ +void +apcicnputc(dev, c) + dev_t dev; + int c; +{ + int timo; + u_char stat; + int s; + + s = splhigh(); + + if (apciconsinit == 0) { + apciinit(apci_cn, apcidefaultrate); + apciconsinit = 1; + } + + /* wait for any pending transmission to finish */ + timo = 50000; + while (((stat = apci_cn->ap_lsr) & LSR_TXRDY) == 0 && --timo) + ; + + apci_cn->ap_data = c & 0xff; + + /* wait for this transmission to complete */ + timo = 1500000; + while (((stat = apci_cn->ap_lsr) & LSR_TXRDY) == 0 && --timo) + ; + + /* clear any interrupts generated by this transmission */ + stat = apci_cn->ap_iir; + splx(s); +} diff --git a/sys/arch/hp300/dev/apci_subr.c b/sys/arch/hp300/dev/apci_subr.c new file mode 100644 index 00000000000..dafff24c2f6 --- /dev/null +++ b/sys/arch/hp300/dev/apci_subr.c @@ -0,0 +1,126 @@ +/* $OpenBSD: apci_subr.c,v 1.1 2005/04/22 11:59:11 miod Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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 by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright (c) 1997 Michael Smith. All rights reserved. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. 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. 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. + * + * @(#)dca.c 8.2 (Berkeley) 1/12/94 + */ + +/* + * Routines shared by the apci and dnkbd drivers. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/tty.h> +#include <sys/kernel.h> + +#include <hp300/dev/apcireg.h> +#include <hp300/dev/apcivar.h> +#include <hp300/dev/dcareg.h> + +const struct speedtab apcispeedtab[] = { + { 0, 0 }, + { 50, APCIBRD(50) }, + { 75, APCIBRD(75) }, + { 110, APCIBRD(110) }, + { 134, APCIBRD(134) }, + { 150, APCIBRD(150) }, + { 200, APCIBRD(200) }, + { 300, APCIBRD(300) }, + { 600, APCIBRD(600) }, + { 1200, APCIBRD(1200) }, + { 1800, APCIBRD(1800) }, + { 2400, APCIBRD(2400) }, + { 4800, APCIBRD(4800) }, + { 9600, APCIBRD(9600) }, + { 19200, APCIBRD(19200) }, + { 38400, APCIBRD(38400) }, + { -1, -1 }, +}; + +int +apciinit(struct apciregs *apci, u_int16_t rate, u_int16_t cfcr) +{ + int s, stat; + + s = splhigh(); + + rate = ttspeedtab(rate, apcispeedtab); + + apci->ap_cfcr = CFCR_DLAB; + apci->ap_data = rate & 0xff; + apci->ap_ier = (rate >> 8) & 0xff; + apci->ap_cfcr = cfcr; + apci->ap_ier = IER_ERXRDY | IER_ETXRDY; + apci->ap_fifo = + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1; + apci->ap_mcr = MCR_DTR | MCR_RTS; + delay(100); + stat = apci->ap_iir; + splx(s); + + return (stat); +} diff --git a/sys/arch/hp300/dev/apcivar.h b/sys/arch/hp300/dev/apcivar.h new file mode 100644 index 00000000000..d72bfcbe2d1 --- /dev/null +++ b/sys/arch/hp300/dev/apcivar.h @@ -0,0 +1,72 @@ +/* $OpenBSD: apcivar.h,v 1.1 2005/04/22 11:59:11 miod Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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 by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright (c) 1997 Michael Smith. All rights reserved. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. 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. 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. + * + * @(#)dca.c 8.2 (Berkeley) 1/12/94 + */ + +int apciinit(struct apciregs *, u_int16_t, u_int16_t); +extern const struct speedtab apcispeedtab[]; diff --git a/sys/arch/hp300/dev/dnkbd.c b/sys/arch/hp300/dev/dnkbd.c new file mode 100644 index 00000000000..917c9454ed8 --- /dev/null +++ b/sys/arch/hp300/dev/dnkbd.c @@ -0,0 +1,881 @@ +/* $OpenBSD: dnkbd.c,v 1.1 2005/04/22 11:59:11 miod Exp $ */ + +/* + * Copyright (c) 2005, Miodrag Vallat + * Copyright (c) 1997 Michael Smith. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Driver for the Apollo Domain keyboard and mouse. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> +#include <sys/timeout.h> + +#include <machine/autoconf.h> +#include <machine/cpu.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> +#ifdef WSDISPLAY_COMPAT_RAWKBD +#include <dev/wscons/wskbdraw.h> +#endif +#include <dev/wscons/wsmousevar.h> + +#include <hp300/dev/apcireg.h> +#include <hp300/dev/apcivar.h> +#include <hp300/dev/dcareg.h> +#include <hp300/dev/dnkbdmap.h> +#include <hp300/dev/frodoreg.h> +#include <hp300/dev/frodovar.h> + +#include "hilkbd.h" + +/* + * Keyboard key codes + */ + +#define DNKEY_REPEAT 0x7e +#define DNKEY_RELEASE 0x80 +#define DNKEY_CHANNEL 0xff + +/* + * Channels + */ + +#define DNCHANNEL_RESET 0x00 +#define DNCHANNEL_KBD 0x01 +#define DNCHANNEL_MOUSE 0x02 + +/* + * Keyboard modes + */ + +#define DNMODE_COOKED 0x00 +#define DNMODE_RAW 0x01 + +/* + * Keyboard commands + */ + +#define DNCMD_PREFIX 0xff +#define DNCMD_COOKED DNMODE_COOKED +#define DNCMD_RAW DNMODE_RAW +#define DNCMD_IDENT_1 0x12 +#define DNCMD_IDENT_2 0x21 + +/* + * Mouse status + */ + +#define DNBUTTON_L 0x10 +#define DNBUTTON_R 0x20 +#define DNBUTTON_M 0x40 + +struct dnkbd_softc { + struct device sc_dev; + struct isr sc_isr; + struct apciregs *sc_regs; + + int sc_flags; +#define SF_ENABLED 0x01 /* keyboard enabled */ +#define SF_CONSOLE 0x02 /* keyboard is console */ +#define SF_POLLING 0x04 /* polling mode */ +#define SF_PLUGGED 0x08 /* keyboard has been seen plugged */ +#define SF_ATTACHED 0x10 /* subdevices have been attached */ +#define SF_MOUSE 0x20 /* mouse enabled */ + + u_int sc_identlen; +#define MAX_IDENTLEN 32 + char sc_ident[MAX_IDENTLEN]; + + enum { STATE_KEYBOARD, STATE_MOUSE, STATE_CHANNEL } sc_state; + + u_int8_t sc_mousepkt[3]; /* mouse packet being constructed */ + u_int sc_mousepos; /* index in above */ + + struct device *sc_wskbddev; + struct device *sc_wsmousedev; + +#ifdef WSDISPLAY_COMPAT_RAWKBD + int sc_rawkbd; + int sc_nrep; + char sc_rep[2]; /* at most, one key */ + struct timeout sc_rawrepeat_ch; +#define REP_DELAY1 400 +#define REP_DELAYN 100 +#endif +}; + +int dnkbd_match(struct device *, void *, void *); +void dnkbd_attach(struct device *, struct device *, void *); + +struct cfdriver dnkbd_cd = { + NULL, "dnkbd", DV_DULL +}; + +struct cfattach dnkbd_ca = { + sizeof(struct dnkbd_softc), dnkbd_match, dnkbd_attach +}; + +int dnkbd_enable(void *, int); +void dnkbd_set_leds(void *, int); +int dnkbd_ioctl(void *, u_long, caddr_t, int, struct proc *); + +const struct wskbd_accessops dnkbd_accessops = { + dnkbd_enable, + dnkbd_set_leds, + dnkbd_ioctl +}; + +int dnmouse_enable(void *); +int dnmouse_ioctl(void *, u_long, caddr_t, int, struct proc *); +void dnmouse_disable(void *); + +const struct wsmouse_accessops dnmouse_accessops = { + dnmouse_enable, + dnmouse_ioctl, + dnmouse_disable +}; + +void dnkbd_cngetc(void *, u_int *, int *); +void dnkbd_cnpollc(void *, int); + +const struct wskbd_consops dnkbd_consops = { + dnkbd_cngetc, + dnkbd_cnpollc, + NULL /* bell */ +}; + +struct wskbd_mapdata dnkbd_keymapdata = { + dnkbd_keydesctab, + KB_US +}; + +typedef enum { EVENT_NONE, EVENT_KEYBOARD, EVENT_MOUSE } dnevent; + +void dnevent_kbd(struct dnkbd_softc *, int); +void dnevent_mouse(struct dnkbd_softc *, u_int8_t *); +void dnkbd_attach_subdevices(struct dnkbd_softc *); +void dnkbd_decode(int, u_int *, int *); +int dnkbd_init(struct apciregs *); +dnevent dnkbd_input(struct dnkbd_softc *, int); +int dnkbd_intr(void *); +int dnkbd_pollin(struct apciregs *, u_int); +int dnkbd_pollout(struct apciregs *, int); +int dnkbd_probe(struct dnkbd_softc *); +void dnkbd_rawrepeat(void *); +int dnkbd_send(struct apciregs *, u_int8_t *, size_t); +int dnsubmatch_kbd(struct device *, void *, void *); +int dnsubmatch_mouse(struct device *, void *, void *); + +int +dnkbd_match(struct device *parent, void *match, void *aux) +{ + struct frodo_attach_args *fa = aux; + + if (strcmp(fa->fa_name, dnkbd_cd.cd_name) != 0) + return (0); + + /* only attach to the first frodo port */ + return (fa->fa_offset == FRODO_APCI_OFFSET(0)); +} + +void +dnkbd_attach(struct device *parent, struct device *self, void *aux) +{ + struct dnkbd_softc *sc = (struct dnkbd_softc *)self; + struct frodo_attach_args *fa = aux; + + printf(": "); + + sc->sc_regs = (struct apciregs *)IIOV(FRODO_BASE + fa->fa_offset); + +#ifdef WSDISPLAY_COMPAT_RAWKBD + timeout_set(&sc->sc_rawrepeat_ch, dnkbd_rawrepeat, sc); +#endif + + /* reset the port */ + apciinit(sc->sc_regs, 1200, CFCR_8BITS | CFCR_PEVEN | CFCR_PENAB); + + sc->sc_isr.isr_func = dnkbd_intr; + sc->sc_isr.isr_arg = sc; + sc->sc_isr.isr_priority = IPL_TTY; + frodo_intr_establish(parent, fa->fa_line, &sc->sc_isr, self->dv_xname); + + /* probe for keyboard */ + if (dnkbd_probe(sc) != 0) { + printf("no keyboard\n"); + return; + } + + dnkbd_attach_subdevices(sc); +} + +void +dnkbd_attach_subdevices(struct dnkbd_softc *sc) +{ + struct wskbddev_attach_args ka; + struct wsmousedev_attach_args ma; +#if NHILKBD > 0 + extern int hil_is_console; +#endif + + /* + * If both hilkbd and dnkbd are configured, prefer the Domain + * keyboard as console (if we are here, we know the keyboard is + * plugged). But if it's a late hotplug, the hil code will have + * claimed the console keyboard, so don't claim it now. + * Unfortunately, the hil code will claim the console keyboard + * even if no HIL keyboard is connected... + */ +#if NHILKBD > 0 + if (hil_is_console == -1) { + ka.console = 1; + hil_is_console = 0; + } else + ka.console = 0; +#else + ka.console = 1; +#endif + ka.keymap = &dnkbd_keymapdata; + ka.accessops = &dnkbd_accessops; + ka.accesscookie = sc; + + if (ka.console) { + sc->sc_flags = SF_PLUGGED | SF_CONSOLE | SF_ENABLED; + wskbd_cnattach(&dnkbd_consops, sc, &dnkbd_keymapdata); + } else { + sc->sc_flags = SF_PLUGGED; + } + + sc->sc_wskbddev = config_found_sm(&sc->sc_dev, &ka, wskbddevprint, + dnsubmatch_kbd); + + ma.accessops = &dnmouse_accessops; + ma.accesscookie = sc; + + sc->sc_wsmousedev = config_found_sm(&sc->sc_dev, &ma, wsmousedevprint, + dnsubmatch_mouse); + + SET(sc->sc_flags, SF_ATTACHED); +} + +int +dnsubmatch_kbd(struct device *parent, void *match, void *aux) +{ + struct cfdata *cf = match; + extern struct cfdriver wskbd_cd; + + if (strcmp(cf->cf_driver->cd_name, wskbd_cd.cd_name) != 0) + return (0); + + return ((*cf->cf_attach->ca_match)(parent, cf, aux)); +} + +int +dnsubmatch_mouse(struct device *parent, void *match, void *aux) +{ + struct cfdata *cf = match; + extern struct cfdriver wsmouse_cd; + + if (strcmp(cf->cf_driver->cd_name, wsmouse_cd.cd_name) != 0) + return (0); + + return ((*cf->cf_attach->ca_match)(parent, cf, aux)); +} + +int +dnkbd_probe(struct dnkbd_softc *sc) +{ + int dat, rc; + u_int8_t cmdbuf[2]; + char rspbuf[MAX_IDENTLEN], *word, *end; + u_int i; + int s; + + s = splhigh(); + + /* + * Switch keyboard to raw mode. + */ + cmdbuf[0] = DNCMD_RAW; + rc = dnkbd_send(sc->sc_regs, cmdbuf, 1); + if (rc != 0) { + splx(s); + return (rc); + } + + /* + * Send the identify command. + */ + cmdbuf[0] = DNCMD_IDENT_1; + cmdbuf[1] = DNCMD_IDENT_2; + rc = dnkbd_send(sc->sc_regs, cmdbuf, 2); + if (rc != 0) { + splx(s); + return (rc); + } + + for (i = 0; ; i++) { + dat = dnkbd_pollin(sc->sc_regs, 10000); + if (dat == -1) + break; + + if (i < sizeof(rspbuf)) + rspbuf[i] = dat; + } + + if (i >= sizeof(rspbuf)) { + printf("%s: unexpected identify string length %d\n", + sc->sc_dev.dv_xname, i); + splx(s); + return (ENXIO); + } + + /* + * Make sure the identification string is NULL terminated + * (overwriting the keyboard mode byte if necessary). + */ + if (i == sizeof(rspbuf) && dat != 0) + rspbuf[--i] = 0; + + /* + * Now display the identification strings, if it changed. + */ + if (i != sc->sc_identlen || bcmp(rspbuf, sc->sc_ident, i) != 0) { + sc->sc_identlen = i; + bcopy(rspbuf, sc->sc_ident, i); + + if (cold == 0) + printf("%s: ", sc->sc_dev.dv_xname); + word = rspbuf; + for (i = 0; i < 3; i++) { + end = strchr(word, '\r'); + if (end == NULL) + break; + *end++ = '\0'; + printf("<%s> ", word); + word = end; + } + printf("\n"); + } + + splx(s); + return (0); +} + +/* + * State machine. + * + * The keyboard may feed us the following sequences: + * - a raw key code, in the range 0x01-0x7e, or'ed with 0x80 if key release. + * - the key repeat sequence 0x7f. + * - a 3 byte mouse sequence. + * - a 2 byte channel sequence (0xff followed by the channel number) telling + * us which device the following input will come from. + */ + +dnevent +dnkbd_input(struct dnkbd_softc *sc, int dat) +{ + dnevent event = EVENT_NONE; + + switch (sc->sc_state) { + case STATE_KEYBOARD: + switch (dat) { + case DNKEY_REPEAT: + /* + * We ignore event repeats, as wskbd does its own + * soft repeat processing. + */ + break; + case DNKEY_CHANNEL: + sc->sc_state = STATE_CHANNEL; + break; + default: + event = EVENT_KEYBOARD; + break; + } + break; + + case STATE_MOUSE: + if (dat == DNKEY_CHANNEL && sc->sc_mousepos == 0) { + sc->sc_state = STATE_CHANNEL; + } else { + sc->sc_mousepkt[sc->sc_mousepos++] = dat; + if (sc->sc_mousepos == sizeof(sc->sc_mousepkt)) { + sc->sc_mousepos = 0; + event = EVENT_MOUSE; + } + } + break; + + case STATE_CHANNEL: + switch (dat) { + case DNKEY_CHANNEL: + /* + * During hotplug, we might get spurious 0xff bytes. + * Ignore them. + */ + break; + case DNCHANNEL_RESET: + /* + * Identify the keyboard again. This will switch it to + * raw mode again. If this fails, we'll consider the + * keyboard as unplugged (to ignore further events until + * a successfull reset). + */ + if (dnkbd_probe(sc) == 0) { + /* + * We need to attach wskbd and wsmouse children + * if this is a live first plug. + */ + if (!ISSET(sc->sc_flags, SF_ATTACHED)) + dnkbd_attach_subdevices(sc); + SET(sc->sc_flags, SF_PLUGGED); + } else { + CLR(sc->sc_flags, SF_PLUGGED); + } + + sc->sc_state = STATE_KEYBOARD; + break; + case DNCHANNEL_KBD: + sc->sc_state = STATE_KEYBOARD; + break; + case DNCHANNEL_MOUSE: + sc->sc_state = STATE_MOUSE; + sc->sc_mousepos = 0; /* just in case */ + break; + default: + printf("%s: unexpected channel byte %02x\n", + sc->sc_dev.dv_xname, dat); + break; + } + break; + } + + return (event); +} + +/* + * Event breakers. + */ + +void +dnkbd_decode(int keycode, u_int *type, int *key) +{ + *type = (keycode & DNKEY_RELEASE) ? + WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; + *key = (keycode & ~DNKEY_RELEASE); +} + +void +dnevent_kbd(struct dnkbd_softc *sc, int dat) +{ + u_int type; + int key; + int s; + + if (!ISSET(sc->sc_flags, SF_PLUGGED)) + return; + + if (sc->sc_wskbddev == NULL) + return; + + if (!ISSET(sc->sc_flags, SF_ENABLED)) + return; + + dnkbd_decode(dat, &type, &key); + +#ifdef WSDISPLAY_COMPAT_RAWKBD + if (sc->sc_rawkbd) { + u_char cbuf[2]; + int c, j = 0; + + c = dnkbd_raw[key]; + if (c != RAWKEY_Null) { + /* fake extended scancode if necessary */ + if (c & 0x80) + cbuf[j++] = 0xe0; + cbuf[j] = c & 0x7f; + if (type == WSCONS_EVENT_KEY_UP) + cbuf[j] |= 0x80; + else { + /* remember pressed key for autorepeat */ + bcopy(cbuf, sc->sc_rep, sizeof(sc->sc_rep)); + } + } + + s = spltty(); + wskbd_rawinput(sc->sc_wskbddev, cbuf, j); + splx(s); + timeout_del(&sc->sc_rawrepeat_ch); + sc->sc_nrep = j; + if (j != 0) { + timeout_add(&sc->sc_rawrepeat_ch, + (hz * REP_DELAY1) / 1000); + } + } else +#endif + { + s = spltty(); + wskbd_input(sc->sc_wskbddev, type, key); + splx(s); + } +} + +#ifdef WSDISPLAY_COMPAT_RAWKBD +void +dnkbd_rawrepeat(void *v) +{ + struct dnkbd_softc *sc = v; + int s; + + s = spltty(); + wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); + splx(s); + + timeout_add(&sc->sc_rawrepeat_ch, (hz * REP_DELAYN) / 1000); +} +#endif + +void +dnevent_mouse(struct dnkbd_softc *sc, u_int8_t *dat) +{ + if (!ISSET(sc->sc_flags, SF_PLUGGED)) + return; + + if (sc->sc_wsmousedev == NULL) + return; + + if (!ISSET(sc->sc_flags, SF_MOUSE)) + return; + + /* + * First byte is button status. It has the 0x80 bit always set, and + * the next 3 bits are *cleared* when the mouse buttons are pressed. + */ +#ifdef DEBUG + if (!ISSET(*dat, 0x80)) { + printf("%s: incorrect mouse packet %02x %02x %02x\n", + sc->sc_dev.dv_xname, dat[0], dat[1], dat[2]); + return; + } +#endif + + wsmouse_input(sc->sc_wsmousedev, + (~dat[0] & (DNBUTTON_L | DNBUTTON_M | DNBUTTON_R)) >> 4, + (int8_t)dat[1], (int8_t)dat[2], 0, WSMOUSE_INPUT_DELTA); +} + +/* + * Low-level communication routines. + */ + +int +dnkbd_pollin(struct apciregs *apci, u_int tries) +{ + u_int cnt; + + for (cnt = tries; cnt != 0; cnt--) { + if (apci->ap_lsr & LSR_RXRDY) + break; + DELAY(10); + } + + if (cnt == 0) + return (-1); + else + return ((int)apci->ap_data); +} + +int +dnkbd_pollout(struct apciregs *apci, int dat) +{ + u_int cnt; + + for (cnt = 10000; cnt != 0; cnt--) { + if (apci->ap_lsr & LSR_TXRDY) + break; + DELAY(10); + } + if (cnt == 0) + return (EBUSY); + else { + apci->ap_data = dat; + return (0); + } +} + +int +dnkbd_send(struct apciregs *apci, u_int8_t *cmdbuf, size_t cmdlen) +{ + int cnt, rc, dat; + u_int cmdpos; + + /* drain rxfifo */ + for (cnt = 10; cnt != 0; cnt--) { + if (dnkbd_pollin(apci, 10) == -1) + break; + } + if (cnt == 0) + return (EBUSY); + + /* send command escape */ + if ((rc = dnkbd_pollout(apci, DNCMD_PREFIX)) != 0) + return (rc); + + /* send command buffer */ + for (cmdpos = 0; cmdpos < cmdlen; cmdpos++) { + if ((rc = dnkbd_pollout(apci, cmdbuf[cmdpos])) != 0) + return (rc); + } + + /* wait for command echo */ + do { + dat = dnkbd_pollin(apci, 10000); + if (dat == -1) + return (EIO); + } while (dat != DNCMD_PREFIX); + + for (cmdpos = 0; cmdpos < cmdlen; cmdpos++) { + dat = dnkbd_pollin(apci, 10000); + if (dat != cmdbuf[cmdpos]) + return (EIO); + } + + return (0); +} + +int +dnkbd_intr(void *v) +{ + struct dnkbd_softc *sc = v; + struct apciregs *apci = sc->sc_regs; + u_int8_t iir, lsr, c; + int claimed = 0; + + for (;;) { + iir = apci->ap_iir; + + switch (iir & IIR_IMASK) { + case IIR_RLS: + /* + * Line status change. This should never happen, + * so silently ack the interrupt. + */ + c = apci->ap_lsr; + break; + + case IIR_RXRDY: + case IIR_RXTOUT: + /* + * Data available. We process it byte by byte. + */ + for (;;) { + c = apci->ap_data; + switch (dnkbd_input(sc, c)) { + case EVENT_KEYBOARD: + dnevent_kbd(sc, c); + break; + case EVENT_MOUSE: + dnevent_mouse(sc, sc->sc_mousepkt); + break; + default: /* appease gcc */ + break; + } + lsr = apci->ap_lsr & LSR_RCV_MASK; + if (lsr == 0) + break; + else if (lsr != LSR_RXRDY) { + /* ignore error */ + break; + } + } + break; + + case IIR_TXRDY: + /* + * Transmit available. Since we do all our commands + * in polling mode, we do not need to do anything here. + */ + break; + + default: + if (iir & IIR_NOPEND) + return (claimed); + /* FALLTHROUGH */ + + case IIR_MLSC: + /* + * Modem status change. This should never happen, + * so silently ack the interrupt. + */ + c = apci->ap_msr; + break; + } + + claimed = 1; + } +} + +/* + * Wskbd callbacks + */ + +int +dnkbd_enable(void *v, int on) +{ + struct dnkbd_softc *sc = v; + + if (on) { + if (ISSET(sc->sc_flags, SF_ENABLED)) + return (EBUSY); + SET(sc->sc_flags, SF_ENABLED); + } else { + if (ISSET(sc->sc_flags, SF_CONSOLE)) + return (EBUSY); + CLR(sc->sc_flags, SF_ENABLED); + } + + return (0); +} + +void +dnkbd_set_leds(void *v, int leds) +{ + /* + * Not supported. There is only one LED on this keyboard, and + * is hardware tied to the caps lock key. + */ +} + +int +dnkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct dnkbd_softc *sc = v; + + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_DOMAIN; + return (0); + case WSKBDIO_SETLEDS: + return (ENXIO); + case WSKBDIO_GETLEDS: + *(int *)data = 0; + return (0); +#ifdef WSDISPLAY_COMPAT_RAWKBD + case WSKBDIO_SETMODE: + sc->sc_rawkbd = *(int *)data == WSKBD_RAW; + timeout_del(&sc->sc_rawrepeat_ch); + return (0); +#endif + } + + return (-1); +} + +/* + * Wsmouse callbacks + */ + +int +dnmouse_enable(void *v) +{ + struct dnkbd_softc *sc = v; + + if (ISSET(sc->sc_flags, SF_MOUSE)) + return (EBUSY); + SET(sc->sc_flags, SF_MOUSE); + + return (0); +} + +int +dnmouse_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ +#if 0 + struct dnkbd_softc *sc = v; +#endif + + switch (cmd) { + case WSMOUSEIO_GTYPE: + *(int *)data = WSMOUSE_TYPE_DOMAIN; + return (0); + } + + return (-1); +} + +void +dnmouse_disable(void *v) +{ + struct dnkbd_softc *sc = v; + + CLR(sc->sc_flags, SF_MOUSE); +} + +/* + * Console support + */ + +void +dnkbd_cngetc(void *v, u_int *type, int *data) +{ + struct dnkbd_softc *sc = v; + int s; + int dat; + + for (;;) { + s = splhigh(); + dat = dnkbd_pollin(sc->sc_regs, 10000); + if (dat != -1) { + if (dnkbd_input(sc, dat) == EVENT_KEYBOARD) { + splx(s); + break; + } + } + splx(s); + } + + dnkbd_decode(dat, type, data); +} + +void +dnkbd_cnpollc(void *v, int on) +{ + struct dnkbd_softc *sc = v; + + if (on) + SET(sc->sc_flags, SF_POLLING); + else + CLR(sc->sc_flags, SF_POLLING); +} diff --git a/sys/arch/hp300/dev/dnkbdmap.c b/sys/arch/hp300/dev/dnkbdmap.c new file mode 100644 index 00000000000..04165d1f916 --- /dev/null +++ b/sys/arch/hp300/dev/dnkbdmap.c @@ -0,0 +1,293 @@ +/* $OpenBSD: dnkbdmap.c,v 1.1 2005/04/22 11:59:11 miod Exp $ */ +/* + * Copyright (c) 2005, Miodrag Vallat + * + * 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. + * + * 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/types.h> + +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> + +#include <hp300/dev/dnkbdmap.h> + +#ifdef WSDISPLAY_COMPAT_RAWKBD +#include <dev/wscons/wskbdraw.h> + +/* + * Translate Domain keycodes to US keyboard XT scancodes, for proper + * X11-over-wsmux operation. + */ +const u_int8_t dnkbd_raw[0x80] = { + RAWKEY_Null, + RAWKEY_Null, /* 01 Ins Mark */ + RAWKEY_Null, /* 02 Line Del */ + RAWKEY_Null, /* 03 Char Del */ + RAWKEY_f10, /* 04 f0 */ + RAWKEY_f1, + RAWKEY_f2, + RAWKEY_f3, + RAWKEY_f4, + RAWKEY_f5, + RAWKEY_f6, + RAWKEY_f7, + RAWKEY_f8, + RAWKEY_f9, + RAWKEY_Null, /* 0e Again */ + RAWKEY_Null, /* 0f Read */ + RAWKEY_Null, /* 10 Save Edit */ + RAWKEY_Null, /* 11 Abort Exit */ + RAWKEY_Hold_Screen, /* 12 Help Hold */ + RAWKEY_Null, /* 13 Cut Copy */ + RAWKEY_Null, /* 14 Undo Paste */ + RAWKEY_Null, /* 15 Move Grow */ + RAWKEY_Null, + RAWKEY_Escape, + RAWKEY_1, + RAWKEY_2, + RAWKEY_3, + RAWKEY_4, + RAWKEY_5, + RAWKEY_6, + RAWKEY_7, + RAWKEY_8, + RAWKEY_9, + RAWKEY_0, + RAWKEY_minus, + RAWKEY_equal, + RAWKEY_grave, + RAWKEY_BackSpace, + RAWKEY_Null, + RAWKEY_Null, /* 27 Left Edge */ + RAWKEY_Null, /* 28 Shell Cmd */ + RAWKEY_Null, /* 29 Right Edge */ + RAWKEY_Null, + RAWKEY_Null, + RAWKEY_Tab, + RAWKEY_q, + RAWKEY_w, + RAWKEY_e, + RAWKEY_r, + RAWKEY_t, + RAWKEY_y, + RAWKEY_u, + RAWKEY_i, + RAWKEY_o, + RAWKEY_p, + RAWKEY_bracketleft, + RAWKEY_bracketright, + RAWKEY_Null, + RAWKEY_Delete, + RAWKEY_Null, + RAWKEY_KP_Home, + RAWKEY_KP_Up, + RAWKEY_KP_Prior, + RAWKEY_KP_Add, + RAWKEY_Null, /* 40 Left Box */ + RAWKEY_Up, + RAWKEY_Null, /* 42 Right Box */ + RAWKEY_Control_L, + RAWKEY_Null, + RAWKEY_Null, + RAWKEY_a, + RAWKEY_s, + RAWKEY_d, + RAWKEY_f, + RAWKEY_g, + RAWKEY_h, + RAWKEY_j, + RAWKEY_k, + RAWKEY_l, + RAWKEY_semicolon, + RAWKEY_apostrophe, + RAWKEY_Null, + RAWKEY_Return, + RAWKEY_backslash, + RAWKEY_Null, + RAWKEY_KP_Left, + RAWKEY_KP_Begin, + RAWKEY_KP_Right, + RAWKEY_KP_Subtract, + RAWKEY_Left, + RAWKEY_Null, /* 5a Next Wndw */ + RAWKEY_Right, + RAWKEY_Null, + RAWKEY_Null, /* 5d Rept */ + RAWKEY_Shift_L, + RAWKEY_Null, + RAWKEY_z, + RAWKEY_x, + RAWKEY_c, + RAWKEY_v, + RAWKEY_b, + RAWKEY_n, + RAWKEY_m, + RAWKEY_comma, + RAWKEY_period, + RAWKEY_slash, + RAWKEY_Shift_R, + RAWKEY_Null, + RAWKEY_Null, /* 6c Pop */ + RAWKEY_Null, + RAWKEY_KP_End, + RAWKEY_KP_Down, + RAWKEY_KP_Next, + RAWKEY_Null, + RAWKEY_Null, /* 72 Top Box */ + RAWKEY_Down, + RAWKEY_Null, /* 74 Bottom Box */ + RAWKEY_Alt_L, + RAWKEY_space, + RAWKEY_Alt_R, + RAWKEY_Null, + RAWKEY_KP_Insert, + RAWKEY_Null, + RAWKEY_KP_Delete, + RAWKEY_KP_Enter, + RAWKEY_Null, + RAWKEY_Caps_Lock, + RAWKEY_Null +}; +#endif + +#define KC(n) KS_KEYCODE(n) + +const keysym_t dnkbd_keydesc_us[] = { +/* pos command normal shifted */ + /* 01 Ins Mark */ + /* 02 Line Del */ + /* 03 Char Del */ + KC(0x04), KS_f10, + KC(0x05), KS_f1, + KC(0x06), KS_f2, + KC(0x07), KS_f3, + KC(0x08), KS_f4, + KC(0x09), KS_f5, + KC(0x0a), KS_f6, + KC(0x0b), KS_f7, + KC(0x0c), KS_f8, + KC(0x0d), KS_f9, + /* 0e Again */ + /* 0f Read */ + /* 10 Save Edit */ + /* 11 Abort Exit */ + KC(0x12), KS_Hold_Screen, + /* 13 Cut Copy */ + /* 14 Undo Paste */ + /* 15 Move Grow */ + KC(0x17), KS_Cmd_Debugger, KS_Escape, + KC(0x18), KS_1, KS_exclam, + KC(0x19), KS_2, KS_at, + KC(0x1a), KS_3, KS_numbersign, + KC(0x1b), KS_4, KS_dollar, + KC(0x1c), KS_5, KS_percent, + KC(0x1d), KS_6, KS_asciicircum, + KC(0x1e), KS_7, KS_ampersand, + KC(0x1f), KS_8, KS_asterisk, + KC(0x20), KS_9, KS_parenleft, + KC(0x21), KS_0, KS_parenright, + KC(0x22), KS_minus, KS_underscore, + KC(0x23), KS_equal, KS_plus, + KC(0x24), KS_grave, KS_asciitilde, + KC(0x25), KS_Cmd_ResetEmul, KS_Delete, /* backspace */ + KC(0x27), KS_Home, + /* 28 Shell Cmd */ + KC(0x29), KS_End, + KC(0x2c), KS_Tab, + KC(0x2d), KS_q, + KC(0x2e), KS_w, + KC(0x2f), KS_e, + KC(0x30), KS_r, + KC(0x31), KS_t, + KC(0x32), KS_y, + KC(0x33), KS_u, + KC(0x34), KS_i, + KC(0x35), KS_o, + KC(0x36), KS_p, + KC(0x37), KS_bracketleft, KS_braceleft, + KC(0x38), KS_bracketright,KS_braceright, + KC(0x3a), KS_Delete, + KC(0x3c), KS_KP_7, + KC(0x3d), KS_KP_8, + KC(0x3e), KS_KP_9, + KC(0x3f), KS_KP_Add, + /* 40 Left Box */ + KC(0x41), KS_Up, + /* 42 Right Box */ + KC(0x43), KS_Cmd1, KS_Control_L, + KC(0x46), KS_a, + KC(0x47), KS_s, + KC(0x48), KS_d, + KC(0x49), KS_f, + KC(0x4a), KS_g, + KC(0x4b), KS_h, + KC(0x4c), KS_j, + KC(0x4d), KS_k, + KC(0x4e), KS_l, + KC(0x4f), KS_semicolon, KS_colon, + KC(0x50), KS_apostrophe, KS_quotedbl, + KC(0x52), KS_Return, + KC(0x53), KS_backslash, KS_bar, + KC(0x55), KS_KP_4, + KC(0x56), KS_KP_5, + KC(0x57), KS_KP_6, + KC(0x58), KS_KP_Subtract, + KC(0x59), KS_Left, + /* 5a Next Wndw */ + KC(0x5b), KS_Right, + /* 5d Rept */ + KC(0x5e), KS_Shift_L, + KC(0x60), KS_z, + KC(0x61), KS_x, + KC(0x62), KS_c, + KC(0x63), KS_v, + KC(0x64), KS_b, + KC(0x65), KS_n, + KC(0x66), KS_m, + KC(0x67), KS_comma, KS_less, + KC(0x68), KS_period, KS_greater, + KC(0x69), KS_slash, KS_question, + KC(0x6a), KS_Shift_R, + /* 6c Pop */ + KC(0x6e), KS_KP_1, + KC(0x6f), KS_KP_2, + KC(0x70), KS_KP_3, + /* 72 Top Box */ + KC(0x73), KS_Down, + /* 74 Bottom Box */ + KC(0x75), KS_Cmd2, KS_Alt_L, + KC(0x76), KS_space, + KC(0x77), KS_Cmd2, KS_Alt_R, + KC(0x79), KS_KP_0, + KC(0x7b), KS_KP_Separator, + KC(0x7c), KS_KP_Enter, + KC(0x7e), KS_Caps_Lock +}; + +#define KBD_MAP(name, base, map) \ + { name, base, sizeof(map) / sizeof(keysym_t), map } + +const struct wscons_keydesc dnkbd_keydesctab[] = { + KBD_MAP(KB_US, 0, dnkbd_keydesc_us), + { 0, 0, 0, 0 } +}; diff --git a/sys/arch/hp300/dev/dnkbdmap.h b/sys/arch/hp300/dev/dnkbdmap.h new file mode 100644 index 00000000000..90ffb046925 --- /dev/null +++ b/sys/arch/hp300/dev/dnkbdmap.h @@ -0,0 +1,28 @@ +/* $OpenBSD: dnkbdmap.h,v 1.1 2005/04/22 11:59:11 miod Exp $ */ +/* + * Copyright (c) 2005, Miodrag Vallat + * + * 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. + * + * 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. + */ + +extern const struct wscons_keydesc dnkbd_keydesctab[]; +extern const u_int8_t dnkbd_raw[0x80]; |