From: Geert.Uytterhoeven@thomas.kotnet.org
Date: Tue, 20 May 1997 23:29:00 +0200 (MET DST)
To: Linux/m68k <linux-m68k@phil.uni-sb.de>
Subject: L68K: Keyboard cleanup (TNG)
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>


Here's a (hopefully) uncorrupted version of my keyboard cleanup patch.

Bonus: now it works on Linux/ix86, so a native patch will appear on
       linux-kernel soon...

--- linux-2.1.39/arch/m68k/amiga/amikeyb.c.orig	Sun May 18 23:08:51 1997
+++ linux-2.1.39/arch/m68k/amiga/amikeyb.c	Mon May 19 12:50:58 1997
@@ -29,6 +29,8 @@
 #include <asm/irq.h>
 
 extern void handle_scancode(unsigned char);
+extern unsigned int keymap_count;
+extern struct pt_regs *pt_regs;
 
 #define AMIKEY_CAPS	(0x62)
 #define BREAK_MASK	(0x80)
@@ -178,7 +180,6 @@
 static void amikeyb_rep(unsigned long ignore);
 static struct timer_list amikeyb_rep_timer = {NULL, NULL, 0, 0, amikeyb_rep};
 
-extern struct pt_regs *pt_regs;
 
 static void amikeyb_rep(unsigned long ignore)
 {
@@ -310,6 +311,7 @@
     key_maps[8]  = amialt_map;
     key_maps[12] = amictrl_alt_map;
     memcpy(plain_map, amiplain_map, sizeof(plain_map));
+    keymap_count = 7;
 
     /*
      * Initialize serial data direction.
--- linux-2.1.39/arch/m68k/kernel/Makefile.orig	Sun May 18 23:05:14 1997
+++ linux-2.1.39/arch/m68k/kernel/Makefile	Mon May 19 15:38:08 1997
@@ -23,6 +23,16 @@
 O_OBJS += kgdb.o
 endif
 
+ifdef CONFIG_AMIGA
+O_OBJS += commonkeymap.o
+endif
+ifdef CONFIG_ATARI
+O_OBJS += commonkeymap.o
+endif
+
 head.o: head.S
 
 include $(TOPDIR)/Rules.make
+
+commonkeymap.c: commonkeymap.map
+	loadkeys --mktable commonkeymap.map > commonkeymap.c
--- linux-2.1.39/arch/m68k/kernel/commonkeymap.map.orig	Mon May 19 15:26:51 1997
+++ linux-2.1.39/arch/m68k/kernel/commonkeymap.map	Mon May 19 12:58:14 1997
@@ -0,0 +1,104 @@
+# Common parts of the kernel keymap for m68k.
+#
+# It contains
+#   - one keycode, to make sure the plain_map will be generated
+#   - string definitions
+#   - compose definitions
+#
+keycode   1 = Escape
+string F1 = "\033[[A"
+string F2 = "\033[[B"
+string F3 = "\033[[C"
+string F4 = "\033[[D"
+string F5 = "\033[[E"
+string F6 = "\033[17~"
+string F7 = "\033[18~"
+string F8 = "\033[19~"
+string F9 = "\033[20~"
+string F10 = "\033[21~"
+string F11 = "\033[23~"
+string F12 = "\033[24~"
+string F13 = "\033[25~"
+string F14 = "\033[26~"
+string F15 = "\033[28~"
+string F16 = "\033[29~"
+string F17 = "\033[31~"
+string F18 = "\033[32~"
+string F19 = "\033[33~"
+string F20 = "\033[34~"
+string Find = "\033[1~"
+string Insert = "\033[2~"
+string Remove = "\033[3~"
+string Select = "\033[4~"
+string Prior = "\033[5~"
+string Next = "\033[6~"
+string Macro = "\033[M"
+string Pause = "\033[P"
+compose '`' 'A' to 'À'
+compose '`' 'a' to 'à'
+compose '\'' 'A' to 'Á'
+compose '\'' 'a' to 'á'
+compose '^' 'A' to 'Â'
+compose '^' 'a' to 'â'
+compose '~' 'A' to 'Ã'
+compose '~' 'a' to 'ã'
+compose '"' 'A' to 'Ä'
+compose '"' 'a' to 'ä'
+compose 'O' 'A' to 'Å'
+compose 'o' 'a' to 'å'
+compose '0' 'A' to 'Å'
+compose '0' 'a' to 'å'
+compose 'A' 'A' to 'Å'
+compose 'a' 'a' to 'å'
+compose 'A' 'E' to 'Æ'
+compose 'a' 'e' to 'æ'
+compose ',' 'C' to 'Ç'
+compose ',' 'c' to 'ç'
+compose '`' 'E' to 'È'
+compose '`' 'e' to 'è'
+compose '\'' 'E' to 'É'
+compose '\'' 'e' to 'é'
+compose '^' 'E' to 'Ê'
+compose '^' 'e' to 'ê'
+compose '"' 'E' to 'Ë'
+compose '"' 'e' to 'ë'
+compose '`' 'I' to 'Ì'
+compose '`' 'i' to 'ì'
+compose '\'' 'I' to 'Í'
+compose '\'' 'i' to 'í'
+compose '^' 'I' to 'Î'
+compose '^' 'i' to 'î'
+compose '"' 'I' to 'Ï'
+compose '"' 'i' to 'ï'
+compose '-' 'D' to 'Ð'
+compose '-' 'd' to 'ð'
+compose '~' 'N' to 'Ñ'
+compose '~' 'n' to 'ñ'
+compose '`' 'O' to 'Ò'
+compose '`' 'o' to 'ò'
+compose '\'' 'O' to 'Ó'
+compose '\'' 'o' to 'ó'
+compose '^' 'O' to 'Ô'
+compose '^' 'o' to 'ô'
+compose '~' 'O' to 'Õ'
+compose '~' 'o' to 'õ'
+compose '"' 'O' to 'Ö'
+compose '"' 'o' to 'ö'
+compose '/' 'O' to 'Ø'
+compose '/' 'o' to 'ø'
+compose '`' 'U' to 'Ù'
+compose '`' 'u' to 'ù'
+compose '\'' 'U' to 'Ú'
+compose '\'' 'u' to 'ú'
+compose '^' 'U' to 'Û'
+compose '^' 'u' to 'û'
+compose '"' 'U' to 'Ü'
+compose '"' 'u' to 'ü'
+compose '\'' 'Y' to 'Ý'
+compose '\'' 'y' to 'ý'
+compose 'T' 'H' to 'Þ'
+compose 't' 'h' to 'þ'
+compose 's' 's' to 'ß'
+compose '"' 'y' to 'ÿ'
+compose 's' 'z' to 'ß'
+compose 'i' 'j' to 'ÿ'
--- linux-2.1.39/arch/m68k/kernel/commonkeymap.c.orig	Mon May 19 15:26:51 1997
+++ linux-2.1.39/arch/m68k/kernel/commonkeymap.c	Mon May 19 13:58:06 1997
@@ -0,0 +1,145 @@
+/* Do not edit this file! It was automatically generated by   */
+/*    loadkeys --mktable defkeymap.map > defkeymap.c          */
+
+#include <linux/types.h>
+#include <linux/keyboard.h>
+#include <linux/kd.h>
+
+u_short plain_map[NR_KEYS] = {
+	0xf200,	0xf01b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+ushort *key_maps[MAX_NR_KEYMAPS] = {
+	plain_map,	0
+};
+
+unsigned int keymap_count = 1;
+
+/*
+ * Philosophy: most people do not define more strings, but they who do
+ * often want quite a lot of string space. So, we statically allocate
+ * the default and allocate dynamically in chunks of 512 bytes.
+ */
+
+char func_buf[] = {
+	'\033', '[', '[', 'A', 0, 
+	'\033', '[', '[', 'B', 0, 
+	'\033', '[', '[', 'C', 0, 
+	'\033', '[', '[', 'D', 0, 
+	'\033', '[', '[', 'E', 0, 
+	'\033', '[', '1', '7', '~', 0, 
+	'\033', '[', '1', '8', '~', 0, 
+	'\033', '[', '1', '9', '~', 0, 
+	'\033', '[', '2', '0', '~', 0, 
+	'\033', '[', '2', '1', '~', 0, 
+	'\033', '[', '2', '3', '~', 0, 
+	'\033', '[', '2', '4', '~', 0, 
+	'\033', '[', '2', '5', '~', 0, 
+	'\033', '[', '2', '6', '~', 0, 
+	'\033', '[', '2', '8', '~', 0, 
+	'\033', '[', '2', '9', '~', 0, 
+	'\033', '[', '3', '1', '~', 0, 
+	'\033', '[', '3', '2', '~', 0, 
+	'\033', '[', '3', '3', '~', 0, 
+	'\033', '[', '3', '4', '~', 0, 
+	'\033', '[', '1', '~', 0, 
+	'\033', '[', '2', '~', 0, 
+	'\033', '[', '3', '~', 0, 
+	'\033', '[', '4', '~', 0, 
+	'\033', '[', '5', '~', 0, 
+	'\033', '[', '6', '~', 0, 
+	'\033', '[', 'M', 0, 
+	'\033', '[', 'P', 0, 
+};
+
+char *funcbufptr = func_buf;
+int funcbufsize = sizeof(func_buf);
+int funcbufleft = 0;          /* space left */
+
+char *func_table[MAX_NR_FUNC] = {
+	func_buf + 0,
+	func_buf + 5,
+	func_buf + 10,
+	func_buf + 15,
+	func_buf + 20,
+	func_buf + 25,
+	func_buf + 31,
+	func_buf + 37,
+	func_buf + 43,
+	func_buf + 49,
+	func_buf + 55,
+	func_buf + 61,
+	func_buf + 67,
+	func_buf + 73,
+	func_buf + 79,
+	func_buf + 85,
+	func_buf + 91,
+	func_buf + 97,
+	func_buf + 103,
+	func_buf + 109,
+	func_buf + 115,
+	func_buf + 120,
+	func_buf + 125,
+	func_buf + 130,
+	func_buf + 135,
+	func_buf + 140,
+	func_buf + 145,
+	0,
+	0,
+	func_buf + 149,
+	0,
+};
+
+struct kbdiacr accent_table[MAX_DIACR] = {
+	{'`', 'A', '\300'},	{'`', 'a', '\340'},
+	{'\'', 'A', '\301'},	{'\'', 'a', '\341'},
+	{'^', 'A', '\302'},	{'^', 'a', '\342'},
+	{'~', 'A', '\303'},	{'~', 'a', '\343'},
+	{'"', 'A', '\304'},	{'"', 'a', '\344'},
+	{'O', 'A', '\305'},	{'o', 'a', '\345'},
+	{'0', 'A', '\305'},	{'0', 'a', '\345'},
+	{'A', 'A', '\305'},	{'a', 'a', '\345'},
+	{'A', 'E', '\306'},	{'a', 'e', '\346'},
+	{',', 'C', '\307'},	{',', 'c', '\347'},
+	{'`', 'E', '\310'},	{'`', 'e', '\350'},
+	{'\'', 'E', '\311'},	{'\'', 'e', '\351'},
+	{'^', 'E', '\312'},	{'^', 'e', '\352'},
+	{'"', 'E', '\313'},	{'"', 'e', '\353'},
+	{'`', 'I', '\314'},	{'`', 'i', '\354'},
+	{'\'', 'I', '\315'},	{'\'', 'i', '\355'},
+	{'^', 'I', '\316'},	{'^', 'i', '\356'},
+	{'"', 'I', '\317'},	{'"', 'i', '\357'},
+	{'-', 'D', '\320'},	{'-', 'd', '\360'},
+	{'~', 'N', '\321'},	{'~', 'n', '\361'},
+	{'`', 'O', '\322'},	{'`', 'o', '\362'},
+	{'\'', 'O', '\323'},	{'\'', 'o', '\363'},
+	{'^', 'O', '\324'},	{'^', 'o', '\364'},
+	{'~', 'O', '\325'},	{'~', 'o', '\365'},
+	{'"', 'O', '\326'},	{'"', 'o', '\366'},
+	{'/', 'O', '\330'},	{'/', 'o', '\370'},
+	{'`', 'U', '\331'},	{'`', 'u', '\371'},
+	{'\'', 'U', '\332'},	{'\'', 'u', '\372'},
+	{'^', 'U', '\333'},	{'^', 'u', '\373'},
+	{'"', 'U', '\334'},	{'"', 'u', '\374'},
+	{'\'', 'Y', '\335'},	{'\'', 'y', '\375'},
+	{'T', 'H', '\336'},	{'t', 'h', '\376'},
+	{'s', 's', '\337'},	{'"', 'y', '\377'},
+	{'s', 'z', '\337'},	{'i', 'j', '\377'},
+};
+
+unsigned int accent_table_size = 68;
--- linux-2.1.39/drivers/char/Makefile.orig	Sun May 18 23:36:28 1997
+++ linux-2.1.39/drivers/char/Makefile	Mon May 19 14:02:55 1997
@@ -158,7 +158,10 @@
 
 ifndef CONFIG_SUN_KEYBOARD
 ifdef CONFIG_VT
-L_OBJS += keyboard.o defkeymap.o
+L_OBJS += keyboard.o
+endif
+ifneq ($(ARCH),m68k)
+L_OBJS += pc_keyb.o defkeymap.o
 endif
 endif
 
--- linux-2.1.39/drivers/char/keyboard.c.orig	Sun May 18 23:36:31 1997
+++ linux-2.1.39/drivers/char/keyboard.c	Mon May 19 20:00:14 1997
@@ -15,18 +15,15 @@
  * 11-11-96: SAK should now work in the raw mode (Martin Mares)
  * 
  * Modified to provide 'generic' keyboard support by Hamish Macdonald
- * Merge with the m68k keyboard driver by Geert Uytterhoeven
+ * Merge with the m68k keyboard driver and split-off of the PC low-level
+ * parts by Geert Uytterhoeven, May 1997
  */
 
 #include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/mm.h>
-#include <linux/ptrace.h>
-#include <linux/signal.h>
 #include <linux/string.h>
-#include <linux/ioport.h>
 #include <linux/random.h>
 #include <linux/init.h>
 
@@ -37,16 +34,6 @@
 #include "diacr.h"
 #include "vt_kern.h"
 
-/*
- * On non-x86 and non-m68k hardware we do a full keyboard controller
- * initialization, in case the bootup software hasn't done
- * it. On a x86, the BIOS will already have initialized the
- * keyboard. On m68k we use the machdep abstraction (hint, hint... ;-)
- */
-#ifdef INIT_KBD
-static int initialize_kbd(void);
-#endif
-
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
 #ifndef KBD_DEFMODE
@@ -65,16 +52,11 @@
 #define KBD_DEFLOCK 0
 #endif
 
-#include <asm/io.h>
-#include <asm/system.h>
-
 extern void ctrl_alt_del(void);
 extern void reset_vc(unsigned int new_console);
 extern void scrollback(int);
 extern void scrollfront(int);
 
-unsigned char kbd_read_mask = 0x01;	/* modified by psaux.c */
-
 struct wait_queue * keypress_wait = NULL;
 
 void keyboard_wait_for_keypress(void)
@@ -109,14 +91,7 @@
 static struct kbd_struct * kbd = kbd_table;
 static struct tty_struct * tty = NULL;
 
-#if !USE_MACHDEP_ABSTRACTION
-/* used only by send_data - set by keyboard_interrupt */
-static volatile unsigned char reply_expected = 0;
-static volatile unsigned char acknowledge = 0;
-static volatile unsigned char resend = 0;
-#endif /* !USE_MACHDEP_ABSTRACTION */
-
-extern void compute_shiftstate(void);
+void compute_shiftstate(void);
 
 typedef void (*k_hand)(unsigned char value, char up_flag);
 typedef void (k_handfn)(unsigned char value, char up_flag);
@@ -189,191 +164,27 @@
        but we need only 16 bits here */
 }
 
-#if TRANSLATE_SCANCODES
 /*
  * Translation of escaped scancodes to keycodes.
- * This is now user-settable.
- * The keycodes 1-88,96-111,119 are fairly standard, and
- * should probably not be changed - changing might confuse X.
- * X also interprets scancode 0x5d (KEY_Begin).
- *
- * For 1-88 keycode equals scancode.
- */
-
-#define E0_KPENTER 96
-#define E0_RCTRL   97
-#define E0_KPSLASH 98
-#define E0_PRSCR   99
-#define E0_RALT    100
-#define E0_BREAK   101  /* (control-pause) */
-#define E0_HOME    102
-#define E0_UP      103
-#define E0_PGUP    104
-#define E0_LEFT    105
-#define E0_RIGHT   106
-#define E0_END     107
-#define E0_DOWN    108
-#define E0_PGDN    109
-#define E0_INS     110
-#define E0_DEL     111
-
-#define E1_PAUSE   119
-
-/*
- * The keycodes below are randomly located in 89-95,112-118,120-127.
- * They could be thrown away (and all occurrences below replaced by 0),
- * but that would force many users to use the `setkeycodes' utility, where
- * they needed not before. It does not matter that there are duplicates, as
- * long as no duplication occurs for any single keyboard.
- */
-#define SC_LIM 89
-
-#define FOCUS_PF1 85           /* actual code! */
-#define FOCUS_PF2 89
-#define FOCUS_PF3 90
-#define FOCUS_PF4 91
-#define FOCUS_PF5 92
-#define FOCUS_PF6 93
-#define FOCUS_PF7 94
-#define FOCUS_PF8 95
-#define FOCUS_PF9 120
-#define FOCUS_PF10 121
-#define FOCUS_PF11 122
-#define FOCUS_PF12 123
-
-#define JAP_86     124
-/* tfj@olivia.ping.dk:
- * The four keys are located over the numeric keypad, and are
- * labelled A1-A4. It's an rc930 keyboard, from
- * Regnecentralen/RC International, Now ICL.
- * Scancodes: 59, 5a, 5b, 5c.
- */
-#define RGN1 124
-#define RGN2 125
-#define RGN3 126
-#define RGN4 127
-
-static unsigned char high_keys[128 - SC_LIM] = {
-  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
-  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
-  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
-  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
-  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
-  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
-};
-
-/* BTC */
-#define E0_MACRO   112
-/* LK450 */
-#define E0_F13     113
-#define E0_F14     114
-#define E0_HELP    115
-#define E0_DO      116
-#define E0_F17     117
-#define E0_KPMINPLUS 118
-/*
- * My OmniKey generates e0 4c for  the "OMNI" key and the
- * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ * This is now user-settable (for machines were it makes sense).
  */
-#define E0_OK	124
-/*
- * New microsoft keyboard is rumoured to have
- * e0 5b (left window button), e0 5c (right window button),
- * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
- * [or: Windows_L, Windows_R, TaskMan]
- */
-#define E0_MSLW	125
-#define E0_MSRW	126
-#define E0_MSTM	127
-
-static unsigned char e0_keys[128] = {
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x00-0x07 */
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x08-0x0f */
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x10-0x17 */
-  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,	      /* 0x18-0x1f */
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x20-0x27 */
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x28-0x2f */
-  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,	      /* 0x30-0x37 */
-  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	      /* 0x38-0x3f */
-  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	      /* 0x40-0x47 */
-  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
-  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	      /* 0x50-0x57 */
-  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	      /* 0x58-0x5f */
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x60-0x67 */
-  0, 0, 0, 0, 0, 0, 0, E0_MACRO,		      /* 0x68-0x6f */
-  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x70-0x77 */
-  0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
-};
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-	if (scancode < SC_LIM || scancode > 255 || keycode > 127)
-	  return -EINVAL;
-	if (scancode < 128)
-	  high_keys[scancode - SC_LIM] = keycode;
-	else
-	  e0_keys[scancode - 128] = keycode;
-	return 0;
+    return kbd_setkeycode(scancode, keycode);
 }
 
 int getkeycode(unsigned int scancode)
 {
-	return
-	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :
-	  (scancode < 128) ? high_keys[scancode - SC_LIM] :
-	    e0_keys[scancode - 128];
-}
-
-#else /* TRANSLATE_SCANCODES */
-
-int setkeycode(unsigned int scancode, unsigned int keycode)
-{
-	return -EOPNOTSUPP;
+    return kbd_getkeycode(scancode);
 }
 
