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];

Reply via email to