diff -u --recursive --new-file v1.1.53/linux/Makefile linux/Makefile
--- v1.1.53/linux/Makefile	Tue Oct 11 09:29:17 1994
+++ linux/Makefile	Tue Oct 11 08:47:39 1994
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 53
+SUBLEVEL = 54
 
 ARCH = i386
 
diff -u --recursive --new-file v1.1.53/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.1.53/linux/arch/i386/config.in	Fri Sep  9 05:33:47 1994
+++ linux/arch/i386/config.in	Tue Oct 11 09:46:01 1994
@@ -11,6 +11,7 @@
 bool 'Networking support' CONFIG_NET y
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
 bool 'System V IPC' CONFIG_SYSVIPC y
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
 bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y
 
 if [ "$CONFIG_NET" = "y" ]; then
diff -u --recursive --new-file v1.1.53/linux/drivers/block/cdu31a.c linux/drivers/block/cdu31a.c
--- v1.1.53/linux/drivers/block/cdu31a.c	Fri Aug 26 14:44:36 1994
+++ linux/drivers/block/cdu31a.c	Thu Oct 13 13:43:12 1994
@@ -1135,7 +1135,7 @@
    unsigned int dev;
    int nsect;
    unsigned char params[10];
-   unsigned char res_reg[2];
+   unsigned char res_reg[12];
    unsigned int res_size;
    int copyoff;
    int spin_up_retry;
@@ -1263,6 +1263,14 @@
              * next block to read.
              */
             copyoff = (block - sony_first_block) * 512;
+            /*
+             * Bugfix: get_data calls handle_sony_cd_attention
+             *         there the buffer may be declared invalid
+             *         if the CD ist changed by setting sony_first_block = -1
+             *         This would cause a segfault in memcpy
+             */ 
+            if(sony_first_block <0) goto cdu31a_request_startover;
+ 
             memcpy(CURRENT->buffer, sony_buffer+copyoff, 512);
                
             block += 1;
diff -u --recursive --new-file v1.1.53/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.1.53/linux/drivers/block/floppy.c	Sun Oct  9 12:00:23 1994
+++ linux/drivers/block/floppy.c	Mon Oct 10 18:59:31 1994
@@ -1745,6 +1745,7 @@
 	raw_cmd.track = format_req.track << floppy->stretch;
 	buffer_track = -1;
 	setup_format_params();
+	clear_bit(current_drive, &changed_floppies);
 	floppy_start();
 #ifdef DEBUGT
 	debugt("queue format request");
diff -u --recursive --new-file v1.1.53/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v1.1.53/linux/drivers/block/hd.c	Sun Oct  9 12:00:24 1994
+++ linux/drivers/block/hd.c	Fri Oct 14 10:44:36 1994
@@ -132,6 +132,45 @@
 	NR_HD = hdind+1;
 }
 
+static void dump_status (char *msg, unsigned int stat)
+{
+	unsigned long flags;
+	char dev;
+
+	dev  = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?';
+	save_flags (flags);
+	sti();
+	printk("hd%c: %s: status=0x%02x { ", dev, msg, stat & 0xff);
+	if (stat & BUSY_STAT)	printk("Busy ");
+	if (stat & READY_STAT)	printk("DriveReady ");
+	if (stat & WRERR_STAT)	printk("WriteFault ");
+	if (stat & SEEK_STAT)	printk("SeekComplete ");
+	if (stat & DRQ_STAT)	printk("DataRequest ");
+	if (stat & ECC_STAT)	printk("CorrectedError ");
+	if (stat & INDEX_STAT)	printk("Index ");
+	if (stat & ERR_STAT)	printk("Error ");
+	printk("}\n");
+	if (stat & ERR_STAT) {
+		unsigned int err = inb(HD_ERROR);
+		printk("hd%c: %s: error=0x%02x { ", dev, msg, err & 0xff);
+		if (err & BBD_ERR)	printk("BadSector ");
+		if (err & ECC_ERR)	printk("UncorrectableError ");
+		if (err & ID_ERR)	printk("SectorIdNotFound ");
+		if (err & ABRT_ERR)	printk("DriveStatusError ");
+		if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
+		if (err & MARK_ERR)	printk("AddrMarkNotFound ");
+		printk("}");
+		if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
+			if (CURRENT)
+				printk(", sector=%ld", CURRENT->sector);
+			printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
+				inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
+		}
+		printk("\n");
+	}
+	restore_flags (flags);
+}
+
 static int win_result(void)
 {
 	int i=inb_p(HD_STATUS);
@@ -141,11 +180,7 @@
 	        hd_error = 0;
 		return 0; /* ok */
 	}
-	printk("HD: win_result: status = 0x%02x\n",i);
-	if (i&1) {
-		hd_error = inb(HD_ERROR);
-		printk("HD: win_result: error = 0x%02x\n",hd_error);
-	}	
+	dump_status("win_result", i);
 	return 1;
 }
 
@@ -280,7 +315,7 @@
 	if (unmask_intr[dev])
 		sti();
 	if (stat & (BUSY_STAT|ERR_STAT)) {
-		printk ("  hd%c: non-IDE device, CHS=%d%d%d\n", dev+'a',
+		printk ("  hd%c: non-IDE device, CHS=%d/%d/%d\n", dev+'a',
 			hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
 		if (id != NULL) {
 			hd_ident_info[dev] = NULL;
@@ -331,7 +366,7 @@
 		sti();
 	if (stat & (BUSY_STAT|ERR_STAT)) {
 		mult_req[dev] = mult_count[dev] = 0;
-		printk ("  hd%c: set multiple mode failed\n", dev+'a');
+		dump_status("set multiple mode failed", stat);
 	} else {
 		if ((mult_count[dev] = mult_req[dev]))
 			printk ("  hd%c: enabled %d-sector multiple mode\n",
@@ -357,7 +392,7 @@
 		if (c == (READY_STAT | SEEK_STAT))
 			return 0;
 	}
-	printk("HD controller times out, status = 0x%02x\n",c);
+	dump_status("reset timed out", c);
 	return 1;
 }
 
@@ -409,16 +444,24 @@
 		hd_request();
 }
 
+
 /*
  * Ok, don't know what to do with the unexpected interrupts: on some machines
  * doing a reset and a retry seems to result in an eternal loop. Right now I
  * ignore it, and just set the timeout.
+ *
+ * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
+ * drive enters "idle", "standby", or "sleep" mode, so if the status looks
+ * "good", we just ignore the interrupt completely.
  */
 void unexpected_hd_interrupt(void)
 {
-	sti();
-	printk(KERN_DEBUG "Unexpected HD interrupt\n");
-	SET_TIMER;
+	unsigned int stat = inb_p(HD_STATUS);
+
+	if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
+		dump_status ("unexpected interrupt", stat);
+		SET_TIMER;
+	}
 }
 
 /*
@@ -445,11 +488,12 @@
 
 static inline int wait_DRQ(void)
 {
-	int retries = 100000;
+	int retries = 100000, stat;
 
 	while (--retries > 0)
-		if (inb_p(HD_STATUS) & DRQ_STAT)
+		if ((stat = inb_p(HD_STATUS)) & DRQ_STAT)
 			return 0;
+	dump_status("wait_DRQ", stat);
 	return -1;
 }
 
@@ -472,14 +516,8 @@
 		if (i & DRQ_STAT)
 			goto ok_to_read;
 	} while (--retries > 0);
-	sti();
-	printk("hd%c: read_intr: status = 0x%02x\n",dev+'a',i);
-	if (i & ERR_STAT) {
-		hd_error = (unsigned) inb(HD_ERROR);
-		printk("hd%c: read_intr: error = 0x%02x\n",dev+'a',hd_error);
-	}
+	dump_status("read_intr", i);
 	bad_rw_intr();
-	cli();
 	hd_request();
 	return;
 ok_to_read:
@@ -565,14 +603,8 @@
 			}
 		}
 	}
-	sti();
-	printk("hd%c: multwrite_intr: status = 0x%02x\n",dev+'a',i);
-	if (i & ERR_STAT) {
-		hd_error = (unsigned) inb(HD_ERROR);
-		printk("hd:%c multwrite_intr: error = 0x%02x\n",dev+'a',hd_error);
-	}
+	dump_status("multwrite_intr", i);
 	bad_rw_intr();
-	cli();
 	hd_request();
 }
 
@@ -592,14 +624,8 @@
 		if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
 			goto ok_to_write;
 	} while (--retries > 0);
-	sti();
-	printk("HD: write_intr: status = 0x%02x\n",i);
-	if (i & ERR_STAT) {
-		hd_error = (unsigned) inb(HD_ERROR);
-		printk("HD: write_intr: error = 0x%02x\n",hd_error);
-	}
+	dump_status("write_intr", i);
 	bad_rw_intr();
-	cli();
 	hd_request();
 	return;
 ok_to_write:
@@ -644,13 +670,13 @@
 		return;
 	reset = 1;
 	printk(KERN_DEBUG "HD timeout\n");
-	cli();
 	if (++CURRENT->errors >= MAX_ERRORS) {
 #ifdef DEBUG
 		printk("hd : too many errors.\n");
 #endif
 		end_request(0);
 	}
+	cli();
 
 	hd_request();
 }
@@ -763,7 +789,6 @@
 			CURRENT->sector+nsect-1, (long) CURRENT->buffer);
 #endif
 		if (wait_DRQ()) {
-			printk("hd%c: hd_request: no DRQ\n", dev+'a');
 			bad_rw_intr();
 			goto repeat;
 		}
diff -u --recursive --new-file v1.1.53/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.1.53/linux/drivers/char/ChangeLog	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/ChangeLog	Tue Oct 11 09:21:13 1994
@@ -0,0 +1,84 @@
+Sun Oct  9 23:46:03 1994  Theodore Y. Ts'o  (tytso@rt-11)
+
+	* tty_io.c (do_tty_hangup): If the tty driver flags
+		TTY_DRIVER_RESET_TERMIOS is set, then reset the termios
+		settings back to the driver's initial configuration.  This
+		allows the termios settings to be reset even if a process
+		has hung up file descriptors keeping a pty's termios from
+		being freed and reset.
+
+	* tty_io.c (release_dev): Fix memory leak.  The pty's other
+		termios structure should also be freed.
+
+	* serial.c (rs_close, shutdown): Change how we wait for the
+		transmitter to completely drain before shutting down the
+		serial port.  We now do it by scheduling in another
+		process instead of busy looping with the interrupts turned
+		on.  This may eliminate some race condition problems that
+		some people seem to be reporting.
+
+Sun Sep 25 14:18:14 1994  Theodore Y. Ts'o  (tytso@rt-11)
+
+	* tty_io.c (release_dev): When freeing a tty make sure that both
+		the tty and the o_tty (if present) aren't a process's
+		controlling tty.  (Previously, we only checked the tty.)
+
+	* serial.c (change_speed): Only enable the Modem Status
+		Interrupt for a port if CLOCAL is not set or CRTSCTS
+		is set.  If we're not checking the carrier detect and
+		CTS line, there's no point in enabling the modem
+		status interrupt.  This will save spurious interrupts
+		from slowing down systems who have terminals that
+		don't support either line.  (Of course, if you want
+		only one of CD and CTS support, you will need a
+		properly wired serial cable.)
+
+Thu Sep 22 08:32:48 1994  Theodore Y. Ts'o  (tytso@rt-11)
+
+	* tty_io.c (do_SAK): Return if tty is null.
+
+	* tty_io.c (_tty_name): Return "NULL tty" if the passed in tty is
+		NULL.
+
+Sat Sep 17 13:19:25 1994  Theodore Y. Ts'o  (tytso@rt-11)
+
+	* tty_ioctl.c (n_tty_ioctl): Fix TIOCGLCKTRMIOS and
+		TIOCSLCKTRMIOS, which were totally broken.  Remove
+		extra indirection from argument; it should be a struct
+		termios *, not a struct termios **.
+		&real_tty->termios_locked should have been
+		real_tty->termios_locked.  This caused us to be
+		reading and writing the termios_locked structure to
+		random places in kernel memory.  
+
+	* tty_io.c (release_dev): Oops!  Forgot to delete a critical kfree
+		of the locked_termios.  This leaves the locked_termios
+		structure pointed at a freed object.  
+
+Fri Sep 16 08:13:25 1994  Theodore Y. Ts'o  (tytso@rt-11)
+
+	* tty_io.c (tty_open): Don't check for an exclusive open until
+		after the device specific open routine has been called.
+		Otherwise, the serial device ref counting will be screwed
+		up.
+
+	* serial.c (rs_open, block_til_ready): Don't set termios structure
+		until after block_til_ready has returned successfully.
+		Modify block_til_ready to check the normal_termios
+		structure directly, so it doesn't rely on termios being
+		set before its called.
+
+Thu Sep 15 23:34:01 1994  Theodore Y. Ts'o  (tytso@rt-11)
+
+	* serial.c (rs_close): Turn off interrupts during rs_close() to
+		prevent a race condition with the hangup code (which
+		runs during a software interrupt).
+
+	* tty_io.c (release_dev): Don't free the locked_termios structure;
+		its state must be retained across device opens.
+
+
+	* tty_io.c (tty_unregister_driver): Added function to unregister a
+		tty driver.  (For loadable device drivers.)
+
+
diff -u --recursive --new-file v1.1.53/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v1.1.53/linux/drivers/char/Makefile	Tue Aug  9 17:20:30 1994
+++ linux/drivers/char/Makefile	Thu Oct 13 14:07:03 1994
@@ -18,11 +18,11 @@
 
 OBJS  = tty_io.o n_tty.o console.o keyboard.o serial.o \
 	tty_ioctl.o pty.o vt.o mem.o \
-	defkeymap.o
+	defkeymap.o uni_to_437.o
 
 SRCS  = tty_io.c n_tty.c console.c keyboard.c serial.c \
 	tty_ioctl.c pty.c vt.c mem.c \
-	defkeymap.c
+	defkeymap.c uni_to_437.c
 
 
 ifdef CONFIG_ATIXL_BUSMOUSE
diff -u --recursive --new-file v1.1.53/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.53/linux/drivers/char/console.c	Tue Oct 11 09:29:17 1994
+++ linux/drivers/char/console.c	Thu Oct 13 14:07:05 1994
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/console.c
+ *  linux/drivers/char/console.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
@@ -9,16 +9,35 @@
  *
  * This module exports the console io functions:
  * 
- *	'long con_init(long)'
- *	'int con_open(struct tty_struct *tty, struct file * filp)'
- * 	'void update_screen(int new_console)'
- * 	'void blank_screen(void)'
- * 	'void unblank_screen(void)'
+ *     'void do_keyboard_interrupt(void)'
  *
- *      'int  con_get_font(char *)' 
- *      'int  con_set_font(char *)' 
- *      'int  con_get_trans(char *)'
- *      'int  con_set_trans(char *)'
+ *     'int vc_allocate(unsigned int console)' 
+ *     'int vc_cons_allocated(unsigned int console)'
+ *     'int vc_resize(unsigned long lines, unsigned long cols)'
+ *     'void vc_disallocate(unsigned int currcons)'
+ *
+ *     'long con_init(long)'
+ *     'int con_open(struct tty_struct *tty, struct file * filp)'
+ *     'void con_write(struct tty_struct * tty)'
+ *     'void console_print(const char * b)'
+ *     'void update_screen(int new_console)'
+ *
+ *     'void blank_screen(void)'
+ *     'void unblank_screen(void)'
+ *     'void poke_blanked_console(void)'
+ *     'void scrollback(int lines)'
+ *     'void scrollfront(int lines)'
+ *     'int do_screendump(int arg)'
+ *
+ *     'int con_get_font(char *)' 
+ *     'int con_set_font(char *)' 
+ *     'int con_get_trans(char *)'
+ *     'int con_set_trans(char *)'
+ *
+ *     'int set_selection(const int arg)'
+ *     'int paste_selection(struct tty_struct *tty)'
+ *     'int sel_loadlut(const int arg)'
+ *     'int mouse_reporting(void)'
  * 
  * Hopefully this will be a rather complete VT102 implementation.
  *
@@ -35,11 +54,18 @@
  * Code to check for different video-cards mostly by Galen Hunt,
  * <g-hunt@ee.utah.edu>
  *
+ * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
+ * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
+ *
+ * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
+ * Resizing of consoles, aeb, 940926
+ *
  * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
  * <poe@daimi.aau.dk>
  *
  */
 
+#define BLANK 0x0020
 #define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
 
 /*
@@ -59,6 +85,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kd.h>
+#include <linux/malloc.h>
 #include <linux/major.h>
 
 #include <asm/io.h>
@@ -75,9 +102,9 @@
 
 struct tty_driver console_driver;
 static int console_refcount;
-static struct tty_struct *console_table[NR_CONSOLES];
-static struct termios *console_termios[NR_CONSOLES];
-static struct termios *console_termios_locked[NR_CONSOLES];
+static struct tty_struct *console_table[MAX_NR_CONSOLES];
+static struct termios *console_termios[MAX_NR_CONSOLES];
+static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 
 #ifdef CONFIG_SELECTION
 #include <linux/ctype.h>
@@ -90,7 +117,7 @@
 
 /* Variables for selection control. */
 #define SEL_BUFFER_SIZE 4096
-static int sel_cons;
+static int sel_cons = 0;
 static int sel_start = -1;
 static int sel_end;
 static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
@@ -98,24 +125,44 @@
 
 #define NPAR 16
 
+static void con_setsize(unsigned long rows, unsigned long cols);
+static void vc_init(unsigned int console, unsigned long rows, unsigned long cols,
+		    int do_clear);
+static void get_scrmem(int currcons);
+static void set_scrmem(int currcons, long offset);
+static void set_origin(int currcons);
+static void gotoxy(int currcons, int new_x, int new_y);
+static void save_cur(int currcons);
+static inline void set_cursor(int currcons);
+static void reset_terminal(int currcons, int do_clear);
+extern void reset_vc(unsigned int new_console);
 extern void vt_init(void);
 extern void register_console(void (*proc)(const char *));
 extern void compute_shiftstate(void);
-
-unsigned long	video_num_columns;		/* Number of text columns	*/
-unsigned long	video_num_lines;		/* Number of text lines		*/
+extern int conv_uni_to_pc(unsigned long ucs);
 
+/* Description of the hardware situation */
 static unsigned char	video_type;		/* Type of display being used	*/
 static unsigned long	video_mem_base;		/* Base of video memory		*/
 static unsigned long	video_mem_term;		/* End of video memory		*/
-static unsigned long	video_size_row;		/* Bytes per row		*/
-static unsigned char	video_page;		/* Initial video page		*/
+static unsigned char	video_page;		/* Initial video page (unused)  */
 static unsigned short	video_port_reg;		/* Video register select port	*/
 static unsigned short	video_port_val;		/* Video register value port	*/
+static unsigned long	video_num_columns;	/* Number of text columns	*/
+static unsigned long	video_num_lines;	/* Number of text lines		*/
+static unsigned long	video_size_row;
+static unsigned long	video_screen_size;
 static int can_do_color = 0;
-static int printable = 0;
+static int printable = 0;			/* Is console ready for printing? */
+
+static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
+
+static int console_blanked = 0;
+static int blankinterval = 10*60*HZ;
+static long blank_origin, blank__origin, unblank_origin;
 
-static struct {
+struct vc_data {
+	unsigned long	vc_screenbuf_size;
 	unsigned short	vc_video_erase_char;	/* Background erase character */
 	unsigned char	vc_attr;		/* Current attributes */
 	unsigned char	vc_def_color;		/* Default colors */
@@ -144,6 +191,7 @@
 	unsigned long	vc_decawm	: 1;	/* Autowrap Mode */
 	unsigned long	vc_deccm	: 1;	/* Cursor Visible */
 	unsigned long	vc_decim	: 1;	/* Insert Mode */
+	unsigned long	vc_deccolm	: 1;	/* 80/132 Column Mode */
 	/* attribute flags */
 	unsigned long	vc_intensity	: 2;	/* 0=half-bright, 1=normal, 2=bold */
 	unsigned long	vc_underline	: 1;
@@ -156,7 +204,12 @@
 	/* misc */
 	unsigned long	vc_ques		: 1;
 	unsigned long	vc_need_wrap	: 1;
+	unsigned long	vc_has_scrolled : 1;	/* Info for unblank_screen */
+	unsigned long	vc_kmalloced	: 1;	/* kfree_s() needed */
 	unsigned long	vc_report_mouse : 2;
+	unsigned char	vc_utf		: 1;	/* Unicode UTF-8 encoding */
+	unsigned char	vc_utf_count;
+	unsigned long	vc_utf_char;
 	unsigned long	vc_tab_stop[5];		/* Tab stops. 160 columns. */
 	unsigned char * vc_translate;
 	unsigned char *	vc_G0_charset;
@@ -164,65 +217,237 @@
 	unsigned char *	vc_saved_G0;
 	unsigned char *	vc_saved_G1;
 	/* additional information is in vt_kern.h */
-} vc_cons [NR_CONSOLES];
+};
 
-unsigned short *vc_scrbuf[NR_CONSOLES];
-static unsigned short * vc_scrmembuf;
-static int console_blanked = 0;
+static struct vc {
+	struct vc_data *d;
 
-#define origin		(vc_cons[currcons].vc_origin)
-#define scr_end		(vc_cons[currcons].vc_scr_end)
-#define pos		(vc_cons[currcons].vc_pos)
-#define top		(vc_cons[currcons].vc_top)
-#define bottom		(vc_cons[currcons].vc_bottom)
-#define x		(vc_cons[currcons].vc_x)
-#define y		(vc_cons[currcons].vc_y)
-#define vc_state		(vc_cons[currcons].vc_state)
-#define npar		(vc_cons[currcons].vc_npar)
-#define par		(vc_cons[currcons].vc_par)
-#define ques		(vc_cons[currcons].vc_ques)
-#define attr		(vc_cons[currcons].vc_attr)
-#define saved_x		(vc_cons[currcons].vc_saved_x)
-#define saved_y		(vc_cons[currcons].vc_saved_y)
-#define translate	(vc_cons[currcons].vc_translate)
-#define G0_charset	(vc_cons[currcons].vc_G0_charset)
-#define G1_charset	(vc_cons[currcons].vc_G1_charset)
-#define saved_G0	(vc_cons[currcons].vc_saved_G0)
-#define saved_G1	(vc_cons[currcons].vc_saved_G1)
-#define video_mem_start	(vc_cons[currcons].vc_video_mem_start)
-#define video_mem_end	(vc_cons[currcons].vc_video_mem_end)
-#define video_erase_char (vc_cons[currcons].vc_video_erase_char)	
-#define disp_ctrl	(vc_cons[currcons].vc_disp_ctrl)
-#define toggle_meta	(vc_cons[currcons].vc_toggle_meta)
-#define decscnm		(vc_cons[currcons].vc_decscnm)
-#define decom		(vc_cons[currcons].vc_decom)
-#define decawm		(vc_cons[currcons].vc_decawm)
-#define deccm		(vc_cons[currcons].vc_deccm)
-#define decim		(vc_cons[currcons].vc_decim)
-#define need_wrap	(vc_cons[currcons].vc_need_wrap)
-#define report_mouse	(vc_cons[currcons].vc_report_mouse)
-#define color		(vc_cons[currcons].vc_color)
-#define s_color		(vc_cons[currcons].vc_s_color)
-#define def_color	(vc_cons[currcons].vc_def_color)
+	/* might add  scrmem, vt_struct, kbd  at some time,
+	   to have everything in one place - the disadvantage
+	   would be that vc_cons etc can no longer be static */
+} vc_cons [MAX_NR_CONSOLES];
+
+#define screenbuf_size	(vc_cons[currcons].d->vc_screenbuf_size)
+#define origin		(vc_cons[currcons].d->vc_origin)
+#define scr_end		(vc_cons[currcons].d->vc_scr_end)
+#define pos		(vc_cons[currcons].d->vc_pos)
+#define top		(vc_cons[currcons].d->vc_top)
+#define bottom		(vc_cons[currcons].d->vc_bottom)
+#define x		(vc_cons[currcons].d->vc_x)
+#define y		(vc_cons[currcons].d->vc_y)
+#define vc_state	(vc_cons[currcons].d->vc_state)
+#define npar		(vc_cons[currcons].d->vc_npar)
+#define par		(vc_cons[currcons].d->vc_par)
+#define ques		(vc_cons[currcons].d->vc_ques)
+#define attr		(vc_cons[currcons].d->vc_attr)
+#define saved_x		(vc_cons[currcons].d->vc_saved_x)
+#define saved_y		(vc_cons[currcons].d->vc_saved_y)
+#define translate	(vc_cons[currcons].d->vc_translate)
+#define G0_charset	(vc_cons[currcons].d->vc_G0_charset)
+#define G1_charset	(vc_cons[currcons].d->vc_G1_charset)
+#define saved_G0	(vc_cons[currcons].d->vc_saved_G0)
+#define saved_G1	(vc_cons[currcons].d->vc_saved_G1)
+#define utf		(vc_cons[currcons].d->vc_utf)
+#define utf_count	(vc_cons[currcons].d->vc_utf_count)
+#define utf_char	(vc_cons[currcons].d->vc_utf_char)
+#define video_mem_start	(vc_cons[currcons].d->vc_video_mem_start)
+#define video_mem_end	(vc_cons[currcons].d->vc_video_mem_end)
+#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)	
+#define disp_ctrl	(vc_cons[currcons].d->vc_disp_ctrl)
+#define toggle_meta	(vc_cons[currcons].d->vc_toggle_meta)
+#define decscnm		(vc_cons[currcons].d->vc_decscnm)
+#define decom		(vc_cons[currcons].d->vc_decom)
+#define decawm		(vc_cons[currcons].d->vc_decawm)
+#define deccm		(vc_cons[currcons].d->vc_deccm)
+#define decim		(vc_cons[currcons].d->vc_decim)
+#define deccolm	 	(vc_cons[currcons].d->vc_deccolm)
+#define need_wrap	(vc_cons[currcons].d->vc_need_wrap)
+#define has_scrolled	(vc_cons[currcons].d->vc_has_scrolled)
+#define kmalloced	(vc_cons[currcons].d->vc_kmalloced)
+#define report_mouse	(vc_cons[currcons].d->vc_report_mouse)
+#define color		(vc_cons[currcons].d->vc_color)
+#define s_color		(vc_cons[currcons].d->vc_s_color)
+#define def_color	(vc_cons[currcons].d->vc_def_color)
 #define	foreground	(color & 0x0f)
 #define background	(color & 0xf0)
-#define charset		(vc_cons[currcons].vc_charset)
-#define s_charset	(vc_cons[currcons].vc_s_charset)
-#define	intensity	(vc_cons[currcons].vc_intensity)
-#define	underline	(vc_cons[currcons].vc_underline)
-#define	blink		(vc_cons[currcons].vc_blink)
-#define	reverse		(vc_cons[currcons].vc_reverse)
-#define	s_intensity	(vc_cons[currcons].vc_s_intensity)
-#define	s_underline	(vc_cons[currcons].vc_s_underline)
-#define	s_blink		(vc_cons[currcons].vc_s_blink)
-#define	s_reverse	(vc_cons[currcons].vc_s_reverse)
-#define	ulcolor		(vc_cons[currcons].vc_ulcolor)
-#define	halfcolor	(vc_cons[currcons].vc_halfcolor)
-#define tab_stop	(vc_cons[currcons].vc_tab_stop)
-#define vcmode		(vt_cons[currcons].vc_mode)
-#define vtmode		(vt_cons[currcons].vt_mode)
-#define vtpid		(vt_cons[currcons].vt_pid)
-#define vtnewvt		(vt_cons[currcons].vt_newvt)
+#define charset		(vc_cons[currcons].d->vc_charset)
+#define s_charset	(vc_cons[currcons].d->vc_s_charset)
+#define	intensity	(vc_cons[currcons].d->vc_intensity)
+#define	underline	(vc_cons[currcons].d->vc_underline)
+#define	blink		(vc_cons[currcons].d->vc_blink)
+#define	reverse		(vc_cons[currcons].d->vc_reverse)
+#define	s_intensity	(vc_cons[currcons].d->vc_s_intensity)
+#define	s_underline	(vc_cons[currcons].d->vc_s_underline)
+#define	s_blink		(vc_cons[currcons].d->vc_s_blink)
+#define	s_reverse	(vc_cons[currcons].d->vc_s_reverse)
+#define	ulcolor		(vc_cons[currcons].d->vc_ulcolor)
+#define	halfcolor	(vc_cons[currcons].d->vc_halfcolor)
+#define tab_stop	(vc_cons[currcons].d->vc_tab_stop)
+
+#define vcmode		(vt_cons[currcons]->vc_mode)
+#define structsize	(sizeof(struct vc_data) + sizeof(struct vt_struct))
+
+static void * memsetw(void * s, unsigned short c, unsigned int count)
+{
+__asm__("cld\n\t"
+	"rep\n\t"
+	"stosw"
+	: /* no output */
+	:"a" (c),"D" (s),"c" (count/2)
+	:"cx","di");
+return s;
+}
+
+int vc_cons_allocated(unsigned int i)
+{
+	return (i < MAX_NR_CONSOLES && vc_cons[i].d);
+}
+
+int vc_allocate(unsigned int i)		/* return 0 on success */
+{
+	if (i >= MAX_NR_CONSOLES)
+	  return -ENODEV;
+	if (!vc_cons[i].d) {
+	    long p, q;
+
+	    /* prevent users from taking too much memory */
+	    if (i >= MAX_NR_USER_CONSOLES && !suser())
+	      return -EPERM;
+
+	    /* due to the granularity of kmalloc, we waste some memory here */
+	    /* the alloc is done in two steps, to optimize the common situation
+	       of a 25x80 console (structsize=216, video_screen_size=4000) */
+	    q = (long) kmalloc(video_screen_size, GFP_KERNEL);
+	    if (!q)
+	      return -ENOMEM;
+	    p = (long) kmalloc(structsize, GFP_KERNEL);
+	    if (!p) {
+		kfree_s((char *) q, video_screen_size);
+		return -ENOMEM;
+	    }
+
+	    vc_cons[i].d = (struct vc_data *) p;
+	    p += sizeof(struct vc_data);
+	    vt_cons[i] = (struct vt_struct *) p;
+	    vc_scrbuf[i] = (unsigned short *) q;
+	    vc_cons[i].d->vc_kmalloced = 1;
+	    vc_cons[i].d->vc_screenbuf_size = video_screen_size;
+	    vc_init (i, video_num_lines, video_num_columns, 1);
+	}
+	return 0;
+}
+
+/*
+ * Change # of rows and columns (0 means unchanged)
+ * [this is to be used together with some user program
+ * like resize that changes the hardware videomode]
+ */
+int vc_resize(unsigned long lines, unsigned long cols)
+{
+	unsigned long cc, ll, ss, sr;
+	unsigned long occ, oll, oss, osr;
+	unsigned short *p;
+	unsigned int currcons, i;
+	unsigned short *newscreens[MAX_NR_CONSOLES];
+	long ol, nl, rlth, rrem;
+
+	cc = (cols ? cols : video_num_columns);
+	ll = (lines ? lines : video_num_lines);
+	sr = cc << 1;
+	ss = sr * ll;
+
+	if (ss > video_mem_term - video_mem_base)
+	  return -ENOMEM;
+
+	/*
+	 * Some earlier version had all consoles of potentially
+	 * different sizes, but that was really messy.
+	 * So now we only change if there is room for all consoles
+	 * of the same size.
+	 */
+	for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
+	    if (!vc_cons_allocated(currcons))
+	      newscreens[currcons] = 0;
+	    else {
+		p = (unsigned short *) kmalloc(ss, GFP_USER);
+		if (!p) {
+		    for (i = 0; i< currcons; i++)
+		      if (newscreens[i])
+			kfree_s(newscreens[i], ss);
+		    return -ENOMEM;
+		}
+		newscreens[currcons] = p;
+	    }
+	}
+
+	get_scrmem(fg_console);
+
+	oll = video_num_lines;
+	occ = video_num_columns;
+	osr = video_size_row;
+	oss = video_screen_size;
+
+	video_num_lines = ll;
+	video_num_columns = cc;
+	video_size_row = sr;
+	video_screen_size = ss;
+
+	for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
+	    if (!vc_cons_allocated(currcons))
+	      continue;
+
+	    rlth = MIN(osr, sr);
+	    rrem = sr - rlth;
+	    ol = origin;
+	    nl = (long) newscreens[currcons];
+	    if (ll < oll)
+	      ol += (oll - ll) * osr;
+
+	    while (ol < scr_end) {
+		memcpy((void *) nl, (void *) ol, rlth);
+		if (rrem)
+		  memsetw((void *)(nl + rlth), video_erase_char, rrem);
+		ol += osr;
+		nl += sr;
+	    }
+
+	    if (kmalloced)
+	      kfree_s(vc_scrbuf[currcons], screenbuf_size);
+	    vc_scrbuf[currcons] = newscreens[currcons];
+	    kmalloced = 1;
+	    screenbuf_size = ss;
+
+	    origin = video_mem_start = (long) vc_scrbuf[currcons];
+	    scr_end = video_mem_end = video_mem_start + ss;
+
+	    if (scr_end > nl)
+	      memsetw((void *) nl, video_erase_char, scr_end - nl);
+
+	    /* do part of a reset_terminal() */
+	    top = 0;
+	    bottom = video_num_lines;
+	    gotoxy(currcons, x, y);
+	    save_cur(currcons);
+	}
+
+	set_scrmem(fg_console, 0);
+	set_origin(fg_console);
+	set_cursor(fg_console);
+
+	return 0;
+}
+
+void vc_disallocate(unsigned int currcons)
+{
+	if (vc_cons_allocated(currcons)) {
+	    if (kmalloced)
+	      kfree_s(vc_scrbuf[currcons], screenbuf_size);
+	    if (currcons >= MIN_NR_CONSOLES)
+	      kfree_s(vc_cons[currcons].d, structsize);
+	    vc_cons[currcons].d = 0;
+	}
+}
+
 
 #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
 #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
