
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 <adevries@thepuffingroup.com>
- *  Copyright (1999) The Puffin Group
- *  Mostly rewritten by Philipp Rumpf <prumpf@tux.org>
- *  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 <debackex@esiee.fr>
- *		Marteau Thomas <marteaut@esiee.fr>
- *		Djoudi Malek <djoudim@esiee.fr>
- * - fixed some keysym defines 
- *
- * 2001/04/28	Debacker Xavier <debackex@esiee.fr>
- * - 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
-/* tfj@olivia.ping.dk:
- * 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. [kkoller@nyx10.cs.du.edu]
- */
-#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. - aeb@cwi.nl
-	       */
-	      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 <adevries@thepuffingroup.com>
- *	Copyright 1999, 2000 Philipp Rumpf <prumpf@tux.org>
- *
- *	2000/10/26	Debacker Xavier (debackex@esiee.fr)
- *			Marteau Thomas (marteaut@esiee.fr)
- * 			Djoudi Malek (djoudim@esiee.fr)
- *	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 <canetl@esiee.fr>
+ * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
+ *
+ * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
+ * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
+ *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
+ *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
+ *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
+ *
+ * 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 <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>");
+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);
