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