patch-2.1.132 linux/drivers/acorn/char/keyb_ps2.c

Next file: linux/drivers/acorn/char/mouse_rpc.c
Previous file: linux/drivers/acorn/char/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c
@@ -0,0 +1,355 @@
+/*
+ * linux/arch/arm/drivers/block/keyb_ps2.c
+ *
+ * Keyboard driver for RPC ARM Linux.
+ *
+ * Note!!! This driver talks directly to the keyboard.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/kbd_ll.h>
+#include <linux/init.h>
+
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+extern void kbd_reset_kdown(void);
+int kbd_read_mask;
+
+#define IRQ_KEYBOARDRX 15
+
+#define VERSION 100
+
+#define KBD_REPORT_ERR
+#define KBD_REPORT_UNKN
+
+#define KBD_ESCAPEE0	0xe0		/* in */
+#define KBD_ESCAPEE1	0xe1		/* in */
+
+#define ESCE0(x)	(0xe000|(x))
+#define ESCE1(x)	(0xe100|(x))
+
+#define KBD_BAT		0xaa		/* in */
+#define KBD_SETLEDS	0xed		/* out */
+#define KBD_ECHO	0xee		/* in/out */
+#define KBD_BREAK	0xf0		/* in */
+#define KBD_TYPRATEDLY	0xf3		/* out */
+#define KBD_SCANENABLE	0xf4		/* out */
+#define KBD_DEFDISABLE	0xf5		/* out */
+#define KBD_DEFAULT	0xf6		/* out */
+#define KBD_ACK		0xfa		/* in */
+#define KBD_DIAGFAIL	0xfd		/* in */
+#define KBD_RESEND	0xfe		/* in/out */
+#define KBD_RESET	0xff		/* out */
+
+#define CODE_BREAK	1
+#define CODE_ESCAPEE0	2
+#define CODE_ESCAPEE1	4
+#define CODE_ESCAPE12	8
+
+#define K_NONE		0x7f
+#define K_ESC		0x00
+#define K_F1		0x01
+#define K_F2		0x02
+#define K_F3		0x03
+#define K_F4		0x04
+#define K_F5		0x05
+#define K_F6		0x06
+#define K_F7		0x07
+#define K_F8		0x08
+#define K_F9		0x09
+#define K_F10		0x0a
+#define K_F11		0x0b
+#define K_F12		0x0c
+#define K_PRNT		0x0d
+#define K_SCRL		0x0e
+#define K_BRK		0x0f
+#define K_AGR		0x10
+#define K_1		0x11
+#define K_2		0x12
+#define K_3		0x13
+#define K_4		0x14
+#define K_5		0x15
+#define K_6		0x16
+#define K_7		0x17
+#define K_8		0x18
+#define K_9		0x19
+#define K_0		0x1a
+#define K_MINS		0x1b
+#define K_EQLS		0x1c
+#define K_BKSP		0x1e
+#define K_INS		0x1f
+#define K_HOME		0x20
+#define K_PGUP		0x21
+#define K_NUML		0x22
+#define KP_SLH		0x23
+#define KP_STR		0x24
+#define KP_MNS		0x3a
+#define K_TAB		0x26
+#define K_Q		0x27
+#define K_W		0x28
+#define K_E		0x29
+#define K_R		0x2a
+#define K_T		0x2b
+#define K_Y		0x2c
+#define K_U		0x2d
+#define K_I		0x2e
+#define K_O		0x2f
+#define K_P		0x30
+#define K_LSBK		0x31
+#define K_RSBK		0x32
+#define K_ENTR		0x47
+#define K_DEL		0x34
+#define K_END		0x35
+#define K_PGDN		0x36
+#define KP_7		0x37
+#define KP_8		0x38
+#define KP_9		0x39
+#define KP_PLS		0x4b
+#define K_CAPS		0x5d
+#define K_A		0x3c
+#define K_S		0x3d
+#define K_D		0x3e
+#define K_F		0x3f
+#define K_G		0x40
+#define K_H		0x41
+#define K_J		0x42
+#define K_K		0x43
+#define K_L		0x44
+#define K_SEMI		0x45
+#define K_SQOT		0x46
+#define K_HASH		0x1d
+#define KP_4		0x48
+#define KP_5		0x49
+#define KP_6		0x4a
+#define K_LSFT		0x4c
+#define K_BSLH		0x33
+#define K_Z		0x4e
+#define K_X		0x4f
+#define K_C		0x50
+#define K_V		0x51
+#define K_B		0x52
+#define K_N		0x53
+#define K_M		0x54
+#define K_COMA		0x55
+#define K_DOT		0x56
+#define K_FSLH		0x57
+#define K_RSFT		0x58
+#define K_UP		0x59
+#define KP_1		0x5a
+#define KP_2		0x5b
+#define KP_3		0x5c
+#define KP_ENT		0x67
+#define K_LCTL		0x3b
+#define K_LALT		0x5e
+#define K_SPCE		0x5f
+#define K_RALT		0x60
+#define K_RCTL		0x61
+#define K_LEFT		0x62
+#define K_DOWN		0x63
+#define K_RGHT		0x64
+#define KP_0		0x65
+#define KP_DOT		0x66
+
+static unsigned char keycode_translate[256] =
+{
+/* 00 */  K_NONE, K_F9  , K_NONE, K_F5  , K_F3  , K_F1  , K_F2  , K_F12 ,
+/* 08 */  K_NONE, K_F10 , K_F8  , K_F6  , K_F4  , K_TAB , K_AGR , K_NONE,
+/* 10 */  K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q   , K_1   , K_NONE,
+/* 18 */  K_NONE, K_NONE, K_Z   , K_S   , K_A   , K_W   , K_2   , K_NONE,
+/* 20 */  K_NONE, K_C   , K_X   , K_D   , K_E   , K_4   , K_3   , K_NONE,
+/* 28 */  K_NONE, K_SPCE, K_V   , K_F   , K_T   , K_R   , K_5   , K_NONE,
+/* 30 */  K_NONE, K_N   , K_B   , K_H   , K_G   , K_Y   , K_6   , K_NONE,
+/* 38 */  K_NONE, K_NONE, K_M   , K_J   , K_U   , K_7   , K_8   , K_NONE,
+/* 40 */  K_NONE, K_COMA, K_K   , K_I   , K_O   , K_0   , K_9   , K_NONE,
+/* 48 */  K_NONE, K_DOT , K_FSLH, K_L   , K_SEMI, K_P   , K_MINS, K_NONE,
+/* 50 */  K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
+/* 58 */  K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_HASH, K_NONE, K_NONE,
+/* 60 */  K_NONE, K_BSLH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
+/* 68 */  K_NONE, KP_1  , K_NONE, KP_4  , KP_7  , K_NONE, K_NONE, K_NONE,
+/* 70 */  KP_0  , KP_DOT, KP_2  , KP_5  , KP_6  , KP_8  , K_ESC , K_NUML,
+/* 78 */  K_F11 , KP_PLS, KP_3  , KP_MNS, KP_STR, KP_9  , K_SCRL, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_F7  , K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE
+};
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char ps2kbd_sysrq_xlate[] = 
+{
+    27,    0,    0,    0,    0,    0,    0,    0,
+     0,    0,    0,    0,    0,    0,    0,    0,
+   '`',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+   '8',  '9',  '0',  '-',  '=',  '£',  127,    0,
+     0,    0,    0,  '/',  '*',  '#',    9,  'q',
+   'w',  'e',  'r',  't',  'y',  'u',  'i',  'o',
+   'p',  '[',  ']', '\\',  22,    23,   25,  '7',
+   '8',  '9',  '-',    0,  'a',  's',  'd',  'f',
+   'g',  'h',  'j',  'k',  'l',  ';', '\'',   13,
+   '4',  '5',  '6',  '+',    0,    0,  'z',  'x',
+   'c',  'v',  'b',  'n',  'm',  ',',  '.',  '/',
+     0,    0,  '1',  '2',  '3',    0,    0,  ' ',
+     0,    0,    0,    0,    0,  '0',  '.',   10,
+     0,    0,    0,    0,    0,    0,    0,    0,
+     0,    0,    0,    0,    0,    0,    0,    0,
+     0,    0,    0,    0,    0,    0,    0,    0,
+};
+#endif
+
+int ps2kbd_pretranslate(unsigned char scancode)
+{
+	return 1;
+}
+
+int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *uf_p)
+{
+	*uf_p = scancode & 0200;
+	*keycode_p = scancode & 0x7f;
+	return 1;
+}
+
+static void ps2kbd_key(unsigned int keycode, unsigned int up_flag)
+{
+	handle_scancode(keycode + (up_flag ? 0x80 : 0));
+}
+
+static inline void ps2kbd_sendbyte(unsigned char val)
+{
+	while(!(inb(IOMD_KCTRL) & (1 << 7)));
+	outb(val, IOMD_KARTTX);
+}
+
+static unsigned char status;
+static unsigned char ncodes;
+static unsigned char bi;
+static unsigned char buffer[4];
+
+static inline void ps2kbd_reset(void)
+{
+	status = 0;
+	kbd_reset_kdown();
+}
+
+static void handle_rawcode(int keyval)
+{
+	int keysym;
+
+	if (keyval > 0x83) {
+		switch (keyval) {
+			case KBD_ESCAPEE0:
+				ncodes = 2;
+				bi = 0;
+				break;
+			case KBD_ESCAPEE1:
+				ncodes = 3;
+				bi = 0;
+				break;
+			case KBD_BREAK:
+				status |= CODE_BREAK;
+			default:
+				return;
+		}
+	}
+
+	if (ncodes) {
+		buffer[bi++] = keyval;
+		ncodes -= 1;
+		if (ncodes)
+			return;
+		keysym = K_NONE;
+		switch (buffer[0] << 8 | buffer[1]) {
+		case ESCE0(0x11): keysym = K_RALT; break;
+		case ESCE0(0x14): keysym = K_RCTL; break;
+		case ESCE0(0x4a): keysym = KP_SLH; break;
+		case ESCE0(0x5a): keysym = KP_ENT; break;
+		case ESCE0(0x69): keysym = K_END;  break;
+		case ESCE0(0x6b): keysym = K_LEFT; break;
+		case ESCE0(0x6c): keysym = K_HOME; break;
+		case ESCE0(0x70): keysym = K_INS;  break;
+		case ESCE0(0x71): keysym = K_DEL;  break;
+		case ESCE0(0x72): keysym = K_DOWN; break;
+		case ESCE0(0x74): keysym = K_RGHT; break;
+		case ESCE0(0x75): keysym = K_UP;   break;
+		case ESCE0(0x7a): keysym = K_PGDN; break;
+		case ESCE0(0x7c): keysym = K_PRNT; break;
+		case ESCE0(0x7d): keysym = K_PGUP; break;
+		case ESCE1(0x14):
+			if (buffer[2] == 0x77)
+				keysym = K_BRK;
+			break;
+		case ESCE0(0x12):		/* ignore escaped shift key */
+			status = 0;
+			return;
+		}
+	} else {
+		bi = 0;
+		keysym = keycode_translate[keyval];
+	}
+
+	if (keysym != K_NONE)
+		ps2kbd_key(keysym, status & CODE_BREAK);
+	status = 0;
+}
+
+void ps2kbd_leds(unsigned int leds)
+{
+	ps2kbd_sendbyte(KBD_SETLEDS);
+	ps2kbd_sendbyte(leds);
+	ps2kbd_sendbyte(KBD_SCANENABLE);
+}
+
+static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs)
+{
+	kbd_pt_regs = regs;
+
+	while (inb(IOMD_KCTRL) & (1 << 5))
+		handle_rawcode(inb(IOMD_KARTRX));
+	mark_bh(KEYBOARD_BH);
+}
+
+static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+__initfunc(int ps2kbd_init_hw(void))
+{
+	unsigned long flags;
+
+	save_flags_cli (flags);
+	if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0)
+		panic("Could not allocate keyboard receive IRQ!");
+	if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0)
+		panic("Could not allocate keyboard transmit IRQ!");
+	disable_irq (IRQ_KEYBOARDTX);
+	(void)IOMD_KARTRX;
+	restore_flags (flags);
+
+	printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100);
+	return 0;
+}
+

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