-int getkeycode(unsigned int scancode)
-{
-	return -EOPNOTSUPP;
-}
-
-#endif /* TRANSLATE_SCANCODES */
-
 void handle_scancode(unsigned char scancode)
 {
 	unsigned char keycode;
-#if TRANSLATE_SCANCODES
-	static unsigned int prev_scancode = 0;   /* remember E0, E1 */
-#endif /* TRANSLATE_SCANCODES */
 	char up_flag;				 /* 0 or 0200 */
 	char raw_mode;
 
-#if !USE_MACHDEP_ABSTRACTION
-	if (reply_expected) {
-	  /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
-	  /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
-		reply_expected = 0;
-		if (scancode == 0xfa) {
-			acknowledge = 1;
-			return;
-		} else if (scancode == 0xfe) {
-			resend = 1;
-			return;
-		}
-		/* strange ... */
-		reply_expected = 1;
-#if 0
-		printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
-		       scancode);
-#endif
-	}
-	if (scancode == 0) {
-#ifdef KBD_REPORT_ERR
-		printk(KERN_INFO "keyboard buffer overflow\n");
-#endif
-		prev_scancode = 0;
-		return;
-	}
-#endif /* !USE_MACHDEP_ABSTRACTION */
 	do_poke_blanked_console = 1;
 	mark_bh(CONSOLE_BH);
 	add_keyboard_randomness(scancode);
