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);