@@ -231,12 +456,8 @@
 #define decarm		VC_REPEAT
 #define decckm		VC_CKMODE
 #define kbdapplic	VC_APPLIC
-#define kbdraw		VC_RAW
 #define lnm		VC_CRLF
 
-int blankinterval = 10*60*HZ;
-static int screen_size = 0;
-
 /*
  * this is what the terminal answers to a ESC-Z or csi0c query.
  */
@@ -357,7 +578,7 @@
  * *Very* limited hardware scrollback support..
  */
 static unsigned short __real_origin;
-static unsigned short __origin;
+static unsigned short __origin;		/* offset of currently displayed screen */
 
 static inline void __set_origin(unsigned short offset)
 {
@@ -427,7 +648,7 @@
 	if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 		return;
 	if (__real_origin != __origin)
-		set_origin(__real_origin);
+		__set_origin(__real_origin);
 	save_flags(flags); cli();
 	if (deccm) {
 		outb_p(14, video_port_reg);
@@ -469,6 +690,7 @@
 			scr_end -= origin-video_mem_start;
 			pos -= origin-video_mem_start;
 			origin = video_mem_start;
+			has_scrolled = 1;
 		} else {
 			__asm__("cld\n\t"
 				"rep\n\t"
@@ -514,6 +736,7 @@
 		"D" (origin+video_size_row*b-4),
 		"S" (origin+video_size_row*(b-1)-4)
 		:"ax","cx","di","si");
+	has_scrolled = 1;
 }
 
 static void lf(int currcons)
@@ -555,16 +778,7 @@
 
 static inline void del(int currcons)
 {
-#if 0
-	if (x) {
-		if (!need_wrap) {    /* this is not the right condition */
-		        pos -= 2;
-			x--;
-		}
-		*(unsigned short *)pos = video_erase_char;
-		need_wrap = 0;
-	}
-#endif
+	/* ignored */
 }
 
 static void csi_J(int currcons, int vpar)
@@ -629,13 +843,13 @@
 	need_wrap = 0;
 }
 
-static void csi_X(int currcons, int vpar)
-{
+static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
+{					  /* not vt100? */
 	long count;
 	long start;
 
 	if (!vpar)
-	        vpar++;
+		vpar++;
 
 	start=pos;
 	count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
@@ -650,9 +864,6 @@
 	need_wrap = 0;
 }
 
-/*
- *  I hope this works. The monochrome part is untested.
- */
 static void update_attr(int currcons)
 {
 	attr = color;
@@ -847,8 +1058,12 @@
 					clr_kbd(decckm);
 				break;
 			case 3:	/* 80/132 mode switch unimplemented */
-				csi_J(currcons,2);
-				gotoxy(currcons,0,0);
+				deccolm = on_off;
+#if 0
+				(void) vc_resize(video_num_lines, deccolm ? 132 : 80);
+				/* this alone does not suffice; some user mode
+				   utility has to change the hardware regs */
+#endif
 				break;
 			case 5:			/* Inverted screen on/off */
 				if (decscnm != on_off) {
@@ -1032,13 +1247,13 @@
 }
 
 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
-	EShash, ESsetG0, ESsetG1, ESignore };
+	EShash, ESsetG0, ESsetG1, ESpercent, ESignore };
 
 static void reset_terminal(int currcons, int do_clear)
 {
 	top		= 0;
 	bottom		= video_num_lines;
-	vc_state		= ESnormal;
+	vc_state	= ESnormal;
 	ques		= 0;
 	translate	= NORM_TRANS;
 	G0_charset	= NORM_TRANS;
@@ -1046,6 +1261,8 @@
 	charset		= 0;
 	need_wrap	= 0;
 	report_mouse	= 0;
+	utf             = 0;
+	utf_count       = 0;
 
 	disp_ctrl	= 0;
 	toggle_meta	= 0;
@@ -1061,7 +1278,8 @@
 	clr_kbd(kbdapplic);
 	clr_kbd(lnm);
 	kbd_table[currcons].lockstate = 0;
-	kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
+	kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
+	kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
 	set_leds();
 
 	default_attr(currcons);
@@ -1073,11 +1291,10 @@
 	tab_stop[3]	=
 	tab_stop[4]	= 0x01010101;
 
-	if (do_clear) {
-		gotoxy(currcons,0,0);
-		csi_J(currcons,2);
-		save_cur(currcons);
-	}
+	gotoxy(currcons,0,0);
+	save_cur(currcons);
+	if (do_clear)
+	    csi_J(currcons,2);
 }
 
 /*
@@ -1089,7 +1306,7 @@
 	if (!tty)
 		return;
 	console_num = MINOR(tty->device) - (tty->driver.minor_start);
-	if (console_num < 0 || console_num >= NR_CONSOLES)
+	if (!vc_cons_allocated(console_num))
 		return;
 	set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
 	set_leds();
@@ -1104,7 +1321,7 @@
 	if (!tty)
 		return;
 	console_num = MINOR(tty->device) - (tty->driver.minor_start);
-	if (console_num < 0 || console_num >= NR_CONSOLES)
+	if (!vc_cons_allocated(console_num))
 		return;
 	clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
 	set_leds();
@@ -1113,14 +1330,19 @@
 static int con_write(struct tty_struct * tty, int from_user,
 		     unsigned char *buf, int count)
 {
-	int c, n = 0;
+	int c, tc, ok, n = 0;
 	unsigned int currcons;
 	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 
 	currcons = vt->vc_num;
-	if (currcons >= NR_CONSOLES) {
-		printk("con_write: illegal vc index (%d)\n", currcons);
-		return 0;
+	if (!vc_cons_allocated(currcons)) {
+	    /* could this happen? */
+	    static int error = 0;
+	    if (!error) {
+		error = 1;
+		printk("con_write: tty %d not allocated\n", currcons+1);
+	    }
+	    return 0;
 	}
 #ifdef CONFIG_SELECTION
 	/* clear the selection */
