diff -u --recursive --new-file v1.1.91/linux/Makefile linux/Makefile
--- v1.1.91/linux/Makefile	Wed Feb 15 10:36:37 1995
+++ linux/Makefile	Wed Feb 15 10:52:56 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 91
+SUBLEVEL = 92
 
 ARCH = i386
 
@@ -198,7 +198,7 @@
 MODV = -DCONFIG_MODVERSIONS
 endif
 
-modules: dummy
+modules: include/linux/version.h
 	@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="$(CFLAGS) -DMODULE $(MODV)" modules; done
 	
 modules_install:
diff -u --recursive --new-file v1.1.91/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.1.91/linux/arch/alpha/config.in	Sun Feb  5 19:31:50 1995
+++ linux/arch/alpha/config.in	Wed Feb 15 10:50:55 1995
@@ -199,11 +199,6 @@
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
-bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n
-if [ "$CONFIG_VESA_PSPM" = "y" ]; then
-bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n
-fi
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
diff -u --recursive --new-file v1.1.91/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.1.91/linux/arch/i386/config.in	Wed Feb 15 10:36:37 1995
+++ linux/arch/i386/config.in	Wed Feb 15 10:50:55 1995
@@ -10,7 +10,7 @@
 bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
 if [ "$CONFIG_ST506" = "y" ]; then
   comment 'Please see drivers/block/README.ide for help/info on IDE drives'
-  bool '   Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD y
+  bool '   Use old disk-only driver for primary i/f' CONFIG_BLK_DEV_HD n
   if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
     bool '   Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n
   else
@@ -229,7 +229,6 @@
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
diff -u --recursive --new-file v1.1.91/linux/arch/mips/config.in linux/arch/mips/config.in
--- v1.1.91/linux/arch/mips/config.in	Mon Jan 30 06:41:55 1995
+++ linux/arch/mips/config.in	Wed Feb 15 10:50:55 1995
@@ -219,7 +219,6 @@
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
   
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
 if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
diff -u --recursive --new-file v1.1.91/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v1.1.91/linux/arch/sparc/config.in	Sun Feb  5 19:31:51 1995
+++ linux/arch/sparc/config.in	Wed Feb 15 10:50:55 1995
@@ -206,11 +206,6 @@
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
-bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n
-if [ "$CONFIG_VESA_PSPM" = "y" ]; then
-bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n
-fi
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
diff -u --recursive --new-file v1.1.91/linux/drivers/block/README.sonycd535 linux/drivers/block/README.sonycd535
--- v1.1.91/linux/drivers/block/README.sonycd535	Wed Feb 15 10:36:37 1995
+++ linux/drivers/block/README.sonycd535	Wed Feb 15 10:51:06 1995
@@ -45,7 +45,7 @@
 ======
 
 1) The drive MUST be turned on when booting or it will not be recognized!
-   (but see comments on modulized version below)
+   (but see comments on modularized version below)
 
 2) when the cdrom device is opened the eject button is disabled to keep the
    user from ejecting a mounted disk and replacing it with another.
@@ -60,8 +60,13 @@
 Many thanks to Ron Jeppesen (ronj.an@site007.saic.com) for getting
 this project off the ground.  He wrote the initial release and
 the first two patches to this driver (0.1, 0.2, and 0.3).
+Thanks also to Eberhard Moenkeberg (emoenke@gwdg.de) for prodding
+me to place this code into the mainstream Linux source tree (as
+of Linux version 1.1.91), as well as some patches to make it a
+better device citizen.  Further thanks to "S. Joel Katz"
+<stimpson@panix.com> for his MODULE patches (see details below).
 
-(aknowlegements from Ron Jeppesen in the 0.3 release:)
+(Acknowledgments from Ron Jeppesen in the 0.3 release:)
 Thanks to Corey Minyard who wrote the original CDU-31A driver on which
 this driver is based.  Thanks to Ken Pizzini and Bob Blair who provided 
 patches and feedback on the first release of this driver.
@@ -89,7 +94,7 @@
 to if MODULE is not defined. That means your patched file should behave
 exactly as it used to if compiled into the kernel.
 
-	I have an externel drive, and I usually leave it powered off. I used
+	I have an external drive, and I usually leave it powered off. I used
 to have to reboot if I needed to use the CDROM drive. Now I don't.
 
 	Even if you have an internal drive, why waste the 268K of memory
diff -u --recursive --new-file v1.1.91/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.1.91/linux/drivers/block/ll_rw_blk.c	Wed Feb 15 10:36:37 1995
+++ linux/drivers/block/ll_rw_blk.c	Wed Feb 15 10:51:06 1995
@@ -399,9 +399,6 @@
 	int correct_size;
 	struct blk_dev_struct * dev;
 	int i;
-#if defined(CONFIG_CDU535) && defined(CONFIG_CDU31A)
-	int sonycd_save_mem_start;
-#endif
 
 	/* Make sure that the first block contains something reasonable */
 	while (!*bh) {
@@ -545,24 +542,12 @@
 #ifdef CONFIG_BLK_DEV_XD
 	mem_start = xd_init(mem_start,mem_end);
 #endif
-#if defined(CONFIG_CDU535) && defined(CONFIG_CDU31A)
-	{  /* since controllers for 535 and 31A can be at same location
-	    * we have to be careful.
-	    */
-		sonycd_save_mem_start = mem_start;
-		mem_start = cdu31a_init(mem_start,mem_end);
-		if ( mem_start == sonycd_save_mem_start ) {  /* CDU31A not found */
-			mem_start = sony535_init(mem_start,mem_end);
-		}
-	}
-#else
 #ifdef CONFIG_CDU31A
 	mem_start = cdu31a_init(mem_start,mem_end);
 #endif
 #ifdef CONFIG_CDU535
 	mem_start = sony535_init(mem_start,mem_end);
 #endif
-#endif  /* CONFIG_CDU31A && CONFIG_CDU535 */
 #ifdef CONFIG_MCD
 	mem_start = mcd_init(mem_start,mem_end);
 #endif
diff -u --recursive --new-file v1.1.91/linux/drivers/block/sonycd535.c linux/drivers/block/sonycd535.c
--- v1.1.91/linux/drivers/block/sonycd535.c	Wed Feb 15 10:36:37 1995
+++ linux/drivers/block/sonycd535.c	Wed Feb 15 10:51:06 1995
@@ -44,7 +44,7 @@
  * include/linux/cdrom.h).  With this interface, CDROMs can be
  * accessed and standard audio CDs can be played back normally.
  *
- * This interface is (unfortunatly) a polled interface.  This is
+ * This interface is (unfortunately) a polled interface.  This is
  * because most Sony interfaces are set up with DMA and interrupts
  * disables.  Some (like mine) do not even have the capability to
  * handle interrupts or DMA.  For this reason you will see a lot of
@@ -65,7 +65,7 @@
  *
  * This ugly hack waits for something to happen, sleeping a little
  * between every try.  it also handles attentions, which are
- * asyncronous events from the drive informing the driver that a disk
+ * asynchronous events from the drive informing the driver that a disk
  * has been inserted, removed, etc.
  *
  * One thing about these drives: They talk in MSF (Minute Second Frame) format.
@@ -93,10 +93,11 @@
 
 
 #include <linux/config.h>
-#ifdef CONFIG_CDU535
+#if defined(CONFIG_CDU535) || defined(MODULE)
 
 #ifdef MODULE
 # include <linux/module.h>
+# include <linux/malloc.h>
 # include <linux/version.h>
 #endif
 
@@ -130,16 +131,25 @@
 #endif
 
 /*
- * this is the base address of the interface card for the Sony CDU535
+ * this is the base address of the interface card for the Sony CDU-535
  * CDROM drive.  If your jumpers are set for an address other than
  * this one (the default), change the following line to the
  * proper address.
  */
 #ifndef CDU535_ADDRESS
-#define CDU535_ADDRESS	(0x340)
+# define CDU535_ADDRESS	(0x340)
 #endif
 
-#define DEBUG	1
+#ifndef CDU535_HANDLE
+# define CDU535_HANDLE			"cdu535"
+#endif
+#ifndef CDU535_MESSAGE_NAME
+# define CDU535_MESSAGE_NAME	"Sony CDU-535"
+#endif
+
+#ifndef DEBUG
+# define DEBUG	1
+#endif
 
 /*
  *  SONY535_BUFFER_SIZE determines the size of internal buffer used
@@ -440,10 +450,10 @@
  *  should be placed in the cmd[] array, number of bytes in the command is
  *  stored in nCmd.  The response from the command will be stored in the
  *  response array.  The number of bytes you expect back (excluding status)
- *  should be passed in nReponse.  Finally, some
+ *  should be passed in nResponse.  Finally, some
  *  commands set bit 7 of the return status even when there is no second
  *  status byte, on these commands set ignoreStatusBit7 TRUE.
- *    If the command was sent and data recieved back, then we return 0,
+ *    If the command was sent and data received back, then we return 0,
  *  else we return TIME_OUT.  You still have to check the status yourself.
  *    You should call check_drive_status() before calling this routine
  *  so that you do not lose notifications of disk changes, etc.
@@ -843,7 +853,7 @@
 			break;
 
 		default:
-			panic("Unkown SONY CD cmd");
+			panic("Unknown SONY CD cmd");
 		}
 	}
 }
@@ -1432,7 +1442,8 @@
 		if (do_sony_cmd(cmd_buff, 1, status, (Byte *) & drive_config, 28, 1) == 0) {
 			/* was able to get the configuration, set drive mode as rest of init */
 #if DEBUG > 0
-			if ( (status[0] & 0x7f) != 0 )
+			/* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
+			if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
 				printk("Inquiry command returned status = 0x%x\n", status[0]);
 #endif
 			cmd_buff[0] = SONY535_SET_DRIVE_MODE;
@@ -1448,8 +1459,9 @@
 					   drive_config.product_rev_level);
 				printk("  using %d byte buffer\n", sony_buffer_size);
 
-				if (register_blkdev(MAJOR_NR, "cdu-535", &cdu_fops)) {
-					printk("Unable to get major %d for sony CDU-535 cd\n", MAJOR_NR);
+				if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
+					printk("Unable to get major %d for %s\n",
+							MAJOR_NR, CDU535_MESSAGE_NAME);
 #ifndef MODULE
 					return mem_start;
 #else
@@ -1482,19 +1494,17 @@
 		}
 	}
 
-#ifndef MODULE
-	if (!initialized)
-		printk("Did not find a Sony CDU-535 drive\n");
-	else
-		snarf_region(sony_cd_base_io, 4);
-	return mem_start;
-#else
 	if (!initialized) {
-		printk("Did not find a Sony CDU-535 drive\n");
+		printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
+#ifdef MODULE
 		return -EIO;
+#endif
 	} else {
-		snarf_region(sony_cd_base_io, 4);
+		request_region(sony_cd_base_io, 4, CDU535_HANDLE);
 	}
+#ifndef MODULE
+	return mem_start;
+#else
 	return 0;
 #endif
 }
@@ -1519,7 +1529,8 @@
 		irq_used = ints[2];
 #endif
 	if ((strings != NULL) && (*strings != '\0'))
-		printk("Sony CDU-535: Warning: Unknown interface type: %s\n", strings);
+		printk("%s: Warning: Unknown interface type: %s\n",
+				strings, CDU535_MESSAGE_NAME);
 }
 
 #else /* MODULE */
@@ -1527,21 +1538,21 @@
 void 
 cleanup_module(void)
 {
-	int     i;
+	int i;
 	if (MOD_IN_USE) {
 		printk("Sony 535 module in use, cannot remove\n");
 		return;
 	}
-	if (unregister_blkdev(MAJOR_NR, "cdu-535") == (-EINVAL)) {
-		printk("Uh oh, couldn't unregister cdu-535\n");
-		return;
-	}
+	release_region(sony_cd_base_io, 4);
 	kfree_s(sony_toc, sizeof (*sony_toc));
 	kfree_s(last_sony_subcode, sizeof (*last_sony_subcode));
 	for (i = 0; i < sony_buffer_sectors; i++)
 		kfree_s(sony_buffer[i], 2048);
 	kfree_s(sony_buffer, 4 * sony_buffer_sectors);
-	printk("cdu-535 module released\n");
+	if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
+		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
+	else
+		printk(CDU535_HANDLE " module released\n");
 }
 #endif	/* MODULE */
 
diff -u --recursive --new-file v1.1.91/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v1.1.91/linux/drivers/char/Makefile	Mon Jan 30 08:53:06 1995
+++ linux/drivers/char/Makefile	Wed Feb 15 10:50:55 1995
@@ -17,12 +17,12 @@
 	$(CC) $(CFLAGS) -c $<
 
 OBJS  = tty_io.o n_tty.o console.o keyboard.o serial.o \
-	tty_ioctl.o pty.o vt.o mem.o \
-	defkeymap.o uni_to_437.o vesa_blank.o
+	tty_ioctl.o pty.o vt.o mem.o vc_screen.o \
+	defkeymap.o consolemap.o vesa_blank.o selection.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 uni_to_437.c vesa_blank.c
+	tty_ioctl.c pty.c vt.c mem.c vc_screen.c \
+	defkeymap.c consolemap.c vesa_blank.c selection.c
 
 
 ifdef CONFIG_CYCLADES
diff -u --recursive --new-file v1.1.91/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.91/linux/drivers/char/console.c	Sun Feb  5 19:31:52 1995
+++ linux/drivers/char/console.c	Wed Feb 15 10:50:55 1995
@@ -25,20 +25,20 @@
  *     'void do_blank_screen(int)'
  *     'void do_unblank_screen(void)'
  *     'void poke_blanked_console(void)'
+ *
+ *     'unsigned short *screen_pos(int currcons, int w_offset, int viewed)'
+ *     'void complement_pos(int currcons, int offset)'
+ *     'void invert_screen(int currcons, int offset, int count, int shift)'
+ *
  *     'void scrollback(int lines)'
  *     'void scrollfront(int lines)'
- *     'int do_screendump(int arg, int mode)'
  *
  *     'int con_get_font(char *)' 
- *     'int con_set_font(char *)' 
- *     'int con_get_trans(char *)'
- *     'int con_set_trans(char *)'
+ *     'int con_set_font(char *)'
  *
- *     'int set_selection(const int arg)'
- *     'int paste_selection(struct tty_struct *tty)'
- *     'int sel_loadlut(const int arg)'
+ *     'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
  *     'int mouse_reporting(void)'
- * 
+ *
  * Hopefully this will be a rather complete VT102 implementation.
  *
  * Beeping thanks to John T Kohl.
@@ -104,40 +104,9 @@
 
 #include "kbd_kern.h"
 #include "vt_kern.h"
+#include "consolemap.h"
+#include "selection.h"
 
-#ifdef __alpha__
- 
-static inline void scrwritew(unsigned short val, unsigned short * addr)
-{
-	if ((long) addr < 0)
-		*addr = val;
-	else
-		writew(val, (unsigned long) addr);
-}
-
-static inline unsigned short scrreadw(unsigned short * addr)
-{
-	if ((long) addr < 0)
-		return *addr;
-	return readw((unsigned long) addr);
-}
-
-#else
-
-static inline void scrwritew(unsigned short val, unsigned short * addr)
-{
-	*addr = val;
-}
-
-static inline unsigned short scrreadw(unsigned short * addr)
-{
-	return *addr;
-}
-
-#endif
-
-#define writew(x,y) scrwritew((x),(y))
-#define readw(x) scrreadw(x)
 
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
@@ -149,23 +118,6 @@
 static struct termios *console_termios[MAX_NR_CONSOLES];
 static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 
-#ifdef CONFIG_SELECTION
-#include <linux/ctype.h>
-
-/* Routines for selection control. */
-int set_selection(const int arg, struct tty_struct *tty);
-int paste_selection(struct tty_struct *tty);
-static void clear_selection(void);
-static void highlight_pointer(const int currcons, const int where);
-
-/* Variables for selection control. */
-/* Use a dynamic buffer, instead of static (Dec 1994) */
-static int sel_cons = 0;
-static int sel_start = -1;
-static int sel_end;
-static char *sel_buffer = NULL;
-#endif /* CONFIG_SELECTION */
-
 #define NPAR 16
 
 static void con_setsize(unsigned long rows, unsigned long cols);
@@ -194,11 +146,13 @@
 static unsigned long	video_mem_base;		/* Base of video memory		*/
 static unsigned long	video_mem_term;		/* End of video memory		*/
 static unsigned char	video_page;		/* Initial video page (unused)  */
+       /* these two also used in vesa_blank.c */
        unsigned short	video_port_reg;		/* Video register select port	*/
        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;
+       /* these three also used in selection.c */
+       unsigned long	video_num_columns;	/* Number of text columns	*/
+       unsigned long	video_num_lines;	/* Number of text lines		*/
+       unsigned long	video_size_row;
 static unsigned long	video_screen_size;
 static int can_do_color = 0;
 static int printable = 0;			/* Is console ready for printing? */
@@ -260,10 +214,10 @@
 	unsigned long	vc_utf_char;
 	unsigned long	vc_tab_stop[5];		/* Tab stops. 160 columns. */
 	unsigned char * vc_translate;
-	unsigned char *	vc_G0_charset;
-	unsigned char *	vc_G1_charset;
-	unsigned char *	vc_saved_G0;
-	unsigned char *	vc_saved_G1;
+	unsigned char 	vc_G0_charset;
+	unsigned char 	vc_G1_charset;
+	unsigned char 	vc_saved_G0;
+	unsigned char 	vc_saved_G1;
 	/* additional information is in vt_kern.h */
 };
 
@@ -342,7 +296,7 @@
 	count /= 2;
 	while (count) {
 		count--;
-		writew(c, addr++);
+		scr_writew(c, addr++);
 	}
 }
 
@@ -352,7 +306,7 @@
 	count /= 2;
 	while (count) {
 		count--;
-		writew(readw(from++), to++);
+		scr_writew(scr_readw(from++), to++);
 	}
 }
 
@@ -522,81 +476,6 @@
 #define VT100ID "\033[?1;2c"
 #define VT102ID "\033[?6c"
 
-static unsigned char * translations[] = {
-/* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
-(unsigned char *)
-	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-	"\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
-	" !\"#$%&'()*+,-./0123456789:;<=>?"
-	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
-	"`abcdefghijklmnopqrstuvwxyz{|}~\0"
-	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-	"\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
-	"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
-	"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
-	"\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
-	"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
-	"\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
-/* vt100 graphics */
-(unsigned char *)
-	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-	"\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
-	" !\"#$%&'()*+,-./0123456789:;<=>?"
-	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
-	"\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
-	"\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
-	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-	"\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
-	"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
-	"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
-	"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
-	"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
-	"\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
-/* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
-(unsigned char *)
-	"\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
-	"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
-	"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
-	"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
-	"\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
-	"\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
-	"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
-	"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
-	"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
-	"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
-	"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
-	"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
-	"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
-	"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
-	"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
-	"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
- /* USER: customizable mappings, initialized as the previous one (IBM) */
-(unsigned char *)
-	"\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
-	"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
-	"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
-	"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
-	"\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
-	"\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
-	"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
-	"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
-	"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
-	"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
-	"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
-	"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
-	"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
-	"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
-	"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
-	"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
-};
-
-#define NORM_TRANS (translations[0])
-#define GRAF_TRANS (translations[1])
-#define NULL_TRANS (translations[2])
-#define USER_TRANS (translations[3])
-
 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 				       8,12,10,14, 9,13,11,15 };
 