@@ -387,127 +198,28 @@
 		   values when finishing RAW mode or when changing VT's */
  	}
 
-#if TRANSLATE_SCANCODES
-	if (scancode == 0xff) {
-	        /* in scancode mode 1, my ESC key generates 0xff */
-		/* the calculator keys on a FOCUS 9000 generate 0xff */
-#ifndef KBD_IS_FOCUS_9000
-#ifdef KBD_REPORT_ERR
-		if (!raw_mode)
-		  printk(KERN_DEBUG "keyboard error\n");
-#endif
-#endif
-		prev_scancode = 0;
-		return;
-	}
-
-	if (scancode == 0xe0 || scancode == 0xe1) {
-		prev_scancode = scancode;
-		return;
- 	}
-#endif /* TRANSLATE_SCANCODES */
-
+	if (!kbd_pretranslate(scancode, raw_mode))
+	    return;
  	/*
-	 *  Convert scancode to keycode, using prev_scancode.
+	 *  Convert scancode to keycode
  	 */
 	up_flag = (scancode & 0200);
  	scancode &= 0x7f;
 
-#if TRANSLATE_SCANCODES
-	if (prev_scancode) {
-	  /*
-	   * usually it will be 0xe0, but a Pause key generates
-	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released
-	   */
-	  if (prev_scancode != 0xe0) {
-	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
-		  prev_scancode = 0x100;
-		  return;
-	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
-		  keycode = E1_PAUSE;
-		  prev_scancode = 0;
-	      } else {
-#ifdef KBD_REPORT_UNKN
-		  if (!raw_mode)
-		    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
-#endif
-		  prev_scancode = 0;
-		  return;
-	      }
-	  } else {
-	      prev_scancode = 0;
-	      /*
-	       *  The keyboard maintains its own internal caps lock and
-	       *  num lock statuses. In caps lock mode E0 AA precedes make
-	       *  code and E0 2A follows break code. In num lock mode,
-	       *  E0 2A precedes make code and E0 AA follows break code.
-	       *  We do our own book-keeping, so we will just ignore these.
-	       */
-	      /*
-	       *  For my keyboard there is no caps lock mode, but there are
-	       *  both Shift-L and Shift-R modes. The former mode generates
-	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
-	       *  So, we should also ignore the latter. - aeb@cwi.nl
-	       */
-	      if (scancode == 0x2a || scancode == 0x36)
-		return;
-
-	      if (e0_keys[scancode])
-		keycode = e0_keys[scancode];
-	      else {
-#ifdef KBD_REPORT_UNKN
-		  if (!raw_mode)
-		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
-			   scancode);
-#endif
-		  return;
-	      }
-	  }
-	} else if (scancode >= SC_LIM) {
-	    /* This happens with the FOCUS 9000 keyboard
-	       Its keys PF1..PF12 are reported to generate
-	       55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
-	       Moreover, unless repeated, they do not generate
-	       key-down events, so we have to zero up_flag below */
-	    /* Also, Japanese 86/106 keyboards are reported to
-	       generate 0x73 and 0x7d for \ - and \ | respectively. */
-	    /* Also, some Brazilian keyboard is reported to produce
-	       0x73 and 0x7e for \ ? and KP-dot, respectively. */
-
-	  keycode = high_keys[scancode - SC_LIM];
-
-	  if (!keycode) {
-	      if (!raw_mode) {
-#ifdef KBD_REPORT_UNKN
-		  printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
-			 " - ignored\n", scancode);
-#endif
-	      }
-	      return;
-	  }
- 	} else
-#endif /* TRANSLATE_SCANCODES */
-	  keycode = scancode;
+	if (!kbd_translate(scancode, &keycode, raw_mode))
+	    return;
 
 	/*
 	 * At this point the variable `keycode' contains the keycode.
-	 * Note: the keycode must not be 0.
+	 * Note: the keycode must not be 0 (++Geert: on m68k 0 is valid).
 	 * We keep track of the up/down status of the key, and
 	 * return the keycode if in MEDIUMRAW mode.
 	 */
 
 	if (up_flag) {
 		rep = 0;
- 		if(!test_and_clear_bit(keycode, key_down)) {
-#if !USE_MACHDEP_ABSTRACTION
-		    /* unexpected, but this can happen:
-		       maybe this was a key release for a FOCUS 9000
-		       PF key; if we want to see it, we have to clear
-		       up_flag */
-		    if (keycode >= SC_LIM || keycode == 85)
-		      up_flag = 0;
-#endif /* !USE_MACHDEP_ABSTRACTION */
-		}
+ 		if(!test_and_clear_bit(keycode, key_down))
+		    up_flag = kbd_unexpected_up(keycode);
 	} else
  		rep = test_and_set_bit(keycode, key_down);
 
