diff -c --recursive linux/kernel/chr_drv_orig/Makefile linux/kernel/chr_drv/Makefile
*** linux/kernel/chr_drv_orig/Makefile	Mon Jun 14 02:26:22 1993
--- linux/kernel/chr_drv/Makefile	Mon Jun 14 11:56:57 1993
***************
*** 9,20 ****
  # parent makes..
  #
  
  .c.s:
  	$(CC) $(CFLAGS) -S $<
  .s.o:
  	$(AS) -c -o $*.o $<
  .c.o:
! 	$(CC) $(CFLAGS) -c $<
  
  SUBDIRS= sound
  
--- 9,23 ----
  # parent makes..
  #
  
+ # comment out next line to disable dual-monitor support
+ DUAL= -DCONFIG_DUALMON
+ 
  .c.s:
  	$(CC) $(CFLAGS) -S $<
  .s.o:
  	$(AS) -c -o $*.o $<
  .c.o:
! 	$(CC) $(DUAL) $(SELECTION) $(CFLAGS) -c $<
  
  SUBDIRS= sound
  
diff -c --recursive linux/kernel/chr_drv_orig/console.c linux/kernel/chr_drv/console.c
*** linux/kernel/chr_drv_orig/console.c	Mon Jun 14 02:26:23 1993
--- linux/kernel/chr_drv/console.c	Mon Jun 14 12:01:31 1993
***************
*** 14,19 ****
--- 14,21 ----
   * 	'void update_screen(int new_console)'
   * 	'void blank_screen(void)'
   * 	'void unblank_screen(void)'
+  * 	'int con_get_num_lines(int console)'
+  * 	'int con_get_num_columns(int console)'
   * 
   * Hopefully this will be a rather complete VT102 implementation.
   *
***************
*** 35,40 ****
--- 37,51 ----
   * <g-hunt@ee.utah.edu>
   */
  
+ /*
+  * original multi-adapter mods by Tuomas J. Lukka (lukka@kruuna.helsinki.fi)
+  * version updating done by Cory West (corywest@rice.edu)
+  * dynamic assignment done by Jeff Grills (jefftep@cs.utexas.edu)
+  *
+  * patches now maintained by Jeff Grills jefftep@cs.utexas.edu)
+  * please mail me comments, questions, etc...
+  */
+ 
  #include <linux/sched.h>
  #include <linux/timer.h>
  #include <linux/tty.h>
***************
*** 50,75 ****
  #include <asm/segment.h>
  
  #include "vt_kern.h"
  
  #define NPAR 16
  
  extern void vt_init(void);
  extern void register_console(void (*proc)(const char *));
  
! unsigned long	video_num_columns;		/* Number of text columns	*/
! unsigned long	video_num_lines;		/* Number of test lines		*/
  
- static unsigned char	video_type;		/* Type of display being used	*/
- static unsigned long	video_mem_base;		/* Base of video memory		*/
- static unsigned long	video_mem_term;		/* End of video memory		*/
- static unsigned long	video_size_row;		/* Bytes per row		*/
- static unsigned char	video_page;		/* Initial video page		*/
- static unsigned short	video_port_reg;		/* Video register select port	*/
- static unsigned short	video_port_val;		/* Video register value port	*/
- static int can_do_color = 0;
- static int printable = 0;
- 
  static struct {
  	unsigned short	vc_video_erase_char;	/* Background erase character */
  	unsigned char	vc_attr;		/* Current attributes */
  	unsigned char	vc_def_color;		/* Default colors */
--- 61,103 ----
  #include <asm/segment.h>
  
  #include "vt_kern.h"
+ int set_window_size(struct tty_struct * tty, struct winsize * ws);
  
  #define NPAR 16
  
+ #ifdef CONFIG_DUALMON
+ #define NR_ADAPTERS 2
+ #define MONO_CONSOLE 7
+ #else
+ #define NR_ADAPTERS 1
+ #endif
+ 
  extern void vt_init(void);
  extern void register_console(void (*proc)(const char *));
  
! struct {
! 	unsigned long	ad_video_num_columns;	/* Number of text columns */
! 	unsigned long	ad_video_num_lines;	/* Number of test lines */
! 	unsigned char	ad_video_type;		/* Type of display being used */
! 	unsigned long	ad_video_mem_base;	/* Base of video memory */
! 	unsigned long	ad_video_mem_term;	/* End of video memory */
! 	unsigned long	ad_video_size_row;	/* Bytes per row */
! 	unsigned char	ad_video_page;		/* Initial video page */
! 	unsigned short 	ad_video_port_reg;	/* Video register select port */
! 	unsigned short	ad_video_port_val;	/* Video register value port */
! 	unsigned int	ad_video_screen_size;	/* Number of bytes on video screen */
! 	int		ad_can_do_color;	/* Is this adapter color or not */
! #ifdef CONFIG_DUALMON
! 	unsigned char	ad_current_console;
! 	unsigned char	*ad_display_desc;	/* type of this monitor */
! #endif
! } video_adapters[NR_ADAPTERS];
  
  static struct {
+ #ifdef CONFIG_DUALMON
+ 	unsigned char	vc_adapter;
+ 	unsigned char	vc_old_adapter;
+ #endif
  	unsigned short	vc_video_erase_char;	/* Background erase character */
  	unsigned char	vc_attr;		/* Current attributes */
  	unsigned char	vc_def_color;		/* Default colors */
***************
*** 86,91 ****
--- 114,120 ----
  	unsigned long	vc_npar,vc_par[NPAR];
  	unsigned long	vc_video_mem_start;	/* Start of video RAM		*/
  	unsigned long	vc_video_mem_end;	/* End of video RAM (sort of)	*/
+ 	unsigned short *vc_scrbuf;
  	unsigned long	vc_saved_x;
  	unsigned long	vc_saved_y;
  	/* mode flags */
***************
*** 118,127 ****
  	/* additional information is in vt_kern.h */
  } vc_cons [NR_CONSOLES];
  
! unsigned short *vc_scrbuf[NR_CONSOLES];
  static unsigned short * vc_scrmembuf;
  static int console_blanked = 0;
  
  #define origin		(vc_cons[currcons].vc_origin)
  #define scr_end		(vc_cons[currcons].vc_scr_end)
  #define pos		(vc_cons[currcons].vc_pos)
--- 147,175 ----
  	/* additional information is in vt_kern.h */
  } vc_cons [NR_CONSOLES];
  