@@ -641,9 +520,9 @@
 static inline void __set_origin(unsigned short offset)
 {
 	unsigned long flags;
-#ifdef CONFIG_SELECTION
+
 	clear_selection();
-#endif /* CONFIG_SELECTION */
+
 	save_flags(flags); cli();
 	__origin = offset;
 	outb_p(12, video_port_reg);
@@ -740,12 +619,12 @@
 			count = (video_num_lines-1)*video_num_columns;
 			while (count) {
 				count--;
-				writew(readw(s++),d++);
+				scr_writew(scr_readw(s++),d++);
 			}
 			count = video_num_columns;
 			while (count) {
 				count--;
-				writew(video_erase_char, d++);
+				scr_writew(video_erase_char, d++);
 			}
 			scr_end -= origin-video_mem_start;
 			pos -= origin-video_mem_start;
@@ -759,7 +638,7 @@
 			count = video_num_columns;
 			while (count) {
 				count--;
-				writew(video_erase_char, d++);
+				scr_writew(video_erase_char, d++);
 			}
 		}
 		set_origin(currcons);
@@ -770,12 +649,12 @@
 
 		while (count) {
 			count--;
-			writew(readw(s++), d++);
+			scr_writew(scr_readw(s++), d++);
 		}
 		count = video_num_columns;
 		while (count) {
 			count--;
-			writew(video_erase_char, d++);
+			scr_writew(video_erase_char, d++);
 		}
 	}
 }
@@ -792,12 +671,12 @@
 	count = (b-t-1)*video_num_columns;
 	while (count) {
 		count--;
-		writew(readw(--s), --d);
+		scr_writew(scr_readw(--s), --d);
 	}
 	count = video_num_columns;
 	while (count) {
 		count--;
-		writew(video_erase_char, --d);
+		scr_writew(video_erase_char, --d);
 	}
 	has_scrolled = 1;
 }
@@ -873,7 +752,7 @@
 	}
 	while (count) {
 		count--;
-		writew(video_erase_char, start++);
+		scr_writew(video_erase_char, start++);
 	}
 	need_wrap = 0;
 }
@@ -901,7 +780,7 @@
 	}
 	while (count) {
 		count--;
-		writew(video_erase_char, start++);
+		scr_writew(video_erase_char, start++);
 	}
 	need_wrap = 0;
 }
@@ -919,7 +798,7 @@
 
 	while (count) {
 		count--;
-		writew(video_erase_char, start++);
+		scr_writew(video_erase_char, start++);
 	}
 	need_wrap = 0;
 }
@@ -934,7 +813,7 @@
 			attr = (attr & 0xf0) | halfcolor;
 	}
 	if (reverse ^ decscnm)
-		attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
+		attr = reverse_video_char(attr);
 	if (blink)
 		attr ^= 0x80;
 	if (intensity == 2)
@@ -946,7 +825,7 @@
 			attr = (attr & 0xf0) | 0x08;
 	}
 	if (decscnm)
-		video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
+		video_erase_char = (reverse_video_char(color) << 8) | ' ';
 	else
 		video_erase_char = (color << 8) | ' ';
 }
@@ -989,7 +868,7 @@
 				  * control chars if defined, don't set
 				  * bit 8 on output.
 				  */
-				translate = (charset == 0
+				translate = set_translate(charset == 0
 						? G0_charset
 						: G1_charset);
 				disp_ctrl = 0;
@@ -999,7 +878,7 @@
 				  * Select first alternate font, let's
 				  * chars < 32 be displayed as ROM chars.
 				  */
-				translate = NULL_TRANS;
+				translate = set_translate(NULL_MAP);
 				disp_ctrl = 1;
 				toggle_meta = 0;
 				break;
@@ -1007,7 +886,7 @@
 				  * Select second alternate font, toggle
 				  * high bit before displaying as ROM char.
 				  */
-				translate = NULL_TRANS;
+				translate = set_translate(NULL_MAP);
 				disp_ctrl = 1;
 				toggle_meta = 1;
 				break;
@@ -1072,9 +951,17 @@
 	respond_string(buf, tty);
 }
 
-#ifdef CONFIG_SELECTION
-static void mouse_report(int currcons, struct tty_struct * tty,
-			 int butt, int mrx, int mry)
+static inline void status_report(struct tty_struct * tty)
+{
+	respond_string("\033[0n", tty);	/* Terminal ok */
+}
+
+static inline void respond_ID(struct tty_struct * tty)
+{
+	respond_string(VT102ID, tty);
+}
+
+void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
 {
 	char buf[8];
 
@@ -1082,33 +969,85 @@
 		(char)('!' + mry));
 	respond_string(buf, tty);
 }
-#endif
 
-static inline void status_report(int currcons, struct tty_struct * tty)
+/* invoked via ioctl(TIOCLINUX) */
+int mouse_reporting(void)
 {
-	respond_string("\033[0n", tty);	/* Terminal ok */
+	int currcons = fg_console;
+
+	return report_mouse;
 }
 
-static inline void respond_ID(int currcons, struct tty_struct * tty)
+static inline unsigned short *screenpos(int currcons, int offset, int viewed)
 {
-	respond_string(VT102ID, tty);
+	unsigned short *p = (unsigned short *)(origin + offset);
+	if (viewed && currcons == fg_console)
+		p -= (__real_origin - __origin);
+	return p;
 }
 
-static void invert_screen(int currcons) {
+/* Note: inverting the screen twice should revert to the original state */
+void invert_screen(int currcons, int offset, int count, int viewed)
+{
 	unsigned short *p;
 
+	count /= 2;
+	p = screenpos(currcons, offset, viewed);
 	if (can_do_color)
-		for (p = (unsigned short *)origin; p < (unsigned short *)scr_end; p++) {
-			unsigned short old = readw(p);
-			writew((old & 0x88ff) | (((old >> 4) | ((old & 0xff00) << 4)) & 0x7700), p);
+		while (count--) {
+			unsigned short old = scr_readw(p);
+			scr_writew(reverse_video_short(old), p);
+			p++;
 		}
 	else
-		for (p = (unsigned short *)origin; p < (unsigned short *)scr_end; p++) {
-			unsigned short old = readw(p);
-			writew(old ^ ((old & 0x0700 == 0x0100) ? 0x7000 : 0x7700), p);
+		while (count--) {
+			unsigned short old = scr_readw(p);
+			scr_writew(old ^ ((old & 0x0700 == 0x0100)
+					  ? 0x7000 : 0x7700), p);
 		}
 }
 
+/* used by selection: complement pointer position */
+void complement_pos(int currcons, int offset)
+{
+	static unsigned short *p = NULL;
+	static unsigned short old = 0;
+
+	if (p)
+		scr_writew(old, p);
+	if (offset == -1)
+		p = NULL;
+	else {
+		p = screenpos(currcons, offset, 1);
+		old = scr_readw(p);
+		scr_writew(old ^ 0x7700, p);
+	}
+}
+
+/* used by selection */
+unsigned short screen_word(int currcons, int offset, int viewed)
+{
+	return scr_readw(screenpos(currcons, offset, viewed));
+}
+
+/* used by vcs - note the word offset */
+unsigned short *screen_pos(int currcons, int w_offset, int viewed)
+{
+	return screenpos(currcons, 2 * w_offset, viewed);
+}
+
+void getconsxy(int currcons, char *p)
+{
+	p[0] = x;
+	p[1] = y;
+}
+
+void putconsxy(int currcons, char *p)
+{
+	gotoxy(currcons, p[0], p[1]);
+	set_cursor(currcons);
+}
+
 static void set_mode(int currcons, int on_off)
 {
 	int i;
@@ -1132,7 +1071,7 @@
 			case 5:			/* Inverted screen on/off */
 				if (decscnm != on_off) {
 					decscnm = on_off;
-					invert_screen(currcons);
+					invert_screen(currcons, 0, video_screen_size, 0);
 					update_attr(currcons);
 				}
 				break;
@@ -1211,8 +1150,8 @@
 	unsigned short * p = (unsigned short *) pos;
 
 	while (i++ < video_num_columns) {
-		tmp = readw(p);
-		writew(old, p);
+		tmp = scr_readw(p);
+		scr_writew(old, p);
 		old = tmp;
 		p++;
 	}
@@ -1231,10 +1170,10 @@
 	unsigned short * p = (unsigned short *) pos;
 
 	while (++i < video_num_columns) {
-		writew(readw(p+1), p);
+		scr_writew(scr_readw(p+1), p);
 		p++;
 	}
-	writew(video_erase_char, p);
+	scr_writew(video_erase_char, p);
 	need_wrap = 0;
 }
 
@@ -1309,7 +1248,7 @@
 	color		= s_color;
 	G0_charset	= saved_G0;
 	G1_charset	= saved_G1;
-	translate	= charset ? G1_charset : G0_charset;
+	translate	= set_translate(charset ? G1_charset : G0_charset);
 	update_attr(currcons);
 	need_wrap = 0;
 }
@@ -1323,9 +1262,9 @@
 	bottom		= video_num_lines;
 	vc_state	= ESnormal;
 	ques		= 0;
-	translate	= NORM_TRANS;
-	G0_charset	= NORM_TRANS;
-	G1_charset	= GRAF_TRANS;
+	translate	= set_translate(NORM_MAP);
+	G0_charset	= NORM_MAP;
+	G1_charset	= GRAF_MAP;
 	charset		= 0;
 	need_wrap	= 0;
 	report_mouse	= 0;
@@ -1412,11 +1351,10 @@
 	    }
 	    return 0;
 	}
-#ifdef CONFIG_SELECTION
-	/* clear the selection */
+
 	if (currcons == sel_cons)
 		clear_selection();
-#endif /* CONFIG_SELECTION */
+
 	disable_bh(KEYBOARD_BH);
 	while (!tty->stopped &&	count) {
 		c = from_user ? get_fs_byte(buf) : *buf;
@@ -1426,7 +1364,6 @@
 		    /* 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--;
@@ -1448,18 +1385,15 @@
 			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];
+		    tc = conv_uni_to_pc(c);
+		    if (tc == -1 || tc == -2)
+		      continue;
+		    if (tc == -3 || tc == -4) {	/* hashtable not valid */
+						/* or symbol not found */
+			tc = (c <= 0xff) ? translate[c] : 040;
 			ok = 0;
-		    }
+		    } else
+		        ok = 1;
 		} else {	/* no utf */
 		    tc = translate[toggle_meta ? (c|0x80) : c];
 		    ok = 0;
@@ -1483,7 +1417,7 @@
 			}
 			if (decim)
 				insert_char(currcons);
-			writew((attr << 8) + tc, (unsigned short *) pos);
+			scr_writew((attr << 8) + tc, (unsigned short *) pos);
 			if (x == video_num_columns - 1)
 				need_wrap = decawm;
 			else {
@@ -1522,12 +1456,12 @@
 				continue;
 			case 14:
 				charset = 1;
-				translate = G1_charset;
+				translate = set_translate(G1_charset);
 				disp_ctrl = 1;
 				continue;
 			case 15:
 				charset = 0;
-				translate = G0_charset;
+				translate = set_translate(G0_charset);
 				disp_ctrl = 0;
 				continue;
 			case 24: case 26:
@@ -1567,7 +1501,7 @@
 					tab_stop[x >> 5] |= (1 << (x & 31));
 					continue;
 				  case 'Z':
-					respond_ID(currcons,tty);
+					respond_ID(tty);
 					continue;
 				  case '7':
 					save_cur(currcons);
@@ -1628,7 +1562,7 @@
 					case 'n':
 						if (!ques)
 							if (par[0] == 5)
-								status_report(currcons,tty);
+								status_report(tty);
 							else if (par[0] == 6)
 								cursor_report(currcons,tty);
 						continue;
@@ -1692,7 +1626,7 @@
 						continue;
 					case 'c':
 						if (!par[0])
-							respond_ID(currcons,tty);
+							respond_ID(tty);
 						continue;
 					case 'g':
 						if (!par[0])
@@ -1775,28 +1709,28 @@
 				continue;
 			case ESsetG0:
 				if (c == '0')
-					G0_charset = GRAF_TRANS;
+					G0_charset = GRAF_MAP;
 				else if (c == 'B')
-					G0_charset = NORM_TRANS;
+					G0_charset = NORM_MAP;
 				else if (c == 'U')
-					G0_charset = NULL_TRANS;
+					G0_charset = NULL_MAP;
 				else if (c == 'K')
-					G0_charset = USER_TRANS;
+					G0_charset = USER_MAP;
 				if (charset == 0)
-					translate = G0_charset;
+					translate = set_translate(G0_charset);
 				vc_state = ESnormal;
 				continue;
 			case ESsetG1:
 				if (c == '0')
-					G1_charset = GRAF_TRANS;
+					G1_charset = GRAF_MAP;
 				else if (c == 'B')
-					G1_charset = NORM_TRANS;
+					G1_charset = NORM_MAP;
 				else if (c == 'U')
-					G1_charset = NULL_TRANS;
+					G1_charset = NULL_MAP;
 				else if (c == 'K')
-					G1_charset = USER_TRANS;
+					G1_charset = USER_MAP;
 				if (charset == 1)
-					translate = G1_charset;
+					translate = set_translate(G1_charset);
 				vc_state = ESnormal;
 				continue;
 			default:
@@ -1859,7 +1793,7 @@
 			if (c == 10 || c == 13)
 				continue;
 		}
-		writew((attr << 8) + c, (unsigned short *) pos);
+		scr_writew((attr << 8) + c, (unsigned short *) pos);
 		if (x == video_num_columns - 1) {
 			need_wrap = 1;
 			continue;
@@ -2189,9 +2123,9 @@
 		return;
 	}
 	lock = 1;
-#ifdef CONFIG_SELECTION
+
 	clear_selection();
-#endif /* CONFIG_SELECTION */
+
 	if (!console_blanked)
 		get_scrmem(fg_console);
 	else
@@ -2207,59 +2141,6 @@
 }
 
 /*
- * do_screendump is used for three tasks:
- *   if (mode==0) is the old ioctl(TIOCLINUX,0)
- *   if (mode==1) dumps wd,hg, cursor position, and all the char-attr pairs
- *   if (mode==2) restores what mode1 got.
- * the new modes are needed for a fast and complete dump-restore cycle,
- * needed to implement root-window menus in text mode (A Rubini Nov 1994)
- */
-int do_screendump(unsigned long arg, int mode)
-{
-	char *sptr, *buf = (char *)arg;
-	int currcons, l, chcount;
-
-	l = verify_area(VERIFY_READ, buf, 2);
-	if (l)
-		return l;
-	currcons = get_fs_byte(buf+1);
-	currcons = (currcons ? currcons-1 : fg_console);
-	if (!vc_cons_allocated(currcons))
-		return -EIO;
-	
-	/* mode 0 needs 2+wd*ht, modes 1 and 2 need 4+2*wd*ht */
-	chcount=video_num_columns*video_num_lines;
-	l = verify_area(mode==2 ? VERIFY_READ :VERIFY_WRITE,
-		buf, (2+chcount)*(mode ? 2 : 1));
-	if (l)
-		return l;
-	if (mode<2) {
-	put_fs_byte((char)(video_num_lines),buf++);   
-	put_fs_byte((char)(video_num_columns),buf++);
-	    }
-#ifdef CONFIG_SELECTION
-	clear_selection();
-#endif
-	switch(mode) {
-	    case 0:
-			sptr = (char *) origin;
-			for (l=chcount; l>0 ; l--, sptr++)
-				put_fs_byte(*sptr++,buf++);	
-			break;
-	    case 1:
-			put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++);
-/*XXX*/			memcpy_tofs(buf,(char *)origin,2*chcount);
-			break;
-	    case 2:
-			gotoxy(currcons, get_fs_byte(buf+2), get_fs_byte(buf+3));
-			buf+=4; /* ioctl#, console#, x,y */
-/*XXX*/			memcpy_fromfs((char *)origin,buf,2*chcount);
-			break;
-	    }
-	return(0);
-}
-
-/*
  * Allocate the console screen memory.
  */
 int con_open(struct tty_struct *tty, struct file * filp)