@@ -1131,19 +1353,63 @@
 	while (!tty->stopped &&	count) {
 		c = from_user ? get_fs_byte(buf) : *buf;
 		buf++; n++; count--;
-		if (vc_state == ESnormal
-		&& (c >= 32 || (disp_ctrl && (c&0x7f) != 27))
-		&& (toggle_meta ? translate[c|0x80] : translate[c])) {
-			if (toggle_meta)
-				c |= 0x80;
+
+		if (utf) {
+		    /* Combine UTF-8 into Unicode */
+		    /* Incomplete characters silently ignored */
+		    if(c > 0x7f) {   
+			/* UTF-8 to Latin-1 decoding */
+			if (utf_count > 0 && (c & 0xc0) == 0x80) {
+				utf_char = (utf_char << 6) | (c & 0x3f);
+				utf_count--;
+				if (utf_count == 0)
+				    c = utf_char;
+				else continue;
+			} else {
+				if ((c & 0xe0) == 0xc0) {
+				    utf_count = 1;
+				    utf_char = (c & 0x1f);
+				} else if ((c & 0xf0) == 0xe0) {
+				    utf_count = 2;
+				    utf_char = (c & 0x0f);
+				} else
+				    utf_count = 0;
+				continue;
+			}
+		    } else
+			utf_count = 0;
+
+		    /* Now try to find out how to display it */
+		    if (c > 0xff) {
+			tc = conv_uni_to_pc(c);
+			if (tc == -2)
+			  continue;
+			vc_state = ESnormal;
+			if (tc == -1)
+			  tc = 0376; 	/* small square: symbol not found */
+			ok = 1;
+		    } else {
+			tc = NORM_TRANS[c];
+			ok = 0;
+		    }
+		} else {	/* no utf */
+		    tc = translate[toggle_meta ? (c|0x80) : c];
+		    ok = 0;
+		}
+
+		/* Can print ibm (even if 0), and latin1 provided
+		   it is a printing char or control chars are printed ^@ */
+		if (!ok && tc && (c >= 32 || (disp_ctrl && (c&0x7f) != 27)))
+		    ok = 1;
+
+		if (vc_state == ESnormal && ok) {
 			if (need_wrap) {
 				cr(currcons);
 				lf(currcons);
 			}
 			if (decim)
 				insert_char(currcons);
-			c = translate[c];
-			*(unsigned short *) pos = (attr << 8) + c;
+			*(unsigned short *) pos = (attr << 8) + tc;
 			if (x == video_num_columns - 1)
 				need_wrap = decawm;
 			else {
@@ -1208,6 +1474,9 @@
 				  case '[':
 					vc_state = ESsquare;
 					continue;
+				  case '%':
+					vc_state = ESpercent;
+					continue;
 				  case 'E':
 					cr(currcons);
 					lf(currcons);
@@ -1363,6 +1632,12 @@
 					case 'm':
 						csi_m(currcons);
 						continue;
+					case 'q': /* DECLL - but only 3 leds */
+						/* map 0,1,2,3 to 0,1,2,4 */
+						if (par[0] < 4)
+						  setledstate(kbd_table + currcons,
+							      (par[0] < 3) ? par[0] : 4);
+						continue;
 					case 'r':
 						if (!par[0])
 							par[0]++;
@@ -1393,6 +1668,21 @@
 						continue;
 				}
 				continue;
+			case ESpercent:
+				vc_state = ESnormal;
+				switch (c) {
+				  case '@':  /* defined in ISO 2022 */
+					utf = 0;
+					continue;
+				  case '8':
+					/* ISO/ECMA hasn't yet registered an
+					   official ESC sequence for UTF-8,
+					   so this one (ESC %8) will likely
+					   change in the future. */
+					utf = 1;
+					continue;
+				}
+				continue;
 			case ESfunckey:
 				vc_state = ESnormal;
 				continue;
@@ -1458,7 +1748,7 @@
 void poke_blanked_console(void)
 {
 	timer_active &= ~(1<<BLANK_TIMER);
-	if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
+	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
 		return;
 	if (console_blanked) {
 		timer_table[BLANK_TIMER].expires = 0;
@@ -1469,24 +1759,20 @@
 	}
 }
 
-void * memsetw(void * s, unsigned short c, unsigned int count)
-{
-__asm__("cld\n\t"
-	"rep\n\t"
-	"stosw"
-	: /* no output */
-	:"a" (c),"D" (s),"c" (count/2)
-	:"cx","di");
-return s;
-}
-
 void console_print(const char * b)
 {
 	int currcons = fg_console;
 	unsigned char c;
 
-	if (!printable || currcons<0 || currcons>=NR_CONSOLES)
+	if (!printable)
+		return;	 /* console not yet initialized */
+
+	if (!vc_cons_allocated(currcons)) {
+		/* impossible */
+		printk("console_print: tty %d not allocated ??\n", currcons+1);
 		return;
+	}
+
 	while ((c = *(b++)) != 0) {
 		if (c == 10 || c == 13 || need_wrap) {
 			if (c != 13)
@@ -1504,7 +1790,7 @@
 		pos+=2;
 	}
 	set_cursor(currcons);
-	if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
+	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
 		return;
 	timer_active &= ~(1<<BLANK_TIMER);
 	if (console_blanked) {
@@ -1532,6 +1818,34 @@
 	wake_up_interruptible(&vt->paste_wait);
 }
 
+static void vc_init(unsigned int currcons, unsigned long rows, unsigned long cols, int do_clear)
+{
+	long base = (long) vc_scrbuf[currcons];
+
+	video_num_columns = cols;
+	video_num_lines = rows;
+	video_size_row = cols<<1;
+	video_screen_size = video_num_lines * video_size_row;
+
+	pos = origin = video_mem_start = base;
+	scr_end = base + video_screen_size;
+	video_mem_end = base + video_screen_size;
+	reset_vc(currcons);
+	def_color       = 0x07;   /* white */
+	ulcolor		= 0x0f;   /* bold white */
+	halfcolor       = 0x08;   /* grey */
+	vt_cons[currcons]->paste_wait = 0;
+	reset_terminal(currcons, do_clear);
+}
+
+static void con_setsize(unsigned long rows, unsigned long cols)
+{
+	video_num_lines = rows;
+	video_num_columns = cols;
+	video_size_row = 2 * cols;
+	video_screen_size = video_num_lines * video_size_row;
+}
+
 /*
  *  long con_init(long);
  *
@@ -1546,7 +1860,6 @@
 {
 	char *display_desc = "????";
 	int currcons = 0;
-	long base;
 	int orig_x = ORIG_X;
 	int orig_y = ORIG_Y;
 
@@ -1556,7 +1869,7 @@
 	console_driver.name_base = 1;
 	console_driver.major = TTY_MAJOR;
 	console_driver.minor_start = 1;
-	console_driver.num = NR_CONSOLES;
+	console_driver.num = MAX_NR_CONSOLES;
 	console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
 	console_driver.init_termios = tty_std_termios;
 	console_driver.flags = TTY_DRIVER_REAL_RAW;
@@ -1578,13 +1891,9 @@
 	if (tty_register_driver(&console_driver))
 		panic("Couldn't register console driver\n");
 	
-	vc_scrmembuf = (unsigned short *) kmem_start;
-	video_num_columns = ORIG_VIDEO_COLS;
-	video_size_row = video_num_columns * 2;
-	video_num_lines = ORIG_VIDEO_LINES;
-	video_page = ORIG_VIDEO_PAGE;
-	screen_size = (video_num_lines * video_size_row);
-	kmem_start += NR_CONSOLES * screen_size;
+	con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS);
+	video_page = ORIG_VIDEO_PAGE; 			/* never used */
+
 	timer_table[BLANK_TIMER].fn = blank_screen;
 	timer_table[BLANK_TIMER].expires = 0;
 	if (blankinterval) {
@@ -1632,64 +1941,46 @@
 	
 	/* Initialize the variables used for scrolling (mostly EGA/VGA)	*/
 
-	base = (long)vc_scrmembuf;
-	for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
-		pos = origin = video_mem_start = base;
-		scr_end = video_mem_end = (base += screen_size);
-		vc_scrbuf[currcons] = (unsigned short *) origin;
-		vcmode		= KD_TEXT;
-		vtmode.mode	= VT_AUTO;
-		vtmode.waitv	= 0;
-		vtmode.relsig	= 0;
-		vtmode.acqsig	= 0;
-		vtmode.frsig	= 0;
-		vtpid		= -1;
-		vtnewvt		= -1;
-		clr_kbd(kbdraw);
-		def_color	= 0x07;   /* white */
-		ulcolor		= 0x0f;   /* bold white */
-		halfcolor	= 0x08;   /* grey */
-		vt_cons[currcons].paste_wait = 0;
-		reset_terminal(currcons, currcons);
+	/* Due to kmalloc roundup allocating statically is more efficient -
+	   so provide MIN_NR_CONSOLES for people with very little memory */
+	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
+		vc_cons[currcons].d = (struct vc_data *) kmem_start;
+		kmem_start += sizeof(struct vc_data);
+		vt_cons[currcons] = (struct vt_struct *) kmem_start;
+		kmem_start += sizeof(struct vt_struct);
+		vc_scrbuf[currcons] = (unsigned short *) kmem_start;
+		kmem_start += video_screen_size;
+		kmalloced = 0;
+		screenbuf_size = video_screen_size;
+		vc_init(currcons, video_num_lines, video_num_columns, currcons);
 	}
+
 	currcons = fg_console = 0;
 
 	video_mem_start = video_mem_base;
 	video_mem_end = video_mem_term;
 	origin = video_mem_start;
 	scr_end	= video_mem_start + video_num_lines * video_size_row;
-	gotoxy(currcons,0,0);
-	save_cur(currcons);
 	gotoxy(currcons,orig_x,orig_y);
-	update_screen(fg_console);
 	printable = 1;
-	printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
-		can_do_color?"colour":"mono",
+	printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
+		can_do_color ? "colour" : "mono",
 		display_desc,
 		video_num_columns,video_num_lines,
-		NR_CONSOLES);
+		MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
 	register_console(console_print);
 	return kmem_start;
 }
 
-/*
- * kbdsave doesn't need to do anything: it's all handled automatically
- * with the new data structures..
- */
-void kbdsave(int new_console)
-{
-}
-
 static void get_scrmem(int currcons)
 {
-	memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
-	video_mem_start = (unsigned long)vc_scrbuf[currcons];
-	origin 	= video_mem_start;
-	scr_end = video_mem_end = video_mem_start+screen_size;
+	memcpy((void *)vc_scrbuf[currcons], (void *)origin, video_screen_size);
+	origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
+	scr_end = video_mem_end = video_mem_start + video_screen_size;
 	pos = origin + y*video_size_row + (x<<1);
 }
 
-static void set_scrmem(int currcons)
+static void set_scrmem(int currcons, long offset)
 {
 #ifdef CONFIG_HGA
   /* This works with XFree86 1.2, 1.3 and 2.0
@@ -1722,38 +2013,77 @@
 	  }
 #endif CONFIG_HGA
 
+	if (video_mem_term - video_mem_base < offset + video_screen_size)
+	  offset = 0;	/* strange ... */
+	memcpy((void *)(video_mem_base + offset), (void *) origin, video_screen_size);
 	video_mem_start = video_mem_base;
 	video_mem_end = video_mem_term;
-	origin	= video_mem_start;
-	scr_end	= video_mem_start + screen_size;
+	origin = video_mem_base + offset;
+	scr_end = origin + video_screen_size;
 	pos = origin + y*video_size_row + (x<<1);
-	memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
 }
 
 void blank_screen(void)
 {
+	int currcons;
+
 	if (console_blanked)
 		return;
+	if (!vc_cons_allocated(fg_console)) {
+		/* impossible */
+		printk("blank_screen: tty %d not allocated ??\n", fg_console+1);
+		return;
+	}
 	timer_table[BLANK_TIMER].fn = unblank_screen;
+
+	/* try not to lose information by blanking, and not to waste memory */
+	currcons = fg_console;
+	has_scrolled = 0;
+	blank__origin = __origin;
+	blank_origin = origin;
+	set_origin(fg_console);
 	get_scrmem(fg_console);
+	unblank_origin = origin;
+	memsetw((void *)blank_origin, BLANK, video_mem_term-blank_origin);
 	hide_cursor();
-	console_blanked = 1;
-	memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
+	console_blanked = fg_console + 1;
 }
 
 void unblank_screen(void)
 {
+	int currcons;
+	int resetorg;
+	long offset;
+
 	if (!console_blanked)
 		return;
+	if (!vc_cons_allocated(fg_console)) {
+		/* impossible */
+		printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
+		return;
+	}
 	timer_table[BLANK_TIMER].fn = blank_screen;
 	if (blankinterval) {
 		timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
 		timer_active |= 1<<BLANK_TIMER;
 	}
+	currcons = fg_console;
+	offset = 0;
+	resetorg = 0;
+	if (console_blanked == fg_console + 1 && origin == unblank_origin
+	    && !has_scrolled) {
+		/* try to restore the exact situation before blanking */
+		resetorg = 1;
+		offset = (blank_origin - video_mem_base)
+			- (unblank_origin - video_mem_start);
+	}
+
 	console_blanked = 0;
-	set_scrmem(fg_console);
+	set_scrmem(fg_console, offset);
 	set_origin(fg_console);
 	set_cursor(fg_console);
+	if (resetorg)
+		__set_origin(blank__origin);
 }
 
 void update_screen(int new_console)
@@ -1762,16 +2092,24 @@
 
 	if (new_console == fg_console || lock)
 		return;
+	if (!vc_cons_allocated(new_console)) {
+		/* strange ... */
+		printk("update_screen: tty %d not allocated ??\n", new_console+1);
+		return;
+	}
 	lock = 1;
-	kbdsave(new_console);
 #ifdef CONFIG_SELECTION
 	highlight_pointer(fg_console,-1);
 #endif /* CONFIG_SELECTION */
-	get_scrmem(fg_console); 
-	fg_console = new_console;
-	set_scrmem(fg_console); 
+	if (!console_blanked)
+		get_scrmem(fg_console);
+	else
+		console_blanked = -1;	   /* no longer of the form console+1 */
+	fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
+				  /* consequently, fg_console will always be allocated */
+	set_scrmem(fg_console, 0); 
 	set_origin(fg_console);
-	set_cursor(new_console);
+	set_cursor(fg_console);
 	set_leds();
 	compute_shiftstate();
 	lock = 0;
@@ -1784,15 +2122,18 @@
 
 	if (!suser())
 		return -EPERM;
-	l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
+	l = verify_area(VERIFY_READ, buf, 2);
 	if (l)
 		return l;
 	currcons = get_fs_byte(buf+1);
-	if ((currcons<0) || (currcons>NR_CONSOLES))
+	currcons = (currcons ? currcons-1 : fg_console);
+	if (!vc_cons_allocated(currcons))
 		return -EIO;
-	put_fs_byte((char)(video_num_lines),buf++);	
+	l = verify_area(VERIFY_WRITE, buf, 2+video_num_columns*video_num_lines);
+	if (l)
+		return l;
+	put_fs_byte((char)(video_num_lines),buf++);   
 	put_fs_byte((char)(video_num_columns),buf++);
-	currcons = (currcons ? currcons-1 : fg_console);
 	sptr = (char *) origin;
 	for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
 		put_fs_byte(*sptr++,buf++);	
@@ -1800,19 +2141,21 @@
 }
 
 /*
- * Later on maybe we'll dynamically allocate the console screen
- * memory.
+ * Allocate the console screen memory.
  */
 int con_open(struct tty_struct *tty, struct file * filp)
 {
-	int	idx;
+	unsigned int	idx;
+	int i;
 
 	idx = MINOR(tty->device) - tty->driver.minor_start;
 	
-	if (idx > NR_CONSOLES)
-		return -ENODEV;
-	vt_cons[idx].vc_num = idx;
-	tty->driver_data = &vt_cons[idx];
+	i = vc_allocate(idx);
+	if (i)
+		return i;
+
+	vt_cons[idx]->vc_num = idx;
+	tty->driver_data = vt_cons[idx];
 	
 	if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
 		tty->winsize.ws_row = video_num_lines;
@@ -1845,20 +2188,20 @@
 /* use complementary color to show the pointer */
 static void highlight_pointer(const int currcons, const int where)
 {
-        unsigned char *p;
+	unsigned char *p;
 	static unsigned char *prev=NULL;
 
 	if (where==-1) /* remove the pointer */
 	{
-                if (prev)
+		if (prev)
 		{
 			*prev ^= 0x77;
 			prev=NULL;
 		}
-        }
+	}
 	else
 	{
-	        p = (unsigned char *)origin - hwscroll_offset + where + 1;
+		p = (unsigned char *)origin - hwscroll_offset + where + 1;
 		*p ^= 0x77;
 		if (prev) *prev ^= 0x77; /* remove the previous one */
 		prev=p;
@@ -1976,16 +2319,16 @@
 			new_sel_end = pe + video_size_row
 				    - pe % video_size_row - 2;
 			break;
-                case 3: /* pointer highlight */
-		        if (sel_cons != currcons)
-        		{
+		case 3: /* pointer highlight */
+			if (sel_cons != currcons)
+			{
 				highlight_pointer(sel_cons,-1);
-        	        	clear_selection();
-                		sel_cons = currcons;
-        		}
+				clear_selection();
+				sel_cons = currcons;
+			}
 			highlight_pointer(sel_cons,pe);
 			return 0; /* nothing more */
-	        default:
+		default:
 			return -EINVAL;
 	}
 	/* select to end of line if on trailing space */
@@ -2090,7 +2433,7 @@
    the selection. */
 static void clear_selection()
 {
-        highlight_pointer(sel_cons, -1); /* hide the pointer */
+	highlight_pointer(sel_cons, -1); /* hide the pointer */
 	if (sel_start != -1)
 	{
 		highlight(sel_cons, sel_start, sel_end);
@@ -2140,7 +2483,7 @@
 
 	i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
 	if (i)
-	        return i;
+		return i;
 
 	cli();
 	outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
@@ -2218,7 +2561,7 @@
 
 	i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
 	if (i)
-	        return i;
+		return i;
 
 	for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
 	USER_TRANS[012]=0;
@@ -2234,7 +2577,7 @@
 
 	i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
 	if (i)
-	        return i;
+		return i;
 
 	for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
 	return 0;
diff -u --recursive --new-file v1.1.53/linux/drivers/char/defkeymap.c linux/drivers/char/defkeymap.c
--- v1.1.53/linux/drivers/char/defkeymap.c	Tue Feb  1 13:04:28 1994
+++ linux/drivers/char/defkeymap.c	Thu Oct 13 14:07:05 1994
@@ -1,287 +1,159 @@
-/* Automatically generated by mktable */
-/* Do not edit this file!             */
+/* Do not edit this file! It was automatically generated by   */
+/*    loadkeys --mktable defkeymap.map > defkeymap.c          */
 
 #include <linux/types.h>
 #include <linux/keyboard.h>
 #include <linux/kd.h>
 
-u_short key_map[NR_KEYMAPS][NR_KEYS] = {
-	{
-	0x0200,	0x001b,	0x0031,	0x0032,	0x0033,	0x0034,	0x0035,	0x0036,	
-	0x0037,	0x0038,	0x0039,	0x0030,	0x002d,	0x003d,	0x007f,	0x0009,	
-	0x0b71,	0x0b77,	0x0b65,	0x0b72,	0x0b74,	0x0b79,	0x0b75,	0x0b69,	
-	0x0b6f,	0x0b70,	0x005b,	0x005d,	0x0201,	0x0702,	0x0b61,	0x0b73,	
-	0x0b64,	0x0b66,	0x0b67,	0x0b68,	0x0b6a,	0x0b6b,	0x0b6c,	0x003b,	
-	0x0027,	0x0060,	0x0700,	0x005c,	0x0b7a,	0x0b78,	0x0b63,	0x0b76,	
-	0x0b62,	0x0b6e,	0x0b6d,	0x002c,	0x002e,	0x002f,	0x0700,	0x030c,	
-	0x0703,	0x0020,	0x0207,	0x0100,	0x0101,	0x0102,	0x0103,	0x0104,	
-	0x0105,	0x0106,	0x0107,	0x0108,	0x0109,	0x0208,	0x0209,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x003c,	0x010a,	
-	0x010b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x001c,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x001b,	0x0021,	0x0040,	0x0023,	0x0024,	0x0025,	0x005e,	
-	0x0026,	0x002a,	0x0028,	0x0029,	0x005f,	0x002b,	0x007f,	0x0009,	
-	0x0b51,	0x0b57,	0x0b45,	0x0b52,	0x0b54,	0x0b59,	0x0b55,	0x0b49,	
-	0x0b4f,	0x0b50,	0x007b,	0x007d,	0x0201,	0x0702,	0x0b41,	0x0b53,	
-	0x0b44,	0x0b46,	0x0b47,	0x0b48,	0x0b4a,	0x0b4b,	0x0b4c,	0x003a,	
-	0x0022,	0x007e,	0x0700,	0x007c,	0x0b5a,	0x0b58,	0x0b43,	0x0b56,	
-	0x0b42,	0x0b4e,	0x0b4d,	0x003c,	0x003e,	0x003f,	0x0700,	0x030c,	
-	0x0703,	0x0020,	0x0207,	0x010a,	0x010b,	0x010c,	0x010d,	0x010e,	
-	0x010f,	0x0110,	0x0111,	0x0112,	0x0113,	0x0208,	0x0203,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x003e,	0x010a,	
-	0x010b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x020b,	0x0601,	0x0602,	0x0117,	0x0600,	0x020a,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0040,	0x0200,	0x0024,	0x0200,	0x0200,	
-	0x007b,	0x005b,	0x005d,	0x007d,	0x005c,	0x0200,	0x0200,	0x0200,	
-	0x0b71,	0x0b77,	0x0b65,	0x0b72,	0x0b74,	0x0b79,	0x0b75,	0x0b69,	
-	0x0b6f,	0x0b70,	0x0200,	0x007e,	0x0201,	0x0702,	0x0b61,	0x0b73,	
-	0x0b64,	0x0b66,	0x0b67,	0x0b68,	0x0b6a,	0x0b6b,	0x0b6c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x0b7a,	0x0b78,	0x0b63,	0x0b76,	
-	0x0b62,	0x0b6e,	0x0b6d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x050c,	0x050d,	0x050e,	0x050f,	0x0510,	
-	0x0511,	0x0512,	0x0513,	0x0514,	0x0515,	0x0208,	0x0202,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x007c,	0x0516,	
-	0x0517,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0b51,	0x0b57,	0x0b45,	0x0b52,	0x0b54,	0x0b59,	0x0b55,	0x0b49,	
-	0x0b4f,	0x0b50,	0x0200,	0x0200,	0x0201,	0x0702,	0x0b41,	0x0b53,	
-	0x0b44,	0x0b46,	0x0b47,	0x0b48,	0x0b4a,	0x0b4b,	0x0b4c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x0b5a,	0x0b58,	0x0b43,	0x0b56,	
-	0x0b42,	0x0b4e,	0x0b4d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0000,	0x001b,	0x001c,	0x001d,	0x001e,	
-	0x001f,	0x007f,	0x0200,	0x0200,	0x001f,	0x0200,	0x0200,	0x0200,	
-	0x0011,	0x0017,	0x0005,	0x0012,	0x0014,	0x0019,	0x0015,	0x0009,	
-	0x000f,	0x0010,	0x001b,	0x001d,	0x0201,	0x0702,	0x0001,	0x0013,	
-	0x0004,	0x0006,	0x0007,	0x0008,	0x000a,	0x000b,	0x000c,	0x0200,	
-	0x0007,	0x0000,	0x0700,	0x001c,	0x001a,	0x0018,	0x0003,	0x0016,	
-	0x0002,	0x000e,	0x000d,	0x0200,	0x020e,	0x007f,	0x0700,	0x030c,	
-	0x0703,	0x0000,	0x0207,	0x0100,	0x0101,	0x0102,	0x0103,	0x0104,	
-	0x0105,	0x0106,	0x0107,	0x0108,	0x0109,	0x0208,	0x0204,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x010a,	
-	0x010b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x001c,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0000,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x001f,	0x0200,	0x0200,	0x0200,	
-	0x0011,	0x0017,	0x0005,	0x0012,	0x0014,	0x0019,	0x0015,	0x0009,	
-	0x000f,	0x0010,	0x0200,	0x0200,	0x0201,	0x0702,	0x0001,	0x0013,	
-	0x0004,	0x0006,	0x0007,	0x0008,	0x000a,	0x000b,	0x000c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x001a,	0x0018,	0x0003,	0x0016,	
-	0x0002,	0x000e,	0x000d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0011,	0x0017,	0x0005,	0x0012,	0x0014,	0x0019,	0x0015,	0x0009,	
-	0x000f,	0x0010,	0x0200,	0x0200,	0x0201,	0x0702,	0x0001,	0x0013,	
-	0x0004,	0x0006,	0x0007,	0x0008,	0x000a,	0x000b,	0x000c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x001a,	0x0018,	0x0003,	0x0016,	
-	0x0002,	0x000e,	0x000d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x020c,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x020c,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0011,	0x0017,	0x0005,	0x0012,	0x0014,	0x0019,	0x0015,	0x0009,	
-	0x000f,	0x0010,	0x0200,	0x0200,	0x0201,	0x0702,	0x0001,	0x0013,	
-	0x0004,	0x0006,	0x0007,	0x0008,	0x000a,	0x000b,	0x000c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x001a,	0x0018,	0x0003,	0x0016,	
-	0x0002,	0x000e,	0x000d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x081b,	0x0831,	0x0832,	0x0833,	0x0834,	0x0835,	0x0836,	
-	0x0837,	0x0838,	0x0839,	0x0830,	0x082d,	0x083d,	0x087f,	0x0809,	
-	0x0871,	0x0877,	0x0865,	0x0872,	0x0874,	0x0879,	0x0875,	0x0869,	
-	0x086f,	0x0870,	0x085b,	0x085d,	0x080d,	0x0702,	0x0861,	0x0873,	
-	0x0864,	0x0866,	0x0867,	0x0868,	0x086a,	0x086b,	0x086c,	0x083b,	
-	0x0827,	0x0860,	0x0700,	0x085c,	0x087a,	0x0878,	0x0863,	0x0876,	
-	0x0862,	0x086e,	0x086d,	0x082c,	0x082e,	0x082f,	0x0700,	0x030c,	
-	0x0703,	0x0820,	0x0207,	0x0500,	0x0501,	0x0502,	0x0503,	0x0504,	
-	0x0505,	0x0506,	0x0507,	0x0508,	0x0509,	0x0208,	0x0209,	0x0907,	
-	0x0908,	0x0909,	0x030b,	0x0904,	0x0905,	0x0906,	0x030a,	0x0901,	
-	0x0902,	0x0903,	0x0900,	0x0310,	0x0206,	0x0200,	0x083c,	0x050a,	
-	0x050b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x001c,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0851,	0x0857,	0x0845,	0x0852,	0x0854,	0x0859,	0x0855,	0x0849,	
-	0x084f,	0x0850,	0x0200,	0x0200,	0x0201,	0x0702,	0x0841,	0x0853,	
-	0x0844,	0x0846,	0x0847,	0x0848,	0x084a,	0x084b,	0x084c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x085a,	0x0858,	0x0843,	0x0856,	
-	0x0842,	0x084e,	0x084d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0871,	0x0877,	0x0865,	0x0872,	0x0874,	0x0879,	0x0875,	0x0869,	
-	0x086f,	0x0870,	0x0200,	0x0200,	0x0201,	0x0702,	0x0861,	0x0873,	
-	0x0864,	0x0866,	0x0867,	0x0868,	0x086a,	0x086b,	0x086c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x087a,	0x0878,	0x0863,	0x0876,	
-	0x0862,	0x086e,	0x086d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0851,	0x0857,	0x0845,	0x0852,	0x0854,	0x0859,	0x0855,	0x0849,	
-	0x084f,	0x0850,	0x0200,	0x0200,	0x0201,	0x0702,	0x0841,	0x0853,	
-	0x0844,	0x0846,	0x0847,	0x0848,	0x084a,	0x084b,	0x084c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x085a,	0x0858,	0x0843,	0x0856,	
-	0x0842,	0x084e,	0x084d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0811,	0x0817,	0x0805,	0x0812,	0x0814,	0x0819,	0x0815,	0x0809,	
-	0x080f,	0x0810,	0x0200,	0x0200,	0x0201,	0x0702,	0x0801,	0x0813,	
-	0x0804,	0x0806,	0x0807,	0x0808,	0x080a,	0x080b,	0x080c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x081a,	0x0818,	0x0803,	0x0816,	
-	0x0802,	0x080e,	0x080d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x020c,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x020c,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0811,	0x0817,	0x0805,	0x0812,	0x0814,	0x0819,	0x0815,	0x0809,	
-	0x080f,	0x0810,	0x0200,	0x0200,	0x0201,	0x0702,	0x0801,	0x0813,	
-	0x0804,	0x0806,	0x0807,	0x0808,	0x080a,	0x080b,	0x080c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x081a,	0x0818,	0x0803,	0x0816,	
-	0x0802,	0x080e,	0x080d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0811,	0x0817,	0x0805,	0x0812,	0x0814,	0x0819,	0x0815,	0x0809,	
-	0x080f,	0x0810,	0x0200,	0x0200,	0x0201,	0x0702,	0x0801,	0x0813,	
-	0x0804,	0x0806,	0x0807,	0x0808,	0x080a,	0x080b,	0x080c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x081a,	0x0818,	0x0803,	0x0816,	
-	0x0802,	0x080e,	0x080d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, {
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0811,	0x0817,	0x0805,	0x0812,	0x0814,	0x0819,	0x0815,	0x0809,	
-	0x080f,	0x0810,	0x0200,	0x0200,	0x0201,	0x0702,	0x0801,	0x0813,	
-	0x0804,	0x0806,	0x0807,	0x0808,	0x080a,	0x080b,	0x080c,	0x0200,	
-	0x0200,	0x0200,	0x0700,	0x0200,	0x081a,	0x0818,	0x0803,	0x0816,	
-	0x0802,	0x080e,	0x080d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,	
-	0x0703,	0x0200,	0x0207,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0208,	0x0200,	0x0307,	
-	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,	
-	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x0200,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,	
-	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,	
-	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,	
-	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	
-	}, 
+u_short plain_map[NR_KEYS] = {
+	0xf200,	0xf01b,	0xf031,	0xf032,	0xf033,	0xf034,	0xf035,	0xf036,
+	0xf037,	0xf038,	0xf039,	0xf030,	0xf02d,	0xf03d,	0xf07f,	0xf009,
+	0xfb71,	0xfb77,	0xfb65,	0xfb72,	0xfb74,	0xfb79,	0xfb75,	0xfb69,
+	0xfb6f,	0xfb70,	0xf05b,	0xf05d,	0xf201,	0xf702,	0xfb61,	0xfb73,
+	0xfb64,	0xfb66,	0xfb67,	0xfb68,	0xfb6a,	0xfb6b,	0xfb6c,	0xf03b,
+	0xf027,	0xf060,	0xf700,	0xf05c,	0xfb7a,	0xfb78,	0xfb63,	0xfb76,
+	0xfb62,	0xfb6e,	0xfb6d,	0xf02c,	0xf02e,	0xf02f,	0xf700,	0xf30c,
+	0xf703,	0xf020,	0xf207,	0xf100,	0xf101,	0xf102,	0xf103,	0xf104,
+	0xf105,	0xf106,	0xf107,	0xf108,	0xf109,	0xf208,	0xf209,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf03c,	0xf10a,
+	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
 };
 
-char func_buf[FUNC_BUFSIZE] = {
+u_short shift_map[NR_KEYS] = {
+	0xf200,	0xf01b,	0xf021,	0xf040,	0xf023,	0xf024,	0xf025,	0xf05e,
+	0xf026,	0xf02a,	0xf028,	0xf029,	0xf05f,	0xf02b,	0xf07f,	0xf009,
+	0xfb51,	0xfb57,	0xfb45,	0xfb52,	0xfb54,	0xfb59,	0xfb55,	0xfb49,
+	0xfb4f,	0xfb50,	0xf07b,	0xf07d,	0xf201,	0xf702,	0xfb41,	0xfb53,
+	0xfb44,	0xfb46,	0xfb47,	0xfb48,	0xfb4a,	0xfb4b,	0xfb4c,	0xf03a,
+	0xf022,	0xf07e,	0xf700,	0xf07c,	0xfb5a,	0xfb58,	0xfb43,	0xfb56,
+	0xfb42,	0xfb4e,	0xfb4d,	0xf03c,	0xf03e,	0xf03f,	0xf700,	0xf30c,
+	0xf703,	0xf020,	0xf207,	0xf10a,	0xf10b,	0xf10c,	0xf10d,	0xf10e,
+	0xf10f,	0xf110,	0xf111,	0xf112,	0xf113,	0xf208,	0xf203,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf03e,	0xf10a,
+	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf20b,	0xf601,	0xf602,	0xf117,	0xf600,	0xf20a,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short altgr_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf040,	0xf200,	0xf024,	0xf200,	0xf200,
+	0xf07b,	0xf05b,	0xf05d,	0xf07d,	0xf05c,	0xf200,	0xf200,	0xf200,
+	0xfb71,	0xfb77,	0xf918,	0xfb72,	0xfb74,	0xfb79,	0xfb75,	0xfb69,
+	0xfb6f,	0xfb70,	0xf200,	0xf07e,	0xf201,	0xf702,	0xf914,	0xfb73,
+	0xf917,	0xf919,	0xfb67,	0xfb68,	0xfb6a,	0xfb6b,	0xfb6c,	0xf200,
+	0xf200,	0xf200,	0xf700,	0xf200,	0xfb7a,	0xfb78,	0xf916,	0xfb76,
+	0xf915,	0xfb6e,	0xfb6d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf30c,
+	0xf703,	0xf200,	0xf207,	0xf50c,	0xf50d,	0xf50e,	0xf50f,	0xf510,
+	0xf511,	0xf512,	0xf513,	0xf514,	0xf515,	0xf208,	0xf202,	0xf911,
+	0xf912,	0xf913,	0xf30b,	0xf90e,	0xf90f,	0xf910,	0xf30a,	0xf90b,
+	0xf90c,	0xf90d,	0xf90a,	0xf310,	0xf206,	0xf200,	0xf07c,	0xf516,
+	0xf517,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short ctrl_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf000,	0xf01b,	0xf01c,	0xf01d,	0xf01e,
+	0xf01f,	0xf07f,	0xf200,	0xf200,	0xf01f,	0xf200,	0xf008,	0xf200,
+	0xf011,	0xf017,	0xf005,	0xf012,	0xf014,	0xf019,	0xf015,	0xf009,
+	0xf00f,	0xf010,	0xf01b,	0xf01d,	0xf201,	0xf702,	0xf001,	0xf013,
+	0xf004,	0xf006,	0xf007,	0xf008,	0xf00a,	0xf00b,	0xf00c,	0xf200,
+	0xf007,	0xf000,	0xf700,	0xf01c,	0xf01a,	0xf018,	0xf003,	0xf016,
+	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf20e,	0xf07f,	0xf700,	0xf30c,
+	0xf703,	0xf000,	0xf207,	0xf100,	0xf101,	0xf102,	0xf103,	0xf104,
+	0xf105,	0xf106,	0xf107,	0xf108,	0xf109,	0xf208,	0xf204,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf200,	0xf10a,
+	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short shift_ctrl_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf000,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf01f,	0xf200,	0xf200,	0xf200,
+	0xf011,	0xf017,	0xf005,	0xf012,	0xf014,	0xf019,	0xf015,	0xf009,
+	0xf00f,	0xf010,	0xf200,	0xf200,	0xf201,	0xf702,	0xf001,	0xf013,
+	0xf004,	0xf006,	0xf007,	0xf008,	0xf00a,	0xf00b,	0xf00c,	0xf200,
+	0xf200,	0xf200,	0xf700,	0xf200,	0xf01a,	0xf018,	0xf003,	0xf016,
+	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf30c,
+	0xf703,	0xf200,	0xf207,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf208,	0xf200,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short alt_map[NR_KEYS] = {
+	0xf200,	0xf81b,	0xf831,	0xf832,	0xf833,	0xf834,	0xf835,	0xf836,
+	0xf837,	0xf838,	0xf839,	0xf830,	0xf82d,	0xf83d,	0xf87f,	0xf809,
+	0xf871,	0xf877,	0xf865,	0xf872,	0xf874,	0xf879,	0xf875,	0xf869,
+	0xf86f,	0xf870,	0xf85b,	0xf85d,	0xf80d,	0xf702,	0xf861,	0xf873,
+	0xf864,	0xf866,	0xf867,	0xf868,	0xf86a,	0xf86b,	0xf86c,	0xf83b,
+	0xf827,	0xf860,	0xf700,	0xf85c,	0xf87a,	0xf878,	0xf863,	0xf876,
+	0xf862,	0xf86e,	0xf86d,	0xf82c,	0xf82e,	0xf82f,	0xf700,	0xf30c,
+	0xf703,	0xf820,	0xf207,	0xf500,	0xf501,	0xf502,	0xf503,	0xf504,
+	0xf505,	0xf506,	0xf507,	0xf508,	0xf509,	0xf208,	0xf209,	0xf907,
+	0xf908,	0xf909,	0xf30b,	0xf904,	0xf905,	0xf906,	0xf30a,	0xf901,
+	0xf902,	0xf903,	0xf900,	0xf310,	0xf206,	0xf200,	0xf83c,	0xf50a,
+	0xf50b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf210,	0xf211,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short ctrl_alt_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf811,	0xf817,	0xf805,	0xf812,	0xf814,	0xf819,	0xf815,	0xf809,
+	0xf80f,	0xf810,	0xf200,	0xf200,	0xf201,	0xf702,	0xf801,	0xf813,
+	0xf804,	0xf806,	0xf807,	0xf808,	0xf80a,	0xf80b,	0xf80c,	0xf200,
+	0xf200,	0xf200,	0xf700,	0xf200,	0xf81a,	0xf818,	0xf803,	0xf816,
+	0xf802,	0xf80e,	0xf80d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf30c,
+	0xf703,	0xf200,	0xf207,	0xf500,	0xf501,	0xf502,	0xf503,	0xf504,
+	0xf505,	0xf506,	0xf507,	0xf508,	0xf509,	0xf208,	0xf200,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf20c,	0xf206,	0xf200,	0xf200,	0xf50a,
+	0xf50b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf20c,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+ushort *key_maps[MAX_NR_KEYMAPS] = {
+	plain_map, shift_map, altgr_map, 0,
+	ctrl_map, shift_ctrl_map, 0, 0,
+	alt_map, 0, 0, 0,
+	ctrl_alt_map,	0
+};
+
+unsigned int keymap_count = 7;
+
+/*
+ * Philosophy: most people do not define more strings, but they who do
+ * often want quite a lot of string space. So, we statically allocate
+ * the default and allocate dynamically in chunks of 512 bytes.
+ */
+
+char func_buf[] = {
 	'\033', '[', '[', 'A', 0, 
 	'\033', '[', '[', 'B', 0, 
 	'\033', '[', '[', 'C', 0, 
@@ -309,18 +181,14 @@
 	'\033', '[', '5', '~', 0, 
 	'\033', '[', '6', '~', 0, 
 	'\033', '[', 'M', 0, 
-	0, 
-	0, 
 	'\033', '[', 'P', 0, 
-	0, 
-	0, 
-	0, 
-	0, 
-	0, 
-	0, 
 };
 
-char *func_table[NR_FUNC] = {
+char *funcbufptr = func_buf;
+int funcbufsize = sizeof(func_buf);
+int funcbufleft = 0;          /* space left */
+
+char *func_table[MAX_NR_FUNC] = {
 	func_buf + 0,
 	func_buf + 5,
 	func_buf + 10,
@@ -348,15 +216,10 @@
 	func_buf + 135,
 	func_buf + 140,
 	func_buf + 145,
+	0,
+	0,
 	func_buf + 149,
-	func_buf + 150,
-	func_buf + 151,
-	func_buf + 155,
-	func_buf + 156,
-	func_buf + 157,
-	func_buf + 158,
-	func_buf + 159,
-	func_buf + 160,
+	0,
 };
 
 struct kbdiacr accent_table[MAX_DIACR] = {
diff -u --recursive --new-file v1.1.53/linux/drivers/char/defkeymap.map linux/drivers/char/defkeymap.map
--- v1.1.53/linux/drivers/char/defkeymap.map	Sat Jan  8 14:35:07 1994
+++ linux/drivers/char/defkeymap.map	Thu Oct 13 14:07:05 1994
@@ -1,12 +1,24 @@
-keycode   0 =
+# Default kernel keymap. This uses 7 modifier combinations.
+keymaps 0-2,4-5,8,12
+# Change the above line into
+#	keymaps 0-2,4-6,8,12
+# in case you want the entries
+#	altgr   control keycode  83 = Boot            
+#	altgr   control keycode 111 = Boot            
+# below.
+#
+# In fact AltGr is used very little, and one more keymap can
+# be saved by mapping AltGr to Alt (and adapting a few entries):
+# keycode 100 = Alt
+#
 keycode   1 = Escape           Escape          
 	alt     keycode   1 = Meta_Escape     
 keycode   2 = one              exclam          
 	alt     keycode   2 = Meta_one        
 keycode   3 = two              at               at              
-	control keycode   3 = nul             
-	shift control keycode 3 = nul
-	alt     keycode   3 = Meta_two        
+	control	keycode   3 = nul             
+	shift	control	keycode   3 = nul             
+	alt	keycode   3 = Meta_two        
 keycode   4 = three            numbersign      
 	control keycode   4 = Escape          
 	alt     keycode   4 = Meta_three      
@@ -30,18 +42,20 @@
 keycode  11 = zero             parenright       braceright      
 	alt     keycode  11 = Meta_zero       
 keycode  12 = minus            underscore       backslash       
-	control keycode  12 = Control_underscore
-	shift control keycode 12 = Control_underscore
-	alt     keycode  12 = Meta_minus      
+	control	keycode  12 = Control_underscore
+	shift	control	keycode  12 = Control_underscore
+	alt	keycode  12 = Meta_minus      
 keycode  13 = equal            plus            
 	alt     keycode  13 = Meta_equal      
 keycode  14 = Delete           Delete          
+	control keycode  14 = BackSpace
 	alt     keycode  14 = Meta_Delete     
 keycode  15 = Tab              Tab             
 	alt     keycode  15 = Meta_Tab        
 keycode  16 = q               
 keycode  17 = w               
-keycode  18 = e               
+keycode  18 = e
+	altgr   keycode  18 = Hex_E   
 keycode  19 = r               
 keycode  20 = t               
 keycode  21 = y               
@@ -58,10 +72,13 @@
 keycode  28 = Return          
 	alt     keycode  28 = Meta_Control_m  
 keycode  29 = Control         
-keycode  30 = a               
+keycode  30 = a
+	altgr   keycode  30 = Hex_A
 keycode  31 = s               
-keycode  32 = d               
-keycode  33 = f               
+keycode  32 = d
+	altgr   keycode  32 = Hex_D   
+keycode  33 = f
+	altgr   keycode  33 = Hex_F               
 keycode  34 = g               
 keycode  35 = h               
 keycode  36 = j               
@@ -81,15 +98,17 @@
 	alt     keycode  43 = Meta_backslash  
 keycode  44 = z               
 keycode  45 = x               
-keycode  46 = c               
+keycode  46 = c
+	altgr   keycode  46 = Hex_C   
 keycode  47 = v               
-keycode  48 = b               
+keycode  48 = b
+	altgr   keycode  48 = Hex_B
 keycode  49 = n               
 keycode  50 = m               
 keycode  51 = comma            less            
 	alt     keycode  51 = Meta_comma      
 keycode  52 = period           greater         
-	control keycode  52 = Compose
+	control keycode  52 = Compose         
 	alt     keycode  52 = Meta_period     
 keycode  53 = slash            question        
 	control keycode  53 = Delete          
@@ -104,61 +123,81 @@
 keycode  59 = F1               F11              Console_13      
 	control keycode  59 = F1              
 	alt     keycode  59 = Console_1       
+	control alt     keycode  59 = Console_1       
 keycode  60 = F2               F12              Console_14      
 	control keycode  60 = F2              
 	alt     keycode  60 = Console_2       
+	control alt     keycode  60 = Console_2       
 keycode  61 = F3               F13              Console_15      
 	control keycode  61 = F3              
 	alt     keycode  61 = Console_3       
+	control alt     keycode  61 = Console_3       
 keycode  62 = F4               F14              Console_16      
 	control keycode  62 = F4              
 	alt     keycode  62 = Console_4       
+	control alt     keycode  62 = Console_4       
 keycode  63 = F5               F15              Console_17      
 	control keycode  63 = F5              
 	alt     keycode  63 = Console_5       
+	control alt     keycode  63 = Console_5       
 keycode  64 = F6               F16              Console_18      
 	control keycode  64 = F6              
 	alt     keycode  64 = Console_6       
+	control alt     keycode  64 = Console_6       
 keycode  65 = F7               F17              Console_19      
 	control keycode  65 = F7              
 	alt     keycode  65 = Console_7       
+	control alt     keycode  65 = Console_7       
 keycode  66 = F8               F18              Console_20      
 	control keycode  66 = F8              
 	alt     keycode  66 = Console_8       
+	control alt     keycode  66 = Console_8       
 keycode  67 = F9               F19              Console_21      
 	control keycode  67 = F9              
 	alt     keycode  67 = Console_9       
+	control alt     keycode  67 = Console_9       
 keycode  68 = F10              F20              Console_22      
 	control keycode  68 = F10             
 	alt     keycode  68 = Console_10      
+	control alt     keycode  68 = Console_10      
 keycode  69 = Num_Lock        
 keycode  70 = Scroll_Lock      Show_Memory      Show_Registers  
 	control keycode  70 = Show_State      
 	alt     keycode  70 = Scroll_Lock     
 keycode  71 = KP_7            
 	alt     keycode  71 = Ascii_7         
+	altgr   keycode  71 = Hex_7         
 keycode  72 = KP_8            
 	alt     keycode  72 = Ascii_8         
+	altgr   keycode  72 = Hex_8         
 keycode  73 = KP_9            
 	alt     keycode  73 = Ascii_9         
+	altgr   keycode  73 = Hex_9         
 keycode  74 = KP_Subtract     
 keycode  75 = KP_4            
 	alt     keycode  75 = Ascii_4         
+	altgr   keycode  75 = Hex_4         
 keycode  76 = KP_5            
 	alt     keycode  76 = Ascii_5         
+	altgr   keycode  76 = Hex_5         
 keycode  77 = KP_6            
 	alt     keycode  77 = Ascii_6         
+	altgr   keycode  77 = Hex_6         
 keycode  78 = KP_Add          
 keycode  79 = KP_1            
 	alt     keycode  79 = Ascii_1         
+	altgr   keycode  79 = Hex_1         
 keycode  80 = KP_2            
 	alt     keycode  80 = Ascii_2         
+	altgr   keycode  80 = Hex_2         
 keycode  81 = KP_3            
 	alt     keycode  81 = Ascii_3         
+	altgr   keycode  81 = Hex_3         
 keycode  82 = KP_0            
 	alt     keycode  82 = Ascii_0         
+	altgr   keycode  82 = Hex_0         
 keycode  83 = KP_Period       
-	altgr   control keycode  83 = Boot            
+#	altgr   control keycode  83 = Boot            
 	control alt     keycode  83 = Boot            
 keycode  84 = Last_Console    
 keycode  85 =
@@ -167,9 +206,11 @@
 keycode  87 = F11              F11              Console_23      
 	control keycode  87 = F11             
 	alt     keycode  87 = Console_11      
+	control alt     keycode  87 = Console_11      
 keycode  88 = F12              F12              Console_24      
 	control keycode  88 = F12             
 	alt     keycode  88 = Console_12      
+	control alt     keycode  88 = Console_12      
 keycode  89 =
 keycode  90 =
 keycode  91 =
@@ -190,14 +231,16 @@
 keycode 104 = Prior           
 	shift   keycode 104 = Scroll_Backward 
 keycode 105 = Left            
+	alt     keycode 105 = Decr_Console
 keycode 106 = Right           
+	alt     keycode 106 = Incr_Console
 keycode 107 = Select          
 keycode 108 = Down            
 keycode 109 = Next            
 	shift   keycode 109 = Scroll_Forward  
 keycode 110 = Insert          
 keycode 111 = Remove          
-	altgr   control keycode 111 = Boot            
+#	altgr   control keycode 111 = Boot            
 	control alt     keycode 111 = Boot            
 keycode 112 = Macro           
 keycode 113 = F13             
@@ -206,7 +249,7 @@
 keycode 116 = Do              
 keycode 117 = F17             
 keycode 118 = KP_MinPlus      
-keycode 119 = Pause
+keycode 119 = Pause           
 keycode 120 =
 keycode 121 =
 keycode 122 =
@@ -241,16 +284,8 @@
 string Select = "\033[4~"
 string Prior = "\033[5~"
 string Next = "\033[6~"
-string Help = ""
-string Do = ""
 string Macro = "\033[M"
 string Pause = "\033[P"
-string F21 = ""
-string F22 = ""
-string F23 = ""
-string F24 = ""
-string F25 = ""
-string F26 = ""
 compose '`' 'A' to 'À'
 compose '`' 'a' to 'à'
 compose '\'' 'A' to 'Á'
diff -u --recursive --new-file v1.1.53/linux/drivers/char/kbd_kern.h linux/drivers/char/kbd_kern.h
--- v1.1.53/linux/drivers/char/kbd_kern.h	Mon Aug 22 21:57:53 1994
+++ linux/drivers/char/kbd_kern.h	Thu Oct 13 14:07:06 1994
@@ -6,6 +6,11 @@
 
 #include <linux/keyboard.h>
 
+extern char *func_table[MAX_NR_FUNC];
+extern char func_buf[];
+extern char *funcbufptr;
+extern int funcbufsize, funcbufleft;
+
 /*
  * kbd->xxx contains the VC-local things (flag settings etc..)
  *
@@ -16,57 +21,59 @@
  * Note: lockstate is used as index in the array key_map.
  */
 struct kbd_struct {
-        unsigned char ledstate;		/* 3 bits */
-	unsigned char default_ledstate;
-#define VC_SCROLLOCK	0	/* scroll-lock mode */
-#define VC_NUMLOCK	1	/* numeric lock mode */
-#define VC_CAPSLOCK	2	/* capslock mode */
 
-	unsigned char lockstate;	/* 4 bits - must be in 0..15 */
+	unsigned char lockstate;
+/* 8 modifiers - the names do not have any meaning at all;
+   they can be associated to arbitrarily chosen keys */
 #define VC_SHIFTLOCK	KG_SHIFT	/* shift lock mode */
 #define VC_ALTGRLOCK	KG_ALTGR	/* altgr lock mode */
 #define VC_CTRLLOCK	KG_CTRL 	/* control lock mode */
 #define VC_ALTLOCK	KG_ALT  	/* alt lock mode */
+#define VC_SHIFTLLOCK	KG_SHIFTL	/* shiftl lock mode */
+#define VC_SHIFTRLOCK	KG_SHIFTR	/* shiftr lock mode */
+#define VC_CTRLLLOCK	KG_CTRLL 	/* ctrll lock mode */
+#define VC_CTRLRLOCK	KG_CTRLR 	/* ctrlr lock mode */
+
+	unsigned char ledmode:2; 	/* one 2-bit value */
+#define LED_SHOW_FLAGS 0        /* traditional state */
+#define LED_SHOW_IOCTL 1        /* only change leds upon ioctl */
+#define LED_SHOW_MEM 2          /* `heartbeat': peek into memory */
+
+	unsigned char ledflagstate:3;	/* flags, not lights */
+	unsigned char default_ledflagstate:3;
+#define VC_SCROLLOCK	0	/* scroll-lock mode */
+#define VC_NUMLOCK	1	/* numeric lock mode */
+#define VC_CAPSLOCK	2	/* capslock mode */
+
+	unsigned char kbdmode:2;	/* one 2-bit value */
+#define VC_XLATE	0	/* translate keycodes using keymap */
+#define VC_MEDIUMRAW	1	/* medium raw (keycode) mode */
+#define VC_RAW		2	/* raw (scancode) mode */
+#define VC_UNICODE	3	/* Unicode mode */
 
-	unsigned char modeflags;
+	unsigned char modeflags:5;
 #define VC_APPLIC	0	/* application key mode */
 #define VC_CKMODE	1	/* cursor key mode */
 #define VC_REPEAT	2	/* keyboard repeat */
 #define VC_CRLF		3	/* 0 - enter sends CR, 1 - enter sends CRLF */
 #define VC_META		4	/* 0 - meta, 1 - meta=prefix with ESC */
-#define VC_PAUSE	5	/* pause key pressed - unused */
-#define VC_RAW		6	/* raw (scancode) mode */
-#define VC_MEDIUMRAW	7	/* medium raw (keycode) mode */
 };
 
 extern struct kbd_struct kbd_table[];
 
-
 extern unsigned long kbd_init(unsigned long);
 
-extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag)
-{
-	return ((kbd->ledstate >> flag) & 1);
-}
-
-extern inline int vc_kbd_lock(struct kbd_struct * kbd, int flag)
-{
-	return ((kbd->lockstate >> flag) & 1);
-}
+extern unsigned char getledstate(void);
+extern void setledstate(struct kbd_struct *kbd, unsigned int led);
 
 extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag)
 {
 	return ((kbd->modeflags >> flag) & 1);
 }
 
-extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag)
-{
-	kbd->ledstate |= 1 << flag;
-}
-
-extern inline void set_vc_kbd_lock(struct kbd_struct * kbd, int flag)
+extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag)
 {
-	kbd->lockstate |= 1 << flag;
+	return ((kbd->ledflagstate >> flag) & 1);
 }
 
 extern inline void set_vc_kbd_mode(struct kbd_struct * kbd, int flag)
@@ -74,14 +81,9 @@
 	kbd->modeflags |= 1 << flag;
 }
 
-extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag)
-{
-	kbd->ledstate &= ~(1 << flag);
-}
-
-extern inline void clr_vc_kbd_lock(struct kbd_struct * kbd, int flag)
+extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag)
 {
-	kbd->lockstate &= ~(1 << flag);
+	kbd->ledflagstate |= 1 << flag;
 }
 
 extern inline void clr_vc_kbd_mode(struct kbd_struct * kbd, int flag)
@@ -89,9 +91,9 @@
 	kbd->modeflags &= ~(1 << flag);
 }
 
-extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
+extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag)
 {
-	kbd->ledstate ^= 1 << flag;
+	kbd->ledflagstate &= ~(1 << flag);
 }
 
 extern inline void chg_vc_kbd_lock(struct kbd_struct * kbd, int flag)
@@ -103,5 +105,12 @@
 {
 	kbd->modeflags ^= 1 << flag;
 }
+
+extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+	kbd->ledflagstate ^= 1 << flag;
+}
+
+#define U(x) ((x) ^ 0xf000)
 
 #endif
diff -u --recursive --new-file v1.1.53/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.53/linux/drivers/char/keyboard.c	Mon Aug 22 21:57:53 1994
+++ linux/drivers/char/keyboard.c	Thu Oct 13 14:07:06 1994
@@ -1,5 +1,5 @@
 /*
- * linux/kernel/chr_drv/keyboard.c
+ * linux/drivers/char/keyboard.c
  *
  * Keyboard driver for Linux v0.99 using Latin-1.
  *
@@ -7,8 +7,13 @@
  * the assembly version by Linus (with diacriticals added)
  *
  * Some additional features added by Christoph Niemann (ChN), March 1993
+ *
  * Loadable keymaps by Risto Kankkunen, May 1993
+ *
  * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
+ * Added decr/incr_console, dynamic keymaps, Unicode support,
+ * dynamic function/string keys, led setting,  Sept 1994
+ * 
  */
 
 #define KEYBOARD_IRQ 1
@@ -33,6 +38,7 @@
 
 #define KBD_REPORT_ERR
 #define KBD_REPORT_UNKN
+/* #define KBD_IS_FOCUS_9000 */
 
 #ifndef KBD_DEFMODE
 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
@@ -63,9 +69,11 @@
 
 extern void poke_blanked_console(void);
 extern void ctrl_alt_del(void);
+extern void reset_vc(unsigned int new_console);
 extern void change_console(unsigned int new_console);
 extern void scrollback(int);
 extern void scrollfront(int);
+extern int vc_cons_allocated(unsigned int);
 
 #define fake_keyboard_interrupt() \
 __asm__ __volatile__("int $0x21")
@@ -88,19 +96,20 @@
 static int dead_key_next = 0;
 /* 
  * In order to retrieve the shift_state (for the mouse server), either
- * the variable must be global, or a new procedure must be create to 
+ * the variable must be global, or a new procedure must be created to 
  * return the value. I chose the former way.
  */
 /*static*/ int shift_state = 0;
 static int npadch = -1;			/* -1 or number assembled on pad */
 static unsigned char diacr = 0;
 static char rep = 0;			/* flag telling character repeat */
-struct kbd_struct kbd_table[NR_CONSOLES];
+struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 static struct tty_struct **ttytab;
 static struct kbd_struct * kbd = kbd_table;
 static struct tty_struct * tty = NULL;
 
 /* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected = 0;
 static volatile unsigned char acknowledge = 0;
 static volatile unsigned char resend = 0;
 
@@ -109,24 +118,40 @@
 
 static k_handfn
 	do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
-	do_meta, do_ascii, do_lock, do_lowercase;
+	do_meta, do_ascii, do_lock, do_lowercase, do_ignore;
 
-static k_hand key_handler[] = {
+static k_hand key_handler[16] = {
 	do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
-	do_meta, do_ascii, do_lock, do_lowercase
+	do_meta, do_ascii, do_lock, do_lowercase,
+	do_ignore, do_ignore, do_ignore, do_ignore
+};
+
+typedef void (*void_fnp)(void);
+typedef void (void_fn)(void);
+
+static void_fn enter, show_ptregs, send_intr, lastcons, caps_toggle,
+	num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
+	SAK, decr_console, incr_console;
+
+static void_fnp spec_fn_table[] = {
+	NULL,		enter,		show_ptregs,	show_mem,
+	show_state,	send_intr,	lastcons,	caps_toggle,
+	num,		hold,		scroll_forw,	scroll_back,
+	boot_it,	caps_on,	compose,	SAK,
+	decr_console,	incr_console
 };
 
 /* maximum values each key_handler can handle */
 const int max_vals[] = {
-	255, NR_FUNC - 1, 15, 17, 4, 255, 3, NR_SHIFT,
-	255, 9, 3, 255
+	255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
+	NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
+	255, NR_ASCII - 1, NR_LOCK - 1, 255
 };
 
 const int NR_TYPES = SIZE(max_vals);
 
 static void put_queue(int);
 static unsigned char handle_diacr(unsigned char);
-static void SAK(void);
 
 /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
 static struct pt_regs * pt_regs;
@@ -147,6 +172,27 @@
 }
 
 /*
+ * Many other routines do put_queue, but I think either
+ * they produce ASCII, or they produce some user-assigned
+ * string, and in both cases we might assume that it is
+ * in utf-8 already.
+ */
+void to_utf8(ushort c) {
+    if (c < 0x80)
+	put_queue(c);			/*  0*******  */
+    else if (c < 0x800) {
+	put_queue(0xc0 | (c >> 6)); 	/*  110***** 10******  */
+	put_queue(0x80 | (c & 0x3f));
+    } else {
+	put_queue(0xe0 | (c >> 12)); 	/*  1110**** 10****** 10******  */
+	put_queue(0x80 | ((c >> 6) & 0x3f));
+	put_queue(0x80 | (c & 0x3f));
+    }
+    /* uft-8 is defined for words of up to 36 bits,
+       but we need only 16 bits here */
+}
+
+/*
  * Translation of escaped scancodes to keysyms.
  * This should be user-settable.
  */
@@ -178,7 +224,7 @@
 #define E0_F17     (E0_BASE+21)
 #define E0_KPMINPLUS (E0_BASE+22)
 
-#define E1_PAUSE   (E0_BASE+23)
+#define E1_PAUSE   (E0_BASE+23)	                      /* 119 */
 
 static unsigned char e0_keys[128] = {
   0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x00-0x07 */
@@ -199,9 +245,42 @@
   0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
 };
 
+/* kludge to stay below 128 - next time someone comes with a strange
+   keyboard, key codes will have to become 2 (or 4) bytes. */
+/* Owners of a FOCUS 9000 can assign F1,F2-F8,F9-F12 to 85,89-95,120-123 */
+/* Owners of a certain Japanese keyboard can use 89 and 124 */
+/* Owners of a certain Brazilian keyboard can use 89 and 121 */
+/* Note: MEDIUMRAW mode will change, and all keycodes above 89 will change;
+   this is only a temporary solution */
+
+#define SC_LIM 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 (E1_PAUSE + 1)
+#define FOCUS_PF10 (E1_PAUSE + 2)
+#define FOCUS_PF11 (E1_PAUSE + 3)
+#define FOCUS_PF12 (E1_PAUSE + 4)                    /* 123 */
+#define JAP_86     (E1_PAUSE + 5)                    /* 124 */
+
+static unsigned char high_keys[128 - SC_LIM] = {
+  0, 0, 0, 0, 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 */
+};
+
 static void keyboard_interrupt(int int_pt_regs)
 {
-	unsigned char scancode;
+	unsigned char scancode, keycode;
 	static unsigned int prev_scancode = 0;   /* remember E0, E1 */
 	char up_flag;				 /* 0 or 0200 */
 	char raw_mode;
@@ -213,27 +292,44 @@
 		goto end_kbd_intr;
 	scancode = inb(0x60);
 	mark_bh(KEYBOARD_BH);
-	if (scancode == 0xfa) {
-		acknowledge = 1;
-		goto end_kbd_intr;
-	} else if (scancode == 0xfe) {
-		resend = 1;
-		goto end_kbd_intr;
-	} else if (scancode == 0) {
+	if (reply_expected) {
+	  /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
+	  /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
+		reply_expected = 0;
+		if (scancode == 0xfa) {
+			acknowledge = 1;
+			goto end_kbd_intr;
+		} else if (scancode == 0xfe) {
+			resend = 1;
+			goto end_kbd_intr;
+		}
+		/* strange ... */
+		reply_expected = 1;
 #ifdef KBD_REPORT_ERR
+		printk("keyboard reply expected - got %02x\n", scancode);
+#endif
+	}
+	if (scancode == 0) {
+#ifdef KBD_REPORT_ERR
 		printk("keyboard buffer overflow\n");
 #endif
+		prev_scancode = 0;
 		goto end_kbd_intr;
-	} else if (scancode == 0xff) {
+	}
+	if (scancode == 0xff) {
+		/* the calculator keys on a FOCUS 9000 generate 0xff */
+#ifndef KBD_IS_FOCUS_9000
 #ifdef KBD_REPORT_ERR
 		printk("keyboard error\n");
 #endif
+#endif
 		prev_scancode = 0;
 		goto end_kbd_intr;
 	}
+
 	tty = ttytab[fg_console];
  	kbd = kbd_table + fg_console;
-	if ((raw_mode = vc_kbd_mode(kbd,VC_RAW))) {
+	if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
  		put_queue(scancode);
 		/* we do not return yet, because we want to maintain
 		   the key_down array, so that we have the correct
@@ -245,7 +341,7 @@
  	}
 
  	/*
-	 *  Convert scancode to keysym, using prev_scancode.
+	 *  Convert scancode to keycode, using prev_scancode.
  	 */
 	up_flag = (scancode & 0200);
  	scancode &= 0x7f;
@@ -260,10 +356,12 @@
 		  prev_scancode = 0x100;
 		  goto end_kbd_intr;
 	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
-		  scancode = E1_PAUSE;
+		  keycode = E1_PAUSE;
 		  prev_scancode = 0;
 	      } else {
+#ifdef KBD_REPORT_UNKN
 		  printk("keyboard: unknown e1 escape sequence\n");
+#endif
 		  prev_scancode = 0;
 		  goto end_kbd_intr;
 	      }
@@ -286,50 +384,75 @@
 		goto end_kbd_intr;
 
 	      if (e0_keys[scancode])
-		scancode = e0_keys[scancode];
-	      else if (!raw_mode) {
+		keycode = e0_keys[scancode];
+	      else {
 #ifdef KBD_REPORT_UNKN
-		  printk("keyboard: unknown scancode e0 %02x\n", scancode);
+		  if (!raw_mode)
+		    printk("keyboard: unknown scancode e0 %02x\n", scancode);
 #endif
 		  goto end_kbd_intr;
 	      }
 	  }
-	} else if (scancode >= E0_BASE && !raw_mode) {
+	} 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("keyboard: scancode (%02x) not in range 00 - %2x\n",
-		 scancode, E0_BASE - 1);
+		  printk("keyboard: unrecognized scancode (%02x) - ignored\n"
+			 , scancode);
 #endif
-	  goto end_kbd_intr;
- 	}
+	      }
+	      goto end_kbd_intr;
+	  }
+ 	} else
+	  keycode = scancode;
 
 	/*
-	 * At this point the variable `scancode' contains the keysym.
+	 * At this point the variable `keycode' contains the keycode.
+	 * Note: the keycode must not be 0.
 	 * We keep track of the up/down status of the key, and
-	 * return the keysym if in MEDIUMRAW mode.
-	 * (Note: earlier kernels had a bug and did not pass the up/down
-	 * bit to applications.)
+	 * return the keycode if in MEDIUMRAW mode.
 	 */
 
 	if (up_flag) {
- 		clear_bit(scancode, key_down);
 		rep = 0;
+ 		if(!clear_bit(keycode, key_down)) {
+		    /* unexpected, but this can happen:
+		       maybe this was a key release for a FOCUS 9000
+		       PF key; if we want to see it, we have to clear
+		       up_flag */
+		    if (keycode >= SC_LIM || keycode == 85)
+		      up_flag = 0;
+		}
 	} else
