summaryrefslogtreecommitdiff
path: root/chips/lk201.c
diff options
context:
space:
mode:
Diffstat (limited to 'chips/lk201.c')
-rw-r--r--chips/lk201.c695
1 files changed, 695 insertions, 0 deletions
diff --git a/chips/lk201.c b/chips/lk201.c
new file mode 100644
index 0000000..d11b1e9
--- /dev/null
+++ b/chips/lk201.c
@@ -0,0 +1,695 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: lk201.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Routines for the LK201 Keyboard Driver
+ */
+
+#include <lk.h>
+#if NLK > 0
+#include <bm.h>
+
+#include <mach_kdb.h>
+
+#include <mach/std_types.h>
+#include <device/device_types.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <sys/ioctl.h>
+#include <machine/machspl.h>
+#include <chips/lk201.h>
+#include <chips/serial_defs.h>
+#include <chips/screen_defs.h>
+
+
+/*
+ * Structures describing the keyboard status
+ */
+typedef struct {
+ unsigned short kbd_flags;
+ unsigned short kbd_previous;
+ char kbd_gen_shift;
+ char kbd_ctrl;
+ char kbd_lock;
+ char kbd_meta;
+ char kbd_shift;
+} lk201_kbd_state_t;
+
+#define mapLOCKtoCNTRL 0x1 /* flags */
+
+typedef struct {
+ char led_active;
+ char led_pattern;
+ char led_increasing;
+ char led_lights;
+ int led_interval;
+ int led_light_count;
+} lk201_led_state_t;
+
+
+/*
+ * Keyboard state
+ */
+
+struct lk201_softc {
+ lk201_kbd_state_t kbd;
+ lk201_led_state_t led;
+ int sl_unit;
+} lk201_softc_data[NLK];
+
+typedef struct lk201_softc *lk201_softc_t;
+
+lk201_softc_t lk201_softc[NLK];
+
+/*
+ * Forward decls
+ */
+io_return_t
+lk201_translation(
+ int key,
+ char c,
+ int tabcode );
+
+int
+lk201_input(
+ int unit,
+ unsigned short data);
+
+
+/*
+ * Autoconf (sort-of)
+ */
+lk201_probe(
+ int unit)
+{
+ lk201_softc[unit] = &lk201_softc_data[unit];
+ return 1;
+}
+
+void lk201_attach(
+ int unit,
+ int sl_unit)
+{
+ lk201_softc[unit]->sl_unit = sl_unit;
+ lk201_selftest(unit);
+}
+
+/*
+ * Keyboard initialization
+ */
+
+static unsigned char lk201_reset_string[] = {
+ LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */
+ LK_CMD_SET_DEFAULTS,
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,1),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,2),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,3),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,4),
+ LK_CMD_MODE(LK_MODE_DOWN_UP,5),
+ LK_CMD_MODE(LK_MODE_DOWN_UP,6),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,7),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,8),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,9),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,10),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,11),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,12),
+ LK_CMD_MODE(LK_MODE_DOWN,13),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,14),
+ LK_CMD_ENB_RPT,
+/* LK_CMD_ENB_KEYCLK, LK_PARAM_VOLUME(4), */
+ LK_CMD_DIS_KEYCLK,
+ LK_CMD_RESUME,
+ LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
+ LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf)
+};
+
+void
+lk201_reset(
+ int unit)
+{
+ register int i, sl;
+ register spl_t s;
+ lk201_softc_t lk;
+
+ lk = lk201_softc[unit];
+ sl = lk->sl_unit;
+ s = spltty();
+ for (i = 0; i < sizeof(lk201_reset_string); i++) {
+ (*console_putc)(sl,
+ SCREEN_LINE_KEYBOARD,
+ lk201_reset_string[i]);
+ delay(100);
+ }
+ /* zero any state associated with previous keypresses */
+ bzero(lk, sizeof(*lk));
+ lk->sl_unit = sl;
+ splx(s);
+}
+
+lk201_selftest(
+ int unit)
+{
+ int messg[4], sl;
+ spl_t s;
+
+ sl = lk201_softc[unit]->sl_unit;
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_REQ_ID);
+ delay(10000);/* arbitrary */
+ messg[0] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[1] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ splx(s);
+
+ printf("( lk201 id %x.%x", messg[0], messg[1]);
+
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_POWER_UP);
+
+ /* cannot do this, waiting too long might cause receiver overruns */
+/* delay(80000);/* spec says 70 msecs or less */
+
+ messg[0] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[1] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[2] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[3] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ splx(s);
+
+ printf(", self-test ");
+ if (messg[0] != 0x01 || messg[1] || messg[2] || messg[3])
+ printf("bad [%x %x %x %x]",
+ messg[0], messg[1], messg[2], messg[3]);
+ else
+ printf("ok )");
+
+ lk201_reset(unit);
+}
+
+/*
+ * Tinkerbell
+ */
+void
+lk201_ring_bell(
+ int unit)
+{
+ spl_t s = spltty();
+ (*console_putc)(lk201_softc[unit]->sl_unit, SCREEN_LINE_KEYBOARD, LK_CMD_BELL);
+ splx(s);
+}
+
+/*
+ * Here is your LED toy, Bob
+ */
+void
+lk201_lights(
+ int unit,
+ boolean_t on)
+{
+ unsigned int sl;
+ spl_t s;
+
+ sl = lk201_softc[unit]->sl_unit;
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0xf));
+ if (on < 16 && on > 0) {
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(on));
+ }
+ splx(s);
+}
+
+
+lk201_led(
+ int unit)
+{
+ lk201_led_state_t *leds = &lk201_softc[unit]->led;
+ unsigned int sl;
+ spl_t s;
+
+ sl = lk201_softc[unit]->sl_unit;
+ if (leds->led_interval) { /* leds are on */
+ if (leds->led_light_count <= 0) { /* hit this lights */
+
+ if (leds->led_lights <= 0) leds->led_lights= 1; /* sanity */
+ if (leds->led_lights > 16) leds->led_lights = 16;/* sanity */
+ leds->led_light_count = leds->led_interval; /* reset */
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(leds->led_lights));
+ switch (leds->led_pattern) {
+ case LED_OFF:
+ leds->led_interval = 0; /* since you can now set */
+ break; /* the interval even if off */
+ case LED_COUNT:
+ leds->led_lights++;
+ if (leds->led_lights > 16) leds->led_lights = 1;
+ break;
+ case LED_ROTATE:
+ leds->led_lights <<= 1;
+ if (leds->led_lights > 8) leds->led_lights = 1;
+ break;
+ case LED_CYLON:
+ if (leds->led_increasing) {
+ leds->led_lights <<= 1;
+ if (leds->led_lights > 8) {
+ leds->led_lights >>= 2;
+ leds->led_increasing = 0;
+ }
+ } else {
+ leds->led_lights >>= 1;
+ if (leds->led_lights <= 0) {
+ leds->led_lights = 2;
+ leds->led_increasing = 1;
+ }
+ }
+ break;
+ }
+ (*console_putc)( sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON);
+ (*console_putc)( sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(leds->led_lights));
+ splx(s);
+ }
+ leds->led_light_count--;
+ } else {
+ if (leds->led_lights) {
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0xf));
+ leds->led_lights = 0;
+ splx(s);
+ }
+ leds->led_active = 0;
+#if NBM > 0
+ screen_enable_vretrace(unit, 0); /* interrupts off */
+#endif
+ }
+}
+
+
+/*
+ * Special user-visible ops
+ */
+io_return_t
+lk201_set_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ lk201_led_state_t *leds = &lk201_softc[unit]->led;
+ lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd;
+
+ switch( flavor ) {
+ case LK201_SEND_CMD:{
+ register lk201_cmd_t *cmd = (lk201_cmd_t*)status;
+ unsigned int cnt, s, sl;
+
+ if ((status_count < (sizeof(*cmd)/sizeof(int))) ||
+ ((cnt = cmd->len) > 2))
+ return D_INVALID_SIZE;
+
+ if (cnt == 0)
+ cmd->command |= LK_PARAM;
+ else
+ cmd->params[cnt-1] |= LK_PARAM;
+ sl = lk201_softc[unit]->sl_unit;
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->command);
+ if (cnt > 0)
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->params[0]);
+ if (cnt > 1)
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->params[1]);
+ splx(s);
+ return D_SUCCESS;
+ }
+ case LK201_LED_PATTERN:{
+ register int ptn = * (int *) status;
+ if (ptn != LED_OFF && ptn != LED_COUNT &&
+ ptn != LED_ROTATE && ptn != LED_CYLON ) {
+ return -1;
+ } else {
+ leds->led_pattern = ptn;
+ }
+ break;
+ }
+ case LK201_LED_INTERVAL:{
+ register int lcnt = * (int *) status;
+ if (lcnt < 0)
+ lcnt = 1;
+ leds->led_interval = lcnt;
+ break;
+ }
+ case LK201_mapLOCKtoCNTRL:{
+ boolean_t enable = * (boolean_t*) status;
+ if (enable)
+ kbd->kbd_flags |= mapLOCKtoCNTRL;
+ else
+ kbd->kbd_flags &= ~mapLOCKtoCNTRL;
+ return D_SUCCESS;
+ }
+ case LK201_REMAP_KEY:{
+ register KeyMap *k = (KeyMap *) status;
+ int mode;
+
+ if (status_count < (sizeof(KeyMap)/sizeof(int)))
+ return D_INVALID_SIZE;
+
+ mode = k->shifted ? 1 : 0;
+ if (k->meta) mode += 2;
+ return lk201_translation( k->in_keyval,
+ k->out_keyval,
+ mode );
+ }
+ default:
+ return D_INVALID_OPERATION;
+ }
+ leds->led_lights = 1;
+ leds->led_active = 1;
+#if NBM > 0
+ screen_enable_vretrace(unit, 1); /* interrupts on */
+#endif
+ return D_SUCCESS;
+}
+
+/*
+ * Keycode translation tables
+ *
+ * NOTE: these tables have been compressed a little bit
+ * because the lk201 cannot generate very small codes.
+ */
+
+unsigned char lk201_xlate_key[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f,'\r','\t','`'
+ /* 192 */ ,'1' ,'q' ,'a' ,'z' ,0 ,'2' ,'w' ,'s'
+ /* 200 */ ,'x' ,'<' ,0 ,'3' ,'e' ,'d' ,'c' ,0
+ /* 208 */ ,'4' ,'r' ,'f' ,'v' ,' ' ,0 ,'5' ,'t'
+ /* 216 */ ,'g' ,'b' ,0 ,'6' ,'y' ,'h' ,'n' ,0
+ /* 224 */ ,'7' ,'u' ,'j' ,'m' ,0 ,'8' ,'i' ,'k'
+ /* 232 */ ,',' ,0 ,'9' ,'o' ,'l' ,'.' ,0 ,'0'
+ /* 240 */ ,'p' ,0 ,';' ,'/' ,0 ,'=' ,']' ,'\\'
+ /* 248 */ ,0 ,'-' ,'[' ,'\'' ,0 ,0 ,0 ,0
+};
+
+unsigned char lk201_xlate_shifted[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~'
+ /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S'
+ /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0
+ /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T'
+ /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0
+ /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K'
+ /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')'
+ /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|'
+ /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0
+};
+
+unsigned char lk201_xlate_meta[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~'
+ /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S'
+ /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0
+ /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T'
+ /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0
+ /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K'
+ /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')'
+ /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|'
+ /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0
+};
+
+unsigned char lk201_xlate_shifted_meta[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~'
+ /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S'
+ /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0
+ /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T'
+ /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0
+ /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K'
+ /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')'
+ /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|'
+ /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0
+};
+
+
+io_return_t
+lk201_translation(
+ int key,
+ char c,
+ int tabcode )
+{
+ unsigned char *table;
+
+ if ((key &= 0xff) < LK_MINCODE)
+ return D_INVALID_OPERATION;
+
+ switch (tabcode) {
+ case 3:
+ table = lk201_xlate_shifted_meta;
+ break;
+ case 2:
+ table = lk201_xlate_meta;
+ break;
+ case 1:
+ table = lk201_xlate_shifted;
+ break;
+ case 0:
+ default:
+ table = lk201_xlate_key;
+ break;
+ }
+ table[key - LK_MINCODE] = c;
+ return D_SUCCESS;
+}
+
+/*
+ * Input character processing
+ */
+
+lk201_rint(
+ int unit,
+ unsigned short data,
+ boolean_t handle_shift,
+ boolean_t from_kernel)
+{
+ int c;
+ lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd;
+
+ /*
+ * Keyboard touched, clean char to 8 bits.
+ */
+#if NBM > 0
+ ssaver_bump(unit);
+#endif
+
+ data &= 0xff;
+
+ /* Translate keycode into ASCII */
+ if ((c = lk201_input(unit, data)) == -1)
+ return -1;
+
+#if NBM > 0
+ /*
+ * Notify X, unless we are called from inside kernel
+ */
+ if (!from_kernel &&
+ screen_keypress_event(unit, DEV_KEYBD, data, EVT_BUTTON_RAW))
+ return -1;
+#endif
+
+ /* Handle shifting if need to */
+ if (kbd->kbd_gen_shift)
+ return (handle_shift) ? cngetc() : -1;
+
+ return c;
+}
+
+/*
+ * Routine to grock a character from LK201
+ */
+#if MACH_KDB
+int lk201_allow_kdb = 1;
+#endif
+
+int lk201_debug = 0;
+
+lk201_input(
+ int unit,
+ unsigned short data)
+{
+ int c, sl;
+ lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd;
+
+ kbd->kbd_gen_shift = 0;
+
+#if MACH_KDB
+ if (lk201_allow_kdb && (data == LK_DO)) {
+ kdb_kintr();
+ return -2;
+ }
+#endif
+
+ /*
+ * Sanity checks
+ */
+
+ if (data == LK_INPUT_ERR || data == LK_OUTPUT_ERR) {
+ printf(" Keyboard error, code = %x\n",data);
+ return -1;
+ }
+ if (data < LK_MINCODE)
+ return -1;
+
+ /*
+ * Check special keys: shifts, ups, ..
+ */
+
+ if (data == LK_LOCK && (kbd->kbd_flags&mapLOCKtoCNTRL))
+ data = LK_CNTRL;
+
+ switch (data) {
+ case LK_LOCK:
+ kbd->kbd_lock ^= 1;
+ kbd->kbd_gen_shift = 1;
+ sl = lk201_softc[unit]->sl_unit;
+ /* called from interrupt, no need for spl */
+ if (kbd->kbd_lock)
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON);
+ else
+ (*console_putc)(sl,SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0x4));
+ return 0;
+
+ case LK_ALT:
+ case LK_L_ALT:
+ case LK_R_ALT:
+ case LK_R_COMPOSE:
+ kbd->kbd_meta ^= 1;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_SHIFT:
+ case LK_R_SHIFT:
+ kbd->kbd_shift ^= 1;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_CNTRL:
+ kbd->kbd_ctrl ^= 1;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_ALLUP:
+ kbd->kbd_ctrl = 0;
+ kbd->kbd_shift = 0;
+ kbd->kbd_meta = 0;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_REPEAT:
+ c = kbd->kbd_previous;
+ break;
+
+ default:
+
+ /*
+ * Do the key translation to ASCII
+ */
+ if (kbd->kbd_ctrl || kbd->kbd_lock || kbd->kbd_shift) {
+ c = ((kbd->kbd_meta) ?
+ lk201_xlate_shifted_meta : lk201_xlate_shifted)
+ [data - LK_MINCODE];
+ if (kbd->kbd_ctrl)
+ c &= 0x1f;
+ } else
+ c = ((kbd->kbd_meta) ?
+ lk201_xlate_meta : lk201_xlate_key)
+ [data-LK_MINCODE];
+ break;
+
+ }
+
+ kbd->kbd_previous = c;
+
+ /*
+ * DEBUG code DEBUG
+ */
+ if (lk201_debug && (c == 0)) {
+ printf("lk201: [%x]\n", data);
+ }
+
+ return c;
+}
+
+#endif /* NLK > 0 */