@@ -2283,289 +2164,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_SELECTION
-/* correction factor for when screen is hardware-scrolled */
-#define	hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
-
-/* set reverse video on characters s-e of console with selection. */
-static void highlight(const int currcons, const int s, const int e)
-{
-	unsigned char *p, *p1, *p2;
-
-	p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
-	p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
-
-	for (p = p1; p <= p2; p += 2)
-		*p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
-}
-
-/* use complementary color to show the pointer */
-static void highlight_pointer(const int currcons, const int where)
-{
-	unsigned char *p;
-	static unsigned char *prev=NULL;
-
-	if (where==-1) /* remove the pointer */
-	{
-		if (prev)
-		{
-			*prev ^= 0x77;
-			prev=NULL;
-		}
-	}
-	else
-	{
-		p = (unsigned char *)origin - hwscroll_offset + where + 1;
-		*p ^= 0x77;
-		if (prev) *prev ^= 0x77; /* remove the previous one */
-		prev=p;
-	}
-}
-
-
-/*
- * This function uses a 128-bit look up table
- * WARNING: This depends on both endianness and the ascii code
- */
-static unsigned long inwordLut[4]={
-  0x00000000, /* control chars     */
-  0x03FF0000, /* digits            */
-  0x87FFFFFE, /* uppercase and '_' */
-  0x07FFFFFE  /* lowercase         */
-};
-static inline int inword(const char c) {
-   return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
-}
-
-/* set inwordLut contents. Invoked by ioctl(). */
-int sel_loadlut(const int arg)
-{
-    memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
-    return 0;
-}
-
-/* does screen address p correspond to character at LH/RH edge of screen? */
-static inline int atedge(const int p)
-{
-	return (!(p % video_size_row) || !((p + 2) % video_size_row));
-}
-
-/* constrain v such that v <= u */
-static inline unsigned short limit(const unsigned short v, const unsigned short u)
-{
-/* gcc miscompiles the ?: operator, so don't use it.. */
-	if (v > u)
-		return u;
-	return v;
-}
-
-/* invoked via ioctl(TIOCLINUX) */
-int mouse_reporting(void)
-{
-	int currcons = fg_console;
-
-	return report_mouse;
-}
-
-/* set the current selection. Invoked by ioctl(). */
-int set_selection(const int arg, struct tty_struct *tty)
-{
-	unsigned short *args, xs, ys, xe, ye;
-	int currcons = fg_console;
-	int sel_mode, new_sel_start, new_sel_end, spc;
-	char *bp, *obp, *spos;
-	int i, ps, pe;
-	char *off = (char *)origin - hwscroll_offset;
-
-	unblank_screen();
-	args = (unsigned short *)(arg + 1);
-	xs = get_fs_word(args++) - 1;
-	ys = get_fs_word(args++) - 1;
-	xe = get_fs_word(args++) - 1;
-	ye = get_fs_word(args++) - 1;
-	sel_mode = get_fs_word(args);
-
-	xs = limit(xs, video_num_columns - 1);
-	ys = limit(ys, video_num_lines - 1);
-	xe = limit(xe, video_num_columns - 1);
-	ye = limit(ye, video_num_lines - 1);
-	ps = ys * video_size_row + (xs << 1);
-	pe = ye * video_size_row + (xe << 1);
-
-	if (report_mouse && (sel_mode & 16)) {
-		mouse_report(currcons, tty, sel_mode & 15, xs, ys);
-		return 0;
-	}
-
-	if (ps > pe)	/* make sel_start <= sel_end */
-	{
-		int tmp = ps;
-		ps = pe;
-		pe = tmp;
-	}
-
-	switch (sel_mode)
-	{
-		case 0:	/* character-by-character selection */
-			new_sel_start = ps;
-			new_sel_end = pe;
-			break;
-		case 1:	/* word-by-word selection */
-			spc = isspace(*(off + ps));
-			for (new_sel_start = ps; ; ps -= 2)
-			{
-				if ((spc && !isspace(*(off + ps))) ||
-				    (!spc && !inword(*(off + ps))))
-					break;
-				new_sel_start = ps;
-				if (!(ps % video_size_row))
-					break;
-			}
-			spc = isspace(*(off + pe));
-			for (new_sel_end = pe; ; pe += 2)
-			{
-				if ((spc && !isspace(*(off + pe))) ||
-				    (!spc && !inword(*(off + pe))))
-					break;
-				new_sel_end = pe;
-				if (!((pe + 2) % video_size_row))
-					break;
-			}
-			break;
-		case 2:	/* line-by-line selection */
-			new_sel_start = ps - ps % video_size_row;
-			new_sel_end = pe + video_size_row
-				    - pe % video_size_row - 2;
-			break;
-		case 3: /* pointer highlight */
-			if (sel_cons != currcons)
-			{
-				clear_selection();
-				sel_cons = currcons;
-			}
-			highlight_pointer(sel_cons,pe);
-			return 0; /* nothing more */
-		default:
-			return -EINVAL;
-	}
-	/* remove the pointer */
-	highlight_pointer(sel_cons,-1);
-	/* select to end of line if on trailing space */
-	if (new_sel_end > new_sel_start &&
-		!atedge(new_sel_end) && isspace(*(off + new_sel_end)))
-	{
-		for (pe = new_sel_end + 2; ; pe += 2)
-		{
-			if (!isspace(*(off + pe)) || atedge(pe))
-				break;
-		}
-		if (isspace(*(off + pe)))
-			new_sel_end = pe;
-	}
-	if (sel_cons != currcons)
-	{
-		clear_selection();
-		sel_cons = currcons;
-	}
-	if (sel_start == -1)	/* no current selection */
-		highlight(sel_cons, new_sel_start, new_sel_end);
-	else if (new_sel_start == sel_start)
-	{
-		if (new_sel_end == sel_end)	/* no action required */
-			return 0;
-		else if (new_sel_end > sel_end)	/* extend to right */
-			highlight(sel_cons, sel_end + 2, new_sel_end);
-		else				/* contract from right */
-			highlight(sel_cons, new_sel_end + 2, sel_end);
-	}
-	else if (new_sel_end == sel_end)
-	{
-		if (new_sel_start < sel_start)	/* extend to left */
-			highlight(sel_cons, new_sel_start, sel_start - 2);
-		else				/* contract from left */
-			highlight(sel_cons, sel_start, new_sel_start - 2);
-	}
-	else	/* some other case; start selection from scratch */
-	{
-		clear_selection();
-		highlight(sel_cons, new_sel_start, new_sel_end);
-	}
-	sel_start = new_sel_start;
-	sel_end = new_sel_end;
-
-	/* realloc the buffer (it seems to be efficient, anyway) */
-	if (sel_buffer) kfree(sel_buffer);
-	sel_buffer = kmalloc((sel_end-sel_start)/2+2, GFP_KERNEL);
-	if (!sel_buffer)
-	{
-		printk("selection: kmalloc() failed\n");
-		clear_selection();
-		return (0); /* is it right? */
-	}
-	obp = bp = sel_buffer;
-	for (i = sel_start; i <= sel_end; i += 2)
-	{
-		spos = (char *)off + i;
-		*bp++ = *spos;
-		if (!isspace(*spos))
-			obp = bp;
-		if (! ((i + 2) % video_size_row))
-		{
-			/* strip trailing blanks from line and add newline,
-			   unless non-space at end of line. */
-			if (obp != bp)
-			{
-				bp = obp;
-				*bp++ = '\r';
-			}
-			obp = bp;
-		}
-	}
-	*bp = '\0';
-	return 0;
-}
-
-/* insert the contents of the selection buffer into the queue of the
-   tty associated with the current console. Invoked by ioctl(). */
-int paste_selection(struct tty_struct *tty)
-{
-	struct wait_queue wait = { current, NULL };
-	char	*bp = sel_buffer;
-	int	c, l;
-	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
-	
-	if (!bp || !bp[0])
-		return 0;
-	unblank_screen();
-	c = strlen(sel_buffer);
-	current->state = TASK_INTERRUPTIBLE;
-	add_wait_queue(&vt->paste_wait, &wait);
-	while (c) {
-		if (test_bit(TTY_THROTTLED, &tty->flags)) {
-			schedule();
-			continue;
-		}
-		l = MIN(c, tty->ldisc.receive_room(tty));
-		tty->ldisc.receive_buf(tty, bp, 0, l);
-		c -= l;
-		bp += l;
-	}
-	current->state = TASK_RUNNING;
-	return 0;
-}
-
-/* remove the current selection highlight, if any, from the console holding
-   the selection. */
-static void clear_selection()
-{
-	highlight_pointer(sel_cons, -1); /* hide the pointer */
-	if (sel_start != -1)
-	{
-		highlight(sel_cons, sel_start, sel_end);
-		sel_start = -1;
-	}
-}
-#endif /* CONFIG_SELECTION */
 
 /*
  * PIO_FONT support.
@@ -2668,43 +2266,11 @@
 
 int con_set_font (char *arg)
 {
+	hashtable_contents_valid = 0;
 	return set_get_font (arg,1);
 }
 
 int con_get_font (char *arg)
 {
 	return set_get_font (arg,0);
-}
-
-/*
- * Load customizable translation table (USER_TRANS[]). All checks are here,
- * so we need only include 'return con_set_trans(arg)' in the ioctl handler
- * arg points to a 256 byte translation table.
- */
-int con_set_trans(char * arg)
-{
-	int i;
-
-	i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
-	if (i)
-		return i;
-
-	for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
-	USER_TRANS[012]=0;
-	USER_TRANS[014]=0;
-	USER_TRANS[015]=0;
-	USER_TRANS[033]=0;
-	return 0;
-}
-
-int con_get_trans(char * arg)
-{
-	int i;
-
-	i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
-	if (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.91/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c
--- v1.1.91/linux/drivers/char/consolemap.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/consolemap.c	Wed Feb 15 10:50:55 1995
@@ -0,0 +1,286 @@
+/*
+ * consolemap.c
+ *
+ * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
+ * to font positions.
+ *
+ * aeb, 950210
+ */
+
+#include <linux/kd.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <asm/segment.h>
+#include "consolemap.h"
+
+static unsigned char * translations[] = {
+/* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
+(unsigned char *)
+	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+	"\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
+	" !\"#$%&'()*+,-./0123456789:;<=>?"
+	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+	"`abcdefghijklmnopqrstuvwxyz{|}~\0"
+	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+	"\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
+	"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
+	"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
+	"\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
+	"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
+	"\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
+/* vt100 graphics */
+(unsigned char *)
+	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+	"\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
+	" !\"#$%&'()*+,-./0123456789:;<=>?"
+	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
+	"\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
+	"\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
+	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+	"\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
+	"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
+	"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
+	"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
+	"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
+	"\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
+/* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
+(unsigned char *)
+	"\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
+	"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
+	"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
+	"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
+	"\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
+	"\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
+	"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
+	"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
+	"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+	"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+	"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+	"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+	"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+	"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+	"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
+	"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
+ /* USER: customizable mappings, initialized as the previous one (IBM) */
+(unsigned char *)
+	"\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
+	"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
+	"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
+	"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
+	"\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
+	"\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
+	"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
+	"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
+	"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+	"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+	"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+	"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+	"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+	"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+	"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
+	"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
+};
+
+/* the above mappings are not invertible - this is just a best effort */
+static unsigned char * inv_translate = NULL;
+static unsigned char inv_norm_transl[E_TABSZ];
+static unsigned char * inverse_translations[4] = { NULL, NULL, NULL, NULL };
+
+static void set_inverse_transl(int i)
+{
+	int j;
+	unsigned char *p = translations[i];
+	unsigned char *q = inverse_translations[i];
+
+	if (!q) {
+		/* slightly messy to avoid calling kmalloc too early */
+		q = inverse_translations[i] = ((i == NORM_MAP)
+			? inv_norm_transl
+			: (unsigned char *) kmalloc(E_TABSZ, GFP_KERNEL));
+		if (!q)
+			return;
+	}
+	for (j=0; j<E_TABSZ; j++)
+		q[j] = 0;
+	for (j=0; j<E_TABSZ; j++)
+		if (q[p[j]] < 32)	/* prefer '-' above SHY etc. */
+			q[p[j]] = j;
+}
+
+unsigned char *set_translate(int m)
+{
+	if (!inverse_translations[m])
+		set_inverse_transl(m);
+	inv_translate = inverse_translations[m];
+	return translations[m];
+}
+
+/*
+ * Inverse translation is impossible for several reasons:
+ * 1. The translation maps are not 1-1
+ * 2. The text may have been written while a different translation map
+ *    was active
+ * Still, it is now possible to a certain extent to cut and paste non-ASCII.
+ */
+unsigned char inverse_translate(unsigned char c) {
+	return ((inv_translate && inv_translate[c]) ? inv_translate[c] : c);
+}
+
+/*
+ * Load customizable translation table
+ * arg points to a 256 byte translation table.
+ */
+int con_set_trans(char * arg)
+{
+	int i;
+	unsigned char *p = translations[USER_MAP];
+
+	i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
+	if (i)
+		return i;
+
+	for (i=0; i<E_TABSZ ; i++)
+		p[i] = get_fs_byte(arg+i);
+	p[012] = p[014] = p[015] = p[033] = 0;
+	set_inverse_transl(USER_MAP);
+	return 0;
+}
+
+int con_get_trans(char * arg)
+{
+	int i;
+	unsigned char *p = translations[USER_MAP];
+
+	i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
+	if (i)
+		return i;
+
+	for (i=0; i<E_TABSZ ; i++) put_fs_byte(p[i],arg+i);
+	return 0;
+}
+
+/*
+ * Unicode -> current font conversion 
+ *
+ * A font has at most 512 chars, usually 256.
+ * But one font position may represent several Unicode chars
+ * (and moreover, hashtables work best when they are not too full),
+ * so pick HASHSIZE somewhat larger than 512.
+ * Since there are likely to be long consecutive stretches
+ * (like U+0000 to U+00FF), HASHSTEP should not be too small.
+ * Searches longer than MAXHASHLEVEL steps are refused, unless
+ * requested explicitly.
+ *
+ * Note: no conversion tables are compiled in, so the user
+ * must supply an explicit mapping herself. See kbd-0.90 (or an
+ * earlier kernel version) for the default Unicode-to-PC mapping.
+ * Usually, the mapping will be loaded simultaneously with the font.
+ */
+
+#define HASHSIZE   641
+#define HASHSTEP   189		/* yields hashlevel = 3 initially */
+#define MAXHASHLEVEL 6
+static struct unipair hashtable[HASHSIZE];
+
+int hashtable_contents_valid = 0; 	/* cleared by setfont */
+
+static unsigned int hashsize;
+static unsigned int hashstep;
+static unsigned int hashlevel;
+static unsigned int maxhashlevel;
+
+void
+con_clear_unimap(struct unimapinit *ui) {
+	int i;
+
+	/* read advisory values for hash algorithm */
+	hashsize = ui->advised_hashsize;
+	if (hashsize < 256 || hashsize > HASHSIZE)
+	  hashsize = HASHSIZE;
+	hashstep = (ui->advised_hashstep % hashsize);
+	if (hashstep < 64)
+	  hashstep = HASHSTEP;
+	maxhashlevel = ui->advised_hashlevel;
+	if (!maxhashlevel)
+	  maxhashlevel = MAXHASHLEVEL;
+	if (maxhashlevel > hashsize)
+	  maxhashlevel = hashsize;
+
+	/* initialize */
+	hashlevel = 0;
+	for (i=0; i<hashsize; i++)
+	  hashtable[i].unicode = 0xffff;
+	hashtable_contents_valid = 1;
+}
+
+int
+con_set_unimap(ushort ct, struct unipair *list){
+	int i, lct;
+	ushort u, hu;
+	struct unimapinit hashdefaults = { 0, 0, 0 };
+
+	if (!hashtable_contents_valid)
+	  con_clear_unimap(&hashdefaults);
+	while(ct) {
+	    u = get_fs_word(&list->unicode);
+	    i = u % hashsize;
+	    lct = 1;
+	    while ((hu = hashtable[i].unicode) != 0xffff && hu != u) {
+		if (lct++ >=  maxhashlevel)
+		  return -ENOMEM;
+		i += hashstep;
+		if (i >= hashsize)
+		  i -= hashsize;
+	    }
+	    if (lct > hashlevel)
+	      hashlevel = lct;
+	    hashtable[i].unicode = u;
+	    hashtable[i].fontpos = get_fs_word(&list->fontpos);
+	    list++;
+	    ct--;
+	}
+	return 0;
+}
+
+int
+con_get_unimap(ushort ct, ushort *uct, struct unipair *list){
+	int i, ect;
+
+	ect = 0;
+	if (hashtable_contents_valid)
+	  for (i = 0; i<hashsize; i++)
+	    if (hashtable[i].unicode != 0xffff) {
+		if (ect++ < ct) {
+		    put_fs_word(hashtable[i].unicode, &list->unicode);
+		    put_fs_word(hashtable[i].fontpos, &list->fontpos);
+		    list++;
+		}
+	    }
+	put_fs_word(ect, uct);
+	return ((ect <= ct) ? 0 : -ENOMEM);
+}
+
+int
+conv_uni_to_pc(unsigned long ucs) {
+      int i, h;
+
+      if (!hashtable_contents_valid || ucs < 0x20)
+	return -3;
+      if (ucs == 0xffff || ucs == 0xfffe)
+	return -1;
+      if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
+	return -2;
+      
+      h = ucs % hashsize;
+      for (i = 0; i < hashlevel; i++) {
+	  if (hashtable[h].unicode == ucs)
+	    return hashtable[h].fontpos;
+	  if ((h += hashstep) >= hashsize)
+	    h -= hashsize;
+      }
+
+      return -4;		/* not found */
+}
diff -u --recursive --new-file v1.1.91/linux/drivers/char/consolemap.h linux/drivers/char/consolemap.h
--- v1.1.91/linux/drivers/char/consolemap.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/consolemap.h	Wed Feb 15 10:50:55 1995
@@ -0,0 +1,13 @@
+/*
+ * consolemap.h
+ *
+ * Interface between console.c, selection.c  and consolemap.c
+ */
+#define NORM_MAP 0
+#define GRAF_MAP 1
+#define NULL_MAP 2
+#define USER_MAP 3
+
+extern int hashtable_contents_valid;
+extern unsigned char inverse_translate(unsigned char c);
+extern unsigned char *set_translate(int m);
diff -u --recursive --new-file v1.1.91/linux/drivers/char/kbd_kern.h linux/drivers/char/kbd_kern.h
--- v1.1.91/linux/drivers/char/kbd_kern.h	Sun Feb  5 19:31:52 1995
+++ linux/drivers/char/kbd_kern.h	Wed Feb 15 10:50:55 1995
@@ -4,6 +4,8 @@
 #include <linux/interrupt.h>
 #include <linux/keyboard.h>
 
+extern int shift_state;
+
 extern char *func_table[MAX_NR_FUNC];
 extern char func_buf[];
 extern char *funcbufptr;
diff -u --recursive --new-file v1.1.91/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.91/linux/drivers/char/keyboard.c	Wed Feb 15 10:36:38 1995
+++ linux/drivers/char/keyboard.c	Wed Feb 15 10:50:55 1995
@@ -370,25 +370,29 @@
 		prev_scancode = 0;
 		goto end_kbd_intr;
 	}
+
+	tty = ttytab[fg_console];
+ 	kbd = kbd_table + fg_console;
+	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
+		   values when finishing RAW mode or when changing VT's */
+ 	}
+
 	if (scancode == 0xff) {
+	        /* in scancode mode 1, my ESC key generates 0xff */
 		/* the calculator keys on a FOCUS 9000 generate 0xff */
 #ifndef KBD_IS_FOCUS_9000
 #ifdef KBD_REPORT_ERR
-		printk("keyboard error\n");
+		if (!raw_mode)
+		  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 = (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
-		   values when finishing RAW mode or when changing VT's */
- 	}
 	if (scancode == 0xe0 || scancode == 0xe1) {
 		prev_scancode = scancode;
 		goto end_kbd_intr;
@@ -414,7 +418,8 @@
 		  prev_scancode = 0;
 	      } else {
 #ifdef KBD_REPORT_UNKN
-		  printk("keyboard: unknown e1 escape sequence\n");
+		  if (!raw_mode)
+		    printk("keyboard: unknown e1 escape sequence\n");
 #endif
 		  prev_scancode = 0;
 		  goto end_kbd_intr;
@@ -729,7 +734,7 @@
 	 * work.
 	 */
 	reset_vc(fg_console);
-	unblank_screen();	/* not in interrupt routine? */
+	do_unblank_screen();	/* not in interrupt routine? */
 #endif
 }
 
diff -u --recursive --new-file v1.1.91/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v1.1.91/linux/drivers/char/selection.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/selection.c	Wed Feb 15 10:50:55 1995
@@ -0,0 +1,291 @@
+/*
+ * linux/drivers/char/selection.c
+ *
+ * This module exports the functions:
+ *
+ *     'int set_selection(const int arg)'
+ *     'void clear_selection(void)'
+ *     'int paste_selection(struct tty_struct *tty)'
+ *     'int sel_loadlut(const int arg)'
+ *
+ * Now that /dev/vcs exists, most of this can disappear again.
+ */
+
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include "vt_kern.h"
+#include "consolemap.h"
+#include "selection.h"
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
+#define isspace(c)	((c) == ' ')
+
+/* Variables for selection control. */
+/* Use a dynamic buffer, instead of static (Dec 1994) */
+       int sel_cons = 0;		/* must not be disallocated */
+static volatile int sel_start = -1; 	/* cleared by clear_selection */
+static int sel_end;
+static int sel_buffer_lth = 0;
+static char *sel_buffer = NULL;
+
+#define sel_pos(n)	inverse_translate(screen_word(sel_cons, n, 1) & 0xff)
+
+/* clear_selection, highlight and highlight_pointer can be called
+   from interrupt (via scrollback/front) */
+
+/* set reverse video on characters s-e of console with selection. */
+inline static void
+highlight(const int s, const int e) {
+	invert_screen(sel_cons, s, e-s+2, 1);
+}
+
+/* use complementary color to show the pointer */
+inline static void
+highlight_pointer(const int where) {
+	complement_pos(sel_cons, where);
+}
+
+/* remove the current selection highlight, if any,
+   from the console holding the selection. */
+void
+clear_selection(void) {
+	highlight_pointer(-1); /* hide the pointer */
+	if (sel_start != -1) {
+		highlight(sel_start, sel_end);
+		sel_start = -1;
+	}
+}
+
+/*
+ * User settable table: what characters are to be considered alphabetic?
+ * 256 bits
+ */
+static unsigned long inwordLut[8]={
+  0x00000000, /* control chars     */
+  0x03FF0000, /* digits            */
+  0x87FFFFFE, /* uppercase and '_' */
+  0x07FFFFFE, /* lowercase         */
+  0x00000000,
+  0x00000000,
+  0xFF7FFFFF, /* latin-1 accented letters, not multiplication sign */
+  0xFF7FFFFF  /* latin-1 accented letters, not division sign */
+};
+
+static inline int inword(const unsigned char c) {
+	return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+}
+
+/* set inwordLut contents. Invoked by ioctl(). */
+int sel_loadlut(const int arg)
+{
+	int i = verify_area(VERIFY_READ, (char *) arg, 36);
+	if (i)
+		return i;
+	memcpy_fromfs(inwordLut, (unsigned long *)(arg+4), 32);
+	return 0;
+}
+
+/* does screen address p correspond to character at LH/RH edge of screen? */
+static inline int atedge(const int p)
+{
+	return (!(p % video_size_row) || !((p + 2) % video_size_row));
+}
+
+/* constrain v such that v <= u */
+static inline unsigned short limit(const unsigned short v, const unsigned short u)
+{
+/* gcc miscompiles the ?: operator, so don't use it.. */
+	if (v > u)
+		return u;
+	return v;
+}
+
+/* set the current selection. Invoked by ioctl(). */
+int set_selection(const int arg, struct tty_struct *tty)
+{
+	int sel_mode, new_sel_start, new_sel_end, spc;
+	char *bp, *obp;
+	int i, ps, pe;
+
+	do_unblank_screen();
+
+	{ unsigned short *args, xs, ys, xe, ye;
+
+	  args = (unsigned short *)(arg + 1);
+	  xs = get_fs_word(args++) - 1;
+	  ys = get_fs_word(args++) - 1;
+	  xe = get_fs_word(args++) - 1;
+	  ye = get_fs_word(args++) - 1;
+	  sel_mode = get_fs_word(args);
+
+	  xs = limit(xs, video_num_columns - 1);
+	  ys = limit(ys, video_num_lines - 1);
+	  xe = limit(xe, video_num_columns - 1);
+	  ye = limit(ye, video_num_lines - 1);
+	  ps = ys * video_size_row + (xs << 1);
+	  pe = ye * video_size_row + (xe << 1);
+
+	  if (sel_mode == 4) {
+	      /* useful for screendump without selection highlights */
+	      clear_selection();
+	      return 0;
+	  }
+
+	  if (mouse_reporting() && (sel_mode & 16)) {
+	      mouse_report(tty, sel_mode & 15, xs, ys);
+	      return 0;
+	  }
+        }
+
+	if (ps > pe)	/* make sel_start <= sel_end */
+	{
+		int tmp = ps;
+		ps = pe;
+		pe = tmp;
+	}
+
+	if (sel_cons != fg_console) {
+		clear_selection();
+		sel_cons = fg_console;
+	}
+
+	switch (sel_mode)
+	{
+		case 0:	/* character-by-character selection */
+			new_sel_start = ps;
+			new_sel_end = pe;
+			break;
+		case 1:	/* word-by-word selection */
+			spc = isspace(sel_pos(ps));
+			for (new_sel_start = ps; ; ps -= 2)
+			{
+				if ((spc && !isspace(sel_pos(ps))) ||
+				    (!spc && !inword(sel_pos(ps))))
+					break;
+				new_sel_start = ps;
+				if (!(ps % video_size_row))
+					break;
+			}
+			spc = isspace(sel_pos(pe));
+			for (new_sel_end = pe; ; pe += 2)
+			{
+				if ((spc && !isspace(sel_pos(pe))) ||
+				    (!spc && !inword(sel_pos(pe))))
+					break;
+				new_sel_end = pe;
+				if (!((pe + 2) % video_size_row))
+					break;
+			}
+			break;
+		case 2:	/* line-by-line selection */
+			new_sel_start = ps - ps % video_size_row;
+			new_sel_end = pe + video_size_row
+				    - pe % video_size_row - 2;
+			break;
+		case 3:
+			highlight_pointer(pe);
+			return 0;
+		default:
+			return -EINVAL;
+	}
+
+	/* remove the pointer */
+	highlight_pointer(-1);
+
+	/* select to end of line if on trailing space */
+	if (new_sel_end > new_sel_start &&
+		!atedge(new_sel_end) && isspace(sel_pos(new_sel_end))) {
+		for (pe = new_sel_end + 2; ; pe += 2)
+			if (!isspace(sel_pos(pe)) || atedge(pe))
+				break;
+		if (isspace(sel_pos(pe)))
+			new_sel_end = pe;
+	}
+	if (sel_start == -1)	/* no current selection */
+		highlight(new_sel_start, new_sel_end);
+	else if (new_sel_start == sel_start)
+	{
+		if (new_sel_end == sel_end)	/* no action required */
+			return 0;
+		else if (new_sel_end > sel_end)	/* extend to right */
+			highlight(sel_end + 2, new_sel_end);
+		else				/* contract from right */
+			highlight(new_sel_end + 2, sel_end);
+	}
+	else if (new_sel_end == sel_end)
+	{
+		if (new_sel_start < sel_start)	/* extend to left */
+			highlight(new_sel_start, sel_start - 2);
+		else				/* contract from left */
+			highlight(sel_start, new_sel_start - 2);
+	}
+	else	/* some other case; start selection from scratch */
+	{
+		clear_selection();
+		highlight(new_sel_start, new_sel_end);
+	}
+	sel_start = new_sel_start;
+	sel_end = new_sel_end;
+
+	if (sel_buffer)
+		kfree(sel_buffer);
+	sel_buffer = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
+	if (!sel_buffer) {
+		printk("selection: kmalloc() failed\n");
+		clear_selection();
+		return -ENOMEM;
+	}
+
+	obp = bp = sel_buffer;
+	for (i = sel_start; i <= sel_end; i += 2) {
+		*bp = sel_pos(i);
+		if (!isspace(*bp++))
+			obp = bp;
+		if (! ((i + 2) % video_size_row)) {
+			/* strip trailing blanks from line and add newline,
+			   unless non-space at end of line. */
+			if (obp != bp) {
+				bp = obp;
+				*bp++ = '\r';
+			}
+			obp = bp;
+		}
+	}
+	sel_buffer_lth = bp - sel_buffer;
+	return 0;
+}
+
+/* Insert the contents of the selection buffer into the queue of the
+   tty associated with the current console. Invoked by ioctl(). */
+int paste_selection(struct tty_struct *tty)
+{
+	struct wait_queue wait = { current, NULL };
+	char	*bp = sel_buffer;
+	int	c = sel_buffer_lth;
+	int	l;
+	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
+	
+	if (!bp || !c)
+		return 0;
+	do_unblank_screen();
+	current->state = TASK_INTERRUPTIBLE;
+	add_wait_queue(&vt->paste_wait, &wait);
+	while (c) {
+		if (test_bit(TTY_THROTTLED, &tty->flags)) {
+			schedule();
+			continue;
+		}
+		l = MIN(c, tty->ldisc.receive_room(tty));
+		tty->ldisc.receive_buf(tty, bp, 0, l);
+		c -= l;
+		bp += l;
+	}
+	current->state = TASK_RUNNING;
+	return 0;
+}
diff -u --recursive --new-file v1.1.91/linux/drivers/char/selection.h linux/drivers/char/selection.h
--- v1.1.91/linux/drivers/char/selection.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/selection.h	Wed Feb 15 10:50:55 1995
@@ -0,0 +1,64 @@
+/*
+ * selection.h
+ *
+ * Interface between console.c, tty_io.c, vt.c, vc_screen.c and selection.c
+ */
+extern int sel_cons;
+
+extern void clear_selection(void);
+extern int set_selection(const int arg, struct tty_struct *tty);
+extern int paste_selection(struct tty_struct *tty);
+extern int sel_loadlut(const int arg);
+extern int mouse_reporting(void);
+extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry);
+
+extern unsigned long video_num_columns;
+extern unsigned long video_num_lines;
+extern unsigned long video_size_row;
+
+extern void do_unblank_screen(void);
+extern unsigned short *screen_pos(int currcons, int w_offset, int viewed);
+extern unsigned short screen_word(int currcons, int offset, int viewed);
+extern void complement_pos(int currcons, int offset);
+extern void invert_screen(int currcons, int offset, int count, int shift);
+
+#define reverse_video_char(a)	(((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77))
+#define reverse_video_short(a)	(((a) & 0x88ff) | \
+	(((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4))
+/* this latter line used to have masks 0xf000 and 0x0f00, but selection
+   requires a self-inverse operation; moreover, the old version looks wrong */
+
+extern void getconsxy(int currcons, char *p);
+extern void putconsxy(int currcons, char *p);
+
+/* how to access screen memory */
+#ifdef __alpha__
+ 
+static inline void scr_writew(unsigned short val, unsigned short * addr)
+{
+	if ((long) addr < 0)
+		*addr = val;
+	else
+		writew(val, (unsigned long) addr);
+}
+
+static inline unsigned short scr_readw(unsigned short * addr)
+{
+	if ((long) addr < 0)
+		return *addr;
+	return readw((unsigned long) addr);
+}
+
+#else
+
+static inline void scr_writew(unsigned short val, unsigned short * addr)
+{
+	*addr = val;
+}
+
+static inline unsigned short scr_readw(unsigned short * addr)
+{
+	return *addr;
+}
+
+#endif
diff -u --recursive --new-file v1.1.91/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v1.1.91/linux/drivers/char/tty_io.c	Sun Feb  5 19:31:52 1995
+++ linux/drivers/char/tty_io.c	Wed Feb 15 10:50:55 1995
@@ -60,6 +60,7 @@
 
 #include "kbd_kern.h"
 #include "vt_kern.h"
+#include "selection.h"
 
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
 #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
@@ -69,14 +70,6 @@
 #define TTY_PARANOIA_CHECK
 #define CHECK_TTY_COUNT
 
-#ifdef CONFIG_SELECTION
-extern int set_selection(const int arg, struct tty_struct *tty);
-extern int paste_selection(struct tty_struct *tty);
-extern int sel_loadlut(const int arg);
-extern int mouse_reporting(void);
-extern int shift_state;
-#endif /* CONFIG_SELECTION */
-extern int do_screendump(unsigned long arg, int mode);
 extern void do_blank_screen(int nopowersave);
 extern void do_unblank_screen(void);
 extern void set_vesa_blanking(const unsigned long arg);
@@ -1247,6 +1240,7 @@
 	return 0;	
 }
 
