Module Name: src
Committed By: jdc
Date: Sat Oct 13 17:51:28 UTC 2012
Modified Files:
src/sys/dev/ic: pckbc.c
src/sys/dev/pckbport: pckbd.c
Log Message:
Add two flags to keyboard/mouse attachment:
PCKBC_CANT_TRANSLATE for keyboards that cannot translate to XT scancodes
PCKBC_NEED_AUXWRITE for mice that don't probe first time
These flags can be set by the port-specific attachments.
Add the translation table and function to handle set 2 to set 1 keyboard
translation in software.
Based on OpenBSD sys/dev/ic/pckbc.c revisions 1.10, 1.16, 1.17, and
sys/dev/pckbc/pckbd.c revision 1.15, and 8042 scan code information at:
http://www.computer-engineering.org/ps2keyboard/
Note, that this changes the signature of pckbc_cnattach(), so ride the
kernel version bump for namei.
To generate a diff of this commit:
cvs rdiff -u -r1.53 -r1.54 src/sys/dev/ic/pckbc.c
cvs rdiff -u -r1.29 -r1.30 src/sys/dev/pckbport/pckbd.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/pckbc.c
diff -u src/sys/dev/ic/pckbc.c:1.53 src/sys/dev/ic/pckbc.c:1.54
--- src/sys/dev/ic/pckbc.c:1.53 Thu Feb 2 19:43:03 2012
+++ src/sys/dev/ic/pckbc.c Sat Oct 13 17:51:28 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pckbc.c,v 1.53 2012/02/02 19:43:03 tls Exp $ */
+/* $NetBSD: pckbc.c,v 1.54 2012/10/13 17:51:28 jdc Exp $ */
/*
* Copyright (c) 2004 Ben Harris.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pckbc.c,v 1.53 2012/02/02 19:43:03 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pckbc.c,v 1.54 2012/10/13 17:51:28 jdc Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -354,6 +354,20 @@ pckbc_attach(struct pckbc_softc *sc)
t->t_haveaux = 1;
bus_space_write_1(iot, ioh_d, 0, 0x5a); /* a random value */
res = pckbc_poll_data1(t, PCKBC_AUX_SLOT);
+
+ /*
+ * The following is needed to find the aux port on the Tadpole
+ * SPARCle.
+ */
+ if (res == -1 && ISSET(t->t_flags, PCKBC_NEED_AUXWRITE)) {
+ /* Read of aux echo timed out, try again */
+ if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE))
+ goto nomouse;
+ if (!pckbc_wait_output(iot, ioh_c))
+ goto nomouse;
+ bus_space_write_1(iot, ioh_d, 0, 0x5a);
+ res = pckbc_poll_data1(t, PCKBC_AUX_SLOT);
+ }
if (res != -1) {
/*
* In most cases, the 0x5a gets echoed.
@@ -365,6 +379,7 @@ pckbc_attach(struct pckbc_softc *sc)
if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT))
cmdbits |= KC8_MENABLE;
} else {
+
#ifdef PCKBCDEBUG
printf("pckbc: aux echo test failed\n");
#endif
@@ -395,6 +410,9 @@ pckbc_xt_translation(void *self, pckbc_s
struct pckbc_internal *t = self;
int ison;
+ if (ISSET(t->t_flags, PCKBC_CANT_TRANSLATE))
+ return (-1);
+
if (slot != PCKBC_KBD_SLOT) {
/* translation only for kbd slot */
if (on)
@@ -602,7 +620,7 @@ pckbcintr(void *vsc)
int
pckbc_cnattach(bus_space_tag_t iot, bus_addr_t addr,
- bus_size_t cmd_offset, pckbc_slot_t slot)
+ bus_size_t cmd_offset, pckbc_slot_t slot, int flags)
{
bus_space_handle_t ioh_d, ioh_c;
#ifdef PCKBC_CNATTACH_SELFTEST
@@ -622,6 +640,7 @@ pckbc_cnattach(bus_space_tag_t iot, bus_
pckbc_consdata.t_ioh_d = ioh_d;
pckbc_consdata.t_ioh_c = ioh_c;
pckbc_consdata.t_addr = addr;
+ pckbc_consdata.t_flags = flags;
callout_init(&pckbc_consdata.t_cleanup, 0);
/* flush */
Index: src/sys/dev/pckbport/pckbd.c
diff -u src/sys/dev/pckbport/pckbd.c:1.29 src/sys/dev/pckbport/pckbd.c:1.30
--- src/sys/dev/pckbport/pckbd.c:1.29 Wed Feb 24 22:38:08 2010
+++ src/sys/dev/pckbport/pckbd.c Sat Oct 13 17:51:28 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pckbd.c,v 1.29 2010/02/24 22:38:08 dyoung Exp $ */
+/* $NetBSD: pckbd.c,v 1.30 2012/10/13 17:51:28 jdc Exp $ */
/*-
* Copyright (c) 1998, 2009 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.29 2010/02/24 22:38:08 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.30 2012/10/13 17:51:28 jdc Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -100,9 +100,12 @@ struct pckbd_internal {
pckbport_tag_t t_kbctag;
pckbport_slot_t t_kbcslot;
+ int t_translating;
+
int t_lastchar;
int t_extended0;
int t_extended1;
+ int t_releasing;
struct pckbd_softc *t_sc; /* back pointer */
};
@@ -167,7 +170,9 @@ void *pckbd_bell_fn_arg;
void pckbd_bell(u_int, u_int, u_int, int);
-int pckbd_set_xtscancode(pckbport_tag_t, pckbport_slot_t);
+int pckbd_scancode_translate(struct pckbd_internal *, int);
+int pckbd_set_xtscancode(pckbport_tag_t, pckbport_slot_t,
+ struct pckbd_internal *);
int pckbd_init(struct pckbd_internal *, pckbport_tag_t, pckbport_slot_t,
int);
void pckbd_input(void *, int);
@@ -179,9 +184,10 @@ static int pckbd_led_decode(int);
struct pckbd_internal pckbd_consdata;
int
-pckbd_set_xtscancode(pckbport_tag_t kbctag, pckbport_slot_t kbcslot)
+pckbd_set_xtscancode(pckbport_tag_t kbctag, pckbport_slot_t kbcslot,
+ struct pckbd_internal *id)
{
- int res;
+ int xt, res = 0;
u_char cmd[2];
/*
@@ -192,12 +198,14 @@ pckbd_set_xtscancode(pckbport_tag_t kbct
* known to not work on some PS/2 machines. We try desperately to deal
* with this by checking the (lack of a) translate bit in the 8042 and
* attempting to set the keyboard to XT mode. If this all fails, well,
- * tough luck.
+ * tough luck. If the PCKBC_CANT_TRANSLATE pckbc flag was set, we
+ * enable software translation.
*
* XXX It would perhaps be a better choice to just use AT scan codes
* and not bother with this.
*/
- if (pckbport_xt_translation(kbctag, kbcslot, 1)) {
+ xt = pckbport_xt_translation(kbctag, kbcslot, 1);
+ if (xt == 1) {
/* The 8042 is translating for us; use AT codes. */
cmd[0] = KBC_SETTABLE;
cmd[1] = 2;
@@ -216,6 +224,12 @@ pckbd_set_xtscancode(pckbport_tag_t kbct
pckbport_flush(kbctag, kbcslot);
res = 0;
}
+ if (id != NULL)
+ id->t_translating = 1;
+ } else if (xt == -1) {
+ /* Software translation required */
+ if (id != NULL)
+ id->t_translating = 0;
} else {
/* Stupid 8042; set keyboard to XT codes. */
cmd[0] = KBC_SETTABLE;
@@ -223,6 +237,8 @@ pckbd_set_xtscancode(pckbport_tag_t kbct
res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
if (res)
aprint_debug("pckbd: error setting scanset 1\n");
+ if (id != NULL)
+ id->t_translating = 1;
}
return res;
}
@@ -331,7 +347,7 @@ pckbdprobe(device_t parent, cfdata_t cf,
*/
pckbport_flush(pa->pa_tag, pa->pa_slot);
- if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot))
+ if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
return 0;
return 2;
@@ -421,7 +437,7 @@ pckbd_enable(void *v, int on)
}
res = pckbd_set_xtscancode(sc->id->t_kbctag,
- sc->id->t_kbcslot);
+ sc->id->t_kbcslot, sc->id);
if (res)
return res;
@@ -446,21 +462,395 @@ pckbd_enable(void *v, int on)
return 0;
}
+const u_int8_t pckbd_xtbl[] = {
+/* 0x00 */
+ 0,
+ 0x43, /* F9 */
+ 0x89, /* SunStop */
+ 0x3f, /* F5 */
+ 0x3d, /* F3 */
+ 0x3b, /* F1 */
+ 0x3c, /* F2 */
+ 0x58, /* F12 */
+ 0,
+ 0x44, /* F10 */
+ 0x42, /* F8 */
+ 0x40, /* F6 */
+ 0x3e, /* F4 */
+ 0x0f, /* Tab */
+ 0x29, /* ` ~ */
+ 0,
+/* 0x10 */
+ 0,
+ 0x38, /* Left Alt */
+ 0x2a, /* Left Shift */
+ 0,
+ 0x1d, /* Left Ctrl */
+ 0x10, /* q */
+ 0x02, /* 1 ! */
+ 0,
+ 0,
+ 0,
+ 0x2c, /* z */
+ 0x1f, /* s */
+ 0x1e, /* a */
+ 0x11, /* w */
+ 0x03, /* 2 @ */
+ 0,
+/* 0x20 */
+ 0,
+ 0x2e, /* c */
+ 0x2d, /* x */
+ 0x20, /* d */
+ 0x12, /* e */
+ 0x05, /* 4 $ */
+ 0x04, /* 3 # */
+ 0,
+ 0,
+ 0x39, /* Space */
+ 0x2f, /* v */
+ 0x21, /* f */
+ 0x14, /* t */
+ 0x13, /* r */
+ 0x06, /* 5 % */
+ 0,
+/* 0x30 */
+ 0,
+ 0x31, /* n */
+ 0x30, /* b */
+ 0x23, /* h */
+ 0x22, /* g */
+ 0x15, /* y */
+ 0x07, /* 6 ^ */
+ 0,
+ 0,
+ 0,
+ 0x32, /* m */
+ 0x24, /* j */
+ 0x16, /* u */
+ 0x08, /* 7 & */
+ 0x09, /* 8 * */
+ 0,
+/* 0x40 */
+ 0,
+ 0x33, /* , < */
+ 0x25, /* k */
+ 0x17, /* i */
+ 0x18, /* o */
+ 0x0b, /* 0 ) */
+ 0x0a, /* 9 ( */
+ 0,
+ 0,
+ 0x34, /* . > */
+ 0x35, /* / ? */
+ 0x26, /* l */
+ 0x27, /* ; : */
+ 0x19, /* p */
+ 0x0c, /* - _ */
+ 0,
+/* 0x50 */
+ 0,
+ 0,
+ 0x28, /* ' " */
+ 0,
+ 0x1a, /* [ { */
+ 0x0d, /* = + */
+ 0,
+ 0,
+ 0x3a, /* Caps Lock */
+ 0x36, /* Right Shift */
+ 0x1c, /* Return */
+ 0x1b, /* ] } */
+ 0,
+ 0x2b, /* \ | */
+ 0,
+ 0,
+/* 0x60 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x0e, /* Back Space */
+ 0,
+ 0,
+ 0x4f, /* KP 1 */
+ 0,
+ 0x4b, /* KP 4 */
+ 0x47, /* KP 7 */
+ 0,
+ 0,
+ 0,
+/* 0x70 */
+ 0x52, /* KP 0 */
+ 0x53, /* KP . */
+ 0x50, /* KP 2 */
+ 0x4c, /* KP 5 */
+ 0x4d, /* KP 6 */
+ 0x48, /* KP 8 */
+ 0x01, /* Escape */
+ 0x45, /* Num Lock */
+ 0x57, /* F11 */
+ 0x4e, /* KP + */
+ 0x51, /* KP 3 */
+ 0x4a, /* KP - */
+ 0x37, /* KP * */
+ 0x49, /* KP 9 */
+ 0x46, /* Scroll Lock */
+ 0,
+/* 0x80 */
+ 0,
+ 0,
+ 0,
+ 0x41, /* F7 (produced as an actual 8 bit code) */
+ 0, /* Alt-Print Screen */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/* 0x90 */
+ 0xdb, /* Left Meta */
+ 0x88, /* SunHelp */
+ 0x8a, /* SunAgain */
+ 0x8c, /* SunUndo */
+ 0x8e, /* SunCopy */
+ 0x90, /* SunPaste */
+ 0x92, /* SunCut */
+ 0x8b, /* SunProps */
+ 0x8d, /* SunFront */
+ 0x8f, /* SunOpen */
+ 0x91 /* SunFind */
+};
+
+const u_int8_t pckbd_xtbl_ext[] = {
+/* 0x00 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/* 0x10 */
+ 0,
+ 0x38, /* Right Alt */
+ 0, /* E0 12, to be ignored */
+ 0,
+ 0x1d, /* Right Ctrl */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/* 0x20 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0xdd, /* Compose */
+/* 0x30 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/* 0x40 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0xb5, /* KP / */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/* 0x50 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x1c, /* KP Return */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/* 0x60 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x4f, /* End */
+ 0,
+ 0x4b, /* Left */
+ 0x47, /* Home */
+ 0,
+ 0,
+ 0,
+/* 0x70 */
+ 0x52, /* Insert */
+ 0x53, /* Delete */
+ 0x50, /* Down */
+ 0,
+ 0x4d, /* Right */
+ 0x48, /* Up */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x51, /* Page Down */
+ 0,
+ 0x37, /* Print Screen */
+ 0x49, /* Page Up */
+ 0x46, /* Ctrl-Break */
+ 0
+};
+
+/*
+ * Translate scan codes from set 2 to set 1
+ */
+int
+pckbd_scancode_translate(struct pckbd_internal *id, int datain)
+{
+ if (id->t_translating != 0)
+ return datain;
+
+ if (datain == KBR_BREAK) {
+ id->t_releasing = 0x80; /* next keycode is a release */
+ return 0; /* consume scancode */
+ }
+
+ /*
+ * Handle extended sequences
+ */
+ if (datain == KBR_EXTENDED0 || datain == KBR_EXTENDED1)
+ return datain;
+
+ /*
+ * Convert BREAK sequence (14 77 -> 1D 45)
+ */
+ if (id->t_extended1 == 2 && datain == 0x14)
+ return 0x1d | id->t_releasing;
+ else if (id->t_extended1 == 1 && datain == 0x77)
+ return 0x45 | id->t_releasing;
+
+ if (id->t_extended0 != 0) {
+ if (datain >= sizeof pckbd_xtbl_ext)
+ datain = 0;
+ else
+ datain = pckbd_xtbl_ext[datain];
+ } else {
+ if (datain >= sizeof pckbd_xtbl)
+ datain = 0;
+ else
+ datain = pckbd_xtbl[datain];
+ }
+
+ /*
+ * If we are mapping in the range 128-254, then make this
+ * an extended keycode, as table 1 codes are limited to
+ * the range 0-127 (the top bit is used for key up/break).
+ */
+ if (datain > 0x7f) {
+ datain &= 0x7f;
+ id->t_extended0 = 0x80;
+ }
+
+ if (datain == 0) {
+ /*
+ * We don't know how to translate this scan code, but
+ * we can't silently eat it either (because there might
+ * have been an extended byte transmitted already).
+ * Hopefully this value will be harmless to the upper
+ * layers.
+ */
+ return 0xff;
+ }
+ return datain | id->t_releasing;
+}
+
static int
pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout)
{
int key;
+ int releasing;
if (datain == KBR_EXTENDED0) {
- id->t_extended0 = 1;
+ id->t_extended0 = 0x80;
return 0;
} else if (datain == KBR_EXTENDED1) {
id->t_extended1 = 2;
return 0;
}
- if (id->t_extended0 == 1) {
- switch (datain & 0x7f) {
+ releasing = datain & 0x80;
+ datain &= 0x7f;
+
+ if (id->t_extended0 == 0x80) {
+ switch (datain) {
case 0x2a:
case 0x36:
id->t_extended0 = 0;
@@ -470,8 +860,8 @@ pckbd_decode(struct pckbd_internal *id,
}
}
- /* map extended keys to (unused) codes 128-254 */
- key = (datain & 0x7f) | (id->t_extended0 ? 0x80 : 0);
+ /* map extended keys to (unused) codes 128-254 */
+ key = datain | id->t_extended0;
id->t_extended0 = 0;
/*
@@ -489,7 +879,14 @@ pckbd_decode(struct pckbd_internal *id,
id->t_extended1 = 0;
}
- if (datain & 0x80) {
+ if (id->t_translating != 0) {
+ id->t_releasing = releasing;
+ } else {
+ /* id->t_releasing computed in pckbd_scancode_translate() */
+ }
+
+ if (id->t_releasing) {
+ id->t_releasing = 0;
id->t_lastchar = 0;
*type = WSCONS_EVENT_KEY_UP;
} else {
@@ -515,7 +912,7 @@ pckbd_init(struct pckbd_internal *t, pck
t->t_kbctag = kbctag;
t->t_kbcslot = kbcslot;
- return pckbd_set_xtscancode(kbctag, kbcslot);
+ return pckbd_set_xtscancode(kbctag, kbcslot, t);
}
static int
@@ -574,6 +971,10 @@ pckbd_input(void *vsc, int data)
int key;
u_int type;
+ data = pckbd_scancode_translate(sc->id, data);
+ if (data == 0)
+ return;
+
#ifdef WSDISPLAY_COMPAT_RAWKBD
if (sc->rawkbd) {
u_char d = data;
@@ -692,7 +1093,14 @@ pckbd_cngetc(void *v, u_int *type, int *
for (;;) {
val = pckbport_poll_data(t->t_kbctag, t->t_kbcslot);
- if ((val != -1) && pckbd_decode(t, val, type, data))
+ if (val == -1)
+ continue;
+
+ val = pckbd_scancode_translate(t, val);
+ if (val == 0)
+ continue;
+
+ if (pckbd_decode(t, val, type, data))
return;
}
}