@@ -579,86 +291,6 @@
 	}
 }
 
-#if !USE_MACHDEP_ABSTRACTION
-static inline void kb_wait(void)
-{
-	int i;
-
-	for (i=0; i<0x100000; i++)
-		if ((inb_p(0x64) & 0x02) == 0)
-			return;
-	printk(KERN_WARNING "Keyboard timed out\n");
-}
-
-static inline void send_cmd(unsigned char c)
-{
-	kb_wait();
-	outb(c,0x64);
-}
-
-#if DISABLE_KBD_DURING_INTERRUPTS
-#define disable_keyboard()	do { send_cmd(0xAD); kb_wait(); } while (0)
-#define enable_keyboard()	send_cmd(0xAE)
-#else
-#define disable_keyboard()	/* nothing */
-#define enable_keyboard()	/* nothing */
-#endif
-
-static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned char status;
-
-	pt_regs = regs;
-	disable_keyboard();
-
-	status = inb_p(0x64);
-	do {
-		unsigned char scancode;
-
-		/* mouse data? */
-		if (status & kbd_read_mask & 0x20)
-			break;
-
-		scancode = inb(0x60);
-		if (status & 0x01)
-			handle_scancode(scancode);
-
-		status = inb(0x64);
-	} while (status & 0x01);
-
-	mark_bh(KEYBOARD_BH);
-	enable_keyboard();
-}
-
-/*
- * send_data sends a character to the keyboard and waits
- * for an acknowledge, possibly retrying if asked to. Returns
- * the success status.
- */
-static int send_data(unsigned char data)
-{
-	int retries = 3;
-	int i;
-
-	do {
-		kb_wait();
-		acknowledge = 0;
-		resend = 0;
-		reply_expected = 1;
-		outb_p(data, 0x60);
-		for(i=0; i<0x200000; i++) {
-			inb_p(0x64);		/* just as a delay */
-			if (acknowledge)
-				return 1;
-			if (resend)
-				break;
-		}
-		if (!resend)
-			return 0;
-	} while (retries-- > 0);
-	return 0;
-}
-#endif /* !USE_MACHDEP_ABSTRACTION */
 
 static void put_queue(int ch)
 {
@@ -1213,13 +845,7 @@
 
 	if (leds != ledstate) {
 		ledstate = leds;
-#if USE_MACHDEP_ABSTRACTION
-		if (mach_kbd_leds)
-			mach_kbd_leds(leds);
-#else /* USE_MACHDEP_ABSTRACTION */
-		if (!send_data(0xed) || !send_data(leds))
-			send_data(0xf4);	/* re-enable kbd if any errors */
-#endif /* USE_MACHDEP_ABSTRACTION */
+		kbd_leds(leds);
 	}
 }
 