+#if 0
 /*
  * XXX does anyone use this anymore?!?
  */
@@ -1278,6 +1272,7 @@
 			put_fs_long(0, (unsigned long *)(ts->present+n));
 	return(0);			
 }
+#endif
 
 static int tty_ioctl(struct inode * inode, struct file * file,
 		     unsigned int cmd, unsigned long arg)
@@ -1452,21 +1447,23 @@
 				return retval;
 			switch (retval = get_fs_byte((char *)arg))
 			{
-				case 0: 
-					return do_screendump(arg,0);
+				case 0:
+				case 8:
+				case 9:
+					printk("TIOCLINUX (0/8/9) ioctl is gone - use /dev/vcs\n");
+					return -EINVAL;
+#if 0
 				case 1:
 					printk("Deprecated TIOCLINUX (1) ioctl\n");
 					return do_get_ps_info(arg);
-#ifdef CONFIG_SELECTION
+#endif
 				case 2:
 					return set_selection(arg, tty);
 				case 3:
 					return paste_selection(tty);
-#endif /* CONFIG_SELECTION */
 				case 4:
 					do_unblank_screen();
 					return 0;
-#ifdef CONFIG_SELECTION
 				case 5:
 					return sel_loadlut(arg);
 				case 6:
@@ -1481,16 +1478,13 @@
 				case 7:
 					put_fs_byte(mouse_reporting(),arg);
 					return 0;
-#endif /* CONFIG_SELECTION */
-				case 8: /* second arg is 1 or 2 */
-				case 9: /* both are explained in console.c */
-					return do_screendump(arg,retval-7);
 				case 10:
 					set_vesa_blanking(arg);
 					return 0;
 				default: 
 					return -EINVAL;
 			}
+
 		case TIOCTTYGSTRUCT:
 			retval = verify_area(VERIFY_WRITE, (void *) arg,
 						sizeof(struct tty_struct));
@@ -1742,5 +1736,6 @@
 	kmem_start = cy_init(kmem_start);
 #endif
 	kmem_start = pty_init(kmem_start);
+	kmem_start = vcs_init(kmem_start);
 	return kmem_start;
 }
diff -u --recursive --new-file v1.1.91/linux/drivers/char/uni_to_437.c linux/drivers/char/uni_to_437.c
--- v1.1.91/linux/drivers/char/uni_to_437.c	Thu Oct 13 14:07:08 1994
+++ linux/drivers/char/uni_to_437.c	Thu Jan  1 02:00:00 1970
@@ -1,169 +0,0 @@
-/*
- * 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.91/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v1.1.91/linux/drivers/char/vc_screen.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/vc_screen.c	Wed Feb 15 10:50:55 1995
@@ -0,0 +1,212 @@
+/*
+ * linux/drivers/char/vc_screen.c
+ *
+ * Provide access to virtual console memory.
+ * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
+ * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
+ *            [minor: N]
+ *
+ * /dev/vcsaN: idem, but including attributes, and prefixed with
+ *	the 4 bytes lines,columns,x,y (as screendump used to give)
+ *            [minor: N+128]
+ *
+ * This replaces screendump and part of selection, so that the system
+ * administrator can control access using file system permissions.
+ *
+ * aeb@cwi.nl - efter Friedas begravelse - 950211
+ */
+
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/fs.h>
+#include <asm/segment.h>
+#include "vt_kern.h"
+#include "selection.h"
+
+#define HEADER_SIZE	4
+
+static inline int
+vcs_size(struct inode *inode)
+{
+	int size = video_num_lines * video_num_columns;
+	if (MINOR(inode->i_rdev) & 128)
+		size = 2*size + HEADER_SIZE;
+	return size;
+}
+
+static int
+vcs_lseek(struct inode *inode, struct file *file, off_t offset, int orig)
+{
+	int size = vcs_size(inode);
+
+	switch (orig) {
+		case 0:
+			file->f_pos = offset;
+			break;
+		case 1:
+			file->f_pos += offset;
+			break;
+		case 2:
+			file->f_pos = size + offset;
+			break;
+		default:
+			return -EINVAL;
+	}
+	if (file->f_pos < 0 || file->f_pos > size)
+		return -EINVAL;
+	return file->f_pos;
+}
+
+static int
+vcs_read(struct inode *inode, struct file *file, char *buf, int count)
+{
+	unsigned long p = file->f_pos;
+	unsigned int cons = MINOR(inode->i_rdev);
+	int viewed, attr, size, read;
+	char *buf0;
+	unsigned short *org;
+
+	attr = (cons & 128);
+	cons = (cons & 127);
+	if (cons == 0) {
+		cons = fg_console;
+		viewed = 1;
+	} else {
+		cons--;
+		viewed = 0;
+	}
+	if (!vc_cons_allocated(cons))
+		return -ENXIO;
+
+	size = vcs_size(inode);
+	if (count < 0 || p > size)
+		return -EINVAL;
+	if (count > size - p)
+		count = size - p;
+
+	buf0 = buf;
+	if (!attr) {
+		org = screen_pos(cons, p, viewed);
+		while (count-- > 0)
+			put_fs_byte(scr_readw(org++) & 0xff, buf++);
+	} else {
+		if (p < HEADER_SIZE) {
+			char header[HEADER_SIZE];
+			header[0] = (char) video_num_lines;
+			header[1] = (char) video_num_columns;
+			getconsxy(cons, header+2);
+			while (p < HEADER_SIZE && count-- > 0)
+			    put_fs_byte(header[p++], buf++);
+		}
+		p -= HEADER_SIZE;
+		org = screen_pos(cons, p/2, viewed);
+		if ((p & 1) && count-- > 0)
+			put_fs_byte(scr_readw(org++) >> 8, buf++);
+		while (count > 1) {
+			put_fs_word(scr_readw(org++), buf);
+			buf += 2;
+			count -= 2;
+		}
+		if (count > 0)
+			put_fs_byte(scr_readw(org) & 0xff, buf++);
+	}
+	read = buf - buf0;
+	file->f_pos += read;
+	return read;
+}
+
+static int
+vcs_write(struct inode *inode, struct file *file, char *buf, int count)
+{
+	unsigned long p = file->f_pos;
+	unsigned int cons = MINOR(inode->i_rdev);
+	int viewed, attr, size, written;
+	char *buf0;
+	unsigned short *org;
+
+	attr = (cons & 128);
+	cons = (cons & 127);
+	if (cons == 0) {
+		cons = fg_console;
+		viewed = 1;
+	} else {
+		cons--;
+		viewed = 0;
+	}
+	if (!vc_cons_allocated(cons))
+		return -ENXIO;
+
+	size = vcs_size(inode);
+	if (count < 0 || p > size)
+		return -EINVAL;
+	if (count > size - p)
+		count = size - p;
+
+	buf0 = buf;
+	if (!attr) {
+		org = screen_pos(cons, p, viewed);
+		while (count-- > 0) {
+			scr_writew((scr_readw(org) & 0xff00) |
+				get_fs_byte(buf++), org);
+			org++;
+		}
+	} else {
+		if (p < HEADER_SIZE) {
+			char header[HEADER_SIZE];
+			getconsxy(cons, header+2);
+			while (p < HEADER_SIZE && count-- > 0)
+				header[p++] = get_fs_byte(buf++);
+			if (!viewed)
+				putconsxy(cons, header+2);
+		}
+		p -= HEADER_SIZE;
+		org = screen_pos(cons, p/2, viewed);
+		if ((p & 1) && count-- > 0) {
+			scr_writew((get_fs_byte(buf++) << 8) |
+				   (scr_readw(org) & 0xff), org);
+			org++;
+		}
+		while (count > 1) {
+			scr_writew(get_fs_word(buf), org++);
+			buf += 2;
+			count -= 2;
+		}
+		if (count > 0)
+			scr_writew((scr_readw(org) & 0xff00) |
+				   get_fs_byte(buf++), org);
+	}
+	written = buf - buf0;
+	file->f_pos += written;
+	return written;
+}
+
+static int
+vcs_open(struct inode *inode, struct file *filp)
+{
+	unsigned int cons = (MINOR(inode->i_rdev) & 127);
+	if(cons && !vc_cons_allocated(cons-1))
+		return -ENXIO;
+	return 0;
+}
+
+static struct file_operations vcs_fops = {
+	vcs_lseek,	/* lseek */
+	vcs_read,	/* read */
+	vcs_write,	/* write */
+	NULL,		/* readdir */
+	NULL,		/* select */
+	NULL,		/* ioctl */
+	NULL,		/* mmap */
+	vcs_open,	/* open */
+	NULL,		/* release */
+	NULL		/* fsync */
+};
+
+long vcs_init(long kmem_start)
+{
+	if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
+		printk("unable to get major %d for vcs device", VCS_MAJOR);
+	return kmem_start;
+}
diff -u --recursive --new-file v1.1.91/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v1.1.91/linux/drivers/char/vt.c	Sun Jan 22 21:39:40 1995
+++ linux/drivers/char/vt.c	Wed Feb 15 10:50:55 1995
@@ -24,10 +24,13 @@
 #include "kbd_kern.h"
 #include "vt_kern.h"
 #include "diacr.h"