- 		rep = set_bit(scancode, key_down);
+ 		rep = set_bit(keycode, key_down);
 
 	if (raw_mode)
 		goto end_kbd_intr;
 
- 	if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) {
- 		put_queue(scancode + up_flag);
+	if (kbd->kbdmode == VC_MEDIUMRAW) {
+		/* soon keycodes will require more than one byte */
+ 		put_queue(keycode + up_flag);
 		goto end_kbd_intr;
  	}
 
  	/*
 	 * Small change in philosophy: earlier we defined repetition by
-	 *	 rep = scancode == prev_keysym;
-	 *	 prev_keysym = scancode;
+	 *	 rep = keycode == prev_keycode;
+	 *	 prev_keycode = keycode;
 	 * but now by the fact that the depressed key was down already.
-	 * Does this ever make a difference?
+	 * Does this ever make a difference? Yes.
 	 */
 
 	/*
@@ -340,21 +463,45 @@
 	if (!rep ||
 	    (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 	     (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
-		u_short key_code;
+		u_short keysym;
 		u_char type;
 
 		/* the XOR below used to be an OR */
 		int shift_final = shift_state ^ kbd->lockstate;
-
-		key_code = key_map[shift_final][scancode];
-		type = KTYP(key_code);
+		ushort *key_map = key_maps[shift_final];
 
-		if (type == KT_LETTER) {
-		    type = KT_LATIN;
-		    if (vc_kbd_led(kbd,VC_CAPSLOCK))
-			key_code = key_map[shift_final ^ (1<<KG_SHIFT)][scancode];
+		if (key_map != NULL) {
+			keysym = key_map[keycode];
+			type = KTYP(keysym);
+
+			if (type >= 0xf0) {
+			    type -= 0xf0;
+			    if (type == KT_LETTER) {
+				type = KT_LATIN;
+				if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
+				    key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
+				    if (key_map)
+				      keysym = key_map[keycode];
+				}
+			    }
+			    (*key_handler[type])(keysym & 0xff, up_flag);
+			} else {
+			    /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
+			    if (!up_flag)
+			      to_utf8(keysym);
+			}
+		} else {
+			/* maybe beep? */
+			/* we have at least to update shift_state */
+#if 0			/* how? two almost equivalent choices follow */
+			compute_shiftstate();
+#else
+			keysym = U(plain_map[keycode]);
+			type = KTYP(keysym);
+			if (type == KT_SHIFT)
+			  (*key_handler[type])(keysym & 0xff, up_flag);
+#endif
 		}
-		(*key_handler[type])(key_code & 0xff, up_flag);
 	}
 
 end_kbd_intr:
@@ -403,14 +550,14 @@
 {
 	if (rep)
 		return;
-	chg_vc_kbd_led(kbd,VC_CAPSLOCK);
+	chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 }
 
 static void caps_on(void)
 {
 	if (rep)
 		return;
-	set_vc_kbd_led(kbd,VC_CAPSLOCK);
+	set_vc_kbd_led(kbd, VC_CAPSLOCK);
 }
 
 static void show_ptregs(void)
@@ -439,7 +586,7 @@
 	/*
 	 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 	 * these routines are also activated by ^S/^Q.
-	 * (And SCROLLOCK can also be set by the ioctl KDSETLED.)
+	 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 	 */
 	if (tty->stopped)
 		start_tty(tty);
@@ -447,14 +594,6 @@
 		stop_tty(tty);
 }
 
-#if 0
-/* unused at present - and the VC_PAUSE bit is not used anywhere either */
-static void pause(void)
-{
-	chg_vc_kbd_mode(kbd,VC_PAUSE);
-}
-#endif
-
 static void num(void)
 {
 	if (vc_kbd_mode(kbd,VC_APPLIC)) {
@@ -467,10 +606,36 @@
 
 static void lastcons(void)
 {
-	/* pressing alt-printscreen switches to the last used console, ChN */
+	/* switch to the last used console, ChN */
 	want_console = last_console;
 }
 
+static void decr_console(void)
+{
+	int i;
+ 
+	for (i = fg_console-1; i != fg_console; i--) {
+		if (i == -1)
+			i = MAX_NR_CONSOLES-1;
+		if (vc_cons_allocated(i))
+			break;
+	}
+	want_console = i;
+}
+
+static void incr_console(void)
+{
+	int i;
+
+	for (i = fg_console+1; i != fg_console; i++) {
+		if (i == MAX_NR_CONSOLES)
+			i = 0;
+		if (vc_cons_allocated(i))
+			break;
+	}
+	want_console = i;
+}
+
 static void send_intr(void)
 {
 	if (!tty || (tty->termios && I_IGNBRK(tty)))
@@ -478,12 +643,12 @@
 	tty_insert_flip_char(tty, 0, TTY_BREAK);
 }
 
-static void scrll_forw(void)
+static void scroll_forw(void)
 {
 	scrollfront(0);
 }
 
-static void scrll_back(void)
+static void scroll_back(void)
 {
 	scrollback(0);
 }
@@ -511,37 +676,24 @@
 	 * attention key is that it should be guaranteed to always
 	 * work.
 	 */
-	clr_vc_kbd_flag(kbd, VC_RAW);
-	clr_vc_kbd_flag(kbd, VC_MEDIUMRAW);
-	vt_cons[fg_console].vc_mode = KD_TEXT;
-	vt_cons[fg_console].vt_mode.mode = VT_AUTO;
-	vt_cons[fg_console].vt_mode.waitv = 0;
-	vt_cons[fg_console].vt_mode.relsig = 0;
-	vt_cons[fg_console].vt_mode.acqsig = 0;
-	vt_cons[fg_console].vt_mode.frsig = 0;
-	vt_cons[fg_console].vt_pid = -1;
-	vt_cons[fg_console].vt_newvt = -1;
-	unblank_screen();
+	reset_vc(fg_console);
+	unblank_screen();	/* not in interrupt routine? */
 #endif
 }
 
-static void do_spec(unsigned char value, char up_flag)
+static void do_ignore(unsigned char value, char up_flag)
 {
-	typedef void (*fnp)(void);
-	fnp fn_table[] = {
-		NULL,		enter,		show_ptregs,	show_mem,
-		show_state,	send_intr,	lastcons,	caps_toggle,
-		num,		hold,		scrll_forw,	scrll_back,
-		boot_it,	caps_on,        compose,        SAK
-	};
+}
 
+static void do_spec(unsigned char value, char up_flag)
+{
 	if (up_flag)
 		return;
-	if (value >= SIZE(fn_table))
+	if (value >= SIZE(spec_fn_table))
 		return;
-	if (!fn_table[value])
+	if (!spec_fn_table[value])
 		return;
-	fn_table[value]();
+	spec_fn_table[value]();
 }
 
 static void do_lowercase(unsigned char value, char up_flag)
@@ -624,9 +776,10 @@
 {
 	if (up_flag)
 		return;
-	if (value < SIZE(func_table))
-		puts_queue(func_table[value]);
-	else
+	if (value < SIZE(func_table)) {
+		if (func_table[value])
+			puts_queue(func_table[value]);
+	} else
 		printk("do_fn called with value=%d\n", value);
 }
 
@@ -703,7 +856,8 @@
 	if (rep)
 		return;
 
-	/* kludge... */
+	/* Mimic typewriter:
+	   a CapsShift key acts like Shift but undoes CapsLock */
 	if (value == KVAL(K_CAPSSHIFT)) {
 		value = KVAL(K_SHIFT);
 		if (!up_flag)
@@ -725,13 +879,17 @@
 
 	/* kludge */
 	if (up_flag && shift_state != old_state && npadch != -1) {
-		put_queue(npadch);
+		if (kbd->kbdmode == VC_UNICODE)
+		  to_utf8(npadch & 0xffff);
+		else
+		  put_queue(npadch & 0xff);
 		npadch = -1;
 	}
 }
 
 /* called after returning from RAW mode or when changing consoles -
    recompute k_down[] and shift_state from key_down[] */
+/* maybe called when keymap is undefined, so that shiftkey release is seen */
 void compute_shiftstate(void)
 {
 	int i, j, k, sym, val;
@@ -745,9 +903,11 @@
 	    k = (i<<5);
 	    for(j=0; j<32; j++,k++)
 	      if(test_bit(k, key_down)) {
-		sym = key_map[0][k];
+		sym = U(plain_map[k]);
 		if(KTYP(sym) == KT_SHIFT) {
 		  val = KVAL(sym);
+		  if (val == KVAL(K_CAPSSHIFT))
+		    val = KVAL(K_SHIFT);
 		  k_down[val]++;
 		  shift_state |= (1<<val);
 		}
@@ -769,13 +929,22 @@
 
 static void do_ascii(unsigned char value, char up_flag)
 {
+	int base;
+
 	if (up_flag)
 		return;
 
+	if (value < 10)    /* decimal input of code, while Alt depressed */
+	    base = 10;
+	else {       /* hexadecimal input of code, while AltGr depressed */
+	    value -= 10;
+	    base = 16;
+	}
+
 	if (npadch == -1)
-		npadch = value;
+	  npadch = value;
 	else
-		npadch = (npadch * 10 + value) % 1000;
+	  npadch = npadch * base + value;
 }
 
 static void do_lock(unsigned char value, char up_flag)
@@ -799,6 +968,7 @@
 		kb_wait();
 		acknowledge = 0;
 		resend = 0;
+		reply_expected = 1;
 		outb_p(data, 0x60);
 		for(i=0; i<0x20000; i++) {
 			inb_p(0x64);		/* just as a delay */
@@ -814,6 +984,76 @@
 }
 
 /*
+ * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
+ * or (ii) whatever pattern of lights people want to show using KDSETLED,
+ * or (iii) specified bits of specified words in kernel memory.
+ */
+
+static unsigned char ledstate = 0xff; /* undefined */
+static unsigned char ledioctl;
+
+unsigned char getledstate(void) {
+    return ledstate;
+}
+
+void setledstate(struct kbd_struct *kbd, unsigned int led) {
+    if (!(led & ~7)) {
+	ledioctl = led;
+	kbd->ledmode = LED_SHOW_IOCTL;
+    } else
+	kbd->ledmode = LED_SHOW_FLAGS;
+    set_leds();
+}
+
+static struct ledptr {
+    unsigned int *addr;
+    unsigned int mask;
+    unsigned char valid:1;
+} ledptrs[3];
+
+void register_leds(int console, unsigned int led,
+		   unsigned int *addr, unsigned int mask) {
+    struct kbd_struct *kbd = kbd_table + console;
+    if (led < 3) {
+	ledptrs[led].addr = addr;
+	ledptrs[led].mask = mask;
+	ledptrs[led].valid = 1;
+	kbd->ledmode = LED_SHOW_MEM;
+    } else
+	kbd->ledmode = LED_SHOW_FLAGS;
+}
+
+static inline unsigned char getleds(void){
+    struct kbd_struct *kbd = kbd_table + fg_console;
+    unsigned char leds;
+
+    if (kbd->ledmode == LED_SHOW_IOCTL)
+      return ledioctl;
+    leds = kbd->ledflagstate;
+    if (kbd->ledmode == LED_SHOW_MEM) {
+	if (ledptrs[0].valid) {
+	    if (*ledptrs[0].addr & ledptrs[0].mask)
+	      leds |= 1;
+	    else
+	      leds &= ~1;
+	}
+	if (ledptrs[1].valid) {
+	    if (*ledptrs[1].addr & ledptrs[1].mask)
+	      leds |= 2;
+	    else
+	      leds &= ~2;
+	}
+	if (ledptrs[2].valid) {
+	    if (*ledptrs[2].addr & ledptrs[2].mask)
+	      leds |= 4;
+	    else
+	      leds &= ~4;
+	}
+    }
+    return leds;
+}
+
+/*
  * This routine is the bottom half of the keyboard interrupt
  * routine, and runs with all interrupts enabled. It does
  * console changing, led setting and copy_to_cooked, which can
@@ -828,11 +1068,10 @@
  */
 static void kbd_bh(void * unused)
 {
-	static unsigned char old_leds = 0xff;
-	unsigned char leds = kbd_table[fg_console].ledstate;
+	unsigned char leds = getleds();
 
-	if (leds != old_leds) {
-		old_leds = leds;
+	if (leds != ledstate) {
+		ledstate = leds;
 		if (!send_data(0xed) || !send_data(leds))
 			send_data(0xf4);	/* re-enable kbd if any errors */
 	}
@@ -840,6 +1079,9 @@
 		if (want_console != fg_console) {
 			last_console = fg_console;
 			change_console(want_console);
+			/* we only changed when the console had already
+			   been allocated - a new console is not created
+			   in an interrupt routine */
 		}
 		want_console = -1;
 	}
@@ -880,16 +1122,18 @@
 unsigned long kbd_init(unsigned long kmem_start)
 {
 	int i;
-	struct kbd_struct * kbd;
+	struct kbd_struct kbd0;
 	extern struct tty_driver console_driver;
 
-	kbd = kbd_table + 0;
-	for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) {
-		kbd->ledstate = KBD_DEFLEDS;
-		kbd->default_ledstate = KBD_DEFLEDS;
-		kbd->lockstate = KBD_DEFLOCK;
-		kbd->modeflags = KBD_DEFMODE;
-	}
+	kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
+	kbd0.ledmode = LED_SHOW_FLAGS;
+	kbd0.lockstate = KBD_DEFLOCK;
+	kbd0.modeflags = KBD_DEFMODE;
+	kbd0.kbdmode = VC_XLATE;
+ 
+	for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
+		kbd_table[i] = kbd0;
+
 	ttytab = console_driver.table;
 
 	bh_base[KEYBOARD_BH].routine = kbd_bh;
diff -u --recursive --new-file v1.1.53/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v1.1.53/linux/drivers/char/mem.c	Sun Aug 21 17:48:25 1994
+++ linux/drivers/char/mem.c	Thu Oct 13 14:07:06 1994
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/chr_drv/mem.c
+ *  linux/drivers/char/mem.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
diff -u --recursive --new-file v1.1.53/linux/drivers/char/mouse.c linux/drivers/char/mouse.c
--- v1.1.53/linux/drivers/char/mouse.c	Sun Jan  9 15:14:37 1994
+++ linux/drivers/char/mouse.c	Thu Oct 13 14:07:06 1994
@@ -1,5 +1,5 @@
 /*
- * linux/kernel/chr_drv/mouse.c
+ * linux/drivers/char/mouse.c
  *
  * Generic mouse open routine by Johan Myreen
  *
diff -u --recursive --new-file v1.1.53/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v1.1.53/linux/drivers/char/psaux.c	Thu Aug 11 20:43:04 1994
+++ linux/drivers/char/psaux.c	Thu Oct 13 14:07:07 1994
@@ -1,5 +1,5 @@
 /*
- * linux/kernel/chr_drv/psaux.c
+ * linux/drivers/char/psaux.c
  *
  * Driver for PS/2 type mouse by Johan Myreen.
  *
diff -u --recursive --new-file v1.1.53/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v1.1.53/linux/drivers/char/pty.c	Thu Aug 11 20:43:04 1994
+++ linux/drivers/char/pty.c	Thu Oct 13 14:07:07 1994
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/chr_drv/pty.c
+ *  linux/drivers/char/pty.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
diff -u --recursive --new-file v1.1.53/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.1.53/linux/drivers/char/serial.c	Fri Aug 19 14:04:02 1994
+++ linux/drivers/char/serial.c	Thu Oct 13 14:07:07 1994
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/serial.c
+ *  linux/drivers/char/serial.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
@@ -987,7 +987,6 @@
 static void shutdown(struct async_struct * info)
 {
 	unsigned long	flags;
-	unsigned long timeout;
 	int		retval;
 
 	if (!(info->flags & ASYNC_INITIALIZED))
@@ -1039,24 +1038,6 @@
 		(void) inb((info->port & 0xFE0) | 0x01F);
 	}
 	
-	/*
-	 * Before we drop DTR, make sure the UART transmitter has
-	 * completely drained; this is especially important if there
-	 * is a transmit FIFO!
-	 * 
-	 * We busy loop here, which is not great; unfortunately the
-	 * UART does not provide an interrupt for TEMT, and putting it
-	 * in the interrupt handler would slow down normal accesses
-	 * anyway.
-	 */
-	sti();
-	timeout = jiffies + info->timeout;
-	while (!(serial_inp(info, UART_LSR) & UART_LSR_TEMT)) {
-		if (jiffies > timeout)
-			break;
-	}
-	cli();
-	
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
 		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
 		info->MCR_noint &= ~(UART_MCR_DTR|UART_MCR_RTS);
@@ -1142,15 +1123,20 @@
 	} else
 		fcr = 0;
 	
-	/* CTS flow control flag */
-	if (cflag & CRTSCTS)
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	if (cflag & CRTSCTS) {
 		info->flags |= ASYNC_CTS_FLOW;
-	else
+		info->IER |= UART_IER_MSI;
+	} else
 		info->flags &= ~ASYNC_CTS_FLOW;
 	if (cflag & CLOCAL)
 		info->flags &= ~ASYNC_CHECK_CD;
-	else
+	else {
 		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	serial_out(info, UART_IER, info->IER);
 
 	/*
 	 * Set up parity check flag
@@ -1749,12 +1735,17 @@
 static void rs_close(struct tty_struct *tty, struct file * filp)
 {
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
 
 	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
 		return;
 	
-	if (tty_hung_up_p(filp))
+	save_flags(flags); cli();
+	
+	if (tty_hung_up_p(filp)) {
+		restore_flags(flags);
 		return;
+	}
 	
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_close ttys%d, count = %d\n", info->line, info->count);
@@ -1776,8 +1767,10 @@
 		       info->line, info->count);
 		info->count = 0;
 	}
-	if (info->count)
+	if (info->count) {
+		restore_flags(flags);
 		return;
+	}
 	info->flags |= ASYNC_CLOSING;
 	/*
 	 * Save the termios structure, since this port may have
@@ -1787,8 +1780,19 @@
 		info->normal_termios = *tty->termios;
 	if (info->flags & ASYNC_CALLOUT_ACTIVE)
 		info->callout_termios = *tty->termios;
-	if (info->flags & ASYNC_INITIALIZED)
+	if (info->flags & ASYNC_INITIALIZED) {
 		wait_until_sent(tty, 3000); /* 30 seconds timeout */
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		while (!(serial_inp(info, UART_LSR) & UART_LSR_TEMT)) {
+			current->state = TASK_INTERRUPTIBLE;
+			current->timeout = jiffies + info->timeout;
+			schedule();
+		}
+	}
 	shutdown(info);
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
@@ -1815,6 +1819,7 @@
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 			 ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
+	restore_flags(flags);
 }
 
 /*
@@ -1845,7 +1850,7 @@
 {
 	struct wait_queue wait = { current, NULL };
 	int		retval;
-	int		do_clocal = C_CLOCAL(tty);
+	int		do_clocal = 0;
 
 	/*
 	 * If the device is in the middle of being closed, then block
@@ -1893,6 +1898,9 @@
 		return 0;
 	}
 
+	if (info->normal_termios.c_cflag & CLOCAL)
+		do_clocal = 1;
+
 	/*
 	 * Block waiting for the carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
@@ -1990,12 +1998,6 @@
 			return -ENOMEM;
 	}
 	
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-			*tty->termios = info->normal_termios;
-		else 
-			*tty->termios = info->callout_termios;
-	}
 	/*
 	 * Start up serial port
 	 */
@@ -2010,6 +2012,14 @@
 		       retval);
 #endif
 		return retval;
+	}
+
+	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->normal_termios;
+		else 
+			*tty->termios = info->callout_termios;
+		change_speed(info);
 	}
 
 	info->session = current->session;
diff -u --recursive --new-file v1.1.53/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v1.1.53/linux/drivers/char/tty_io.c	Sun Oct  9 12:00:24 1994
+++ linux/drivers/char/tty_io.c	Thu Oct 13 14:07:08 1994
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/tty_io.c
+ *  linux/drivers/char/tty_io.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
@@ -109,9 +109,12 @@
  */
 char *_tty_name(struct tty_struct *tty, char *buf)
 {
-	sprintf(buf, "%s%d", tty->driver.name,
-		MINOR(tty->device) - tty->driver.minor_start +
-		tty->driver.name_base);
+	if (tty)
+		sprintf(buf, "%s%d", tty->driver.name,
+			MINOR(tty->device) - tty->driver.minor_start +
+			tty->driver.name_base);
+	else
+		strcpy(buf, "NULL tty");
 	return buf;
 }
 
@@ -363,6 +366,8 @@
 		if (p->tty == tty)
 			p->tty = NULL;
 	}
+	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS)
+		*tty->termios = tty->driver.init_termios;
 	if (tty->driver.hangup)
 		(tty->driver.hangup)(tty);
 }
@@ -439,6 +444,19 @@
 
 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
 
+void reset_vc(unsigned int new_console)
+{
+	vt_cons[new_console]->vc_mode = KD_TEXT;
+	kbd_table[new_console].kbdmode = VC_XLATE;
+	vt_cons[new_console]->vt_mode.mode = VT_AUTO;
+	vt_cons[new_console]->vt_mode.waitv = 0;
+	vt_cons[new_console]->vt_mode.relsig = 0;
+	vt_cons[new_console]->vt_mode.acqsig = 0;
+	vt_cons[new_console]->vt_mode.frsig = 0;
+	vt_cons[new_console]->vt_pid = -1;
+	vt_cons[new_console]->vt_newvt = -1;
+}
+
 /*
  * Performs the back end of a vt switch
  */