@@ -1241,198 +867,8 @@
 
 	ttytab = console_driver.table;
 
-#if USE_MACHDEP_ABSTRACTION
-	mach_keyb_init();
-#else /* USE_MACHDEP_ABSTRACTION */
-	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
-	request_region(0x60,16,"keyboard");
-#ifdef INIT_KBD
-	initialize_kbd();
-#endif
-#endif /* USE_MACHDEP_ABSTRACTION */
+	kbd_init_hw();
 	init_bh(KEYBOARD_BH, kbd_bh);
 	mark_bh(KEYBOARD_BH);
 	return 0;
 }
-
-#ifdef INIT_KBD
-/*
- * keyboard controller registers
- */
-#define KBD_STATUS_REG      (unsigned int) 0x64
-#define KBD_CNTL_REG        (unsigned int) 0x64
-#define KBD_DATA_REG	    (unsigned int) 0x60
-/*
- * controller commands
- */
-#define KBD_READ_MODE	    (unsigned int) 0x20
-#define KBD_WRITE_MODE	    (unsigned int) 0x60
-#define KBD_SELF_TEST	    (unsigned int) 0xAA
-#define KBD_SELF_TEST2	    (unsigned int) 0xAB
-#define KBD_CNTL_ENABLE	    (unsigned int) 0xAE
-/*
- * keyboard commands
- */
-#define KBD_ENABLE	    (unsigned int) 0xF4
-#define KBD_DISABLE	    (unsigned int) 0xF5
-#define KBD_RESET	    (unsigned int) 0xFF
-/*
- * keyboard replies
- */
-#define KBD_ACK		    (unsigned int) 0xFA
-#define KBD_POR		    (unsigned int) 0xAA
-/*
- * status register bits
- */
-#define KBD_OBF		    (unsigned int) 0x01
-#define KBD_IBF		    (unsigned int) 0x02
-#define KBD_GTO		    (unsigned int) 0x40
-#define KBD_PERR	    (unsigned int) 0x80
-/*
- * keyboard controller mode register bits
- */
-#define KBD_EKI		    (unsigned int) 0x01
-#define KBD_SYS		    (unsigned int) 0x04
-#define KBD_DMS		    (unsigned int) 0x20
-#define KBD_KCC		    (unsigned int) 0x40
-
-#define TIMEOUT_CONST	    500000
-
-static int kbd_wait_for_input(void)
-{
-        int     n;
-        int     status, data;
-
-        n = TIMEOUT_CONST;
-        do {
-                status = inb(KBD_STATUS_REG);
-                /*
-                 * Wait for input data to become available.  This bit will
-                 * then be cleared by the following read of the DATA
-                 * register.
-                 */
-
-                if (!(status & KBD_OBF))
-			continue;
-
-		data = inb(KBD_DATA_REG);
-
-                /*
-                 * Check to see if a timeout error has occurred.  This means
-                 * that transmission was started but did not complete in the
-                 * normal time cycle.  PERR is set when a parity error occurred
-                 * in the last transmission.
-                 */
-                if (status & (KBD_GTO | KBD_PERR)) {
-			continue;
-                }
-		return (data & 0xff);
-        } while (--n);
-        return (-1);	/* timed-out if fell through to here... */
-}
-
-static void kbd_write(int address, int data)
-{
-	int status;
-
-	do {
-		status = inb(KBD_STATUS_REG);  /* spin until input buffer empty*/
-	} while (status & KBD_IBF);
-	outb(data, address);               /* write out the data*/
-}
-
-__initfunc(static int initialize_kbd(void))
-{
-	unsigned long flags;
-
-	save_flags(flags); cli();
-
-	/* Flush any pending input. */
-	while (kbd_wait_for_input() != -1)
-		continue;
-
-	/*
-	 * Test the keyboard interface.
-	 * This seems to be the only way to get it going.
-	 * If the test is successful a x55 is placed in the input buffer.
-	 */
-	kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
-	if (kbd_wait_for_input() != 0x55) {
-		printk(KERN_WARNING "initialize_kbd: "
-		       "keyboard failed self test.\n");
-		restore_flags(flags);
-		return(-1);
-	}
-
-	/*
-	 * Perform a keyboard interface test.  This causes the controller
-	 * to test the keyboard clock and data lines.  The results of the
-	 * test are placed in the input buffer.
-	 */
-	kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
-	if (kbd_wait_for_input() != 0x00) {
-		printk(KERN_WARNING "initialize_kbd: "
-		       "keyboard failed self test 2.\n");
-		restore_flags(flags);
-		return(-1);
-	}
-
-	/* Enable the keyboard by allowing the keyboard clock to run. */
-	kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
-
-	/*
-	 * Reset keyboard. If the read times out
-	 * then the assumption is that no keyboard is
-	 * plugged into the machine.
-	 * This defaults the keyboard to scan-code set 2.
-	 */
-	kbd_write(KBD_DATA_REG, KBD_RESET);
-	if (kbd_wait_for_input() != KBD_ACK) {
-		printk(KERN_WARNING "initialize_kbd: "
-		       "reset kbd failed, no ACK.\n");
-		restore_flags(flags);
-		return(-1);
-	}
-
-	if (kbd_wait_for_input() != KBD_POR) {
-		printk(KERN_WARNING "initialize_kbd: "
-		       "reset kbd failed, not POR.\n");
-		restore_flags(flags);
-		return(-1);
-	}
-
-	/*
-	 * now do a DEFAULTS_DISABLE always
-	 */
-	kbd_write(KBD_DATA_REG, KBD_DISABLE);
-	if (kbd_wait_for_input() != KBD_ACK) {
-		printk(KERN_WARNING "initialize_kbd: "
-		       "disable kbd failed, no ACK.\n");
-		restore_flags(flags);
-		return(-1);
-	}
-
-	/*
-	 * Enable keyboard interrupt, operate in "sys" mode,
-	 *  enable keyboard (by clearing the disable keyboard bit),
-	 *  disable mouse, do conversion of keycodes.
-	 */
-	kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
-	kbd_write(KBD_DATA_REG, KBD_EKI|KBD_SYS|KBD_DMS|KBD_KCC);
-
-	/*
-	 * now ENABLE the keyboard to set it scanning...
-	 */
-	kbd_write(KBD_DATA_REG, KBD_ENABLE);
-	if (kbd_wait_for_input() != KBD_ACK) {
-		printk(KERN_WARNING "initialize_kbd: "
-		       "keyboard enable failed.\n");
-		restore_flags(flags);
-		return(-1);
-	}
-
-	restore_flags(flags);
-
-	return (1);
-}
-#endif /* INIT_KBD */
--- linux-2.1.39/drivers/char/pc_keyb.c.orig	Mon May 19 15:26:51 1997
+++ linux-2.1.39/drivers/char/pc_keyb.c	Tue May 20 23:00:41 1997
@@ -0,0 +1,609 @@
+/*
+ * linux/drivers/char/pc_keyb.c
+ *
+ * Written for linux by Johan Myreen as a translation from
+ * the assembly version by Linus (with diacriticals added)
+ *
+ * Some additional features added by Christoph Niemann (ChN), March 1993
+ *
+ * Loadable keymaps by Risto Kankkunen, May 1993
+ *
+ * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
+ * Added decr/incr_console, dynamic keymaps, Unicode support,
+ * dynamic function/string keys, led setting,  Sept 1994
+ * `Sticky' modifier keys, 951006.
+ * 11-11-96: SAK should now work in the raw mode (Martin Mares)
+ * 
+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
+ */
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/config.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+
+/*
+ * On non-x86 hardware we do a full keyboard controller
+ * initialization, in case the bootup software hasn't done
+ * it. On a x86, the BIOS will already have initialized the
+ * keyboard.
+ */
+#ifdef INIT_KBD
+static int initialize_kbd(void);
+#endif
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+unsigned char kbd_read_mask = 0x01;	/* modified by psaux.c */
+
+/* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected = 0;
+static volatile unsigned char acknowledge = 0;
+static volatile unsigned char resend = 0;
+
+/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
+static inline void kb_wait(void)
+{
+	int i;
+
+	for (i=0; i<0x100000; i++)
+		if ((inb_p(0x64) & 0x02) == 0)
+			return;
+	printk(KERN_WARNING "Keyboard timed out\n");
+}
+
+extern struct pt_regs *pt_regs;
+
+extern void handle_scancode(unsigned char scancode);
+
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL   97
+#define E0_KPSLASH 98
+#define E0_PRSCR   99
+#define E0_RALT    100
+#define E0_BREAK   101  /* (control-pause) */
+#define E0_HOME    102
+#define E0_UP      103
+#define E0_PGUP    104
+#define E0_LEFT    105
+#define E0_RIGHT   106
+#define E0_END     107
+#define E0_DOWN    108
+#define E0_PGDN    109
+#define E0_INS     110
+#define E0_DEL     111
+
+#define E1_PAUSE   119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89
+
+#define FOCUS_PF1 85           /* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86     124
+/* tfj@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
+  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
+  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
+  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
+  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO   112
+/* LK450 */
+#define E0_F13     113
+#define E0_F14     114
+#define E0_HELP    115
+#define E0_DO      116
+#define E0_F17     117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for  the "OMNI" key and the
+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ */
+#define E0_OK	124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW	125
+#define E0_MSRW	126
+#define E0_MSTM	127
+
+static unsigned char e0_keys[128] = {
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x00-0x07 */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x08-0x0f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x10-0x17 */
+  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,	      /* 0x18-0x1f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x20-0x27 */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x28-0x2f */
+  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,	      /* 0x30-0x37 */
+  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	      /* 0x38-0x3f */
+  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	      /* 0x40-0x47 */
+  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
+  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	      /* 0x50-0x57 */
+  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	      /* 0x58-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x60-0x67 */
+  0, 0, 0, 0, 0, 0, 0, E0_MACRO,		      /* 0x68-0x6f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x70-0x77 */
+  0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
+};
+
+static unsigned int prev_scancode = 0;   /* remember E0, E1 */
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+	  return -EINVAL;
+	if (scancode < 128)
+	  high_keys[scancode - SC_LIM] = keycode;
+	else
+	  e0_keys[scancode - 128] = keycode;
+	return 0;
+}
+
+int pckbd_getkeycode(unsigned int scancode)
+{
+	return
+	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+	  (scancode < 128) ? high_keys[scancode - SC_LIM] :
+	    e0_keys[scancode - 128];
+}
+
+#if DISABLE_KBD_DURING_INTERRUPTS
+static inline void send_cmd(unsigned char c)
+{
+	kb_wait();
+	outb(c,0x64);
+}
+
+#define disable_keyboard()	do { send_cmd(0xAD); kb_wait(); } while (0)
+#define enable_keyboard()	send_cmd(0xAE)
+#else
+#define disable_keyboard()	/* nothing */
+#define enable_keyboard()	/* nothing */
+#endif
+
+static int do_acknowledge(unsigned char scancode)
+{
+	if (reply_expected) {
+	  /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
+	  /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
+		reply_expected = 0;
+		if (scancode == 0xfa) {
+			acknowledge = 1;
+			return 0;
+		} else if (scancode == 0xfe) {
+			resend = 1;
+			return 0;
+		}
+		/* strange ... */
+		reply_expected = 1;
+#if 0
+		printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
+		       scancode);
+#endif
+	}
+	if (scancode == 0) {
+#ifdef KBD_REPORT_ERR
+		printk(KERN_INFO "keyboard buffer overflow\n");
+#endif
+		prev_scancode = 0;
+		return 0;
+	}
+	return 1;
+}
+
+int pckbd_pretranslate(unsigned char scancode, char raw_mode)
+{
+	if (scancode == 0xff) {
+	        /* in scancode mode 1, my ESC key generates 0xff */
+		/* the calculator keys on a FOCUS 9000 generate 0xff */
+#ifndef KBD_IS_FOCUS_9000
+#ifdef KBD_REPORT_ERR
+		if (!raw_mode)
+		  printk(KERN_DEBUG "keyboard error\n");
+#endif
+#endif
+		prev_scancode = 0;
+		return 0;
+	}
+
+	if (scancode == 0xe0 || scancode == 0xe1) {
+		prev_scancode = scancode;
+		return 0;
+ 	}
+ 	return 1;
+}
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode)
+{
+	if (prev_scancode) {
+	  /*
+	   * usually it will be 0xe0, but a Pause key generates
+	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+	   */
+	  if (prev_scancode != 0xe0) {
+	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
+		  prev_scancode = 0x100;
+		  return 0;
+	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
+		  *keycode = E1_PAUSE;
+		  prev_scancode = 0;
+	      } else {
+#ifdef KBD_REPORT_UNKN
+		  if (!raw_mode)
+		    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
+#endif
+		  prev_scancode = 0;
+		  return 0;
+	      }
+	  } else {
+	      prev_scancode = 0;
+	      /*
+	       *  The keyboard maintains its own internal caps lock and
+	       *  num lock statuses. In caps lock mode E0 AA precedes make
+	       *  code and E0 2A follows break code. In num lock mode,
+	       *  E0 2A precedes make code and E0 AA follows break code.
+	       *  We do our own book-keeping, so we will just ignore these.
+	       */
+	      /*
+	       *  For my keyboard there is no caps lock mode, but there are
+	       *  both Shift-L and Shift-R modes. The former mode generates
+	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+	       *  So, we should also ignore the latter. - aeb@cwi.nl
+	       */
+	      if (scancode == 0x2a || scancode == 0x36)
+		return 0;
+
+	      if (e0_keys[scancode])
+		*keycode = e0_keys[scancode];
+	      else {
+#ifdef KBD_REPORT_UNKN
+		  if (!raw_mode)
+		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
+			   scancode);
+#endif
+		  return 0;
+	      }
+	  }
+	} else if (scancode >= SC_LIM) {
+	    /* This happens with the FOCUS 9000 keyboard
+	       Its keys PF1..PF12 are reported to generate
+	       55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+	       Moreover, unless repeated, they do not generate
+	       key-down events, so we have to zero up_flag below */
+	    /* Also, Japanese 86/106 keyboards are reported to
+	       generate 0x73 and 0x7d for \ - and \ | respectively. */
+	    /* Also, some Brazilian keyboard is reported to produce
+	       0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+	  *keycode = high_keys[scancode - SC_LIM];
+
+	  if (!*keycode) {
+	      if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+		  printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
+			 " - ignored\n", scancode);
+#endif
+	      }
+	      return 0;
+	  }
+ 	} else
+	  *keycode = scancode;
+ 	return 1;
+}
+
+char pckbd_unexpected_up(unsigned char keycode)
+{
+	/* unexpected, but this can happen: maybe this was a key release for a
+	   FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
+	if (keycode >= SC_LIM || keycode == 85)
+	    return 0;
+	else
+	    return 0200;
+}
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned char status;
+
+	pt_regs = regs;
+	disable_keyboard();
+
+	status = inb_p(0x64);
+	do {
+		unsigned char scancode;
+
+		/* mouse data? */
+		if (status & kbd_read_mask & 0x20)
+			break;
+
+		scancode = inb(0x60);
+		if ((status & 0x01) && do_acknowledge(scancode))
+			handle_scancode(scancode);
+
+		status = inb(0x64);
+	} while (status & 0x01);
+
+	mark_bh(KEYBOARD_BH);
+	enable_keyboard();
+}
+
+/*
+ * send_data sends a character to the keyboard and waits
+ * for an acknowledge, possibly retrying if asked to. Returns
+ * the success status.
+ */
+static int send_data(unsigned char data)
+{
+	int retries = 3;
+	int i;
+
+	do {
+		kb_wait();
+		acknowledge = 0;
+		resend = 0;
+		reply_expected = 1;
+		outb_p(data, 0x60);
+		for(i=0; i<0x200000; i++) {
+			inb_p(0x64);		/* just as a delay */
+			if (acknowledge)
+				return 1;
+			if (resend)
+				break;
+		}
+		if (!resend)
+			return 0;
+	} while (retries-- > 0);
+	return 0;
+}
+
+void pckbd_leds(unsigned char leds)
+{
+	if (!send_data(0xed) || !send_data(leds))
+	    send_data(0xf4);	/* re-enable kbd if any errors */
+}
+
+__initfunc(void pckbd_init_hw(void))
+{
+	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
+	request_region(0x60,16,"keyboard");
+#ifdef INIT_KBD
+	initialize_kbd();
+#endif
+}
+
+#ifdef INIT_KBD
+/*
+ * keyboard controller registers
+ */
+#define KBD_STATUS_REG      (unsigned int) 0x64
+#define KBD_CNTL_REG        (unsigned int) 0x64
+#define KBD_DATA_REG	    (unsigned int) 0x60
+/*
+ * controller commands
+ */
+#define KBD_READ_MODE	    (unsigned int) 0x20
+#define KBD_WRITE_MODE	    (unsigned int) 0x60
+#define KBD_SELF_TEST	    (unsigned int) 0xAA
+#define KBD_SELF_TEST2	    (unsigned int) 0xAB
+#define KBD_CNTL_ENABLE	    (unsigned int) 0xAE
+/*
+ * keyboard commands
+ */
+#define KBD_ENABLE	    (unsigned int) 0xF4
+#define KBD_DISABLE	    (unsigned int) 0xF5
+#define KBD_RESET	    (unsigned int) 0xFF
+/*
+ * keyboard replies
+ */
+#define KBD_ACK		    (unsigned int) 0xFA
+#define KBD_POR		    (unsigned int) 0xAA
+/*
+ * status register bits
+ */
+#define KBD_OBF		    (unsigned int) 0x01
+#define KBD_IBF		    (unsigned int) 0x02
+#define KBD_GTO		    (unsigned int) 0x40
+#define KBD_PERR	    (unsigned int) 0x80
+/*
+ * keyboard controller mode register bits
+ */
+#define KBD_EKI		    (unsigned int) 0x01
+#define KBD_SYS		    (unsigned int) 0x04
+#define KBD_DMS		    (unsigned int) 0x20
+#define KBD_KCC		    (unsigned int) 0x40
+
+#define TIMEOUT_CONST	    500000
+
+static int kbd_wait_for_input(void)
+{
+        int     n;
+        int     status, data;
+
+        n = TIMEOUT_CONST;
+        do {
+                status = inb(KBD_STATUS_REG);
+                /*
+                 * Wait for input data to become available.  This bit will
+                 * then be cleared by the following read of the DATA
+                 * register.
+                 */
+
+                if (!(status & KBD_OBF))
+			continue;
+
+		data = inb(KBD_DATA_REG);
+
+                /*
+                 * Check to see if a timeout error has occurred.  This means
+                 * that transmission was started but did not complete in the
+                 * normal time cycle.  PERR is set when a parity error occurred
+                 * in the last transmission.
+                 */
+                if (status & (KBD_GTO | KBD_PERR)) {
+			continue;
+                }
+		return (data & 0xff);
+        } while (--n);
+        return (-1);	/* timed-out if fell through to here... */
+}
+
+static void kbd_write(int address, int data)
+{
+	int status;
+
+	do {
+		status = inb(KBD_STATUS_REG);  /* spin until input buffer empty*/
+	} while (status & KBD_IBF);
+	outb(data, address);               /* write out the data*/
+}
+
+__initfunc(static int initialize_kbd(void))
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+
+	/* Flush any pending input. */
+	while (kbd_wait_for_input() != -1)
+		continue;
+
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55) {
+		printk(KERN_WARNING "initialize_kbd: "
+		       "keyboard failed self test.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
+	if (kbd_wait_for_input() != 0x00) {
+		printk(KERN_WARNING "initialize_kbd: "
+		       "keyboard failed self test 2.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	/* Enable the keyboard by allowing the keyboard clock to run. */
+	kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
+
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 */
+	kbd_write(KBD_DATA_REG, KBD_RESET);
+	if (kbd_wait_for_input() != KBD_ACK) {
+		printk(KERN_WARNING "initialize_kbd: "
+		       "reset kbd failed, no ACK.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	if (kbd_wait_for_input() != KBD_POR) {
+		printk(KERN_WARNING "initialize_kbd: "
+		       "reset kbd failed, not POR.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	/*
+	 * now do a DEFAULTS_DISABLE always
+	 */
+	kbd_write(KBD_DATA_REG, KBD_DISABLE);
+	if (kbd_wait_for_input() != KBD_ACK) {
+		printk(KERN_WARNING "initialize_kbd: "
+		       "disable kbd failed, no ACK.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	/*
+	 * Enable keyboard interrupt, operate in "sys" mode,
+	 *  enable keyboard (by clearing the disable keyboard bit),
+	 *  disable mouse, do conversion of keycodes.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
+	kbd_write(KBD_DATA_REG, KBD_EKI|KBD_SYS|KBD_DMS|KBD_KCC);
+
+	/*
+	 * now ENABLE the keyboard to set it scanning...
+	 */
+	kbd_write(KBD_DATA_REG, KBD_ENABLE);
+	if (kbd_wait_for_input() != KBD_ACK) {
+		printk(KERN_WARNING "initialize_kbd: "
+		       "keyboard enable failed.\n");
+		restore_flags(flags);
+		return(-1);
+	}
+
+	restore_flags(flags);
+
+	return (1);
+}
+#endif /* INIT_KBD */
--- linux-2.1.39/include/asm-i386/keyboard.h.orig	Sun May 18 23:36:54 1997
+++ linux-2.1.39/include/asm-i386/keyboard.h	Mon May 19 19:58:51 1997
@@ -16,12 +16,26 @@
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
-#define TRANSLATE_SCANCODES		1
-#define USE_MACHDEP_ABSTRACTION		0
-
 #define KBD_REPORT_ERR
 #define KBD_REPORT_UNKN
 /* #define KBD_IS_FOCUS_9000 */
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_pretranslate	pckbd_pretranslate
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
 
 #endif /* __KERNEL__ */
 
--- linux-2.1.39/include/asm-mips/keyboard.h.orig	Sun May 18 23:36:57 1997
+++ linux-2.1.39/include/asm-mips/keyboard.h	Mon May 19 19:59:02 1997
@@ -16,12 +16,26 @@
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
-#define TRANSLATE_SCANCODES		1
-#define USE_MACHDEP_ABSTRACTION		0
-
 #define KBD_REPORT_ERR
 #define KBD_REPORT_UNKN
 /* #define KBD_IS_FOCUS_9000 */
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_pretranslate	pckbd_pretranslate
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
 
 #define INIT_KBD
 
--- linux-2.1.39/include/asm-alpha/keyboard.h.orig	Sun May 18 23:36:54 1997
+++ linux-2.1.39/include/asm-alpha/keyboard.h	Mon May 19 19:58:46 1997
@@ -16,12 +16,26 @@
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
-#define TRANSLATE_SCANCODES		1
-#define USE_MACHDEP_ABSTRACTION		0
-
 #define KBD_REPORT_ERR
 #define KBD_REPORT_UNKN
 /* #define KBD_IS_FOCUS_9000 */
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_pretranslate	pckbd_pretranslate
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
 
 #define INIT_KBD
 
--- linux-2.1.39/include/asm-m68k/keyboard.h.orig	Mon May 19 01:23:21 1997
+++ linux-2.1.39/include/asm-m68k/keyboard.h	Mon May 19 19:58:57 1997
@@ -13,9 +13,43 @@
 
 #ifdef __KERNEL__
 
-#define TRANSLATE_SCANCODES		0
-#define USE_MACHDEP_ABSTRACTION		1
 #include <asm/machdep.h>
+
+static __inline__ int kbd_setkeycode(unsigned int scancode,
+				     unsigned int keycode)
+{
+    return -EOPNOTSUPP;
+}
+
+static __inline__ int kbd_getkeycode(unsigned int scancode)
+{
+    return -EOPNOTSUPP;
+}
+
+static __inline__ int kbd_pretranslate(unsigned char scancode, char raw_mode)
+{
+    return 1;
+}
+
+static __inline__ int kbd_translate(unsigned char scancode,
+				    unsigned char *keycode, char raw_mode)
+{
+    *keycode = scancode;
+    return 1;
+}
+
+static __inline__ char kbd_unexpected_up(unsigned char keycode)
+{
+    return 0200;
+}
+
+static __inline__ void kbd_leds(unsigned char leds)
+{
+    if (mach_kbd_leds)
+	mach_kbd_leds(leds);
+}
+
+#define kbd_init_hw	mach_keyb_init
 
 #endif /* __KERNEL__ */
 
--- linux-2.1.39/include/asm-ppc/keyboard.h.orig	Sun May 18 23:36:57 1997
+++ linux-2.1.39/include/asm-ppc/keyboard.h	Mon May 19 19:59:06 1997
@@ -16,12 +16,26 @@
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
-#define TRANSLATE_SCANCODES		1
-#define USE_MACHDEP_ABSTRACTION		0
-
 #define KBD_REPORT_ERR
 #define KBD_REPORT_UNKN
 /* #define KBD_IS_FOCUS_9000 */
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_pretranslate	pckbd_pretranslate
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
 
 #define INIT_KBD
 

Greetings,

						Geert

--
Geert Uytterhoeven                   Geert.Uytterhoeven@thomas.kotnet.org
Linux/m68k on Amiga, Wavelets        http://www.thomas.kotnet.org/~geert/
KotNET@Thomas Network Administration -- Make you bed part of Cyberspace!!