+#include "selection.h"
 
 extern struct tty_driver console_driver;
+extern int sel_cons;
 
 #define VT_IS_IN_USE(i)	(console_driver.table[i] && console_driver.table[i]->count)
+#define VT_BUSY(i)	(VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
 
 /*
  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
@@ -62,6 +65,9 @@
  */
 extern int con_set_trans(char * table);
 extern int con_get_trans(char * table);
+extern void con_clear_unimap(struct unimapinit *ui);
+extern int con_set_unimap(ushort ct, struct unipair *list);
+extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
 extern int con_set_font(char * fontmap);
 extern int con_get_font(char * fontmap);
 
@@ -792,12 +798,12 @@
 		if (arg == 0) {
 		    /* disallocate all unused consoles, but leave 0 */
 		    for (i=1; i<MAX_NR_CONSOLES; i++)
-		      if (! VT_IS_IN_USE(i) && i != fg_console)
+		      if (! VT_BUSY(i))
 			vc_disallocate(i);
 		} else {
 		    /* disallocate a single console, if possible */
 		    arg--;
-		    if (VT_IS_IN_USE(arg) || arg == fg_console)
+		    if (VT_BUSY(arg))
 		      return -EBUSY;
 		    if (arg)			      /* leave 0 */
 		      vc_disallocate(arg);
@@ -836,12 +842,61 @@
 		if (!perm)
 			return -EPERM;
 		return con_set_trans((char *)arg);
-		/* con_set_trans() defined in console.c */
 
 	case GIO_SCRNMAP:
 		return con_get_trans((char *)arg);
-		/* con_get_trans() defined in console.c */
 
+	case PIO_UNIMAPCLR:
+	      { struct unimapinit ui;
+		if (!perm)
+			return -EPERM;
+		i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
+		if (i)
+		  return i;
+		memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
+		con_clear_unimap(&ui);
+		return 0;
+	      }
+
+	case PIO_UNIMAP:
+	      { struct unimapdesc *ud;
+		u_short ct;
+		struct unipair *list;
+
+		if (!perm)
+			return -EPERM;
+		i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
+		if (i == 0) {
+		    ud = (struct unimapdesc *) arg;
+		    ct = get_fs_word(&ud->entry_ct);
+		    list = (struct unipair *) get_fs_long(&ud->entries);
+		    i = verify_area(VERIFY_READ, (void *) list,
+				    ct*sizeof(struct unipair));
+		}
+		if (i)
+		  return i;
+		return con_set_unimap(ct, list);
+	      }
+
+	case GIO_UNIMAP:
+	      { struct unimapdesc *ud;
+		u_short ct;
+		struct unipair *list;
+
+		i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
+		if (i == 0) {
+		    ud = (struct unimapdesc *) arg;
+		    ct = get_fs_word(&ud->entry_ct);
+		    list = (struct unipair *) get_fs_long(&ud->entries);
+		    if (ct)
+		      i = verify_area(VERIFY_WRITE, (void *) list,
+				      ct*sizeof(struct unipair));
+		}
+		if (i)
+		  return i;
+		return con_get_unimap(ct, &(ud->entry_ct), list);
+	      }
+ 
 	default:
 		return -ENOIOCTLCMD;
 	}
diff -u --recursive --new-file v1.1.91/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v1.1.91/linux/drivers/net/3c501.c	Thu Feb  9 10:18:51 1995
+++ linux/drivers/net/3c501.c	Wed Feb 15 10:50:33 1995
@@ -270,7 +270,7 @@
     if (autoirq)
 	dev->irq = autoirq;
 
-    printk("%s: %s EtherLink at %#x, using %sIRQ %d.\n",
+    printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
 	   dev->name, mname, dev->base_addr,
 	   autoirq ? "auto":"assigned ", dev->irq);
 	   
diff -u --recursive --new-file v1.1.91/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v1.1.91/linux/drivers/net/3c509.c	Thu Jan 26 07:49:05 1995
+++ linux/drivers/net/3c509.c	Wed Feb 15 10:50:49 1995
@@ -228,7 +228,7 @@
 
 	{
 		char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
-		printk("%s: 3c509 at %#3.3x tag %d, %s port, address ",
+		printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
 			   dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
 	}
 
diff -u --recursive --new-file v1.1.91/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v1.1.91/linux/drivers/net/ppp.c	Sun Feb  5 19:31:53 1995
+++ linux/drivers/net/ppp.c	Wed Feb 15 10:50:55 1995
@@ -1485,7 +1485,7 @@
     error = verify_area (VERIFY_WRITE, (void *) l, sizeof (temp_i));
     if (error == 0) {
       put_fs_long (ppp->dev->base_addr, l);
-      PRINTKN (3,(KERN_INFO "ppp_ioctl: get unit: %d", ppp->dev->base_addr));
+      PRINTKN (3,(KERN_INFO "ppp_ioctl: get unit: %ld", ppp->dev->base_addr));
     }
     break;
 
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v1.1.91/linux/drivers/scsi/eata.c	Wed Feb 15 10:36:39 1995
+++ linux/drivers/scsi/eata.c	Wed Feb 15 10:23:44 1995
@@ -1,6 +1,11 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      11 Feb 1995 rev. 1.17 for linux 1.1.91
+ *          Now DEBUG_RESET is disabled by default.
+ *          Register a board even if it does not assert DMA protocol support
+ *          (DPT SK2011B does not report correctly the dmasup bit).
+ *
  *       9 Feb 1995 rev. 1.16 for linux 1.1.90
  *          Use host->wish_block instead of host->block.
  *          New list of Data Out SCSI commands.
@@ -124,6 +129,7 @@
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
+#undef  DEBUG_RESET
 
 #define MAX_TARGET 8
 #define MAX_IRQ 16
@@ -390,9 +396,9 @@
 
    if (*port_base & EISA_RANGE) {
 
-      if (!info.haaval || info.ata || info.drqvld || !info.dmasup) {
-         printk("%s: unusable EISA board found (%d%d%d%d), detaching.\n", 
-                name, info.haaval, info.ata, info.drqvld, info.dmasup);
+      if (!info.haaval || info.ata || info.drqvld) {
+         printk("%s: unusable EISA board found (%d%d%d), detaching.\n", 
+                name, info.haaval, info.ata, info.drqvld);
          return FALSE;
          }
 
@@ -401,9 +407,9 @@
       }
    else {
 
-      if (!info.haaval || info.ata || !info.drqvld || !info.dmasup) {
-         printk("%s: unusable ISA board found (%d%d%d%d), detaching.\n",
-                name, info.haaval, info.ata, info.drqvld, info.dmasup);
+      if (!info.haaval || info.ata || !info.drqvld) {
+         printk("%s: unusable ISA board found (%d%d%d), detaching.\n",
+                name, info.haaval, info.ata, info.drqvld);
          return FALSE;
          }
 
@@ -411,6 +417,9 @@
       dma_channel = dma_channel_table[3 - info.drqx];
       }
 
+   if (!info.dmasup)
+      printk("%s: warning, DMA protocol support not asserted.\n", name);
+
    if (subversion == ESA && !info.irq_tr)
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
              name, irq);
@@ -799,7 +808,11 @@
       }
 
    printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));
+
+#if defined (DEBUG_RESET)
    do_trace = TRUE;
+#endif
+
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v1.1.91/linux/drivers/scsi/eata.h	Wed Feb 15 10:36:39 1995
+++ linux/drivers/scsi/eata.h	Wed Feb 15 10:23:49 1995
@@ -7,7 +7,7 @@
 
 #include <linux/scsicam.h>
 
-#define EATA_VERSION "1.16.00"
+#define EATA_VERSION "1.17.00"
 
 int eata2x_detect(Scsi_Host_Template *);
 int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v1.1.91/linux/drivers/scsi/eata_dma.c	Sun Feb  5 19:31:54 1995
+++ linux/drivers/scsi/eata_dma.c	Tue Feb 14 08:02:58 1995
@@ -44,10 +44,10 @@
  * Thanks also to Greg Hosler who did a lot of testing and  *
  * found quite a number of bugs during the development.     *
  ************************************************************
- *  last change: 95/01/30                                   *
+ *  last change: 95/02/13       OS: Linux 1.1.91 or higher  *
  ************************************************************/
 
-/* Look in eata_dma.h for configuration information */
+/* Look in eata_dma.h for configuration and revision information */
 
 #ifdef MODULE
 #include <linux/module.h>
@@ -63,12 +63,17 @@
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include "eata_dma.h"
+#include "../block/blk.h"
 #include "scsi.h"
 #include "sd.h"
+#include "hosts.h"
+#include <linux/scsicam.h>
+#include "eata_dma.h"
 
-#if 0
-#include "eata_dma_proc.c"
+#if EATA_DMA_PROC  
+#include "eata_dma_proc.h"  /* If you're interested send me a mail */ 
+ulong  reads[13];           /* /proc/scsi probably won't get       */ 
+ulong  writes[13];          /* into the kernel before pl. 1.3      */
 #endif
 
 static uint ISAbases[] =
@@ -85,7 +90,7 @@
 static struct eata_sp status[MAXIRQ];	/* Statuspacket array   */
 
 static uint internal_command_finished = TRUE;
-
+static unchar HBA_interpret = FALSE;
 static struct geom_emul geometry;	/* Drive 1 & 2 geometry */
 
 static ulong int_counter = 0;
@@ -96,6 +101,10 @@
     return;
 }	
 
+#if EATA_DMA_PROC 
+#include "eata_dma_proc.c"
+#endif
+
 int eata_release(struct Scsi_Host *sh)
 {
   if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
@@ -235,7 +244,10 @@
  
 	restore_flags(flags);
 	if(cmd->scsi_done != eata_scsi_done) cmd->scsi_done(cmd);
-	else internal_command_finished = TRUE;
+	else {
+	    internal_command_finished = TRUE;
+	    HBA_interpret = FALSE;
+	}
 	save_flags(flags);
 	cli();
     }
@@ -337,7 +349,7 @@
 	cp->DataIn = TRUE;	/* Input mode  */
     }
 
-    if (done == (void *) eata_scsi_done) 
+    if (done == (void *) eata_scsi_done && HBA_interpret == TRUE) 
         cp->Interpret = TRUE;   /* Interpret command */
    
     if (cmd->use_sg) {
@@ -699,7 +711,7 @@
 	return (FALSE);
     }
 
-    if(gc->HAA_valid == FALSE || ntohl(gc->len) == 0x1c || ntohl(gc->len) == 0x1e) 
+    if(gc->HAA_valid == FALSE || ntohl(gc->len) <= 0x1e) 
         gc->MAX_CHAN = 0;
 
     if(strncmp("PM2322", &buff[16], 6) && strncmp("PM3021", &buff[16], 6)
@@ -746,7 +758,6 @@
 		   "This might be a PM2012 with a defective Firmware\n");
     }
 
-    
     size = sizeof(hostdata) + ((sizeof(struct eata_ccb) * ntohs(gc->queuesiz))/
 			       (gc->MAX_CHAN + 1));
 
@@ -824,11 +835,14 @@
 	else
 	    hd->primary = TRUE;
 
-	if (hd->bustype != 'I')
+	if (hd->bustype != 'I') {
 	    sh->unchecked_isa_dma = FALSE;
-	else
+	    sh->wish_block = FALSE;        
+	}
+	else {
 	    sh->unchecked_isa_dma = TRUE;   /* We're doing ISA DMA */
-
+	    sh->wish_block = TRUE;          /* This will reduce performance */
+	}
 	if((hd->primary == TRUE) && (i == 0) && HARDCODED){                  
 	  geometry.drv[0].heads = HEADS0;          
 	  geometry.drv[0].sectors = SECTORS0;      
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/eata_dma.h linux/drivers/scsi/eata_dma.h
--- v1.1.91/linux/drivers/scsi/eata_dma.h	Thu Feb  9 10:18:52 1995
+++ linux/drivers/scsi/eata_dma.h	Tue Feb 14 08:02:58 1995
@@ -2,21 +2,16 @@
 * Header file for eata_dma.c Linux EATA-DMA SCSI driver *
 * (c) 1993,94,95 Michael Neuffer                        *
 *********************************************************
-* last change: 95/01/30                                 *
+* last change: 95/02/13                                 *
 ********************************************************/
 
 
 #ifndef _EATA_DMA_H
 #define _EATA_DMA_H
 
-#include "../block/blk.h"
-#include "scsi.h"
-#include "hosts.h"
-#include <linux/scsicam.h>
-
 #define VER_MAJOR 2
 #define VER_MINOR 3
-#define VER_SUB   "0a"
+#define VER_SUB   "1a"
 
 /************************************************************************
  * Here you can configure your drives that are using a non-standard     *
@@ -44,6 +39,7 @@
  ************************************************************************/
 
 #define CHECKPAL        0        /* EISA pal checking on/off            */
+#define EATA_DMA_PROC   0        /* proc-fs support                     */
 
 /************************************************************************
  * Debug options.                                                       * 
@@ -132,19 +128,22 @@
 #define C_P_L_CURRENT_MAX 10  /* Until this limit in the mm is removed    
 			       * Kernels < 1.1.86 died horrible deaths
 			       * if you used values >2. The memory management
-			       * of pl.86 seems to cope with 10. 
+			       * since pl1.1.86 seems to cope with up to 10
+			       * queued commands per device. 
 			       */
 #define C_P_L_DIV          4  /* 1 <= C_P_L_DIV <= 8            
 			       * You can use this parameter to fine-tune
 			       * the driver. Depending on the number of 
-			       * devices and their ability to queue commands
-			       * you will get the best results with a value
+			       * devices and their speed and ability to queue 
+			       * commands, you will get the best results with a
+			       * value
 			       * ~= numdevices-(devices_unable_to_queue_commands/2)
-			       * The reason for this is that the disk driver tents 
-			       * to flood the queue, so that other drivers have 
-			       * problems to queue commands themselves. This can 
-			       * for example result in the effect that the tape
-			       * stops during disk accesses. 
+			       * The reason for this is that the disk driver 
+			       * tends to flood the queue, so that other 
+			       * drivers have problems to queue commands 
+			       * themselves. This can for example result in 
+			       * the effect that the tape stops during disk 
+			       * accesses. 
 			       */
 
 #define FREE       0
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v1.1.91/linux/drivers/scsi/hosts.c	Wed Feb 15 10:36:39 1995
+++ linux/drivers/scsi/hosts.c	Tue Feb 14 08:06:50 1995
@@ -216,9 +216,6 @@
 void
 scsi_unregister(struct Scsi_Host * sh){
 	struct Scsi_Host * shpnt;
-	int j;
-
-	j = sh->extra_bytes;
 
 	if(scsi_hostlist == sh)
 		scsi_hostlist = sh->next;
@@ -227,8 +224,14 @@
 		while(shpnt->next != sh) shpnt = shpnt->next;
 		shpnt->next = shpnt->next->next;
 	};
+
+        /* If we are removing the last host registered, it is safe to reuse
+           its host number (this avoids "holes" at boot time) (DB) */
+        if (max_scsi_hosts == next_scsi_host && !scsi_loadable_module_flag)
+           max_scsi_hosts--;
+
 	next_scsi_host--;
-	scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + j);
+	scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + sh->extra_bytes);
 }
 
 /* We call this when we come across a new host adapter. We only do this
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.1.91/linux/drivers/scsi/scsi.c	Wed Feb 15 10:36:39 1995
+++ linux/drivers/scsi/scsi.c	Tue Feb 14 08:06:50 1995
@@ -307,12 +307,15 @@
   struct Scsi_Device_Template * sdtpnt;
   Scsi_Cmnd  SCmd;
 
+  memset(&SCmd, 0,  sizeof(SCmd));
   ++in_scan_scsis;
   lun = 0;
   type = -1;
   SCmd.next = NULL;
   SCmd.prev = NULL;
   SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), GFP_ATOMIC);
+  SCmd.device = SDpnt;  /* This was really needed! (DB) */
+  memset(SDpnt, 0, sizeof(Scsi_Device));
   SDtail = scsi_devices;
   if(scsi_devices) {
     while(SDtail->next) SDtail = SDtail->next;
@@ -1913,36 +1916,51 @@
    pool */
 
 static unsigned long scsi_init_memory_start = 0;
+static unsigned long scsi_memory_lower_value = 0;
+static unsigned long scsi_memory_upper_value = 0;
 int scsi_loadable_module_flag; /* Set after we scan builtin drivers */
 
 void * scsi_init_malloc(unsigned int size, int priority)
 {
   unsigned long retval;
-  if(scsi_loadable_module_flag) {
+#if 0 /* Use the statically allocated memory instead of kmalloc  (DB) */
+  if(scsi_loadable_module_flag && !(priority & GFP_DMA))
+#else
+  if(scsi_loadable_module_flag)
+#endif
     retval = (unsigned long) kmalloc(size, priority);
-  } else {
+  else {
     /*
      * Keep all memory aligned on 16-byte boundaries. Some host adaptors
      * (e.g. BusLogic BT-445S) require DMA buffers to be aligned that way.
      */
     size = (size + 15) & ~15;
-    retval = scsi_init_memory_start;
-    scsi_init_memory_start += size;
-  }
+
+    if(scsi_loadable_module_flag &&
+       (scsi_init_memory_start + size) > scsi_memory_upper_value) {
+       retval = 0;
+       printk("scsi_init_malloc: no more statically allocated memory.\n");
+       }
+    else {
+       retval = scsi_init_memory_start;
+       scsi_init_memory_start += size;
+       }
+    }
   return (void *) retval;
 }
 
 
 void scsi_init_free(char * ptr, unsigned int size)
-{ /* FIXME - not right.  We need to compare addresses to see whether this was
-     kmalloc'd or not */
-  if((unsigned long) ptr > scsi_init_memory_start) {
-    kfree(ptr);
-  } else {
-    size = (size + 15) & ~15; /* Use the same alignment as scsi_init_malloc(). */
+{ /* We need to compare addresses to see whether this was kmalloc'd or not */
+
+  if((unsigned long) ptr >= scsi_init_memory_start ||
+     (unsigned long) ptr <  scsi_memory_lower_value) kfree(ptr);
+  else {
+    size = (size + 15) & ~15; /* Use the same alignment as scsi_init_malloc() */
+
     if(((unsigned long) ptr) + size == scsi_init_memory_start)
       scsi_init_memory_start = (unsigned long) ptr;
-  }
+    }
 }
 
 /*
@@ -1967,6 +1985,7 @@
 	scsi_loadable_module_flag = 0;
 	/* Align everything on 16-byte boundaries. */
 	scsi_init_memory_start = (memory_start + 15) & ~ 15;
+	scsi_memory_lower_value = scsi_init_memory_start;
 
 	timer_table[SCSI_TIMER].fn = scsi_main_timeout;
 	timer_table[SCSI_TIMER].expires = 0;
@@ -2068,7 +2087,20 @@
 	    (*sdtpnt->finish)();
 
 	scsi_loadable_module_flag = 1;
+
+#if 0   /* This allocates statically some extra memory to be used for modules,
+           until the kmalloc problem is fixed (DB) */
+
+        scsi_memory_upper_value = scsi_init_memory_start + 
+                     2 * (scsi_init_memory_start - scsi_memory_lower_value);
+
+        printk ("scsi memory: lower %p, upper %p.\n", 
+             (void *)scsi_memory_lower_value, (void *)scsi_memory_upper_value);
+
+	return scsi_memory_upper_value;
+#else
 	return scsi_init_memory_start;
+#endif
 	}
 
 static void print_inquiry(unsigned char *data)
@@ -2292,7 +2324,8 @@
      commands */
 
   for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt->next)