@@ -446,15 +464,17 @@
 {
 	unsigned char old_vc_mode;
 
-	if (new_console == fg_console || new_console >= NR_CONSOLES)
-		return;
+        if (new_console == fg_console)
+                return;
+        if (!vc_cons_allocated(new_console))
+                return;
 
 	/*
 	 * If we're switching, we could be going from KD_GRAPHICS to
 	 * KD_TEXT mode or vice versa, which means we need to blank or
 	 * unblank the screen later.
 	 */
-	old_vc_mode = vt_cons[fg_console].vc_mode;
+	old_vc_mode = vt_cons[fg_console]->vc_mode;
 	update_screen(new_console);
 
 	/*
@@ -462,15 +482,15 @@
 	 * telling it that it has acquired. Also check if it has died and
 	 * clean up (similar to logic employed in change_console())
 	 */
-	if (vt_cons[new_console].vt_mode.mode == VT_PROCESS)
+	if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
 	{
 		/*
 		 * Send the signal as privileged - kill_proc() will
 		 * tell us if the process has gone or something else
 		 * is awry
 		 */
-		if (kill_proc(vt_cons[new_console].vt_pid,
-			      vt_cons[new_console].vt_mode.acqsig,
+		if (kill_proc(vt_cons[new_console]->vt_pid,
+			      vt_cons[new_console]->vt_mode.acqsig,
 			      1) != 0)
 		{
 		/*
@@ -482,16 +502,7 @@
 		 * this outside of VT_PROCESS but there is no single process
 		 * to account for and tracking tty count may be undesirable.
 		 */
-			vt_cons[new_console].vc_mode = KD_TEXT;
-			clr_vc_kbd_mode(kbd_table + new_console, VC_RAW);
-			clr_vc_kbd_mode(kbd_table + new_console, VC_MEDIUMRAW);
- 			vt_cons[new_console].vt_mode.mode = VT_AUTO;
- 			vt_cons[new_console].vt_mode.waitv = 0;
- 			vt_cons[new_console].vt_mode.relsig = 0;
-			vt_cons[new_console].vt_mode.acqsig = 0;
-			vt_cons[new_console].vt_mode.frsig = 0;
-			vt_cons[new_console].vt_pid = -1;
-			vt_cons[new_console].vt_newvt = -1;
+		        reset_vc(new_console);
 		}
 	}
 
@@ -499,9 +510,9 @@
 	 * We do this here because the controlling process above may have
 	 * gone, and so there is now a new vc_mode
 	 */
-	if (old_vc_mode != vt_cons[new_console].vc_mode)
+	if (old_vc_mode != vt_cons[new_console]->vc_mode)
 	{
-		if (vt_cons[new_console].vc_mode == KD_TEXT)
+		if (vt_cons[new_console]->vc_mode == KD_TEXT)
 			unblank_screen();
 		else {
 			timer_active &= ~(1<<BLANK_TIMER);
@@ -521,7 +532,9 @@
  */
 void change_console(unsigned int new_console)
 {
-	if (new_console == fg_console || new_console >= NR_CONSOLES)
+        if (new_console == fg_console)
+                return;
+        if (!vc_cons_allocated(new_console))
 		return;
 
 	/*
@@ -539,15 +552,15 @@
 	 * the user waits just the right amount of time :-) and revert the
 	 * vt to auto control.
 	 */
-	if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS)
+	if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
 	{
 		/*
 		 * Send the signal as privileged - kill_proc() will
 		 * tell us if the process has gone or something else
 		 * is awry
 		 */
-		if (kill_proc(vt_cons[fg_console].vt_pid,
-			      vt_cons[fg_console].vt_mode.relsig,
+		if (kill_proc(vt_cons[fg_console]->vt_pid,
+			      vt_cons[fg_console]->vt_mode.relsig,
 			      1) == 0)
 		{
 			/*
@@ -555,7 +568,7 @@
 			 * return. The process needs to send us a
 			 * VT_RELDISP ioctl to complete the switch.
 			 */
-			vt_cons[fg_console].vt_newvt = new_console;
+			vt_cons[fg_console]->vt_newvt = new_console;
 			return;
 		}
 
@@ -568,16 +581,8 @@
 		 * this outside of VT_PROCESS but there is no single process
 		 * to account for and tracking tty count may be undesirable.
 		 */
-		vt_cons[fg_console].vc_mode = KD_TEXT;
-		clr_vc_kbd_mode(kbd_table + fg_console, VC_RAW);
-		clr_vc_kbd_mode(kbd_table + fg_console, VC_MEDIUMRAW);
-		vt_cons[fg_console].vt_mode.mode = VT_AUTO;
-		vt_cons[fg_console].vt_mode.waitv = 0;
-		vt_cons[fg_console].vt_mode.relsig = 0;
-		vt_cons[fg_console].vt_mode.acqsig = 0;
-		vt_cons[fg_console].vt_mode.frsig = 0;
-		vt_cons[fg_console].vt_pid = -1;
-		vt_cons[fg_console].vt_newvt = -1;
+		reset_vc(fg_console);
+
 		/*
 		 * Fall through to normal (VT_AUTO) handling of the switch...
 		 */
@@ -586,7 +591,7 @@
 	/*
 	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
 	 */
-	if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
+	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
 		return;
 
 	complete_change_console(new_console);
@@ -971,21 +976,12 @@
 	if (tty->count)
 		return;
 	
-	/*
-	 * Make sure there aren't any processes that still think this
-	 * tty is their controlling tty.
-	 */
-	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
-		if ((*p) && (*p)->tty == tty)
-		(*p)->tty = NULL;
-	}
-
 	if (o_tty) {
 		if (o_tty->count)
 			return;
 		tty->driver.other->table[idx] = NULL;
 		tty->driver.other->termios[idx] = NULL;
-		tty->driver.other->termios_locked[idx] = NULL;
+		kfree_s(o_tp, sizeof(struct termios));
 	}
 	
 #ifdef TTY_DEBUG_HANGUP
@@ -993,6 +989,19 @@
 #endif
 
 	/*
+	 * Make sure there aren't any processes that still think this
+	 * tty is their controlling tty.
+	 */
+	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
+		if (*p == 0)
+			continue;
+		if ((*p)->tty == tty)
+			(*p)->tty = NULL;
+		if (o_tty && (*p)->tty == o_tty)
+			(*p)->tty = NULL;
+	}
+
+	/*
 	 * Shutdown the current line discipline, and reset it to
 	 * N_TTY.
 	 */
@@ -1004,9 +1013,7 @@
 	tty->driver.table[idx] = NULL;
 	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
 		tty->driver.termios[idx] = NULL;
-		tty->driver.termios_locked[idx] = NULL;
 		kfree_s(tp, sizeof(struct termios));
-		kfree_s(ltp, sizeof(struct termios));
 	}
 	if (tty == redirect || o_tty == redirect)
 		redirect = NULL;
@@ -1037,10 +1044,6 @@
 		(*o_tty->driver.refcount)--;
 		free_page((unsigned long) o_tty);
 	}
-	if (o_tp)
-		kfree_s(o_tp, sizeof(struct termios));
-	if (o_ltp)
-		kfree_s(o_ltp, sizeof(struct termios));
 }
 
 /*
@@ -1087,13 +1090,14 @@
 #ifdef TTY_DEBUG_HANGUP
 	printk("opening %s...", tty_name(tty));
 #endif
-	if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser())
-		retval = -EBUSY;
-	else if (tty->driver.open)
+	if (tty->driver.open)
 		retval = tty->driver.open(tty, filp);
 	else
 		retval = -ENODEV;
 
+	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser())
+		retval = -EBUSY;
+
 	if (retval) {
 #ifdef TTY_DEBUG_HANGUP
 		printk("error %d in opening %s...", retval, tty_name(tty));
@@ -1396,12 +1400,18 @@
 					return set_selection(arg, tty);
 				case 3:
 					return paste_selection(tty);
+#endif /* CONFIG_SELECTION */
 				case 4:
 					unblank_screen();
 					return 0;
+#ifdef CONFIG_SELECTION
 				case 5:
 					return sel_loadlut(arg);
 				case 6:
+			/* Make it possible to react to Shift+Mousebutton */
+			/* Note that shift_state is an undocumented
+			   kernel-internal variable; programs not closely
+			   related to the kernel should not use this. */
 					put_fs_byte(shift_state,arg);
 					return 0;
 				case 7:
@@ -1451,6 +1461,8 @@
 	int		i;
 	struct file	*filp;
 	
+	if (!tty)
+		return;
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 	if (tty->driver.flush_buffer)
@@ -1562,6 +1574,44 @@
 	tty_drivers = driver;
 	return error;
 }
+
+/*
+ * Called by a tty driver to unregister itself.
+ */
+int tty_unregister_driver(struct tty_driver *driver)
+{
+	int	retval;
+	struct tty_driver *p;
+	int	found = 0;
+	int	major_inuse = 0;
+	
+	if (driver->refcount)
+		return -EBUSY;
+
+	for (p = tty_drivers; p; p = p->next) {
+		if (p == driver)
+			found++;
+		else if (p->major == driver->major)
+			major_inuse++;
+	}
+
+	if (!major_inuse) {
+		retval = unregister_chrdev(driver->major, driver->name);
+		if (retval)
+			return retval;
+	}
+
+	if (driver->prev)
+		driver->prev->next = driver->next;
+	else
+		tty_drivers = driver->next;
+	
+	if (driver->next)
+		driver->next = driver->next->prev;
+
+	return 0;
+}
+
 
 /*
  * Initialize the console device. This is called *early*, so
diff -u --recursive --new-file v1.1.53/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v1.1.53/linux/drivers/char/tty_ioctl.c	Sun Oct  9 12:00:24 1994
+++ linux/drivers/char/tty_ioctl.c	Thu Oct 13 14:07:08 1994
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/drivers/char/tty_ioctl.c
+ *  linux/drivers/char/tty_ioctl.c
  *
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *
@@ -314,32 +314,22 @@
 					    (unsigned long *) arg);
 			return 0;
 		case TIOCGLCKTRMIOS:
-			retval = verify_area(VERIFY_READ, (void *) arg,
-					     sizeof (unsigned long));
-			if (retval)
-				return retval;
-			arg = get_fs_long((unsigned long *) arg);
 			retval = verify_area(VERIFY_WRITE, (void *) arg,
 					     sizeof (struct termios));
 			if (retval)
 				return retval;
 			memcpy_tofs((struct termios *) arg,
-				    &real_tty->termios_locked,
+				    real_tty->termios_locked,
 				    sizeof (struct termios));
 			return 0;
 		case TIOCSLCKTRMIOS:
 			if (!suser())
 				return -EPERM;
 			retval = verify_area(VERIFY_READ, (void *) arg,
-					     sizeof (unsigned long));
-			if (retval)
-				return retval;
-			arg = get_fs_long((unsigned long *) arg);
-			retval = verify_area(VERIFY_READ, (void *) arg,
 					     sizeof (struct termios));
 			if (retval)
 				return retval;
-			memcpy_fromfs(&real_tty->termios_locked,
+			memcpy_fromfs(real_tty->termios_locked,
 				      (struct termios *) arg,
 				      sizeof (struct termios));
 			return 0;
diff -u --recursive --new-file v1.1.53/linux/drivers/char/uni_to_437.c linux/drivers/char/uni_to_437.c
--- v1.1.53/linux/drivers/char/uni_to_437.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/uni_to_437.c	Thu Oct 13 14:07:08 1994
@@ -0,0 +1,169 @@
+/*
+ * non-Latin-1 (>0x00ff) Unicode -> IBM CP437 conversion hash table
+ * Markus Kuhn
+ */
+#define IBM_HASHSIZE   146
+#define IBM_HASHSTEP    19
+#define IBM_HASHLEVEL    4
+static struct {
+      unsigned short ucs;        /* a Unicode code */
+      unsigned char ibm437;      /* the corresponding IBM code */
+} ibm_hash[IBM_HASHSIZE] = {
+  {0x221a,0xfb}, {0x2580,0xdf}, {0x2524,0xb4}, {0xffff,0x00}, {0x221e,0xec}, 
+  {0x20a7,0x9e}, {0x2126,0xea}, {0x253c,0xc5}, {0xffff,0x00}, {0x2588,0xdb}, 
+  {0x2666,0x04}, {0x2190,0x1b}, {0x2193,0x19}, {0x2665,0x03}, {0x2195,0x12}, 
+  {0x2663,0x05}, {0x2660,0x06}, {0x2590,0xde}, {0x2022,0x07}, {0x2592,0xb1}, 
+  {0x266c,0x0e}, {0x2502,0xb3}, {0x266a,0x0d}, {0x250c,0xda}, {0x258c,0xdd}, 
+  {0xffff,0x00}, {0xffff,0x00}, {0xffff,0x00}, {0xffff,0x00}, {0x2191,0x18}, 
+  {0x2261,0xf0}, {0x2514,0xc0}, {0x2192,0x1a}, {0x2264,0xf3}, {0x2194,0x1d}, 
+  {0x2591,0xb0}, {0x0393,0xe2}, {0x2593,0xb2}, {0x2500,0xc4}, {0x251c,0xc3}, 
+  {0x2205,0xed}, {0xffff,0x00}, {0x266b,0x0e}, {0x2518,0xd9}, {0x203c,0x13}, 
+  {0xffff,0x00}, {0x2642,0x0b}, {0x2564,0xd1}, {0x2640,0x0c}, {0x2566,0xcb}, 
+  {0x2561,0xb5}, {0x2560,0xcc}, {0x2563,0xb9}, {0x2562,0xb6}, {0x2510,0xbf}, 
+  {0x256c,0xce}, {0x2008,0x00}, {0x03a6,0xe8}, {0x2569,0xca}, {0x2568,0xd0}, 
+  {0x256b,0xd7}, {0x256a,0xd8}, {0x03a9,0xea}, {0xffff,0x00}, {0xffff,0x00}, 
+  {0x25c0,0x11}, {0x0398,0xe9}, {0x2567,0xcf}, {0xffff,0x00}, {0x2248,0xf7}, 
+  {0x03b1,0xe0}, {0x03a3,0xe4}, {0x2265,0xf2}, {0xffff,0x00}, {0x25cb,0x09}, 
+  {0x03b4,0xeb}, {0x2320,0xf4}, {0xffff,0x00}, {0xffff,0x00}, {0xffff,0x00}, 
+  {0x25c4,0x11}, {0xffff,0x00}, {0xffff,0x00}, {0x03bc,0xe6}, {0x2565,0xd2}, 
+  {0xffff,0x00}, {0x22c5,0xf9}, {0x2302,0x7f}, {0x25d9,0x0a}, {0x25d8,0x08}, 
+  {0xffff,0x00}, {0x03c4,0xe7}, {0xffff,0x00}, {0xffff,0x00}, {0x2555,0xb8}, 
+  {0x2554,0xc9}, {0x2557,0xbb}, {0x2556,0xb7}, {0x2551,0xba}, {0x2550,0xcd}, 
+  {0x2553,0xd6}, {0x2552,0xd5}, {0x255d,0xbc}, {0x255c,0xbd}, {0x255f,0xc7}, 
+  {0x2310,0xa9}, {0x2559,0xd3}, {0x2558,0xd4}, {0x255b,0xbe}, {0x255a,0xc8}, 
+  {0xffff,0x00}, {0x0192,0x9f}, {0x2319,0x1c}, {0x2321,0xf5}, {0xffff,0x00}, 
+  {0x25a0,0xfe}, {0xffff,0x00}, {0x21a8,0x17}, {0x263c,0x0f}, {0x25ac,0x16}, 
+  {0x263a,0x01}, {0x263b,0x02}, {0x03c3,0xe5}, {0xffff,0x00}, {0x255e,0xc6}, 
+  {0x03c0,0xe3}, {0x03b2,0xe1}, {0x2300,0xed}, {0xffff,0x00}, {0x25b6,0x10}, 
+  {0x207f,0xfc}, {0xffff,0x00}, {0x2208,0xee}, {0x25b2,0x1e}, {0x220e,0xfe}, 
+  {0x25bc,0x1f}, {0x212b,0x8f}, {0x252c,0xc2}, {0xffff,0x00}, {0x2229,0xef}, 
+  {0xffff,0x00}, {0x25ba,0x10}, {0xffff,0x00}, {0x2584,0xdc}, {0xffff,0x00}, 
+  {0x2534,0xc1}
+};
+
+/*
+ * Find the correct PC character set (CP437) code for a 
+ * UCS character outside Latin-1 by hash lookup in ibm_hash[].
+ * Return -1 if character not available, return -2 for zero-width
+ * space characters.
+ */
+int
+conv_uni_to_pc(unsigned long ucs)
+{
+      int c = -1;
+      int i, h;
+      
+      if (ucs == 0xffff || ucs == 0xfffe)
+              return -1;
+      if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
+              return -2;
+      
+      h = (ucs ^ (ucs >> 8)) % IBM_HASHSIZE;
+      for (i = 0; i < IBM_HASHLEVEL && c == -1; i++)
+              if (ibm_hash[h].ucs == ucs)
+                      c = ibm_hash[h].ibm437;
+              else
+                      if ((h += IBM_HASHSTEP) >= IBM_HASHSIZE)
+                              h -= IBM_HASHSIZE;
+      
+      return c;
+}
+
+#if 0
+/* 
+ * Conversion from unicode to ibm pc character set (code page 437)
+ *
+ * aeb@cwi.nl, Dec 1993
+ */
+#define NOTFOUND	254	/* small square */
+
+static struct unipc {
+	long unicode;
+	unsigned char pc;
+} uni_to_pc[255] = {
+	{0x0020, 0x20},  {0x0021, 0x21},  {0x0022, 0x22},  {0x0023, 0x23},
+	{0x0024, 0x24},  {0x0025, 0x25},  {0x0026, 0x26},  {0x0027, 0x27},
+	{0x0028, 0x28},  {0x0029, 0x29},  {0x002A, 0x2A},  {0x002B, 0x2B},
+	{0x002C, 0x2C},  {0x002D, 0x2D},  {0x002E, 0x2E},  {0x002F, 0x2F},
+	{0x0030, 0x30},  {0x0031, 0x31},  {0x0032, 0x32},  {0x0033, 0x33},
+	{0x0034, 0x34},  {0x0035, 0x35},  {0x0036, 0x36},  {0x0037, 0x37},
+	{0x0038, 0x38},  {0x0039, 0x39},  {0x003A, 0x3A},  {0x003B, 0x3B},
+	{0x003C, 0x3C},  {0x003D, 0x3D},  {0x003E, 0x3E},  {0x003F, 0x3F},
+	{0x0040, 0x40},  {0x0041, 0x41},  {0x0042, 0x42},  {0x0043, 0x43},
+	{0x0044, 0x44},  {0x0045, 0x45},  {0x0046, 0x46},  {0x0047, 0x47},
+	{0x0048, 0x48},  {0x0049, 0x49},  {0x004A, 0x4A},  {0x004B, 0x4B},
+	{0x004C, 0x4C},  {0x004D, 0x4D},  {0x004E, 0x4E},  {0x004F, 0x4F},
+	{0x0050, 0x50},  {0x0051, 0x51},  {0x0052, 0x52},  {0x0053, 0x53},
+	{0x0054, 0x54},  {0x0055, 0x55},  {0x0056, 0x56},  {0x0057, 0x57},
+	{0x0058, 0x58},  {0x0059, 0x59},  {0x005A, 0x5A},  {0x005B, 0x5B},
+	{0x005C, 0x5C},  {0x005D, 0x5D},  {0x005E, 0x5E},  {0x005F, 0x5F},
+	{0x0060, 0x60},  {0x0061, 0x61},  {0x0062, 0x62},  {0x0063, 0x63},
+	{0x0064, 0x64},  {0x0065, 0x65},  {0x0066, 0x66},  {0x0067, 0x67},
+	{0x0068, 0x68},  {0x0069, 0x69},  {0x006A, 0x6A},  {0x006B, 0x6B},
+	{0x006C, 0x6C},  {0x006D, 0x6D},  {0x006E, 0x6E},  {0x006F, 0x6F},
+	{0x0070, 0x70},  {0x0071, 0x71},  {0x0072, 0x72},  {0x0073, 0x73},
+	{0x0074, 0x74},  {0x0075, 0x75},  {0x0076, 0x76},  {0x0077, 0x77},
+	{0x0078, 0x78},  {0x0079, 0x79},  {0x007A, 0x7A},  {0x007B, 0x7B},
+	{0x007C, 0x7C},  {0x007D, 0x7D},  {0x007E, 0x7E},  {0x00A0, 0xFF},
+	{0x00A1, 0xAD},  {0x00A2, 0x9B},  {0x00A3, 0x9C},  {0x00A5, 0x9D},
+	{0x00A7, 0x15},  {0x00AA, 0xA6},  {0x00AB, 0xAE},  {0x00AC, 0xAA},
+	{0x00B0, 0xF8},  {0x00B1, 0xF1},  {0x00B2, 0xFD},  {0x00B5, 0xE6},
+	{0x00B6, 0x14},  {0x00B7, 0xFA},  {0x00BA, 0xA7},  {0x00BB, 0xAF},
+	{0x00BC, 0xAC},  {0x00BD, 0xAB},  {0x00BF, 0xA8},  {0x00C4, 0x8E},
+	{0x00C5, 0x8F},  {0x00C6, 0x92},  {0x00C7, 0x80},  {0x00C9, 0x90},
+	{0x00D1, 0xA5},  {0x00D6, 0x99},  {0x00DC, 0x9A},  {0x00DF, 0xE1},
+	{0x00E0, 0x85},  {0x00E1, 0xA0},  {0x00E2, 0x83},  {0x00E4, 0x84},
+	{0x00E5, 0x86},  {0x00E6, 0x91},  {0x00E7, 0x87},  {0x00E8, 0x8A},
+	{0x00E9, 0x82},  {0x00EA, 0x88},  {0x00EB, 0x89},  {0x00EC, 0x8D},
+	{0x00ED, 0xA1},  {0x00EE, 0x8C},  {0x00EF, 0x8B},  {0x00F1, 0xA4},
+	{0x00F2, 0x95},  {0x00F3, 0xA2},  {0x00F4, 0x93},  {0x00F6, 0x94},
+	{0x00F7, 0xF6},  {0x00F9, 0x97},  {0x00FA, 0xA3},  {0x00FB, 0x96},
+	{0x00FC, 0x81},  {0x00FF, 0x98},  {0x0192, 0x9F},  {0x0393, 0xE2},
+	{0x0398, 0xE9},  {0x03A3, 0xE4},  {0x03A6, 0xE8},  {0x03A9, 0xEA},
+	{0x03B1, 0xE0},  {0x03B4, 0xEB},  {0x03B5, 0xEE},  {0x03C0, 0xE3},
+	{0x03C3, 0xE5},  {0x03C4, 0xE7},  {0x03C6, 0xED},  {0x2022, 0x07},
+	{0x203C, 0x13},  {0x207F, 0xFC},  {0x20A7, 0x9E},  {0x2190, 0x1B},
+	{0x2191, 0x18},  {0x2192, 0x1A},  {0x2193, 0x19},  {0x2194, 0x1D},
+	{0x2195, 0x12},  {0x21A8, 0x17},  {0x2219, 0xF9},  {0x221A, 0xFB},
+	{0x221E, 0xEC},  {0x221F, 0x1C},  {0x2229, 0xEF},  {0x2248, 0xF7},
+	{0x2261, 0xF0},  {0x2264, 0xF3},  {0x2265, 0xF2},  {0x2302, 0x7F},
+	{0x2310, 0xA9},  {0x2320, 0xF4},  {0x2321, 0xF5},  {0x2500, 0xC4},
+	{0x2502, 0xB3},  {0x250C, 0xDA},  {0x2510, 0xBF},  {0x2514, 0xC0},
+	{0x2518, 0xD9},  {0x251C, 0xC3},  {0x2524, 0xB4},  {0x252C, 0xC2},
+	{0x2534, 0xC1},  {0x253C, 0xC5},  {0x2550, 0xCD},  {0x2551, 0xBA},
+	{0x2552, 0xD5},  {0x2553, 0xD6},  {0x2554, 0xC9},  {0x2555, 0xB8},
+	{0x2556, 0xB7},  {0x2557, 0xBB},  {0x2558, 0xD4},  {0x2559, 0xD3},
+	{0x255A, 0xC8},  {0x255B, 0xBE},  {0x255C, 0xBD},  {0x255D, 0xBC},
+	{0x255E, 0xC6},  {0x255F, 0xC7},  {0x2560, 0xCC},  {0x2561, 0xB5},
+	{0x2562, 0xB6},  {0x2563, 0xB9},  {0x2564, 0xD1},  {0x2565, 0xD2},
+	{0x2566, 0xCB},  {0x2567, 0xCF},  {0x2568, 0xD0},  {0x2569, 0xCA},
+	{0x256A, 0xD8},  {0x256B, 0xD7},  {0x256C, 0xCE},  {0x2580, 0xDF},
+	{0x2584, 0xDC},  {0x2588, 0xDB},  {0x258C, 0xDD},  {0x2590, 0xDE},
+	{0x2591, 0xB0},  {0x2592, 0xB1},  {0x2593, 0xB2},  {0x25A0, 0xFE},
+	{0x25AC, 0x16},  {0x25B2, 0x1E},  {0x25BA, 0x10},  {0x25BC, 0x1F},
+	{0x25C4, 0x11},  {0x25CB, 0x09},  {0x25D8, 0x08},  {0x25D9, 0x0A},
+	{0x263A, 0x01},  {0x263B, 0x02},  {0x263C, 0x0F},  {0x2640, 0x0C},
+	{0x2642, 0x0B},  {0x2660, 0x06},  {0x2663, 0x05},  {0x2665, 0x03},
+	{0x2666, 0x04},  {0x266A, 0x0D},  {0x266B, 0x0E}
+};
+
+unsigned char
+conv_uni_to_pc(unsigned long u) {
+	/* Binary search - no doubt this can be sped up using hash codes */
+	/* (or by table lookup if we are in the first half) */
+	int step = 128;
+	struct unipc *up = uni_to_pc + step - 1;
+
+	while(1) {
+		if(up->unicode == u)
+			return up->pc;
+		step >>= 1;
+		if(!step)
+			return NOTFOUND;
+		if(up->unicode < u)
+			up += step;
+		else
+			up -= step;
+	}
+}
+#endif
diff -u --recursive --new-file v1.1.53/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v1.1.53/linux/drivers/char/vt.c	Mon Aug 15 11:47:07 1994
+++ linux/drivers/char/vt.c	Thu Oct 13 14:07:08 1994
@@ -1,8 +1,10 @@
 /*
- *  kernel/chr_drv/vt.c
+ *  linux/drivers/char/vt.c
  *
  *  Copyright (C) 1992 obz under the linux copyright
+ *
  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
+ *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
  */
 
 #include <linux/types.h>
@@ -14,6 +16,7 @@
 #include <linux/kd.h>
 #include <linux/vt.h>
 #include <linux/string.h>
+#include <linux/malloc.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -24,6 +27,8 @@
 
 extern struct tty_driver console_driver;
 
+#define VT_IS_IN_USE(i)	(console_driver.table[i] && console_driver.table[i]->count)
+
 /*
  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  * experimentation and study of X386 SYSV handling.
@@ -31,13 +36,13 @@
  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
- * always treat our set of vt as numbered 1..NR_CONSOLES (corresponding to
- * ttys 0..NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
+ * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
+ * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  * to the current console is done by the main ioctl code.
  */
 
-struct vt_struct vt_cons[NR_CONSOLES];
+struct vt_struct *vt_cons[MAX_NR_CONSOLES];
 
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
 
@@ -46,6 +51,8 @@
 extern void complete_change_console(unsigned int new_console);
 extern int vt_waitactive(void);
 
+extern unsigned int keymap_count;
+
 /*
  * routines to load custom translation table and EGA/VGA font from console.c
  */
@@ -118,14 +125,15 @@
 int vt_ioctl(struct tty_struct *tty, struct file * file,
 	     unsigned int cmd, unsigned long arg)
 {
-	int console, i;
+	int i;
+	unsigned int console;
 	unsigned char ucval;
 	struct kbd_struct * kbd;
 	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 
 	console = vt->vc_num;
 
-	if (console < 0 || console >= NR_CONSOLES)
+	if (!vc_cons_allocated(console)) 	/* impossible? */
 		return -ENOIOCTLCMD;
 
 	kbd = kbd_table + console;
@@ -189,9 +197,9 @@
 		default:
 			return -EINVAL;
 		}
-		if (vt_cons[console].vc_mode == (unsigned char) arg)
+		if (vt_cons[console]->vc_mode == (unsigned char) arg)
 			return 0;
-		vt_cons[console].vc_mode = (unsigned char) arg;
+		vt_cons[console]->vc_mode = (unsigned char) arg;
 		if (console != fg_console)
 			return 0;
 		/*
@@ -208,7 +216,7 @@
 	case KDGETMODE:
 		i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 		if (!i)
-			put_fs_long(vt_cons[console].vc_mode, (unsigned long *) arg);
+			put_fs_long(vt_cons[console]->vc_mode, (unsigned long *) arg);
 		return i;
 
 	case KDMAPDISP:
@@ -222,18 +230,19 @@
 	case KDSKBMODE:
 		switch(arg) {
 		  case K_RAW:
-		        set_vc_kbd_mode(kbd, VC_RAW);
-			clr_vc_kbd_mode(kbd, VC_MEDIUMRAW);
+			kbd->kbdmode = VC_RAW;
 			break;
 		  case K_MEDIUMRAW:
-			clr_vc_kbd_mode(kbd, VC_RAW);
-			set_vc_kbd_mode(kbd, VC_MEDIUMRAW);
+			kbd->kbdmode = VC_MEDIUMRAW;
 			break;
 		  case K_XLATE:
-			clr_vc_kbd_mode(kbd, VC_RAW);
-			clr_vc_kbd_mode(kbd, VC_MEDIUMRAW);
+			kbd->kbdmode = VC_XLATE;
 			compute_shiftstate();
 			break;
+		  case K_UNICODE:
+			kbd->kbdmode = VC_UNICODE;
+			compute_shiftstate();
+			break;
 		  default:
 			return -EINVAL;
 		}
@@ -244,8 +253,9 @@
 	case KDGKBMODE:
 		i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 		if (!i) {
-			ucval = (vc_kbd_mode(kbd, VC_RAW) ? K_RAW :
-				 vc_kbd_mode(kbd, VC_MEDIUMRAW) ? K_MEDIUMRAW :
+			ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
+				 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
+				 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 				 K_XLATE);
 			put_fs_long(ucval, (unsigned long *) arg);
 		}
@@ -278,6 +288,7 @@
 	case KDGKBENT:
 	{
 		struct kbentry * const a = (struct kbentry *)arg;
+		ushort *key_map, val;
 		u_char s;
 
 		i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
@@ -285,15 +296,23 @@
 			return i;
 		if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
 			return -EINVAL;
-		if ((s = get_fs_byte((char *) &a->kb_table)) >= NR_KEYMAPS)
+		if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
 			return -EINVAL;
-		put_fs_word(key_map[s][i], (short *) &a->kb_value);
+		key_map = key_maps[s];
+		if (key_map) {
+		    val = U(key_map[i]);
+		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
+			val = K_HOLE;
+		} else
+		    val = (i ? K_HOLE : K_NOSUCHMAP);
+		put_fs_word(val, (short *) &a->kb_value);
 		return 0;
 	}
 
 	case KDSKBENT:
 	{
 		const struct kbentry * a = (struct kbentry *)arg;
+		ushort *key_map;
 		u_char s;
 		u_short v;
 
@@ -302,20 +321,55 @@
 			return i;
 		if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
 			return -EINVAL;
-		if ((s = get_fs_byte((char *) &a->kb_table)) >= NR_KEYMAPS)
+		if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
 			return -EINVAL;
-		if (KTYP(v = get_fs_word(&a->kb_value)) >= NR_TYPES)
+		v = get_fs_word(&a->kb_value);
+		if (!i && v == K_NOSUCHMAP) {
+			/* disallocate map */
+			key_map = key_maps[s];
+			if (key_map) {
+			    key_maps[s] = 0;
+			    if (key_map[0] == U(K_ALLOCATED)) {
+				kfree_s(key_map, sizeof(plain_map));
+				keymap_count--;
+			    }
+			}
+			return 0;
+		}
+
+		if (KTYP(v) < NR_TYPES) {
+		    if (KVAL(v) > max_vals[KTYP(v)])
 			return -EINVAL;
-		if (KVAL(v) > max_vals[KTYP(v)])
+		} else
+		    if (kbd->kbdmode != VC_UNICODE)
 			return -EINVAL;
+
+		/* assignment to entry 0 only tests validity of args */
+		if (!i)
+			return 0;
+
+		if (!(key_map = key_maps[s])) {
+			if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
+				return -EPERM;
+
+			key_map = (ushort *) kmalloc(sizeof(plain_map),
+						     GFP_KERNEL);
+			if (!key_map)
+				return -ENOMEM;
+			key_maps[s] = key_map;
+			key_map[0] = U(K_ALLOCATED);
+			for (s = 1; s < NR_KEYS; s++)
+				key_map[s] = U(K_HOLE);
+			keymap_count++;
+		}
 		/*
 		 * Only the Superuser can set or unset the Secure
 		 * Attention Key.
 		 */
-		if (((key_map[s][i] == K_SAK) || (v == K_SAK)) &&
+		if (((key_map[i] == U(K_SAK)) || (v == K_SAK)) &&
 		    !suser())
 			return -EPERM;
-		key_map[s][i] = v;
+		key_map[i] = U(v);
 		return 0;
 	}
 
@@ -324,65 +378,91 @@
 		struct kbsentry *a = (struct kbsentry *)arg;
 		char *p;
 		u_char *q;
+		int sz;
 
 		i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 		if (i)
 			return i;
-		if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC || i < 0)
+		if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
 			return -EINVAL;
+		sz = sizeof(a->kb_string) - 1; /* sz should have been
+						  a struct member */
 		q = a->kb_string;
 		p = func_table[i];
-		if(!p) {
-		    /* beware of tables generated for a smaller NR_FUNC */
-		    printk("KDGKBSENT error: func_table[%d] is nil.\n",
-			   i);
-		    return -EINVAL;
-		}
-		for ( ; *p; p++)
-			put_fs_byte(*p, q++);
+		if(p)
+			for ( ; *p && sz; p++, sz--)
+				put_fs_byte(*p, q++);
 		put_fs_byte(0, q);
-		return 0;
+		return ((p && *p) ? -EOVERFLOW : 0);
 	}
 
 	case KDSKBSENT:
 	{
 		struct kbsentry * const a = (struct kbsentry *)arg;
 		int delta;
-		char *first_free;
-		int k;
+		char *first_free, *fj, *fnw;
+		int j, k, sz;
 		u_char *p;
 		char *q;
 
 		i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 		if (i)
 			return i;
-		if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC)
+		if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC)
 			return -EINVAL;
 		q = func_table[i];
-		if (!q) {
-		    /* beware of tables generated for a smaller NR_FUNC */
-		    printk("KDSKBSENT error: func_table[%d] is nil.\n",
-			   i);
-		    return -EINVAL;
-		}
-		delta = -strlen(q);
-		for (p = a->kb_string; get_fs_byte(p); p++)
+
+		first_free = funcbufptr + (funcbufsize - funcbufleft);
+		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
+		if (j < MAX_NR_FUNC)
+			fj = func_table[j];
+		else
+			fj = first_free;
+
+		delta = (q ? -strlen(q) : 1);
+		sz = sizeof(a->kb_string); 	/* sz should have been
+						   a struct member */
+		for (p = a->kb_string; get_fs_byte(p) && sz; p++,sz--)
 			delta++;