! static int printable = 0;
  static unsigned short * vc_scrmembuf;
  static int console_blanked = 0;
  
+ #ifdef CONFIG_DUALMON
+ #define curradapt		(vc_cons[currcons].vc_adapter)
+ #define oldadapt		(vc_cons[currcons].vc_old_adapter)
+ #else
+ #define curradapt		0
+ #endif
+ 
+ #define video_num_columns 	(video_adapters[curradapt].ad_video_num_columns)
+ #define video_num_lines 	(video_adapters[curradapt].ad_video_num_lines)
+ #define video_type 		(video_adapters[curradapt].ad_video_type)
+ #define video_mem_base 		(video_adapters[curradapt].ad_video_mem_base)
+ #define video_mem_term 		(video_adapters[curradapt].ad_video_mem_term)
+ #define video_size_row 		(video_adapters[curradapt].ad_video_size_row)
+ #define video_page 		(video_adapters[curradapt].ad_video_page)
+ #define video_port_reg 		(video_adapters[curradapt].ad_video_port_reg)
+ #define video_port_val	 	(video_adapters[curradapt].ad_video_port_val)
+ #define video_screen_size 	(video_adapters[curradapt].ad_video_screen_size)
+ #define video_can_do_color 	(video_adapters[curradapt].ad_can_do_color)
+ 
  #define origin		(vc_cons[currcons].vc_origin)
  #define scr_end		(vc_cons[currcons].vc_scr_end)
  #define pos		(vc_cons[currcons].vc_pos)
***************
*** 143,148 ****
--- 191,197 ----
  #define saved_G1	(vc_cons[currcons].vc_saved_G1)
  #define video_mem_start	(vc_cons[currcons].vc_video_mem_start)
  #define video_mem_end	(vc_cons[currcons].vc_video_mem_end)
+ #define scrbuf		(vc_cons[currcons].vc_scrbuf)
  #define video_erase_char (vc_cons[currcons].vc_video_erase_char)	
  #define decscnm		(vc_cons[currcons].vc_decscnm)
  #define decom		(vc_cons[currcons].vc_decom)
***************
*** 185,191 ****
  #define lnm		VC_CRLF
  
  int blankinterval = 10*60*HZ;
- static int screen_size = 0;
  
  extern void kd_mksound(int freq, int time);
  
--- 234,239 ----
***************
*** 251,256 ****
--- 299,323 ----
  static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
  				       8,12,10,14, 9,13,11,15 };
  