-    if(sdpnt->host->hostt == tpnt && *sdpnt->host->hostt->usage_count) return;
+    if(sdpnt->host->hostt == tpnt && sdpnt->host->hostt->usage_count
+                                 && *sdpnt->host->hostt->usage_count) return;
 
   for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next)
     {
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v1.1.91/linux/drivers/scsi/sr_ioctl.c	Thu Feb  9 10:18:52 1995
+++ linux/drivers/scsi/sr_ioctl.c	Wed Feb 15 10:51:05 1995
@@ -15,7 +15,8 @@
 
 #define IOCTL_RETRIES 3
 /* The CDROM is fairly slow, so we need a little extra time */
-#define IOCTL_TIMEOUT 2000
+/* In fact, it is very slow if it has to spin up first */
+#define IOCTL_TIMEOUT 3000
 
 extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v1.1.91/linux/drivers/scsi/st.c	Sun Feb  5 19:31:54 1995
+++ linux/drivers/scsi/st.c	Wed Feb 15 10:23:32 1995
@@ -54,7 +54,7 @@
 
 #define ST_BLOCK_SIZE 1024
 
-#define ST_MAX_BUFFERS 2
+#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
 
 #define ST_BUFFER_BLOCKS 32
 
@@ -1948,7 +1948,7 @@
   }
 
   /* Allocate the buffers */
-  st_nbr_buffers = st_template.dev_noticed;
+  st_nbr_buffers = st_template.dev_noticed + ST_EXTRA_DEVS;
   if (st_nbr_buffers > st_max_buffers)
     st_nbr_buffers = st_max_buffers;
   st_buffers = (ST_buffer **) scsi_init_malloc(st_nbr_buffers * 
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v1.1.91/linux/drivers/scsi/u14-34f.c	Wed Feb 15 10:36:39 1995
+++ linux/drivers/scsi/u14-34f.c	Tue Feb 14 08:06:50 1995
@@ -1,6 +1,10 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      11 Feb 1995 rev. 1.17 for linux 1.1.91
+ *          U14F qualified to run with 32 sglists.
+ *          Now DEBUG_RESET is disabled by default.
+ *
  *       9 Feb 1995 rev. 1.16 for linux 1.1.90
  *          Use host->wish_block instead of host->block.
  *
@@ -69,8 +73,8 @@
  *
  *  Here a sample configuration using two U14F boards:
  *
- U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 16, Mbox 16, CmdLun 2, C1.
- U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 16, Mbox 16, CmdLun 2, C1.
+ U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, Mbox 16, CmdLun 2, C1.
+ U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, Mbox 16, CmdLun 2, C1.
  *
  *  The boot controller must have its BIOS enabled, while other boards can
  *  have their BIOS disabled, or enabled to an higher address.
@@ -159,12 +163,14 @@
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
+#undef  DEBUG_RESET
 
 #define MAX_TARGET 8
 #define MAX_IRQ 16
 #define MAX_BOARDS 4
 #define MAX_MAILBOXES 16
-#define MAX_SGLIST 16
+#define MAX_SGLIST 32
+#define MAX_SAFE_SGLIST 16
 #define MAX_CMD_PER_LUN 2
 
 #define FALSE 0
@@ -427,7 +433,6 @@
    if (HD(j)->subversion == ESA) {
       sh[j]->dma_channel = NO_DMA;
       sh[j]->unchecked_isa_dma = FALSE;
-      sh[j]->hostt->use_clustering = ENABLE_CLUSTERING;
       sprintf(BN(j), "U34F%d", j);
       }
    else {
@@ -435,8 +440,7 @@
 
 #if defined (HAVE_OLD_U14F_FIRMWARE)
       sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
-#else
-      sh[j]->hostt->use_clustering = ENABLE_CLUSTERING;
+      sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
 #endif
 
       sh[j]->dma_channel = dma_channel;
@@ -456,6 +460,7 @@
          printk("%s: firmware %s is outdated, BIOS rev. should be 2.01.\n", 
                 BN(j), &HD(j)->board_id[32]);
          sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+         sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
          }
       }
 
@@ -737,7 +742,11 @@
 
    outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR);
    printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));
+
+#if defined (DEBUG_RESET)
    do_trace = TRUE;
+#endif
+
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
diff -u --recursive --new-file v1.1.91/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v1.1.91/linux/drivers/scsi/u14-34f.h	Wed Feb 15 10:36:39 1995
+++ linux/drivers/scsi/u14-34f.h	Tue Feb 14 08:06:50 1995
@@ -10,7 +10,7 @@
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, int, int *);
 
-#define U14_34F_VERSION "1.16.00"
+#define U14_34F_VERSION "1.17.00"
 
 #define ULTRASTOR_14_34F {                                            \
                 NULL, /* Ptr for modules */                           \
@@ -31,6 +31,6 @@
                 0,   /* cmd_per_lun, reset by detect */               \
 		0,   /* number of boards present */                   \
                 1,   /* unchecked isa dma, reset by detect */         \
-                0,   /* use_clustering, reset by detect */            \
+                ENABLE_CLUSTERING                                     \
                 }
 #endif
diff -u --recursive --new-file v1.1.91/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v1.1.91/linux/fs/binfmt_elf.c	Wed Feb  1 09:23:06 1995
+++ linux/fs/binfmt_elf.c	Wed Feb 15 10:51:06 1995
@@ -38,7 +38,7 @@
 #include <linux/config.h>
 
 #include <linux/unistd.h>
-typedef int (*sysfun_p)();
+typedef int (*sysfun_p)(int);
 extern sysfun_p sys_call_table[];
 #define SYS(name)	(sys_call_table[__NR_##name])
 
diff -u --recursive --new-file v1.1.91/linux/fs/locks.c linux/fs/locks.c
--- v1.1.91/linux/fs/locks.c	Wed Nov 30 10:01:43 1994
+++ linux/fs/locks.c	Wed Feb 15 09:31:55 1995
@@ -15,6 +15,15 @@
  *  Converted file_lock_table to a linked list from an array, which eliminates
  *  the limits on how many active file locks are open - Chad Page
  *  (pageone@netcom.com), November 27, 1994 
+ * 
+ *  Removed dependency on file descriptors. dup()'ed file descriptors now
+ *  get the same locks as the original file descriptors, and a close() on
+ *  any file descriptor removes ALL the locks on the file for the current
+ *  process. Since locks still depend on the process id, locks are inherited
+ *  after an exec() but not after a fork(). This agrees with POSIX, and both
+ *  BSD and SVR4 practice.
+ *  Andy Walker (andy@keo.kvaerner.no), February 14, 1994
+ *
  */
 
 #define DEADLOCK_DETECTION
@@ -30,20 +39,22 @@
 
 #define OFFSET_MAX	((off_t)0x7fffffff)	/* FIXME: move elsewhere? */
 
-static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
-                      unsigned int fd);
+static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l);
 static int conflict(struct file_lock *caller_fl, struct file_lock *sys_fl);
 static int overlap(struct file_lock *fl1, struct file_lock *fl2);
-static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd);
-static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl,
-                                    unsigned int fd);
+static int lock_it(struct file *filp, struct file_lock *caller);
+static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl);
 static void free_lock(struct file_lock **fl);
+static void free_list_garbage_collect(void);
 #ifdef DEADLOCK_DETECTION
 int locks_deadlocked(int my_pid,int blocked_pid);
 #endif
 
+#define FREE_LIST_GARBAGE_COLLECT 20
+
 static struct file_lock *file_lock_table = NULL;
 static struct file_lock *file_lock_free_list = NULL;
+static int free_list_cnt = 0;
 
 int fcntl_getlk(unsigned int fd, struct flock *l)
 {
@@ -60,7 +71,7 @@
 	memcpy_fromfs(&flock, l, sizeof(flock));
 	if (flock.l_type == F_UNLCK)
 		return -EINVAL;
-	if (!copy_flock(filp, &file_lock, &flock, fd))
+	if (!copy_flock(filp, &file_lock, &flock))
 		return -EINVAL;
 
 	for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
@@ -102,7 +113,7 @@
 	if (error)
 		return error;
 	memcpy_fromfs(&flock, l, sizeof(flock));
-	if (!copy_flock(filp, &file_lock, &flock, fd))
+	if (!copy_flock(filp, &file_lock, &flock))
 		return -EINVAL;
 	switch (file_lock.fl_type) {
 	case F_RDLCK :
@@ -159,7 +170,7 @@
 	 * Lock doesn't conflict with any other lock ...
 	 */
 
-	return lock_it(filp, &file_lock, fd);
+	return lock_it(filp, &file_lock);
 }
 
 #ifdef DEADLOCK_DETECTION
@@ -196,8 +207,7 @@
  * This function is called when the file is closed.
  */
 
-void fcntl_remove_locks(struct task_struct *task, struct file *filp,
-                        unsigned int fd)
+void fcntl_remove_locks(struct task_struct *task, struct file *filp)
 {
 	struct file_lock *fl;
 	struct file_lock **before;
@@ -205,12 +215,12 @@
 	/* Find first lock owned by caller ... */
 
 	before = &filp->f_inode->i_flock;
-	while ((fl = *before) && (task != fl->fl_owner || fd != fl->fl_fd))
+	while ((fl = *before) && task != fl->fl_owner)
 		before = &fl->fl_next;
 
 	/* The list is sorted by owner and fd ... */
 
-	while ((fl = *before) && task == fl->fl_owner && fd == fl->fl_fd)
+	while ((fl = *before) && task == fl->fl_owner)
 		free_lock(before);
 }
 
@@ -219,8 +229,7 @@
  * Result is a boolean indicating success.
  */
 
-static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
-                      unsigned int fd)
+static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l)
 {
 	off_t start;
 
@@ -243,7 +252,6 @@
 	if (l->l_len == 0 || (fl->fl_end = start + l->l_len - 1) < 0)
 		fl->fl_end = OFFSET_MAX;
 	fl->fl_owner = current;
-	fl->fl_fd = fd;
 	fl->fl_wait = NULL;		/* just for cleanliness */
 	return 1;
 }
@@ -254,8 +262,7 @@
 
 static int conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
 {
-	if (   caller_fl->fl_owner == sys_fl->fl_owner
-            && caller_fl->fl_fd == sys_fl->fl_fd)
+	if (caller_fl->fl_owner == sys_fl->fl_owner)
 		return 0;
 	if (!overlap(caller_fl, sys_fl))
 		return 0;
@@ -293,7 +300,7 @@
  * To all purists: Yes, I use a few goto's. Just pass on to the next function.
  */
 
-static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd)
+static int lock_it(struct file *filp, struct file_lock *caller)
 {
 	struct file_lock *fl;
 	struct file_lock *left = 0;
@@ -306,18 +313,14 @@
 	 */
 
 	before = &filp->f_inode->i_flock;
-	while ((fl = *before) &&
-	    (caller->fl_owner != fl->fl_owner ||
-	     caller->fl_fd != fl->fl_fd))
+	while ((fl = *before) && caller->fl_owner != fl->fl_owner)
 		before = &fl->fl_next;
 
 	/*
 	 * Look up all locks of this owner.
 	 */
 
-	while (   (fl = *before)
-               && caller->fl_owner == fl->fl_owner
-               && caller->fl_fd == fl->fl_fd) {
+	while ((fl = *before) && caller->fl_owner == fl->fl_owner) {
 		/*
 		 * Detect adjacent or overlapping regions (if same lock type)
 		 */
@@ -417,7 +420,7 @@
 			return 0;
 #endif
 		}
-		if (! (caller = alloc_lock(before, caller, fd)))
+		if (! (caller = alloc_lock(before, caller)))
 			return -ENOLCK;
 	}
 	if (right) {
@@ -427,7 +430,7 @@
 			 * have to allocate one more lock (in this case, even
 			 * F_UNLCK may fail!).
 			 */
-			if (! (left = alloc_lock(before, right, fd))) {
+			if (! (left = alloc_lock(before, right))) {
 				if (! added)
 					free_lock(before);
 				return -ENOLCK;
@@ -446,10 +449,8 @@
  *  Modified to create a new node if no free entries available - Chad Page
  *
  */
-
 static struct file_lock *alloc_lock(struct file_lock **pos,
-				    struct file_lock *fl,
-                                    unsigned int     fd)
+				    struct file_lock *fl)
 {
 	struct file_lock *tmp;
 
@@ -468,6 +469,7 @@
 	{
 		/* remove from free list */
 		file_lock_free_list = tmp->fl_next;
+		free_list_cnt--;
 	}
 
 	if (tmp->fl_owner != NULL)
@@ -477,7 +479,6 @@
 	*pos = tmp;
 
 	tmp->fl_owner = current;	/* FIXME: needed? */
-	tmp->fl_fd = fd;		/* FIXME: needed? */
 	tmp->fl_wait = NULL;
 
 	tmp->fl_type = fl->fl_type;
@@ -506,5 +507,15 @@
 	file_lock_free_list = fl;
 	fl->fl_owner = NULL;			/* for sanity checks */
 
+	free_list_cnt++;
+	if (free_list_cnt == FREE_LIST_GARBAGE_COLLECT)
+		free_list_garbage_collect();
+
 	wake_up(&fl->fl_wait);
+}
+
+static void free_list_garbage_collect(void)
+{
+	/* Do nothing for now */
+	return;
 }
diff -u --recursive --new-file v1.1.91/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v1.1.91/linux/fs/nfs/inode.c	Thu Jan 26 07:49:08 1995
+++ linux/fs/nfs/inode.c	Wed Feb 15 09:31:56 1995
@@ -29,7 +29,7 @@
 #include <linux/errno.h>
 #include <linux/locks.h>
 
-extern int close_fp(struct file *filp, unsigned int fd);
+extern int close_fp(struct file *filp);
 
 static int nfs_notify_change(struct inode *, struct iattr *);
 static void nfs_put_inode(struct inode *);
@@ -54,8 +54,7 @@
 
 void nfs_put_super(struct super_block *sb)
 {
-        /* No locks should be open on this, so 0 should be safe as a fd. */
-	close_fp(sb->u.nfs_sb.s_server.file, 0);
+	close_fp(sb->u.nfs_sb.s_server.file);
 	lock_super(sb);
 	sb->s_dev = 0;
 	unlock_super(sb);
diff -u --recursive --new-file v1.1.91/linux/fs/open.c linux/fs/open.c
--- v1.1.91/linux/fs/open.c	Mon Jan 30 06:41:57 1995
+++ linux/fs/open.c	Wed Feb 15 09:31:56 1995
@@ -20,7 +20,7 @@
 
 #include <asm/segment.h>
 
-extern void fcntl_remove_locks(struct task_struct *, struct file *, unsigned int fd);
+extern void fcntl_remove_locks(struct task_struct *, struct file *);
 
 asmlinkage int sys_ustat(int dev, struct ustat * ubuf)
 {
@@ -477,7 +477,7 @@
 	return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 }
 
-int close_fp(struct file *filp, unsigned int fd)
+int close_fp(struct file *filp)
 {
 	struct inode *inode;
 
@@ -487,7 +487,7 @@
 	}
 	inode = filp->f_inode;
 	if (inode)
-		fcntl_remove_locks(current, filp, fd);
+		fcntl_remove_locks(current, filp);
 	if (filp->f_count > 1) {
 		filp->f_count--;
 		return 0;
@@ -511,7 +511,7 @@
 	if (!(filp = current->files->fd[fd]))
 		return -EBADF;
 	current->files->fd[fd] = NULL;
-	return (close_fp (filp, fd));
+	return (close_fp (filp));
 }
 
 /*
diff -u --recursive --new-file v1.1.91/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.1.91/linux/fs/proc/array.c	Wed Feb  1 09:23:06 1995
+++ linux/fs/proc/array.c	Wed Feb 15 13:21:30 1995
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *  linux/fs/proc/array.c
  *
@@ -334,22 +335,31 @@
 	return NULL;
 }
 
-static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
+static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
 {
-	pgd_t *dir;
-	pte_t *table, pte;
+	pgd_t *page_dir;
+	pmd_t *page_middle;
+	pte_t pte;
 
-	if (!p || !*p || ptr >= TASK_SIZE)
+	if (!p || ptr >= TASK_SIZE)
 		return 0;
-	dir = PAGE_DIR_OFFSET(*p,ptr);
-	if (pgd_none(*dir))
+	page_dir = pgd_offset(p,ptr);
+	if (pgd_none(*page_dir))
 		return 0;
-	if (pgd_bad(*dir)) {
-		printk("bad page directory entry %08lx\n", pgd_val(*dir));
+	if (pgd_bad(*page_dir)) {
+		printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
+		pgd_clear(page_dir);
 		return 0;
 	}
-	table = (pte_t *) (pgd_page(*dir) + PAGE_PTR(ptr));
-	pte = *table;
+	page_middle = pmd_offset(page_dir,ptr);
+	if (pmd_none(*page_middle))
+		return 0;
+	if (pmd_bad(*page_middle)) {
+		printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
+		pmd_clear(page_middle);
+		return 0;
+	}
+	pte = *pte_offset(page_middle,ptr);
 	if (!pte_present(pte))
 		return 0;
 	return pte_page(pte) + (ptr & ~PAGE_MASK);
@@ -364,7 +374,7 @@
 	if (start >= end)
 		return result;
 	for (;;) {
-		addr = get_phys_addr(p, start);
+		addr = get_phys_addr(*p, start);
 		if (!addr)
 			goto ready;
 		do {
@@ -511,55 +521,109 @@
 		sigcatch,
 		wchan);
 }
+		
+static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
+	int * pages, int * shared, int * dirty, int * total)
+{
+	pte_t * pte;
+	unsigned long end;
+
+	if (pmd_none(*pmd))
+		return;
+	if (pmd_bad(*pmd)) {
+		printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+		pmd_clear(pmd);
+		return;
+	}
+	pte = pte_offset(pmd, address);
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		pte_t page = *pte;
+
+		address += PAGE_SIZE;
+		pte++;
+		if (pte_none(page))
+			continue;
+		++*total;
+		if (!pte_present(page))
+			continue;
+		++*pages;
+		if (pte_dirty(page))
+			++*dirty;
+		if (pte_page(page) >= high_memory)
+			continue;
+		if (mem_map[MAP_NR(pte_page(page))] > 1)
+			++*shared;
+	} while (address < end);
+}
+
+static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
+	int * pages, int * shared, int * dirty, int * total)
+{
+	pmd_t * pmd;
+	unsigned long end;
+
+	if (pgd_none(*pgd))
+		return;
+	if (pgd_bad(*pgd)) {
+		printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
+		pgd_clear(pgd);
+		return;
+	}
+	pmd = pmd_offset(pgd, address);
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	do {
+		statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+}
+
+static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
+	int * pages, int * shared, int * dirty, int * total)
+{
+	while (address < end) {
+		statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		pgd++;
+	}
+}
 
 static int get_statm(int pid, char * buffer)
 {
 	struct task_struct ** p = get_task(pid);
-	pgd_t *pagedir;
-	pte_t *pte;
-	int i, j, tpag;
 	int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
 
 	if (!p || !*p)
 		return 0;
-	tpag = (*p)->mm->end_code / PAGE_SIZE;
 	if ((*p)->state != TASK_ZOMBIE) {
-	  pagedir = PAGE_DIR_OFFSET(*p, 0);
-	  for (i = 0; i < 0x300; ++i) {
-	    if (pgd_none(pagedir[i])) {
-	      tpag -= PTRS_PER_PAGE;
-	      continue;
-	    }
-	    if (pgd_bad(pagedir[i])) {
-	    	printk("bad page table dir %08lx\n", pgd_val(pagedir[i]));
-	    	pgd_clear(pagedir+i);
-	    	tpag -= PTRS_PER_PAGE;
-	    	continue;
-	    }
-	    pte = (pte_t *) pgd_page(pagedir[i]);
-	    for (j = 0; j < PTRS_PER_PAGE; j++, pte++) {
-	      if (!pte_none(*pte)) {
-		++size;
-		if (pte_present(*pte)) {
-		  ++resident;
-		  if (tpag > 0)
-		    ++trs;
-		  else
-		    ++drs;
-		  if (i >= 15 && i < 0x2f0) {
-		    ++lrs;
-		    if (pte_dirty(*pte))
-		      ++dt;
-		    else
-		      --drs;
-		  }
-		  if (pte_page(*pte) < high_memory && mem_map[MAP_NR(pte_page(*pte))] > 1)
-		    ++share;
+		struct vm_area_struct * vma = (*p)->mm->mmap;
+
+		while (vma) {
+			pgd_t *pgd = pgd_offset(*p, vma->vm_start);
+			int pages = 0, shared = 0, dirty = 0, total = 0;
+
+			statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
+			resident += pages;
+			share += shared;
+			dt += dirty;
+			size += total;
+			if (vma->vm_flags & VM_EXECUTABLE)
+				trs += pages;	/* text */
+			else if (vma->vm_flags & VM_GROWSDOWN)
+				drs += pages;	/* stack */
+			else if (vma->vm_end > 0x60000000)
+				lrs += pages;	/* library */
+			else
+				drs += pages;
+			vma = vma->vm_next;
 		}
-	      }
-	      --tpag;
-	    }
-	  }
 	}
 	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
 		       size, resident, share, trs, lrs, drs, dt);
