patch-2.1.87 linux/arch/m68k/mac/mackeyb.c

Next file: linux/arch/m68k/mac/via6522.c
Previous file: linux/arch/m68k/mac/macints.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.86/linux/arch/m68k/mac/mackeyb.c linux/arch/m68k/mac/mackeyb.c
@@ -0,0 +1,766 @@
+/*
+ *  linux/arch/m68k/mac/mackeyb.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * misc. keyboard stuff (everything not in adb-bus.c or keyb_m68k.c)
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/interrupt.h>
+/* keyb */
+#include <linux/keyboard.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+/* keyb */
+
+#include <asm/setup.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+/* for keyboard_input stuff */
+#include <asm/adb.h>
+#define KEYB_KEYREG	0	/* register # for key up/down data */
+#define KEYB_LEDREG	2	/* register # for leds on ADB keyboard */
+#define MOUSE_DATAREG	0	/* reg# for movement/button codes from mouse */
+/* end keyboard_input stuff */
+
+#include <asm/keyboard.h>
+#include <linux/kbd_kern.h>
+#include <linux/kbd_ll.h>
+
+static void kbd_repeat(unsigned long);
+static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat };
+static int last_keycode;
+
+static void input_keycode(int, int);
+
+extern struct kbd_struct kbd_table[];
+
+extern void handle_scancode(unsigned char);
+extern void put_queue(int);
+
+/* keyb */
+static void mac_leds_done(struct adb_request *);
+static void keyboard_input(unsigned char *, int, struct pt_regs *);
+static void mouse_input(unsigned char *, int, struct pt_regs *);
+/* Hook for mouse driver */
+void (*mac_mouse_interrupt_hook) (char *);
+int mac_emulate_button2;
+int mac_emulate_button3;
+/* The mouse driver - for debugging */
+extern void mac_mouse_interrupt(char *);
+/* end keyb */
+
+/* this map indicates which keys shouldn't autorepeat. */
+static unsigned char dont_repeat[128] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,	/* esc...option */
+	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/*
+ * Mac private key maps
+ */
+u_short mac_plain_map[NR_KEYS] = {
+	0xfb61,	0xfb73,	0xfb64,	0xfb66,	0xfb68,	0xfb67,	0xfb7a,	0xfb78,
+	0xfb63,	0xfb76,	0xf200,	0xfb62,	0xfb71,	0xfb77,	0xfb65,	0xfb72,
+	0xfb79,	0xfb74,	0xf031,	0xf032,	0xf033,	0xf034,	0xf036,	0xf035,
+	0xf03d,	0xf039,	0xf037,	0xf02d,	0xf038,	0xf030,	0xf05d,	0xfb6f,
+	0xfb75,	0xf05b,	0xfb69,	0xfb70,	0xf201,	0xfb6c,	0xfb6a,	0xf027,
+	0xfb6b,	0xf03b,	0xf05c,	0xf02c,	0xf02f,	0xfb6e,	0xfb6d,	0xf02e,
+	0xf009,	0xf020,	0xf060,	0xf07f,	0xf200,	0xf01b,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf601,	0xf602,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf300,	0xf301,	0xf302,	0xf303,	0xf304,	0xf305,
+	0xf306,	0xf307,	0xfb61,	0xf308,	0xf309,	0xf200,	0xf200,	0xf200,
+	0xf104,	0xf105,	0xf106,	0xf102,	0xf107,	0xf108,	0xf200,	0xf10a,
+	0xf200,	0xf10c,	0xf200,	0xf209,	0xf200,	0xf109,	0xf200,	0xf10b,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf118,	0xf116,	0xf103,	0xf117,
+	0xf101,	0xf119,	0xf100,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short mac_shift_map[NR_KEYS] = {
+	0xfb41,	0xfb53,	0xfb44,	0xfb46,	0xfb48,	0xfb47,	0xfb5a,	0xfb58,
+	0xfb43,	0xfb56,	0xf200,	0xfb42,	0xfb51,	0xfb57,	0xfb45,	0xfb52,
+	0xfb59,	0xfb54,	0xf021,	0xf040,	0xf023,	0xf024,	0xf05e,	0xf025,
+	0xf02b,	0xf028,	0xf026,	0xf05f,	0xf02a,	0xf029,	0xf07d,	0xfb4f,
+	0xfb55,	0xf07b,	0xfb49,	0xfb50,	0xf201,	0xfb4c,	0xfb4a,	0xf022,
+	0xfb4b,	0xf03a,	0xf07c,	0xf03c,	0xf03f,	0xfb4e,	0xfb4d,	0xf03e,
+	0xf009,	0xf020,	0xf07e,	0xf07f,	0xf200,	0xf01b,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf601,	0xf602,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf300,	0xf301,	0xf302,	0xf303,	0xf304,	0xf305,
+	0xf306,	0xf307,	0xfb41,	0xf308,	0xf309,	0xf200,	0xf200,	0xf200,
+	0xf10e,	0xf10f,	0xf110,	0xf10c,	0xf111,	0xf112,	0xf200,	0xf10a,
+	0xf200,	0xf10c,	0xf200,	0xf203,	0xf200,	0xf113,	0xf200,	0xf10b,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf20b,	0xf116,	0xf10d,	0xf117,
+	0xf10b,	0xf20a,	0xf10a,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short mac_altgr_map[NR_KEYS] = {
+	0xf914,	0xfb73,	0xf917,	0xf919,	0xfb68,	0xfb67,	0xfb7a,	0xfb78,
+	0xf916,	0xfb76,	0xf200,	0xf915,	0xfb71,	0xfb77,	0xf918,	0xfb72,
+	0xfb79,	0xfb74,	0xf200,	0xf040,	0xf200,	0xf024,	0xf200,	0xf200,
+	0xf200,	0xf05d,	0xf07b,	0xf05c,	0xf05b,	0xf07d,	0xf07e,	0xfb6f,
+	0xfb75,	0xf200,	0xfb69,	0xfb70,	0xf201,	0xfb6c,	0xfb6a,	0xf200,
+	0xfb6b,	0xf200,	0xf200,	0xf200,	0xf200,	0xfb6e,	0xfb6d,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf601,	0xf602,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf90a,	0xf90b,	0xf90c,	0xf90d,	0xf90e,	0xf90f,
+	0xf910,	0xf911,	0xf914,	0xf912,	0xf913,	0xf200,	0xf200,	0xf200,
+	0xf510,	0xf511,	0xf512,	0xf50e,	0xf513,	0xf514,	0xf200,	0xf516,
+	0xf200,	0xf10c,	0xf200,	0xf202,	0xf200,	0xf515,	0xf200,	0xf517,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf118,	0xf116,	0xf50f,	0xf117,
+	0xf50d,	0xf119,	0xf50c,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short mac_ctrl_map[NR_KEYS] = {
+	0xf001,	0xf013,	0xf004,	0xf006,	0xf008,	0xf007,	0xf01a,	0xf018,
+	0xf003,	0xf016,	0xf200,	0xf002,	0xf011,	0xf017,	0xf005,	0xf012,
+	0xf019,	0xf014,	0xf200,	0xf000,	0xf01b,	0xf01c,	0xf01e,	0xf01d,
+	0xf200,	0xf200,	0xf01f,	0xf01f,	0xf07f,	0xf200,	0xf01d,	0xf00f,
+	0xf015,	0xf01b,	0xf009,	0xf010,	0xf201,	0xf00c,	0xf00a,	0xf007,
+	0xf00b,	0xf200,	0xf01c,	0xf200,	0xf07f,	0xf00e,	0xf00d,	0xf20e,
+	0xf200,	0xf000,	0xf000,	0xf008,	0xf200,	0xf200,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf601,	0xf602,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf300,	0xf301,	0xf302,	0xf303,	0xf304,	0xf305,
+	0xf306,	0xf307,	0xf001,	0xf308,	0xf309,	0xf200,	0xf200,	0xf200,
+	0xf104,	0xf105,	0xf106,	0xf102,	0xf107,	0xf108,	0xf200,	0xf10a,
+	0xf200,	0xf10c,	0xf200,	0xf204,	0xf200,	0xf109,	0xf200,	0xf10b,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf118,	0xf116,	0xf103,	0xf117,
+	0xf101,	0xf119,	0xf100,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short mac_shift_ctrl_map[NR_KEYS] = {
+	0xf001,	0xf013,	0xf004,	0xf006,	0xf008,	0xf007,	0xf01a,	0xf018,
+	0xf003,	0xf016,	0xf200,	0xf002,	0xf011,	0xf017,	0xf005,	0xf012,
+	0xf019,	0xf014,	0xf200,	0xf000,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf01f,	0xf200,	0xf200,	0xf200,	0xf00f,
+	0xf015,	0xf200,	0xf009,	0xf010,	0xf201,	0xf00c,	0xf00a,	0xf200,
+	0xf00b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf00e,	0xf00d,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf601,	0xf602,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf300,	0xf301,	0xf302,	0xf303,	0xf304,	0xf305,
+	0xf306,	0xf307,	0xf001,	0xf308,	0xf309,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf10c,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf118,	0xf116,	0xf200,	0xf117,
+	0xf200,	0xf119,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf20c,
+};
+
+u_short mac_alt_map[NR_KEYS] = {
+	0xf861,	0xf873,	0xf864,	0xf866,	0xf868,	0xf867,	0xf87a,	0xf878,
+	0xf863,	0xf876,	0xf200,	0xf862,	0xf871,	0xf877,	0xf865,	0xf872,
+	0xf879,	0xf874,	0xf831,	0xf832,	0xf833,	0xf834,	0xf836,	0xf835,
+	0xf83d,	0xf839,	0xf837,	0xf82d,	0xf838,	0xf830,	0xf85d,	0xf86f,
+	0xf875,	0xf85b,	0xf869,	0xf870,	0xf80d,	0xf86c,	0xf86a,	0xf827,
+	0xf86b,	0xf83b,	0xf85c,	0xf82c,	0xf82f,	0xf86e,	0xf86d,	0xf82e,
+	0xf809,	0xf820,	0xf860,	0xf87f,	0xf200,	0xf81b,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf210,	0xf211,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf900,	0xf901,	0xf902,	0xf903,	0xf904,	0xf905,
+	0xf906,	0xf907,	0xf861,	0xf908,	0xf909,	0xf200,	0xf200,	0xf200,
+	0xf504,	0xf505,	0xf506,	0xf502,	0xf507,	0xf508,	0xf200,	0xf50a,
+	0xf200,	0xf10c,	0xf200,	0xf209,	0xf200,	0xf509,	0xf200,	0xf50b,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf118,	0xf116,	0xf503,	0xf117,
+	0xf501,	0xf119,	0xf500,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short mac_ctrl_alt_map[NR_KEYS] = {
+	0xf801,	0xf813,	0xf804,	0xf806,	0xf808,	0xf807,	0xf81a,	0xf818,
+	0xf803,	0xf816,	0xf200,	0xf802,	0xf811,	0xf817,	0xf805,	0xf812,
+	0xf819,	0xf814,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf80f,
+	0xf815,	0xf200,	0xf809,	0xf810,	0xf201,	0xf80c,	0xf80a,	0xf200,
+	0xf80b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf80e,	0xf80d,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf702,	0xf703,
+	0xf700,	0xf207,	0xf701,	0xf601,	0xf602,	0xf600,	0xf603,	0xf200,
+	0xf200,	0xf310,	0xf200,	0xf30c,	0xf200,	0xf30a,	0xf200,	0xf208,
+	0xf200,	0xf200,	0xf200,	0xf30d,	0xf30e,	0xf200,	0xf30b,	0xf200,
+	0xf200,	0xf200,	0xf300,	0xf301,	0xf302,	0xf303,	0xf304,	0xf305,
+	0xf306,	0xf307,	0xf801,	0xf308,	0xf309,	0xf200,	0xf200,	0xf200,
+	0xf504,	0xf505,	0xf506,	0xf502,	0xf507,	0xf508,	0xf200,	0xf50a,
+	0xf200,	0xf10c,	0xf200,	0xf200,	0xf200,	0xf509,	0xf200,	0xf50b,
+	0xf200,	0xf11d,	0xf115,	0xf114,	0xf118,	0xf116,	0xf503,	0xf117,
+	0xf501,	0xf119,	0xf500,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+extern unsigned int keymap_count;
+
+#if 0
+ushort *mac_key_maps[MAX_NR_KEYMAPS] = {
+	mac_plain_map, mac_shift_map, mac_altgr_map, 0,
+	mac_ctrl_map, mac_shift_ctrl_map, 0, 0,
+	mac_alt_map, 0, 0, 0,
+	mac_ctrl_alt_map,	0
+};
+#endif
+
+/*
+ * Misc. defines for testing 
+ */
+
+extern int console_loglevel;
+
+static struct adb_request led_request;
+extern int in_keybinit;
+
+/*
+ * machdep keyboard routines, interface and key repeat method modeled after
+ * drivers/macintosh/keyb_mac.c
+ */
+
+int mac_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+		     char raw_mode)
+{
+	if (!raw_mode) {
+		/*
+		 * Convert R-shift/control/option to L version.
+		 * Remap keycode 0 (A) to the unused keycode 0x5a.
+		 * Other parts of the system assume 0 is not a valid keycode.
+		 */
+		switch (keycode) {
+		case 0x7b: keycode = 0x38; break; /* R-shift */
+		case 0x7c: keycode = 0x3a; break; /* R-option */
+		case 0x7d: keycode = 0x36; break; /* R-control */
+		case 0:	   keycode = 0x5a; break; /* A */
+		}
+	}
+	*keycodep = keycode;
+	return 1;
+}
+
+int mac_kbd_unexpected_up(unsigned char keycode)
+{
+	return 0x80;
+}
+
+static void
+keyboard_input(unsigned char *data, int nb, struct pt_regs *regs)
+{
+	/* first check this is from register 0 */
+	if (nb != 5 || (data[2] & 3) != KEYB_KEYREG)
+		return;		/* ignore it */
+	kbd_pt_regs = regs;
+	input_keycode(data[3], 0);
+	if (!(data[4] == 0xff || (data[4] == 0x7f && data[3] == 0x7f)))
+		input_keycode(data[4], 0);
+}
+
+static void
+input_keycode(int keycode, int repeat)
+{
+	struct kbd_struct *kbd;
+	int up_flag;
+
+ 	kbd = kbd_table + fg_console;
+	up_flag = (keycode & 0x80);
+        keycode &= 0x7f;
+	if (!repeat)
+		del_timer(&repeat_timer);
+
+	/*
+	 * XXX: Add mouse button 2+3 fake codes here if mouse open.
+	 *	As we only report up/down events, keep track of faked buttons.
+	 *	Really messy; might need to check if keyboard is in
+	 *	VC_RAW mode for X?.
+	 *	Might also want to know how many buttons need to be emulated.
+	 *	-> hide this as function in arch/m68k/mac ?
+	 *	Current emulation buttons: right alt/option and control
+	 *	(wanted: command and alt/option, or KP= and KP( ...)
+	 *	Debug version; might be rewritten to be faster on normal keys.
+	 */
+	if (mac_mouse_interrupt_hook || console_loglevel >= 8) {
+		unsigned char button, button2, button3, fake_event;
+		static unsigned char button2state=0, button3state=0; /* up */
+		/* faked ADB packet: device type ff, handler 4 ! */
+		static char data[6] = { 0xff, 0x40, 0x3c, 0x80, 0x80, 0x80 };
+
+		button = 0;
+		fake_event = 0;
+		switch (keycode) {	/* which 'button' ? */
+			case 0x7c:	/* R-option */
+				button2 = (!up_flag);		/* new state */
+				if (button2 != button2state)	/* change ? */
+					button = 2; 
+				button2state = button2;		/* save state */
+				fake_event = 2;
+				break; 
+			case 0x7d:	/* R-control */
+				button3 = (!up_flag);		/* new state */
+				if (button3 != button3state)	/* change ? */ 
+					button = 3; 
+				button3state = button3; 	/* save state */
+				fake_event = 3;
+				break; 
+		}
+#ifdef DEBUG_ADBMOUSE
+		if (fake_event && console_loglevel >= 8)
+			printk("fake event: button2 %d button3 %d button %d\n",
+				 button2state, button3state, button);
+#endif
+		if (button) {		/* there's been a button state change */
+			/* fake a mouse packet : send all bytes, change one! */
+			data[button+2] = (up_flag ? 0x80 : 0);
+			if (mac_mouse_interrupt_hook)
+				mac_mouse_interrupt_hook(data);
+#ifdef DEBUG_ADBMOUSE
+			else
+				printk("mouse_fake: data %2x %2x %2x buttons %2x \n", 
+					data[3], data[4], data[5],
+					~( (data[3] & 0x80 ? 0 : 4) 
+					 | (data[4] & 0x80 ? 0 : 1) 
+					 | (data[5] & 0x80 ? 0 : 2) )&7 );
+#endif
+		}
+		/*
+		 * for mouse 3-button emulation: don't process 'fake' keys!
+		 * Keys might autorepeat, and console state gets generally messed
+		 * up enough so that selection stops working.
+		 */
+		if (fake_event)
+			return;
+	}
+
+	/*
+	 * Convert R-shift/control/option to L version.
+	 */
+	switch (keycode) {
+		case 0x7b: keycode = 0x38; break; /* R-shift */
+		case 0x7c: keycode = 0x3a; break; /* R-option */
+		case 0x7d: keycode = 0x36; break; /* R-control */
+		case 0x0:  if (kbd->kbdmode != VC_RAW) 
+			       keycode = 0x5a; /* A; keycode 0 deprecated */
+			       break; 
+	}
+
+	if (kbd->kbdmode != VC_RAW) {
+		if (!up_flag && !dont_repeat[keycode]) {
+			last_keycode = keycode;
+			repeat_timer.expires = jiffies + (repeat? HZ/15: HZ/2);
+			add_timer(&repeat_timer);
+		}
+
+		/*
+		 * XXX fix caps-lock behaviour by turning the key-up
+		 * transition into a key-down transition.
+		 * MSch: need to turn each caps-lock event into a down-up
+		 * double event (keyboard code assumes caps-lock is a toggle)
+		 */
+#if 0
+		if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK))
+			up_flag = 0;
+#else
+		if (keycode == 0x39) {
+			handle_scancode(keycode);	/* down */
+			up_flag = 0x80;			/* see below ... */
+		}
+#endif
+	}
+
+	handle_scancode(keycode + up_flag);
+}
+
+static void
+kbd_repeat(unsigned long xxx)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	input_keycode(last_keycode, 1);
+	restore_flags(flags);
+}
+
+  /* [ACA:23-Mar-97] Three button mouse support.  This is designed to
+     function with MkLinux DR-2.1 style X servers.  It only works with
+     three-button mice that conform to Apple's multi-button mouse
+     protocol. */
+
+  /*
+    The X server for MkLinux DR2.1 uses the following unused keycodes to
+    read the mouse:
+
+    0x7e  This indicates that the next two keycodes should be interpreted
+          as mouse information.  The first following byte's high bit
+          represents the state of the left button.  The lower seven bits
+          represent the x-axis acceleration.  The lower seven bits of the
+          second byte represent y-axis acceleration.
+
+    0x3f  The x server interprets this keycode as a middle button
+          release.
+
+    0xbf  The x server interprets this keycode as a middle button
+          depress.
+
+    0x40  The x server interprets this keycode as a right button
+          release.
+
+    0xc0  The x server interprets this keycode as a right button
+          depress.
+
+    NOTES: There should be a better way of handling mice in the X server.
+    The MOUSE_ESCAPE code (0x7e) should be followed by three bytes instead
+    of two.  The three mouse buttons should then, in the X server, be read
+    as the high-bits of all three bytes.  The x and y motions can still be
+    in the first two bytes.  Maybe I'll do this...
+  */
+
+  /*
+    Handler 4 -- Apple Extended mouse protocol.
+
+    For Apple's 3-button mouse protocol the data array will contain the
+    following values:
+
+		BITS    COMMENTS
+    data[0] = 0000 0000 ADB packet identifer.
+    data[1] = 0100 0000 Extended protocol register.
+	      Bits 6-7 are the device id, which should be 1.
+	      Bits 4-5 are resolution which is in "units/inch".
+	      The Logitech MouseMan returns these bits clear but it has
+	      200/300cpi resolution.
+	      Bits 0-3 are unique vendor id.
+    data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
+	      Bits 2-3 should be 8 + 4.
+		      Bits 4-7 should be 3 for a mouse device.
+    data[3] = bxxx xxxx Left button and x-axis motion.
+    data[4] = byyy yyyy Second button and y-axis motion.
+    data[5] = byyy bxxx Third button and fourth button.  Y is additional
+	      high bits of y-axis motion.  XY is additional
+	      high bits of x-axis motion.
+
+    NOTE: data[0] and data[2] are confirmed by the parent function and
+    need not be checked here.
+  */
+
+  /*
+    Handler 1 -- 100cpi original Apple mouse protocol.
+    Handler 2 -- 200cpi original Apple mouse protocol.
+
+    For Apple's standard one-button mouse protocol the data array will
+    contain the following values:
+
+                BITS    COMMENTS
+    data[0] = 0000 0000 ADB packet identifer.
+    data[1] = ???? ???? (?)
+    data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
+    data[3] = bxxx xxxx First button and x-axis motion.
+    data[4] = byyy yyyy Second button and y-axis motion.
+
+    NOTE: data[0] is confirmed by the parent function and need not be
+    checked here.
+  */
+
+static void
+mouse_input(unsigned char *data, int nb, struct pt_regs *regs)
+{
+	struct kbd_struct *kbd;
+	int i;
+
+	if (nb < 5 || nb > 6 || (data[2] & 3) != MOUSE_DATAREG) {
+		printk("data from mouse:");
+		for (i = 0; i < nb; ++i)
+			printk(" %x", data[i]);
+		printk("\n");
+		return;
+	}
+
+	if (mac_mouse_interrupt_hook) {
+		mac_mouse_interrupt_hook(data);
+		/*
+		 * passing the mouse data to i.e. the X server as done for
+		 * Xpmac will confuse applications on a sane X server :-)
+		 */
+		return;
+	} 
+#ifdef DEBUG_ADBMOUSE
+	else
+		if (console_loglevel >= 8)
+		    printk("mouse_input: data %x %x %x buttons %x dx %d dy %d \n", 
+			data[3], data[4], data[5],
+			~((data[3] & 0x80 ? 0 : 4) 
+			| (data[4] & 0x80 ? 0 : 1)
+			| (data[5] & 0x80 ? 0 : 2))&7,
+			((data[4]&0x7f) < 64 ? (data[4]&0x7f) : (data[4]&0x7f)-128 ),
+			((data[3]&0x7f) < 64 ? -(data[3]&0x7f) : 128-(data[3]&0x7f) ) );
+#endif
+
+
+	kbd = kbd_table + fg_console;
+
+#if 0	/* The entirely insane way of MkLinux handling mouse input */
+	/* Requires put_queue which is static in keyboard.c :-( */
+	/* Only send mouse codes when keyboard is in raw mode. */
+	if (kbd->kbdmode == VC_RAW) {
+		static unsigned char uch_ButtonStateSecond = 0;
+		unsigned char uchButtonSecond;
+
+		/* Send first button, second button and movement. */
+		put_queue( 0x7e );
+		put_queue( data[3] );
+		put_queue( data[4] );
+
+		/* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */
+
+		/* Store the button state. */
+		uchButtonSecond = (data[4] & 0x80);
+
+		/* Send second button. */
+		if (uchButtonSecond != uch_ButtonStateSecond) {
+			put_queue( 0x3f | uchButtonSecond );
+			uch_ButtonStateSecond = uchButtonSecond;
+		}
+
+		/* Macintosh 3-button mouse (handler 4). */
+		if ((nb == 6) && (data[1] & 0x40)) {
+			static unsigned char uch_ButtonStateThird = 0;
+			unsigned char uchButtonThird;
+
+			/* Store the button state for speed. */
+			uchButtonThird = (data[5] & 0x80);
+
+			/* Send third button. */
+			if (uchButtonThird != uch_ButtonStateThird) {
+				put_queue( 0x40 | uchButtonThird );
+				uch_ButtonStateThird = uchButtonThird;
+			}
+		}
+	}
+#endif	/* insane MkLinux mouse hack */
+}
+
+/* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */
+static unsigned char mac_ledmap[8] = {
+    0,		/* none */
+    4,		/* scroll lock */
+    1,		/* num lock */
+    5,		/* scroll + num lock */
+    2,		/* caps lock */
+    6,		/* caps + scroll lock */
+    3,		/* caps + num lock */
+    7,		/* caps + num + scroll lock */
+};
+
+static int leds_pending;
+
+void mac_kbd_leds(unsigned int leds)
+{
+	if (led_request.got_reply) {
+#ifdef DEBUG_ADB
+		if (console_loglevel == 10)
+			printk("mac_kbd_leds: got reply, sending request!\n");
+#endif
+		adb_request(&led_request, mac_leds_done, 4, ADB_PACKET,
+			     ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG),
+			     0xff, ~mac_ledmap[leds]);
+	} else
+		leds_pending = leds | 0x100;
+}
+
+static void mac_leds_done(struct adb_request *req)
+{
+	int leds;
+
+	if (leds_pending) {
+		leds = leds_pending & 0xff;
+		leds_pending = 0;
+		mac_kbd_leds(leds);
+	}
+	mark_bh(KEYBOARD_BH);
+}
+
+int mac_kbdrate(struct kbd_repeat *k)
+{
+	return 0;
+}
+
+int mac_keyb_init(void)
+{
+	static struct adb_request autopoll_req, confcod_req, mouse_req, readkey_req;
+	volatile int ct;
+
+	/* setup key map */
+	key_maps[0]  = mac_plain_map;
+	key_maps[1]  = mac_shift_map;
+	key_maps[2]  = mac_altgr_map;
+	key_maps[4]  = mac_ctrl_map;
+	key_maps[5]  = mac_shift_ctrl_map;
+	key_maps[8]  = mac_alt_map;
+	/* key_maps[9]  = atashift_alt_map; */
+	key_maps[12] = mac_ctrl_alt_map;
+	/* key_maps[13] = atashift_ctrl_alt_map; */
+	memcpy (plain_map, mac_plain_map, sizeof(plain_map));
+	keymap_count = 7;
+
+	/* initialize mouse interrupt hook */
+	mac_mouse_interrupt_hook = NULL;
+	/* assume broken mouse :-) */
+	mac_emulate_button2 = 1;
+	mac_emulate_button3 = 1;
+
+	/*
+	 * Might put that someplace else, possibly ....
+	 */
+	adb_bus_init();
+
+	/* the input functions ... */	
+	adb_register(ADB_KEYBOARD, keyboard_input);
+	adb_register(ADB_MOUSE, mouse_input);
+
+	/* turn on ADB auto-polling in the CUDA */
+	
+	/*
+	 *	Older boxes don't support CUDA_* targets and CUDA commands
+	 *	instead we emulate them in the adb_request hook to make
+	 *	the code interfaces saner.
+	 *
+	 *	Note XXX: the Linux PMac and this code both assume the
+	 *	devices are at their primary ids and do not do device
+	 *	assignment. This isn't ideal. We should fix it to follow
+	 *	the reassignment specs.
+	 */
+
+	if (macintosh_config->adb_type == MAC_ADB_CUDA) {
+		printk("CUDA autopoll on ...\n");
+		adb_request(&autopoll_req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
+		ct=0; 
+		while (!autopoll_req.got_reply && ++ct<1000)
+		{
+			adb_poll();
+				udelay(10);
+		}
+		if(ct==1000)
+			printk("Keyboard timed out.\n");
+	}
+
+	/*
+	 *	XXX: all ADB requests now in CUDA format; adb_request takes 
+	 *	care of that for other Macs.
+	 */
+
+	printk("Configuring keyboard\n");
+
+	/* 
+	 * turn on all leds - the keyboard driver will turn them back off 
+	 * via mac_kbd_leds if everything works ok!
+	 */
+	printk("leds on ...\n");
+	adb_request(&led_request, NULL, 4, ADB_PACKET,
+		     ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, ~7);
+
+	/*
+	 * The polling stuff should go away as soon as the ADB driver is stable
+	 */
+	ct = 0;
+	adb_poll();
+	while (!led_request.got_reply && ++ct<1000)
+	{
+		adb_poll();
+		udelay(10);
+	}
+	if(ct==1000)
+		printk("Keyboard timed out.\n");
+
+#if 1
+	printk("Configuring coding mode ...\n");
+
+	/* 
+	 * get the keyboard to send separate codes for
+	 * left and right shift, control, option keys. 
+	 */
+	adb_request(&confcod_req, NULL, 4, ADB_PACKET, 
+		     ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
+
+	ct=0; 
+	adb_poll();
+	while (!confcod_req.got_reply && ++ct<1000)
+	{
+		adb_poll();
+		udelay(10);
+	}
+	if(ct==1000)
+		printk("Keyboard timed out.\n");
+#endif
+
+#if 0	/* seems to hurt, at least Geert's Mac */
+	printk("Configuring mouse (3-button mode) ...\n");
+
+	/* 
+	 * XXX: taken from the PPC driver again ... 
+	 * Try to switch the mouse (id 3) to handler 4, for three-button
+	 * mode. (0x20 is Service Request Enable, 0x03 is Device ID). 
+	 */
+	adb_request(&mouse_req, NULL, 4, ADB_PACKET,
+		    ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
+
+	ct=0; 
+	adb_poll();
+	while (!mouse_req.got_reply && ++ct<1000)
+	{
+		adb_poll();
+		udelay(10);
+	}
+	if(ct==1000)
+		printk("Mouse timed out.\n");
+#endif
+
+#if 0
+	printk("Start polling keyboard ...\n");
+
+	/* 
+	 *	get the keyboard to send data back, via the adb_input hook
+	 *	XXX: was never used properly, and the driver takes care
+	 *	of polling and timeout retransmits now.
+	 *	Might be of use if we want to start talking to a specific
+	 *	device here...
+	 */
+	adb_request(&readkey_req, NULL, 2, ADB_PACKET, 
+		     ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG));
+#endif
+
+	/*
+	 * fake 'request done' for the driver if requests timed out
+	 */
+
+	autopoll_req.got_reply = 1;
+#if 0
+	/* XXX: results in race and hang with mac_kbd_leds and serial (why ?) */
+	led_request.got_reply  = 1;
+#endif
+	confcod_req.got_reply  = 1;
+
+	in_keybinit = 0;
+	printk("Keyboard init done\n");
+
+	return 0;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov