This patch converts the PA-RISC PS/2 keyboard & mouse driver to the
input layer. New driver written by Laurent Canet & Thibaut Varene.
diff -urpNX build-tools/dontdiff linus-2.5/arch/parisc/kernel/Makefile parisc-2.5/arch/parisc/kernel/Makefile
--- linus-2.5/arch/parisc/kernel/Makefile Tue Nov 5 11:16:58 2002
+++ parisc-2.5/arch/parisc/kernel/Makefile Fri Nov 8 06:05:52 2002
@@ -11,7 +11,7 @@ endif
AFLAGS_entry.o := -traditional
AFLAGS_pacache.o := -traditional
-export-objs := parisc_ksyms.o keyboard.o
+export-objs := parisc_ksyms.o
obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
@@ -22,7 +22,6 @@ obj-y := cache.o pacache.o setup.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PA11) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_VT) += keyboard.o
obj-$(CONFIG_PARISC64) += binfmt_elf32.o sys_parisc32.o \
ioctl32.o signal32.o
# only supported for PCX-W/U in 64-bit mode at the moment
diff -urpNX build-tools/dontdiff linus-2.5/arch/parisc/kernel/keyboard.c parisc-2.5/arch/parisc/kernel/keyboard.c
--- linus-2.5/arch/parisc/kernel/keyboard.c Mon Nov 11 12:47:37 2002
+++ parisc-2.5/arch/parisc/kernel/keyboard.c Wed Dec 31 17:00:00 1969
@@ -1,101 +0,0 @@
-/*
- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- * ---------------------------------------------------------------
- * This source file will be removed as soon as we have converted
- * hp_psaux.c and hp_keyb.c to the input layer !
- *
- */
-
-/*
- * linux/arch/parisc/kernel/keyboard.c
- *
- * Alex deVries <
[email protected]>
- * Copyright (1999) The Puffin Group
- * Mostly rewritten by Philipp Rumpf <
[email protected]>
- * Copyright 2000 Philipp Rumpf
- */
-
-#include <linux/errno.h>
-#include <linux/keyboard.h>
-#include <asm/keyboard.h>
-#include <linux/module.h>
-
-static int def_setkeycode(unsigned int x, unsigned int y)
-{
- return 0;
-}
-
-static int def_getkeycode(unsigned int x)
-{
- return 0;
-}
-
-static int def_translate(unsigned char scancode, unsigned char *keycode,
- char raw)
-{
- *keycode = scancode;
-
- return 1;
-}
-
-static char def_unexpected_up(unsigned char c)
-{
- return 128;
-}
-
-static void def_leds(unsigned char leds)
-{
-}
-
-static void def_init_hw(void)
-{
-}
-
-static char def_sysrq_xlate[NR_KEYS];
-
-#define DEFAULT_KEYB_OPS \
- .setkeycode = def_setkeycode, \
- .getkeycode = def_getkeycode, \
- .translate = def_translate, \
- .unexpected_up = def_unexpected_up, \
- .leds = def_leds, \
- .init_hw = def_init_hw, \
- .sysrq_key = 0xff, \
- .sysrq_xlate = def_sysrq_xlate,
-
-static struct kbd_ops def_kbd_ops = {
- DEFAULT_KEYB_OPS
-};
-
-struct kbd_ops *kbd_ops = &def_kbd_ops;
-
-void unregister_kbd_ops(void)
-{
- struct kbd_ops new_kbd_ops = { DEFAULT_KEYB_OPS };
- register_kbd_ops(&new_kbd_ops);
-}
-EXPORT_SYMBOL(unregister_kbd_ops);
-
-void register_kbd_ops(struct kbd_ops *ops)
-{
- if(ops->setkeycode)
- kbd_ops->setkeycode = ops->setkeycode;
-
- if(ops->getkeycode)
- kbd_ops->getkeycode = ops->getkeycode;
-
- if(ops->translate)
- kbd_ops->translate = ops->translate;
-
- if(ops->unexpected_up)
- kbd_ops->unexpected_up = ops->unexpected_up;
-
- if(ops->leds)
- kbd_ops->leds = ops->leds;
-
- if(ops->init_hw)
- kbd_ops->init_hw = ops->init_hw;
-
- kbd_ops->sysrq_key = ops->sysrq_key;
- kbd_ops->sysrq_xlate = ops->sysrq_xlate;
-}
diff -urpNX build-tools/dontdiff linus-2.5/drivers/char/hp_keyb.c parisc-2.5/drivers/char/hp_keyb.c
--- linus-2.5/drivers/char/hp_keyb.c Thu Jul 18 09:52:56 2002
+++ parisc-2.5/drivers/char/hp_keyb.c Wed Dec 31 17:00:00 1969
@@ -1,519 +0,0 @@
-/*
- * linux/drivers/char/hp_keyb.c
- * helper-functions for the keyboard/psaux driver for HP-PARISC workstations
- *
- * based on pc_keyb.c by Geert Uytterhoeven & Martin Mares
- *
- * 2000/10/26 Debacker Xavier <
[email protected]>
- * Marteau Thomas <
[email protected]>
- * Djoudi Malek <
[email protected]>
- * - fixed some keysym defines
- *
- * 2001/04/28 Debacker Xavier <
[email protected]>
- * - scancode translation rewritten in handle_at_scancode()
- */
-
-#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/slab.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>
-
-#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 0x01
-#define K_F1 0x3b
-#define K_F2 0x3c
-#define K_F3 0x3d
-#define K_F4 0x3e
-#define K_F5 0x3f
-#define K_F6 0x40
-#define K_F7 0x41
-#define K_F8 0x42
-#define K_F9 0x43
-#define K_F10 0x44
-#define K_F11 0x57
-#define K_F12 0x58
-#define K_PRNT 0x54
-#define K_SCRL 0x46
-#define K_BRK 0x77
-#define K_AGR 0x29
-#define K_1 0x02
-#define K_2 0x03
-#define K_3 0x04
-#define K_4 0x05
-#define K_5 0x06
-#define K_6 0x07
-#define K_7 0x08
-#define K_8 0x09
-#define K_9 0x0a
-#define K_0 0x0b
-#define K_MINS 0x0c
-#define K_EQLS 0x0d
-#define K_BKSP 0x0e
-#define K_INS 0x6e
-#define K_HOME 0x66
-#define K_PGUP 0x68
-#define K_NUML 0x45
-#define KP_SLH 0x62
-#define KP_STR 0x37
-#define KP_MNS 0x4a
-#define K_TAB 0x0f
-#define K_Q 0x10
-#define K_W 0x11
-#define K_E 0x12
-#define K_R 0x13
-#define K_T 0x14
-#define K_Y 0x15
-#define K_U 0x16
-#define K_I 0x17
-#define K_O 0x18
-#define K_P 0x19
-#define K_LSBK 0x1a
-#define K_RSBK 0x1b
-#define K_ENTR 0x1c
-#define K_DEL 111
-#define K_END 0x6b
-#define K_PGDN 0x6d
-#define KP_7 0x47
-#define KP_8 0x48
-#define KP_9 0x49
-#define KP_PLS 0x4e
-#define K_CAPS 0x3a
-#define K_A 0x1e
-#define K_S 0x1f
-#define K_D 0x20
-#define K_F 0x21
-#define K_G 0x22
-#define K_H 0x23
-#define K_J 0x24
-#define K_K 0x25
-#define K_L 0x26
-#define K_SEMI 0x27
-#define K_SQOT 0x28
-#define K_HASH K_NONE
-#define KP_4 0x4b
-#define KP_5 0x4c
-#define KP_6 0x4d
-#define K_LSFT 0x2a
-#define K_BSLH 0x2b
-#define K_Z 0x2c
-#define K_X 0x2d
-#define K_C 0x2e
-#define K_V 0x2f
-#define K_B 0x30
-#define K_N 0x31
-#define K_M 0x32
-#define K_COMA 0x33
-#define K_DOT 0x34
-#define K_FSLH 0x35
-#define K_RSFT 0x36
-#define K_UP 0x67
-#define KP_1 0x4f
-#define KP_2 0x50
-#define KP_3 0x51
-#define KP_ENT 0x60
-#define K_LCTL 0x1d
-#define K_LALT 0x38
-#define K_SPCE 0x39
-#define K_RALT 0x64
-#define K_RCTL 0x61
-#define K_LEFT 0x69
-#define K_DOWN 0x6c
-#define K_RGHT 0x6a
-#define KP_0 0x52
-#define KP_DOT 0x53
-
-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_BSLH, K_NONE, K_NONE,
-/* 60 */ K_NONE, K_HASH, 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_PRNT,
-/* 80 */ K_NONE, K_NONE, K_NONE, K_F7 , K_NONE, K_NONE, K_NONE, K_NONE,
-/* 88 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* 90 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* 98 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* a0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* a8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* b0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* b8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* c0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* c8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* d0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* d8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* e0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* e8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* f0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
-/* f8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, KBD_RESEND, K_NONE
-};
-
-/* ----- the following code stolen from pc_keyb.c */
-
-
-#ifdef CONFIG_MAGIC_SYSRQ
-unsigned char hp_ps2kbd_sysrq_xlate[128] =
- "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
- "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
- "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
- "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
- "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
- "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
- "\r\000/"; /* 0x60 - 0x6f */
-#endif
-
-/*
- * 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 /* 0x59 == 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
-/*
[email protected]:
- * 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. [
[email protected]]
- */
-#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 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];
-}
-
-int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode)
-{
- static int prev_scancode;
-
- /* special prefix scancodes.. */
- if (scancode == 0xe0 || scancode == 0xe1) {
- prev_scancode = scancode;
- return 0;
- }
-
- /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
- if (scancode == 0x00 || scancode == 0xff) {
- prev_scancode = 0;
- return 0;
- }
- scancode &= 0x7f;
-
- 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. -
[email protected]
- */
- 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;
-}
-
-/* ----- end of stolen part ------ */
-
-
-void kbd_reset_setup(void)
-{
-}
-
-void handle_at_scancode(int keyval)
-{
- static int brk;
- static int esc0;
- static int esc1;
- int scancode = 0;
-
- switch (keyval) {
- case KBD_BREAK :
- /* sets the "release_key" bit when a key is
- released. HP keyboard send f0 followed by
- the keycode while AT keyboard send the keycode
- with this bit set. */
- brk = 0x80;
- return;
- case KBD_ESCAPEE0 :
- /* 2chars sequence, commonly used to differenciate
- the two ALT keys and the two ENTER keys and so
- on... */
- esc0 = 2; /* e0-xx are 2 chars */
- scancode = keyval;
- break;
- case KBD_ESCAPEE1 :
- /* 3chars sequence, only used by the Pause key. */
- esc1 = 3; /* e1-xx-xx are 3 chars */
- scancode = keyval;
- break;
-#if 0
- case KBD_RESEND :
- /* dunno what to do when it happens. RFC */
- printk(KERN_INFO "keyboard: KBD_RESEND received.\n");
- return;
-#endif
- case 0x14 :
- /* translate e1-14-77-e1-f0-14-f0-77 to
- e1-1d-45-e1-9d-c5 (the Pause key) */
- if (esc1==2) scancode = brk | 0x1d;
- break;
- case 0x77 :
- if (esc1==1) scancode = brk | 0x45;
- break;
- case 0x12 :
- /* an extended key is e0-12-e0-xx e0-f0-xx-e0-f0-12
- on HP, while it is e0-2a-e0-xx e0-(xx|80)-f0-aa
- on AT. */
- if (esc0==1) scancode = brk | 0x2a;
- break;
- }
-
-
- /* translates HP scancodes to AT scancodes */
- if (!scancode) scancode = brk | keycode_translate[keyval];
-
-
- if (!scancode) printk(KERN_INFO "keyboard: unexpected key code %02x\n",keyval);
-
- /* now behave like an AT keyboard */
- handle_scancode(scancode,!(scancode&0x80));
-
- if (esc0) esc0--;
- if (esc1) esc1--;
-
- /* release key bit must be unset for the next key */
- brk = 0;
-}
-
diff -urpNX build-tools/dontdiff linus-2.5/drivers/char/hp_psaux.c parisc-2.5/drivers/char/hp_psaux.c
--- linus-2.5/drivers/char/hp_psaux.c Mon Nov 11 12:47:53 2002
+++ parisc-2.5/drivers/char/hp_psaux.c Wed Dec 31 17:00:00 1969
@@ -1,551 +0,0 @@
-/*
- * LASI PS/2 keyboard/psaux driver for HP-PARISC workstations
- *
- * (c) Copyright 1999 The Puffin Group Inc.
- * by Alex deVries <
[email protected]>
- * Copyright 1999, 2000 Philipp Rumpf <
[email protected]>
- *
- * 2000/10/26 Debacker Xavier (
[email protected])
- * Marteau Thomas (
[email protected])
- * Djoudi Malek (
[email protected])
- * fixed leds control
- * implemented the psaux and controlled the mouse scancode based on pc_keyb.c
- */
-
-#include <linux/config.h>
-
-#include <asm/hardware.h>
-#include <asm/keyboard.h>
-#include <asm/gsc.h>
-
-#include <linux/types.h>
-#include <linux/ptrace.h> /* interrupt.h wants struct pt_regs defined */
-#include <linux/interrupt.h>
-#include <linux/sched.h> /* for request_irq/free_irq */
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/pc_keyb.h>
-#include <linux/kbd_kern.h>
-
-/* mouse includes */
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-#include <linux/poll.h>
-
-/* HP specific LASI PS/2 keyboard and psaux constants */
-#define AUX_REPLY_ACK 0xFA /* Command byte ACK. */
-#define AUX_RECONNECT 0xAA /* scancode when ps2 device is plugged (back) in */
-
-#define LASI_PSAUX_OFFSET 0x0100 /* offset from keyboard to psaux port */
-
-#define LASI_ID 0x00 /* ID and reset port offsets */
-#define LASI_RESET 0x00
-#define LASI_RCVDATA 0x04 /* receive and transmit port offsets */
-#define LASI_XMTDATA 0x04
-#define LASI_CONTROL 0x08 /* see: control register bits */
-#define LASI_STATUS 0x0C /* see: status register bits */
-
-/* control register bits */
-#define LASI_CTRL_ENBL 0x01 /* enable interface */
-#define LASI_CTRL_LPBXR 0x02 /* loopback operation */
-#define LASI_CTRL_DIAG 0x20 /* directly control clock/data line */
-#define LASI_CTRL_DATDIR 0x40 /* data line direct control */
-#define LASI_CTRL_CLKDIR 0x80 /* clock line direct control */
-
-/* status register bits */
-#define LASI_STAT_RBNE 0x01
-#define LASI_STAT_TBNE 0x02
-#define LASI_STAT_TERR 0x04
-#define LASI_STAT_PERR 0x08
-#define LASI_STAT_CMPINTR 0x10
-#define LASI_STAT_DATSHD 0x40
-#define LASI_STAT_CLKSHD 0x80
-
-static void *lasikbd_hpa;
-static void *lasips2_hpa;
-
-
-static inline u8 read_input(void *hpa)
-{
- return gsc_readb(hpa+LASI_RCVDATA);
-}
-
-static inline u8 read_control(void *hpa)
-{
- return gsc_readb(hpa+LASI_CONTROL);
-}
-
-static inline void write_control(u8 val, void *hpa)
-{
- gsc_writeb(val, hpa+LASI_CONTROL);
-}
-
-static inline u8 read_status(void *hpa)
-{
- return gsc_readb(hpa+LASI_STATUS);
-}
-
-static int write_output(u8 val, void *hpa)
-{
- int wait = 0;
-
- while (read_status(hpa) & LASI_STAT_TBNE) {
- wait++;
- if (wait>10000) {
- /* printk(KERN_WARNING "Lasi PS/2 transmit buffer timeout\n"); */
- return 0;
- }
- }
-
- if (wait)
- printk(KERN_DEBUG "Lasi PS/2 wait %d\n", wait);
-
- gsc_writeb(val, hpa+LASI_XMTDATA);
-
- return 1;
-}
-
-/* This function is the PA-RISC adaptation of i386 source */
-
-static inline int aux_write_ack(u8 val)
-{
- return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET);
-}
-
-static void lasikbd_leds(unsigned char leds)
-{
- write_output(KBD_CMD_SET_LEDS, lasikbd_hpa);
- write_output(leds, lasikbd_hpa);
- write_output(KBD_CMD_ENABLE, lasikbd_hpa);
-}
-
-#if 0
-/* this might become useful again at some point. not now -prumpf */
-int lasi_ps2_test(void *hpa)
-{
- u8 control,c;
- int i, ret = 0;
-
- control = read_control(hpa);
- write_control(control | LASI_CTRL_LPBXR | LASI_CTRL_ENBL, hpa);
-
- for (i=0; i<256; i++) {
- write_output(i, hpa);
-
- while (!(read_status(hpa) & LASI_STAT_RBNE))
- /* just wait */;
-
- c = read_input(hpa);
- if (c != i)
- ret--;
- }
-
- write_control(control, hpa);
-
- return ret;
-}
-#endif
-
-static int __init lasi_ps2_reset(void *hpa, int id)
-{
- u8 control;
- int ret = 1;
-
- /* reset the interface */
- gsc_writeb(0xff, hpa+LASI_RESET);
- gsc_writeb(0x0 , hpa+LASI_RESET);
-
- /* enable it */
- control = read_control(hpa);
- write_control(control | LASI_CTRL_ENBL, hpa);
-
- /* initializes the leds at the default state */
- if (id==0) {
- write_output(KBD_CMD_SET_LEDS, hpa);
- write_output(0, hpa);
- ret = write_output(KBD_CMD_ENABLE, hpa);
- }
-
- return ret;
-}
-
-static int inited;
-
-static void lasi_ps2_init_hw(void)
-{
- ++inited;
-}
-
-
-/* Greatly inspired by pc_keyb.c */
-
-/*
- * Wait for keyboard controller input buffer to drain.
- *
- * Don't use 'jiffies' so that we don't depend on
- * interrupts..
- *
- * Quote from PS/2 System Reference Manual:
- *
- * "Address hex 0060 and address hex 0064 should be written only when
- * the input-buffer-full bit and output-buffer-full bit in the
- * Controller Status register are set 0."
- */
-#ifdef CONFIG_PSMOUSE
-
-static struct aux_queue *queue;
-static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
-static unsigned char mouse_reply_expected;
-static int aux_count;
-
-static int fasync_aux(int fd, struct file *filp, int on)
-{
- int retval;
-
- retval = fasync_helper(fd, filp, on, &queue->fasync);
- if (retval < 0)
- return retval;
-
- return 0;
-}
-
-
-
-static inline void handle_mouse_scancode(unsigned char scancode)
-{
- if (mouse_reply_expected) {
- if (scancode == AUX_REPLY_ACK) {
- mouse_reply_expected--;
- return;
- }
- mouse_reply_expected = 0;
- }
- else if (scancode == AUX_RECONNECT) {
- queue->head = queue->tail = 0; /* Flush input queue */
- return;
- }
-
- add_mouse_randomness(scancode);
- if (aux_count) {
- int head = queue->head;
-
- queue->buf[head] = scancode;
- head = (head + 1) & (AUX_BUF_SIZE-1);
-
- if (head != queue->tail) {
- queue->head = head;
- kill_fasync(&queue->fasync, SIGIO, POLL_IN);
- wake_up_interruptible(&queue->proc_list);
- }
- }
-}
-
-static inline int queue_empty(void)
-{
- return queue->head == queue->tail;
-}
-
-static unsigned char get_from_queue(void)
-{
- unsigned char result;
- unsigned long flags;
-
- spin_lock_irqsave(&kbd_controller_lock, flags);
- result = queue->buf[queue->tail];
- queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
- spin_unlock_irqrestore(&kbd_controller_lock, flags);
-
- return result;
-}
-
-
-/*
- * Write to the aux device.
- */
-
-static ssize_t write_aux(struct file * file, const char * buffer,
- size_t count, loff_t *ppos)
-{
- ssize_t retval = 0;
-
- if (count) {
- ssize_t written = 0;
-
- if (count > 32)
- count = 32; /* Limit to 32 bytes. */
- do {
- char c;
- get_user(c, buffer++);
- written++;
- } while (--count);
- retval = -EIO;
- if (written) {
- retval = written;
- file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
- }
- }
-
- return retval;
-}
-
-
-
-static ssize_t read_aux(struct file * file, char * buffer,
- size_t count, loff_t *ppos)
-{
- DECLARE_WAITQUEUE(wait, current);
- ssize_t i = count;
- unsigned char c;
-
- if (queue_empty()) {
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- add_wait_queue(&queue->proc_list, &wait);
-repeat:
- set_current_state(TASK_INTERRUPTIBLE);
- if (queue_empty() && !signal_pending(current)) {
- schedule();
- goto repeat;
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&queue->proc_list, &wait);
- }
- while (i > 0 && !queue_empty()) {
- c = get_from_queue();
- put_user(c, buffer++);
- i--;
- }
- if (count-i) {
- file->f_dentry->d_inode->i_atime = CURRENT_TIME;
- return count-i;
- }
- if (signal_pending(current))
- return -ERESTARTSYS;
- return 0;
-}
-
-
-static int open_aux(struct inode * inode, struct file * file)
-{
- if (aux_count++)
- return 0;
-
- queue->head = queue->tail = 0; /* Flush input queue */
- aux_count = 1;
- aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
-
- return 0;
-}
-
-
-/* No kernel lock held - fine */
-static unsigned int aux_poll(struct file *file, poll_table * wait)
-{
-
- poll_wait(file, &queue->proc_list, wait);
- if (!queue_empty())
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-
-static int release_aux(struct inode * inode, struct file * file)
-{
- lock_kernel();
- fasync_aux(-1, file, 0);
- if (--aux_count) {
- unlock_kernel();
- return 0;
- }
- unlock_kernel();
- return 0;
-}
-
-static struct file_operations psaux_fops = {
- .read = read_aux,
- .write = write_aux,
- .poll = aux_poll,
- .open = open_aux,
- .release = release_aux,
- .fasync = fasync_aux,
-};
-
-static struct miscdevice psaux_mouse = {
- .minor = PSMOUSE_MINOR,
- .name = "psaux",
- .fops = &psaux_fops,
-};
-
-#endif /* CONFIG_PSMOUSE */
-
-
-/* This function is looking at the PS2 controller and empty the two buffers */
-
-static u8 handle_lasikbd_event(void *hpa)
-{
- u8 status_keyb,status_mouse,scancode,id;
- extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
-
- /* Mask to get the base address of the PS/2 controller */
- id = gsc_readb(hpa+LASI_ID) & 0x0f;
-
- if (id==1)
- hpa -= LASI_PSAUX_OFFSET;
- lasikbd_hpa = hpa;
-
-
- status_keyb = read_status(hpa);
- status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
-
- while ((status_keyb|status_mouse) & LASI_STAT_RBNE){
-
- while (status_keyb & LASI_STAT_RBNE) {
-
- scancode = read_input(hpa);
-
- /* XXX don't know if this is a valid fix, but filtering
- * 0xfa avoids 'unknown scancode' errors on, eg, capslock
- * on some keyboards.
- */
- if (inited && scancode != 0xfa)
- handle_at_scancode(scancode);
-
- status_keyb =read_status(hpa);
- }
-
-#ifdef CONFIG_PSMOUSE
- while (status_mouse & LASI_STAT_RBNE) {
- scancode = read_input(hpa+LASI_PSAUX_OFFSET);
- handle_mouse_scancode(scancode);
- status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
- }
- status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
-#endif /* CONFIG_PSMOUSE */
- status_keyb = read_status(hpa);
- }
-
- tasklet_schedule(&keyboard_tasklet);
- return (status_keyb|status_mouse);
-}
-
-
-
-
-extern struct pt_regs *kbd_pt_regs;
-
-static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs)
-{
- lasips2_hpa = dev; /* save "hpa" for lasikbd_leds() */
- kbd_pt_regs = regs;
- handle_lasikbd_event(lasips2_hpa);
-}
-
-
-extern int pckbd_translate(unsigned char, unsigned char *, char);
-
-static struct kbd_ops gsc_ps2_kbd_ops = {
- .translate = pckbd_translate,
- .init_hw = lasi_ps2_init_hw,
- .leds = lasikbd_leds,
-#ifdef CONFIG_MAGIC_SYSRQ
- .sysrq_key = 0x54,
- .sysrq_xlate = hp_ps2kbd_sysrq_xlate,
-#endif
-};
-
-static int __init
-lasi_ps2_register(struct hp_device *d, struct pa_iodc_driver *dri)
-{
- void *hpa = (void *) d->hpa;
- unsigned int irq;
- char *name;
- int device_found;
- u8 id;
-
- id = gsc_readb(hpa+LASI_ID) & 0x0f;
-
- switch (id) {
- case 0:
- name = "keyboard";
- lasikbd_hpa = hpa;
- break;
- case 1:
- name = "psaux";
- break;
- default:
- printk(KERN_WARNING "%s: Unknown PS/2 port (id=%d) - ignored.\n",
- __FUNCTION__, id );
- return 0;
- }
-
- /* reset the PS/2 port */
- device_found = lasi_ps2_reset(hpa,id);
-
- /* allocate the irq and memory region for that device */
- if (!(irq = busdevice_alloc_irq(d)))
- return -ENODEV;
-
- if (request_irq(irq, lasikbd_interrupt, 0, name, hpa))
- return -ENODEV;
-
- if (!request_mem_region((unsigned long)hpa, LASI_STATUS + 4, name))
- return -ENODEV;
-
- switch (id) {
- case 0:
- register_kbd_ops(&gsc_ps2_kbd_ops);
- break;
- case 1:
-#ifdef CONFIG_PSMOUSE
- queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
- if (!queue)
- return -ENOMEM;
-
- memset(queue, 0, sizeof(*queue));
- queue->head = queue->tail = 0;
- init_waitqueue_head(&queue->proc_list);
-
- misc_register(&psaux_mouse);
-
- aux_write_ack(AUX_ENABLE_DEV);
- /* try it a second time, this will give status if the device is
- * available */
- device_found = aux_write_ack(AUX_ENABLE_DEV);
- break;
-#else
- /* return without printing any unnecessary and misleading info */
- return 0;
-#endif
- } /* of case */
-
- printk(KERN_INFO "PS/2 %s controller at 0x%08lx (irq %d) found, "
- "%sdevice attached.\n",
- name, (unsigned long)hpa, irq,
- device_found ? "":"no ");
-
- return 0;
-}
-
-
-static struct pa_iodc_driver lasi_psaux_drivers_for[] __initdata = {
- {HPHW_FIO, 0x0, 0,0x00084, 0, 0,
- DRIVER_CHECK_HWTYPE + DRIVER_CHECK_SVERSION,
- "Lasi psaux", "generic", (void *) lasi_ps2_register},
- { 0, }
-};
-
-static int __init gsc_ps2_init(void)
-{
- return pdc_register_driver(lasi_psaux_drivers_for);
-}
-
-module_init(gsc_ps2_init);
-
diff -urpNX build-tools/dontdiff linus-2.5/drivers/input/misc/Kconfig parisc-2.5/drivers/input/misc/Kconfig
--- linus-2.5/drivers/input/misc/Kconfig Thu Oct 31 10:27:26 2002
+++ parisc-2.5/drivers/input/misc/Kconfig Wed Nov 27 09:13:51 2002
@@ -56,3 +56,12 @@ config INPUT_UINPUT
The module will be called uinput.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
+config INPUT_GSC
+ tristate "PA-RISC GSC PS/2 keyboard/mouse support"
+ depends on GSC && INPUT && INPUT_MISC
+ help
+ Say Y here if you have a PS/2 keyboard and/or mouse attached
+ to your PA-RISC box. HP run the keyboard in AT mode rather than
+ XT mode like everyone else, so we need our own driver.
+ Furthermore, the GSC PS/2 controller shares IRQ between mouse and
+ keyboard.
diff -urpNX build-tools/dontdiff linus-2.5/drivers/input/misc/Makefile parisc-2.5/drivers/input/misc/Makefile
--- linus-2.5/drivers/input/misc/Makefile Fri Oct 18 08:23:04 2002
+++ parisc-2.5/drivers/input/misc/Makefile Wed Nov 27 09:13:51 2002
@@ -8,7 +8,4 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcs
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
-
-# The global Rules.make.
-
-include $(TOPDIR)/Rules.make
+obj-$(CONFIG_INPUT_GSC) += gsc_ps2.o
diff -urpNX build-tools/dontdiff linus-2.5/drivers/input/misc/gsc_ps2.c parisc-2.5/drivers/input/misc/gsc_ps2.c
--- linus-2.5/drivers/input/misc/gsc_ps2.c Wed Dec 31 17:00:00 1969
+++ parisc-2.5/drivers/input/misc/gsc_ps2.c Fri Nov 29 08:30:24 2002
@@ -0,0 +1,699 @@
+/*
+ * drivers/input/misc/gsc_ps2.c
+ *
+ * Copyright (c) 2002 Laurent Canet <
[email protected]>
+ * Copyright (c) 2002 Thibaut Varene <
[email protected]>
+ *
+ * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
+ * Copyright (c) 1999 Alex deVries <
[email protected]>
+ * Copyright (c) 1999-2000 Philipp Rumpf <
[email protected]>
+ * Copyright (c) 2000 Xavier Debacker <
[email protected]>
+ * Copyright (c) 2000-2001 Thomas Marteau <
[email protected]>
+ *
+ * HP PS/2 Keyboard, found in PA/RISC Workstations
+ * very similar to AT keyboards, but without i8042
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * STATUS:
+ * 11/09: lc: Only basic keyboard is supported, mouse still needs to be done.
+ * 11/12: tv: switching iomapping; cleaning code; improving module stuff.
+ * 11/13: lc & tv: leds aren't working. auto_repeat/meta are. Generaly good behavior.
+ * 11/15: tv: 2AM: leds ARE working !
+ * 11/16: tv: 3AM: escaped keycodes emulation *handled*, some keycodes are
+ * still deliberately ignored (18), what are they used for ?
+ * 11/21: lc: mouse is now working
+ * 11/29: tv: first try for error handling in init sequence
+ *
+ * TODO:
+ * Error handling in init sequence
+ * SysRq handling
+ * Pause key handling
+ * Intellimouse & other rodents handling (at least send an error when
+ * such a mouse is plugged : it will totally fault)
+ * Mouse: set scaling / Dino testing
+ * Bug chasing...
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ptrace.h> /* interrupt.h wants struct pt_regs defined */
+#include <linux/interrupt.h>
+#include <linux/sched.h> /* for request_irq/free_irq */
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/pc_keyb.h>
+#include <linux/ioport.h>
+#include <linux/kd.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+
+/* Debugging stuff */
+#undef KBD_DEBUG
+#ifdef KBD_DEBUG
+ #define DPRINTK(fmt,args...) printk(KERN_DEBUG __FILE__ ":" fmt, ##args)
+#else
+ #define DPRINTK(x,...)
+#endif
+
+
+/*
+ * Driver constants
+ */
+
+/* PS/2 keyboard and mouse constants */
+#define AUX_RECONNECT 0xAA /* PS/2 Mouse end of test successful */
+#define AUX_REPLY_ACK 0xFA
+
+/* Order of the mouse bytes coming to the host */
+#define PACKET_X 1
+#define PACKET_Y 2
+#define PACKET_CTRL 0
+
+#define GSC_MOUSE_OFFSET 0x0100 /* offset from keyboard to mouse port */
+#define GSC_DINO_OFFSET 0x800 /* offset for DINO controller versus LASI one */
+
+#define GSC_ID 0x00 /* ID and reset port offsets */
+#define GSC_RESET 0x00
+#define GSC_RCVDATA 0x04 /* receive and transmit port offsets */
+#define GSC_XMTDATA 0x04
+#define GSC_CONTROL 0x08 /* see: control register bits */
+#define GSC_STATUS 0x0C /* see: status register bits */
+
+/* Control register bits */
+#define GSC_CTRL_ENBL 0x01 /* enable interface */
+#define GSC_CTRL_LPBXR 0x02 /* loopback operation */
+#define GSC_CTRL_DIAG 0x20 /* directly control clock/data line */
+#define GSC_CTRL_DATDIR 0x40 /* data line direct control */
+#define GSC_CTRL_CLKDIR 0x80 /* clock line direct control */
+
+/* Status register bits */
+#define GSC_STAT_RBNE 0x01 /* Receive Buffer Not Empty */
+#define GSC_STAT_TBNE 0x02 /* Transmit Buffer Not Empty */
+#define GSC_STAT_TERR 0x04 /* Timeout Error */
+#define GSC_STAT_PERR 0x08 /* Parity Error */
+#define GSC_STAT_CMPINTR 0x10 /* Composite Interrupt */
+#define GSC_STAT_DATSHD 0x40 /* Data Line Shadow */
+#define GSC_STAT_CLKSHD 0x80 /* Clock Line Shadow */
+
+/* Keycode map */
+#define KBD_ESCAPE0 0xe0
+#define KBD_ESCAPE1 0xe1
+#define KBD_RELEASE 0xf0
+#define KBD_ACK 0xfa
+#define KBD_RESEND 0xfe
+#define KBD_UNKNOWN 0
+
+#define KBD_TBLSIZE 512
+
+/* Mouse */
+#define MOUSE_LEFTBTN 0x1
+#define MOUSE_MIDBTN 0x4
+#define MOUSE_RIGHTBTN 0x2
+#define MOUSE_ALWAYS1 0x8
+#define MOUSE_XSIGN 0x10
+#define MOUSE_YSIGN 0x20
+#define MOUSE_XOVFLOW 0x40
+#define MOUSE_YOVFLOW 0x80
+
+
+static unsigned char hpkeyb_keycode[KBD_TBLSIZE] =
+{
+ /* 00 */ KBD_UNKNOWN, KEY_F9, KBD_UNKNOWN, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12,
+ /* 08 */ KBD_UNKNOWN, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, KBD_UNKNOWN,
+ /* 10 */ KBD_UNKNOWN, KEY_LEFTALT, KEY_LEFTSHIFT, KBD_UNKNOWN, KEY_LEFTCTRL, KEY_Q, KEY_1, KBD_UNKNOWN,
+ /* 18 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KBD_UNKNOWN,
+ /* 20 */ KBD_UNKNOWN, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KBD_UNKNOWN,
+ /* 28 */ KBD_UNKNOWN, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KBD_UNKNOWN,
+ /* 30 */ KBD_UNKNOWN, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KBD_UNKNOWN,
+ /* 38 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KBD_UNKNOWN,
+ /* 40 */ KBD_UNKNOWN, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KBD_UNKNOWN,
+ /* 48 */ KBD_UNKNOWN, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KBD_UNKNOWN,
+ /* 50 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_APOSTROPHE,KBD_UNKNOWN, KEY_LEFTBRACE, KEY_EQUAL, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 58 */ KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER, KEY_RIGHTBRACE,KBD_UNKNOWN, KEY_BACKSLASH,KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 60 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KEY_BACKSPACE, KBD_UNKNOWN,
+ /* 68 */ KBD_UNKNOWN, KEY_KP1, KBD_UNKNOWN, KEY_KP4, KEY_KP7, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK,
+ /* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_103RD,
+ /* 80 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KEY_F7, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 88 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 90 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 98 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* a0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* a8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* b0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* b8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* c0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* c8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* d0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* d8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* e0 */ KBD_ESCAPE0, KBD_ESCAPE1, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* e8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* f0 */ KBD_RELEASE, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* f8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_ACK, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_RESEND, KBD_UNKNOWN,
+/* These are offset for escaped keycodes */
+ /* 00 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 08 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 10 */ KBD_UNKNOWN, KEY_RIGHTALT, KBD_UNKNOWN, KBD_UNKNOWN, KEY_RIGHTCTRL, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 18 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 20 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 28 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 30 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 38 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 40 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 48 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_KPSLASH, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 50 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 58 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_KPENTER, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 60 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 68 */ KBD_UNKNOWN, KEY_END, KBD_UNKNOWN, KEY_LEFT, KEY_HOME, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 70 */ KEY_INSERT, KEY_DELETE, KEY_DOWN, KBD_UNKNOWN, KEY_RIGHT, KEY_UP, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 78 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_PAGEDOWN, KBD_UNKNOWN, KEY_SYSRQ, KEY_PAGEUP, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 80 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 88 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 90 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* 98 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* a0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* a8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* b0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* b8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* c0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* c8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* d0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* d8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* e0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* e8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* f0 */ KBD_RELEASE, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN,
+ /* f8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN
+};
+
+
+/* Keyboard struct */
+static struct {
+ struct input_dev dev;
+ char * addr;
+ unsigned int irq;
+ unsigned int scancode;
+ unsigned int escaped;
+ unsigned int released;
+ unsigned int initialized;
+}
+hpkeyb = {
+ .escaped = 0,
+ .released = 0,
+ .initialized = 0
+};
+
+/* Mouse struct */
+static struct {
+ struct input_dev dev;
+ char * addr;
+ unsigned long irq;
+ unsigned long initialized;
+ int nbread;
+ unsigned char bytes[3];
+ unsigned long last;
+}
+hpmouse = {
+ .initialized = 0,
+ .nbread = 0
+};
+
+static spinlock_t gscps2_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * Various HW level routines
+ */
+
+#define gscps2_readb_input(x) readb(x+GSC_RCVDATA)
+#define gscps2_readb_control(x) readb(x+GSC_CONTROL)
+#define gscps2_readb_status(x) readb(x+GSC_STATUS)
+#define gscps2_writeb_control(x, y) writeb(x, y+GSC_CONTROL)
+
+static inline void gscps2_writeb_output(u8 val, char * addr)
+{
+ int wait = 250; /* Keyboard is expected to react within 250ms */
+
+ while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
+ if (!--wait)
+ return; /* This should not happen */
+ mdelay(1);
+ }
+ writeb(val, addr+GSC_XMTDATA);
+}
+
+static inline unsigned char gscps2_wait_input(char * addr)
+{
+ int wait = 250; /* Keyboard is expected to react within 250ms */
+
+ while (!(gscps2_readb_status(addr) & GSC_STAT_RBNE)) {
+ if (!--wait)
+ return 0; /* This should not happen */
+ mdelay(1);
+ }
+ return gscps2_readb_input(addr);
+}
+
+static int gscps2_writeb_safe_output(u8 val)
+{
+ /* This function waits for keyboard's ACK */
+ u8 scanread = KBD_UNKNOWN;
+ int loop = 5;
+
+ while (hpkeyb_keycode[scanread]!=KBD_ACK && --loop > 0) {
+ gscps2_writeb_output(val, hpkeyb.addr);
+ mdelay(5);
+ scanread = gscps2_wait_input(hpkeyb.addr);
+ }
+
+ if (loop <= 0)
+ return -1;
+
+ return 0;
+}
+
+/* Reset the PS2 port */
+static void __init gscps2_reset(char * addr)
+{
+ /* reset the interface */
+ writeb(0xff, addr+GSC_RESET);
+ writeb(0x0 , addr+GSC_RESET);
+
+ /* enable it */
+ gscps2_writeb_control(gscps2_readb_control(addr) | GSC_CTRL_ENBL, addr);
+}
+
+
+/**
+ * gscps2_kbd_docode() - PS2 Keyboard basic handler
+ *
+ * Receives a keyboard scancode, analyses it and sends it to the input layer.
+ */
+
+static void gscps2_kbd_docode(void)
+{
+ int scancode = gscps2_readb_input(hpkeyb.addr);
+ DPRINTK("rel=%d scancode=%d, esc=%d ", hpkeyb.released, scancode, hpkeyb.escaped);
+
+ /* Handle previously escaped scancodes */
+ if (hpkeyb.escaped == KBD_ESCAPE0)
+ scancode |= 0x100; /* jump to the next 256 chars of the table */
+
+ switch (hpkeyb_keycode[scancode]) {
+ case KBD_RELEASE:
+ DPRINTK("release\n");
+ hpkeyb.released = 1;
+ break;
+ case KBD_RESEND:
+ DPRINTK("resend request\n");
+ break;
+ case KBD_ACK:
+ DPRINTK("ACK\n");
+ break;
+ case KBD_ESCAPE0:
+ case KBD_ESCAPE1:
+ DPRINTK("escape code %d\n", hpkeyb_keycode[scancode]);
+ hpkeyb.escaped = hpkeyb_keycode[scancode];
+ break;
+ case KBD_UNKNOWN:
+ DPRINTK("received unknown scancode %d, escape %d.\n",
+ scancode, hpkeyb.escaped); /* This is a DPRINTK atm since we do not handle escaped scancodes cleanly */
+ if (hpkeyb.escaped)
+ hpkeyb.escaped = 0;
+ if (hpkeyb.released)
+ hpkeyb.released = 0;
+ return;
+ default:
+ hpkeyb.scancode = scancode;
+ DPRINTK("sent=%d, rel=%d\n",hpkeyb.scancode, hpkeyb.released);
+ input_report_key(&hpkeyb.dev, hpkeyb_keycode[hpkeyb.scancode], !hpkeyb.released);
+ input_sync(&hpkeyb.dev);
+ if (hpkeyb.escaped)
+ hpkeyb.escaped = 0;
+ if (hpkeyb.released)
+ hpkeyb.released = 0;
+ break;
+ }
+}
+
+
+/**
+ * gscps2_mouse_docode() - PS2 Mouse basic handler
+ *
+ * Receives mouse codes, processes them by packets of three, and sends
+ * correct events to the input layer.
+ */
+
+static void gscps2_mouse_docode(void)
+{
+ int xrel, yrel;
+
+ /* process BAT (end of basic tests) command */
+ if ((hpmouse.nbread == 1) && (hpmouse.bytes[0] == AUX_RECONNECT))
+ hpmouse.nbread--;
+
+ /* stolen from psmouse.c */
+ if (hpmouse.nbread && time_after(jiffies, hpmouse.last + HZ/20)) {
+ printk(KERN_DEBUG "%s:%d : Lost mouse synchronization, throwing %d bytes away.\n", __FILE__, __LINE__,
+ hpmouse.nbread);
+ hpmouse.nbread = 0;
+ }
+
+ hpmouse.last = jiffies;
+ hpmouse.bytes[hpmouse.nbread++] = gscps2_readb_input(hpmouse.addr);
+
+ /* process packet */
+ if (hpmouse.nbread == 3) {
+
+ if (!(hpmouse.bytes[PACKET_CTRL] & MOUSE_ALWAYS1))
+ DPRINTK("Mouse: error on packet always1 bit checking\n");
+ /* XXX should exit now, bad data on the line! */
+
+ if ((hpmouse.bytes[PACKET_CTRL] & (MOUSE_XOVFLOW | MOUSE_YOVFLOW)))
+ DPRINTK("Mouse: position overflow\n");
+
+ input_report_key(&hpmouse.dev, BTN_LEFT, hpmouse.bytes[PACKET_CTRL] & MOUSE_LEFTBTN);
+ input_report_key(&hpmouse.dev, BTN_MIDDLE, hpmouse.bytes[PACKET_CTRL] & MOUSE_MIDBTN);
+ input_report_key(&hpmouse.dev, BTN_RIGHT, hpmouse.bytes[PACKET_CTRL] & MOUSE_RIGHTBTN);
+
+ xrel = hpmouse.bytes[PACKET_X];
+ yrel = hpmouse.bytes[PACKET_Y];
+
+ /* Data sent by mouse are 9-bit signed, the sign bit is in the control packet */
+ if (xrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_XSIGN))
+ xrel = xrel - 0x100;
+ if (yrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_YSIGN))
+ yrel = yrel - 0x100;
+
+ input_report_rel(&hpmouse.dev, REL_X, xrel);
+ input_report_rel(&hpmouse.dev, REL_Y, -yrel); /* Y axis is received upside-down */
+
+ input_sync(&hpmouse.dev);
+
+ hpmouse.nbread = 0;
+ }
+}
+
+
+/**
+ * gscps2_interrupt() - Interruption service routine
+ *
+ * This processes the list of scancodes queued and sends appropriate
+ * key value to the system.
+ */
+
+static void gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
+{
+ /* process mouse actions */
+ while (gscps2_readb_status(hpmouse.addr) & GSC_STAT_RBNE)
+ gscps2_mouse_docode();
+
+ /* process keyboard scancode */
+ while (gscps2_readb_status(hpkeyb.addr) & GSC_STAT_RBNE)
+ gscps2_kbd_docode();
+}
+
+
+/**
+ * gscps2_hpkeyb_event() - Event handler
+ * @return: success/error report
+ *
+ * Currently only updates leds on keyboard
+ */
+
+int gscps2_hpkeyb_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ DPRINTK("Calling %s, type=%d, code=%d, value=%d\n",
+ __FUNCTION__, type, code, value);
+
+ if (!hpkeyb.initialized)
+ return -1;
+
+ if (type == EV_LED) {
+ u8 leds[2];
+
+ if (gscps2_writeb_safe_output(KBD_CMD_SET_LEDS)) {
+ printk(KERN_ERR "gsckbd_leds: timeout\n");
+ return -1;
+ }
+ DPRINTK("KBD_CMD_SET_LEDS\n");
+
+ *leds = (test_bit(LED_SCROLLL, dev->led) ? LED_SCR : 0)
+ | (test_bit(LED_NUML, dev->led) ? LED_NUM : 0)
+ | (test_bit(LED_CAPSL, dev->led) ? LED_CAP : 0);
+ DPRINTK("Sending leds=%x\n", *leds);
+
+ if (gscps2_writeb_safe_output(*leds)) {
+ printk(KERN_ERR "gsckbd_leds: timeout\n");
+ return -1;
+ }
+ DPRINTK("leds sent\n");
+
+ if (gscps2_writeb_safe_output(KBD_CMD_ENABLE)) {
+ printk(KERN_ERR "gsckbd_leds: timeout\n");
+ return -1;
+ }
+ DPRINTK("End\n");
+
+ return 0;
+
+ }
+ return -1;
+}
+
+
+/**
+ * gscps2_kbd_probe() - Probes keyboard device and init input_dev structure
+ * @return: number of device initialized (1, 0 on error)
+ */
+
+static int __init gscps2_kbd_probe(void)
+{
+ int i, res = 0;
+ unsigned long flags;
+
+ if (hpkeyb.initialized) {
+ printk(KERN_ERR "GSC PS/2 keyboard driver already registered\n");
+ return 0;
+ }
+
+ spin_lock_irqsave(&gscps2_lock, flags);
+
+ if (!gscps2_writeb_safe_output(KBD_CMD_SET_LEDS) &&
+ !gscps2_writeb_safe_output(0) &&
+ !gscps2_writeb_safe_output(KBD_CMD_ENABLE))
+ res = 1;
+
+ spin_unlock_irqrestore(&gscps2_lock, flags);
+
+ if (!res)
+ printk(KERN_ERR "Keyboard initialization sequence failled\n");
+
+ init_input_dev(&hpkeyb.dev);
+
+ for (i = 0; i < KBD_TBLSIZE; i++)
+ if (hpkeyb_keycode[i] != KBD_UNKNOWN)
+ set_bit(hpkeyb_keycode[i], hpkeyb.dev.keybit);
+
+ hpkeyb.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+ hpkeyb.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ hpkeyb.dev.keycode = hpkeyb_keycode;
+ hpkeyb.dev.keycodesize = sizeof(unsigned char);
+ hpkeyb.dev.keycodemax = KBD_TBLSIZE;
+ hpkeyb.dev.name = "GSC Keyboard";
+ hpkeyb.dev.phys = "hpkbd/input0";
+
+ hpkeyb.dev.event = gscps2_hpkeyb_event;
+
+ /* TODO These need some adjustement, are they really useful ? */
+ hpkeyb.dev.id.bustype = BUS_GSC;
+ hpkeyb.dev.id.vendor = 0x0001;
+ hpkeyb.dev.id.product = 0x0001;
+ hpkeyb.dev.id.version = 0x0010;
+ hpkeyb.initialized = 1;
+
+ return 1;
+}
+
+
+/**
+ * gscps2_mouse_probe() - Probes mouse device and init input_dev structure
+ * @return: number of device initialized (1, 0 on error)
+ *
+ * Currently no check on initialization is performed
+ */
+
+static int __init gscps2_mouse_probe(void)
+{
+ if (hpmouse.initialized) {
+ printk(KERN_ERR "GSC PS/2 Mouse driver already registered\n");
+ return 0;
+ }
+
+ init_input_dev(&hpmouse.dev);
+
+ hpmouse.dev.name = "GSC Mouse";
+ hpmouse.dev.phys = "hpmouse/input0";
+ hpmouse.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ hpmouse.dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ hpmouse.dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ hpmouse.last = 0;
+
+ gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr);
+ /* Try it a second time, this will give status if the device is available */
+ gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr);
+
+ /* TODO These need some adjustement, are they really useful ? */
+ hpmouse.dev.id.bustype = BUS_GSC;
+ hpmouse.dev.id.vendor = 0x0001;
+ hpmouse.dev.id.product = 0x0001;
+ hpmouse.dev.id.version = 0x0010;
+ hpmouse.initialized = 1;
+ return 1; /* XXX: we don't check if initialization failed */
+}
+
+
+/**
+ * gscps2_probe() - Probes PS2 devices
+ * @return: success/error report
+ */
+
+static int __init gscps2_probe(struct parisc_device *dev)
+{
+ u8 id;
+ char *addr, *name;
+ int ret, device_found = 0;
+ unsigned long hpa = dev->hpa;
+
+ if (!dev->irq)
+ goto fail_pitifully;
+
+ /* Offset for DINO PS/2. Works with LASI even */
+ if (dev->id.sversion == 0x96)
+ hpa += GSC_DINO_OFFSET;
+
+ addr = ioremap(hpa, 256);
+
+ if (!hpmouse.initialized || !hpkeyb.initialized)
+ gscps2_reset(addr);
+
+ ret = -EINVAL;
+ id = readb(addr+GSC_ID) & 0x0f;
+ switch (id) {
+ case 0: /* keyboard */
+ hpkeyb.addr = addr;
+ name = "keyboard";
+ device_found = gscps2_kbd_probe();
+ break;
+ case 1: /* mouse */
+ hpmouse.addr = addr;
+ name = "mouse";
+ device_found = gscps2_mouse_probe();
+ break;
+ default:
+ printk(KERN_WARNING "%s: Unsupported PS/2 port (id=%d) ignored\n",
+ __FUNCTION__, id);
+ goto fail_miserably;
+ }
+
+ /* No valid device found */
+ ret = -ENODEV;
+ if (!device_found)
+ goto fail_miserably;
+
+ /* Here we claim only if we have a device attached */
+ /* Allocate the irq and memory region for that device */
+ ret = -EBUSY;
+ if (request_irq(dev->irq, gscps2_interrupt, 0, name, NULL))
+ goto fail_miserably;
+
+ if (!request_mem_region(hpa, GSC_STATUS + 4, name))
+ goto fail_request_mem;
+
+ /* Finalize input struct and register it */
+ switch (id) {
+ case 0: /* keyboard */
+ hpkeyb.irq = dev->irq;
+ input_register_device(&hpkeyb.dev);
+ break;
+ case 1: /* mouse */
+ hpmouse.irq = dev->irq;
+ input_register_device(&hpmouse.dev);
+ break;
+ default:
+ break;
+ }
+
+ printk(KERN_INFO "input: PS/2 %s port at 0x%08lx (irq %d) found and attached\n",
+ name, hpa, dev->irq);
+
+ return 0;
+
+fail_request_mem: free_irq(dev->irq, NULL);
+fail_miserably: iounmap(addr);
+fail_pitifully: return ret;
+}
+
+
+
+static struct parisc_device_id gscps2_device_tbl[] = {
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
+/* { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, DINO PS/2 (XXX Not yet tested) */
+ { 0, } /* 0 terminated list */
+};
+
+static struct parisc_driver gscps2_driver = {
+ .name = "GSC PS2",
+ .id_table = gscps2_device_tbl,
+ .probe = gscps2_probe,
+};
+
+static int __init gscps2_init(void)
+{
+ if (register_parisc_driver(&gscps2_driver))
+ return -EBUSY;
+ return 0;
+}
+
+static void __exit gscps2_exit(void)
+{
+ /* TODO this is probably not very good and needs to be checked */
+ if (hpkeyb.initialized) {
+ free_irq(hpkeyb.irq, gscps2_interrupt);
+ iounmap(hpkeyb.addr);
+ hpkeyb.initialized = 0;
+ input_unregister_device(&hpkeyb.dev);
+ }
+ if (hpmouse.initialized) {
+ free_irq(hpmouse.irq, gscps2_interrupt);
+ iounmap(hpmouse.addr);
+ hpmouse.initialized = 0;
+ input_unregister_device(&hpmouse.dev);
+ }
+ unregister_parisc_driver(&gscps2_driver);
+}
+
+
+MODULE_AUTHOR("Laurent Canet <
[email protected]>, Thibaut Varene <
[email protected]>");
+MODULE_DESCRIPTION("GSC PS/2 keyboard/mouse driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
+
+
+module_init(gscps2_init);
+module_exit(gscps2_exit);