diff -u --recursive --new-file v1.1.91/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v1.1.91/linux/include/asm-alpha/system.h	Sun Feb  5 19:31:54 1995
+++ linux/include/asm-alpha/system.h	Tue Feb 14 08:39:06 1995
@@ -81,7 +81,6 @@
 
 #define halt() __asm__ __volatile__(".long 0");
 
-#define move_to_user_mode()	printk("Null move_to_user_mode\n")
 #define switch_to(x)		panic("switch_to() not yet done")
 
 #ifndef mb
diff -u --recursive --new-file v1.1.91/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v1.1.91/linux/include/asm-i386/pgtable.h	Wed Feb 15 10:36:39 1995
+++ linux/include/asm-i386/pgtable.h	Wed Feb 15 21:27:25 1995
@@ -132,12 +132,18 @@
 extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_PRESENT; }
 extern inline int pte_inuse(pte_t *ptep)	{ return mem_map[MAP_NR(ptep)] > 1; }
 extern inline void pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
+extern inline void pte_reuse(pte_t * ptep)
+{
+	if (!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED))
+		mem_map[MAP_NR(ptep)]++;
+}
 
 extern inline int pmd_none(pmd_t pmd)		{ return !pmd_val(pmd); }
 extern inline int pmd_bad(pmd_t pmd)		{ return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; }
 extern inline int pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & _PAGE_PRESENT; }
 extern inline int pmd_inuse(pmd_t *pmdp)	{ return 0; }
 extern inline void pmd_clear(pmd_t * pmdp)	{ pmd_val(*pmdp) = 0; }
+extern inline void pmd_reuse(pmd_t * pmdp)	{ }
 
 #ifdef THREE_LEVEL
 /*
@@ -150,6 +156,11 @@
 extern inline int pgd_present(pgd_t pgd)	{ return 1; }
 extern inline int pgd_inuse(pgd_t * pgdp)	{ return mem_map[MAP_NR(pgdp)] > 1; }
 extern inline void pgd_clear(pgd_t * pgdp)	{ }
+extern inline void pgd_reuse(pgd_t * pgdp)
+{
+	if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED))
+		mem_map[MAP_NR(pgdp)]++;
+}
 #else
 /*
  * These are the old (and incorrect) ones needed for code that doesn't
diff -u --recursive --new-file v1.1.91/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v1.1.91/linux/include/asm-i386/system.h	Sun Feb  5 19:31:55 1995
+++ linux/include/asm-i386/system.h	Tue Feb 14 08:39:06 1995
@@ -3,21 +3,6 @@
 
 #include <asm/segment.h>
 
-#define move_to_user_mode() \
-__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
-	"pushl %0\n\t" \
-	"pushl %%eax\n\t" \
-	"pushfl\n\t" \
-	"pushl %1\n\t" \
-	"pushl $1f\n\t" \
-	"iret\n" \
-	"1:\tmovl %0,%%eax\n\t" \
-	"mov %%ax,%%ds\n\t" \
-	"mov %%ax,%%es\n\t" \
-	"mov %%ax,%%fs\n\t" \
-	"mov %%ax,%%gs" \
-	: /* no outputs */ :"i" (USER_DS), "i" (USER_CS):"ax")
-
 /*
  * Entry into gdt where to find first TSS. GDT layout:
  *   0 - nul
diff -u --recursive --new-file v1.1.91/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.1.91/linux/include/linux/fs.h	Fri Jan 13 16:57:06 1995
+++ linux/include/linux/fs.h	Wed Feb 15 09:31:56 1995
@@ -269,7 +269,6 @@
 	struct file_lock *fl_next;	/* singly linked list */
 	struct file_lock *fl_nextlink;
 	struct task_struct *fl_owner;	/* NULL if on free list, for sanity checks */
-        unsigned int fl_fd;             /* File descriptor for this lock */
 	struct wait_queue *fl_wait;
 	char fl_type;
 	char fl_whence;
diff -u --recursive --new-file v1.1.91/linux/include/linux/major.h linux/include/linux/major.h
--- v1.1.91/linux/include/linux/major.h	Sun Jan 22 21:39:44 1995
+++ linux/include/linux/major.h	Wed Feb 15 10:51:05 1995
@@ -24,7 +24,7 @@
  *  4 - /dev/tty*
  *  5 - /dev/tty; /dev/cua*
  *  6 - lp
- *  7 -                                               UNUSED
+ *  7 - /dev/vcs*
  *  8 -                        scsi disk
  *  9 - scsi tape
  * 10 - mice
@@ -57,7 +57,7 @@
 #define TTY_MAJOR	4
 #define TTYAUX_MAJOR	5
 #define LP_MAJOR	6
-/* unused: 7 */
+#define VCS_MAJOR	7
 #define SCSI_DISK_MAJOR	8
 #define SCSI_TAPE_MAJOR	9
 #define MOUSE_MAJOR	10
diff -u --recursive --new-file v1.1.91/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.1.91/linux/include/linux/mm.h	Sun Feb  5 19:31:55 1995
+++ linux/include/linux/mm.h	Wed Feb 15 10:51:06 1995
@@ -185,7 +185,7 @@
 extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem);
 extern void mem_init(unsigned long start_mem, unsigned long end_mem);
 extern void show_mem(void);
-extern void oom(struct task_struct * task);
+extern void oom(struct task_struct * tsk);
 extern void si_meminfo(struct sysinfo * val);
 
 /* vmalloc.c */
diff -u --recursive --new-file v1.1.91/linux/include/linux/tty.h linux/include/linux/tty.h
--- v1.1.91/linux/include/linux/tty.h	Thu Feb  9 10:18:53 1995
+++ linux/include/linux/tty.h	Wed Feb 15 10:51:05 1995
@@ -278,6 +278,10 @@
 extern long con_init(long);
 extern long pty_init(long);
 extern long tty_init(long);
+extern long vcs_init(long);
+#ifdef CONFIG_CYCLADES
+extern long cy_init(long);
+#endif
 
 extern int tty_paranoia_check(struct tty_struct *tty, dev_t device,
 			      const char *routine);
diff -u --recursive --new-file v1.1.91/linux/init/main.c linux/init/main.c
--- v1.1.91/linux/init/main.c	Wed Feb 15 10:36:40 1995
+++ linux/init/main.c	Tue Feb 14 08:39:06 1995
@@ -420,7 +420,6 @@
 
 	printk(linux_banner);
 
-	move_to_user_mode();
 	if (!fork())		/* we count on this going ok */
 		init();
 /*
diff -u --recursive --new-file v1.1.91/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.1.91/linux/kernel/ksyms.c	Wed Feb 15 10:36:40 1995
+++ linux/kernel/ksyms.c	Wed Feb 15 09:33:15 1995
@@ -67,7 +67,7 @@
 extern int request_dma(unsigned int dmanr, char * deviceID);
 extern void free_dma(unsigned int dmanr);
 
-extern int close_fp(struct file *filp, unsigned int fd);
+extern int close_fp(struct file *filp);
 extern void (* iABI_hook)(struct pt_regs * regs);
 
 struct symbol_table symbol_table = {
diff -u --recursive --new-file v1.1.91/linux/mm/filemap.c linux/mm/filemap.c
--- v1.1.91/linux/mm/filemap.c	Wed Feb  1 09:23:08 1995
+++ linux/mm/filemap.c	Tue Feb 14 08:39:06 1995
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *	linux/mm/filemmap.c
  *
@@ -28,7 +29,7 @@
  * though.
  */
 
