patch-2.1.51 linux/drivers/macintosh/mac_keyb.c
Next file: linux/drivers/macintosh/mackeymap.c
Previous file: linux/drivers/macintosh/imstt.h
Back to the patch index
Back to the overall index
- Lines: 344
- Date:
Sat Aug 16 09:53:08 1997
- Orig file:
v2.1.50/linux/drivers/macintosh/mac_keyb.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
@@ -0,0 +1,343 @@
+/*
+ * drivers/char/mac_keyb.c
+ *
+ * Keyboard driver for Power Macintosh computers.
+ *
+ * Adapted from drivers/char/keyboard.c by Paul Mackerras
+ * (see that file for its authors and contributors).
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+#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 <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/cuda.h>
+
+#include <linux/kbd_kern.h>
+#include <linux/kbd_ll.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 */
+
+unsigned char kbd_read_mask = 0; /* XXX */
+
+static void kbd_repeat(unsigned long);
+static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat };
+static int last_keycode;
+
+static void keyboard_input(unsigned char *, int, struct pt_regs *);
+static void input_keycode(int, int);
+static void leds_done(struct cuda_request *);
+
+extern struct kbd_struct kbd_table[];
+
+extern void handle_scancode(unsigned char);
+extern void put_queue(int);
+
+/* 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,
+};
+
+int mackbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+ return -EINVAL;
+}
+
+int mackbd_getkeycode(unsigned int scancode)
+{
+ return -EINVAL;
+}
+
+int mackbd_pretranslate(unsigned char scancode, char raw_mode)
+{
+ return 1;
+}
+
+int mackbd_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 mackbd_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);
+
+ 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.
+ */
+ if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK))
+ up_flag = 0;
+ }
+
+ 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);
+}
+
+static void
+mouse_input(unsigned char *data, int nb, struct pt_regs *regs)
+{
+ /* [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.
+ */
+ struct kbd_struct *kbd;
+
+ kbd = kbd_table + fg_console;
+
+ /* 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;
+ }
+ }
+ }
+}
+
+/* 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 struct cuda_request led_request;
+static int leds_pending;
+
+void mackbd_leds(unsigned char leds)
+{
+ if (led_request.got_reply) {
+ cuda_request(&led_request, leds_done, 4, ADB_PACKET,
+ ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG),
+ 0xff, ~mac_ledmap[leds]);
+ } else
+ leds_pending = leds | 0x100;
+}
+
+static void leds_done(struct cuda_request *req)
+{
+ int leds;
+
+ if (leds_pending) {
+ leds = leds_pending & 0xff;
+ leds_pending = 0;
+ mackbd_leds(leds);
+ }
+}
+
+void mackbd_init_hw(void)
+{
+ struct cuda_request req;
+
+ adb_register(ADB_KEYBOARD, keyboard_input);
+ adb_register(ADB_MOUSE, mouse_input);
+
+ /* turn on ADB auto-polling in the CUDA */
+ cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
+ while (!req.got_reply)
+ cuda_poll();
+
+ /* turn off all leds */
+ cuda_request(&req, NULL, 4, ADB_PACKET,
+ ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, 0xff);
+ while (!req.got_reply)
+ cuda_poll();
+
+ /* get the keyboard to send separate codes for
+ left and right shift, control, option keys. */
+ cuda_request(&req, NULL, 4, ADB_PACKET,
+ ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
+ while (!req.got_reply)
+ cuda_poll();
+
+ led_request.got_reply = 1;
+
+ /* Try to switch the mouse (id 3) to handler 4, for three-button
+ mode. (0x20 is Service Request Enable, 0x03 is Device ID). */
+ cuda_request(&req, NULL, 4, ADB_PACKET,
+ ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
+ while (!req.got_reply)
+ cuda_poll();
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov