Module Name: src Committed By: tsutsui Date: Sat Feb 12 15:49:02 UTC 2011
Modified Files: src/sys/arch/hp300/conf: GENERIC files.hp300 Added Files: src/sys/arch/hp300/dev: dnkbd.c dnkbdmap.c dnkbdmap.h Log Message: Pull Apollo Domain keyboard and mouse support from OpenBSD. Untested (no hardware), but no bad sideeffect on 425t without Domain keyboard. This is the last portion of "new hp300 kernel features" submitted in PR port-hp300/3528 back in 1997, and I think finally we can close it. To generate a diff of this commit: cvs rdiff -u -r1.163 -r1.164 src/sys/arch/hp300/conf/GENERIC cvs rdiff -u -r1.81 -r1.82 src/sys/arch/hp300/conf/files.hp300 cvs rdiff -u -r0 -r1.1 src/sys/arch/hp300/dev/dnkbd.c \ src/sys/arch/hp300/dev/dnkbdmap.c src/sys/arch/hp300/dev/dnkbdmap.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/hp300/conf/GENERIC diff -u src/sys/arch/hp300/conf/GENERIC:1.163 src/sys/arch/hp300/conf/GENERIC:1.164 --- src/sys/arch/hp300/conf/GENERIC:1.163 Sat Feb 12 05:15:39 2011 +++ src/sys/arch/hp300/conf/GENERIC Sat Feb 12 15:49:01 2011 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.163 2011/02/12 05:15:39 tsutsui Exp $ +# $NetBSD: GENERIC,v 1.164 2011/02/12 15:49:01 tsutsui Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.163 $" +#ident "GENERIC-$Revision: 1.164 $" maxusers 32 # estimated number of users @@ -210,9 +210,9 @@ nhpib* at intio? # slow internal HP-IB # 8250-like serial ports found on Frodo ASIC -#dnkbd0 at frodo? offset 0x0 # Domain keyboard flavor -#wskbd* at dnkbd? mux 1 -#wsmouse* at dnkbd? mux 0 +dnkbd0 at frodo? offset 0x0 # Domain keyboard flavor +wskbd* at dnkbd? mux 1 +wsmouse* at dnkbd? mux 0 com* at frodo? offset ? # tty flavor dvbox* at intio? # Davinci framebuffer Index: src/sys/arch/hp300/conf/files.hp300 diff -u src/sys/arch/hp300/conf/files.hp300:1.81 src/sys/arch/hp300/conf/files.hp300:1.82 --- src/sys/arch/hp300/conf/files.hp300:1.81 Sat Feb 12 05:15:39 2011 +++ src/sys/arch/hp300/conf/files.hp300 Sat Feb 12 15:49:01 2011 @@ -1,4 +1,4 @@ -# $NetBSD: files.hp300,v 1.81 2011/02/12 05:15:39 tsutsui Exp $ +# $NetBSD: files.hp300,v 1.82 2011/02/12 15:49:01 tsutsui Exp $ # # hp300-specific configuration info @@ -80,10 +80,10 @@ file arch/hp300/dev/com_frodo.c com_frodo needs-flag # Apollo Keyboard and mouse -#device dnkbd: wskbddev, wsmousedev -#attach dnkbd at frodo -#file arch/hp300/dev/dnkbd.c dnkbd needs-flag -#file arch/hp300/dev/dnkbdmap.c dnkbd +device dnkbd: wskbddev, wsmousedev +attach dnkbd at frodo +file arch/hp300/dev/dnkbd.c dnkbd needs-flag +file arch/hp300/dev/dnkbdmap.c dnkbd # # Frame buffer devices on Internal I/O and the DIO bus Added files: Index: src/sys/arch/hp300/dev/dnkbd.c diff -u /dev/null src/sys/arch/hp300/dev/dnkbd.c:1.1 --- /dev/null Sat Feb 12 15:49:02 2011 +++ src/sys/arch/hp300/dev/dnkbd.c Sat Feb 12 15:49:01 2011 @@ -0,0 +1,1138 @@ +/* $NetBSD: dnkbd.c,v 1.1 2011/02/12 15:49:01 tsutsui Exp $ */ +/* $OpenBSD: dnkbd.c,v 1.17 2009/07/23 21:05:56 blambert 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/callout.h> +#include <sys/conf.h> +#include <sys/bus.h> +#include <sys/cpu.h> + +#include <machine/autoconf.h> + +#include <dev/cons.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> +#include "wsmouse.h" +#if NWSMOUSE > 0 +#include <dev/wscons/wsmousevar.h> +#endif + +#include <dev/ic/ns16550reg.h> +#include <dev/ic/comreg.h> + +#include <hp300/dev/dnkbdmap.h> +#include <hp300/dev/frodoreg.h> +#include <hp300/dev/frodovar.h> + +#include "hilkbd.h" +#include "ioconf.h" + +/* + * Keyboard key codes + */ + +#define DNKEY_CAPSLOCK 0x7e +#define DNKEY_REPEAT 0x7f +#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 + +/* + * Bell commands + */ + +#define DNCMD_BELL 0x21 +#define DNCMD_BELL_ON 0x81 +#define DNCMD_BELL_OFF 0x82 + +/* + * Mouse status + */ + +#define DNBUTTON_L 0x10 +#define DNBUTTON_R 0x20 +#define DNBUTTON_M 0x40 + +struct dnkbd_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + + 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 */ +#define SF_BELL 0x40 /* bell is active */ +#define SF_BELL_TMO 0x80 /* bell stop timeout is scheduled */ + + u_int sc_identlen; +#define MAX_IDENTLEN 32 + char sc_ident[MAX_IDENTLEN]; + kbd_t sc_layout; + + enum { STATE_KEYBOARD, STATE_MOUSE, STATE_CHANNEL, STATE_ECHO } + sc_state, sc_prevstate; + u_int sc_echolen; + + u_int8_t sc_mousepkt[3]; /* mouse packet being constructed */ + u_int sc_mousepos; /* index in above */ + + struct callout sc_bellstop_tmo; + + device_t sc_wskbddev; +#if NWSMOUSE > 0 + device_t sc_wsmousedev; +#endif + +#ifdef WSDISPLAY_COMPAT_RAWKBD + int sc_rawkbd; + int sc_nrep; + char sc_rep[2]; /* at most, one key */ + struct callout sc_rawrepeat_ch; +#define REP_DELAY1 400 +#define REP_DELAYN 100 +#endif +}; + +int dnkbd_match(device_t, cfdata_t, void *); +void dnkbd_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(dnkbd, sizeof(struct dnkbd_softc), + dnkbd_match, dnkbd_attach, NULL, NULL); + +void dnkbd_init(struct dnkbd_softc *, uint16_t, uint16_t); +int dnkbd_enable(void *, int); +void dnkbd_set_leds(void *, int); +int dnkbd_ioctl(void *, u_long, void *, int, struct lwp *); + +const struct wskbd_accessops dnkbd_accessops = { + dnkbd_enable, + dnkbd_set_leds, + dnkbd_ioctl +}; + +#if NWSMOUSE > 0 +int dnmouse_enable(void *); +int dnmouse_ioctl(void *, u_long, void *, int, struct lwp *); +void dnmouse_disable(void *); + +const struct wsmouse_accessops dnmouse_accessops = { + dnmouse_enable, + dnmouse_ioctl, + dnmouse_disable +}; +#endif + +void dnkbd_bell(void *, u_int, u_int, u_int); +void dnkbd_cngetc(void *, u_int *, int *); +void dnkbd_cnpollc(void *, int); + +const struct wskbd_consops dnkbd_consops = { + dnkbd_cngetc, + dnkbd_cnpollc, + dnkbd_bell +}; + +struct wskbd_mapdata dnkbd_keymapdata = { + dnkbd_keydesctab, +#ifdef DNKBD_LAYOUT + DNKBD_LAYOUT +#else + KB_US +#endif +}; + +typedef enum { EVENT_NONE, EVENT_KEYBOARD, EVENT_MOUSE } dnevent; + +void dnevent_kbd(struct dnkbd_softc *, int); +void dnevent_kbd_internal(struct dnkbd_softc *, int); +void dnevent_mouse(struct dnkbd_softc *, u_int8_t *); +void dnkbd_attach_subdevices(struct dnkbd_softc *); +void dnkbd_bellstop(void *); +void dnkbd_decode(int, u_int *, int *); +dnevent dnkbd_input(struct dnkbd_softc *, int); +int dnkbd_intr(void *); +int dnkbd_pollin(struct dnkbd_softc *, u_int); +int dnkbd_pollout(struct dnkbd_softc *, int); +int dnkbd_probe(struct dnkbd_softc *); +void dnkbd_rawrepeat(void *); +int dnkbd_send(struct dnkbd_softc *, const u_int8_t *, size_t); +int dnsubmatch_kbd(device_t, cfdata_t, const int *, void *); +int dnsubmatch_mouse(device_t, cfdata_t, const int *, void *); + +int +dnkbd_match(device_t parent, cfdata_t cf, void *aux) +{ + struct frodo_attach_args *fa = aux; + + if (strcmp(fa->fa_name, dnkbd_cd.cd_name) != 0) + return (0); + + if (machineid == HP_382) { + /* 382 has frodo but no Domain keyboard connector. */ + return 0; + } + + /* only attach to the first frodo port */ + return (fa->fa_offset == FRODO_APCI_OFFSET(0)); +} + +void +dnkbd_attach(device_t parent, device_t self, void *aux) +{ + struct dnkbd_softc *sc = device_private(self); + struct frodo_attach_args *fa = aux; + + printf(": "); + + sc->sc_dev = self; + sc->sc_bst = fa->fa_bst; + if (bus_space_map(sc->sc_bst, fa->fa_base + fa->fa_offset, + FRODO_APCISPACE, 0, &sc->sc_bsh) != 0) { + aprint_error(": can't map i/o space\n"); + return; + } + + callout_init(&sc->sc_bellstop_tmo, 0); + callout_setfunc(&sc->sc_bellstop_tmo, dnkbd_bellstop, sc); +#ifdef WSDISPLAY_COMPAT_RAWKBD + callout_init(&sc->sc_rawrepeat_ch, 0); + callout_setfunc(&sc->sc_rawrepeat_ch, dnkbd_rawrepeat, sc); +#endif + + /* reset the port */ + dnkbd_init(sc, 1200, LCR_8BITS | LCR_PEVEN | LCR_PENAB); + + frodo_intr_establish(parent, dnkbd_intr, sc, fa->fa_line, IPL_VM); + + /* probe for keyboard */ + if (dnkbd_probe(sc) != 0) { + printf("no keyboard\n"); + return; + } + + dnkbd_attach_subdevices(sc); +} + +void +dnkbd_init(struct dnkbd_softc *sc, uint16_t rate, uint16_t lctl) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + + bst = sc->sc_bst; + bsh = sc->sc_bsh; + + bus_space_write_1(bst, bsh, com_lctl, LCR_DLAB); + bus_space_write_1(bst, bsh, com_dlbl, rate & 0xff); + bus_space_write_1(bst, bsh, com_dlbh, (rate >> 8) & 0xff); + bus_space_write_1(bst, bsh, com_lctl, lctl); + bus_space_write_1(bst, bsh, com_ier, IER_ERXRDY | IER_ETXRDY); + bus_space_write_1(bst, bsh, com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); + bus_space_write_1(bst, bsh, com_mcr, MCR_DTR | MCR_RTS); + + delay(100); +} + +void +dnkbd_attach_subdevices(struct dnkbd_softc *sc) +{ + struct wskbddev_attach_args ka; +#if NWSMOUSE > 0 + struct wsmousedev_attach_args ma; +#endif +#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), unless the console keyboard has been claimed already + * (i.e. late hotplug with hil keyboard plugged first). + */ + if (major(cn_tab->cn_dev) == devsw_name2chr("wsdisplay", NULL, 0)) { +#if NHILKBD > 0 + if (hil_is_console == -1) { + ka.console = 1; + hil_is_console = 0; + } else + ka.console = 0; +#else + ka.console = 1; +#endif + } else + ka.console = 0; + + ka.keymap = &dnkbd_keymapdata; + ka.accessops = &dnkbd_accessops; + ka.accesscookie = sc; +#ifndef DKKBD_LAYOUT + dnkbd_keymapdata.layout = sc->sc_layout; +#endif + + 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_loc(sc->sc_dev, "dnkbd", NULL, &ka, + wskbddevprint, dnsubmatch_kbd); + +#if NWSMOUSE > 0 + ma.accessops = &dnmouse_accessops; + ma.accesscookie = sc; + + sc->sc_wsmousedev = config_found_sm_loc(sc->sc_dev, "dnkbd", NULL, &ma, + wsmousedevprint, dnsubmatch_mouse); +#endif + + SET(sc->sc_flags, SF_ATTACHED); +} + +int +dnsubmatch_kbd(device_t parent, cfdata_t cf, const int *locs, void *aux) +{ + + if (strcmp(cf->cf_name, wskbd_cd.cd_name) != 0) + return (0); + + return config_match(parent, cf, aux); +} + +#if NWSMOUSE > 0 +int +dnsubmatch_mouse(device_t parent, cfdata_t cf, const int *locs, void *aux) +{ + + if (strcmp(cf->cf_name, wsmouse_cd.cd_name) != 0) + return (0); + + return config_match(parent, cf, aux); +} +#endif + +int +dnkbd_probe(struct dnkbd_softc *sc) +{ + int dat, rc, flags; + u_int8_t cmdbuf[2]; + char rspbuf[MAX_IDENTLEN], *word, *end; + u_int i; + int s; + + s = spltty(); + flags = sc->sc_flags; + SET(sc->sc_flags, SF_POLLING); + sc->sc_state = STATE_CHANNEL; + splx(s); + + /* + * Switch keyboard to raw mode. + */ + cmdbuf[0] = DNCMD_RAW; + rc = dnkbd_send(sc, cmdbuf, 1); + if (rc != 0) + goto out; + + /* + * Send the identify command. + */ + cmdbuf[0] = DNCMD_IDENT_1; + cmdbuf[1] = DNCMD_IDENT_2; + rc = dnkbd_send(sc, cmdbuf, 2); + if (rc != 0) + goto out; + + for (i = 0; ; i++) { + dat = dnkbd_pollin(sc, 10000); + if (dat == -1) + break; + + if (i < sizeof(rspbuf)) + rspbuf[i] = dat; + } + + if (i > sizeof(rspbuf) || i == 0) { + printf("%s: unexpected identify string length %d\n", + device_xname(sc->sc_dev), i); + rc = ENXIO; + goto out; + } + + /* + * Make sure the identification string is NULL terminated + * (overwriting the keyboard mode byte if necessary). + */ + i--; + if (rspbuf[i] != 0) + rspbuf[i] = 0; + + /* + * Now display the identification strings, if they changed. + */ + if (i != sc->sc_identlen || memcmp(rspbuf, sc->sc_ident, i) != 0) { + sc->sc_layout = KB_US; + sc->sc_identlen = i; + memcpy(sc->sc_ident, rspbuf, i); + + if (cold == 0) + printf("%s: ", device_xname(sc->sc_dev)); + printf("model "); + word = rspbuf; + for (i = 0; i < 3; i++) { + end = strchr(word, '\r'); + if (end == NULL) + break; + *end++ = '\0'; + printf("<%s> ", word); + /* + * Parse the layout code if applicable + */ + if (i == 1 && *word++ == '3') { + if (*word == '-') + word++; + switch (*word) { +#if 0 + default: + case ' ': + sc->sc_layout = KB_US; + break; +#endif + case 'a': + sc->sc_layout = KB_DE; + break; + case 'b': + sc->sc_layout = KB_FR; + break; + case 'c': + sc->sc_layout = KB_DK; + break; + case 'd': + sc->sc_layout = KB_SV; + break; + case 'e': + sc->sc_layout = KB_UK; + break; + case 'f': + sc->sc_layout = KB_JP; + break; + case 'g': + sc->sc_layout = KB_SG; + break; + } + } + word = end; + } + printf("\n"); + } + + /* + * Ready to work, the default channel is the keyboard. + */ + sc->sc_state = STATE_KEYBOARD; + +out: + s = spltty(); + sc->sc_flags = flags; + splx(s); + + return (rc); +} + +/* + * State machine. + * + * In raw mode, the keyboard may feed us the following sequences: + * - on the keyboard channel: + * + a raw key code, in the range 0x01-0x7e, or'ed with 0x80 if key release. + * + the key repeat sequence 0x7f. + * - on the mouse channel: + * + a 3 byte mouse sequence (buttons state, dx move, dy move). + * - at any time: + * + a 2 byte channel sequence (0xff followed by the channel number) telling + * us which device the following input will come from. + * + if we get 0xff but an invalid channel number, this is a command echo. + * Currently we only handle this for bell commands, which size are known. + * Other commands are issued through dnkbd_send() which ``eats'' the echo. + * + * Older keyboards reset the channel to the keyboard (by sending ff 01) after + * every mouse packet. + */ + +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_prevstate = sc->sc_state; + 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_prevstate = sc->sc_state; + 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 successful 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; + case DNCMD_BELL: + /* + * We are getting a bell command echoed to us. + * Ignore it. + */ + sc->sc_state = STATE_ECHO; + sc->sc_echolen = 1; /* one byte to follow */ + break; + default: + printf("%s: unexpected channel byte %02x\n", + device_xname(sc->sc_dev), dat); + break; + } + break; + + case STATE_ECHO: + if (--sc->sc_echolen == 0) { + /* get back to the state we were in before the echo */ + sc->sc_state = sc->sc_prevstate; + } + 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) +{ + if (!ISSET(sc->sc_flags, SF_PLUGGED)) + return; + + if (sc->sc_wskbddev == NULL) + return; + + if (!ISSET(sc->sc_flags, SF_ENABLED)) + return; + + /* + * Even in raw mode, the caps lock key is treated specially: + * first key press causes event 0x7e, release causes no event; + * then a new key press causes nothing, and release causes + * event 0xfe. Moreover, while kept down, it does not produce + * repeat events. + * + * So the best we can do is fake the missed events, but this + * will not allow the capslock key to be remapped as a control + * key since it will not be possible to chord it with anything. + */ + dnevent_kbd_internal(sc, dat); + if ((dat & ~DNKEY_RELEASE) == DNKEY_CAPSLOCK) + dnevent_kbd_internal(sc, dat ^ DNKEY_RELEASE); +} + +void +dnevent_kbd_internal(struct dnkbd_softc *sc, int dat) +{ + u_int type; + int key; + int s; + + 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 */ + memcpy(sc->sc_rep, cbuf, sizeof(sc->sc_rep)); + } + j++; + } + + if (j != 0) { + s = spltty(); + wskbd_rawinput(sc->sc_wskbddev, cbuf, j); + splx(s); + callout_stop(&sc->sc_rawrepeat_ch); + sc->sc_nrep = j; + callout_schedule(&sc->sc_rawrepeat_ch, + hstohz(REP_DELAY1)); + } + } 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); + + callout_schedule(&sc->sc_rawrepeat_ch, hztoms(REP_DELAYN)); +} +#endif + +#if NWSMOUSE > 0 +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", + device_xname(sc->sc_dev), 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, 0, WSMOUSE_INPUT_DELTA); +} +#endif + +/* + * Low-level communication routines. + */ + +int +dnkbd_pollin(struct dnkbd_softc *sc, u_int tries) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + u_int cnt; + + bst = sc->sc_bst; + bsh = sc->sc_bsh; + + for (cnt = tries; cnt != 0; cnt--) { + if (bus_space_read_1(bst, bsh, com_lsr) & LSR_RXRDY) + break; + DELAY(10); + } + + if (cnt == 0) + return (-1); + else + return (int)bus_space_read_1(bst, bsh, com_data); +} + +int +dnkbd_pollout(struct dnkbd_softc *sc, int dat) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + u_int cnt; + + bst = sc->sc_bst; + bsh = sc->sc_bsh; + + for (cnt = 10000; cnt != 0; cnt--) { + if (bus_space_read_1(bst, bsh, com_lsr) & LSR_TXRDY) + break; + DELAY(10); + } + if (cnt == 0) + return (EBUSY); + else { + bus_space_write_1(bst, bsh, com_data, dat); + return (0); + } +} + +int +dnkbd_send(struct dnkbd_softc *sc, const 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(sc, 10) == -1) + break; + } + if (cnt == 0) + return (EBUSY); + + /* send command escape */ + if ((rc = dnkbd_pollout(sc, DNCMD_PREFIX)) != 0) + return (rc); + + /* send command buffer */ + for (cmdpos = 0; cmdpos < cmdlen; cmdpos++) { + if ((rc = dnkbd_pollout(sc, cmdbuf[cmdpos])) != 0) + return (rc); + } + + /* wait for command echo */ + do { + dat = dnkbd_pollin(sc, 10000); + if (dat == -1) + return (EIO); + } while (dat != DNCMD_PREFIX); + + for (cmdpos = 0; cmdpos < cmdlen; cmdpos++) { + dat = dnkbd_pollin(sc, 10000); + if (dat != cmdbuf[cmdpos]) + return (EIO); + } + + return (0); +} + +int +dnkbd_intr(void *v) +{ + struct dnkbd_softc *sc = v; + bus_space_tag_t bst; + bus_space_handle_t bsh; + u_int8_t iir, lsr, c; + int claimed = 0; + + bst = sc->sc_bst; + bsh = sc->sc_bsh; + + for (;;) { + iir = bus_space_read_1(bst, bsh, com_iir); + + switch (iir & IIR_IMASK) { + case IIR_RLS: + /* + * Line status change. This should never happen, + * so silently ack the interrupt. + */ + c = bus_space_read_1(bst, bsh, com_lsr); + break; + + case IIR_RXRDY: + case IIR_RXTOUT: + /* + * Data available. We process it byte by byte, + * unless we are doing polling work... + */ + if (ISSET(sc->sc_flags, SF_POLLING)) { + return (1); + } + + for (;;) { + c = bus_space_read_1(bst, bsh, com_data); + switch (dnkbd_input(sc, c)) { + case EVENT_KEYBOARD: + dnevent_kbd(sc, c); + break; +#if NWSMOUSE > 0 + case EVENT_MOUSE: + dnevent_mouse(sc, sc->sc_mousepkt); + break; +#endif + default: /* appease gcc */ + break; + } + lsr = bus_space_read_1(bst, bsh, com_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 = bus_space_read_1(bst, bsh, com_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, void *data, int flag, struct lwp *l) +{ +#ifdef WSDISPLAY_COMPAT_RAWKBD + struct dnkbd_softc *sc = v; +#endif + +#define WSKBD_TYPE_UNKNOWN 0 + + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_UNKNOWN; /* XXX */ + return (0); + case WSKBDIO_SETLEDS: + return (ENXIO); + case WSKBDIO_GETLEDS: + *(int *)data = 0; + return (0); + case WSKBDIO_COMPLEXBELL: +#define d ((struct wskbd_bell_data *)data) + dnkbd_bell(v, d->period, d->pitch, d->volume); +#undef d + 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 EPASSTHROUGH; +} + +#if NWSMOUSE > 0 +/* + * 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, void *data, int flag, struct lwp *l) +{ +#if 0 + struct dnkbd_softc *sc = v; +#endif + +#define WSMOUSE_TYPE_UNKNOWN 0 + + switch (cmd) { + case WSMOUSEIO_GTYPE: + *(int *)data = WSMOUSE_TYPE_UNKNOWN; /* XXX */ + return (0); + } + + return (-1); +} + +void +dnmouse_disable(void *v) +{ + struct dnkbd_softc *sc = v; + + CLR(sc->sc_flags, SF_MOUSE); +} +#endif + +/* + * Console support + */ + +void +dnkbd_cngetc(void *v, u_int *type, int *data) +{ + static int lastdat = 0; + struct dnkbd_softc *sc = v; + int s; + int dat; + + /* Take care of caps lock */ + if ((lastdat & ~DNKEY_RELEASE) == DNKEY_CAPSLOCK) { + dat = lastdat ^ DNKEY_RELEASE; + lastdat = 0; + } else { + for (;;) { + s = splhigh(); + dat = dnkbd_pollin(sc, 10000); + if (dat != -1) { + if (dnkbd_input(sc, dat) == EVENT_KEYBOARD) { + splx(s); + break; + } + } + splx(s); + } + lastdat = dat; + } + + 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); +} + +/* + * Bell routines. + */ +void +dnkbd_bell(void *v, u_int period, u_int pitch, u_int volume) +{ + struct dnkbd_softc *sc = v; + int s; + + s = spltty(); + + if (pitch == 0 || period == 0 || volume == 0) { + if (ISSET(sc->sc_flags, SF_BELL_TMO)) { + callout_stop(&sc->sc_bellstop_tmo); + dnkbd_bellstop(v); + } + } else { + + if (!ISSET(sc->sc_flags, SF_BELL)) { + dnkbd_pollout(sc, DNCMD_PREFIX); + dnkbd_pollout(sc, DNCMD_BELL); + dnkbd_pollout(sc, DNCMD_BELL_ON); + SET(sc->sc_flags, SF_BELL); + } + + if (ISSET(sc->sc_flags, SF_BELL_TMO)) + callout_stop(&sc->sc_bellstop_tmo); + callout_schedule(&sc->sc_bellstop_tmo, period); + SET(sc->sc_flags, SF_BELL_TMO); + } + + splx(s); +} + +void +dnkbd_bellstop(void *v) +{ + struct dnkbd_softc *sc = v; + int s; + + s = spltty(); + + dnkbd_pollout(sc, DNCMD_PREFIX); + dnkbd_pollout(sc, DNCMD_BELL); + dnkbd_pollout(sc, DNCMD_BELL_OFF); + CLR(sc->sc_flags, SF_BELL); + CLR(sc->sc_flags, SF_BELL_TMO); + + splx(s); +} Index: src/sys/arch/hp300/dev/dnkbdmap.c diff -u /dev/null src/sys/arch/hp300/dev/dnkbdmap.c:1.1 --- /dev/null Sat Feb 12 15:49:02 2011 +++ src/sys/arch/hp300/dev/dnkbdmap.c Sat Feb 12 15:49:01 2011 @@ -0,0 +1,396 @@ +/* $NetBSD: dnkbdmap.c,v 1.1 2011/02/12 15:49:01 tsutsui Exp $ */ +/* $OpenBSD: dnkbdmap.c,v 1.2 2005/05/06 22:22:53 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 + +/* + * Translate Domain keycodes to US keyboard XT scancodes, for proper + * X11-over-wsmux operation. + */ +const u_int8_t dnkbd_raw[0x80] = { + 0x00, 0x00, 0x00, 0x00, 0x44, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x29, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x00, 0xd3, 0x00, 0x47, 0x48, 0x49, 0x4e, + 0x00, 0xc8, 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x00, 0x1c, 0x2b, 0x00, 0x4b, 0x4c, 0x4d, + 0x4a, 0xcb, 0x00, 0xcd, 0x00, 0x00, 0x2a, 0x00, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x00, 0x00, 0x00, 0x4f, 0x50, + 0x51, 0x00, 0x00, 0xd0, 0x00, 0x38, 0x39, 0xb8, + 0x00, 0x52, 0x00, 0x53, 0x9c, 0x00, 0x3a, 0x00 +}; +#endif + +#define KC(n) KS_KEYCODE(n) + +/* + * US English + */ + +static 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, KS_Multi_key, + KC(0x79), KS_KP_0, + KC(0x7b), KS_KP_Separator, + KC(0x7c), KS_KP_Enter, + KC(0x7e), KS_Caps_Lock +}; + +/* + * German + */ + +static const keysym_t dnkbd_keydesc_de[] = { +/* pos normal shifted altgr */ + KC(0x17), KS_dead_circumflex, KS_dead_abovering, + KC(0x19), KS_2, KS_quotedbl, + KC(0x1a), KS_3, KS_at, KS_section, + KC(0x1d), KS_6, KS_ampersand, + KC(0x1e), KS_7, KS_slash, + KC(0x1f), KS_8, KS_parenleft, + KC(0x20), KS_9, KS_parenright, + KC(0x21), KS_0, KS_equal, + KC(0x22), KS_dead_tilde, KS_question, KS_ssharp, + KC(0x23), KS_dead_acute, KS_dead_grave, + KC(0x32), KS_z, + KC(0x37), KS_braceright, KS_bracketright,KS_udiaeresis, + KC(0x38), KS_plus, KS_asterisk, + KC(0x4f), KS_bar, KS_backslash, KS_odiaeresis, + KC(0x50), KS_braceleft, KS_bracketleft, KS_adiaeresis, + KC(0x51), KS_numbersign, KS_apostrophe, + KC(0x5f), KS_less, KS_greater, + KC(0x60), KS_y, + KC(0x67), KS_comma, KS_semicolon, + KC(0x68), KS_period, KS_colon, + KC(0x69), KS_minus, KS_underscore, + KC(0x77), KS_Mode_switch, KS_Multi_key +}; + +static const keysym_t dnkbd_keydesc_de_nodead[] = { + KC(0x17), KS_asciicircum, KS_degree, + KC(0x22), KS_asciitilde, KS_question, KS_ssharp, + KC(0x23), KS_apostrophe, KS_grave +}; + +/* + * Norwegian / Danish + */ + +static const keysym_t dnkbd_keydesc_dk[] = { +/* pos normal shifted altgr */ + KC(0x17), KS_underscore, + KC(0x19), KS_2, KS_quotedbl, + KC(0x1d), KS_6, KS_ampersand, + KC(0x1e), KS_7, KS_slash, + KC(0x1f), KS_8, KS_parenleft, + KC(0x20), KS_9, KS_parenright, + KC(0x21), KS_0, KS_equal, + KC(0x22), KS_plus, KS_question, + KC(0x23), KS_dead_grave, KS_at, + KC(0x37), KS_braceright, KS_bracketright,KS_aring, + KC(0x38), KS_dead_tilde, KS_dead_circumflex,KS_dead_diaeresis, + KC(0x4f), KS_bar, KS_backslash, KS_oslash, + KC(0x50), KS_braceleft, KS_bracketleft, KS_ae, + KC(0x51), KS_dead_acute, KS_asterisk, + KC(0x5f), KS_less, KS_greater, + KC(0x67), KS_comma, KS_semicolon, + KC(0x68), KS_period, KS_colon, + KC(0x69), KS_minus, KS_underscore, + KC(0x77), KS_Mode_switch, KS_Multi_key +}; + +static const keysym_t dnkbd_keydesc_dk_nodead[] = { +/* pos normal shifted altgr */ + KC(0x23), KS_grave, KS_at, + KC(0x38), KS_asciitilde, KS_asciicircum, KS_diaeresis, + KC(0x51), KS_apostrophe, KS_asterisk, +}; + +/* + * French + */ + +static const keysym_t dnkbd_keydesc_fr[] = { +/* pos normal shifted altgr */ + KC(0x17), KS_bracketleft, KS_degree, + KC(0x18), KS_ampersand, KS_1, + KC(0x19), KS_braceleft, KS_2, KS_eacute, + KC(0x1a), KS_quotedbl, KS_3, + KC(0x1b), KS_apostrophe, KS_4, + KC(0x1c), KS_parenleft, KS_5, + KC(0x1d), KS_bracketright,KS_6, KS_section, + KC(0x1e), KS_braceright, KS_7, KS_egrave, + KC(0x1f), KS_exclam, KS_8, + KC(0x20), KS_backslash, KS_9, KS_ccedilla, + KC(0x21), KS_at, KS_0, KS_agrave, + KC(0x22), KS_parenright, KS_degree, + KC(0x23), KS_minus, KS_underscore, + KC(0x2d), KS_a, + KC(0x2e), KS_z, + KC(0x37), KS_dead_circumflex, KS_asciitilde, KS_dead_diaeresis, + KC(0x38), KS_dollar, KS_asterisk, + KC(0x46), KS_q, + KC(0x4f), KS_m, + KC(0x50), KS_bar, KS_percent, KS_ugrave, + KC(0x51), KS_grave, KS_numbersign, + KC(0x5f), KS_less, KS_greater, + KC(0x60), KS_w, + KC(0x66), KS_comma, KS_question, + KC(0x67), KS_semicolon, KS_period, + KC(0x68), KS_colon, KS_slash, + KC(0x69), KS_equal, KS_plus, + KC(0x77), KS_Mode_switch, KS_Multi_key +}; + +/* + * Japanese (and basis for international layouts) + * + * Apparently this layout lacks all japanese keys (Zenkaku/Hankaku, + * Hiragana/Katakana, Henkan and Muhenkan). Makes one wonder about + * its usefulness. + */ + +static const keysym_t dnkbd_keydesc_jp[] = { +/* pos cmd normal shifted */ + KC(0x16), KS_Cmd_Debugger, KS_Escape, + KC(0x17), KS_grave, KS_asciitilde, + KC(0x24), KS_Cmd_ResetEmul, KS_Delete, /* backspace */ + KC(0x25), KS_Delete, + /* 2b Rept */ + KC(0x3b), KS_KP_Add, + KC(0x3f), KS_parenleft, /* KS_KP_parenleft */ + KC(0x51), KS_backslash, KS_bar, + KC(0x54), KS_KP_Subtract, + KC(0x58), KS_parenright, /* KS_KP_parenright */ + KC(0x5f), KS_less, KS_greater, + KC(0x6d), KS_KP_Multiply, + KC(0x78), KS_KP_Divide, +}; + +/* + * Swiss (relative to the German layout) + */ + +static const keysym_t dnkbd_keydesc_sg[] = { +/* pos normal shifted altgr */ + KC(0x17), KS_at, KS_exclam, KS_section, + KC(0x18), KS_1, KS_plus, + KC(0x1a), KS_3, KS_asterisk, + KC(0x1b), KS_4, KS_backslash, KS_ccedilla, + KC(0x22), KS_apostrophe, KS_question, + KC(0x23), KS_dead_circumflex,KS_dead_grave, + KC(0x37), KS_braceright, KS_dead_tilde, KS_udiaeresis, KS_egrave, + KC(0x38), KS_dead_diaeresis,KS_dead_acute, + KC(0x4f), KS_bar, KS_bracketleft, KS_odiaeresis, KS_eacute, + KC(0x50), KS_braceleft, KS_bracketright,KS_adiaeresis, KS_agrave, + KC(0x51), KS_dollar, KS_numbersign, KS_sterling +}; + +static const keysym_t dnkbd_keydesc_sg_nodead[] = { +/* pos normal shifted altgr */ + KC(0x23), KS_asciicircum, KS_grave, + KC(0x37), KS_braceright, KS_asciitilde, KS_udiaeresis, KS_egrave, + KC(0x38), KS_diaeresis, KS_apostrophe +}; + +/* + * Swedish / Finnish (relative to the Norwegian / Danish layout) + */ + +static const keysym_t dnkbd_keydesc_sv[] = { +/* pos normal shifted altgr */ + KC(0x1b), KS_4, KS_dollar, KS_currency, + KC(0x23), KS_dead_grave, KS_at, KS_eacute, + KC(0x38), KS_dead_tilde, KS_dead_circumflex,KS_udiaeresis, + KC(0x4f), KS_bar, KS_backslash, KS_odiaeresis, + KC(0x50), KS_braceleft, KS_bracketleft, KS_adiaeresis +}; + +static const keysym_t dnkbd_keydesc_sv_nodead[] = { +/* pos normal shifted altgr */ + KC(0x23), KS_grave, KS_at, KS_eacute, + KC(0x38), KS_asciitilde, KS_asciicircum, KS_udiaeresis, + KC(0x51), KS_apostrophe, KS_asterisk, +}; + +/* + * UK English + */ + +static const keysym_t dnkbd_keydesc_uk[] = { +/* pos normal shifted */ + KC(0x17), KS_underscore, + KC(0x19), KS_2, KS_quotedbl, + KC(0x1d), KS_6, KS_ampersand, + KC(0x1e), KS_7, KS_apostrophe, + KC(0x1f), KS_8, KS_parenleft, + KC(0x20), KS_9, KS_parenright, + KC(0x21), KS_0, KS_underscore, + KC(0x22), KS_minus, KS_equal, + KC(0x23), KS_asciicircum, KS_asciitilde, + KC(0x37), KS_at, KS_grave, + KC(0x38), KS_bracketleft, KS_braceleft, + KC(0x4f), KS_semicolon, KS_plus, + KC(0x50), KS_colon, KS_asterisk, + KC(0x51), KS_bracketright,KS_braceright, + KC(0x5f), KS_backslash, KS_bar +}; + +#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), + KBD_MAP(KB_DE, KB_JP, dnkbd_keydesc_de), + KBD_MAP(KB_DE | KB_NODEAD, KB_DE, dnkbd_keydesc_de_nodead), + KBD_MAP(KB_DK, KB_JP, dnkbd_keydesc_dk), + KBD_MAP(KB_DK | KB_NODEAD, KB_DK, dnkbd_keydesc_dk_nodead), + KBD_MAP(KB_FR, KB_JP, dnkbd_keydesc_fr), + KBD_MAP(KB_JP, KB_US, dnkbd_keydesc_jp), + KBD_MAP(KB_SG, KB_DE, dnkbd_keydesc_sg), + KBD_MAP(KB_SG | KB_NODEAD, KB_SG, dnkbd_keydesc_sg_nodead), + KBD_MAP(KB_SV, KB_DK, dnkbd_keydesc_sv), + KBD_MAP(KB_SV | KB_NODEAD, KB_SV, dnkbd_keydesc_sv_nodead), + KBD_MAP(KB_UK, KB_JP, dnkbd_keydesc_uk), + { 0, 0, 0, 0 } +}; Index: src/sys/arch/hp300/dev/dnkbdmap.h diff -u /dev/null src/sys/arch/hp300/dev/dnkbdmap.h:1.1 --- /dev/null Sat Feb 12 15:49:02 2011 +++ src/sys/arch/hp300/dev/dnkbdmap.h Sat Feb 12 15:49:01 2011 @@ -0,0 +1,29 @@ +/* $NetBSD: dnkbdmap.h,v 1.1 2011/02/12 15:49:01 tsutsui Exp $ */ +/* $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];