+ int con_get_num_lines(int currcons)
+ {
+ 	return video_num_lines;
+ }
+ 
+ int con_get_num_columns(int currcons)
+ {
+ 	return video_num_columns;
+ }
+ 
+ int is_visible_con(int currcons)
+ {
+ #ifdef CONFIG_DUALMON
+ 	return (currcons == video_adapters[curradapt].ad_current_console);
+ #else
+ 	return (currcons == fg_console);
+ #endif
+ }
+ 
  /*
   * gotoxy() must verify all boundaries, because the arguments
   * might also be negative. If the given position is out of
***************
*** 289,295 ****
  static unsigned short __real_origin;
  static unsigned short __origin;
  
! static inline void __set_origin(unsigned short offset)
  {
  	cli();
  	__origin = offset;
--- 356,362 ----
  static unsigned short __real_origin;
  static unsigned short __origin;
  
! static inline void __set_origin(unsigned short offset, int currcons)
  {
  	cli();
  	__origin = offset;
***************
*** 300,306 ****
  	sti();
  }
  
! void scrollback(int lines)
  {
  	if (!lines)
  		lines = video_num_lines/2;
--- 367,373 ----
  	sti();
  }
  
! void scrollback(int lines, int currcons)
  {
  	if (!lines)
  		lines = video_num_lines/2;
***************
*** 308,317 ****
  	lines = __origin - lines;
  	if (lines < 0)
  		lines = 0;
! 	__set_origin(lines);
  }
  
! void scrollfront(int lines)
  {
  	if (!lines)
  		lines = video_num_lines/2;
--- 375,384 ----
  	lines = __origin - lines;
  	if (lines < 0)
  		lines = 0;
! 	__set_origin(lines, currcons);
  }
  
! void scrollfront(int lines, int currcons)
  {
  	if (!lines)
  		lines = video_num_lines/2;
***************
*** 319,335 ****
  	lines = __origin + lines;
  	if (lines > __real_origin)
  		lines = __real_origin;
! 	__set_origin(lines);
  }
  
  static void set_origin(int currcons)
  {
  	if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
  		return;
! 	if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
  		return;
  	__real_origin = (origin-video_mem_base) >> 1;
! 	__set_origin(__real_origin);
  }
  
  static inline void hide_cursor(int currcons)
--- 386,402 ----
  	lines = __origin + lines;
  	if (lines > __real_origin)
  		lines = __real_origin;
! 	__set_origin(lines, currcons);
  }
  
  static void set_origin(int currcons)
  {
  	if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
  		return;
! 	if (!is_visible_con(currcons) || console_blanked || vcmode == KD_GRAPHICS)
  		return;
  	__real_origin = (origin-video_mem_base) >> 1;
! 	__set_origin(__real_origin, currcons);
  }
  
  static inline void hide_cursor(int currcons)
***************
*** 342,348 ****
  
  static inline void set_cursor(int currcons)
  {
! 	if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
  		return;
  	if (__real_origin != __origin)
  		set_origin(__real_origin);
--- 409,415 ----
  
  static inline void set_cursor(int currcons)
  {
! 	if (!is_visible_con(currcons) || console_blanked || vcmode == KD_GRAPHICS)
  		return;
  	if (__real_origin != __origin)
  		set_origin(__real_origin);
***************
*** 357,366 ****
--- 424,436 ----
  	sti();
  }
  
+ static int cheese_video_num_columns;
  static void scrup(int currcons, unsigned int t, unsigned int b)
  {
  	int hardscroll = 1;
  
+ 	cheese_video_num_columns = video_num_columns;
+ 
  	if (b > video_num_lines || t >= b)
  		return;
  	if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
***************
*** 375,381 ****
  			__asm__("cld\n\t"
  				"rep\n\t"
  				"movsl\n\t"
! 				"movl _video_num_columns,%1\n\t"
  				"rep\n\t"
  				"stosw"
  				::"a" (video_erase_char),
--- 445,451 ----
  			__asm__("cld\n\t"
  				"rep\n\t"
  				"movsl\n\t"
! 				"movl _cheese_video_num_columns,%1\n\t"
  				"rep\n\t"
  				"stosw"
  				::"a" (video_erase_char),
***************
*** 400,406 ****
  		__asm__("cld\n\t"
  			"rep\n\t"
  			"movsl\n\t"
! 			"movl _video_num_columns,%%ecx\n\t"
  			"rep\n\t"
  			"stosw"
  			::"a" (video_erase_char),
--- 470,476 ----
  		__asm__("cld\n\t"
  			"rep\n\t"
  			"movsl\n\t"
! 			"movl _cheese_video_num_columns,%%ecx\n\t"
  			"rep\n\t"
  			"stosw"
  			::"a" (video_erase_char),
***************
*** 413,425 ****
  
  static void scrdown(int currcons, unsigned int t, unsigned int b)
  {
  	if (b > video_num_lines || t >= b)
  		return;
  	__asm__("std\n\t"
  		"rep\n\t"
  		"movsl\n\t"
  		"addl $2,%%edi\n\t"	/* %edi has been decremented by 4 */
! 		"movl _video_num_columns,%%ecx\n\t"
  		"rep\n\t"
  		"stosw\n\t"
  		"cld"