-		first_free = func_table[NR_FUNC - 1] +
-			strlen(func_table[NR_FUNC - 1]) + 1;
-		if (
-			delta > 0 &&
-			first_free + delta > func_buf + FUNC_BUFSIZE
-		)
-			return -EINVAL;
-		if (i < NR_FUNC - 1) {
-			memmove(
-				func_table[i + 1] + delta,
-				func_table[i + 1],
-				first_free - func_table[i + 1]);
-			for (k = i + 1; k < NR_FUNC; k++)
-			    if (func_table[k])  /* just to be sure */
+		if (!sz)
+			return -EOVERFLOW;
+		if (delta <= funcbufleft) { 	/* it fits in current buf */
+		    if (j < MAX_NR_FUNC) {
+			memmove(fj + delta, fj, first_free - fj);
+			for (k = j; k < MAX_NR_FUNC; k++)
+			    if (func_table[k])
 				func_table[k] += delta;
+		    }
+		    if (!q)
+		      func_table[i] = fj;
+		    funcbufleft -= delta;
+		} else {			/* allocate a larger buffer */
+		    sz = 256;
+		    while (sz < funcbufsize - funcbufleft + delta)
+		      sz <<= 1;
+		    fnw = (char *) kmalloc(sz, GFP_KERNEL);
+		    if(!fnw)
+		      return -ENOMEM;
+
+		    if (!q)
+		      func_table[i] = fj;
+		    if (fj > funcbufptr)
+			memmove(fnw, funcbufptr, fj - funcbufptr);
+		    for (k = 0; k < j; k++)
+		      if (func_table[k])
+			func_table[k] = fnw + (func_table[k] - funcbufptr);
+
+		    if (first_free > fj) {
+			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
+			for (k = j; k < MAX_NR_FUNC; k++)
+			  if (func_table[k])
+			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
+		    }
+		    if (funcbufptr != func_buf)
+		      kfree_s(funcbufptr, funcbufsize);
+		    funcbufptr = fnw;
+		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
+		    funcbufsize = sz;
 		}
 		for (p = a->kb_string, q = func_table[i]; ; p++, q++)
 			if (!(*q = get_fs_byte(p)))
@@ -392,11 +472,11 @@
 
 	case KDGKBDIACR:
 	{
-	        struct kbdiacrs *a = (struct kbdiacrs *)arg;
+		struct kbdiacrs *a = (struct kbdiacrs *)arg;
 
-	        i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
+		i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
 		if (i)
-		        return i;
+			return i;
 		put_fs_long(accent_table_size, &a->kb_cnt);
 		memcpy_tofs(a->kbdiacr, accent_table,
 			    accent_table_size*sizeof(struct kbdiacr));
@@ -405,34 +485,51 @@
 
 	case KDSKBDIACR:
 	{
-	        struct kbdiacrs *a = (struct kbdiacrs *)arg;
+		struct kbdiacrs *a = (struct kbdiacrs *)arg;
 		unsigned int ct;
 
-	        i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
+		i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 		if (i)
-		        return i;
+			return i;
 		ct = get_fs_long(&a->kb_cnt);
 		if (ct >= MAX_DIACR)
-		        return -EINVAL;
+			return -EINVAL;
 		accent_table_size = ct;
 		memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 		return 0;
 	}
 
-	case KDGETLED:
+	/* the ioctls below read/set the flags usually shown in the leds */
+	/* don't use them - they will go away without warning */
+	case KDGKBLED:
 		i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 		if (i)
 			return i;
-		put_fs_byte(kbd->ledstate, (char *) arg);
+		put_fs_byte(kbd->ledflagstate |
+			    (kbd->default_ledflagstate << 4), (char *) arg);
 		return 0;
 
-	case KDSETLED:
-		if (arg & ~7)
+	case KDSKBLED:
+		if (arg & ~0x77)
 			return -EINVAL;
-		kbd->ledstate = arg;
+		kbd->ledflagstate = (arg & 7);
+		kbd->default_ledflagstate = ((arg >> 4) & 7);
 		set_leds();
 		return 0;
 
+	/* the ioctls below only set the lights, not the functions */
+	/* for those, see KDGKBLED and KDSKBLED above */
+	case KDGETLED:
+		i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
+		if (i)
+			return i;
+		put_fs_byte(getledstate(), (char *) arg);
+		return 0;
+
+	case KDSETLED:
+		setledstate(kbd, arg);
+		return 0;
+
 	case VT_SETMODE:
 	{
 		struct vt_mode *vtmode = (struct vt_mode *)arg;
@@ -444,14 +541,14 @@
 		mode = get_fs_byte(&vtmode->mode);
 		if (mode != VT_AUTO && mode != VT_PROCESS)
 			return -EINVAL;
-		vt_cons[console].vt_mode.mode = mode;
-		vt_cons[console].vt_mode.waitv = get_fs_byte(&vtmode->waitv);
-		vt_cons[console].vt_mode.relsig = get_fs_word(&vtmode->relsig);
-		vt_cons[console].vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
+		vt_cons[console]->vt_mode.mode = mode;
+		vt_cons[console]->vt_mode.waitv = get_fs_byte(&vtmode->waitv);
+		vt_cons[console]->vt_mode.relsig = get_fs_word(&vtmode->relsig);
+		vt_cons[console]->vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
 		/* the frsig is ignored, so we set it to 0 */
-		vt_cons[console].vt_mode.frsig = 0;
-		vt_cons[console].vt_pid = current->pid;
-		vt_cons[console].vt_newvt = 0;
+		vt_cons[console]->vt_mode.frsig = 0;
+		vt_cons[console]->vt_pid = current->pid;
+		vt_cons[console]->vt_newvt = 0;
 		return 0;
 	}
 
@@ -462,17 +559,18 @@
 		i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 		if (i)
 			return i;
-		put_fs_byte(vt_cons[console].vt_mode.mode, &vtmode->mode);
-		put_fs_byte(vt_cons[console].vt_mode.waitv, &vtmode->waitv);
-		put_fs_word(vt_cons[console].vt_mode.relsig, &vtmode->relsig);
-		put_fs_word(vt_cons[console].vt_mode.acqsig, &vtmode->acqsig);
-		put_fs_word(vt_cons[console].vt_mode.frsig, &vtmode->frsig);
+		put_fs_byte(vt_cons[console]->vt_mode.mode, &vtmode->mode);
+		put_fs_byte(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
+		put_fs_word(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
+		put_fs_word(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
+		put_fs_word(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 		return 0;
 	}
 
 	/*
 	 * Returns global vt state. Note that VT 0 is always open, since
 	 * it's an alias for the current VT, and people can't use it here.
+	 * We cannot return state for more than 16 VTs, since v_state is short.
 	 */
 	case VT_GETSTATE:
 	{
@@ -484,7 +582,7 @@
 			return i;
 		put_fs_word(fg_console + 1, &vtstat->v_active);
 		state = 1;	/* /dev/tty0 is always open */
-		for (i = 0, mask = 2; i < NR_CONSOLES; ++i, mask <<= 1)
+		for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 			if (console_driver.table[i] &&
 			    console_driver.table[i]->count > 0)
 				state |= mask;
@@ -499,32 +597,36 @@
 		i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
 		if (i)
 			return i;
-		for (i = 0; i < NR_CONSOLES; ++i)
-			if (!console_driver.table[i] ||
-			    console_driver.table[i]->count == 0)
+		for (i = 0; i < MAX_NR_CONSOLES; ++i)
+			if (! VT_IS_IN_USE(i))
 				break;
-		put_fs_long(i < NR_CONSOLES ? (i+1) : -1,
+		put_fs_long(i < MAX_NR_CONSOLES ? (i+1) : -1,
 			    (unsigned long *)arg);
 		return 0;
 
 	/*
 	 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
-	 * with num >= 1 (switches to vt 0, our console) are not allowed, just
-	 * to preserve sanity.
+	 * with num >= 1 (switches to vt 0, our console, are not allowed, just
+	 * to preserve sanity).
 	 */
 	case VT_ACTIVATE:
-		if (arg == 0 || arg > NR_CONSOLES)
+		if (arg == 0 || arg > MAX_NR_CONSOLES)
 			return -ENXIO;
-		change_console(arg - 1);
+		arg--;
+		i = vc_allocate(arg);
+		if (i)
+			return i;
+		change_console(arg);
 		return 0;
 
 	/*
 	 * wait until the specified VT has been activated
 	 */
 	case VT_WAITACTIVE:
-		if (arg == 0 || arg > NR_CONSOLES)
+		if (arg == 0 || arg > MAX_NR_CONSOLES)
 			return -ENXIO;
-		while (fg_console != arg - 1)
+		arg--;
+		while (fg_console != arg)
 		{
 			if (vt_waitactive() < 0)
 				return -EINTR;
@@ -542,20 +644,20 @@
 	 *	2:	completed switch-to OK
 	 */
 	case VT_RELDISP:
-		if (vt_cons[console].vt_mode.mode != VT_PROCESS)
+		if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 			return -EINVAL;
 
 		/*
 		 * Switching-from response
 		 */
-		if (vt_cons[console].vt_newvt >= 0)
+		if (vt_cons[console]->vt_newvt >= 0)
 		{
 			if (arg == 0)
 				/*
 				 * Switch disallowed, so forget we were trying
 				 * to do it.
 				 */
-				vt_cons[console].vt_newvt = -1;
+				vt_cons[console]->vt_newvt = -1;
 
 			else
 			{
@@ -563,8 +665,11 @@
 				 * The current vt has been released, so
 				 * complete the switch.
 				 */
-				int newvt = vt_cons[console].vt_newvt;
-				vt_cons[console].vt_newvt = -1;
+				int newvt = vt_cons[console]->vt_newvt;
+				vt_cons[console]->vt_newvt = -1;
+				i = vc_allocate(newvt);
+				if (i)
+					return i;
 				complete_change_console(newvt);
 			}
 		}
@@ -582,6 +687,45 @@
 		}
 
 		return 0;
+
+	 /*
+	  * Disallocate memory associated to VT (but leave VT1)
+	  */
+	 case VT_DISALLOCATE:
+		if (arg > MAX_NR_CONSOLES)
+			return -ENXIO;
+		if (arg == 0) {
+		    /* disallocate all unused consoles, but leave 0 */
+		    for (i=1; i<MAX_NR_CONSOLES; i++)
+		      if (! VT_IS_IN_USE(i)) {
+			  if (i == fg_console)
+			    change_console(0);
+			  vc_disallocate(i);
+		      }
+		} else {
+		    /* disallocate a single console, if possible */
+		    arg--;
+		    if (VT_IS_IN_USE(arg))
+		      return -EBUSY;
+		    if (arg) {			      /* leave 0 */
+			if (arg == fg_console)
+			  change_console(0);
+			vc_disallocate(arg);
+		    }
+		}
+		return 0;
+
+	case VT_RESIZE:
+	{
+		struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
+		ushort ll,cc;
+		i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
+		if (i)
+			return i;
+		ll = get_fs_word(&vtsizes->v_rows);
+		cc = get_fs_word(&vtsizes->v_cols);
+		return vc_resize(ll, cc);
+	}
 
 	case PIO_FONT:
 		return con_set_font((char *)arg);
diff -u --recursive --new-file v1.1.53/linux/drivers/char/vt_kern.h linux/drivers/char/vt_kern.h
--- v1.1.53/linux/drivers/char/vt_kern.h	Tue May 24 00:34:50 1994
+++ linux/drivers/char/vt_kern.h	Thu Oct 13 14:07:09 1994
@@ -18,8 +18,12 @@
 	int		vt_pid;
 	int		vt_newvt;
 	struct wait_queue *paste_wait;
-} vt_cons[NR_CONSOLES];
+} *vt_cons[MAX_NR_CONSOLES];
 
 void kd_mksound(unsigned int count, unsigned int ticks);
+int vc_allocate(unsigned int console);
+int vc_cons_allocated(unsigned int console);
+int vc_resize(unsigned long lines, unsigned long cols);
+void vc_disallocate(unsigned int console);
 
 #endif /* _VT_KERN_H */
diff -u --recursive --new-file v1.1.53/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v1.1.53/linux/drivers/net/Makefile	Thu Aug 11 20:43:08 1994
+++ linux/drivers/net/Makefile	Tue Oct 11 09:17:04 1994
@@ -190,8 +190,14 @@
 
 modules:
 	echo $(MODULES) > ../../modules/NET_MODULES
-	$(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES)
-	(cd ../../modules;for i in $(MODULES); do ln -sf ../drivers/net/$$i .; done)
+	@(cd ../../modules; \
+		for i in $(MODULES:.o=.c); \
+			do ln -sf ../drivers/net/$$i .; \
+			done ; \
+		ln -sf ../drivers/net/CONFIG . ; \
+		$(MAKE) -f../drivers/net/Makefile -I../drivers/net \
+			CFLAGS="$(CFLAGS) -I../net/inet -I../drivers/net -DMODULE" $(MODULES); \
+		rm $(MODULES:.o=.c) CONFIG)
 
 else
 
diff -u --recursive --new-file v1.1.53/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v1.1.53/linux/drivers/net/depca.c	Thu Aug 11 20:43:11 1994
+++ linux/drivers/net/depca.c	Wed Oct 12 15:00:25 1994
@@ -160,11 +160,13 @@
       0.351 30-apr-94     Added EISA support. Added DE422 recognition.
       0.36  16-may-94     DE422 fix released.
       0.37  22-jul-94     Added MODULE support
+      0.38  15-aug-94     Added DBR ROM switch in depca_close(). 
+                          Multi DEPCA bug fix.
 
     =========================================================================
 */
 
-static char *version = "depca.c:v0.37 7/22/94 davies@wanton.lkg.dec.com\n";
+static char *version = "depca.c:v0.38 8/15/94 davies@wanton.lkg.dec.com\n";
 
 #include <stdarg.h>
 #include <linux/config.h>
@@ -289,7 +291,7 @@
 };
 
 struct depca_private {
-    char devname[8];            /* Not used */
+    char devname[8];            /* Device Product String */
     struct depca_rx_head *rx_ring; /* Pointer to start of RX descriptor ring */
     struct depca_tx_head *tx_ring; /* Pointer to start of TX descriptor ring */
     struct depca_init	init_block;/* Initialization block */
@@ -338,7 +340,7 @@
 static struct device *eisa_probe(struct device *dev);
 static struct device *alloc_device(struct device *dev, int ioaddr);
 
-static int num_depcas = 0, num_eth = 0;;
+static int num_depcas = 0, num_eth = 0, autoprobed = 0;
 
 #else
 int  init_module(void);
@@ -370,15 +372,20 @@
       }
     } else if (base_addr > 0) {	      /* Don't probe at all. */
       status = -ENXIO;
-    } else {                          /* First probe for the DEPCA test */
 
-#ifdef MODULE                         /* pattern in ROM */
+#ifdef MODULE
+    } else {
       printk("Autoprobing is not supported when loading a module based driver.\n");
       status = -EIO;
 #else
+    } else if (!autoprobed) {         /* First probe for the DEPCA test */
+                                      /* pattern in ROM */
       eth0=isa_probe(dev);
       eth0=eisa_probe(eth0);
       if (dev->priv) status=0;
+      autoprobed = 1;
+    } else {
+      status = -ENXIO;
 #endif /* MODULE */
 
     }
@@ -416,19 +423,18 @@
     ** shortens the search time a little for multiple DEPCAs.
     */
 
-      for (j = 0, i = 0; mem_base[i] && (j == 0);) {
+      for (j = 0, i = 0; mem_base[i] && (j == 0);i++) {
 	if (((mem_chkd >> i) & 0x01) == 0) { /* has the memory been checked? */
 	  name = DepcaSignature(mem_base[i]);/* check for a DEPCA here */
 	  mem_chkd |= (0x01 << i);           /* mark location checked */
-	  if (*name != '\0') {			/* one found? */
+	  if (*name != '\0') {               /* one found? */
 	    j = 1;                           /* set exit flag */
-	  } else {
-	    i++;                             /* increment search index */
+	    --i;
 	  }
 	}
       }
 
-      if (*name != '\0') {		/* found a DEPCA device */
+      if (*name != '\0') {                   /* found a DEPCA device */
 	mem_start = mem_base[i];
 	dev->base_addr = ioaddr;
 
@@ -448,7 +454,7 @@
 	 read the ROM info.
       */
 
-	if (strstr(name,"DE100") != NULL) {
+	if (strstr(name,"DE100")!= NULL) {
 	  j = 1;
 	} else {
 	  j = 0;
@@ -471,7 +477,7 @@
 	/*
 	** Set up the maximum amount of network RAM(kB)
 	*/
-	if (strstr(name,"DEPCA") == NULL) {
+	if (strstr(name,"DEPCA")== NULL) {
 	  netRAM=64;
 	} else {
 	  netRAM=48;
@@ -542,6 +548,7 @@
 	dev->priv = (void *)((mem_start + 0x07) & ~0x07);      
 	lp = (struct depca_private *)dev->priv;
 	memset(dev->priv, 0, sizeof(struct depca_private));
+	strcpy(lp->devname,name);
 
 	/* Tx & Rx descriptors (aligned to a quadword boundary) */
 	mem_start = ((((unsigned long)dev->priv + 
@@ -675,6 +682,14 @@
     STOP_DEPCA;
     nicsr = inb(DEPCA_NICSR);
 
+    /*
+    ** Make sure the shadow RAM is enabled
+    */
+    if (strstr(lp->devname,"DEPCA") == NULL) {
+      nicsr |= SHE;
+      outb(nicsr, DEPCA_NICSR);
+    }
+
     /* 
     ** Re-initialize the DEPCA... 
     */
@@ -721,9 +736,9 @@
     }
 
     /*
-    ** Enable DEPCA board interrupts
+    ** Enable DEPCA board interrupts and turn off LED
     */
-    nicsr = ((nicsr & ~IM & ~LED)|SHE|IEN);
+    nicsr = ((nicsr & ~IM & ~LED)|IEN);
     outb(nicsr, DEPCA_NICSR);
     outw(CSR0,DEPCA_ADDR);
 
@@ -1121,33 +1136,43 @@
 static int
 depca_close(struct device *dev)
 {
-    int ioaddr = dev->base_addr;
+  struct depca_private *lp = (struct depca_private *)dev->priv;
+  int nicsr, ioaddr = dev->base_addr;
+
+  dev->start = 0;
+  dev->tbusy = 1;
 
-    dev->start = 0;
-    dev->tbusy = 1;
+  outw(CSR0, DEPCA_ADDR);
 
-    outw(CSR0, DEPCA_ADDR);
+  if (depca_debug > 1) {
+    printk("%s: Shutting down ethercard, status was %2.2x.\n",
+	   dev->name, inw(DEPCA_DATA));
+  }
 
-    if (depca_debug > 1) {
-      printk("%s: Shutting down ethercard, status was %2.2x.\n",
-	     dev->name, inw(DEPCA_DATA));
-    }
+  /* 
+  ** We stop the DEPCA here -- it occasionally polls
+  ** memory if we don't. 
+  */
+  outw(STOP, DEPCA_DATA);
 
-    /* 
-    ** We stop the DEPCA here -- it occasionally polls
-    ** memory if we don't. 
-    */
-    outw(STOP, DEPCA_DATA);
+  /*
+  ** Give back the ROM in case the user wants to go to DOS
+  */
+  if (strstr(lp->devname,"DEPCA") == NULL) {
+    nicsr = inb(DEPCA_NICSR);
+    nicsr &= ~SHE;
+    outb(nicsr, DEPCA_NICSR);
+  }
 
-    free_irq(dev->irq);
+  free_irq(dev->irq);
 
-    irq2dev_map[dev->irq] = 0;
+  irq2dev_map[dev->irq] = 0;
 
 #ifdef MODULE
-    MOD_DEC_USE_COUNT;
+  MOD_DEC_USE_COUNT;
 #endif    
 
-    return 0;
+  return 0;
 }
 
 static void LoadCSRs(struct device *dev)
@@ -1373,12 +1398,12 @@
   */
   if ((dev->next != NULL) &&
       (num_eth > 0) && (num_eth < 9999)) {
-    dev = dev->next;			/* point to the new device */
+    dev = dev->next;                    /* point to the new device */
     dev->name = (char *)(dev + 1);
     sprintf(dev->name,"eth%d", num_eth);/* New device name */
-    dev->base_addr = ioaddr;		/* assign the io address */
-    dev->next = NULL;			/* mark the end of list */
-    dev->init = &depca_probe;		/* initialisation routine */
+    dev->base_addr = ioaddr;            /* assign the io address */
+    dev->next = NULL;                   /* mark the end of list */
+    dev->init = &depca_probe;           /* initialisation routine */
     num_depcas++;
   }
 
@@ -1401,10 +1426,10 @@
   for (i=0;i<16;i++) {                  /* copy the first 16 bytes of ROM to */
     tmpstr[i] = *(unsigned char *)(mem_addr+0xc000+i); /* a temporary string */
   }
-  tmpstr[i] = '\0';
+  tmpstr[i]='\0';
 
   strcpy(thisName,"");
-  for (i = 0 ; *signatures[i] != '\0' && *thisName == '\0' ; i++) {
+  for (i=0;*signatures[i]!='\0' && *thisName=='\0';i++) {
     for (j=0,k=0;j<16 && k<strlen(signatures[i]);j++) {
       if (signatures[i][k] == tmpstr[j]) {              /* track signature */
 	k++;
@@ -1521,7 +1546,7 @@
 #ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 static struct device thisDepca = {
-  "        ", /* device name inserted by /linux/drivers/net/net_init.c */
+  "        ",  /* device name inserted by /linux/drivers/net/net_init.c */
   0, 0, 0, 0,
   0x200, 7,   /* I/O address, IRQ <--- EDIT THIS LINE FOR YOUR CONFIGURATION */
   0, 0, 0, NULL, depca_probe };
@@ -1548,8 +1573,8 @@
 
 /*
  * Local variables:
- *  kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c depca.c"
+ *  kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c depca.c"
  *
- *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c depca.c"
+ *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c depca.c"
  * End:
  */
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v1.1.53/linux/drivers/scsi/53c7,8xx.c	Thu Aug 11 20:43:17 1994
+++ linux/drivers/scsi/53c7,8xx.c	Wed Oct 12 15:42:04 1994
@@ -282,7 +282,7 @@
     int min_revision;
 };
 
-static struct pci_chip pci_chip_ids[2] = { 
+static struct pci_chip pci_chip_ids[3] = { 
     {PCI_DEVICE_ID_NCR_53C810, 810, 1, 1}, 
     {PCI_DEVICE_ID_NCR_53C820, 820, -1, -1},
     {PCI_DEVICE_ID_NCR_53C825, 825, -1, -1},
@@ -413,6 +413,7 @@
     switch (hostdata->chip) {
     case 810:
     case 815:
+    case 825:
     	hostdata->dstat_sir_intr = NCR53c8x0_dstat_sir_intr;
     	hostdata->init_save_regs = NULL;
     	hostdata->dsa_fixup = NCR53c8xx_dsa_fixup;
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/buslogic.h linux/drivers/scsi/buslogic.h
--- v1.1.53/linux/drivers/scsi/buslogic.h	Sun Aug 21 17:48:27 1994
+++ linux/drivers/scsi/buslogic.h	Wed Oct 12 14:57:29 1994
@@ -19,7 +19,14 @@
 int buslogic_reset(Scsi_Cmnd *);
 int buslogic_biosparam(Disk *, int, int *);
 
-#define BUSLOGIC_CMDLUN 4	/* ??? */
+#define BUSLOGIC_CMDLUN 1	/* Do not set this too high.  It sucks
+				   up lots of memory on machines with > 16Mb
+				   because of the huge number of bounce
+				   buffers that need to be allocated.
+				   For boards that use non-ISA bus, we can
+				   bump this in the board detect routine.  
+				   			10/8/94 ERY */
+				   
 
 #define BUSLOGIC { NULL, 			\
 		   "BusLogic",			\
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.1.53/linux/drivers/scsi/scsi.c	Tue Oct 11 09:29:23 1994
+++ linux/drivers/scsi/scsi.c	Fri Oct 14 10:44:52 1994
@@ -374,8 +374,8 @@
 		  printk("scsi: unknown type %d\n", type);
 		  print_inquiry(scsi_result);
 #endif
-#endif
 		  type = -1;
+#endif
 		}
 	      
 	      SDpnt->soft_reset = 
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.1.53/linux/drivers/scsi/scsi.h	Sun Aug 21 17:48:29 1994
+++ linux/drivers/scsi/scsi.h	Wed Oct 12 14:57:29 1994
@@ -515,7 +515,7 @@
 extern int max_scsi_hosts;
 
 #if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR)
-static void end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
+static Scsi_Cmnd * end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
 {
 	struct request * req;
 	struct buffer_head * bh;
@@ -547,7 +547,7 @@
 	} while(sectors && bh);
 	if (req->bh){
 	  req->buffer = bh->b_data;
-	  return;
+	  return SCpnt;
 	};
 	DEVICE_OFF(req->dev);
 	if (req->sem != NULL) {
@@ -555,7 +555,7 @@
 	}
 	req->dev = -1;
 	wake_up(&SCpnt->device->device_wait);
-	return;
+	return NULL;
 }
 
 
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.1.53/linux/drivers/scsi/sd.c	Wed Aug 31 10:14:10 1994
+++ linux/drivers/scsi/sd.c	Wed Oct 12 14:57:29 1994
@@ -226,7 +226,7 @@
 		  SCpnt->request.sector, this_count);
 	  }
       }
-    end_scsi_request(SCpnt, 1, this_count);
+    SCpnt = end_scsi_request(SCpnt, 1, this_count);
     requeue_sd_request(SCpnt);
     return;
   }
@@ -284,7 +284,7 @@
 	      /* further access.					*/
 	      
 		rscsi_disks[DEVICE_NR(SCpnt->request.dev)].device->changed = 1;
-		end_scsi_request(SCpnt, 0, this_count);
+		SCpnt = end_scsi_request(SCpnt, 0, this_count);
 		requeue_sd_request(SCpnt);
 		return;
 	      }
@@ -316,7 +316,7 @@
 
 		if (driver_byte(result) & DRIVER_SENSE)
 			print_sense("sd", SCpnt);
-		end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
+		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
 		requeue_sd_request(SCpnt);
 		return;
 	}
@@ -406,7 +406,7 @@
 
 repeat:
 
-	if(SCpnt->request.dev <= 0) {
+	if(!SCpnt || SCpnt->request.dev <= 0) {
 	  do_sd_request();
 	  return;
 	}
@@ -423,7 +423,7 @@
 	    !rscsi_disks[DEVICE_NR(dev)].device ||
 	    block + SCpnt->request.nr_sectors > sd[dev].nr_sects)
 		{
-		end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		goto repeat;
 		}
 
@@ -436,7 +436,7 @@
  * quietly refuse to do anything to a changed disc until the changed bit has been reset
  */
 		/* printk("SCSI disk has been changed.  Prohibiting further I/O.\n");	*/
-		end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		goto repeat;
 		}
 
@@ -449,7 +449,7 @@
 		case WRITE :
 			if (!rscsi_disks[dev].device->writeable)
 				{
-				end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+				SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 				goto repeat;
 				}
 			cmd[0] = WRITE_6;
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.53/linux/drivers/scsi/sr.c	Wed Aug 31 10:14:10 1994
+++ linux/drivers/scsi/sr.c	Wed Oct 12 14:57:30 1994
@@ -195,7 +195,7 @@
 				  SCpnt->request.sector, this_count);
 			}
 
-		  end_scsi_request(SCpnt, 1, this_count);  /* All done */
+		  SCpnt = end_scsi_request(SCpnt, 1, this_count);  /* All done */
 		  requeue_sr_request(SCpnt);
 		  return;
 		} /* Normal completion */
@@ -225,7 +225,7 @@
 				/* further access.					*/
 		    
 				scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->changed = 1;
-				end_scsi_request(SCpnt, 0, this_count);
+				SCpnt = end_scsi_request(SCpnt, 0, this_count);
 			        requeue_sr_request(SCpnt);
 				return;
 			}
@@ -240,7 +240,7 @@
 				return;
 			} else {
 			  printk("CD-ROM error: Drive reports %d.\n", SCpnt->sense_buffer[2]);				
-			  end_scsi_request(SCpnt, 0, this_count);
+			  SCpnt = end_scsi_request(SCpnt, 0, this_count);
 			  requeue_sr_request(SCpnt); /* Do next request */
 			  return;
 			}
@@ -249,7 +249,7 @@
 
 		if (SCpnt->sense_buffer[2] == NOT_READY) {
 			printk("CDROM not ready.  Make sure you have a disc in the drive.\n");
-			end_scsi_request(SCpnt, 0, this_count);
+			SCpnt = end_scsi_request(SCpnt, 0, this_count);
 			requeue_sr_request(SCpnt); /* Do next request */
 			return;
 		};
@@ -266,7 +266,7 @@
 	  if (status_byte(result) == CHECK_CONDITION)
 		  print_sense("sr", SCpnt);
 	  
-	  end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
+	  SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
 	  requeue_sr_request(SCpnt);
   }
 }
@@ -369,7 +369,7 @@
 	tries = 2;
 
       repeat:
-	if(SCpnt->request.dev <= 0) {
+	if(!SCpnt || SCpnt->request.dev <= 0) {
 	  do_sr_request();
 	  return;
 	}
@@ -382,7 +382,7 @@
 	if (dev >= sr_template.nr_dev)
 		{
 		/* printk("CD-ROM request error: invalid device.\n");			*/
-		end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		tries = 2;
 		goto repeat;
 		}
@@ -390,7 +390,7 @@
 	if (!scsi_CDs[dev].use)
 		{
 		/* printk("CD-ROM request error: device marked not in use.\n");		*/
-		end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		tries = 2;
 		goto repeat;
 		}
@@ -401,7 +401,7 @@
  * quietly refuse to do anything to a changed disc until the changed bit has been reset
  */
 		/* printk("CD-ROM has been changed.  Prohibiting further I/O.\n");	*/
-		end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		tries = 2;
 		goto repeat;
 		}
@@ -409,7 +409,7 @@
 	switch (SCpnt->request.cmd)
 		{
 		case WRITE: 		
-			end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+			SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			goto repeat;
 			break;
 		case READ : 
diff -u --recursive --new-file v1.1.53/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- v1.1.53/linux/drivers/scsi/ultrastor.c	Fri Aug 26 14:44:41 1994
+++ linux/drivers/scsi/ultrastor.c	Wed Oct 12 15:49:14 1994
@@ -309,7 +309,7 @@
 static inline unsigned char xchgb(unsigned char reg,
 				  volatile unsigned char *mem)
 {
-  asm ("xchgb %0, (%2)" : "=q" (reg) : "0" (reg), "q" (mem) : "m");
+  __asm__ ("xchgb %0,%1" : "=q" (reg), "=m" (*mem) : "0" (reg));
   return reg;
 }
 
diff -u --recursive --new-file v1.1.53/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v1.1.53/linux/drivers/sound/ad1848.c	Sun Aug 21 17:48:30 1994
+++ linux/drivers/sound/ad1848.c	Tue Oct 11 08:51:31 1994
@@ -71,8 +71,9 @@
 {-1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1};
 
-static int      ad_format_mask[2 /*devc->mode*/ ] =
+static int      ad_format_mask[3 /*devc->mode*/ ] =
 {
+  0,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM
 };
diff -u --recursive --new-file v1.1.53/linux/drivers/sound/sb16_midi.c linux/drivers/sound/sb16_midi.c
--- v1.1.53/linux/drivers/sound/sb16_midi.c	Tue Jul 19 10:19:08 1994
+++ linux/drivers/sound/sb16_midi.c	Thu Oct 13 13:50:51 1994
@@ -282,7 +282,6 @@
 probe_sb16midi (struct address_info *hw_config)
 {
   int             ok = 0;
-  int             i;
   extern int      sbc_major;
 
   if (sbc_major < 4)
diff -u --recursive --new-file v1.1.53/linux/fs/Makefile linux/fs/Makefile
--- v1.1.53/linux/fs/Makefile	Sun Aug  7 03:30:40 1994
+++ linux/fs/Makefile	Tue Oct 11 08:47:17 1994
@@ -43,6 +43,12 @@
 FS_SUBDIRS := $(FS_SUBDIRS) hpfs
 endif
 
+ifdef CONFIG_BINFMT_ELF
+BINFMTS := $(BINFMTS) binfmt_elf.o
+else
+MODULES := $(MODULES) binfmt_elf.o
+endif
+
 .c.s:
 	$(CC) $(CFLAGS) -S $<
 .c.o:
@@ -54,7 +60,7 @@
 	block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
 	select.o fifo.o locks.o filesystems.o dcache.o $(BINFMTS)
 
-all: fs.o filesystems.a
+all: fs.o filesystems.a modules
 
 fs.o: $(OBJS)
 	$(LD) -r -o fs.o $(OBJS)
@@ -64,6 +70,18 @@
 	set -e; for i in $(FS_SUBDIRS); do \
 	  test ! -d $$i || \
 	    { $(MAKE) -C $$i; $(AR) rcs filesystems.a $$i/$$i.o; }; done
+
+ifdef MODULES
+
+modules:
+	$(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES)
+	(cd ../modules;for i in $(MODULES); do ln -sf ../fs/$$i .; done)
+
+else
+
+modules:
+
+endif
 
 depend dep:
 	$(CPP) -M *.c > .depend
diff -u --recursive --new-file v1.1.53/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v1.1.53/linux/fs/binfmt_elf.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/binfmt_elf.c	Tue Oct 11 08:47:17 1994
@@ -0,0 +1,791 @@
+/*
+ * linux/fs/binfmt_elf.c
+ *
+ * These are the functions used to load ELF format executables as used
+ * on SVr4 machines.  Information on the format may be found in the book
+ * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
+ * Tools".
+ *
+ * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
+ */
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/shm.h>
+#include <linux/personality.h>
+
+#include <asm/segment.h>
+
+#include <linux/config.h>
+
+#ifndef CONFIG_BINFMT_ELF
+#include <linux/module.h>
+#include "../tools/version.h"
+#endif
+
+#include <linux/unistd.h>
+typedef int (*sysfun_p)();
+extern sysfun_p sys_call_table[];
+#define SYS(name)	(sys_call_table[__NR_##name])
+
+#define DLINFO_ITEMS 8
+
+#include <linux/elf.h>
+
+static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
+static int load_elf_library(int fd);
+
+struct linux_binfmt elf_format = {
+#ifdef CONFIG_BINFMT_ELF
+	NULL, NULL, load_elf_binary, load_elf_library, NULL
+#else
+	NULL, &mod_use_count_, load_elf_binary, load_elf_library, NULL
+#endif
+};
+
+/* We need to explicitly zero any fractional pages
+   after the data section (i.e. bss).  This would
+   contain the junk from the file that should not
+   be in memory */
+
+
+static void padzero(int elf_bss){
+  unsigned int fpnt, nbyte;
+  
+  if(elf_bss & 0xfff) {
+    
+    nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff;
+    if(nbyte){
+      verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
+      
+      fpnt = elf_bss;
+      while(fpnt & 0xfff) put_fs_byte(0, fpnt++);
+    };
+  };
+}
+
+unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, int ibcs)
+{
+	unsigned long *argv,*envp, *dlinfo;
+	unsigned long * sp;
+	struct vm_area_struct *mpnt;
+
+	mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
+	if (mpnt) {
+		mpnt->vm_task = current;
+		mpnt->vm_start = PAGE_MASK & (unsigned long) p;
+		mpnt->vm_end = TASK_SIZE;
+		mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
+#ifdef VM_STACK_FLAGS
+		mpnt->vm_flags = VM_STACK_FLAGS;
+		mpnt->vm_pte = 0;
+#else
+#  ifdef VM_GROWSDOWN
+		mpnt->vm_flags = VM_GROWSDOWN;
+#  endif
+#endif
+		mpnt->vm_share = NULL;
+		mpnt->vm_inode = NULL;
+		mpnt->vm_offset = 0;
+		mpnt->vm_ops = NULL;
+		insert_vm_struct(current, mpnt);
+#ifndef VM_GROWSDOWN
+		current->mm->stk_vma = mpnt;
+#endif
+
+	}
+	sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
+	if(exec) sp -= DLINFO_ITEMS*2;
+	dlinfo = sp;
+	sp -= envc+1;
+	envp = sp;
+	sp -= argc+1;
+	argv = sp;
+	if (!ibcs) {
+		put_fs_long((unsigned long)envp,--sp);
+		put_fs_long((unsigned long)argv,--sp);
+	}
+
+	/* The constant numbers (0-9) that we are writing here are
+	   described in the header file sys/auxv.h on at least
+	   some versions of SVr4 */
+	if(exec) { /* Put this here for an ELF program interpreter */
+	  struct elf_phdr * eppnt;
+	  eppnt = (struct elf_phdr *) exec->e_phoff;
+	  put_fs_long(3,dlinfo++); put_fs_long(load_addr + exec->e_phoff,dlinfo++);
+	  put_fs_long(4,dlinfo++); put_fs_long(sizeof(struct elf_phdr),dlinfo++);
+	  put_fs_long(5,dlinfo++); put_fs_long(exec->e_phnum,dlinfo++);
+	  put_fs_long(9,dlinfo++); put_fs_long((unsigned long) exec->e_entry,dlinfo++);
+	  put_fs_long(7,dlinfo++); put_fs_long(SHM_RANGE_START,dlinfo++);
+	  put_fs_long(8,dlinfo++); put_fs_long(0,dlinfo++);
+	  put_fs_long(6,dlinfo++); put_fs_long(PAGE_SIZE,dlinfo++);
+	  put_fs_long(0,dlinfo++); put_fs_long(0,dlinfo++);
+	};
+
+	put_fs_long((unsigned long)argc,--sp);
+	current->mm->arg_start = (unsigned long) p;
+	while (argc-->0) {
+		put_fs_long((unsigned long) p,argv++);
+		while (get_fs_byte(p++)) /* nothing */ ;
+	}
+	put_fs_long(0,argv);
+	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+	while (envc-->0) {
+		put_fs_long((unsigned long) p,envp++);
+		while (get_fs_byte(p++)) /* nothing */ ;
+	}
+	put_fs_long(0,envp);
+	current->mm->env_end = (unsigned long) p;
+	return sp;
+}
+
+
+/* This is much more generalized than the library routine read function,
+   so we keep this separate.  Techincally the library read function
+   is only provided so that we can read a.out libraries that have
+   an ELF header */
+
+static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
+			     struct inode * interpreter_inode)
+{
+        struct file * file;
+	struct elf_phdr *elf_phdata  =  NULL;
+	struct elf_phdr *eppnt;
+	unsigned int len;
+	unsigned int load_addr;
+	int elf_exec_fileno;
+	int elf_bss;
+	int old_fs, retval;
+	unsigned int last_bss;
+	int error;
+	int i, k;
+	
+	elf_bss = 0;
+	last_bss = 0;
+	error = load_addr = 0;
+	
+	/* First of all, some simple consistency checks */
+	if((interp_elf_ex->e_type != ET_EXEC && 
+	    interp_elf_ex->e_type != ET_DYN) || 
+	   (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
+	   (!interpreter_inode->i_op ||
+	    !interpreter_inode->i_op->default_file_ops->mmap)){
+		return 0xffffffff;
+	};
+	
+	/* Now read in all of the header information */
+	
+	if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) 
+	    return 0xffffffff;
+	
+	elf_phdata =  (struct elf_phdr *) 
+		kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
+	if(!elf_phdata) return 0xffffffff;
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
+			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+	set_fs(old_fs);
+	
+	elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
+	if (elf_exec_fileno < 0) return 0xffffffff;
+	file = current->files->fd[elf_exec_fileno];
+
+	eppnt = elf_phdata;
+	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+	  if(eppnt->p_type == PT_LOAD) {
+	    error = do_mmap(file, 
+			    eppnt->p_vaddr & 0xfffff000,
+			    eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+			    PROT_READ | PROT_WRITE | PROT_EXEC,
+			    MAP_PRIVATE | MAP_DENYWRITE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
+			    eppnt->p_offset & 0xfffff000);
+	    
+	    if(!load_addr && interp_elf_ex->e_type == ET_DYN)
+	      load_addr = error;
+	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
+	    if(k > elf_bss) elf_bss = k;
+	    if(error < 0 && error > -1024) break;  /* Real error */
+	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
+	    if(k > last_bss) last_bss = k;
+	  }
+	
+	/* Now use mmap to map the library into memory. */
+
+	
+	SYS(close)(elf_exec_fileno);
+	if(error < 0 && error > -1024) {
+	        kfree(elf_phdata);
+		return 0xffffffff;
+	}
+
+	padzero(elf_bss);
+	len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
+
+	/* Map the last of the bss segment */
+	if (last_bss > len)
+	  do_mmap(NULL, len, last_bss-len,
+		  PROT_READ|PROT_WRITE|PROT_EXEC,
+		  MAP_FIXED|MAP_PRIVATE, 0);
+	kfree(elf_phdata);
+
+	return ((unsigned int) interp_elf_ex->e_entry) + load_addr;
+}
+
+static unsigned int load_aout_interp(struct exec * interp_ex,
+			     struct inode * interpreter_inode)
+{
+  int retval;
+  unsigned int elf_entry;
+  
+  current->mm->brk = interp_ex->a_bss +
+    (current->mm->end_data = interp_ex->a_data +
+     (current->mm->end_code = interp_ex->a_text));
+  elf_entry = interp_ex->a_entry;
+  
+  
+  if (N_MAGIC(*interp_ex) == OMAGIC) {
+    do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
+	    PROT_READ|PROT_WRITE|PROT_EXEC,
+	    MAP_FIXED|MAP_PRIVATE, 0);
+    retval = read_exec(interpreter_inode, 32, (char *) 0, 
+		       interp_ex->a_text+interp_ex->a_data);
+  } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
+    do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
+	    PROT_READ|PROT_WRITE|PROT_EXEC,
+	    MAP_FIXED|MAP_PRIVATE, 0);
+    retval = read_exec(interpreter_inode,
+		       N_TXTOFF(*interp_ex) ,
+		       (char *) N_TXTADDR(*interp_ex),
+		       interp_ex->a_text+interp_ex->a_data);
+  } else
+    retval = -1;
+  
+  if(retval >= 0)
+    do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & 
+	    0xfffff000, interp_ex->a_bss,
+	    PROT_READ|PROT_WRITE|PROT_EXEC,
+	    MAP_FIXED|MAP_PRIVATE, 0);
+  if(retval < 0) return 0xffffffff;
+  return elf_entry;
+}
+
+/*
+ * These are the functions used to load ELF style executables and shared
+ * libraries.  There is no binary dependent code anywhere else.
+ */
+
+#define INTERPRETER_NONE 0
+#define INTERPRETER_AOUT 1
+#define INTERPRETER_ELF 2
+
+
+static int
+load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+	struct elfhdr elf_ex;
+	struct elfhdr interp_elf_ex;
+	struct file * file;
+  	struct exec interp_ex;
+	struct inode *interpreter_inode;
+	unsigned int load_addr;
+	unsigned int interpreter_type = INTERPRETER_NONE;
+	unsigned char ibcs2_interpreter;
+	int i;
+	int old_fs;
+	int error;
+	struct elf_phdr * elf_ppnt, *elf_phdata;
+	int elf_exec_fileno;
+	unsigned int elf_bss, k, elf_brk;
+	int retval;
+	char * elf_interpreter;
+	unsigned int elf_entry;
+	int status;
+	unsigned int start_code, end_code, end_data;
+	unsigned int elf_stack;
+	char passed_fileno[6];
+	
+#ifndef CONFIG_BINFMT_ELF
+	MOD_INC_USE_COUNT;
+#endif
+
+	ibcs2_interpreter = 0;
+	status = 0;
+	load_addr = 0;
+	elf_ex = *((struct elfhdr *) bprm->buf);	  /* exec-header */
+	
+	if (elf_ex.e_ident[0] != 0x7f ||
+	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return  -ENOEXEC;
+	}
+	
+	
+	/* First of all, some simple consistency checks */
+	if(elf_ex.e_type != ET_EXEC || 
+	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
+	   (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
+	    !bprm->inode->i_op->default_file_ops->mmap)){
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return -ENOEXEC;
+	};
+	
+	/* Now read in all of the header information */
+	
+	elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
+						 elf_ex.e_phnum, GFP_KERNEL);
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
+			   elf_ex.e_phentsize * elf_ex.e_phnum);
+	set_fs(old_fs);
+	if (retval < 0) {
+	        kfree (elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return retval;
+	}
+	
+	elf_ppnt = elf_phdata;
+	
+	elf_bss = 0;
+	elf_brk = 0;
+	
+	elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
+
+	if (elf_exec_fileno < 0) {
+	        kfree (elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return elf_exec_fileno;
+	}
+	
+	file = current->files->fd[elf_exec_fileno];
+	
+	elf_stack = 0xffffffff;
+	elf_interpreter = NULL;
+	start_code = 0;
+	end_code = 0;
+	end_data = 0;
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	
+	for(i=0;i < elf_ex.e_phnum; i++){
+		if(elf_ppnt->p_type == PT_INTERP) {
+			/* This is the program interpreter used for shared libraries - 
+			   for now assume that this is an a.out format binary */
+			
+			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
+							   GFP_KERNEL);
+			
+			retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
+					   elf_ppnt->p_filesz);
+			/* If the program interpreter is one of these two,
+			   then assume an iBCS2 image. Otherwise assume
+			   a native linux image. */
+			if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
+			    strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
+			  ibcs2_interpreter = 1;
+#if 0
+			printk("Using ELF interpreter %s\n", elf_interpreter);
+#endif
+			if(retval >= 0)
+				retval = namei(elf_interpreter, &interpreter_inode);
+			if(retval >= 0)
+				retval = read_exec(interpreter_inode,0,bprm->buf,128);
+			
+			if(retval >= 0){
+				interp_ex = *((struct exec *) bprm->buf);		/* exec-header */
+				interp_elf_ex = *((struct elfhdr *) bprm->buf);	  /* exec-header */
+				
+			};
+			if(retval < 0) {
+			  kfree (elf_phdata);
+			  kfree(elf_interpreter);
+#ifndef CONFIG_BINFMT_ELF
+			  MOD_DEC_USE_COUNT;
+#endif
+			  return retval;
+			};
+		};
+		elf_ppnt++;
+	};
+	
+	set_fs(old_fs);
+	
+	/* Some simple consistency checks for the interpreter */
+	if(elf_interpreter){
+	        interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
+		if(retval < 0) {
+			kfree(elf_interpreter);
+			kfree(elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+			MOD_DEC_USE_COUNT;
+#endif
+			return -ELIBACC;
+		};
+		/* Now figure out which format our binary is */
+		if((N_MAGIC(interp_ex) != OMAGIC) && 
+		   (N_MAGIC(interp_ex) != ZMAGIC) &&
+		   (N_MAGIC(interp_ex) != QMAGIC)) 
+		  interpreter_type = INTERPRETER_ELF;
+
+		if (interp_elf_ex.e_ident[0] != 0x7f ||
+		    strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0)
+		  interpreter_type &= ~INTERPRETER_ELF;
+
+		if(!interpreter_type)
+		  {
+		    kfree(elf_interpreter);
+		    kfree(elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+		    MOD_DEC_USE_COUNT;
+#endif
+		    return -ELIBBAD;
+		  };
+	}
+	
+	/* OK, we are done with that, now set up the arg stuff,
+	   and then start this sucker up */
+	
+	if (!bprm->sh_bang) {
+		char * passed_p;
+		
+		if(interpreter_type == INTERPRETER_AOUT) {
+		  sprintf(passed_fileno, "%d", elf_exec_fileno);
+		  passed_p = passed_fileno;
+		
+		  if(elf_interpreter) {
+		    bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
+		    bprm->argc++;
+		  };
+		};
+		if (!bprm->p) {
+		        if(elf_interpreter) {
+			      kfree(elf_interpreter);
+			}
+		        kfree (elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+			MOD_DEC_USE_COUNT;
+#endif
+			return -E2BIG;
+		}
+	}
+	
+	/* OK, This is the point of no return */
+	flush_old_exec(bprm);
+
+	current->mm->end_data = 0;
+	current->mm->end_code = 0;
+	current->mm->start_mmap = ELF_START_MMAP;
+	current->mm->mmap = NULL;
+	elf_entry = (unsigned int) elf_ex.e_entry;
+	
+	/* Do this so that we can load the interpreter, if need be.  We will
+	   change some of these later */
+	current->mm->rss = 0;
+	bprm->p += change_ldt(0, bprm->page);
+	current->mm->start_stack = bprm->p;
+	
+	/* Now we do a little grungy work by mmaping the ELF image into
+	   the correct location in memory.  At this point, we assume that
+	   the image should be loaded at fixed address, not at a variable
+	   address. */
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	
+	elf_ppnt = elf_phdata;
+	for(i=0;i < elf_ex.e_phnum; i++){
+		
+		if(elf_ppnt->p_type == PT_INTERP) {
+			/* Set these up so that we are able to load the interpreter */
+		  /* Now load the interpreter into user address space */
+		  set_fs(old_fs);
+
+		  if(interpreter_type & 1) elf_entry = 
+		    load_aout_interp(&interp_ex, interpreter_inode);
+
+		  if(interpreter_type & 2) elf_entry = 
+		    load_elf_interp(&interp_elf_ex, interpreter_inode);
+
+		  old_fs = get_fs();
+		  set_fs(get_ds());
+
+		  iput(interpreter_inode);
+		  kfree(elf_interpreter);
+			
+		  if(elf_entry == 0xffffffff) { 
+		    printk("Unable to load interpreter\n");
+		    kfree(elf_phdata);
+		    send_sig(SIGSEGV, current, 0);
+#ifndef CONFIG_BINFMT_ELF
+		    MOD_DEC_USE_COUNT;
+#endif
+		    return 0;
+		  };
+		};
+		
+		
+		if(elf_ppnt->p_type == PT_LOAD) {
+			error = do_mmap(file,
+					elf_ppnt->p_vaddr & 0xfffff000,
+					elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
+					PROT_READ | PROT_WRITE | PROT_EXEC,
+					MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+					elf_ppnt->p_offset & 0xfffff000);
+			
+#ifdef LOW_ELF_STACK
+			if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
+				elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
+#endif
+			
+			if(!load_addr) 
+			  load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
+			k = elf_ppnt->p_vaddr;
+			if(k > start_code) start_code = k;
+			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
+			if(k > elf_bss) elf_bss = k;
+			if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
+				end_code = k; 
+			if(end_data < k) end_data = k; 
+			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
+			if(k > elf_brk) elf_brk = k;		     
+		      };
+		elf_ppnt++;
+	};
+	set_fs(old_fs);
+	
+	kfree(elf_phdata);
+	
+	if(interpreter_type != INTERPRETER_AOUT) SYS(close)(elf_exec_fileno);
+	current->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
+
+	if (current->exec_domain && current->exec_domain->use_count)
+		(*current->exec_domain->use_count)--;
+	if (current->binfmt && current->binfmt->use_count)
+		(*current->binfmt->use_count)--;
+	current->exec_domain = lookup_exec_domain(current->personality);
+	current->binfmt = &elf_format;
+	if (current->exec_domain && current->exec_domain->use_count)
+		(*current->exec_domain->use_count)++;
+	if (current->binfmt && current->binfmt->use_count)
+		(*current->binfmt->use_count)++;
+
+#ifndef VM_STACK_FLAGS
+	current->executable = bprm->inode;
+	bprm->inode->i_count++;
+#endif
+#ifdef LOW_ELF_STACK
+	current->start_stack = p = elf_stack - 4;
+#endif
+	bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
+	bprm->p = (unsigned long) 
+	  create_elf_tables((char *)bprm->p,
+			bprm->argc,
+			bprm->envc,
+			(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
+			load_addr,    
+			(interpreter_type == INTERPRETER_AOUT ? 0 : 1));
+	if(interpreter_type == INTERPRETER_AOUT)
+	  current->mm->arg_start += strlen(passed_fileno) + 1;
+	current->mm->start_brk = current->mm->brk = elf_brk;
+	current->mm->end_code = end_code;
+	current->mm->start_code = start_code;
+	current->mm->end_data = end_data;
+	current->mm->start_stack = bprm->p;
+	current->suid = current->euid = bprm->e_uid;
+	current->sgid = current->egid = bprm->e_gid;
+
+	/* Calling sys_brk effectively mmaps the pages that we need for the bss and break
+	   sections */
+	current->mm->brk = (elf_bss + 0xfff) & 0xfffff000;
+	SYS(brk)((elf_brk + 0xfff) & 0xfffff000);
+
+	padzero(elf_bss);
+
+#if 0
+	printk("(start_brk) %x\n" , current->mm->start_brk);
+	printk("(end_code) %x\n" , current->mm->end_code);
+	printk("(start_code) %x\n" , current->mm->start_code);
+	printk("(end_data) %x\n" , current->mm->end_data);
+	printk("(start_stack) %x\n" , current->mm->start_stack);
+	printk("(brk) %x\n" , current->mm->brk);
+#endif
+
+	/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+	   and some applications "depend" upon this behavior.
+	   Since we do not have the power to recompile these, we
+	   emulate the SVr4 behavior.  Sigh.  */
+	error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE, 0);
+
+	regs->eip = elf_entry;		/* eip, magic happens :-) */
+	regs->esp = bprm->p;			/* stack pointer */
+	if (current->flags & PF_PTRACED)
+		send_sig(SIGTRAP, current, 0);
+#ifndef CONFIG_BINFMT_ELF
+	MOD_DEC_USE_COUNT;
+#endif
+	return 0;
+}
+
+/* This is really simpleminded and specialized - we are loading an
+   a.out library that is given an ELF header. */
+
+static int
+load_elf_library(int fd){
+        struct file * file;
+	struct elfhdr elf_ex;
+	struct elf_phdr *elf_phdata  =  NULL;
+	struct  inode * inode;
+	unsigned int len;
+	int elf_bss;
+	int old_fs, retval;
+	unsigned int bss;
+	int error;
+	int i,j, k;
+
+#ifndef CONFIG_BINFMT_ELF
+	MOD_INC_USE_COUNT;
+#endif
+
+	len = 0;
+	file = current->files->fd[fd];
+	inode = file->f_inode;
+	elf_bss = 0;
+	
+	set_fs(KERNEL_DS);
+	if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
+		SYS(close)(fd);
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return -EACCES;
+	}
+	set_fs(USER_DS);
+	
+	if (elf_ex.e_ident[0] != 0x7f ||
+	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return -ENOEXEC;
+	}
+	
+	/* First of all, some simple consistency checks */
+	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
+	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
+	   (!inode->i_op || !inode->i_op->default_file_ops->mmap)){
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return -ENOEXEC;
+	};
+	
+	/* Now read in all of the header information */
+	
+	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) {
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return -ENOEXEC;
+	}
+	
+	elf_phdata =  (struct elf_phdr *) 
+		kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
+			   sizeof(struct elf_phdr) * elf_ex.e_phnum);
+	set_fs(old_fs);
+	
+	j = 0;
+	for(i=0; i<elf_ex.e_phnum; i++)
+		if((elf_phdata + i)->p_type == PT_LOAD) j++;
+	
+	if(j != 1)  {
+		kfree(elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return -ENOEXEC;
+	};
+	
+	while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
+	
+	/* Now use mmap to map the library into memory. */
+	error = do_mmap(file,
+			elf_phdata->p_vaddr & 0xfffff000,
+			elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+			elf_phdata->p_offset & 0xfffff000);
+
+	k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
+	if(k > elf_bss) elf_bss = k;
+	
+	SYS(close)(fd);
+	if (error != elf_phdata->p_vaddr & 0xfffff000) {
+	        kfree(elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+		MOD_DEC_USE_COUNT;
+#endif
+		return error;
+	}
+
+	padzero(elf_bss);
+
+	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
+	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+	if (bss > len)
+	  do_mmap(NULL, len, bss-len,
+		  PROT_READ|PROT_WRITE|PROT_EXEC,
+		  MAP_FIXED|MAP_PRIVATE, 0);
+	kfree(elf_phdata);
+#ifndef CONFIG_BINFMT_ELF
+	MOD_DEC_USE_COUNT;
+#endif
+	return 0;
+}
+
+#ifndef CONFIG_BINFMT_ELF
+char kernel_version[] = UTS_RELEASE;
+
+int init_module(void) {
+	/* Install the COFF, ELF and XOUT loaders.
+	 * N.B. We *rely* on the table being the right size with the
+	 * right number of free slots...
+	 */
+	register_binfmt(&elf_format);
+	return 0;
+}
+
+void cleanup_module( void) {
+	
+	if (MOD_IN_USE)
+		printk(KERN_INFO "iBCS: module is in use, remove delayed\n");
+
+	/* Remove the COFF and ELF loaders. */
+	unregister_binfmt(&elf_format);
+}
+#endif
diff -u --recursive --new-file v1.1.53/linux/fs/exec.c linux/fs/exec.c
--- v1.1.53/linux/fs/exec.c	Sun Oct  9 12:00:25 1994
+++ linux/fs/exec.c	Tue Oct 11 08:47:18 1994
@@ -60,9 +60,16 @@
  * Here are the actual binaries that will be accepted:
  * add more with "register_binfmt()"..
  */
+extern struct linux_binfmt elf_format;
+
 static struct linux_binfmt aout_format = {
-	NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
+#ifndef CONFIG_BINFMT_ELF
+ 	NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
+#else
+ 	&elf_format, NULL, load_aout_binary, load_aout_library, aout_core_dump
+#endif
 };
+
 static struct linux_binfmt *formats = &aout_format;
 
 int register_binfmt(struct linux_binfmt * fmt)
diff -u --recursive --new-file v1.1.53/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v1.1.53/linux/fs/nfs/file.c	Sun Oct  9 12:00:26 1994
+++ linux/fs/nfs/file.c	Wed Oct 12 16:00:56 1994
@@ -7,8 +7,10 @@
  *   - Do not copy data too often around in the kernel.
  *   - In nfs_file_read the return value of kmalloc wasn't checked.
  *   - Put in a better version of read look-ahead buffering. Original idea
- *     and implementation by Wai S Kok elekokw@ee.nus.sg.
+ *     and implementation by Wai S Kok elekokws@ee.nus.sg.
  *
+ *  Expire cache on write to a file by Wai S Kok (Oct 1994).
+ *
  *  nfs regular file handling functions
  */
 
@@ -201,6 +203,14 @@
 	}
 	if (count <= 0)
 		return 0;