-static unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned long address,
+static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address,
 	unsigned long page, int no_share)
 {
 	struct inode * inode = area->vm_inode;
@@ -61,12 +62,13 @@
  * - the "swapout()" function needs to swap out the page to
  *   the shared file instead of using the swap device.
  */
-static inline void file_mmap_sync_page(struct vm_area_struct * vma,
+static void filemap_sync_page(struct vm_area_struct * vma,
 	unsigned long offset,
 	unsigned long page)
 {
 	struct buffer_head * bh;
 
+	printk("msync: %ld: [%08lx]\n", offset, page);
 	bh = buffer_pages[MAP_NR(page)];
 	if (bh) {
 		/* whee.. just mark the buffer heads dirty */
@@ -78,60 +80,94 @@
 		return;
 	}
 	/* we'll need to go fetch the buffer heads etc.. RSN */
-	printk("msync: %ld: [%08lx]\n", offset, page);
 	printk("Can't handle non-shared page yet\n");
 	return;
 }
 
-static void file_mmap_sync(struct vm_area_struct * vma, unsigned long start,
+static inline void filemap_sync_pte(pte_t * pte, struct vm_area_struct *vma,
+	unsigned long address, unsigned int flags)
+{
+	pte_t page = *pte;
+
+	if (!pte_present(page))
+		return;
+	if (!pte_dirty(page))
+		return;
+	if (flags & MS_INVALIDATE) {
+		pte_clear(pte);
+	} else {
+		mem_map[MAP_NR(pte_page(page))]++;
+		*pte = pte_mkclean(page);
+	}
+	filemap_sync_page(vma, address - vma->vm_start, pte_page(page));
+	free_page(pte_page(page));
+}
+
+static inline void filemap_sync_pte_range(pmd_t * pmd,
+	unsigned long address, unsigned long size, 
+	struct vm_area_struct *vma, unsigned long offset, unsigned int flags)
+{
+	pte_t * pte;
+	unsigned long end;
+
+	if (pmd_none(*pmd))
+		return;
+	if (pmd_bad(*pmd)) {
+		printk("filemap_sync_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+		pmd_clear(pmd);
+		return;
+	}
+	pte = pte_offset(pmd, address);
+	offset += address & PMD_MASK;
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		filemap_sync_pte(pte, vma, address + offset, flags);
+		address += PAGE_SIZE;
+		pte++;
+	} while (address < end);
+}
+
+static inline void filemap_sync_pmd_range(pgd_t * pgd,
+	unsigned long address, unsigned long size, 
+	struct vm_area_struct *vma, unsigned int flags)
+{
+	pmd_t * pmd;
+	unsigned long offset, end;
+
+	if (pgd_none(*pgd))
+		return;
+	if (pgd_bad(*pgd)) {
+		printk("filemap_sync_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
+		pgd_clear(pgd);
+		return;
+	}
+	pmd = pmd_offset(pgd, address);
+	offset = address & PMD_MASK;
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	do {
+		filemap_sync_pte_range(pmd, address, end - address, vma, offset, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+}
+
+static void filemap_sync(struct vm_area_struct * vma, unsigned long address,
 	size_t size, unsigned int flags)
 {
 	pgd_t * dir;
-	unsigned long poff, pcnt;
+	unsigned long end = address + size;
 
-	size = size >> PAGE_SHIFT;
-	dir = PAGE_DIR_OFFSET(current,start);
-	poff = (start >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
-	start -= vma->vm_start;
-	pcnt = PTRS_PER_PAGE - poff;
-	if (pcnt > size)
-		pcnt = size;
-
-	for ( ; size > 0; ++dir, size -= pcnt, pcnt = (size > PTRS_PER_PAGE ? PTRS_PER_PAGE : size)) {
-		pte_t *page_table;
-		unsigned long pc;
-
-		if (pgd_none(*dir)) {
-			poff = 0;
-			start += pcnt*PAGE_SIZE;
-			continue;
-		}
-		if (pgd_bad(*dir)) {
-			printk("file_mmap_sync: bad page directory entry %08lx.\n", pgd_val(*dir));
-			pgd_clear(dir);
-			poff = 0;
-			start += pcnt*PAGE_SIZE;
-			continue;
-		}
-		page_table = poff + (pte_t *) pgd_page(*dir);
-		poff = 0;
-		for (pc = pcnt; pc--; page_table++, start += PAGE_SIZE) {
-			pte_t pte;
-
-			pte = *page_table;
-			if (!pte_present(pte))
-				continue;
-			if (!pte_dirty(pte))
-				continue;
-			if (flags & MS_INVALIDATE) {
-				pte_clear(page_table);
-			} else {
-				mem_map[MAP_NR(pte_page(pte))]++;
-				*page_table = pte_mkclean(pte);
-			}
-			file_mmap_sync_page(vma, start, pte_page(pte));
-			free_page(pte_page(pte));
-		}
+	dir = pgd_offset(current, address);
+	while (address < end) {
+		filemap_sync_pmd_range(dir, address, end - address, vma, flags);
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
 	}
 	invalidate();
 	return;
@@ -140,17 +176,17 @@
 /*
  * This handles area unmaps..
  */
-static void file_mmap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
+static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
 {
-	file_mmap_sync(vma, start, len, MS_ASYNC);
+	filemap_sync(vma, start, len, MS_ASYNC);
 }
 
 /*
  * This handles complete area closes..
  */
-static void file_mmap_close(struct vm_area_struct * vma)
+static void filemap_close(struct vm_area_struct * vma)
 {
-	file_mmap_sync(vma, vma->vm_start, vma->vm_end - vma->vm_start, MS_ASYNC);
+	filemap_sync(vma, vma->vm_start, vma->vm_end - vma->vm_start, MS_ASYNC);
 }
 
 /*
@@ -160,7 +196,7 @@
  * so we have to either write it out or just forget it. We currently
  * forget it..
  */
-void file_mmap_swapout(struct vm_area_struct * vma,
+void filemap_swapout(struct vm_area_struct * vma,
 	unsigned long offset,
 	pte_t *page_table)
 {
@@ -175,14 +211,14 @@
  */
 static struct vm_operations_struct file_shared_mmap = {
 	NULL,			/* open */
-	file_mmap_close,	/* close */
-	file_mmap_unmap,	/* unmap */
+	filemap_close,		/* close */
+	filemap_unmap,		/* unmap */
 	NULL,			/* protect */
-	file_mmap_sync,		/* sync */
+	filemap_sync,		/* sync */
 	NULL,			/* advise */
-	file_mmap_nopage,	/* nopage */
+	filemap_nopage,		/* nopage */
 	NULL,			/* wppage */
-	file_mmap_swapout,	/* swapout */
+	filemap_swapout,	/* swapout */
 	NULL,			/* swapin */
 };
 
@@ -199,7 +235,7 @@
 	NULL,			/* protect */
 	NULL,			/* sync */
 	NULL,			/* advise */
-	file_mmap_nopage,	/* nopage */
+	filemap_nopage,		/* nopage */
 	NULL,			/* wppage */
 	NULL,			/* swapout */
 	NULL,			/* swapin */
@@ -221,9 +257,11 @@
 		if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) {
 			static int nr = 0;
 			ops = &file_shared_mmap;
+#ifndef SHARED_MMAP_REALLY_WORKS /* it doesn't, yet */
 			if (nr++ < 5)
 				printk("%s tried to do a shared writeable mapping\n", current->comm);
 			return -EINVAL;
+#endif
 		}
 	}
 	if (!IS_RDONLY(inode)) {
diff -u --recursive --new-file v1.1.91/linux/mm/memory.c linux/mm/memory.c
--- v1.1.91/linux/mm/memory.c	Wed Feb 15 10:36:40 1995
+++ linux/mm/memory.c	Wed Feb 15 21:25:53 1995
@@ -222,7 +222,7 @@
 	pgd_t * pg_dir;
 
 	pg_dir = pgd_offset(current, 0);
-	mem_map[MAP_NR(pg_dir)]++;
+	pgd_reuse(pg_dir);
 	SET_PAGE_DIR(tsk, pg_dir);
 	return 0;
 }
@@ -265,6 +265,7 @@
 	}
 	old_pte = pte_offset(old_pmd, 0);
 	if (pte_inuse(old_pte)) {
+		pte_reuse(old_pte);
 		*new_pmd = *old_pmd;
 		return 0;
 	}
@@ -293,6 +294,7 @@
 	}
 	old_pmd = pmd_offset(old_pgd, 0);
 	if (pmd_inuse(old_pmd)) {
+		pmd_reuse(old_pmd);
 		*new_pgd = *old_pgd;
 		return 0;
 	}
diff -u --recursive --new-file v1.1.91/linux/mm/mprotect.c linux/mm/mprotect.c
--- v1.1.91/linux/mm/mprotect.c	Wed Feb 15 10:36:40 1995
+++ linux/mm/mprotect.c	Tue Feb 14 08:39:06 1995
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *	linux/mm/mprotect.c
  *
@@ -17,44 +18,69 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
+static inline void change_pte_range(pmd_t * pmd, unsigned long address,
+	unsigned long size, pgprot_t newprot)
+{
+	pte_t * pte;
+	unsigned long end;
+
+	if (pmd_none(*pmd))
+		return;
+	if (pmd_bad(*pmd)) {
+		printk("change_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+		pmd_clear(pmd);
+		return;
+	}
+	pte = pte_offset(pmd, address);
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		pte_t entry = *pte;
+		if (pte_present(entry))
+			*pte = pte_modify(entry, newprot);
+		address += PAGE_SIZE;
+		pte++;
+	} while (address < end);
+}
+
+static inline void change_pmd_range(pgd_t * pgd, unsigned long address,
+	unsigned long size, pgprot_t newprot)
+{
+	pmd_t * pmd;
+	unsigned long end;
+
+	if (pgd_none(*pgd))
+		return;
+	if (pgd_bad(*pgd)) {
+		printk("change_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
+		pgd_clear(pgd);
+		return;
+	}
+	pmd = pmd_offset(pgd, address);
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	do {
+		change_pte_range(pmd, address, end - address, newprot);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+}
+
 static void change_protection(unsigned long start, unsigned long end, pgprot_t newprot)
 {
 	pgd_t *dir;
-	pte_t *page_table, entry;
-	unsigned long offset;
-	int nr;
-
-	dir = PAGE_DIR_OFFSET(current, start);
-	offset = (start >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
-	nr = (end - start) >> PAGE_SHIFT;
-	while (nr > 0) {
-		if (pgd_none(*dir)) {
-			dir++;
-			nr = nr - PTRS_PER_PAGE + offset;
-			offset = 0;
-			continue;
-		}
-		if (pgd_bad(*dir)) {
-			printk("Bad page dir entry %08lx\n", pgd_val(*dir));
-			pgd_clear(dir);
-			dir++;
-			nr = nr - PTRS_PER_PAGE + offset;
-			offset = 0;
-			continue;
-		}
-		page_table = offset + (pte_t *) pgd_page(*dir);
-		offset = PTRS_PER_PAGE - offset;
-		if (offset > nr)
-			offset = nr;
-		nr = nr - offset;
-		do {
-			entry = *page_table;
-			if (pte_present(entry))
-				*page_table = pte_modify(entry, newprot);
-			++page_table;
-		} while (--offset);
+
+	dir = pgd_offset(current, start);
+	while (start < end) {
+		change_pmd_range(dir, start, end - start, newprot);
+		start = (start + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
+	invalidate();
 	return;
 }
 
diff -u --recursive --new-file v1.1.91/linux/mm/swap.c linux/mm/swap.c
--- v1.1.91/linux/mm/swap.c	Wed Feb  1 09:23:08 1995
+++ linux/mm/swap.c	Tue Feb 14 08:39:06 1995
@@ -1,3 +1,4 @@
+#define THREE_LEVEL
 /*
  *  linux/mm/swap.c
  *
@@ -387,11 +388,89 @@
  */
 #define SWAP_RATIO	128
 
+static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir,
+	unsigned long address, unsigned long size, unsigned long offset)
+{
+	pte_t * pte;
+	unsigned long end;
+
+	if (pmd_none(*dir))
+		return 0;
+	if (pmd_bad(*dir)) {
+		printk("swap_out_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
+		pmd_clear(dir);
+		return 0;
+	}
+	pte = pte_offset(dir, address);
+	offset += address & PMD_MASK;
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		switch (try_to_swap_out(vma, offset+address-vma->vm_start, pte)) {
+			case 0:
+				break;
+
+			case 1:
+				vma->vm_task->mm->rss--;
+				/* continue with the following page the next time */
+				vma->vm_task->mm->swap_address = address + offset + PAGE_SIZE;
+				return 1;
+
+			default:
+				vma->vm_task->mm->rss--;
+				break;
+		}
+		address += PAGE_SIZE;
+		pte++;
+	} while (address < end);
+	return 0;
+}
+
+static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir,
+	unsigned long address, unsigned long size)
+{
+	pmd_t * pmd;
+	unsigned long offset, end;
+
+	if (pgd_none(*dir))
+		return 0;
+	if (pgd_bad(*dir)) {
+		printk("swap_out_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
+		pgd_clear(dir);
+		return 0;
+	}
+	pmd = pmd_offset(dir, address);
+	offset = address & PGDIR_MASK;
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	do {
+		if (swap_out_pmd(vma, pmd, address, end - address, offset))
+			return 1;
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+	return 0;
+}
+
+static int swap_out_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+	unsigned long start, unsigned long end)
+{
+	while (start < end) {
+		if (swap_out_pgd(vma, pgdir, start, end - start))
+			return 1;
+		start = (start + PGDIR_SIZE) & PGDIR_MASK;
+		pgdir++;
+	}
+	return 0;
+}
+
 static int swap_out_process(struct task_struct * p)
 {
-	pgd_t *pgdir;
 	unsigned long address;
-	unsigned long offset;
 	struct vm_area_struct* vma;
 
 	/*
@@ -409,60 +488,14 @@
 	if (address < vma->vm_start)
 		address = vma->vm_start;
 
-	pgdir = PAGE_DIR_OFFSET(p, address);
-	offset = address & ~PGDIR_MASK;
-	address &= PGDIR_MASK;
-	for ( ; address < TASK_SIZE ; pgdir++, address = address + PGDIR_SIZE, offset = 0) {
-		pte_t *pg_table;
-
-		if (pgd_none(*pgdir))
-			continue;
-		if (pgd_bad(*pgdir)) {
-			printk("Bad page directory at address %08lx: %08lx\n", address, pgd_val(*pgdir));
-			pgd_clear(pgdir);
-			continue;
-		}
-		pg_table = (pte_t *) pgd_page(*pgdir);
-		if (mem_map[MAP_NR((unsigned long) pg_table)] & MAP_PAGE_RESERVED)
-			continue;
-		pg_table += offset >> PAGE_SHIFT;
-
-		/*
-		 * Go through this page table.
-		 */
-		for( ; offset < ~PGDIR_MASK ; pg_table++, offset += PAGE_SIZE) {
-			/*
-			 * Update vma again..
-			 */
-			for (;;) {
-				if (address+offset < vma->vm_end)
-					break;
-				vma = vma->vm_next;
-				if (!vma)
-					return 0;
-			}
-
-			switch(try_to_swap_out(vma, offset+address-vma->vm_start, pg_table)) {
-				case 0:
-					break;
-
-				case 1:
-					p->mm->rss--;
-					/* continue with the following page the next time */
-					p->mm->swap_address = address + offset + PAGE_SIZE;
-					return 1;
-
-				default:
-					p->mm->rss--;
-					break;
-			}
-		}
+	for (;;) {
+		if (swap_out_vma(vma, pgd_offset(p, address), address, vma->vm_end))
+			return 1;
+		vma = vma->vm_next;
+		if (!vma)
+			return 0;
+		address = vma->vm_start;
 	}
-	/*
-	 * Finish work with this process, if we reached the end of the page
-	 * directory.
-	 */
-	return 0;
 }
 
 static int swap_out(unsigned int priority)
@@ -748,77 +781,157 @@
 /*
  * Trying to stop swapping from a file is fraught with races, so
  * we repeat quite a bit here when we have to pause. swapoff()
- * isn't exactly timing-critical, so who cares?
+ * isn't exactly timing-critical, so who cares (but this is /really/
+ * inefficient, ugh).
+ *
+ * We return 1 after having slept, which makes the process start over
+ * from the beginning for this process..
  */
-static int try_to_unuse(unsigned int type)
+static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address,
+	pte_t *dir, unsigned int type, unsigned long page)
 {
-	int nr;
-	unsigned long tmp = 0;
-	struct task_struct *p;
+	pte_t pte = *dir;
+
+	if (pte_none(pte))
+		return 0;
+	if (pte_present(pte)) {
+		unsigned long page = pte_page(pte);
+		if (page >= high_memory)
+			return 0;
+		if (!in_swap_cache(page))
+			return 0;
+		if (SWP_TYPE(in_swap_cache(page)) != type)
+			return 0;
+		delete_from_swap_cache(page);
+		*dir = pte_mkdirty(pte);
+		return 0;
+	}
+	if (SWP_TYPE(pte_val(pte)) != type)
+		return 0;
+	read_swap_page(pte_val(pte), (char *) page);
+	if (pte_val(*dir) != pte_val(pte)) {
+		free_page(page);
+		return 1;
+	}
+	*dir = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	++vma->vm_task->mm->rss;
+	swap_free(pte_val(pte));
+	return 1;
+}
+
+static inline int unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
+	unsigned long address, unsigned long size, unsigned long offset,
+	unsigned int type, unsigned long page)
+{
+	pte_t * pte;
+	unsigned long end;
+
+	if (pmd_none(*dir))
+		return 0;
+	if (pmd_bad(*dir)) {
+		printk("unuse_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
+		pmd_clear(dir);
+		return 0;
+	}
+	pte = pte_offset(dir, address);
+	offset += address & PMD_MASK;
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		if (unuse_pte(vma, offset+address-vma->vm_start, pte, type, page))
+			return 1;
+		address += PAGE_SIZE;
+		pte++;
+	} while (address < end);
+	return 0;
+}
+
+static inline int unuse_pgd(struct vm_area_struct * vma, pgd_t *dir,
+	unsigned long address, unsigned long size,
+	unsigned int type, unsigned long page)
+{
+	pmd_t * pmd;
+	unsigned long offset, end;
+
+	if (pgd_none(*dir))
+		return 0;
+	if (pgd_bad(*dir)) {
+		printk("unuse_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
+		pgd_clear(dir);
+		return 0;
+	}
+	pmd = pmd_offset(dir, address);
+	offset = address & PGDIR_MASK;
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	do {
+		if (unuse_pmd(vma, pmd, address, end - address, offset, type, page))
+			return 1;
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+	return 0;
+}
+
+static int unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+	unsigned long start, unsigned long end,
+	unsigned int type, unsigned long page)
+{
+	while (start < end) {
+		if (unuse_pgd(vma, pgdir, start, end - start, type, page))
+			return 1;
+		start = (start + PGDIR_SIZE) & PGDIR_MASK;
+		pgdir++;
+	}
+	return 0;
+}
+
+static int unuse_process(struct task_struct * p, unsigned int type, unsigned long page)
+{
+	struct vm_area_struct* vma;
+
+	/*
+	 * Go through process' page directory.
+	 */
+	vma = p->mm->mmap;
+	while (vma) {
+		pgd_t * pgd = pgd_offset(p, vma->vm_start);
+		if (unuse_vma(vma, pgd, vma->vm_start, vma->vm_end, type, page))
+			return 1;
+		vma = vma->vm_next;
+	}
+	return 0;
+}
 
-	nr = 0;	
 /*
- * When we have to sleep, we restart the whole algorithm from the same
- * task we stopped in. That at least rids us of all races.
+ * To avoid races, we repeat for each process after having
+ * swapped something in. That gets rid of a few pesky races,
+ * and "swapoff" isn't exactly timing critical.
  */
-repeat:
-	for (; nr < NR_TASKS ; nr++) {
-		pgd_t * page_dir;
-		int i;
-
-		p = task[nr];
-		if (!p)
-			continue;
-		page_dir = PAGE_DIR_OFFSET(p, 0);
-		for (i = 0 ; i < PTRS_PER_PAGE ; page_dir++, i++) {
-			int j;
-			pte_t *page_table;
+static int try_to_unuse(unsigned int type)
+{
+	int nr;
+	unsigned long page = get_free_page(GFP_KERNEL);
 
-			if (pgd_none(*page_dir))
-				continue;
-			if (pgd_bad(*page_dir)) {
-				printk("bad page directory entry [%d] %08lx\n", i, pgd_val(*page_dir));
-				pgd_clear(page_dir);
+	if (!page)
+		return -ENOMEM;
+	nr = 0;
+	while (nr < NR_TASKS) {
+		if (task[nr]) {
+			if (unuse_process(task[nr], type, page)) {
+				page = get_free_page(GFP_KERNEL);
+				if (!page)
+					return -ENOMEM;
 				continue;
 			}
-			page_table = (pte_t *) pgd_page(*page_dir);
-			if (mem_map[MAP_NR((unsigned long) page_table)] & MAP_PAGE_RESERVED)
-				continue;
-			for (j = 0 ; j < PTRS_PER_PAGE ; page_table++, j++) {
-				pte_t pte;
-				pte = *page_table;
-				if (pte_none(pte))
-					continue;
-				if (pte_present(pte)) {
-					unsigned long page = pte_page(pte);
-					if (page >= high_memory)
-						continue;
-					if (!in_swap_cache(page))
-						continue;
-					if (SWP_TYPE(in_swap_cache(page)) != type)
-						continue;
-					delete_from_swap_cache(page);
-					*page_table = pte_mkdirty(pte);
-					continue;
-				}
-				if (SWP_TYPE(pte_val(pte)) != type)
-					continue;
-				if (!tmp) {
-					if (!(tmp = __get_free_page(GFP_KERNEL)))
-						return -ENOMEM;
-					goto repeat;
-				}
-				read_swap_page(pte_val(pte), (char *) tmp);
-				if (pte_val(*page_table) != pte_val(pte))
-					goto repeat;
-				*page_table = pte_mkwrite(pte_mkdirty(mk_pte(tmp, PAGE_COPY)));
-				++p->mm->rss;
-				swap_free(pte_val(pte));
-				tmp = 0;
-			}
 		}
+		nr++;
 	}
-	free_page(tmp);
+	free_page(page);
 	return 0;
 }
 
diff -u --recursive --new-file v1.1.91/linux/net/inet/arp.c linux/net/inet/arp.c
--- v1.1.91/linux/net/inet/arp.c	Wed Feb 15 10:36:41 1995
+++ linux/net/inet/arp.c	Mon Feb 13 12:33:40 1995
@@ -841,7 +841,7 @@
 	/*
 	 *	Find an entry
 	 */
-	entry = arp_lookup(paddr, 0);
+	entry = arp_lookup(paddr, 1);
 
 	if (entry != NULL) 	/* It exists */
 	{
diff -u --recursive --new-file v1.1.91/linux/net/inet/dev.c linux/net/inet/dev.c
--- v1.1.91/linux/net/inet/dev.c	Wed Feb  1 09:23:08 1995
+++ linux/net/inet/dev.c	Wed Feb 15 21:31:24 1995
@@ -28,6 +28,7 @@
  *		Alan Cox	:	100 backlog just doesn't cut it when
  *					you start doing multicast video 8)
  *		Alan Cox	:	Rewrote net_bh and list manager.
+ *		Alan Cox	: 	Fix ETH_P_ALL echoback lengths.
  *
  *	Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have
  *	the rest as well commented in the end.
@@ -398,6 +399,11 @@
 				struct sk_buff *skb2;
 				if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
 					break;
+				/*
+				 *	The protocol knows this has (for other paths) been taken off
+				 *	and adds it back.
+				 */
+				skb2->len-=skb->dev->hard_header_len;
 				ptype->func(skb2, skb->dev, ptype);
 				nitcount--;
 			}
diff -u --recursive --new-file v1.1.91/linux/net/inet/ip.c linux/net/inet/ip.c
--- v1.1.91/linux/net/inet/ip.c	Sun Feb  5 19:31:56 1995
+++ linux/net/inet/ip.c	Wed Feb 15 10:50:39 1995
@@ -2052,19 +2052,6 @@
 	if(level!=SOL_IP)
 		return -EOPNOTSUPP;
 
-#ifdef CONFIG_IP_MULTICAST
-	if(optname==IP_MULTICAST_TTL)
-	{
-		unsigned char ucval;
-		ucval=get_fs_byte((unsigned char *)optval);
-		printk("MC TTL %d\n", ucval);
-		if(ucval<1||ucval>255)
-	 		return -EINVAL;
-		sk->ip_mc_ttl=(int)ucval;
-		return 0;
-	}
-#endif
-
 	switch(optname)
 	{
 		case IP_TOS:
@@ -2082,19 +2069,16 @@
 			sk->ip_ttl=val;
 			return 0;
 #ifdef CONFIG_IP_MULTICAST
-#ifdef GCC_WORKS
 		case IP_MULTICAST_TTL: 
 		{
 			unsigned char ucval;
 
 			ucval=get_fs_byte((unsigned char *)optval);
-			printk("MC TTL %d\n", ucval);
 			if(ucval<1||ucval>255)
                                 return -EINVAL;
 			sk->ip_mc_ttl=(int)ucval;
 	                return 0;
 		}
-#endif
 		case IP_MULTICAST_LOOP: 
 		{
 			unsigned char ucval;