--- 483,497 ----
  
  static void scrdown(int currcons, unsigned int t, unsigned int b)
  {
+ 	cheese_video_num_columns = video_num_columns;
+ 
  	if (b > video_num_lines || t >= b)
  		return;
  	__asm__("std\n\t"
  		"rep\n\t"
  		"movsl\n\t"
  		"addl $2,%%edi\n\t"	/* %edi has been decremented by 4 */
! 		"movl _cheese_video_num_columns,%%ecx\n\t"
  		"rep\n\t"
  		"stosw\n\t"
  		"cld"
***************
*** 543,549 ****
  static void update_attr(int currcons)
  {
  	attr = color;
! 	if (can_do_color) {
  		if (underline)
  			attr = (attr & 0xf0) | ulcolor;
  		else if (intensity == 0)
--- 615,621 ----
  static void update_attr(int currcons)
  {
  	attr = color;
! 	if (video_can_do_color) {
  		if (underline)
  			attr = (attr & 0xf0) | ulcolor;
  		else if (intensity == 0)
***************
*** 555,561 ****
  		attr ^= 0x80;
  	if (intensity == 2)
  		attr ^= 0x08;
! 	if (!can_do_color) {
  		if (underline)
  			attr = (attr & 0xf8) | 0x01;
  		else if (intensity == 0)
--- 627,633 ----
  		attr ^= 0x80;
  	if (intensity == 2)
  		attr ^= 0x08;
! 	if (!video_can_do_color) {
  		if (underline)
  			attr = (attr & 0xf8) | 0x01;
  		else if (intensity == 0)
***************
*** 679,685 ****
  static void invert_screen(int currcons) {
  	unsigned char *p;
  
! 	if (can_do_color)
  		for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
  			*p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
  	else
--- 751,757 ----
  static void invert_screen(int currcons) {
  	unsigned char *p;
  
! 	if (video_can_do_color)
  		for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
  			*p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
  	else
***************
*** 744,757 ****
  {
  	switch(par[0]) {
  		case 1:	/* set color for underline mode */
! 			if (can_do_color && par[1] < 16) {
  				ulcolor = color_table[par[1]];
  				if (underline)
  					update_attr(currcons);
  			}
  			break;
  		case 2:	/* set color for half intensity mode */
! 			if (can_do_color && par[1] < 16) {
  				halfcolor = color_table[par[1]];
  				if (intensity == 0)
  					update_attr(currcons);
--- 816,829 ----
  {
  	switch(par[0]) {
  		case 1:	/* set color for underline mode */
! 			if (video_can_do_color && par[1] < 16) {
  				ulcolor = color_table[par[1]];
  				if (underline)
  					update_attr(currcons);
  			}
  			break;
  		case 2:	/* set color for half intensity mode */
! 			if (video_can_do_color && par[1] < 16) {
  				halfcolor = color_table[par[1]];
  				if (intensity == 0)
  					update_attr(currcons);
***************
*** 1274,1345 ****
   */
  long con_init(long kmem_start)
  {
  	char *display_desc = "????";
  	int currcons = 0;
  	long base;
  	int orig_x = ORIG_X;
  	int orig_y = ORIG_Y;
  	void console_print(const char * b);
  
  	vc_scrmembuf = (unsigned short *) kmem_start;
  	video_num_columns = ORIG_VIDEO_COLS;
  	video_size_row = video_num_columns * 2;
  	video_num_lines = ORIG_VIDEO_LINES;
  	video_page = ORIG_VIDEO_PAGE;
! 	screen_size = (video_num_lines * video_size_row);
! 	kmem_start += NR_CONSOLES * screen_size;
  	timer_table[BLANK_TIMER].fn = blank_screen;
  	timer_table[BLANK_TIMER].expires = 0;
  	if (blankinterval) {
  		timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
  		timer_active |= 1<<BLANK_TIMER;
  	}
! 	
! 	if (ORIG_VIDEO_MODE == 7)	/* Is this a monochrome display? */
! 	{
  		video_mem_base = 0xb0000;
  		video_port_reg = 0x3b4;
  		video_port_val = 0x3b5;
! 		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
! 		{
  			video_type = VIDEO_TYPE_EGAM;
  			video_mem_term = 0xb8000;
  			display_desc = "EGA+";
  		}
! 		else
! 		{
  			video_type = VIDEO_TYPE_MDA;
  			video_mem_term = 0xb2000;
  			display_desc = "*MDA";
  		}
  	}
! 	else				/* If not, it is color. */
! 	{
! 		can_do_color = 1;
  		video_mem_base = 0xb8000;
  		video_port_reg	= 0x3d4;
  		video_port_val	= 0x3d5;
! 		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
! 		{
  			video_type = VIDEO_TYPE_EGAC;
  			video_mem_term = 0xc0000;
  			display_desc = "EGA+";
  		}
! 		else
! 		{
  			video_type = VIDEO_TYPE_CGA;
  			video_mem_term = 0xba000;
  			display_desc = "*CGA";
  		}
  	}
  	
  	/* Initialize the variables used for scrolling (mostly EGA/VGA)	*/
  
  	base = (long)vc_scrmembuf;
  	for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
! 		pos = origin = video_mem_start = base;
! 		scr_end = video_mem_end = (base += screen_size);
! 		vc_scrbuf[currcons] = (unsigned short *) origin;
  		vcmode		= KD_TEXT;
  		vtmode.mode	= VT_AUTO;
  		vtmode.waitv	= 0;
--- 1352,1459 ----
   */
  long con_init(long kmem_start)
  {
+ 
+ #ifdef CONFIG_DUALMON
+ #define display_desc video_adapters[curradapt].ad_display_desc
+ 	int max_screen_size;
+ #else
+ #define max_screen_size video_screen_size
  	char *display_desc = "????";
+ #endif
+ 
  	int currcons = 0;
  	long base;
  	int orig_x = ORIG_X;
  	int orig_y = ORIG_Y;
  	void console_print(const char * b);
  
+ #ifdef CONFIG_DUALMON
+ 	/* -q- would like to make this more ... flexible */
+ 	currcons = MONO_CONSOLE;
+ 	curradapt = 1;
+ 	video_num_columns = 80;
+ 	video_size_row = video_num_columns * 2;
+ 	video_num_lines = 25;
+ 	video_page = 0;
+ 	video_screen_size = (video_num_lines * video_size_row);
+ 	max_screen_size = video_screen_size;
+ 	video_mem_base = 0xb0000;
+ 	video_port_reg = 0x3b4;
+ 	video_port_val = 0x3b5;
+ 	video_type = VIDEO_TYPE_MDA;
+ 	video_mem_term = 0xb2000;
+ 	display_desc = "*MDA";
+ 	currcons = 0;
+ 	curradapt = 0;
+ #endif
+ 
  	vc_scrmembuf = (unsigned short *) kmem_start;
  	video_num_columns = ORIG_VIDEO_COLS;
  	video_size_row = video_num_columns * 2;
  	video_num_lines = ORIG_VIDEO_LINES;
  	video_page = ORIG_VIDEO_PAGE;
! 	video_screen_size = (video_num_lines * video_size_row);
! 	kmem_start += NR_CONSOLES * video_screen_size;
  	timer_table[BLANK_TIMER].fn = blank_screen;
  	timer_table[BLANK_TIMER].expires = 0;
  	if (blankinterval) {
  		timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
  		timer_active |= 1<<BLANK_TIMER;
  	}
! 
! 	if (ORIG_VIDEO_MODE == 7) {	/* Is this a monochrome display? */
  		video_mem_base = 0xb0000;
  		video_port_reg = 0x3b4;
  		video_port_val = 0x3b5;
! 		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
  			video_type = VIDEO_TYPE_EGAM;
  			video_mem_term = 0xb8000;
  			display_desc = "EGA+";
  		}
! 		else {
  			video_type = VIDEO_TYPE_MDA;
  			video_mem_term = 0xb2000;
  			display_desc = "*MDA";
  		}
  	}
! 	else {				/* If not, it is color. */
! 		video_can_do_color = 1;
  		video_mem_base = 0xb8000;
  		video_port_reg	= 0x3d4;
  		video_port_val	= 0x3d5;
! 		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
  			video_type = VIDEO_TYPE_EGAC;
  			video_mem_term = 0xc0000;
  			display_desc = "EGA+";
  		}
! 		else {
  			video_type = VIDEO_TYPE_CGA;
  			video_mem_term = 0xba000;
  			display_desc = "*CGA";
  		}
  	}
  	
+ #ifdef CONFIG_DUALMON
+ 	video_adapters[0].ad_current_console = 0;
+ 	video_adapters[1].ad_current_console = MONO_CONSOLE;
+ 	if ( video_screen_size > max_screen_size )
+ 	  max_screen_size = video_screen_size;
+ #endif
+ 
  	/* Initialize the variables used for scrolling (mostly EGA/VGA)	*/
  
  	base = (long)vc_scrmembuf;
  	for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
! #ifdef CONFIG_DUALMON
! 		if ( currcons != MONO_CONSOLE )
! 			curradapt = oldadapt = 0;
! 		else
! 			curradapt = oldadapt = 1;
! #endif		
! 		pos		= origin = video_mem_start = base;
! 		scr_end		= video_mem_end = (base + video_screen_size);
! 		base += max_screen_size;
! 		scrbuf		= (unsigned short *) origin;
  		vcmode		= KD_TEXT;
  		vtmode.mode	= VT_AUTO;
  		vtmode.waitv	= 0;
***************
*** 1365,1376 ****
  	gotoxy(currcons,orig_x,orig_y);
  	update_screen(fg_console);
  	printable = 1;
  	printk("Console: %s %s %dx%d, %d virtual consoles\n",
! 		can_do_color?"colour":"mono",
  		display_desc,
  		video_num_columns,video_num_lines,
  		NR_CONSOLES);
  	register_console(console_print);
  	return kmem_start;
  }
  
--- 1479,1515 ----
  	gotoxy(currcons,orig_x,orig_y);
  	update_screen(fg_console);
  	printable = 1;
+ 
+ #ifndef CONFIG_DUALMON
  	printk("Console: %s %s %dx%d, %d virtual consoles\n",
! 		video_can_do_color?"colour":"mono",
! 		display_desc,
! 		video_num_columns,video_num_lines,
! 		NR_CONSOLES);
! #else
! 	printk("Console: %s %s %dx%d & mono *MDA 80x25, %d virtual consoles\n",
! 		video_can_do_color?"colour":"mono",
  		display_desc,
  		video_num_columns,video_num_lines,
  		NR_CONSOLES);
+ #endif
+ 
  	register_console(console_print);
+ 
+ #ifdef CONFIG_DUALMON
+ 	currcons = MONO_CONSOLE;
+ 	video_mem_start = video_mem_base;
+ 	video_mem_end = video_mem_term;
+ 	origin = video_mem_start;
+ 	scr_end	= video_mem_start + video_num_lines * video_size_row;
+ 	gotoxy(currcons,0,0);
+ 	save_cur(currcons);
+ 	gotoxy(currcons,orig_x,orig_y);
+ 	update_screen(MONO_CONSOLE);
+ 	printk("*MDA secondary adapter\n");
+ 	update_screen(0);
+ #endif	
+ 
  	return kmem_start;
  }
  
***************
*** 1382,1419 ****
  {
  }
  
  static void get_scrmem(int currcons)
  {
! 	memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
! 	video_mem_start = (unsigned long)vc_scrbuf[currcons];
  	origin 	= video_mem_start;
! 	scr_end = video_mem_end = video_mem_start+screen_size;
  	pos = origin + y*video_size_row + (x<<1);
  }
  
  static void set_scrmem(int currcons)
  {
  	video_mem_start = video_mem_base;
  	video_mem_end = video_mem_term;
  	origin	= video_mem_start;
! 	scr_end	= video_mem_start + screen_size;
  	pos = origin + y*video_size_row + (x<<1);
- 	memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
  }
  
  void blank_screen(void)
  {
  	if (console_blanked)
  		return;
  	timer_table[BLANK_TIMER].fn = unblank_screen;
  	get_scrmem(fg_console);
  	hide_cursor(fg_console);
- 	console_blanked = 1;
  	memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
  }
  
  void unblank_screen(void)
  {
  	if (!console_blanked)
  		return;
  	timer_table[BLANK_TIMER].fn = blank_screen;
--- 1521,1652 ----
  {
  }
  
+ #ifdef CONFIG_DUALMON
+ int set_adapter(int currcons, int ad)
+ {
+ 	/* ignore swap attempts */
+ 	if (is_visible_con(currcons) && (curradapt != ad))
+ 		return -1;
+ 
+ 	if ( curradapt != ad ) {
+ 		oldadapt = curradapt;
+ 		curradapt = ad;
+ 		top = 0;
+ 		bottom = video_num_lines;
+ 	}
+ 	return currcons;
+ }
+ 
+ int get_fg_console_con(int cons)
+ {
+ 	return video_adapters[vc_cons[cons].vc_adapter].ad_current_console;
+ }
+ 
+ /* this should be done last because it will reset old_adapter */
+ void resize_console(int currcons)
+ {
+ 	struct winsize ws;
+ 	extern int set_window_size(struct tty_struct *, struct winsize *);
+ 
+ 	if ( oldadapt != curradapt ) {
+ 		oldadapt = curradapt;
+ 		ws.ws_row = video_num_lines;
+ 		ws.ws_col = video_num_columns;
+ 		set_window_size(TTY_TABLE(0), &ws);
+ 	}
+ }
+ #endif CONFIG_DUALMON
+ 
  static void get_scrmem(int currcons)
  {
! 	memcpy((void *)scrbuf, (void *)origin, video_screen_size);
! 	video_mem_start = (unsigned long)scrbuf;
  	origin 	= video_mem_start;
! 	scr_end = video_mem_end = video_mem_start+video_screen_size;
  	pos = origin + y*video_size_row + (x<<1);
  }
  
  static void set_scrmem(int currcons)
  {
+ #ifdef CONFIG_DUALMON
+ 	int old_cols, old_rows, yl, min_rows, cpline, diffl;
+ 	unsigned short *pfrom, *pto;
+ #endif
+ 
  	video_mem_start = video_mem_base;
  	video_mem_end = video_mem_term;
  	origin	= video_mem_start;
! 	scr_end	= video_mem_start + video_screen_size;
! 
! #ifdef CONFIG_DUALMON
! 	old_cols = video_adapters[oldadapt].ad_video_num_columns;
! 	old_rows = video_adapters[oldadapt].ad_video_num_lines;
! 	if ((video_num_columns != old_cols) || (video_num_lines != old_rows)) {
! 
! 		csi_J(currcons, 2);
! 		
! 		pto = (void *)video_mem_base;
! 		pfrom = scrbuf;
! 		if (old_rows <= video_num_lines)
! 			min_rows = old_rows;
! 		else
! 			if (y >= (min_rows = video_num_lines)) {
! 				diffl = (y - video_num_lines) + 1;
! 				pfrom += (diffl * old_cols);
! 				y -= diffl;
! 			}
! 
! 		if (old_cols < video_num_columns)
! 			cpline = video_adapters[oldadapt].ad_video_size_row;
! 		else {
! 			cpline = video_size_row;
! 			if (x >= video_num_columns)
! 				x = video_num_columns - 1;
! 		}
! 
! 		if (old_cols == video_num_columns)
! 			memcpy((void *)pto, (void *)pfrom, min_rows * video_size_row);
! 		else
! 			for (yl = 0; yl < min_rows; yl++) {
! 				memcpy((void *)pto, (void *)pfrom, cpline);
! 				pto += video_num_columns;
! 				pfrom += old_cols;
! 			}
! 	}
! 	else
! #endif
! 		memcpy((void *)video_mem_base, (void *)scrbuf, video_screen_size);
  	pos = origin + y*video_size_row + (x<<1);
  }
  
  void blank_screen(void)
  {
+ #ifdef CONFIG_DUALMON
+ 	int ad, currcons;
+ #endif
  	if (console_blanked)
  		return;
  	timer_table[BLANK_TIMER].fn = unblank_screen;
+ #ifdef CONFIG_DUALMON
+ 	for(ad = 0; ad < 2; ad++) {
+ 		currcons = video_adapters[ad].ad_current_console;
+ 		get_scrmem(currcons);
+ 		hide_cursor(currcons);
+ 		memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
+ 	}
+ #else
  	get_scrmem(fg_console);
  	hide_cursor(fg_console);
  	memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
+ #endif
+ 	console_blanked = 1;
  }
  
  void unblank_screen(void)
  {
+ #ifdef CONFIG_DUALMON
+ 	int ad, currcons;
+ #endif
  	if (!console_blanked)
  		return;
  	timer_table[BLANK_TIMER].fn = blank_screen;
***************
*** 1422,1431 ****
--- 1655,1690 ----
  		timer_active |= 1<<BLANK_TIMER;
  	}
  	console_blanked = 0;
+ #ifdef CONFIG_DUALMON
+ 	for(ad = 0; ad < NR_ADAPTERS; ad++) {
+ 		currcons = video_adapters[ad].ad_current_console;
+ 		set_scrmem(currcons);
+ 		set_origin(currcons);
+ 		set_cursor(currcons);
+ 	}
+ #else
  	set_scrmem(fg_console);
  	set_origin(fg_console);
  	set_cursor(fg_console);
+ #endif
+ }
+ 
+ #ifdef CONFIG_DUALMON
+ /*
+  *	void change_screen(int new_console) 
+  *	
+  *	called when the screen is already the current adapter's fg_console but
+  *	not the global fg_console
+  */
+ 
+ void change_screen(int new_console) 
+ {
+ 	if (!is_visible_con(new_console))
+ 		return;
+ 	fg_console = new_console;
+ 	set_leds();
  }
+ #endif
  
  void update_screen(int new_console)
  {
***************
*** 1433,1444 ****
  
  	if (new_console == fg_console || lock)
  		return;
  	lock = 1;
  	kbdsave(new_console);
! 	get_scrmem(fg_console); 
  	fg_console = new_console;
! 	set_scrmem(fg_console); 
! 	set_origin(fg_console);
  	set_cursor(new_console);
  	set_leds();
  	lock = 0;
--- 1692,1719 ----
  
  	if (new_console == fg_console || lock)
  		return;
+ 
+ #ifdef CONFIG_DUALMON
+ 	if (is_visible_con(new_console)) {
+ 		fg_console = new_console;
+ 		set_leds();
+ 		return;
+ 	}
+ #endif
+ 
  	lock = 1;
  	kbdsave(new_console);
! 
! #ifdef CONFIG_DUALMON
! 	get_scrmem(video_adapters[vc_cons[new_console].vc_adapter].ad_current_console);
! 	video_adapters[vc_cons[new_console].vc_adapter].ad_current_console = new_console;
! #else
! 	get_scrmem(fg_console);
! #endif
! 
  	fg_console = new_console;
! 	set_scrmem(new_console); 
! 	set_origin(new_console);
  	set_cursor(new_console);
  	set_leds();
  	lock = 0;
***************
*** 1449,1454 ****
--- 1724,1730 ----
  	char *sptr, *buf = (char *)arg;
  	int currcons, l;
  
+ 	/* -q- need to fix this */
  	if (!suser())
  		return -EPERM;
  	l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
diff -c --recursive linux/kernel/chr_drv_orig/keyboard.c linux/kernel/chr_drv/keyboard.c
*** linux/kernel/chr_drv_orig/keyboard.c	Mon Jun 14 02:26:23 1993
--- linux/kernel/chr_drv/keyboard.c	Mon Jun 14 11:46:44 1993
***************
*** 46,56 ****
  #include <asm/io.h>
  #include <asm/system.h>
  
  extern void do_keyboard_interrupt(void);
  extern void ctrl_alt_del(void);
  extern void change_console(unsigned int new_console);
! extern void scrollback(int);
! extern void scrollfront(int);
  
  #define fake_keyboard_interrupt() \
  __asm__ __volatile__("int $0x21")
--- 46,63 ----
  #include <asm/io.h>
  #include <asm/system.h>
  
+ #ifdef CONFIG_DUALMON
+ #define RIGHT_ADAPTER 0
+ #define LEFT_ADAPTER 1
+ void resize_console(int);
+ int set_adapter(int, int);
+ #endif
+ 
  extern void do_keyboard_interrupt(void);
  extern void ctrl_alt_del(void);
  extern void change_console(unsigned int new_console);
! extern void scrollback(int, int);
! extern void scrollfront(int, int);
  
  #define fake_keyboard_interrupt() \
  __asm__ __volatile__("int $0x21")
***************
*** 457,463 ****
--- 464,475 ----
  {
  	if (up_flag)
  		return;
+ 
+ #ifdef CONFIG_DUALMON
+ 	want_console = set_adapter(value, RIGHT_ADAPTER);
+ #else
  	want_console = value;
+ #endif
  }
  
  static char *func_table[] = {
***************
*** 479,496 ****
  		return;
  	if (kbd_flags & SHIFT_KEYS) {
  		if (value == KVAL(K_PGDN)) {
! 			scrollfront(0);
  			return;
  		}
  		if (value == KVAL(K_PGUP)) {
! 			scrollback(0);
  			return;
  		}
  	}
  	if (kbd_flags & ALT_KEYS) {
  		want_console = value;
  		return;
  	}
  	puts_queue(func_table[value]);
  }
  
--- 491,514 ----
  		return;
  	if (kbd_flags & SHIFT_KEYS) {
  		if (value == KVAL(K_PGDN)) {
! 			scrollfront(0, fg_console);
  			return;
  		}
  		if (value == KVAL(K_PGUP)) {
! 			scrollback(0, fg_console);
  			return;
  		}
  	}
+ 
  	if (kbd_flags & ALT_KEYS) {
+ #ifdef CONFIG_DUALMON
+ 		want_console = set_adapter(value, LEFT_ADAPTER);
+ #else
  		want_console = value;
+ #endif
  		return;
  	}
+ 
  	puts_queue(func_table[value]);
  }
  
***************
*** 696,701 ****
--- 714,722 ----
  		if (want_console != fg_console) {
  			last_console = fg_console;
  			change_console(want_console);
+ #ifdef CONFIG_DUALMON
+ 			resize_console(want_console);
+ #endif
  		}
  		want_console = -1;
  	}
diff -c --recursive linux/kernel/chr_drv_orig/tty_io.c linux/kernel/chr_drv/tty_io.c
*** linux/kernel/chr_drv_orig/tty_io.c	Mon Jun 14 02:26:23 1993
--- linux/kernel/chr_drv/tty_io.c	Mon Jun 14 11:46:44 1993
***************
*** 79,84 ****
--- 79,90 ----
  static int tty_open(struct inode *, struct file *);
  static void tty_release(struct inode *, struct file *);
  
+ int con_get_num_lines(int console);
+ int con_get_num_columns(int console);
+ int change_screen(int);
+ int is_visible_con(int currcons);
+ int get_fg_console_con(int cons);
+ 
  int tty_register_ldisc(int disc, struct tty_ldisc *new)
  {
  	if (disc < N_TTY || disc >= NR_LDISCS)
***************
*** 316,331 ****
  void complete_change_console(unsigned int new_console)
  {
  	unsigned char old_vc_mode;
  
! 	if (new_console == fg_console || new_console >= NR_CONSOLES)
  		return;
  
  	/*
  	 * If we're switching, we could be going from KD_GRAPHICS to
  	 * KD_TEXT mode or vice versa, which means we need to blank or
  	 * unblank the screen later.
  	 */
! 	old_vc_mode = vt_cons[fg_console].vc_mode;
  	update_screen(new_console);
  
  	/*
--- 322,348 ----
  void complete_change_console(unsigned int new_console)
  {
  	unsigned char old_vc_mode;
+ 	unsigned char ad_fg_console;
  
! 	if (new_console >= NR_CONSOLES)
! 		return;
! 	if (is_visible_con(new_console)) {
! 		change_screen(new_console);
  		return;
+ 	}
  
+ #ifdef CONFIG_DUALMON
+ 	ad_fg_console = get_fg_console_con(new_console);
+ #else
+ 	ad_fg_console = fg_console;
+ #endif
+ 	
  	/*
  	 * If we're switching, we could be going from KD_GRAPHICS to
  	 * KD_TEXT mode or vice versa, which means we need to blank or
  	 * unblank the screen later.
  	 */
! 	old_vc_mode = vt_cons[ad_fg_console].vc_mode;
  	update_screen(new_console);
  
  	/*
***************
*** 391,398 ****
   */
  void change_console(unsigned int new_console)
  {
! 	if (new_console == fg_console || new_console >= NR_CONSOLES)
  		return;
  
  	/*
  	 * If this vt is in process mode, then we need to handshake with
--- 408,427 ----
   */
  void change_console(unsigned int new_console)
  {
! 	unsigned char ad_fg_console;
! 
! 	if (new_console >= NR_CONSOLES)
! 		return;
! 	if (is_visible_con(new_console)) {
! 		change_screen(new_console);
  		return;
+ 	}
+ 
+ #ifdef CONFIG_DUALMON
+ 	ad_fg_console = get_fg_console_con(new_console);
+ #else
+ 	ad_fg_console = fg_console;
+ #endif
  
  	/*
  	 * If this vt is in process mode, then we need to handshake with
***************
*** 409,423 ****
  	 * the user waits just the right amount of time :-) and revert the
  	 * vt to auto control.
  	 */
! 	if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS)
  	{
  		/*
  		 * Send the signal as privileged - kill_proc() will
  		 * tell us if the process has gone or something else
  		 * is awry
  		 */
! 		if (kill_proc(vt_cons[fg_console].vt_pid,
! 			      vt_cons[fg_console].vt_mode.relsig,
  			      1) == 0)
  		{
  			/*
--- 438,452 ----
  	 * the user waits just the right amount of time :-) and revert the
  	 * vt to auto control.
  	 */
! 	if (vt_cons[ad_fg_console].vt_mode.mode == VT_PROCESS)
  	{
  		/*
  		 * Send the signal as privileged - kill_proc() will
  		 * tell us if the process has gone or something else
  		 * is awry
  		 */
! 		if (kill_proc(vt_cons[ad_fg_console].vt_pid,
! 			      vt_cons[ad_fg_console].vt_mode.relsig,
  			      1) == 0)
  		{
  			/*
***************
*** 425,431 ****
  			 * return. The process needs to send us a
  			 * VT_RELDISP ioctl to complete the switch.
  			 */
! 			vt_cons[fg_console].vt_newvt = new_console;
  			return;
  		}
  
--- 454,460 ----
  			 * return. The process needs to send us a
  			 * VT_RELDISP ioctl to complete the switch.
  			 */
! 			vt_cons[ad_fg_console].vt_newvt = new_console;
  			return;
  		}
  
***************
*** 438,452 ****
  		 * this outside of VT_PROCESS but there is no single process
  		 * to account for and tracking tty count may be undesirable.
  		 */
! 		vt_cons[fg_console].vc_mode = KD_TEXT;
! 		clr_vc_kbd_flag(kbd_table + fg_console, VC_RAW);
! 		vt_cons[fg_console].vt_mode.mode = VT_AUTO;
! 		vt_cons[fg_console].vt_mode.waitv = 0;
! 		vt_cons[fg_console].vt_mode.relsig = 0;
! 		vt_cons[fg_console].vt_mode.acqsig = 0;
! 		vt_cons[fg_console].vt_mode.frsig = 0;
! 		vt_cons[fg_console].vt_pid = -1;
! 		vt_cons[fg_console].vt_newvt = -1;
  		/*
  		 * Fall through to normal (VT_AUTO) handling of the switch...
  		 */
--- 467,481 ----
  		 * this outside of VT_PROCESS but there is no single process
  		 * to account for and tracking tty count may be undesirable.
  		 */
! 		vt_cons[ad_fg_console].vc_mode = KD_TEXT;
! 		clr_vc_kbd_flag(kbd_table + ad_fg_console, VC_RAW);
! 		vt_cons[ad_fg_console].vt_mode.mode = VT_AUTO;
! 		vt_cons[ad_fg_console].vt_mode.waitv = 0;
! 		vt_cons[ad_fg_console].vt_mode.relsig = 0;
! 		vt_cons[ad_fg_console].vt_mode.acqsig = 0;
! 		vt_cons[ad_fg_console].vt_mode.frsig = 0;
! 		vt_cons[ad_fg_console].vt_pid = -1;
! 		vt_cons[ad_fg_console].vt_newvt = -1;
  		/*
  		 * Fall through to normal (VT_AUTO) handling of the switch...
  		 */
***************
*** 455,461 ****
  	/*
  	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
  	 */
! 	if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
  		return;
  
  	complete_change_console(new_console);
--- 484,490 ----
  	/*
  	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
  	 */
! 	if (vt_cons[ad_fg_console].vc_mode == KD_GRAPHICS)
  		return;
  
  	complete_change_console(new_console);
***************
*** 1529,1536 ****
  	tty->winsize.ws_col = 0;
  	if (IS_A_CONSOLE(line)) {
  		tty->open = con_open;
! 		tty->winsize.ws_row = video_num_lines;
! 		tty->winsize.ws_col = video_num_columns;
  	} else if IS_A_SERIAL(line) {
  		tty->open = rs_open;
  	} else if IS_A_PTY(line) {
--- 1558,1565 ----
  	tty->winsize.ws_col = 0;
  	if (IS_A_CONSOLE(line)) {
  		tty->open = con_open;
! 		tty->winsize.ws_row = con_get_num_lines(line - 1);
! 		tty->winsize.ws_col = con_get_num_columns(line -1);
  	} else if IS_A_SERIAL(line) {
  		tty->open = rs_open;
  	} else if IS_A_PTY(line) {
diff -c --recursive linux/kernel/chr_drv_orig/tty_ioctl.c linux/kernel/chr_drv/tty_ioctl.c
*** linux/kernel/chr_drv_orig/tty_ioctl.c	Mon Jun 14 02:26:23 1993
--- linux/kernel/chr_drv/tty_ioctl.c	Mon Jun 14 11:53:46 1993
***************
*** 238,244 ****
  	return 0;
  }
  
! static int set_window_size(struct tty_struct * tty, struct winsize * ws)
  {
  	int i,changed;
  	char c, * tmp;
--- 238,244 ----
  	return 0;
  }
  
! int set_window_size(struct tty_struct * tty, struct winsize * ws)
  {
  	int i,changed;
  	char c, * tmp;
