Home | History | Annotate | Line # | Download | only in pckbport
      1  1.39    andvar /* $NetBSD: pckbd.c,v 1.39 2024/02/09 22:08:36 andvar Exp $ */
      2   1.1     bjh21 
      3   1.1     bjh21 /*-
      4  1.26        ad  * Copyright (c) 1998, 2009 The NetBSD Foundation, Inc.
      5   1.1     bjh21  * All rights reserved.
      6   1.1     bjh21  *
      7   1.1     bjh21  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1     bjh21  * by Charles M. Hannum.
      9   1.1     bjh21  *
     10   1.1     bjh21  * Redistribution and use in source and binary forms, with or without
     11   1.1     bjh21  * modification, are permitted provided that the following conditions
     12   1.1     bjh21  * are met:
     13   1.1     bjh21  * 1. Redistributions of source code must retain the above copyright
     14   1.1     bjh21  *    notice, this list of conditions and the following disclaimer.
     15   1.1     bjh21  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1     bjh21  *    notice, this list of conditions and the following disclaimer in the
     17   1.1     bjh21  *    documentation and/or other materials provided with the distribution.
     18   1.1     bjh21  *
     19   1.1     bjh21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1     bjh21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1     bjh21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1     bjh21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1     bjh21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1     bjh21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1     bjh21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1     bjh21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1     bjh21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1     bjh21  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1     bjh21  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1     bjh21  */
     31   1.1     bjh21 
     32   1.1     bjh21 /*-
     33   1.1     bjh21  * Copyright (c) 1990 The Regents of the University of California.
     34   1.1     bjh21  * All rights reserved.
     35   1.1     bjh21  *
     36   1.1     bjh21  * This code is derived from software contributed to Berkeley by
     37   1.1     bjh21  * William Jolitz and Don Ahn.
     38   1.1     bjh21  *
     39   1.1     bjh21  * Redistribution and use in source and binary forms, with or without
     40   1.1     bjh21  * modification, are permitted provided that the following conditions
     41   1.1     bjh21  * are met:
     42   1.1     bjh21  * 1. Redistributions of source code must retain the above copyright
     43   1.1     bjh21  *    notice, this list of conditions and the following disclaimer.
     44   1.1     bjh21  * 2. Redistributions in binary form must reproduce the above copyright
     45   1.1     bjh21  *    notice, this list of conditions and the following disclaimer in the
     46   1.1     bjh21  *    documentation and/or other materials provided with the distribution.
     47   1.1     bjh21  * 3. Neither the name of the University nor the names of its contributors
     48   1.1     bjh21  *    may be used to endorse or promote products derived from this software
     49   1.1     bjh21  *    without specific prior written permission.
     50   1.1     bjh21  *
     51   1.1     bjh21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52   1.1     bjh21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53   1.1     bjh21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54   1.1     bjh21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55   1.1     bjh21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56   1.1     bjh21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57   1.1     bjh21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58   1.1     bjh21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59   1.1     bjh21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60   1.1     bjh21  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61   1.1     bjh21  * SUCH DAMAGE.
     62   1.1     bjh21  *
     63   1.1     bjh21  *	@(#)pccons.c	5.11 (Berkeley) 5/21/91
     64   1.1     bjh21  */
     65   1.1     bjh21 
     66   1.1     bjh21 /*
     67   1.1     bjh21  * code to work keyboard for PC-style console
     68   1.1     bjh21  */
     69   1.1     bjh21 
     70   1.1     bjh21 #include <sys/cdefs.h>
     71  1.39    andvar __KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.39 2024/02/09 22:08:36 andvar Exp $");
     72   1.1     bjh21 
     73   1.1     bjh21 #include <sys/param.h>
     74   1.1     bjh21 #include <sys/systm.h>
     75   1.1     bjh21 #include <sys/device.h>
     76   1.1     bjh21 #include <sys/malloc.h>
     77   1.1     bjh21 #include <sys/ioctl.h>
     78   1.1     bjh21 
     79  1.16        ad #include <sys/bus.h>
     80   1.1     bjh21 
     81   1.1     bjh21 #include <dev/pckbport/pckbportvar.h>
     82   1.1     bjh21 
     83   1.1     bjh21 #include <dev/wscons/wsconsio.h>
     84   1.1     bjh21 #include <dev/wscons/wskbdvar.h>
     85   1.1     bjh21 #include <dev/wscons/wsksymdef.h>
     86   1.1     bjh21 #include <dev/wscons/wsksymvar.h>
     87   1.1     bjh21 
     88   1.6      yamt #include <dev/pckbport/pckbdreg.h>
     89   1.6      yamt #include <dev/pckbport/pckbdvar.h>
     90   1.6      yamt #include <dev/pckbport/wskbdmap_mfii.h>
     91   1.6      yamt 
     92   1.1     bjh21 #include "locators.h"
     93   1.1     bjh21 
     94   1.1     bjh21 #include "opt_pckbd_layout.h"
     95   1.7  augustss #include "opt_pckbd_cnattach_may_fail.h"
     96   1.1     bjh21 #include "opt_wsdisplay_compat.h"
     97   1.1     bjh21 
     98   1.1     bjh21 struct pckbd_internal {
     99   1.1     bjh21 	int t_isconsole;
    100   1.1     bjh21 	pckbport_tag_t t_kbctag;
    101   1.1     bjh21 	pckbport_slot_t t_kbcslot;
    102   1.1     bjh21 
    103  1.30       jdc 	int t_translating;
    104  1.30       jdc 
    105   1.1     bjh21 	int t_lastchar;
    106   1.1     bjh21 	int t_extended0;
    107   1.1     bjh21 	int t_extended1;
    108  1.30       jdc 	int t_releasing;
    109   1.1     bjh21 
    110   1.1     bjh21 	struct pckbd_softc *t_sc; /* back pointer */
    111   1.1     bjh21 };
    112   1.1     bjh21 
    113   1.1     bjh21 struct pckbd_softc {
    114  1.22      cube         device_t sc_dev;
    115   1.1     bjh21 
    116   1.1     bjh21 	struct pckbd_internal *id;
    117   1.1     bjh21 	int sc_enabled;
    118   1.1     bjh21 
    119   1.1     bjh21 	int sc_ledstate;
    120   1.1     bjh21 
    121  1.23      cube 	device_t sc_wskbddev;
    122   1.1     bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
    123   1.1     bjh21 	int rawkbd;
    124   1.1     bjh21 #endif
    125   1.1     bjh21 };
    126   1.1     bjh21 
    127  1.23      cube int pckbdprobe(device_t, cfdata_t, void *);
    128  1.23      cube void pckbdattach(device_t, device_t, void *);
    129   1.1     bjh21 
    130  1.22      cube CFATTACH_DECL_NEW(pckbd, sizeof(struct pckbd_softc),
    131   1.1     bjh21     pckbdprobe, pckbdattach, NULL, NULL);
    132   1.1     bjh21 
    133   1.2     bjh21 int	pckbd_enable(void *, int);
    134   1.2     bjh21 void	pckbd_set_leds(void *, int);
    135  1.15  christos int	pckbd_ioctl(void *, u_long, void *, int, struct lwp *);
    136   1.1     bjh21 
    137   1.1     bjh21 const struct wskbd_accessops pckbd_accessops = {
    138  1.37  riastrad 	.enable = pckbd_enable,
    139  1.37  riastrad 	.set_leds = pckbd_set_leds,
    140  1.37  riastrad 	.ioctl = pckbd_ioctl,
    141   1.1     bjh21 };
    142   1.1     bjh21 
    143   1.2     bjh21 void	pckbd_cngetc(void *, u_int *, int *);
    144   1.2     bjh21 void	pckbd_cnpollc(void *, int);
    145   1.2     bjh21 void	pckbd_cnbell(void *, u_int, u_int, u_int);
    146   1.1     bjh21 
    147   1.1     bjh21 const struct wskbd_consops pckbd_consops = {
    148  1.37  riastrad 	.getc = pckbd_cngetc,
    149  1.37  riastrad 	.pollc = pckbd_cnpollc,
    150  1.37  riastrad 	.bell = pckbd_cnbell,
    151   1.1     bjh21 };
    152   1.1     bjh21 
    153   1.1     bjh21 const struct wskbd_mapdata pckbd_keymapdata = {
    154  1.37  riastrad 	.keydesc = pckbd_keydesctab,
    155   1.1     bjh21 #ifdef PCKBD_LAYOUT
    156  1.37  riastrad 	.layout = PCKBD_LAYOUT,
    157   1.1     bjh21 #else
    158  1.37  riastrad 	.layout = KB_US,
    159   1.1     bjh21 #endif
    160   1.1     bjh21 };
    161   1.1     bjh21 
    162   1.1     bjh21 /*
    163  1.39    andvar  * Hackish support for a bell on the PC Keyboard; when a suitable beeper
    164   1.1     bjh21  * is found, it attaches itself into the pckbd driver here.
    165   1.1     bjh21  */
    166   1.2     bjh21 void	(*pckbd_bell_fn)(void *, u_int, u_int, u_int, int);
    167   1.1     bjh21 void	*pckbd_bell_fn_arg;
    168   1.1     bjh21 
    169   1.2     bjh21 void	pckbd_bell(u_int, u_int, u_int, int);
    170   1.1     bjh21 
    171  1.30       jdc int	pckbd_scancode_translate(struct pckbd_internal *, int);
    172  1.30       jdc int	pckbd_set_xtscancode(pckbport_tag_t, pckbport_slot_t,
    173  1.30       jdc 	    struct pckbd_internal *);
    174   1.2     bjh21 int	pckbd_init(struct pckbd_internal *, pckbport_tag_t, pckbport_slot_t,
    175   1.2     bjh21 			int);
    176   1.2     bjh21 void	pckbd_input(void *, int);
    177   1.2     bjh21 
    178   1.1     bjh21 struct pckbd_internal pckbd_consdata;
    179   1.1     bjh21 
    180   1.1     bjh21 int
    181  1.30       jdc pckbd_set_xtscancode(pckbport_tag_t kbctag, pckbport_slot_t kbcslot,
    182  1.30       jdc     struct pckbd_internal *id)
    183   1.1     bjh21 {
    184  1.30       jdc 	int xt, res = 0;
    185   1.1     bjh21 	u_char cmd[2];
    186   1.1     bjh21 
    187   1.1     bjh21 	/*
    188   1.1     bjh21 	 * Some keyboard/8042 combinations do not seem to work if the keyboard
    189   1.1     bjh21 	 * is set to table 1; in fact, it would appear that some keyboards just
    190   1.1     bjh21 	 * ignore the command altogether.  So by default, we use the AT scan
    191   1.1     bjh21 	 * codes and have the 8042 translate them.  Unfortunately, this is
    192   1.1     bjh21 	 * known to not work on some PS/2 machines.  We try desperately to deal
    193   1.1     bjh21 	 * with this by checking the (lack of a) translate bit in the 8042 and
    194   1.1     bjh21 	 * attempting to set the keyboard to XT mode.  If this all fails, well,
    195  1.30       jdc 	 * tough luck.  If the PCKBC_CANT_TRANSLATE pckbc flag was set, we
    196  1.30       jdc 	 * enable software translation.
    197   1.1     bjh21 	 *
    198   1.1     bjh21 	 * XXX It would perhaps be a better choice to just use AT scan codes
    199   1.1     bjh21 	 * and not bother with this.
    200   1.1     bjh21 	 */
    201  1.30       jdc 	xt = pckbport_xt_translation(kbctag, kbcslot, 1);
    202  1.30       jdc 	if (xt == 1) {
    203   1.1     bjh21 		/* The 8042 is translating for us; use AT codes. */
    204   1.1     bjh21 		cmd[0] = KBC_SETTABLE;
    205   1.1     bjh21 		cmd[1] = 2;
    206   1.1     bjh21 		res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
    207   1.1     bjh21 		if (res) {
    208   1.8  christos 			u_char cmdb[1];
    209  1.38  christos 			aprint_debug("%s: error setting scanset 2\n", __func__);
    210   1.1     bjh21 			/*
    211   1.1     bjh21 			 * XXX at least one keyboard is reported to lock up
    212   1.1     bjh21 			 * if a "set table" is attempted, thus the "reset".
    213   1.1     bjh21 			 * XXX ignore errors, scanset 2 should be
    214   1.1     bjh21 			 * default anyway.
    215   1.1     bjh21 			 */
    216   1.8  christos 			cmdb[0] = KBC_RESET;
    217  1.38  christos 			(void)pckbport_poll_cmd(kbctag, kbcslot, cmdb, 1, 1,
    218  1.38  christos 			    0, 1);
    219   1.1     bjh21 			pckbport_flush(kbctag, kbcslot);
    220   1.1     bjh21 			res = 0;
    221   1.1     bjh21 		}
    222  1.30       jdc 		if (id != NULL)
    223  1.30       jdc 			id->t_translating = 1;
    224  1.30       jdc 	} else if (xt == -1) {
    225  1.30       jdc 		/* Software translation required */
    226  1.30       jdc 		if (id != NULL)
    227  1.30       jdc 			id->t_translating = 0;
    228   1.1     bjh21 	} else {
    229   1.1     bjh21 		/* Stupid 8042; set keyboard to XT codes. */
    230   1.1     bjh21 		cmd[0] = KBC_SETTABLE;
    231   1.1     bjh21 		cmd[1] = 1;
    232   1.1     bjh21 		res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
    233   1.1     bjh21 		if (res)
    234  1.38  christos 			aprint_debug("%s: error setting scanset 1\n", __func__);
    235  1.30       jdc 		if (id != NULL)
    236  1.30       jdc 			id->t_translating = 1;
    237   1.1     bjh21 	}
    238   1.2     bjh21 	return res;
    239   1.1     bjh21 }
    240   1.1     bjh21 
    241   1.1     bjh21 static int
    242   1.2     bjh21 pckbd_is_console(pckbport_tag_t tag, pckbport_slot_t slot)
    243   1.2     bjh21 {
    244   1.2     bjh21 
    245   1.2     bjh21 	return pckbd_consdata.t_isconsole &&
    246   1.2     bjh21 	    tag == pckbd_consdata.t_kbctag && slot == pckbd_consdata.t_kbcslot;
    247   1.1     bjh21 }
    248   1.1     bjh21 
    249  1.18  jmcneill static bool
    250  1.29    dyoung pckbd_suspend(device_t dv, const pmf_qual_t *qual)
    251  1.11  christos {
    252  1.18  jmcneill 	struct pckbd_softc *sc = device_private(dv);
    253  1.18  jmcneill 	u_char cmd[1];
    254  1.11  christos 	int res;
    255  1.11  christos 
    256  1.18  jmcneill 	/* XXX duped from pckbd_enable, but we want to disable
    257  1.18  jmcneill 	 *     it even if it's the console kbd
    258  1.18  jmcneill 	 */
    259  1.18  jmcneill 	cmd[0] = KBC_DISABLE;
    260  1.38  christos 	res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
    261  1.38  christos 	    cmd, 1, 0, 1, 0);
    262  1.18  jmcneill 	if (res)
    263  1.18  jmcneill 		return false;
    264  1.18  jmcneill 
    265  1.18  jmcneill 	pckbport_slot_enable(sc->id->t_kbctag,
    266  1.18  jmcneill 	    sc->id->t_kbcslot, 0);
    267  1.11  christos 
    268  1.18  jmcneill 	sc->sc_enabled = 0;
    269  1.18  jmcneill 	return true;
    270  1.18  jmcneill }
    271  1.11  christos 
    272  1.18  jmcneill static bool
    273  1.29    dyoung pckbd_resume(device_t dv, const pmf_qual_t *qual)
    274  1.18  jmcneill {
    275  1.18  jmcneill 	struct pckbd_softc *sc = device_private(dv);
    276  1.18  jmcneill 	u_char cmd[1], resp[1];
    277  1.18  jmcneill 	int res;
    278  1.11  christos 
    279  1.18  jmcneill 	/* XXX jmcneill reset the keyboard */
    280  1.18  jmcneill 	pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot);
    281  1.11  christos 
    282  1.18  jmcneill 	cmd[0] = KBC_RESET;
    283  1.18  jmcneill 	res = pckbport_poll_cmd(sc->id->t_kbctag,
    284  1.18  jmcneill 	    sc->id->t_kbcslot, cmd, 1, 1, resp, 1);
    285  1.18  jmcneill 	if (res)
    286  1.32     prlw1 		aprint_debug("%s: reset error %d\n", __func__, res);
    287  1.18  jmcneill 	if (resp[0] != KBR_RSTDONE)
    288  1.32     prlw1 		printf("%s: reset response 0x%x\n", __func__, resp[0]);
    289  1.11  christos 
    290  1.18  jmcneill 	pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot);
    291  1.11  christos 
    292  1.18  jmcneill 	pckbd_enable(sc, 1);
    293  1.11  christos 
    294  1.18  jmcneill 	return true;
    295  1.11  christos }
    296  1.11  christos 
    297   1.1     bjh21 /*
    298  1.38  christos  * these are three bad jokes
    299   1.1     bjh21  */
    300  1.38  christos static bool
    301  1.38  christos check_keyboard_by_id(struct pckbport_attach_args *pa)
    302  1.38  christos {
    303  1.38  christos 	u_char cmd[1], resp[2];
    304  1.38  christos 	int res;
    305  1.38  christos 
    306  1.38  christos 	cmd[0] = KBC_GETID;
    307  1.38  christos 	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 0);
    308  1.38  christos 	if (res) {
    309  1.38  christos 		aprint_debug("%s: getid failed with %d\n", __func__, res);
    310  1.38  christos 		return false;
    311  1.38  christos 	}
    312  1.38  christos 
    313  1.38  christos 	switch (resp[0]) {
    314  1.38  christos 	case 0xab: case 0xac:	/* Regular and NCD Sun keyboards */
    315  1.38  christos 	case 0x2b: case 0x5d:	/* Trust keyboard, raw and translated */
    316  1.38  christos 	case 0x60: case 0x47:	/* NMB SGI keyboard, raw and translated */
    317  1.38  christos 		return true;
    318  1.38  christos 	default:
    319  1.38  christos 		aprint_debug("%s: getid returned %#x\n", __func__, resp[0]);
    320  1.38  christos 		return false;
    321  1.38  christos 	}
    322  1.38  christos 
    323  1.38  christos }
    324  1.38  christos 
    325   1.1     bjh21 int
    326  1.23      cube pckbdprobe(device_t parent, cfdata_t cf, void *aux)
    327   1.1     bjh21 {
    328   1.1     bjh21 	struct pckbport_attach_args *pa = aux;
    329   1.2     bjh21 	int res;
    330   1.1     bjh21 	u_char cmd[1], resp[1];
    331   1.1     bjh21 
    332   1.1     bjh21 	/*
    333   1.1     bjh21 	 * XXX There are rumours that a keyboard can be connected
    334   1.1     bjh21 	 * to the aux port as well. For me, this didn't work.
    335   1.1     bjh21 	 * For further experiments, allow it if explicitly
    336   1.1     bjh21 	 * wired in the config file.
    337   1.1     bjh21 	 */
    338   1.1     bjh21 	if ((pa->pa_slot != PCKBPORT_KBD_SLOT) &&
    339   1.1     bjh21 	    (cf->cf_loc[PCKBPORTCF_SLOT] == PCKBPORTCF_SLOT_DEFAULT))
    340   1.2     bjh21 		return 0;
    341   1.1     bjh21 
    342   1.1     bjh21 	/* Flush any garbage. */
    343   1.1     bjh21 	pckbport_flush(pa->pa_tag, pa->pa_slot);
    344   1.1     bjh21 
    345   1.1     bjh21 	/* Reset the keyboard. */
    346   1.1     bjh21 	cmd[0] = KBC_RESET;
    347   1.1     bjh21 	res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
    348   1.1     bjh21 	if (res) {
    349  1.38  christos 		aprint_debug("%s: reset error %d\n", __func__, res);
    350  1.38  christos 
    351  1.38  christos 		/*
    352  1.38  christos 		 * On Chromebooks reset fails but otherwise the controller
    353  1.38  christos 		 * works fine.
    354  1.38  christos 		 * Check keyboard IDs similar to Linux and Haiku.
    355  1.38  christos 		 * FreeBSD's approach here is to skip probing if
    356  1.38  christos 		 * coreboot is detected which is suboptimal as coreboot
    357  1.38  christos 		 * also supports some mac models which have no PC controller
    358  1.38  christos 		 */
    359  1.38  christos 		if (check_keyboard_by_id(pa)) {
    360  1.38  christos 			if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
    361  1.38  christos 				return 0;
    362  1.38  christos 			return 2;
    363  1.38  christos 		}
    364  1.38  christos 
    365   1.1     bjh21 		/*
    366   1.1     bjh21 		 * There is probably no keyboard connected.
    367   1.1     bjh21 		 * Let the probe succeed if the keyboard is used
    368   1.1     bjh21 		 * as console input - it can be connected later.
    369   1.1     bjh21 		 */
    370   1.2     bjh21 		return pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0;
    371   1.1     bjh21 	}
    372   1.1     bjh21 	if (resp[0] != KBR_RSTDONE) {
    373  1.38  christos 		printf("%s: reset response %#x\n", __func__, resp[0]);
    374  1.38  christos 
    375  1.38  christos 		if (check_keyboard_by_id(pa)) {
    376  1.38  christos 			if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
    377  1.38  christos 				return 0;
    378  1.38  christos 			return 2;
    379  1.38  christos 		}
    380  1.38  christos 
    381   1.2     bjh21 		return 0;
    382   1.1     bjh21 	}
    383   1.1     bjh21 
    384   1.1     bjh21 	/*
    385   1.1     bjh21 	 * Some keyboards seem to leave a second ack byte after the reset.
    386   1.1     bjh21 	 * This is kind of stupid, but we account for them anyway by just
    387   1.1     bjh21 	 * flushing the buffer.
    388   1.1     bjh21 	 */
    389   1.1     bjh21 	pckbport_flush(pa->pa_tag, pa->pa_slot);
    390   1.1     bjh21 
    391  1.30       jdc 	if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
    392   1.2     bjh21 		return 0;
    393   1.1     bjh21 
    394   1.2     bjh21 	return 2;
    395   1.1     bjh21 }
    396   1.1     bjh21 
    397   1.1     bjh21 void
    398  1.23      cube pckbdattach(device_t parent, device_t self, void *aux)
    399   1.1     bjh21 {
    400  1.10   thorpej 	struct pckbd_softc *sc = device_private(self);
    401   1.1     bjh21 	struct pckbport_attach_args *pa = aux;
    402   1.2     bjh21 	struct wskbddev_attach_args a;
    403   1.1     bjh21 	int isconsole;
    404   1.1     bjh21 	u_char cmd[1];
    405   1.1     bjh21 
    406  1.17  jmcneill 	aprint_naive("\n");
    407  1.17  jmcneill 	aprint_normal("\n");
    408   1.1     bjh21 
    409  1.22      cube 	sc->sc_dev = self;
    410   1.1     bjh21 	isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot);
    411   1.1     bjh21 
    412   1.1     bjh21 	if (isconsole) {
    413   1.1     bjh21 		sc->id = &pckbd_consdata;
    414   1.1     bjh21 
    415   1.3     perry 		/*
    416   1.3     perry 		 * Some keyboards are not enabled after a reset,
    417   1.1     bjh21 		 * so make sure it is enabled now.
    418   1.1     bjh21 		 */
    419   1.1     bjh21 		cmd[0] = KBC_ENABLE;
    420   1.1     bjh21 		(void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
    421  1.38  christos 		    cmd, 1, 0, 0, 0);
    422   1.1     bjh21 		sc->sc_enabled = 1;
    423   1.1     bjh21 	} else {
    424  1.38  christos 		sc->id = malloc(sizeof(*sc->id), M_DEVBUF, M_WAITOK);
    425   1.1     bjh21 		(void) pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0);
    426   1.1     bjh21 
    427   1.1     bjh21 		/* no interrupts until enabled */
    428   1.1     bjh21 		cmd[0] = KBC_DISABLE;
    429   1.1     bjh21 		(void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
    430  1.38  christos 		    cmd, 1, 0, 0, 0);
    431   1.1     bjh21 		sc->sc_enabled = 0;
    432   1.1     bjh21 	}
    433   1.1     bjh21 
    434   1.1     bjh21 	sc->id->t_sc = sc;
    435   1.1     bjh21 
    436   1.1     bjh21 	pckbport_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot,
    437  1.22      cube 			       pckbd_input, sc, device_xname(sc->sc_dev));
    438   1.1     bjh21 
    439   1.1     bjh21 	a.console = isconsole;
    440   1.1     bjh21 
    441   1.1     bjh21 	a.keymap = &pckbd_keymapdata;
    442   1.1     bjh21 
    443   1.1     bjh21 	a.accessops = &pckbd_accessops;
    444   1.1     bjh21 	a.accesscookie = sc;
    445   1.1     bjh21 
    446  1.18  jmcneill 	if (!pmf_device_register(self, pckbd_suspend, pckbd_resume))
    447  1.18  jmcneill 		aprint_error_dev(self, "couldn't establish power handler\n");
    448  1.11  christos 
    449   1.1     bjh21 	/*
    450   1.1     bjh21 	 * Attach the wskbd, saving a handle to it.
    451   1.1     bjh21 	 * XXX XXX XXX
    452   1.1     bjh21 	 */
    453  1.36   thorpej 	sc->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE);
    454   1.1     bjh21 }
    455   1.1     bjh21 
    456   1.1     bjh21 int
    457   1.2     bjh21 pckbd_enable(void *v, int on)
    458   1.1     bjh21 {
    459   1.1     bjh21 	struct pckbd_softc *sc = v;
    460   1.2     bjh21 	int res;
    461   1.1     bjh21 	u_char cmd[1];
    462   1.1     bjh21 
    463   1.1     bjh21 	if (on) {
    464   1.1     bjh21 		if (sc->sc_enabled) {
    465  1.38  christos 			aprint_debug("%s: bad enable\n", __func__);
    466   1.2     bjh21 			return EBUSY;
    467   1.1     bjh21 		}
    468   1.1     bjh21 
    469   1.1     bjh21 		pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1);
    470   1.1     bjh21 
    471   1.1     bjh21 		cmd[0] = KBC_ENABLE;
    472   1.1     bjh21 		res = pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
    473  1.38  christos 		    cmd, 1, 0, NULL, 0);
    474   1.1     bjh21 		if (res) {
    475  1.38  christos 			printf("%s: command error\n", __func__);
    476  1.38  christos 			return res;
    477   1.1     bjh21 		}
    478   1.1     bjh21 
    479   1.1     bjh21 		res = pckbd_set_xtscancode(sc->id->t_kbctag,
    480  1.38  christos 		    sc->id->t_kbcslot, sc->id);
    481   1.1     bjh21 		if (res)
    482   1.2     bjh21 			return res;
    483   1.1     bjh21 
    484   1.1     bjh21 		sc->sc_enabled = 1;
    485   1.1     bjh21 	} else {
    486   1.1     bjh21 		if (sc->id->t_isconsole)
    487   1.2     bjh21 			return EBUSY;
    488   1.1     bjh21 
    489   1.1     bjh21 		cmd[0] = KBC_DISABLE;
    490   1.1     bjh21 		res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
    491  1.38  christos 		    cmd, 1, 0, 1, 0);
    492   1.1     bjh21 		if (res) {
    493  1.38  christos 			printf("%s: command error\n", __func__);
    494   1.2     bjh21 			return res;
    495   1.1     bjh21 		}
    496   1.1     bjh21 
    497   1.1     bjh21 		pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0);
    498   1.1     bjh21 
    499   1.1     bjh21 		sc->sc_enabled = 0;
    500   1.1     bjh21 	}
    501   1.1     bjh21 
    502   1.2     bjh21 	return 0;
    503   1.1     bjh21 }
    504   1.1     bjh21 
    505  1.30       jdc const u_int8_t pckbd_xtbl[] = {
    506  1.30       jdc /* 0x00 */
    507  1.30       jdc 	0,
    508  1.30       jdc 	0x43,		/* F9 */
    509  1.30       jdc 	0x89,		/* SunStop */
    510  1.30       jdc 	0x3f,		/* F5 */
    511  1.30       jdc 	0x3d,		/* F3 */
    512  1.30       jdc 	0x3b,		/* F1 */
    513  1.30       jdc 	0x3c,		/* F2 */
    514  1.30       jdc 	0x58,		/* F12 */
    515  1.30       jdc 	0,
    516  1.30       jdc 	0x44,		/* F10 */
    517  1.30       jdc 	0x42,		/* F8 */
    518  1.30       jdc 	0x40,		/* F6 */
    519  1.30       jdc 	0x3e,		/* F4 */
    520  1.30       jdc 	0x0f,		/* Tab */
    521  1.30       jdc 	0x29,		/* ` ~ */
    522  1.30       jdc 	0,
    523  1.30       jdc /* 0x10 */
    524  1.30       jdc 	0,
    525  1.30       jdc 	0x38,		/* Left Alt */
    526  1.30       jdc 	0x2a,		/* Left Shift */
    527  1.30       jdc 	0,
    528  1.30       jdc 	0x1d,		/* Left Ctrl */
    529  1.30       jdc 	0x10,		/* q */
    530  1.30       jdc 	0x02,		/* 1 ! */
    531  1.30       jdc 	0,
    532  1.30       jdc 	0,
    533  1.30       jdc 	0,
    534  1.30       jdc 	0x2c,		/* z */
    535  1.30       jdc 	0x1f,		/* s */
    536  1.30       jdc 	0x1e,		/* a */
    537  1.30       jdc 	0x11,		/* w */
    538  1.30       jdc 	0x03,		/* 2 @ */
    539  1.30       jdc 	0,
    540  1.30       jdc /* 0x20 */
    541  1.30       jdc 	0,
    542  1.30       jdc 	0x2e,		/* c */
    543  1.30       jdc 	0x2d,		/* x */
    544  1.30       jdc 	0x20,		/* d */
    545  1.30       jdc 	0x12,		/* e */
    546  1.30       jdc 	0x05,		/* 4 $ */
    547  1.30       jdc 	0x04,		/* 3 # */
    548  1.30       jdc 	0,
    549  1.30       jdc 	0,
    550  1.30       jdc 	0x39,		/* Space */
    551  1.30       jdc 	0x2f,		/* v */
    552  1.30       jdc 	0x21,		/* f */
    553  1.30       jdc 	0x14,		/* t */
    554  1.30       jdc 	0x13,		/* r */
    555  1.30       jdc 	0x06,		/* 5 % */
    556  1.30       jdc 	0,
    557  1.30       jdc /* 0x30 */
    558  1.30       jdc 	0,
    559  1.30       jdc 	0x31,		/* n */
    560  1.30       jdc 	0x30,		/* b */
    561  1.30       jdc 	0x23,		/* h */
    562  1.30       jdc 	0x22,		/* g */
    563  1.30       jdc 	0x15,		/* y */
    564  1.30       jdc 	0x07,		/* 6 ^ */
    565  1.30       jdc 	0,
    566  1.30       jdc 	0,
    567  1.30       jdc 	0,
    568  1.30       jdc 	0x32,		/* m */
    569  1.30       jdc 	0x24,		/* j */
    570  1.30       jdc 	0x16,		/* u */
    571  1.30       jdc 	0x08,		/* 7 & */
    572  1.30       jdc 	0x09,		/* 8 * */
    573  1.30       jdc 	0,
    574  1.30       jdc /* 0x40 */
    575  1.30       jdc 	0,
    576  1.30       jdc 	0x33,		/* , < */
    577  1.30       jdc 	0x25,		/* k */
    578  1.30       jdc 	0x17,		/* i */
    579  1.30       jdc 	0x18,		/* o */
    580  1.30       jdc 	0x0b,		/* 0 ) */
    581  1.30       jdc 	0x0a,		/* 9 ( */
    582  1.30       jdc 	0,
    583  1.30       jdc 	0,
    584  1.30       jdc 	0x34,		/* . > */
    585  1.30       jdc 	0x35,		/* / ? */
    586  1.30       jdc 	0x26,		/* l */
    587  1.30       jdc 	0x27,		/* ; : */
    588  1.30       jdc 	0x19,		/* p */
    589  1.30       jdc 	0x0c,		/* - _ */
    590  1.30       jdc 	0,
    591  1.30       jdc /* 0x50 */
    592  1.30       jdc 	0,
    593  1.30       jdc 	0,
    594  1.30       jdc 	0x28,		/* ' " */
    595  1.30       jdc 	0,
    596  1.30       jdc 	0x1a,		/* [ { */
    597  1.30       jdc 	0x0d,		/* = + */
    598  1.30       jdc 	0,
    599  1.30       jdc 	0,
    600  1.30       jdc 	0x3a,		/* Caps Lock */
    601  1.30       jdc 	0x36,		/* Right Shift */
    602  1.30       jdc 	0x1c,		/* Return */
    603  1.30       jdc 	0x1b,		/* ] } */
    604  1.30       jdc 	0,
    605  1.30       jdc 	0x2b,		/* \ | */
    606  1.30       jdc 	0,
    607  1.30       jdc 	0,
    608  1.30       jdc /* 0x60 */
    609  1.30       jdc 	0,
    610  1.30       jdc 	0,
    611  1.30       jdc 	0,
    612  1.30       jdc 	0,
    613  1.30       jdc 	0,
    614  1.30       jdc 	0,
    615  1.30       jdc 	0x0e,		/* Back Space */
    616  1.30       jdc 	0,
    617  1.30       jdc 	0,
    618  1.30       jdc 	0x4f,		/* KP 1 */
    619  1.30       jdc 	0,
    620  1.30       jdc 	0x4b,		/* KP 4 */
    621  1.30       jdc 	0x47,		/* KP 7 */
    622  1.30       jdc 	0,
    623  1.30       jdc 	0,
    624  1.30       jdc 	0,
    625  1.30       jdc /* 0x70 */
    626  1.30       jdc 	0x52,		/* KP 0 */
    627  1.30       jdc 	0x53,		/* KP . */
    628  1.30       jdc 	0x50,		/* KP 2 */
    629  1.30       jdc 	0x4c,		/* KP 5 */
    630  1.30       jdc 	0x4d,		/* KP 6 */
    631  1.30       jdc 	0x48,		/* KP 8 */
    632  1.30       jdc 	0x01,		/* Escape */
    633  1.30       jdc 	0x45,		/* Num Lock */
    634  1.30       jdc 	0x57,		/* F11 */
    635  1.30       jdc 	0x4e,		/* KP + */
    636  1.30       jdc 	0x51,		/* KP 3 */
    637  1.30       jdc 	0x4a,		/* KP - */
    638  1.30       jdc 	0x37,		/* KP * */
    639  1.30       jdc 	0x49,		/* KP 9 */
    640  1.30       jdc 	0x46,		/* Scroll Lock */
    641  1.30       jdc 	0,
    642  1.30       jdc /* 0x80 */
    643  1.30       jdc 	0,
    644  1.30       jdc 	0,
    645  1.30       jdc 	0,
    646  1.30       jdc 	0x41,		/* F7 (produced as an actual 8 bit code) */
    647  1.30       jdc 	0,		/* Alt-Print Screen */
    648  1.30       jdc 	0,
    649  1.30       jdc 	0,
    650  1.30       jdc 	0,
    651  1.30       jdc 	0,
    652  1.30       jdc 	0,
    653  1.30       jdc 	0,
    654  1.30       jdc 	0,
    655  1.30       jdc 	0,
    656  1.30       jdc 	0,
    657  1.30       jdc 	0,
    658  1.30       jdc 	0,
    659  1.30       jdc /* 0x90 */
    660  1.30       jdc 	0xdb,		/* Left Meta */
    661  1.30       jdc 	0x88,		/* SunHelp */
    662  1.30       jdc 	0x8a,		/* SunAgain */
    663  1.30       jdc 	0x8c,		/* SunUndo */
    664  1.30       jdc 	0x8e,		/* SunCopy */
    665  1.30       jdc 	0x90,		/* SunPaste */
    666  1.30       jdc 	0x92,		/* SunCut */
    667  1.30       jdc 	0x8b,		/* SunProps */
    668  1.30       jdc 	0x8d,		/* SunFront */
    669  1.30       jdc 	0x8f,		/* SunOpen */
    670  1.30       jdc 	0x91		/* SunFind */
    671  1.30       jdc };
    672  1.30       jdc 
    673  1.30       jdc const u_int8_t pckbd_xtbl_ext[] = {
    674  1.30       jdc /* 0x00 */
    675  1.30       jdc 	0,
    676  1.30       jdc 	0,
    677  1.30       jdc 	0,
    678  1.30       jdc 	0,
    679  1.30       jdc 	0,
    680  1.30       jdc 	0,
    681  1.30       jdc 	0,
    682  1.30       jdc 	0,
    683  1.30       jdc 	0,
    684  1.30       jdc 	0,
    685  1.30       jdc 	0,
    686  1.30       jdc 	0,
    687  1.30       jdc 	0,
    688  1.30       jdc 	0,
    689  1.30       jdc 	0,
    690  1.30       jdc 	0,
    691  1.30       jdc /* 0x10 */
    692  1.30       jdc 	0,
    693  1.30       jdc 	0x38,		/* Right Alt */
    694  1.30       jdc 	0,		/* E0 12, to be ignored */
    695  1.30       jdc 	0,
    696  1.30       jdc 	0x1d,		/* Right Ctrl */
    697  1.30       jdc 	0,
    698  1.30       jdc 	0,
    699  1.30       jdc 	0,
    700  1.30       jdc 	0,
    701  1.30       jdc 	0,
    702  1.30       jdc 	0,
    703  1.30       jdc 	0,
    704  1.30       jdc 	0,
    705  1.30       jdc 	0,
    706  1.30       jdc 	0,
    707  1.30       jdc 	0,
    708  1.30       jdc /* 0x20 */
    709  1.30       jdc 	0,
    710  1.30       jdc 	0,
    711  1.30       jdc 	0,
    712  1.30       jdc 	0,
    713  1.30       jdc 	0,
    714  1.30       jdc 	0,
    715  1.30       jdc 	0,
    716  1.30       jdc 	0,
    717  1.30       jdc 	0,
    718  1.30       jdc 	0,
    719  1.30       jdc 	0,
    720  1.30       jdc 	0,
    721  1.30       jdc 	0,
    722  1.30       jdc 	0,
    723  1.30       jdc 	0,
    724  1.30       jdc 	0xdd,		/* Compose */
    725  1.30       jdc /* 0x30 */
    726  1.30       jdc 	0,
    727  1.30       jdc 	0,
    728  1.30       jdc 	0,
    729  1.30       jdc 	0,
    730  1.30       jdc 	0,
    731  1.30       jdc 	0,
    732  1.30       jdc 	0,
    733  1.30       jdc 	0,
    734  1.30       jdc 	0,
    735  1.30       jdc 	0,
    736  1.30       jdc 	0,
    737  1.30       jdc 	0,
    738  1.30       jdc 	0,
    739  1.30       jdc 	0,
    740  1.30       jdc 	0,
    741  1.30       jdc 	0,
    742  1.30       jdc /* 0x40 */
    743  1.30       jdc 	0,
    744  1.30       jdc 	0,
    745  1.30       jdc 	0,
    746  1.30       jdc 	0,
    747  1.30       jdc 	0,
    748  1.30       jdc 	0,
    749  1.30       jdc 	0,
    750  1.30       jdc 	0,
    751  1.30       jdc 	0,
    752  1.30       jdc 	0,
    753  1.30       jdc 	0xb5,		/* KP / */
    754  1.30       jdc 	0,
    755  1.30       jdc 	0,
    756  1.30       jdc 	0,
    757  1.30       jdc 	0,
    758  1.30       jdc 	0,
    759  1.30       jdc /* 0x50 */
    760  1.30       jdc 	0,
    761  1.30       jdc 	0,
    762  1.30       jdc 	0,
    763  1.30       jdc 	0,
    764  1.30       jdc 	0,
    765  1.30       jdc 	0,
    766  1.30       jdc 	0,
    767  1.30       jdc 	0,
    768  1.30       jdc 	0,
    769  1.30       jdc 	0,
    770  1.30       jdc 	0x1c,		/* KP Return */
    771  1.30       jdc 	0,
    772  1.30       jdc 	0,
    773  1.30       jdc 	0,
    774  1.30       jdc 	0,
    775  1.30       jdc 	0,
    776  1.30       jdc /* 0x60 */
    777  1.30       jdc 	0,
    778  1.30       jdc 	0,
    779  1.30       jdc 	0,
    780  1.30       jdc 	0,
    781  1.30       jdc 	0,
    782  1.30       jdc 	0,
    783  1.30       jdc 	0,
    784  1.30       jdc 	0,
    785  1.30       jdc 	0,
    786  1.30       jdc 	0x4f,		/* End */
    787  1.30       jdc 	0,
    788  1.30       jdc 	0x4b,		/* Left */
    789  1.30       jdc 	0x47,		/* Home */
    790  1.30       jdc 	0,
    791  1.30       jdc 	0,
    792  1.30       jdc 	0,
    793  1.30       jdc /* 0x70 */
    794  1.30       jdc 	0x52,		/* Insert */
    795  1.30       jdc 	0x53,		/* Delete */
    796  1.30       jdc 	0x50,		/* Down */
    797  1.30       jdc 	0,
    798  1.30       jdc 	0x4d,		/* Right */
    799  1.30       jdc 	0x48,		/* Up */
    800  1.30       jdc 	0,
    801  1.30       jdc 	0,
    802  1.30       jdc 	0,
    803  1.30       jdc 	0,
    804  1.30       jdc 	0x51,		/* Page Down */
    805  1.30       jdc 	0,
    806  1.30       jdc 	0x37,		/* Print Screen */
    807  1.30       jdc 	0x49,		/* Page Up */
    808  1.30       jdc 	0x46,		/* Ctrl-Break */
    809  1.30       jdc 	0
    810  1.30       jdc };
    811  1.30       jdc 
    812  1.30       jdc /*
    813  1.30       jdc  * Translate scan codes from set 2 to set 1
    814  1.30       jdc  */
    815  1.30       jdc int
    816  1.30       jdc pckbd_scancode_translate(struct pckbd_internal *id, int datain)
    817  1.30       jdc {
    818  1.30       jdc 	if (id->t_translating != 0)
    819  1.30       jdc 		return datain;
    820  1.30       jdc 
    821  1.30       jdc 	if (datain == KBR_BREAK) {
    822  1.30       jdc 		id->t_releasing = 0x80;	/* next keycode is a release */
    823  1.30       jdc 		return 0;	/* consume scancode */
    824  1.30       jdc 	}
    825  1.30       jdc 
    826  1.30       jdc 	/*
    827  1.30       jdc 	 * Handle extended sequences
    828  1.30       jdc 	 */
    829  1.30       jdc 	if (datain == KBR_EXTENDED0 || datain == KBR_EXTENDED1)
    830  1.30       jdc 		return datain;
    831  1.30       jdc 
    832  1.30       jdc 	/*
    833  1.30       jdc 	 * Convert BREAK sequence (14 77 -> 1D 45)
    834  1.30       jdc 	 */
    835  1.30       jdc 	if (id->t_extended1 == 2 && datain == 0x14)
    836  1.30       jdc 		return 0x1d | id->t_releasing;
    837  1.30       jdc 	else if (id->t_extended1 == 1 && datain == 0x77)
    838  1.30       jdc 		return 0x45 | id->t_releasing;
    839  1.30       jdc 
    840  1.30       jdc 	if (id->t_extended0 != 0) {
    841  1.30       jdc 		if (datain >= sizeof pckbd_xtbl_ext)
    842  1.30       jdc 			datain = 0;
    843  1.30       jdc 		else
    844  1.30       jdc 			datain = pckbd_xtbl_ext[datain];
    845  1.30       jdc 	} else {
    846  1.30       jdc 		if (datain >= sizeof pckbd_xtbl)
    847  1.30       jdc 			datain = 0;
    848  1.30       jdc 		else
    849  1.30       jdc 			datain = pckbd_xtbl[datain];
    850  1.30       jdc 	}
    851  1.30       jdc 
    852  1.30       jdc 	/*
    853  1.30       jdc 	 * If we are mapping in the range 128-254, then make this
    854  1.30       jdc 	 * an extended keycode, as table 1 codes are limited to
    855  1.30       jdc 	 * the range 0-127 (the top bit is used for key up/break).
    856  1.30       jdc 	 */
    857  1.30       jdc 	if (datain > 0x7f) {
    858  1.30       jdc 		datain &= 0x7f;
    859  1.30       jdc 		id->t_extended0 = 0x80;
    860  1.30       jdc 	}
    861  1.30       jdc 
    862  1.30       jdc 	if (datain == 0) {
    863  1.30       jdc 		/*
    864  1.30       jdc 		 * We don't know how to translate this scan code, but
    865  1.30       jdc 		 * we can't silently eat it either (because there might
    866  1.30       jdc 		 * have been an extended byte transmitted already).
    867  1.30       jdc 		 * Hopefully this value will be harmless to the upper
    868  1.30       jdc 		 * layers.
    869  1.30       jdc 		 */
    870  1.30       jdc 		return 0xff;
    871  1.30       jdc 	}
    872  1.30       jdc 	return datain | id->t_releasing;
    873  1.30       jdc }
    874  1.30       jdc 
    875  1.38  christos static bool
    876   1.2     bjh21 pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout)
    877   1.1     bjh21 {
    878   1.1     bjh21 	int key;
    879  1.30       jdc 	int releasing;
    880   1.1     bjh21 
    881   1.1     bjh21 	if (datain == KBR_EXTENDED0) {
    882  1.30       jdc 		id->t_extended0 = 0x80;
    883  1.38  christos 		return false;
    884   1.1     bjh21 	} else if (datain == KBR_EXTENDED1) {
    885   1.1     bjh21 		id->t_extended1 = 2;
    886  1.38  christos 		return false;
    887   1.1     bjh21 	}
    888   1.1     bjh21 
    889  1.30       jdc 	releasing = datain & 0x80;
    890  1.30       jdc 	datain &= 0x7f;
    891  1.30       jdc 
    892  1.30       jdc 	if (id->t_extended0 == 0x80) {
    893  1.30       jdc 		switch (datain) {
    894  1.27  jakllsch 		case 0x2a:
    895  1.27  jakllsch 		case 0x36:
    896  1.27  jakllsch 			id->t_extended0 = 0;
    897  1.38  christos 			return false;
    898  1.27  jakllsch 		default:
    899  1.27  jakllsch 			break;
    900  1.27  jakllsch 		}
    901  1.27  jakllsch 	}
    902  1.27  jakllsch 
    903  1.30       jdc 	/* map extended keys to (unused) codes 128-254 */
    904  1.30       jdc 	key = datain | id->t_extended0;
    905   1.1     bjh21 	id->t_extended0 = 0;
    906   1.1     bjh21 
    907   1.1     bjh21 	/*
    908   1.1     bjh21 	 * process PAUSE (also break) key (EXT1 1D 45  EXT1 9D C5):
    909   1.1     bjh21 	 * map to (unused) code 7F
    910   1.1     bjh21 	 */
    911   1.1     bjh21 	if (id->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) {
    912   1.1     bjh21 		id->t_extended1 = 1;
    913  1.38  christos 		return false;
    914   1.1     bjh21 	} else if (id->t_extended1 == 1 &&
    915   1.1     bjh21 		   (datain == 0x45 || datain == 0xc5)) {
    916   1.1     bjh21 		id->t_extended1 = 0;
    917   1.1     bjh21 		key = 0x7f;
    918   1.1     bjh21 	} else if (id->t_extended1 > 0) {
    919   1.1     bjh21 		id->t_extended1 = 0;
    920   1.1     bjh21 	}
    921   1.1     bjh21 
    922  1.30       jdc 	if (id->t_translating != 0) {
    923  1.30       jdc 		id->t_releasing = releasing;
    924  1.30       jdc 	} else {
    925  1.30       jdc 		/* id->t_releasing computed in pckbd_scancode_translate() */
    926  1.30       jdc 	}
    927  1.30       jdc 
    928  1.30       jdc 	if (id->t_releasing) {
    929  1.30       jdc 		id->t_releasing = 0;
    930   1.1     bjh21 		id->t_lastchar = 0;
    931   1.1     bjh21 		*type = WSCONS_EVENT_KEY_UP;
    932   1.1     bjh21 	} else {
    933   1.1     bjh21 		/* Always ignore typematic keys */
    934   1.1     bjh21 		if (key == id->t_lastchar)
    935  1.38  christos 			return false;
    936   1.1     bjh21 		id->t_lastchar = key;
    937   1.1     bjh21 		*type = WSCONS_EVENT_KEY_DOWN;
    938   1.1     bjh21 	}
    939   1.1     bjh21 
    940   1.1     bjh21 	*dataout = key;
    941  1.38  christos 	return true;
    942   1.1     bjh21 }
    943   1.1     bjh21 
    944   1.1     bjh21 int
    945   1.2     bjh21 pckbd_init(struct pckbd_internal *t, pckbport_tag_t kbctag,
    946   1.2     bjh21     pckbport_slot_t kbcslot, int console)
    947   1.1     bjh21 {
    948   1.2     bjh21 
    949   1.1     bjh21 	memset(t, 0, sizeof(struct pckbd_internal));
    950   1.1     bjh21 
    951   1.1     bjh21 	t->t_isconsole = console;
    952   1.1     bjh21 	t->t_kbctag = kbctag;
    953   1.1     bjh21 	t->t_kbcslot = kbcslot;
    954   1.1     bjh21 
    955  1.30       jdc 	return pckbd_set_xtscancode(kbctag, kbcslot, t);
    956   1.1     bjh21 }
    957   1.1     bjh21 
    958   1.1     bjh21 static int
    959   1.2     bjh21 pckbd_led_encode(int led)
    960   1.1     bjh21 {
    961   1.1     bjh21 	int res;
    962   1.1     bjh21 
    963   1.1     bjh21 	res = 0;
    964   1.1     bjh21 
    965   1.1     bjh21 	if (led & WSKBD_LED_SCROLL)
    966   1.1     bjh21 		res |= 0x01;
    967   1.1     bjh21 	if (led & WSKBD_LED_NUM)
    968   1.1     bjh21 		res |= 0x02;
    969   1.1     bjh21 	if (led & WSKBD_LED_CAPS)
    970   1.1     bjh21 		res |= 0x04;
    971   1.2     bjh21 	return res;
    972   1.1     bjh21 }
    973   1.1     bjh21 
    974   1.1     bjh21 static int
    975   1.2     bjh21 pckbd_led_decode(int led)
    976   1.1     bjh21 {
    977   1.1     bjh21 	int res;
    978   1.1     bjh21 
    979   1.1     bjh21 	res = 0;
    980   1.1     bjh21 	if (led & 0x01)
    981   1.1     bjh21 		res |= WSKBD_LED_SCROLL;
    982   1.1     bjh21 	if (led & 0x02)
    983   1.1     bjh21 		res |= WSKBD_LED_NUM;
    984   1.1     bjh21 	if (led & 0x04)
    985   1.1     bjh21 		res |= WSKBD_LED_CAPS;
    986   1.2     bjh21 	return res;
    987   1.1     bjh21 }
    988   1.1     bjh21 
    989   1.1     bjh21 void
    990   1.2     bjh21 pckbd_set_leds(void *v, int leds)
    991   1.1     bjh21 {
    992   1.1     bjh21 	struct pckbd_softc *sc = v;
    993   1.1     bjh21 	u_char cmd[2];
    994   1.1     bjh21 
    995   1.1     bjh21 	cmd[0] = KBC_MODEIND;
    996   1.1     bjh21 	cmd[1] = pckbd_led_encode(leds);
    997   1.1     bjh21 	sc->sc_ledstate = cmd[1];
    998   1.1     bjh21 
    999   1.2     bjh21 	(void)pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
   1000  1.38  christos 	    cmd, 2, 0, 0, 0);
   1001   1.1     bjh21 }
   1002   1.1     bjh21 
   1003   1.1     bjh21 /*
   1004   1.1     bjh21  * Got a console receive interrupt -
   1005   1.1     bjh21  * the console processor wants to give us a character.
   1006   1.1     bjh21  */
   1007   1.1     bjh21 void
   1008   1.2     bjh21 pckbd_input(void *vsc, int data)
   1009   1.1     bjh21 {
   1010   1.1     bjh21 	struct pckbd_softc *sc = vsc;
   1011   1.1     bjh21 	int key;
   1012   1.1     bjh21 	u_int type;
   1013   1.1     bjh21 
   1014  1.30       jdc 	data = pckbd_scancode_translate(sc->id, data);
   1015  1.30       jdc 	if (data == 0)
   1016  1.30       jdc 		return;
   1017  1.30       jdc 
   1018   1.1     bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
   1019   1.1     bjh21 	if (sc->rawkbd) {
   1020   1.1     bjh21 		u_char d = data;
   1021   1.1     bjh21 		wskbd_rawinput(sc->sc_wskbddev, &d, 1);
   1022   1.1     bjh21 		return;
   1023   1.1     bjh21 	}
   1024   1.1     bjh21 #endif
   1025   1.1     bjh21 	if (pckbd_decode(sc->id, data, &type, &key))
   1026   1.1     bjh21 		wskbd_input(sc->sc_wskbddev, type, key);
   1027   1.1     bjh21 }
   1028   1.1     bjh21 
   1029   1.1     bjh21 int
   1030  1.38  christos pckbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
   1031   1.1     bjh21 {
   1032   1.1     bjh21 	struct pckbd_softc *sc = v;
   1033  1.38  christos 	u_char cmdb[2];
   1034   1.1     bjh21 
   1035   1.1     bjh21 	switch (cmd) {
   1036   1.2     bjh21 	case WSKBDIO_GTYPE:
   1037   1.1     bjh21 		*(int *)data = WSKBD_TYPE_PC_XT;
   1038   1.1     bjh21 		return 0;
   1039   1.2     bjh21 	case WSKBDIO_SETLEDS:
   1040   1.8  christos 		cmdb[0] = KBC_MODEIND;
   1041   1.8  christos 		cmdb[1] = pckbd_led_encode(*(int *)data);
   1042   1.8  christos 		sc->sc_ledstate = cmdb[1];
   1043  1.38  christos 		return pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
   1044  1.38  christos 		    cmdb, 2, 0, 1, 0);
   1045   1.2     bjh21 	case WSKBDIO_GETLEDS:
   1046   1.1     bjh21 		*(int *)data = pckbd_led_decode(sc->sc_ledstate);
   1047   1.2     bjh21 		return 0;
   1048  1.33       nat #if 0
   1049   1.2     bjh21 	case WSKBDIO_COMPLEXBELL:
   1050   1.1     bjh21 #define d ((struct wskbd_bell_data *)data)
   1051   1.1     bjh21 		/*
   1052   1.1     bjh21 		 * Keyboard can't beep directly; we have an
   1053   1.1     bjh21 		 * externally-provided global hook to do this.
   1054   1.1     bjh21 		 */
   1055   1.1     bjh21 		pckbd_bell(d->pitch, d->period, d->volume, 0);
   1056   1.1     bjh21 #undef d
   1057   1.2     bjh21 		return 0;
   1058  1.33       nat #endif
   1059   1.1     bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
   1060   1.2     bjh21 	case WSKBDIO_SETMODE:
   1061   1.1     bjh21 		sc->rawkbd = (*(int *)data == WSKBD_RAW);
   1062   1.2     bjh21 		return 0;
   1063   1.1     bjh21 #endif
   1064   1.1     bjh21 	}
   1065   1.1     bjh21 	return EPASSTHROUGH;
   1066   1.1     bjh21 }
   1067   1.1     bjh21 
   1068   1.1     bjh21 void
   1069   1.2     bjh21 pckbd_bell(u_int pitch, u_int period, u_int volume, int poll)
   1070   1.1     bjh21 {
   1071   1.1     bjh21 
   1072   1.1     bjh21 	if (pckbd_bell_fn != NULL)
   1073   1.1     bjh21 		(*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period,
   1074   1.1     bjh21 		    volume, poll);
   1075   1.1     bjh21 }
   1076   1.1     bjh21 
   1077   1.1     bjh21 void
   1078  1.19    dyoung pckbd_unhook_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
   1079  1.19    dyoung {
   1080  1.19    dyoung 	if (pckbd_bell_fn != fn && pckbd_bell_fn_arg != arg)
   1081  1.19    dyoung 		return;
   1082  1.19    dyoung 	pckbd_bell_fn = NULL;
   1083  1.19    dyoung 	pckbd_bell_fn_arg = NULL;
   1084  1.19    dyoung }
   1085  1.19    dyoung 
   1086  1.19    dyoung void
   1087   1.2     bjh21 pckbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
   1088   1.1     bjh21 {
   1089   1.1     bjh21 
   1090   1.1     bjh21 	if (pckbd_bell_fn == NULL) {
   1091   1.1     bjh21 		pckbd_bell_fn = fn;
   1092   1.1     bjh21 		pckbd_bell_fn_arg = arg;
   1093   1.1     bjh21 	}
   1094   1.1     bjh21 }
   1095   1.1     bjh21 
   1096   1.1     bjh21 int
   1097   1.2     bjh21 pckbd_cnattach(pckbport_tag_t kbctag, int kbcslot)
   1098   1.1     bjh21 {
   1099   1.2     bjh21 	int res;
   1100   1.1     bjh21 	u_char cmd[1];
   1101   1.1     bjh21 
   1102   1.1     bjh21 	res = pckbd_init(&pckbd_consdata, kbctag, kbcslot, 1);
   1103   1.7  augustss 	/* We may allow the console to be attached if no keyboard is present */
   1104   1.7  augustss #if defined(PCKBD_CNATTACH_MAY_FAIL)
   1105   1.1     bjh21 	if (res)
   1106   1.2     bjh21 		return res;
   1107   1.1     bjh21 #endif
   1108   1.1     bjh21 
   1109   1.1     bjh21 	/* Just to be sure. */
   1110   1.1     bjh21 	cmd[0] = KBC_ENABLE;
   1111   1.1     bjh21 	res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 1, 0, 0, 0);
   1112   1.1     bjh21 
   1113   1.7  augustss #if defined(PCKBD_CNATTACH_MAY_FAIL)
   1114   1.1     bjh21 	if (res)
   1115   1.2     bjh21 		return res;
   1116   1.1     bjh21 #endif
   1117   1.1     bjh21 
   1118   1.1     bjh21 	wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata);
   1119   1.1     bjh21 
   1120  1.31    martin 	return res;
   1121   1.1     bjh21 }
   1122   1.1     bjh21 
   1123   1.1     bjh21 /* ARGSUSED */
   1124   1.1     bjh21 void
   1125   1.2     bjh21 pckbd_cngetc(void *v, u_int *type, int *data)
   1126   1.1     bjh21 {
   1127   1.1     bjh21         struct pckbd_internal *t = v;
   1128   1.1     bjh21 	int val;
   1129   1.1     bjh21 
   1130   1.1     bjh21 	for (;;) {
   1131   1.1     bjh21 		val = pckbport_poll_data(t->t_kbctag, t->t_kbcslot);
   1132  1.34  jmcneill 		if (val == -1) {
   1133  1.34  jmcneill 			*type = 0;
   1134  1.34  jmcneill 			*data = 0;
   1135  1.34  jmcneill 			return;
   1136  1.34  jmcneill 		}
   1137  1.30       jdc 
   1138  1.30       jdc 		val = pckbd_scancode_translate(t, val);
   1139  1.30       jdc 		if (val == 0)
   1140  1.30       jdc 			continue;
   1141  1.30       jdc 
   1142  1.30       jdc 		if (pckbd_decode(t, val, type, data))
   1143   1.1     bjh21 			return;
   1144   1.1     bjh21 	}
   1145   1.1     bjh21 }
   1146   1.1     bjh21 
   1147   1.1     bjh21 void
   1148   1.2     bjh21 pckbd_cnpollc(void *v, int on)
   1149   1.1     bjh21 {
   1150   1.1     bjh21 	struct pckbd_internal *t = v;
   1151   1.1     bjh21 
   1152   1.1     bjh21 	pckbport_set_poll(t->t_kbctag, t->t_kbcslot, on);
   1153   1.1     bjh21 }
   1154   1.1     bjh21 
   1155   1.1     bjh21 void
   1156  1.14  christos pckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
   1157   1.1     bjh21 {
   1158   1.1     bjh21 
   1159   1.1     bjh21 	pckbd_bell(pitch, period, volume, 1);
   1160   1.1     bjh21 }
   1161