+
+	cli();
+	/* If hit, cache is dirty and must be expired. */
+	for (i = 0; i < READ_CACHE_SIZE; i++)
+		if(cache[i].inode_num == inode->i_ino)
+			cache[i].time -= EXPIRE_CACHE;
+        sti();
+
 	pos = file->f_pos;
 	if (file->f_flags & O_APPEND)
 		pos = inode->i_size;
diff -u --recursive --new-file v1.1.53/linux/fs/nfs/proc.c linux/fs/nfs/proc.c
--- v1.1.53/linux/fs/nfs/proc.c	Tue Oct 11 09:29:23 1994
+++ linux/fs/nfs/proc.c	Wed Oct 12 16:00:57 1994
@@ -77,7 +77,7 @@
 
 static inline int *nfs_rpc_alloc(int size)
 {
-#if 1
+#if 0
 	/* Allow for the NFS crap as well as buffer */
 	return (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL);
 #else 
@@ -88,7 +88,7 @@
 	   so that other processes are run inbetween (and hopefully give
 	   some memory back).		Florian
 	*/
-	int i;
+	int *i;
 
 	while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL))) {
 		/* printk("NFS: call schedule\n"); */
diff -u --recursive --new-file v1.1.53/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v1.1.53/linux/fs/nfs/symlink.c	Tue Oct 11 09:29:23 1994
+++ linux/fs/nfs/symlink.c	Wed Oct 12 16:00:57 1994
@@ -71,7 +71,7 @@
 	}
 	error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
 		&res, &len, NFS_MAXPATHLEN);
-#if 1
+#if 0
 	if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
 		printk("NFS: no memory in nfs_follow_link\n");
 		error = -EIO;
diff -u --recursive --new-file v1.1.53/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v1.1.53/linux/fs/proc/inode.c	Thu Aug 11 20:43:27 1994
+++ linux/fs/proc/inode.c	Tue Oct 11 09:17:04 1994
@@ -175,7 +175,11 @@
 				return;
 			inode->i_op = &proc_link_inode_operations;
 			inode->i_size = 64;
-			inode->i_mode = S_IFLNK | S_IRWXU;
+			inode->i_mode = S_IFLNK;
+			if (p->files->fd[ino]->f_mode & 1)
+				inode->i_mode |= S_IRUSR | S_IXUSR;
+			if (p->files->fd[ino]->f_mode & 2)
+				inode->i_mode |= S_IWUSR | S_IXUSR;
 			return;
 	}
 	return;
diff -u --recursive --new-file v1.1.53/linux/fs/proc/link.c linux/fs/proc/link.c
--- v1.1.53/linux/fs/proc/link.c	Thu Aug 11 20:43:27 1994
+++ linux/fs/proc/link.c	Tue Oct 11 09:17:05 1994
@@ -15,13 +15,30 @@
 #include <linux/stat.h>
 
 static int proc_readlink(struct inode *, char *, int);
-static int proc_follow_link(struct inode *, struct inode *, int, int, struct inode **);
+static int proc_follow_link(struct inode *, struct inode *, int, int,
+			    struct inode **);
+static int proc_fd_dupf(struct inode * inode, struct file * f);
 
+#define PLAN9_SEMANTICS
+
 /*
  * links can't do much...
  */
+static struct file_operations proc_fd_link_operations = {
+	NULL,			/* lseek - default */
+	NULL,			/* read - bad */
+	NULL,			/* write - bad */
+	NULL,			/* readdir - bad */
+	NULL,			/* select - default */
+	NULL,			/* ioctl - default */
+	NULL,			/* mmap */
+	proc_fd_dupf,		/* very special open code */
+	NULL,			/* no special release code */
+	NULL			/* can't fsync */
+};
+
 struct inode_operations proc_link_inode_operations = {
-	NULL,			/* no file-operations */
+	&proc_fd_link_operations,/* file-operations */
 	NULL,			/* create */
 	NULL,			/* lookup */
 	NULL,			/* link */
@@ -38,11 +55,53 @@
 	NULL			/* permission */
 };
 
+/*
+ * This open routine is somewhat of a hack.... what we are doing is
+ * looking up the file structure of the newly opened proc fd file, and
+ * replacing it with the actual file structure of the process's file
+ * descriptor.  This allows plan 9 semantics, so that the returned
+ * file descriptor is an dup of the target file descriptor.
+ */
+static int proc_fd_dupf(struct inode * inode, struct file * f)
+{
+	unsigned int pid, ino;
+	int	i, fd;
+	struct task_struct * p;
+	struct file *new_f;
+	
+	for(fd=0 ; fd<NR_OPEN ; fd++)
+		if (current->files->fd[fd] == f)
+			break;
+	if (fd>=NR_OPEN)
+		return -ENOENT;	/* should never happen */
+
+	ino = inode->i_ino;
+	pid = ino >> 16;
+	ino &= 0x0000ffff;
+
+	for (i = 0 ; i < NR_TASKS ; i++)
+		if ((p = task[i]) && p->pid == pid)
+			break;
+
+	if ((i >= NR_TASKS) ||
+	    ((ino >> 8) != 1) || !(new_f = p->files->fd[ino & 0x0ff]))
+		return -ENOENT;
+
+	if (new_f->f_mode && !f->f_mode && 3)
+		return -EPERM;
+
+	new_f->f_count++;
+	current->files->fd[fd] = new_f;
+	f->f_count--;
+	return 0;
+}
+
 static int proc_follow_link(struct inode * dir, struct inode * inode,
 	int flag, int mode, struct inode ** res_inode)
 {
 	unsigned int pid, ino;
 	struct task_struct * p;
+	struct inode * new_inode;
 	int i;
 
 	*res_inode = NULL;
@@ -57,25 +116,26 @@
 	ino = inode->i_ino;
 	pid = ino >> 16;
 	ino &= 0x0000ffff;
-	iput(inode);
 	for (i = 0 ; i < NR_TASKS ; i++)
 		if ((p = task[i]) && p->pid == pid)
 			break;
-	if (i >= NR_TASKS)
+	if (i >= NR_TASKS) {
+		iput(inode);
 		return -ENOENT;
-	inode = NULL;
+	}
+	new_inode = NULL;
 	switch (ino) {
 		case PROC_PID_CWD:
-			inode = p->fs->pwd;
+			new_inode = p->fs->pwd;
 			break;
 		case PROC_PID_ROOT:
-			inode = p->fs->root;
+			new_inode = p->fs->root;
 			break;
 		case PROC_PID_EXE: {
 			struct vm_area_struct * vma = p->mm->mmap;
 			while (vma) {
 				if (vma->vm_flags & VM_EXECUTABLE) {
-					inode = vma->vm_inode;
+					new_inode = vma->vm_inode;
 					break;
 				}
 				vma = vma->vm_next;
@@ -84,17 +144,25 @@
 		}
 		default:
 			switch (ino >> 8) {
-				case PROC_PID_FD_DIR:
-					ino &= 0xff;
-					if (ino < NR_OPEN && p->files->fd[ino])
-						inode = p->files->fd[ino]->f_inode;
-					break;
+			case PROC_PID_FD_DIR:
+				ino &= 0xff;
+				if (ino < NR_OPEN && p->files->fd[ino]) {
+#ifdef PLAN9_SEMANTICS
+					if (dir) {
+						*res_inode = inode;
+						return 0;
+					}
+#endif
+					new_inode = p->files->fd[ino]->f_inode;
+				}
+				break;
 			}
 	}
-	if (!inode)
+	iput(inode);
+	if (!new_inode)
 		return -ENOENT;
-	*res_inode = inode;
-	inode->i_count++;
+	*res_inode = new_inode;
+	new_inode->i_count++;
 	return 0;
 }
 
diff -u --recursive --new-file v1.1.53/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v1.1.53/linux/include/asm-i386/unistd.h	Fri Aug 19 14:04:04 1994
+++ linux/include/asm-i386/unistd.h	Tue Oct 11 09:17:04 1994
@@ -15,67 +15,69 @@
 return -1; \
 }
 
-#define _syscall1(type,name,atype,a) \
-type name(atype a) \
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
 { \
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(a))); \
+	: "0" (__NR_##name),"b" ((long)(arg1))); \
 if (__res >= 0) \
 	return (type) __res; \
 errno = -__res; \
 return -1; \
 }
 
-#define _syscall2(type,name,atype,a,btype,b) \
-type name(atype a,btype b) \
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
 { \
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
+	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
 if (__res >= 0) \
 	return (type) __res; \
 errno = -__res; \
 return -1; \
 }
 
-#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
-type name(atype a,btype b,ctype c) \
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
 { \
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
+	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+		  "d" ((long)(arg3))); \
 if (__res>=0) \
 	return (type) __res; \
 errno=-__res; \
 return -1; \
 }
 
-#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
-type name (atype a, btype b, ctype c, dtype d) \
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
 { \
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
-	  "d" ((long)(c)),"S" ((long)(d))); \
+	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+	  "d" ((long)(arg3)),"S" ((long)(arg4))); \
 if (__res>=0) \
 	return (type) __res; \
 errno=-__res; \
 return -1; \
-}
+} 
 
-#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
-type name (atype a,btype b,ctype c,dtype d,etype e) \
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+	  type5,arg5) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
 { \
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
-	  "d" ((long)(c)),"S" ((long)(d)),"D" ((long)(e))); \
+	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+	  "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
 if (__res>=0) \
 	return (type) __res; \
 errno=-__res; \
diff -u --recursive --new-file v1.1.53/linux/include/linux/elf.h linux/include/linux/elf.h
--- v1.1.53/linux/include/linux/elf.h	Thu Aug 11 20:43:30 1994
+++ linux/include/linux/elf.h	Thu Oct 13 17:11:59 1994
@@ -75,13 +75,13 @@
 
 
 
-struct dynamic{
+typedef struct dynamic{
   int d_tag;
   union{
     int d_val;
     char * d_ptr;
   } d_un;
-};
+} Elf32_Dyn;
 
 /* The following are used with relocations */
 #define ELF32_R_SYM(x) ((x) >> 8)
@@ -100,27 +100,27 @@
 #define R_386_GOTPC	10
 #define R_386_NUM	11
 
-struct Elf32_Rel{
+typedef struct elf32_rel {
   unsigned int * offset;
   int info;
-};
+} Elf32_Rel;
 
-struct Elf32_Rela{
+typedef struct elf32_rela{
   unsigned int * offset;
   int info;
   int addend;
-};
+} Elf32_Rela;
 
-struct Elf32_Sym{
+typedef struct elf32_sym{
   int st_name;
   unsigned int st_value;
   int st_size;
   unsigned char st_info;
   unsigned char st_other;
   short int st_shndx;
-};
+} Elf32_Sym;
 
-struct elfhdr{
+typedef struct elfhdr{
   char	e_ident[16];
   short int e_type;
   short int e_machine;
@@ -135,9 +135,9 @@
   short int e_shentsize;
   short int e_shnum;
   short int e_shstrndx;
-};
+} Elf32_Ehdr;
 
-struct elf_phdr{
+typedef struct elf_phdr{
   int p_type;
   int p_offset;
   int p_vaddr;
@@ -146,7 +146,7 @@
   int p_memsz;
   int p_flags;
   int p_align;
-};
+} Elf32_Phdr;
 
 #define ELF_START_MMAP 0x80000000
 
diff -u --recursive --new-file v1.1.53/linux/include/linux/kd.h linux/include/linux/kd.h
--- v1.1.53/linux/include/linux/kd.h	Thu Aug 11 20:43:32 1994
+++ linux/include/linux/kd.h	Thu Oct 13 14:07:09 1994
@@ -108,11 +108,11 @@
 #define KIOCSOUND	0x4B2F	/* start sound generation (0 for off) */
 #define KDMKTONE	0x4B30	/* generate tone */
 
-#define KDGETLED	0x4B31	/* return current led flags */
-#define KDSETLED	0x4B32	/* set current led flags */
-#define 	LED_SCR		0x01	/* scroll lock */
-#define 	LED_CAP		0x04	/* caps lock */
-#define 	LED_NUM		0x02	/* num lock */
+#define KDGETLED	0x4B31	/* return current led state */
+#define KDSETLED	0x4B32	/* set led state [lights, not flags] */
+#define 	LED_SCR		0x01	/* scroll lock led */
+#define 	LED_CAP		0x04	/* caps lock led */
+#define 	LED_NUM		0x02	/* num lock led */
 
 #define KDGKBTYPE	0x4B33	/* get keyboard type */
 #define 	KB_84		0x01
@@ -164,15 +164,21 @@
 #define		K_RAW		0x00
 #define		K_XLATE		0x01
 #define		K_MEDIUMRAW	0x02
+#define		K_UNICODE	0x03
 #define KDGKBMODE	0x4B44	/* gets current keyboard mode */
 #define KDSKBMODE	0x4B45	/* sets current keyboard mode */
 
-/* merge with previous pair of ioctls? */
 #define		K_METABIT	0x03
 #define		K_ESCPREFIX	0x04
 #define KDGKBMETA	0x4B62	/* gets meta key handling mode */
 #define KDSKBMETA	0x4B63	/* sets meta key handling mode */
 
+#define		K_SCROLLLOCK	0x01
+#define		K_CAPSLOCK	0x02
+#define		K_NUMLOCK	0x04
+#define	KDGKBLED	0x4B64	/* get led flags (not lights) */
+#define KDSKBLED	0x4B65	/* set led flags (not lights) */
+
 struct kbentry {
 	u_char kb_table;
 	u_char kb_index;
@@ -182,13 +188,13 @@
 #define		K_SHIFTTAB	0x01
 #define		K_ALTTAB	0x02
 #define		K_ALTSHIFTTAB	0x03
-#define		K_SRQTAB	0x04
+
 #define KDGKBENT	0x4B46	/* gets one entry in translation table */
 #define KDSKBENT	0x4B47	/* sets one entry in translation table */
 
 struct kbsentry {
 	u_char kb_func;
-	u_char kb_string[512];	/* FUNC_BUFSIZE from keyboard.h */
+	u_char kb_string[512];
 };
 #define KDGKBSENT	0x4B48	/* gets one function key string entry */
 #define KDSKBSENT	0x4B49	/* sets one function key string entry */
diff -u --recursive --new-file v1.1.53/linux/include/linux/keyboard.h linux/include/linux/keyboard.h
--- v1.1.53/linux/include/linux/keyboard.h	Tue May 24 00:34:56 1994
+++ linux/include/linux/keyboard.h	Thu Oct 13 14:07:09 1994
@@ -5,24 +5,29 @@
 #define KG_CTRL		2
 #define KG_ALT		3
 #define KG_ALTGR	1
-#define KG_SHIFTL       4
-#define KG_SHIFTR       5
-#define KG_CTRLL        6
-#define KG_CTRLR        7
+#define KG_SHIFTL	4
+#define KG_SHIFTR	5
+#define KG_CTRLL	6
+#define KG_CTRLR	7
+#define KG_CAPSSHIFT	8
+
+#define NR_SHIFT	9
+
+#define NR_KEYS		128
+#define MAX_NR_KEYMAPS	256
+/* This means 64Kb if all keymaps are allocated. Only the superuser
+	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
+#define MAX_NR_OF_USER_KEYMAPS 256 	/* should be at least 7 */
 
-#define NR_KEYS 128
-#define NR_KEYMAPS 16
 extern const int NR_TYPES;
 extern const int max_vals[];
-extern unsigned short key_map[NR_KEYMAPS][NR_KEYS];
+extern unsigned short *key_maps[MAX_NR_KEYMAPS];
+extern unsigned short plain_map[NR_KEYS];
 
-#define NR_FUNC 36
-#define FUNC_BUFSIZE 512
-extern char func_buf[FUNC_BUFSIZE];
-extern char *func_table[NR_FUNC];
+#define MAX_NR_FUNC	256	/* max nr of strings assigned to keys */
 
 #define KT_LATIN	0	/* we depend on this being zero */
-#define KT_LETTER      11	/* symbol that can be acted upon by CapsLock */
+#define KT_LETTER	11	/* symbol that can be acted upon by CapsLock */
 #define KT_FN		1
 #define KT_SPEC		2
 #define KT_PAD		3
@@ -62,13 +67,240 @@
 #define K_INSERT	K(KT_FN,21)
 #define K_REMOVE	K(KT_FN,22)
 #define K_SELECT	K(KT_FN,23)
-#define K_PGUP		K(KT_FN,24)
-#define K_PGDN		K(KT_FN,25)
-#define K_MACRO         K(KT_FN,26)
-#define K_HELP          K(KT_FN,27)
-#define K_DO            K(KT_FN,28)
-#define K_PAUSE         K(KT_FN,29)
+#define K_PGUP		K(KT_FN,24) /* PGUP is a synonym for PRIOR */
+#define K_PGDN		K(KT_FN,25) /* PGDN is a synonym for NEXT */
+#define K_MACRO	 	K(KT_FN,26)
+#define K_HELP		K(KT_FN,27)
+#define K_DO		K(KT_FN,28)
+#define K_PAUSE	 	K(KT_FN,29)
+#define K_F21		K(KT_FN,30)
+#define K_F22		K(KT_FN,31)
+#define K_F23		K(KT_FN,32)
+#define K_F24		K(KT_FN,33)
+#define K_F25		K(KT_FN,34)
+#define K_F26		K(KT_FN,35)
+#define K_F27		K(KT_FN,36)
+#define K_F28		K(KT_FN,37)
+#define K_F29		K(KT_FN,38)
+#define K_F30		K(KT_FN,39)
+#define K_F31		K(KT_FN,40)
+#define K_F32		K(KT_FN,41)
+#define K_F33		K(KT_FN,42)
+#define K_F34		K(KT_FN,43)
+#define K_F35		K(KT_FN,44)
+#define K_F36		K(KT_FN,45)
+#define K_F37		K(KT_FN,46)
+#define K_F38		K(KT_FN,47)
+#define K_F39		K(KT_FN,48)
+#define K_F40		K(KT_FN,49)
+#define K_F41		K(KT_FN,50)
+#define K_F42		K(KT_FN,51)
+#define K_F43		K(KT_FN,52)
+#define K_F44		K(KT_FN,53)
+#define K_F45		K(KT_FN,54)
+#define K_F46		K(KT_FN,55)
+#define K_F47		K(KT_FN,56)
+#define K_F48		K(KT_FN,57)
+#define K_F49		K(KT_FN,58)
+#define K_F50		K(KT_FN,59)
+#define K_F51		K(KT_FN,60)
+#define K_F52		K(KT_FN,61)
+#define K_F53		K(KT_FN,62)
+#define K_F54		K(KT_FN,63)
+#define K_F55		K(KT_FN,64)
+#define K_F56		K(KT_FN,65)
+#define K_F57		K(KT_FN,66)
+#define K_F58		K(KT_FN,67)
+#define K_F59		K(KT_FN,68)
+#define K_F60		K(KT_FN,69)
+#define K_F61		K(KT_FN,70)
+#define K_F62		K(KT_FN,71)
+#define K_F63		K(KT_FN,72)
+#define K_F64		K(KT_FN,73)
+#define K_F65		K(KT_FN,74)
+#define K_F66		K(KT_FN,75)
+#define K_F67		K(KT_FN,76)
+#define K_F68		K(KT_FN,77)
+#define K_F69		K(KT_FN,78)
+#define K_F70		K(KT_FN,79)
+#define K_F71		K(KT_FN,80)
+#define K_F72		K(KT_FN,81)
+#define K_F73		K(KT_FN,82)
+#define K_F74		K(KT_FN,83)
+#define K_F75		K(KT_FN,84)
+#define K_F76		K(KT_FN,85)
+#define K_F77		K(KT_FN,86)
+#define K_F78		K(KT_FN,87)
+#define K_F79		K(KT_FN,88)
+#define K_F80		K(KT_FN,89)
+#define K_F81		K(KT_FN,90)
+#define K_F82		K(KT_FN,91)
+#define K_F83		K(KT_FN,92)
+#define K_F84		K(KT_FN,93)
+#define K_F85		K(KT_FN,94)
+#define K_F86		K(KT_FN,95)
+#define K_F87		K(KT_FN,96)
+#define K_F88		K(KT_FN,97)
+#define K_F89		K(KT_FN,98)
+#define K_F90		K(KT_FN,99)
+#define K_F91		K(KT_FN,100)
+#define K_F92		K(KT_FN,101)
+#define K_F93		K(KT_FN,102)
+#define K_F94		K(KT_FN,103)
+#define K_F95		K(KT_FN,104)
+#define K_F96		K(KT_FN,105)
+#define K_F97		K(KT_FN,106)
+#define K_F98		K(KT_FN,107)
+#define K_F99		K(KT_FN,108)
+#define K_F100		K(KT_FN,109)
+#define K_F101		K(KT_FN,110)
+#define K_F102		K(KT_FN,111)
+#define K_F103		K(KT_FN,112)
+#define K_F104		K(KT_FN,113)
+#define K_F105		K(KT_FN,114)
+#define K_F106		K(KT_FN,115)
+#define K_F107		K(KT_FN,116)
+#define K_F108		K(KT_FN,117)
+#define K_F109		K(KT_FN,118)
+#define K_F110		K(KT_FN,119)
+#define K_F111		K(KT_FN,120)
+#define K_F112		K(KT_FN,121)
+#define K_F113		K(KT_FN,122)
+#define K_F114		K(KT_FN,123)
+#define K_F115		K(KT_FN,124)
+#define K_F116		K(KT_FN,125)
+#define K_F117		K(KT_FN,126)
+#define K_F118		K(KT_FN,127)
+#define K_F119		K(KT_FN,128)
+#define K_F120		K(KT_FN,129)
+#define K_F121		K(KT_FN,130)
+#define K_F122		K(KT_FN,131)
+#define K_F123		K(KT_FN,132)
+#define K_F124		K(KT_FN,133)
+#define K_F125		K(KT_FN,134)
+#define K_F126		K(KT_FN,135)
+#define K_F127		K(KT_FN,136)
+#define K_F128		K(KT_FN,137)
+#define K_F129		K(KT_FN,138)
+#define K_F130		K(KT_FN,139)
+#define K_F131		K(KT_FN,140)
+#define K_F132		K(KT_FN,141)
+#define K_F133		K(KT_FN,142)
+#define K_F134		K(KT_FN,143)
+#define K_F135		K(KT_FN,144)
+#define K_F136		K(KT_FN,145)
+#define K_F137		K(KT_FN,146)
+#define K_F138		K(KT_FN,147)
+#define K_F139		K(KT_FN,148)
+#define K_F140		K(KT_FN,149)
+#define K_F141		K(KT_FN,150)
+#define K_F142		K(KT_FN,151)
+#define K_F143		K(KT_FN,152)
+#define K_F144		K(KT_FN,153)
+#define K_F145		K(KT_FN,154)
+#define K_F146		K(KT_FN,155)
+#define K_F147		K(KT_FN,156)
+#define K_F148		K(KT_FN,157)
+#define K_F149		K(KT_FN,158)
+#define K_F150		K(KT_FN,159)
+#define K_F151		K(KT_FN,160)
+#define K_F152		K(KT_FN,161)
+#define K_F153		K(KT_FN,162)
+#define K_F154		K(KT_FN,163)
+#define K_F155		K(KT_FN,164)
+#define K_F156		K(KT_FN,165)
+#define K_F157		K(KT_FN,166)
+#define K_F158		K(KT_FN,167)
+#define K_F159		K(KT_FN,168)
+#define K_F160		K(KT_FN,169)
+#define K_F161		K(KT_FN,170)
+#define K_F162		K(KT_FN,171)
+#define K_F163		K(KT_FN,172)
+#define K_F164		K(KT_FN,173)
+#define K_F165		K(KT_FN,174)
+#define K_F166		K(KT_FN,175)
+#define K_F167		K(KT_FN,176)
+#define K_F168		K(KT_FN,177)
+#define K_F169		K(KT_FN,178)
+#define K_F170		K(KT_FN,179)
+#define K_F171		K(KT_FN,180)
+#define K_F172		K(KT_FN,181)
+#define K_F173		K(KT_FN,182)
+#define K_F174		K(KT_FN,183)
+#define K_F175		K(KT_FN,184)
+#define K_F176		K(KT_FN,185)
+#define K_F177		K(KT_FN,186)
+#define K_F178		K(KT_FN,187)
+#define K_F179		K(KT_FN,188)
+#define K_F180		K(KT_FN,189)
+#define K_F181		K(KT_FN,190)
+#define K_F182		K(KT_FN,191)
+#define K_F183		K(KT_FN,192)
+#define K_F184		K(KT_FN,193)
+#define K_F185		K(KT_FN,194)
+#define K_F186		K(KT_FN,195)
+#define K_F187		K(KT_FN,196)
+#define K_F188		K(KT_FN,197)
+#define K_F189		K(KT_FN,198)
+#define K_F190		K(KT_FN,199)
+#define K_F191		K(KT_FN,200)
+#define K_F192		K(KT_FN,201)
+#define K_F193		K(KT_FN,202)
+#define K_F194		K(KT_FN,203)
+#define K_F195		K(KT_FN,204)
+#define K_F196		K(KT_FN,205)
+#define K_F197		K(KT_FN,206)
+#define K_F198		K(KT_FN,207)
+#define K_F199		K(KT_FN,208)
+#define K_F200		K(KT_FN,209)
+#define K_F201		K(KT_FN,210)
+#define K_F202		K(KT_FN,211)
+#define K_F203		K(KT_FN,212)
+#define K_F204		K(KT_FN,213)
+#define K_F205		K(KT_FN,214)
+#define K_F206		K(KT_FN,215)
+#define K_F207		K(KT_FN,216)
+#define K_F208		K(KT_FN,217)
+#define K_F209		K(KT_FN,218)
+#define K_F210		K(KT_FN,219)
+#define K_F211		K(KT_FN,220)
+#define K_F212		K(KT_FN,221)
+#define K_F213		K(KT_FN,222)
+#define K_F214		K(KT_FN,223)
+#define K_F215		K(KT_FN,224)
+#define K_F216		K(KT_FN,225)
+#define K_F217		K(KT_FN,226)
+#define K_F218		K(KT_FN,227)
+#define K_F219		K(KT_FN,228)
+#define K_F220		K(KT_FN,229)
+#define K_F221		K(KT_FN,230)
+#define K_F222		K(KT_FN,231)
+#define K_F223		K(KT_FN,232)
+#define K_F224		K(KT_FN,233)
+#define K_F225		K(KT_FN,234)
+#define K_F226		K(KT_FN,235)
+#define K_F227		K(KT_FN,236)
+#define K_F228		K(KT_FN,237)
+#define K_F229		K(KT_FN,238)
+#define K_F230		K(KT_FN,239)
+#define K_F231		K(KT_FN,240)
+#define K_F232		K(KT_FN,241)
+#define K_F233		K(KT_FN,242)
+#define K_F234		K(KT_FN,243)
+#define K_F235		K(KT_FN,244)
+#define K_F236		K(KT_FN,245)
+#define K_F237		K(KT_FN,246)
+#define K_F238		K(KT_FN,247)
+#define K_F239		K(KT_FN,248)
+#define K_F240		K(KT_FN,249)
+#define K_F241		K(KT_FN,250)
+#define K_F242		K(KT_FN,251)
+#define K_F243		K(KT_FN,252)
+#define K_F244		K(KT_FN,253)
+#define K_F245		K(KT_FN,254)
+#define K_F246		K(KT_FN,255)
 
+
 #define K_HOLE		K(KT_SPEC,0)
 #define K_ENTER		K(KT_SPEC,1)
 #define K_SH_REGS	K(KT_SPEC,2)
@@ -83,8 +315,13 @@
 #define K_SCROLLBACK	K(KT_SPEC,11)
 #define K_BOOT		K(KT_SPEC,12)
 #define K_CAPSON	K(KT_SPEC,13)
-#define K_COMPOSE       K(KT_SPEC,14)
+#define K_COMPOSE	K(KT_SPEC,14)
 #define K_SAK		K(KT_SPEC,15)
+#define K_DECRCONSOLE	K(KT_SPEC,16)
+#define K_INCRCONSOLE	K(KT_SPEC,17)
+
+#define K_ALLOCATED	K(KT_SPEC,126) /* dynamically allocated keymap */
+#define K_NOSUCHMAP	K(KT_SPEC,127) /* returned by KDGKBENT */
 
 #define K_P0		K(KT_PAD,0)
 #define K_P1		K(KT_PAD,1)
@@ -96,21 +333,25 @@
 #define K_P7		K(KT_PAD,7)
 #define K_P8		K(KT_PAD,8)
 #define K_P9		K(KT_PAD,9)
-#define K_PPLUS		K(KT_PAD,10)	/* key-pad plus			   */
-#define K_PMINUS	K(KT_PAD,11)	/* key-pad minus		   */
-#define K_PSTAR		K(KT_PAD,12)	/* key-pad asterisk (star)	   */
-#define K_PSLASH	K(KT_PAD,13)	/* key-pad slash		   */
-#define K_PENTER	K(KT_PAD,14)	/* key-pad enter		   */
-#define K_PCOMMA	K(KT_PAD,15)	/* key-pad comma: kludge...	   */
+#define K_PPLUS		K(KT_PAD,10)	/* key-pad plus */
+#define K_PMINUS	K(KT_PAD,11)	/* key-pad minus */
+#define K_PSTAR		K(KT_PAD,12)	/* key-pad asterisk (star) */
+#define K_PSLASH	K(KT_PAD,13)	/* key-pad slash */
+#define K_PENTER	K(KT_PAD,14)	/* key-pad enter */
+#define K_PCOMMA	K(KT_PAD,15)	/* key-pad comma: kludge... */
 #define K_PDOT		K(KT_PAD,16)	/* key-pad dot (period): kludge... */
-#define K_PPLUSMINUS    K(KT_PAD,17)    /* key-pad plus/minus              */
+#define K_PPLUSMINUS	K(KT_PAD,17)	/* key-pad plus/minus */
 
+#define NR_PAD		18
+
 #define K_DGRAVE	K(KT_DEAD,0)
 #define K_DACUTE	K(KT_DEAD,1)
 #define K_DCIRCM	K(KT_DEAD,2)
 #define K_DTILDE	K(KT_DEAD,3)
 #define K_DDIERE	K(KT_DEAD,4)
 
+#define NR_DEAD		5
+
 #define K_DOWN		K(KT_CUR,0)
 #define K_LEFT		K(KT_CUR,1)
 #define K_RIGHT		K(KT_CUR,2)
@@ -120,15 +361,12 @@
 #define K_CTRL		K(KT_SHIFT,KG_CTRL)
 #define K_ALT		K(KT_SHIFT,KG_ALT)
 #define K_ALTGR		K(KT_SHIFT,KG_ALTGR)
-#define K_SHIFTL        K(KT_SHIFT,KG_SHIFTL)
-#define K_SHIFTR        K(KT_SHIFT,KG_SHIFTR)
-#define K_CTRLL         K(KT_SHIFT,KG_CTRLL)
-#define K_CTRLR         K(KT_SHIFT,KG_CTRLR)
+#define K_SHIFTL	K(KT_SHIFT,KG_SHIFTL)
+#define K_SHIFTR	K(KT_SHIFT,KG_SHIFTR)
+#define K_CTRLL	 	K(KT_SHIFT,KG_CTRLL)
+#define K_CTRLR	 	K(KT_SHIFT,KG_CTRLR)
+#define K_CAPSSHIFT	K(KT_SHIFT,KG_CAPSSHIFT)
 
-#define NR_SHIFT	4
-
-#define K_CAPSSHIFT	K(KT_SHIFT,NR_SHIFT)
-
 #define K_ASC0		K(KT_ASCII,0)
 #define K_ASC1		K(KT_ASCII,1)
 #define K_ASC2		K(KT_ASCII,2)
@@ -139,11 +377,35 @@
 #define K_ASC7		K(KT_ASCII,7)
 #define K_ASC8		K(KT_ASCII,8)
 #define K_ASC9		K(KT_ASCII,9)
+#define K_HEX0		K(KT_ASCII,10)
+#define K_HEX1		K(KT_ASCII,11)
+#define K_HEX2		K(KT_ASCII,12)
+#define K_HEX3		K(KT_ASCII,13)
+#define K_HEX4		K(KT_ASCII,14)
+#define K_HEX5		K(KT_ASCII,15)
+#define K_HEX6		K(KT_ASCII,16)
+#define K_HEX7		K(KT_ASCII,17)
+#define K_HEX8		K(KT_ASCII,18)
+#define K_HEX9		K(KT_ASCII,19)
+#define K_HEXa		K(KT_ASCII,20)
+#define K_HEXb		K(KT_ASCII,21)
+#define K_HEXc		K(KT_ASCII,22)
+#define K_HEXd		K(KT_ASCII,23)
+#define K_HEXe		K(KT_ASCII,24)
+#define K_HEXf		K(KT_ASCII,25)
 
+#define NR_ASCII	26
+
 #define K_SHIFTLOCK	K(KT_LOCK,KG_SHIFT)
 #define K_CTRLLOCK	K(KT_LOCK,KG_CTRL)
 #define K_ALTLOCK	K(KT_LOCK,KG_ALT)
 #define K_ALTGRLOCK	K(KT_LOCK,KG_ALTGR)
+#define K_SHIFTLLOCK	K(KT_LOCK,KG_SHIFTL)
+#define K_SHIFTRLOCK	K(KT_LOCK,KG_SHIFTR)
+#define K_CTRLLLOCK	K(KT_LOCK,KG_CTRLL)
+#define K_CTRLRLOCK	K(KT_LOCK,KG_CTRLR)
+
+#define NR_LOCK		8
 
-#define MAX_DIACR       256
+#define MAX_DIACR	256
 #endif
diff -u --recursive --new-file v1.1.53/linux/include/linux/tty.h linux/include/linux/tty.h
--- v1.1.53/linux/include/linux/tty.h	Sun Oct  9 12:00:28 1994
+++ linux/include/linux/tty.h	Thu Oct 13 14:07:09 1994
@@ -18,8 +18,14 @@
 /*
  * Note: don't mess with NR_PTYS until you understand the tty minor 
  * number allocation game...
+ * (Note: the *_driver.minor_start values 1, 64, 128, 192 are
+ * hardcoded at present.)
  */
-#define NR_CONSOLES	8
+#define MIN_NR_CONSOLES	1	/* must be at least 1 */
+#define MAX_NR_CONSOLES	63	/* serial lines start at 64 */
+#define MAX_NR_USER_CONSOLES 63	/* must be root to allocate above this */
+		/* Note: the ioctl VT_GETSTATE does not work for
+		   consoles 16 and higher (since it returns a short) */
 #define NR_PTYS		64
 #define NR_LDISCS	16
 
@@ -257,8 +263,6 @@
 extern struct tty_struct * redirect;
 extern struct tty_ldisc ldiscs[];
 extern int fg_console;
-extern unsigned long video_num_columns;
-extern unsigned long video_num_lines;
 extern struct wait_queue * keypress_wait;
 
 /*	intr=^C		quit=^|		erase=del	kill=^U
diff -u --recursive --new-file v1.1.53/linux/include/linux/vt.h linux/include/linux/vt.h
--- v1.1.53/linux/include/linux/vt.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/vt.h	Thu Oct 13 14:07:09 1994
@@ -30,5 +30,13 @@
 
 #define VT_ACTIVATE	0x5606	/* make vt active */
 #define VT_WAITACTIVE	0x5607	/* wait for vt active */
+#define VT_DISALLOCATE	0x5608  /* free memory associated to vt */
+
+struct vt_sizes {
+	ushort v_rows;		/* number of rows */
+	ushort v_cols;		/* number of columns */
+	ushort v_scrollsize;	/* number of lines of scrollback */
+};
+#define VT_RESIZE	0x5609	/* set kernel's idea of screensize */
 
 #endif /* _LINUX_VT_H */
diff -u --recursive --new-file v1.1.53/linux/net/inet/ip.c linux/net/inet/ip.c
--- v1.1.53/linux/net/inet/ip.c	Sun Aug 21 17:48:41 1994
+++ linux/net/inet/ip.c	Wed Oct 12 15:35:00 1994
@@ -1803,11 +1803,9 @@
 	struct sk_buff * skb;
 	struct proto *prot;
 	struct device *dev;
-	int retransmits;
 
 	prot = sk->prot;
 	skb = sk->send_head;
-	retransmits = sk->retransmits;
 
 	while (skb != NULL)
 	{
@@ -1869,7 +1867,7 @@
 		/*
 		 *	Count retransmissions
 		 */
-		retransmits++;
+		sk->retransmits++;
 		sk->prot->retransmits ++;
 
 		/*
@@ -1881,7 +1879,7 @@
 		/*
 		 *	This should cut it off before we send too many packets.
 		 */
-		if (sk->retransmits > sk->cong_window)
+		if (sk->retransmits >= sk->cong_window)
 			break;
 		skb = skb->link3;
 	}
diff -u --recursive --new-file v1.1.53/linux/net/inet/ipx.c linux/net/inet/ipx.c
--- v1.1.53/linux/net/inet/ipx.c	Fri Aug 26 14:44:46 1994
+++ linux/net/inet/ipx.c	Fri Oct 14 10:44:45 1994
@@ -155,11 +155,11 @@
 	for (s = ipx_socket_list; s != NULL; s = s->next)
 	{
 		len += sprintf (buffer+len,"%02X   ", s->ipx_type);
-		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_source_addr.net),
+		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%04X ", htonl(s->ipx_source_addr.net),
 			s->ipx_source_addr.node[0], s->ipx_source_addr.node[1], s->ipx_source_addr.node[2],
 			s->ipx_source_addr.node[3], s->ipx_source_addr.node[4], s->ipx_source_addr.node[5],
 			htons(s->ipx_source_addr.sock));
-		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_dest_addr.net),
+		len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%04X ", htonl(s->ipx_dest_addr.net),
 			s->ipx_dest_addr.node[0], s->ipx_dest_addr.node[1], s->ipx_dest_addr.node[2],
 			s->ipx_dest_addr.node[3], s->ipx_dest_addr.node[4], s->ipx_dest_addr.node[5],
 			htons(s->ipx_dest_addr.sock));
@@ -643,10 +643,13 @@
 {
 	static unsigned short	socketNum = 0x4000;
 
-	while (ipx_find_socket(htons(socketNum)) != NULL)
-		if (socketNum > 0x7ffc) socketNum = 0x4000;
+	while (ipx_find_socket(ntohs(socketNum)) != NULL)
+		if (socketNum > 0x7ffc)
+			socketNum = 0x4000;
+		else
+			socketNum++;
 
-	return	htons(socketNum++);
+	return	ntohs(socketNum);
 }
 	
 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
@@ -726,8 +729,8 @@
 	
 	sk->state = TCP_CLOSE;	
 	sock->state = SS_UNCONNECTED;
-	
-	if(addr_len!=sizeof(addr))
+
+	if(addr_len!=sizeof(*addr))
 		return(-EINVAL);
 	addr=(struct sockaddr_ipx *)uaddr;
 	
@@ -748,6 +751,7 @@
 	memcpy(sk->ipx_dest_addr.node,addr->sipx_node,sizeof(sk->ipx_source_addr.node));
 	if(ipxrtr_get_dev(sk->ipx_dest_addr.net)==NULL)
 		return -ENETUNREACH;
+	sk->ipx_type=addr->sipx_type;
 	sock->state = SS_CONNECTED;
 	sk->state=TCP_ESTABLISHED;
 	return(0);
@@ -786,6 +790,7 @@
 		addr=&sk->ipx_source_addr;
 		
 	sipx.sipx_family = AF_IPX;
+	sipx.sipx_type = sk->ipx_type;
 	sipx.sipx_port = addr->sock;
 	sipx.sipx_network = addr->net;
 	memcpy(sipx.sipx_node,addr->node,sizeof(sipx.sipx_node));
@@ -856,7 +861,7 @@
 		int free_it=0;
 		
 		/* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */
-		if(ipx->ipx_tctrl==16)
+		if((ipx->ipx_tctrl==16) || (dev->flags & IFF_PROMISC))
 		{
 			kfree_skb(skb,FREE_READ);
 			return(0);
@@ -998,6 +1003,7 @@
 			return -ENOTCONN;
 		usipx=&local_sipx;
 		usipx->sipx_family=AF_IPX;
+		usipx->sipx_type=sk->ipx_type;
 		usipx->sipx_port=sk->ipx_dest_addr.sock;
 		usipx->sipx_network=sk->ipx_dest_addr.net;
 		memcpy(usipx->sipx_node,sk->ipx_dest_addr.node,sizeof(usipx->sipx_node));
