Date: Mon, 24 Nov 1997 10:02:55 +0100 (CET)
From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
To: Linux/m68k <linux-m68k@lists.linux-m68k.org>
Subject: L68K: Frame buffer device updates
Sender: owner-linux-m68k@phil.uni-sb.de


Just to get all my trees in sync with yours (and vice versa)...

  - moved font.h from <asm/font.h> to drivers/video
  - use the timer for cursor flashing if no vblank is available (or if we don't
    know how to use it)
  - basic scrollback support (doesn't work with fbcon yet)
  - vgacon.c: `abstract' VGA text console driver
  - fixes for non-m68k (read: PPC)
  - offb.c: Open Firmware based frame buffer device (for Pmac and CHRP)
  - tgafb.c: DEC 21030 TGA frame buffer device (_very_ experimental)

Anyone who'd like to write a fbcon-cfb32? Without that tgafb.c won't work on
24plane or 24plusZ boards for sure...

--- m68k-2.1.64/include/linux/fb.h.orig	Mon Nov 17 22:26:56 1997
+++ m68k-2.1.64/include/linux/fb.h	Sun Nov 23 23:38:40 1997
@@ -76,6 +76,8 @@
 #define FB_ACCEL_AMIGABLITT	2	/* Amiga Blitter                */
 #define FB_ACCEL_CYBERVISION	3	/* Cybervision64 (S3 Trio64)    */
 #define FB_ACCEL_RETINAZ3	4	/* RetinaZ3 (NCR77C32BLT)       */
+#define FB_ACCEL_MACH64		6	/* ATI Mach 64			*/
+#define FB_ACCEL_TGA		7	/* DEC 21030 TGA		*/
 
 #define FB_SYNC_HOR_HIGH_ACT	1	/* horizontal sync high active	*/
 #define FB_SYNC_VERT_HIGH_ACT	2	/* vertical sync high active	*/
--- m68k-2.1.64/include/linux/console.h.orig	Mon Nov 17 22:16:11 1997
+++ m68k-2.1.64/include/linux/console.h	Sun Nov 23 23:33:09 1997
@@ -41,6 +41,7 @@
 	int	(*con_get_font)(struct vc_data *, int *, int *, char *);
 	int	(*con_set_font)(struct vc_data *, int, int, char *);
 	int	(*con_set_palette)(struct vc_data *, unsigned char *);
+	int	(*con_scrolldelta)(int);
 };
 
 extern struct consw *conswitchp;
--- m68k-2.1.64/include/asm-m68k/font.h.orig	Mon Nov 17 22:29:26 1997
+++ m68k-2.1.64/include/asm-m68k/font.h	Sun Nov 23 23:33:27 1997
@@ -1,35 +0,0 @@
-/*
- *  asm-m68k/font.h -- `Soft' font definitions
- *
- *  Created 1995 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#ifndef _ASM_M68K_FONT_H_
-#define _ASM_M68K_FONT_H_
-
-#include <linux/types.h>
-
-
-   /*
-    *    Find a font with a specific name
-    */
-
-extern int findsoftfont(char *name, int *width, int *height, u_char *data[]);
-
-
-   /*
-    *    Get the default font for a specific screen size
-    */
-
-extern void getdefaultfont(int xres, int yres, char *name[], int *width,
-                           int *height, u_char *data[]);
-
-
-/* Max. length for the name of a predefined font */
-#define MAX_FONT_NAME	32
-
-#endif /* _ASM_M68K_FONT_H_ */
--- m68k-2.1.64/drivers/char/fbmem.c.orig	Mon Nov 17 22:00:31 1997
+++ m68k-2.1.64/drivers/char/fbmem.c	Sun Nov 23 23:49:10 1997
@@ -27,7 +27,9 @@
 #include <linux/kerneld.h>
 #endif
 
+#ifdef __mc68000__
 #include <asm/setup.h>
+#endif
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -51,6 +53,7 @@
 extern void clgen_video_setup(char *options, int *ints);
 extern unsigned long virtual_fb_init(unsigned long mem_start);
 extern void vfb_video_setup(char *options, int *ints);
+extern unsigned long offb_init(unsigned long mem_start);
 extern unsigned long Mach64_fb_init(unsigned long mem_start);
 extern void Mach64_video_setup(char *options, int *ints);
 extern void resolver_video_setup(char *options, int *ints);
@@ -80,6 +83,9 @@
 #ifdef CONFIG_FB_VIRTUAL
 	{ "vfb", virtual_fb_init, vfb_video_setup },
 #endif
+#ifdef CONFIG_FB_OPEN_FIRMWARE
+	{ "offb", offb_init, NULL },
+#endif
 #ifdef CONFIG_GSP_RESOLVER
 	/* Not a real frame buffer device... */
 	{ "resolver", NULL, resolver_video_setup },
@@ -233,7 +239,7 @@
 	case FBIOGET_VSCREENINFO:
 		fbidx=GET_FB_IDX(inode->i_rdev);
 		vidx=GET_FB_VAR_IDX(inode->i_rdev);
-		if (! vidx) /* ask device driver for current */ {
+		if (! vidx) {	/* ask device driver for current */
 			if ((i = fb->fb_get_var(&var, PROC_CONSOLE())))
 				return i;
 		} else
@@ -333,10 +339,13 @@
 	}
 	if ((vma->vm_end - vma->vm_start + vma->vm_offset) > len)
 		return -EINVAL;
-	vma->vm_offset += __pa(start);
+#ifndef __powerpc__
+	start = (unsigned char *)__pa(start);
+#endif
+	vma->vm_offset += (unsigned long)start;
 	if (vma->vm_offset & ~PAGE_MASK)
 		return -ENXIO;
-#ifdef __mc68000__
+#if defined(__mc68000__)
 	if (CPU_IS_020_OR_030)
 		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
 	if (CPU_IS_040_OR_060) {
@@ -344,6 +353,8 @@
 		/* Use no-cache mode, serialized */
 		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
 	}
+#elif defined(__powerpc__)
+	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
 #else
 #warning What do we have to do here??
 #endif
--- m68k-2.1.64/drivers/video/Config.in.orig	Mon Nov 17 22:00:35 1997
+++ m68k-2.1.64/drivers/video/Config.in	Sun Nov 23 23:33:08 1997
@@ -22,6 +22,9 @@
   if [ "$CONFIG_ATARI" = "y" ]; then
     bool 'Atari native chipset support' CONFIG_FB_ATARI
 #    tristate 'Mach64 Frame Buffer support' CONFIG_FB_MACH64
+  fi
+  if [ "$CONFIG_CHRP" = "y" -o "$CONFIG_PMAC" = "y" ]; then
+    bool 'Open Firmware frame buffer device support' CONFIG_FB_OPEN_FIRMWARE
   fi 
   tristate 'Virtual Frame Buffer support' CONFIG_FB_VIRTUAL
 
@@ -52,8 +55,13 @@
       define_bool CONFIG_FBCON_IPLAN2P4 y
       define_bool CONFIG_FBCON_IPLAN2P8 y
     fi
-    if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
+    if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o \
+	 "$CONFIG_FB_OPEN_FIRMWARE" = "y" -o \
+	 "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
       define_bool CONFIG_FBCON_CFB8 y
+    fi
+    if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o \
+	 "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
       define_bool CONFIG_FBCON_CFB16 y
     fi
     if [ "$CONFIG_FB_CYBER" = "y" -o "$CONFIG_FB_CYBER" = "m" ]; then
--- m68k-2.1.64/drivers/video/Makefile.orig	Mon Nov 17 22:00:35 1997
+++ m68k-2.1.64/drivers/video/Makefile	Sun Nov 23 23:33:08 1997
@@ -19,13 +19,15 @@
 MX_OBJS  :=
 MOD_LIST_NAME := VIDEO_MODULES
 
-# Frame buffer devices
+# Frame Buffer Console
 
 ifeq ($(CONFIG_FB),y)
   L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o
   LX_OBJS += fbcon.o fbcmap.o
 endif
 
+# Frame buffer devices
+
 ifeq ($(CONFIG_APOLLO),y)
 L_OBJS += dn_fb.o
 endif
@@ -70,6 +72,10 @@
   endif
 endif
 
+ifeq ($(CONFIG_FB_OPEN_FIRMWARE),y)
+L_OBJS += offb.o
+endif
+
 ifeq ($(CONFIG_FB_MACH64),y)
 L_OBJS += mach64fb.o
 else
@@ -78,6 +84,10 @@
   endif
 endif
 
+ifeq ($(CONFIG_FB_TGA),y)
+L_OBJS += tgafb.o
+endif
+
 # Low level drivers
 
 ifeq ($(CONFIG_FBCON_AFB),y)
@@ -168,8 +178,16 @@
   endif
 endif
 
+# GSP Console
+
 ifdef CONFIG_AMIGA_GSP
 L_OBJS := $(L_OBJS) gspcon.o gspcore.o
+endif
+
+# VGA Console
+
+ifdef CONFIG_VGA_CONSOLE
+L_OBJS := $(L_OBJS) vgacon.o
 endif
 
 include $(TOPDIR)/Rules.make
--- m68k-2.1.64/drivers/video/atafb.c.orig	Thu Nov 20 22:51:52 1997
+++ m68k-2.1.64/drivers/video/atafb.c	Sun Nov 23 23:33:09 1997
@@ -47,6 +47,7 @@
 #define ATAFB_EXT
 #define ATAFB_FALCON
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
--- m68k-2.1.64/drivers/video/dn_fb.c.orig	Thu Nov 20 22:52:43 1997
+++ m68k-2.1.64/drivers/video/dn_fb.c	Sun Nov 23 23:33:09 1997
@@ -11,8 +11,6 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/irq.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
 #include <asm/apollohw.h>
 #include <linux/fb.h>
 #include <linux/module.h>
--- m68k-2.1.64/drivers/video/fbcon.c.orig	Mon Nov 17 22:00:36 1997
+++ m68k-2.1.64/drivers/video/fbcon.c	Sun Nov 23 23:33:09 1997
@@ -42,6 +42,7 @@
  *
  *	  o cyber	 CyberVision64 packed pixels (accelerated)
  *	  o retz3	 Retina Z3 packed pixels (accelerated)
+ *	  o mach64	 ATI Mach 64 packed pixels (accelerated)
  *
  *  To do:
  *
@@ -55,6 +56,8 @@
  *  more details.
  */
 
+#define SUPPORT_SCROLLBACK	0
+#define FLASHING_CURSOR		1
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -75,10 +78,7 @@
 #include <linux/kerneld.h>
 #endif
 
-#include <asm/setup.h>
 #include <asm/irq.h>
-#include <asm/font.h>
-#include <asm/machdep.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #ifdef CONFIG_AMIGA
@@ -88,9 +88,14 @@
 #ifdef CONFIG_ATARI
 #include <asm/atariints.h>
 #endif
+#ifdef __mc68000__
+#include <asm/machdep.h>
+#include <asm/setup.h>
+#endif
 #include <asm/linux_logo.h>
 
 #include "fbcon.h"
+#include "font.h"
 
 
 struct display fb_display[MAX_NR_CONSOLES];
@@ -99,6 +104,7 @@
 /* ++Geert: Sorry, no hardware cursor support at the moment;
    use Atari alike software cursor */
 
+#if FLASHING_CURSOR
 static int cursor_drawn = 0;
 
 #define CURSOR_DRAW_DELAY		(2)
@@ -106,6 +112,7 @@
 /* # VBL ints between cursor state changes */
 #define AMIGA_CURSOR_BLINK_RATE		(20)
 #define ATARI_CURSOR_BLINK_RATE		(42)
+#define DEFAULT_CURSOR_BLINK_RATE	(20)
 
 static int vbl_cursor_cnt = 0;
 static int cursor_on = 0;
@@ -119,6 +126,7 @@
     cursor_drawn = 0;
     return(cursor_was_drawn);
 }
+#endif
 
 /*
  *  Scroll Method
@@ -155,6 +163,7 @@
 static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
 static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data);
 static int fbcon_set_palette(struct vc_data *conp, unsigned char *table);
+static int fbcon_scrolldelta(int lines);
 int fbcon_register_driver(struct display_switch *dispsw, int is_accel);
 int fbcon_unregister_driver(struct display_switch *dispsw);
 
@@ -165,10 +174,19 @@
 
 static void fbcon_setup(int con, int setcol, int init);
 static __inline__ int real_y(struct display *p, int ypos);
+#if FLASHING_CURSOR
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp);
+#endif
 static __inline__ void updatescrollmode(struct display *p);
+#if SUPPORT_SCROLLBACK
+static __inline__ void ywrap_up(int unit, struct vc_data *conp,
+				struct display *p, int count);
+static __inline__ void ywrap_down(int unit, struct vc_data *conp,
+				  struct display *p, int count);
+#else
 static __inline__ void ywrap_up(int unit, struct display *p, int count);
 static __inline__ void ywrap_down(int unit, struct display *p, int count);
+#endif
 static __inline__ void ypan_up(int unit, struct vc_data *conp,
 			       struct display *p, int count);
 static __inline__ void ypan_down(int unit, struct vc_data *conp,
@@ -184,6 +202,22 @@
 static struct display_switch *fbcon_get_driver(struct display *disp);
 static int fbcon_show_logo(void);
 
+#if FLASHING_CURSOR
+static void cursor_timer_handler(unsigned long dev_addr);
+
+static struct timer_list cursor_timer = {
+    NULL, NULL, 0, 0L, cursor_timer_handler
+};
+
+static void cursor_timer_handler(unsigned long dev_addr)
+{
+      fbcon_vbl_handler(0, NULL, NULL);
+      cursor_timer.expires = jiffies+2;
+      cursor_timer.data = 0;
+      cursor_timer.next = cursor_timer.next = NULL;
+      add_timer(&cursor_timer);
+}
+#endif
 
 /*
  *  Low Level Operations
@@ -215,12 +249,21 @@
 #ifdef CONFIG_FBCON_CFB16
 extern int fbcon_init_cfb16(void);
 #endif
+#ifdef CONFIG_FBCON_CFB24
+extern int fbcon_init_cfb24(void);
+#endif
+#ifdef CONFIG_FBCON_CFB32
+extern int fbcon_init_cfb32(void);
+#endif
 #ifdef CONFIG_FBCON_CYBER
 extern int fbcon_init_cyber(void);
 #endif
 #ifdef CONFIG_FBCON_RETINAZ3
 extern int fbcon_init_retz3(void);
 #endif
+#ifdef CONFIG_FBCON_MACH64
+extern int fbcon_init_mach64(void);
+#endif
 
 extern int num_registered_fb;
 
@@ -264,16 +307,17 @@
     fbcon_init_cfb16();
 #endif
 #ifdef CONFIG_FBCON_CFB24
-    /* Not yet implemented */
-    fbcon_init_24_packed();
+    fbcon_init_cfb24();
 #endif
 #ifdef CONFIG_FBCON_CFB32
-    /* Not yet implemented */
-    fbcon_init_32_packed();
+    fbcon_init_cfb32();
 #endif
 #ifdef CONFIG_FBCON_CYBER
     fbcon_init_cyber();
 #endif
+#ifdef CONFIG_FBCON_MACH64
+    fbcon_init_mach64();
+#endif
 
     *display_desc = "frame buffer device";
 
@@ -291,19 +335,13 @@
 			     "console/cursor", fbcon_vbl_handler);
     }
 #endif /* CONFIG_ATARI */
-#ifdef CONFIG_APOLLO
-   if(MACH_IS_APOLLO) {
-   	cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
-   	cursor_timer.expires=jiffies+2;
-   	cursor_timer.data=0;
-   	cursor_timer.next=cursor_timer.prev=NULL;
-   	add_timer(&cursor_timer);
-   	irqres=0;
-   }
-#endif /* CONFIG_APOLLO */
-
-    if (irqres)
-	panic("fbcon_startup: Couldn't add vblank interrupt");
+    if (irqres) {
+	cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+	cursor_timer.expires = jiffies+2;
+	cursor_timer.data = 0;
+	cursor_timer.next = cursor_timer.prev = NULL;
+	add_timer(&cursor_timer);
+    }
 
     if (!console_show_logo)
 	console_show_logo = fbcon_show_logo;
@@ -547,6 +585,7 @@
 }
 
 
+#if FLASHING_CURSOR
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
 {
     struct display *p;
@@ -564,9 +603,19 @@
 	vbl_cursor_cnt = cursor_blink_rate;
     }
 }
+#endif
 
+#if SUPPORT_SCROLLBACK
+static int scrollback_max = 0;
+static int scrollback_current = 0;
+#endif
 
+#if SUPPORT_SCROLLBACK
+static __inline__ void ywrap_up(int unit, struct vc_data *conp,
+				struct display *p, int count)
+#else
 static __inline__ void ywrap_up(int unit, struct display *p, int count)
+#endif
 {
     p->yscroll += count;
     if (p->yscroll >= p->vrows)	/* Deal with wrap */
@@ -575,10 +624,21 @@
     p->var.yoffset = p->yscroll*p->fontheight;
     p->var.vmode |= FB_VMODE_YWRAP;
     p->fb_info->updatevar(unit);
+#if SUPPORT_SCROLLBACK
+    scrollback_max += count;
+    if (scrollback_max > p->vrows-conp->vc_rows)
+	scrollback_max = p->vrows-conp->vc_rows;
+    scrollback_current = 0;
+#endif
 }
 
 
+#if SUPPORT_SCROLLBACK
+static __inline__ void ywrap_down(int unit, struct vc_data *conp,
+				  struct display *p, int count)
+#else
 static __inline__ void ywrap_down(int unit, struct display *p, int count)
+#endif
 {
     p->yscroll -= count;
     if (p->yscroll < 0)		/* Deal with wrap */
@@ -587,6 +647,12 @@
     p->var.yoffset = p->yscroll*p->fontheight;
     p->var.vmode |= FB_VMODE_YWRAP;
     p->fb_info->updatevar(unit);
+#if SUPPORT_SCROLLBACK
+    scrollback_max -= count;
+    if (scrollback_max < 0)
+	scrollback_max = 0;
+    scrollback_current = 0;
+#endif
 }
 
 
@@ -647,7 +713,11 @@
 			    if (t > 0)
 				fbcon_bmove(conp, 0, 0, count, 0, t,
 					    conp->vc_cols);
+#if SUPPORT_SCROLLBACK
+			    ywrap_up(unit, conp, p, count);
+#else
 			    ywrap_up(unit, p, count);
+#endif
 			    if (conp->vc_rows-b > 0)
 				fbcon_bmove(conp, b-count, 0, b, 0,
 					    conp->vc_rows-b, conp->vc_cols);
@@ -674,7 +744,7 @@
 
 		    case SCROLL_YMOVE:
 			p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
-			conp->vc_cols);
+					 conp->vc_cols);
 			p->dispsw->clear(conp, p, b-count, 0, count,
 					 conp->vc_cols);
 			break;
@@ -695,7 +765,11 @@
 			    if (conp->vc_rows-b > 0)
 				fbcon_bmove(conp, b, 0, b-count, 0,
 					    conp->vc_rows-b, conp->vc_cols);
+#if SUPPORT_SCROLLBACK
+			    ywrap_down(unit, conp, p, count);
+#else
 			    ywrap_down(unit, p, count);
+#endif
 			    if (t > 0)
 				fbcon_bmove(conp, count, 0, 0, 0, t,
 					    conp->vc_cols);
@@ -821,6 +895,10 @@
 
     if (info && info->switch_con)
 	(*info->switch_con)(conp->vc_num);
+#if SUPPORT_SCROLLBACK
+    scrollback_max = 0;
+    scrollback_current = 0;
+#endif
     return(0);
 }
 
@@ -1003,10 +1081,43 @@
     return(p->fb_info->setcmap(&palette_cmap, unit));
 }
 
+static int fbcon_scrolldelta(int lines)
+{
+#if SUPPORT_SCROLLBACK
+    int unit = fg_console; /* xxx */
+    struct display *p = &fb_display[unit];
+    int offset;
+
+    if (!p->can_soft_blank && console_blanked ||
+	vt_cons[unit]->vc_mode != KD_TEXT || !lines ||
+	p->scrollmode != SCROLL_YWRAP)
+	return 0;
+
+    fbcon_cursor(conp, CM_ERASE);
+
+    scrollback_current -= lines;
+    if (scrollback_current < 0)
+	scrollback_current = 0;
+    else if (scrollback_current > scrollback_max)
+	scrollback_current = scrollback_max;
+
+    offset = p->yscroll-scrollback_current;
+    if (offset < 0)
+	offset += p->vrows;
+    else if (offset > p->vrows)
+	offset -= p->vrows;
+    p->var.vmode |= FB_VMODE_YWRAP;
+    p->var.xoffset = 0;
+    p->var.yoffset = offset*p->fontheight;
+    p->fb_info->updatevar(unit);
+#else
+    return -ENOSYS;
+#endif
+}
 
 
-#define LOGO_H		80
-#define LOGO_W		80
+#define LOGO_H			80
+#define LOGO_W			80
 #define LOGO_LINE	(LOGO_W/8)
 
 __initfunc(static int fbcon_show_logo( void ))
@@ -1204,7 +1315,8 @@
 struct consw fb_con = {
     fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
     fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
-    fbcon_blank, fbcon_get_font, fbcon_set_font, fbcon_set_palette
+    fbcon_blank, fbcon_get_font, fbcon_set_font, fbcon_set_palette,
+    fbcon_scrolldelta
 };
 
 
--- m68k-2.1.64/drivers/video/font.h.orig	Sun Nov 23 23:33:09 1997
+++ m68k-2.1.64/drivers/video/font.h	Sun Nov 23 23:33:09 1997
@@ -0,0 +1,35 @@
+/*
+ *  font.h -- `Soft' font definitions
+ *
+ *  Created 1995 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef _FONT_H_
+#define _FONT_H_
+
+#include <linux/types.h>
+
+
+   /*
+    *    Find a font with a specific name
+    */
+
+extern int findsoftfont(char *name, int *width, int *height, u_char *data[]);
+
+
+   /*
+    *    Get the default font for a specific screen size
+    */
+
+extern void getdefaultfont(int xres, int yres, char *name[], int *width,
+                           int *height, u_char *data[]);
+
+
+/* Max. length for the name of a predefined font */
+#define MAX_FONT_NAME	32
+
+#endif /* _FONT_H_ */
--- m68k-2.1.64/drivers/video/fonts.c.orig	Mon Nov 17 22:00:36 1997
+++ m68k-2.1.64/drivers/video/fonts.c	Sun Nov 23 23:33:09 1997
@@ -11,8 +11,10 @@
 
 #include <linux/types.h>
 #include <linux/string.h>
+#ifdef __mc68000__
 #include <asm/setup.h>
-#include <asm/font.h>
+#endif
+#include "font.h"
 
 
    /*
@@ -91,9 +93,13 @@
 {
     int i;
     
-    if (yres < 400)
-	i = MACH_IS_AMIGA ? PEARL8x8_IDX : VGA8x8_IDX;
-    else
+    if (yres < 400) {
+	i = VGA8x8_IDX;
+#ifdef CONFIG_AMIGA
+	if (MACH_IS_AMIGA)
+	    i = PEARL8x8_IDX;
+#endif
+    } else
 	i = VGA8x16_IDX;
 
     if (name)
--- m68k-2.1.64/drivers/video/offb.c.orig	Sun Nov 23 23:33:09 1997
+++ m68k-2.1.64/drivers/video/offb.c	Sun Nov 23 23:33:09 1997
@@ -0,0 +1,454 @@
+/*
+ *  linux/drivers/video/offb.c -- Open Firmware based frame buffer device
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This driver is partly based on the PowerMac console driver:
+ *
+ *	Copyright (C) 1996 Paul Mackerras
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+
+
+#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
+
+static int currcon = 0;
+static struct display disp;
+static struct fb_info fb_info;
+static struct { u_char red, green, blue, pad; } palette[256];
+static char offb_name[16] = "OFfb ";
+
+static volatile unsigned char *unknown_cmap_adr = NULL;
+static volatile unsigned char *unknown_cmap_data = NULL;
+
+static struct fb_fix_screeninfo fb_fix = { 0, };
+static struct fb_var_screeninfo fb_var = { 0, };
+
+
+    /*
+     *  Interface used by the world
+     */
+
+void offb_video_setup(char *options, int *ints);
+
+static int offb_open(int fbidx);
+static int offb_release(int fbidx);
+static int offb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int offb_get_var(struct fb_var_screeninfo *var, int con);
+static int offb_set_var(struct fb_var_screeninfo *var, int con);
+static int offb_pan_display(struct fb_var_screeninfo *var, int con);
+static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+			    u_long arg, int con);
+
+
+    /*
+     *  Interface to the low level console driver
+     */
+
+unsigned long offb_init(unsigned long mem_start);
+static int offbcon_switch(int con);
+static int offbcon_updatevar(int con);
+static void offbcon_blank(int blank);
+static int offbcon_setcmap(struct fb_cmap *cmap, int con);
+
+
+    /*
+     *  Internal routines
+     */
+
+static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp);
+static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp);
+static void do_install_cmap(int con);
+
+
+static struct fb_ops offb_ops = {
+    offb_open, offb_release, offb_get_fix, offb_get_var, offb_set_var,
+    offb_get_cmap, offb_set_cmap, offb_pan_display, offb_ioctl
+};
+
+
+    /*
+     *  Open/Release the frame buffer device
+     */
+
+static int offb_open(int fbidx)                                       
+{
+    /*                                                                     
+     *  Nothing, only a usage count for the moment                          
+     */                                                                    
+
+    MOD_INC_USE_COUNT;
+    return(0);                              
+}
+        
+static int offb_release(int fbidx)
+{
+    MOD_DEC_USE_COUNT;
+    return(0);                                                    
+}
+
+
+    /*
+     *  Get the Fixed Part of the Display
+     */
+
+static int offb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+    memcpy(fix, &fb_fix, sizeof(fb_fix));
+    return 0;
+}
+
+
+    /*
+     *  Get the User Defined Part of the Display
+     */
+
+static int offb_get_var(struct fb_var_screeninfo *var, int con)
+{
+    memcpy(var, &fb_var, sizeof(fb_var));
+    return 0;
+}
+
+
+    /*
+     *  Set the User Defined Part of the Display
+     */
+
+static int offb_set_var(struct fb_var_screeninfo *var, int con)
+{
+    struct display *display;
+    int oldbpp = -1, err;
+
+    if (con >= 0)
+	display = &fb_display[con];
+    else
+	display = &disp;	/* used during initialization */
+
+    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
+	var->xres_virtual > fb_var.xres_virtual ||
+	var->yres_virtual > fb_var.yres_virtual ||
+	var->bits_per_pixel > fb_var.bits_per_pixel ||
+	var->nonstd ||
+	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+	return -EINVAL;
+    memcpy(var, &fb_var, sizeof(fb_var));
+
+    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+	oldbpp = display->var.bits_per_pixel;
+	display->var = *var;
+    }
+    if (oldbpp != var->bits_per_pixel) {
+	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+	    return err;
+	do_install_cmap(con);
+    }
+    return 0;
+}
+
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int offb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+    if (var->xoffset || var->yoffset)
+	return -EINVAL;
+    else
+	return 0;
+}
+
+    /*
+     *  Get the Colormap
+     */
+
+static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+    if (con == currcon) /* current console? */
+	return fb_get_cmap(cmap, &fb_display[con].var, kspc, offb_getcolreg);
+    else if (fb_display[con].cmap.len) /* non default colormap? */
+	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+    else
+	fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
+		     cmap, kspc ? 0 : 2);
+    return 0;
+}
+
+    /*
+     *  Set the Colormap
+     */
+
+static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+    int err;
+
+    if (!unknown_cmap_adr)
+	return -ENOSYS;
+
+    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+	if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+				 1<<fb_display[con].var.bits_per_pixel, 0)))
+	    return err;
+    }
+    if (con == currcon)			/* current console? */
+	return fb_set_cmap(cmap, &fb_display[con].var, kspc, offb_setcolreg);
+    else
+	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+    return 0;
+}
+
+
+static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		      u_long arg, int con)
+{
+    return -EINVAL;
+}
+
+
+    /*
+     *  Initialisation
+     */
+
+__initfunc(unsigned long offb_init(unsigned long mem_start))
+{
+    struct device_node *dp;
+    int i, err, *pp, len;
+    unsigned *up, address;
+
+    if (!prom_display_path[0])
+	return mem_start;
+    if (!(dp = find_path_device(prom_display_path)))
+	return mem_start;
+
+    strncat(offb_name, dp->name, sizeof(offb_name));
+    offb_name[sizeof(offb_name)-1] = '\0';
+    strcpy(fb_fix.id, offb_name);
+
+    if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
+	&& len == sizeof(int) && *pp != 8) {
+	printk("%s: can't use depth = %d\n", dp->full_name, *pp);
+	return mem_start;
+    }
+    if ((pp = (int *)get_property(dp, "width", &len)) != NULL
+	&& len == sizeof(int))
+	fb_var.xres = fb_var.xres_virtual = *pp;
+    if ((pp = (int *)get_property(dp, "height", &len)) != NULL
+	&& len == sizeof(int))
+	fb_var.yres = fb_var.yres_virtual = *pp;
+    if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
+	&& len == sizeof(int))
+	fb_fix.line_length = *pp;
+    else
+	fb_fix.line_length = fb_var.xres_virtual;
+    fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
+    if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
+	&& len == sizeof(unsigned))
+	address = (u_long)*up;
+    else {
+	for (i = 0; i < dp->n_addrs; ++i)
+	    if (dp->addrs[i].size >= len)
+		break;
+	if (i >= dp->n_addrs) {
+	    printk("no framebuffer address found for %s\n", dp->full_name);
+	    return mem_start;
+	}
+	address = (u_long)dp->addrs[i].address;
+    }
+    fb_fix.smem_start = ioremap(address, fb_fix.smem_len);
+    fb_fix.type = FB_TYPE_PACKED_PIXELS;
+    fb_fix.type_aux = 0;
+
+    /* XXX kludge for ati */
+    if (strncmp(dp->name, "ATY,", 4) == 0) {
+	unknown_cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
+	unknown_cmap_data = unknown_cmap_adr + 1;
+    }
+
+    fb_fix.visual = unknown_cmap_adr ? FB_VISUAL_PSEUDOCOLOR :
+				       FB_VISUAL_STATIC_PSEUDOCOLOR;
+
+    fb_var.xoffset = fb_var.yoffset = 0;
+    fb_var.bits_per_pixel = 8;
+    fb_var.grayscale = 0;
+    fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0;
+    fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
+    fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
+    fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
+    fb_var.nonstd = 0;
+    fb_var.activate = 0;
+    fb_var.height = fb_var.width = -1;
+    fb_var.accel = FB_ACCEL_NONE;
+    fb_var.pixclock = 10000;
+    fb_var.left_margin = fb_var.right_margin = 16;
+    fb_var.upper_margin = fb_var.lower_margin = 16;
+    fb_var.hsync_len = fb_var.vsync_len = 8;
+    fb_var.sync = 0;
+    fb_var.vmode = FB_VMODE_NONINTERLACED;
+
+    disp.var = fb_var;
+    disp.cmap.start = 0;
+    disp.cmap.len = 0;
+    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
+    disp.screen_base = fb_fix.smem_start;
+    disp.visual = fb_fix.visual;
+    disp.type = fb_fix.type;
+    disp.type_aux = fb_fix.type_aux;
+    disp.ypanstep = 0;
+    disp.ywrapstep = 0;
+    disp.line_length = fb_fix.line_length;
+    disp.can_soft_blank = 1;
+    disp.inverse = 0;
+
+    strcpy(fb_info.modename, "OFfb ");
+    strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename));
+    fb_info.node = -1;
+    fb_info.fbops = &offb_ops;
+    fb_info.fbvar_num = 1;
+    fb_info.fbvar = &fb_var;
+    fb_info.disp = &disp;
+    fb_info.fontname[0] = '\0';
+    fb_info.changevar = NULL;
+    fb_info.switch_con = &offbcon_switch;
+    fb_info.updatevar = &offbcon_updatevar;
+    fb_info.blank = &offbcon_blank;
+    fb_info.setcmap = &offbcon_setcmap;
+
+    err = register_framebuffer(&fb_info);
+    if (err < 0)
+	return mem_start;
+
+    offb_set_var(&fb_var, -1);
+
+    printk("Open Firmware frame buffer device on %s\n", dp->full_name);
+    return mem_start;
+}
+
+
+static int offbcon_switch(int con)
+{
+    /* Do we have to save the colormap? */
+    if (fb_display[currcon].cmap.len)
+	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
+		    offb_getcolreg);
+
+    currcon = con;
+    /* Install new colormap */
+    do_install_cmap(con);
+    return 0;
+}
+
+    /*
+     *  Update the `var' structure (called by fbcon.c)
+     */
+
+static int offbcon_updatevar(int con)
+{
+    /* Nothing */
+    return 0;
+}
+
+    /*
+     *  Blank the display.
+     */
+
+static void offbcon_blank(int blank)
+{
+    /* Nothing */
+}
+
+    /*
+     *  Set the colormap
+     */
+
+static int offbcon_setcmap(struct fb_cmap *cmap, int con)
+{
+    return(offb_set_cmap(cmap, 1, con));
+}
+
+
+    /*
+     *  Read a single color register and split it into
+     *  colors/transparent. Return != 0 for invalid regno.
+     */
+
+static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp)
+{
+    if (!unknown_cmap_adr || regno > 255)
+	return 1;
+    *red = palette[regno].red;
+    *green = palette[regno].green;
+    *blue = palette[regno].blue;
+    return 0;
+}
+
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp)
+{
+    if (!unknown_cmap_adr || regno > 255)
+	return 1;
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+    *unknown_cmap_adr = regno;
+#ifdef __powerpc__
+    eieio();
+#endif
+    *unknown_cmap_data = red;
+#ifdef __powerpc__
+    eieio();
+#endif
+    *unknown_cmap_data = green;
+#ifdef __powerpc__
+    eieio();
+#endif
+    *unknown_cmap_data = blue;
+#ifdef __powerpc__
+    eieio();
+#endif
+    return 0;
+}
+
+
+static void do_install_cmap(int con)
+{
+    if (con != currcon)
+	return;
+    if (fb_display[con].cmap.len)
+	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
+		    offb_setcolreg);
+    else
+	fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
+				    &fb_display[con].var, 1, offb_setcolreg);
+}
--- m68k-2.1.64/drivers/video/tgafb.c.orig	Sun Nov 23 23:33:09 1997
+++ m68k-2.1.64/drivers/video/tgafb.c	Sun Nov 23 23:33:09 1997
@@ -0,0 +1,938 @@
+/*
+ *  linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This driver is partly based on the original TGA console driver
+ *
+ *	Copyright (C) 1995  Jay Estabrook
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+
+/* KNOWN PROBLEMS/TO DO ===================================================== *
+ *
+ *	- How to set a single color register?
+ *
+ *	- We don't have support for CFB32 yet (fbcon-cfb32.c)
+ *
+ *	- Hardware cursor (useful for other graphics boards too)
+ *
+ * KNOWN PROBLEMS/TO DO ==================================================== */
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/selection.h>
+#include <asm/io.h>
+
+
+/* TGA hardware description (minimal) */
+/*
+ * Offsets within Memory Space
+ */
+#define	TGA_ROM_OFFSET			0x0000000
+#define	TGA_REGS_OFFSET			0x0100000
+#define	TGA_8PLANE_FB_OFFSET		0x0200000
+#define	TGA_24PLANE_FB_OFFSET		0x0804000
+#define	TGA_24PLUSZ_FB_OFFSET		0x1004000
+
+#define	TGA_PLANEMASK_REG		0x0028
+#define	TGA_MODE_REG			0x0030
+#define	TGA_RASTEROP_REG		0x0034
+#define	TGA_DEEP_REG			0x0050
+#define	TGA_PIXELMASK_REG		0x005c
+#define	TGA_CURSOR_BASE_REG		0x0060
+#define	TGA_HORIZ_REG			0x0064
+#define	TGA_VERT_REG			0x0068
+#define	TGA_BASE_ADDR_REG		0x006c
+#define	TGA_VALID_REG			0x0070
+#define	TGA_CURSOR_XY_REG		0x0074
+#define	TGA_INTR_STAT_REG		0x007c
+#define	TGA_RAMDAC_SETUP_REG		0x00c0
+#define	TGA_BLOCK_COLOR0_REG		0x0140
+#define	TGA_BLOCK_COLOR1_REG		0x0144
+#define	TGA_CLOCK_REG			0x01e8
+#define	TGA_RAMDAC_REG			0x01f0
+#define	TGA_CMD_STAT_REG		0x01f8
+
+/*
+ * useful defines for managing the BT485 on the 8-plane TGA
+ */
+#define	BT485_READ_BIT			0x01
+#define	BT485_WRITE_BIT			0x00
+
+#define	BT485_ADDR_PAL_WRITE		0x00
+#define	BT485_DATA_PAL			0x02
+#define	BT485_PIXEL_MASK		0x04
+#define	BT485_ADDR_PAL_READ		0x06
+#define	BT485_ADDR_CUR_WRITE		0x08
+#define	BT485_DATA_CUR			0x0a
+#define	BT485_CMD_0			0x0c
+#define	BT485_ADDR_CUR_READ		0x0e
+#define	BT485_CMD_1			0x10
+#define	BT485_CMD_2			0x12
+#define	BT485_STATUS			0x14
+#define	BT485_CMD_3			0x14
+#define	BT485_CUR_RAM			0x16
+#define	BT485_CUR_LOW_X			0x18
+#define	BT485_CUR_HIGH_X		0x1a
+#define	BT485_CUR_LOW_Y			0x1c
+#define	BT485_CUR_HIGH_Y		0x1e
+
+/*
+ * useful defines for managing the BT463 on the 24-plane TGAs
+ */
+#define	BT463_ADDR_LO		0x0
+#define	BT463_ADDR_HI		0x1
+#define	BT463_REG_ACC		0x2
+#define	BT463_PALETTE		0x3
+
+#define	BT463_CUR_CLR_0		0x0100
+#define	BT463_CUR_CLR_1		0x0101
+
+#define	BT463_CMD_REG_0		0x0201
+#define	BT463_CMD_REG_1		0x0202
+#define	BT463_CMD_REG_2		0x0203
+
+#define	BT463_READ_MASK_0	0x0205
+#define	BT463_READ_MASK_1	0x0206
+#define	BT463_READ_MASK_2	0x0207
+#define	BT463_READ_MASK_3	0x0208
+
+#define	BT463_BLINK_MASK_0	0x0209
+#define	BT463_BLINK_MASK_1	0x020a
+#define	BT463_BLINK_MASK_2	0x020b
+#define	BT463_BLINK_MASK_3	0x020c
+
+#define	BT463_WINDOW_TYPE_BASE	0x0300
+
+
+int tga_type;
+unsigned int tga_mem_base;
+unsigned long tga_fb_base;
+unsigned long tga_regs_base;
+
+static unsigned int fb_offset_presets[4] __initdata = {
+	TGA_8PLANE_FB_OFFSET,
+	TGA_24PLANE_FB_OFFSET,
+	0xffffffff,
+	TGA_24PLUSZ_FB_OFFSET
+};
+
+static unsigned int deep_presets[4] __initdata = {
+  0x00014000,
+  0x0001440d,
+  0xffffffff,
+  0x0001441d
+};
+
+static unsigned int rasterop_presets[4] __initdata = {
+  0x00000003,
+  0x00000303,
+  0xffffffff,
+  0x00000303
+};
+
+static unsigned int mode_presets[4] __initdata = {
+  0x00002000,
+  0x00002300,
+  0xffffffff,
+  0x00002300
+};
+
+static unsigned int base_addr_presets[4] __initdata = {
+  0x00000000,
+  0x00000001,
+  0xffffffff,
+  0x00000001
+};
+
+#define TGA_WRITE_REG(v,r) \
+	{ writel((v), tga_regs_base+(r)); mb(); }
+
+#define TGA_READ_REG(r) readl(tga_regs_base+(r))
+
+#define BT485_WRITE(v,r) \
+	  TGA_WRITE_REG((r),TGA_RAMDAC_SETUP_REG);		\
+	  TGA_WRITE_REG(((v)&0xff)|((r)<<8),TGA_RAMDAC_REG);
+
+#define BT463_LOAD_ADDR(a) \
+	TGA_WRITE_REG(BT463_ADDR_LO<<2, TGA_RAMDAC_SETUP_REG); \
+	TGA_WRITE_REG((BT463_ADDR_LO<<10)|((a)&0xff), TGA_RAMDAC_REG); \
+	TGA_WRITE_REG(BT463_ADDR_HI<<2, TGA_RAMDAC_SETUP_REG); \
+	TGA_WRITE_REG((BT463_ADDR_HI<<10)|(((a)>>8)&0xff), TGA_RAMDAC_REG);
+
+#define BT463_WRITE(m,a,v) \
+	BT463_LOAD_ADDR((a)); \
+	TGA_WRITE_REG(((m)<<2),TGA_RAMDAC_SETUP_REG); \
+	TGA_WRITE_REG(((m)<<10)|((v)&0xff),TGA_RAMDAC_REG);
+
+
+unsigned char PLLbits[7] __initdata = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 };
+
+const unsigned long bt485_cursor_source[64] __initdata = {
+  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
+  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
+  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
+  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
+  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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+
+const unsigned int bt463_cursor_source[256] __initdata = {
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+  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,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,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,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,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,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
+};
+
+
+#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
+
+static int currcon = 0;
+static struct display disp;
+static struct fb_info fb_info;
+static struct { u_char red, green, blue, pad; } palette[256];
+static char tgafb_name[16] = "DEC TGA ";
+
+static struct fb_fix_screeninfo fb_fix;
+static struct fb_var_screeninfo fb_var = { 0, };
+
+
+    /*
+     *  Interface used by the world
+     */
+
+void tgafb_video_setup(char *options, int *ints);
+
+static int tgafb_open(int fbidx);
+static int tgafb_release(int fbidx);
+static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int tgafb_get_var(struct fb_var_screeninfo *var, int con);
+static int tgafb_set_var(struct fb_var_screeninfo *var, int con);
+static int tgafb_pan_display(struct fb_var_screeninfo *var, int con);
+static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con);
+
+
+    /*
+     *  Interface to the low level console driver
+     */
+
+unsigned long tgafb_init(unsigned long mem_start);
+static int tgafbcon_switch(int con);
+static int tgafbcon_updatevar(int con);
+static void tgafbcon_blank(int blank);
+static int tgafbcon_setcmap(struct fb_cmap *cmap, int con);
+
+
+    /*
+     *  Internal routines
+     */
+
+static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+			   u_int *transp);
+static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp);
+#if 1
+static void tga_update_palette(void);
+#endif
+static void do_install_cmap(int con);
+
+
+static struct fb_ops tgafb_ops = {
+    tgafb_open, tgafb_release, tgafb_get_fix, tgafb_get_var, tgafb_set_var,
+    tgafb_get_cmap, tgafb_set_cmap, tgafb_pan_display, tgafb_ioctl
+};
+
+
+    /*
+     *  Open/Release the frame buffer device
+     */
+
+static int tgafb_open(int fbidx)                                       
+{
+    /*                                                                     
+     *  Nothing, only a usage count for the moment                          
+     */                                                                    
+
+    MOD_INC_USE_COUNT;
+    return(0);                              
+}
+        
+static int tgafb_release(int fbidx)
+{
+    MOD_DEC_USE_COUNT;
+    return(0);                                                    
+}
+
+
+    /*
+     *  Get the Fixed Part of the Display
+     */
+
+static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+    memcpy(fix, &fb_fix, sizeof(fb_fix));
+    return 0;
+}
+
+
+    /*
+     *  Get the User Defined Part of the Display
+     */
+
+static int tgafb_get_var(struct fb_var_screeninfo *var, int con)
+{
+    memcpy(var, &fb_var, sizeof(fb_var));
+    return 0;
+}
+
+
+    /*
+     *  Set the User Defined Part of the Display
+     */
+
+static int tgafb_set_var(struct fb_var_screeninfo *var, int con)
+{
+    struct display *display;
+    int oldbpp = -1, err;
+
+    if (con >= 0)
+	display = &fb_display[con];
+    else
+	display = &disp;	/* used during initialization */
+
+    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
+	var->xres_virtual > fb_var.xres_virtual ||
+	var->yres_virtual > fb_var.yres_virtual ||
+	var->bits_per_pixel > fb_var.bits_per_pixel ||
+	var->nonstd ||
+	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+	return -EINVAL;
+    memcpy(var, &fb_var, sizeof(fb_var));
+
+    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+	oldbpp = display->var.bits_per_pixel;
+	display->var = *var;
+    }
+    if (oldbpp != var->bits_per_pixel) {
+	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+	    return err;
+	do_install_cmap(con);
+    }
+    return 0;
+}
+
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int tgafb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+    if (var->xoffset || var->yoffset)
+	return -EINVAL;
+    else
+	return 0;
+}
+
+    /*
+     *  Get the Colormap
+     */
+
+static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+    if (con == currcon) /* current console? */
+	return fb_get_cmap(cmap, &fb_display[con].var, kspc, tgafb_getcolreg);
+    else if (fb_display[con].cmap.len) /* non default colormap? */
+	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+    else
+	fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
+		     cmap, kspc ? 0 : 2);
+    return 0;
+}
+
+    /*
+     *  Set the Colormap
+     */
+
+static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+    int err;
+
+    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+	if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+				 1<<fb_display[con].var.bits_per_pixel, 0)))
+	    return err;
+    }
+    if (con == currcon) {		/* current console? */
+	err = fb_set_cmap(cmap, &fb_display[con].var, kspc, tgafb_setcolreg);
+#if 1
+	tga_update_palette();
+#endif
+	return err;
+    } else
+	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+    return 0;
+}
+
+
+static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con)
+{
+    return -EINVAL;
+}
+
+
+    /*
+     *  Initialisation
+     */
+
+__initfunc(unsigned long tgafb_init(unsigned long mem_start))
+{
+    unsigned char pci_bus, pci_devfn;
+    int status;
+    int i, j, temp, err;
+    unsigned char *cbp;
+
+    status = pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
+				  0, &pci_bus, &pci_devfn);
+    if (status == PCIBIOS_DEVICE_NOT_FOUND)
+	return mem_start;
+
+    /*
+     * read BASE_REG_0 for memory address
+     */
+    pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0,
+			      &tga_mem_base);
+    tga_mem_base &= ~15;
+#ifdef DEBUG
+    printk("tgafb_init: mem_base 0x%x\n", tga_mem_base);
+#endif /* DEBUG */
+
+    tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f;
+    switch (tga_type) {
+	case 0:
+	    strcat(tgafb_name, "8plane");
+	    break;
+	case 1:
+	    strcat(tgafb_name, "24plane");
+	    break;
+	case 3:
+	    strcat(tgafb_name, "24plusZ");
+	    break;
+	default:
+	    printk("TGA type (0x%x) unrecognized!\n", tga_type);
+	    return mem_start;
+    }
+    strcpy(fb_fix.id, tgafb_name);
+
+    tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET);
+    tga_fb_base = ((unsigned long)tga_mem_base + fb_offset_presets[tga_type]);
+
+    /* first, disable video timing */
+    TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
+
+    /* write the DEEP register */
+    while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+      continue;
+
+    mb();
+    TGA_WRITE_REG(deep_presets[tga_type], TGA_DEEP_REG);
+    while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+	continue;
+    mb();
+
+    /* write some more registers */
+    TGA_WRITE_REG(rasterop_presets[tga_type], TGA_RASTEROP_REG);
+    TGA_WRITE_REG(mode_presets[tga_type], TGA_MODE_REG);
+    TGA_WRITE_REG(base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
+
+    /* write the PLL for 640x480 @ 60Hz */
+    for (i = 0; i <= 6; i++) {
+	for (j = 0; j <= 7; j++) {
+	    temp = (PLLbits[i] >> (7-j)) & 1;
+	    if (i == 6 && j == 7)
+		temp |= 2;
+	    TGA_WRITE_REG(temp, TGA_CLOCK_REG);
+	}
+    }
+
+    /* write some more registers */
+    TGA_WRITE_REG(0xffffffff, TGA_PLANEMASK_REG);
+    TGA_WRITE_REG(0xffffffff, TGA_PIXELMASK_REG);
+    TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR0_REG);
+    TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR1_REG);
+
+    /* init video timing regs for 640x480 @ 60 Hz */
+    TGA_WRITE_REG(0x018608a0, TGA_HORIZ_REG);
+    TGA_WRITE_REG(0x084251e0, TGA_VERT_REG);
+
+    if (tga_type == 0) { /* 8-plane */
+
+	fb_var.bits_per_pixel = 8;
+	fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	/* init BT485 RAMDAC registers */
+	BT485_WRITE(0xa2, BT485_CMD_0);
+	BT485_WRITE(0x01, BT485_ADDR_PAL_WRITE);
+	BT485_WRITE(0x14, BT485_CMD_3); /* cursor 64x64 */
+	BT485_WRITE(0x40, BT485_CMD_1);
+	BT485_WRITE(0x22, BT485_CMD_2); /* WIN cursor type */
+	BT485_WRITE(0xff, BT485_PIXEL_MASK);
+
+	/* fill palette registers */
+	BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
+	TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+
+	for (i = 0; i < 16; i++) {
+	    j = color_table[i];
+	    TGA_WRITE_REG(default_red[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(default_grn[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(default_blu[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	}
+	for (i = 0; i < 240*3; i += 4) {
+	    TGA_WRITE_REG(0x55|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
+	}	  
+
+	/* initialize RAMDAC cursor colors */
+	BT485_WRITE(0, BT485_ADDR_CUR_WRITE);
+
+	BT485_WRITE(0xaa, BT485_DATA_CUR); /* overscan WHITE */
+	BT485_WRITE(0xaa, BT485_DATA_CUR); /* overscan WHITE */
+	BT485_WRITE(0xaa, BT485_DATA_CUR); /* overscan WHITE */
+
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 1 BLACK */
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 1 BLACK */
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 1 BLACK */
+
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 2 BLACK */
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 2 BLACK */
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 2 BLACK */
+
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 3 BLACK */
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 3 BLACK */
+	BT485_WRITE(0x00, BT485_DATA_CUR); /* color 3 BLACK */
+
+	/* initialize RAMDAC cursor RAM */
+	BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
+	cbp = (unsigned char *)bt485_cursor_source;
+	for (i = 0; i < 512; i++) {
+	    BT485_WRITE(*cbp++, BT485_CUR_RAM);
+	}
+	for (i = 0; i < 512; i++) {
+	    BT485_WRITE(0xff, BT485_CUR_RAM);
+	}
+
+    } else { /* 24-plane or 24plusZ */
+
+	fb_var.bits_per_pixel = 32;
+	fb_fix.visual = FB_VISUAL_TRUECOLOR;
+
+	TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+
+	/*
+	 * init some registers
+	 */
+	BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
+	BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
+	BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_2, 0x40);
+
+	BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
+	BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
+	BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
+	BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
+
+	BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
+	BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
+	BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
+	BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
+
+	/*
+	 * fill the palette
+	 */
+	BT463_LOAD_ADDR(0x0000);
+	TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+
+	for (i = 0; i < 16; i++) {
+	    j = color_table[i];
+	    TGA_WRITE_REG(default_red[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(default_grn[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(default_blu[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	}
+	for (i = 0; i < 512*3; i += 4) {
+	    TGA_WRITE_REG(0x55|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	}	  
+
+	/*
+	 * fill window type table after start of vertical retrace
+	 */
+	while (!(TGA_READ_REG(TGA_INTR_STAT_REG) & 0x01))
+	    continue;
+	TGA_WRITE_REG(0x01, TGA_INTR_STAT_REG);
+	mb();
+	while (!(TGA_READ_REG(TGA_INTR_STAT_REG) & 0x01))
+	    continue;
+	TGA_WRITE_REG(0x01, TGA_INTR_STAT_REG);
+
+	BT463_LOAD_ADDR(BT463_WINDOW_TYPE_BASE);
+	TGA_WRITE_REG((BT463_REG_ACC<<2), TGA_RAMDAC_SETUP_REG);
+	
+	for (i = 0; i < 16; i++) {
+	    TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x01|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(0x80|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	}
+
+	/*
+	 * init cursor colors
+	 */
+	BT463_LOAD_ADDR(BT463_CUR_CLR_0);
+
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG); /* background */
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG); /* background */
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG); /* background */
+
+	TGA_WRITE_REG(0xff|(BT463_REG_ACC<<10), TGA_RAMDAC_REG); /* foreground */
+	TGA_WRITE_REG(0xff|(BT463_REG_ACC<<10), TGA_RAMDAC_REG); /* foreground */
+	TGA_WRITE_REG(0xff|(BT463_REG_ACC<<10), TGA_RAMDAC_REG); /* foreground */
+
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+	TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+
+	/*
+	 * finally, init the cursor shape
+	 */
+	temp = tga_fb_base - 1024; /* this assumes video starts at base
+				     and base is beyond memory start*/
+
+	for (i = 0; i < 256; i++) {
+	    writel(bt463_cursor_source[i], temp + i*4);
+	}
+	TGA_WRITE_REG(temp & 0x000fffff, TGA_CURSOR_BASE_REG);
+    }
+
+    /* finally, enable video scan & cursor
+       (and pray for the monitor... :-) */
+    TGA_WRITE_REG(0x05, TGA_VALID_REG); /* SCANNING and CURSOR */
+
+    fb_var.xres = fb_var.xres_virtual = 640;
+    fb_var.yres = fb_var.yres_virtual = 480;
+    fb_fix.line_length = 80*fb_var.bits_per_pixel;
+    fb_fix.smem_start = (char *)tga_fb_base;
+    fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
+    fb_fix.type = FB_TYPE_PACKED_PIXELS;
+    fb_fix.type_aux = 0;
+    fb_fix.mmio_start = (unsigned char *)tga_regs_base;
+    fb_fix.mmio_len = 0x1000;		/* Is this sufficient? */
+
+    fb_var.xoffset = fb_var.yoffset = 0;
+    fb_var.grayscale = 0;
+    fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0;
+    fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
+    fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
+    fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
+    fb_var.nonstd = 0;
+    fb_var.activate = 0;
+    fb_var.height = fb_var.width = -1;
+    fb_var.accel = FB_ACCEL_TGA;
+    fb_var.pixclock = 39722;
+    fb_var.left_margin = 40;
+    fb_var.right_margin = 24;
+    fb_var.upper_margin = 32;
+    fb_var.lower_margin = 11;
+    fb_var.hsync_len = 96;
+    fb_var.vsync_len = 2;
+    fb_var.sync = 0;
+    fb_var.vmode = FB_VMODE_NONINTERLACED;
+
+    disp.var = fb_var;
+    disp.cmap.start = 0;
+    disp.cmap.len = 0;
+    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
+    disp.screen_base = fb_fix.smem_start;
+    disp.visual = fb_fix.visual;
+    disp.type = fb_fix.type;
+    disp.type_aux = fb_fix.type_aux;
+    disp.ypanstep = 0;
+    disp.ywrapstep = 0;
+    disp.line_length = fb_fix.line_length;
+    disp.can_soft_blank = 1;
+    disp.inverse = 0;
+
+    strcpy(fb_info.modename, tgafb_name);
+    fb_info.node = -1;
+    fb_info.fbops = &tgafb_ops;
+    fb_info.fbvar_num = 1;
+    fb_info.fbvar = &fb_var;
+    fb_info.disp = &disp;
+    fb_info.fontname[0] = '\0';
+    fb_info.changevar = NULL;
+    fb_info.switch_con = &tgafbcon_switch;
+    fb_info.updatevar = &tgafbcon_updatevar;
+    fb_info.blank = &tgafbcon_blank;
+    fb_info.setcmap = &tgafbcon_setcmap;
+
+    err = register_framebuffer(&fb_info);
+    if (err < 0)
+	return mem_start;
+
+    tgafb_set_var(&fb_var, -1);
+
+    printk("%s frame buffer device\n", tgafb_name);
+    return mem_start;
+}
+
+
+static int tgafbcon_switch(int con)
+{
+    /* Do we have to save the colormap? */
+    if (fb_display[currcon].cmap.len)
+	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
+		    tgafb_getcolreg);
+
+    currcon = con;
+    /* Install new colormap */
+    do_install_cmap(con);
+    return 0;
+}
+
+    /*
+     *  Update the `var' structure (called by fbcon.c)
+     */
+
+static int tgafbcon_updatevar(int con)
+{
+    /* Nothing */
+    return 0;
+}
+
+    /*
+     *  Blank the display.
+     */
+
+static void tgafbcon_blank(int blank)
+{
+    /* Nothing */
+}
+
+    /*
+     *  Set the colormap
+     */
+
+static int tgafbcon_setcmap(struct fb_cmap *cmap, int con)
+{
+    return(tgafb_set_cmap(cmap, 1, con));
+}
+
+
+    /*
+     *  Read a single color register and split it into
+     *  colors/transparent. Return != 0 for invalid regno.
+     */
+
+static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp)
+{
+    if (regno > 255)
+	return 1;
+    *red = palette[regno].red;
+    *green = palette[regno].green;
+    *blue = palette[regno].blue;
+    return 0;
+}
+
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp)
+{
+    if (regno > 255)
+	return 1;
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+
+    /* How to set a single color register?? */
+
+    return 0;
+}
+
+
+#if 1
+    /*
+     *	FIXME: since I don't know how to set a single arbitrary color register,
+     *  all color palette registers have to be updated
+     */
+
+static void tga_update_palette(void)
+{
+    int i;
+
+    if (tga_type == 0) { /* 8-plane */
+	BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
+	TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+	for (i = 0; i < 256; i++) {
+	    TGA_WRITE_REG(palette[i].red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(palette[i].green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(palette[i].blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+	}
+    } else {
+	BT463_LOAD_ADDR(0x0000);
+	TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+
+	for (i = 0; i < 256; i++) {
+	    TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	    TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	}
+    }
+}
+#endif
+
+static void do_install_cmap(int con)
+{
+    if (con != currcon)
+	return;
+    if (fb_display[con].cmap.len)
+	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
+		    tgafb_setcolreg);
+    else
+	fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
+				    &fb_display[con].var, 1, tgafb_setcolreg);
+#if 1
+    tga_update_palette();
+#endif
+}
+
+
+#if 0	/* No cursor stuff yet */
+
+/*
+ * Hide the cursor from view, during blanking, usually...
+ */
+void
+hide_cursor(void)
+{
+	unsigned long flags;
+	save_flags(flags); cli();
+
+	if (tga_type == 0) {
+	  BT485_WRITE(0x20, BT485_CMD_2);
+	} else {
+	  TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
+	}
+
+	restore_flags(flags);
+}
+
+void
+set_cursor(int currcons)
+{
+  unsigned int idx, xt, yt, row, col;
+  unsigned long flags;
+
+  if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
+    return;
+
+  if (__real_origin != __origin)
+    __set_origin(__real_origin);
+
+  save_flags(flags); cli();
+
+  if (deccm) {
+    idx = (pos - video_mem_base) >> 1;
+    col = idx % 80;
+    row = (idx - col) / 80;
+
+    if (tga_type == 0) { /* 8-plane */
+
+      xt = col * TGA_F_WIDTH + 64;
+      yt = row * TGA_F_HEIGHT_PADDED + 64;
+
+      /* make sure it's enabled */
+      BT485_WRITE(0x22, BT485_CMD_2); /* WIN cursor type */
+
+      BT485_WRITE(xt, BT485_CUR_LOW_X);
+      BT485_WRITE((xt >> 8), BT485_CUR_HIGH_X);
+      BT485_WRITE(yt, BT485_CUR_LOW_Y);
+      BT485_WRITE((yt >> 8), BT485_CUR_HIGH_Y);
+
+    } else {
+
+      xt = col * TGA_F_WIDTH + 144;
+      yt = row * TGA_F_HEIGHT_PADDED + 35;
+
+      TGA_WRITE_REG(0x05, TGA_VALID_REG); /* SCANNING and CURSOR */
+      TGA_WRITE_REG(xt | (yt << 12), TGA_CURSOR_XY_REG);
+    }
+
+  } else
+    hide_cursor();
+  restore_flags(flags);
+}
+
+#endif
--- m68k-2.1.64/drivers/video/txtcon.c.orig	Mon Nov 17 22:00:36 1997
+++ m68k-2.1.64/drivers/video/txtcon.c	Sun Nov 23 23:33:09 1997
@@ -39,6 +39,7 @@
 static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
 static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data);
 static int txtcon_set_palette(struct vc_data *conp, unsigned char *table);
+static int txtcon_scrolldelta(int lines);
 
 
 static int txtcon_startup(u_long *kmem_start, const char **display_desc)
@@ -54,7 +55,7 @@
 
 static int txtcon_deinit(struct vc_data *conp)
 {
-   return(0);
+   return 0;
 }
 
 
@@ -66,69 +67,75 @@
 static int txtcon_clear(struct vc_data *conp, int sy, int sx, int height,
                         int width)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_putc(struct vc_data *conp, int c, int y, int x)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_putcs(struct vc_data *conp, const char *s, int count, int y,
                         int x)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_cursor(struct vc_data *conp, int mode)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
                         int height, int width)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_switch(struct vc_data *conp)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_blank(int blank)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data)
 {
-   return(0);
+   return -ENOSYS;
 }
 
 
 static int txtcon_set_palette(struct vc_data *conp, unsigned char *table)
 {
-   return(0);
+   return -ENOSYS;
+}
+
+
+static int txtcon_scrolldelta(int lines)
+{
+   return -ENOSYS;
 }
 
 
@@ -141,5 +148,6 @@
 struct consw txt_con = {
    txtcon_startup, txtcon_init, txtcon_deinit, txtcon_clear, txtcon_putc,
    txtcon_putcs, txtcon_cursor, txtcon_scroll, txtcon_bmove, txtcon_switch,
-   txtcon_blank, txtcon_get_font, txtcon_set_font, txtcon_set_palette
+   txtcon_blank, txtcon_get_font, txtcon_set_font, txtcon_set_palette,
+   txtcon_scrolldelta
 };
--- m68k-2.1.64/drivers/video/vfb.c.orig	Thu Nov 20 22:53:33 1997
+++ m68k-2.1.64/drivers/video/vfb.c	Sun Nov 23 23:33:09 1997
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/fb/vfb.c -- Virtual frame buffer device
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
  *
  *	Copyright (C) 1997 Geert Uytterhoeven
  *
--- m68k-2.1.64/drivers/video/vgacon.c.orig	Sun Nov 23 23:33:09 1997
+++ m68k-2.1.64/drivers/video/vgacon.c	Sun Nov 23 23:33:09 1997
@@ -0,0 +1,591 @@
+/*
+ *  linux/drivers/video/vgacon.c -- Low level VGA based console driver
+ *
+ *	Created 28 Sep 1997 by Geert Uytterhoeven
+ *
+ *  This file is based on the old console.c, vga.c and vesa_blank.c drivers.
+ *
+ *	Copyright (C) 1991, 1992  Linus Torvalds
+ *			    1995  Jay Estabrook
+ *
+ *	User definable mapping table and font loading by Eugene G. Crosser,
+ *	<crosser@pccross.msk.su>
+ *
+ *	Improved loadable font/UTF-8 support by H. Peter Anvin
+ *	Feb-Sep 1995 <peter.anvin@linux.org>
+ *
+ *	Colour palette handling, by Simon Tatham
+ *	17-Jun-95 <sgt20@cam.ac.uk>
+ *
+ *	if 512 char mode is already enabled don't re-enable it,
+ *	because it causes screen to flicker, by Mitja Horvat
+ *	5-May-96 <mitja.horvat@guest.arnes.si>
+ *
+ *	Use 2 outw instead of 4 outb_p to reduce erroneous text
+ *	flashing on RHS of screen during heavy console scrolling .
+ *	Oct 1996, Paul Gortmaker.
+ *
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+
+
+
+/* KNOWN PROBLEMS/TO DO ===================================================== *
+ *
+ *	- monochrome attribute encoding (convert abscon <-> VGA style)
+ *
+ *	- speed up scrolling by changing the screen origin
+ *
+ *	- add support for palette, loadable fonts and VESA blanking
+ *
+ * KNOWN PROBLEMS/TO DO ==================================================== */
+
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/linux_logo.h>
+
+
+#define BLANK 0x0020
+
+#define CAN_LOAD_EGA_FONTS	/* undefine if the user must not do this */
+#define CAN_LOAD_PALETTE	/* undefine if the user must not do this */
+
+#define dac_reg	(0x3c8)
+#define dac_val	(0x3c9)
+
+#ifdef __powerpc__
+#define VGA_OFFSET _ISA_MEM_BASE;
+#else
+#define VGA_OFFSET 0x0
+#endif
+
+
+/*
+ *  Interface used by the world
+ */
+
+static unsigned long vgacon_startup(unsigned long kmem_start,
+				   const char **display_desc);
+static void vgacon_init(struct vc_data *conp);
+static int vgacon_deinit(struct vc_data *conp);
+static int vgacon_clear(struct vc_data *conp, int sy, int sx, int height,
+		       int width);
+static int vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos);
+static int vgacon_putcs(struct vc_data *conp, const char *s, int count,
+		       int ypos, int xpos);
+static int vgacon_cursor(struct vc_data *conp, int mode);
+static int vgacon_scroll(struct vc_data *conp, int t, int b,
+			int dir, int count);
+static int vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+		       int height, int width);
+static int vgacon_switch(struct vc_data *conp);
+static int vgacon_blank(int blank);
+static int vgacon_get_font(struct vc_data *conp, int *w, int *h, char *data);
+static int vgacon_set_font(struct vc_data *conp, int w, int h, char *data);
+static int vgacon_set_palette(struct vc_data *conp, unsigned char *table);
+static int vgacon_scrolldelta(int lines);
+
+
+/*
+ *  Internal routines
+ */
+
+static int vgacon_show_logo(void);
+
+
+/* Description of the hardware situation */
+static unsigned long   vga_video_mem_base;	/* Base of video memory */
+static unsigned long   vga_video_mem_term;	/* End of video memory */
+static unsigned short  vga_video_port_reg;	/* Video register select port */
+static unsigned short  vga_video_port_val;	/* Video register value port */
+static unsigned long   vga_video_num_columns;	/* Number of text columns */
+static unsigned long   vga_video_num_lines;	/* Number of text lines */
+static unsigned long   vga_video_size_row;
+static unsigned long   vga_video_screen_size;
+
+static int vga_can_do_color = 0;
+static unsigned long vga_default_font_height;	/* Height of default screen font */
+
+static unsigned char vga_video_type;
+static unsigned char vga_has_wrapped;		/* all of videomem is data of fg_console */
+static unsigned char vga_hardscroll_enabled;
+static unsigned char vga_hardscroll_disabled_by_init = 0;
+
+
+
+    /*
+     *  VGA screen access
+     */ 
+
+static inline void vga_writew(unsigned short val, unsigned short * addr)
+{
+#ifdef __powerpc__
+	st_le16(addr, val);
+#else
+	writew(val, (unsigned long) addr);
+#endif /* !__powerpc__ */
+}
+
+static inline unsigned short vga_readw(unsigned short * addr)
+{
+#ifdef __powerpc__
+	return ld_le16(addr);
+#else
+	return readw((unsigned long) addr);
+#endif /* !__powerpc__ */	
+}
+
+static inline void vga_memsetw(void * s, unsigned short c, unsigned int count)
+{
+	unsigned short * addr = (unsigned short *) s;
+
+	while (count) {
+		count--;
+		vga_writew(c, addr++);
+	}
+}
+
+static inline void vga_memmovew(unsigned short *to, unsigned short *from,
+				unsigned int count)
+{
+	if (to < from) {
+	    while (count) {
+		    count--;
+		    vga_writew(vga_readw(from++), to++);
+	    }
+	} else {
+	    from += count;
+	    to += count;
+	    while (count) {
+		    count--;
+		    vga_writew(vga_readw(--from), --to);
+	    }
+	}
+}
+
+
+/*
+ * By replacing the four outb_p with two back to back outw, we can reduce
+ * the window of opportunity to see text mislocated to the RHS of the
+ * console during heavy scrolling activity. However there is the remote
+ * possibility that some pre-dinosaur hardware won't like the back to back
+ * I/O. Since the Xservers get away with it, we should be able to as well.
+ */
+static inline void write_vga(unsigned char reg, unsigned int val)
+{
+#ifndef SLOW_VGA
+	unsigned int v1, v2;
+
+	v1 = reg + (val & 0xff00);
+	v2 = reg + 1 + ((val << 8) & 0xff00);
+	outw(v1, vga_video_port_reg);
+	outw(v2, vga_video_port_reg);
+#else
+	outb_p(reg, vga_video_port_reg);
+	outb_p(val >> 8, vga_video_port_val);
+	outb_p(reg+1, vga_video_port_reg);
+	outb_p(val & 0xff, vga_video_port_val);
+#endif
+}
+
+
+__initfunc(static unsigned long vgacon_startup(unsigned long kmem_start,
+					       const char **display_desc))
+{
+	unsigned short saved;
+	unsigned short *p;
+
+	/*
+	 *	Find out if there is a graphics card present.
+	 *	Are there smarter methods around?
+	 */
+	p = (unsigned short *)(((ORIG_VIDEO_MODE == 7) ? 0xb0000 : 0xb8000) +
+			       + VGA_OFFSET);
+	saved = vga_readw(p);
+	vga_writew(0xAA55, p);
+	if (vga_readw(p) != 0xAA55) {
+		vga_writew(saved, p);
+		return kmem_start;
+	}
+	vga_writew(0x55AA, p);
+	if (vga_readw(p) != 0x55AA) {
+		vga_writew(saved, p);
+		return kmem_start;
+	}
+	vga_writew(saved, p);
+
+	vga_video_num_lines = ORIG_VIDEO_LINES;
+	vga_video_num_columns = ORIG_VIDEO_COLS;
+	vga_video_size_row = 2 * ORIG_VIDEO_COLS;
+	vga_video_screen_size = vga_video_num_lines * vga_video_size_row;
+
+	if (ORIG_VIDEO_MODE == 7)	/* Is this a monochrome display? */
+	{
+		vga_video_mem_base = 0xb0000 + VGA_OFFSET;
+		vga_video_port_reg = 0x3b4;
+		vga_video_port_val = 0x3b5;
+		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
+		{
+			vga_video_type = VIDEO_TYPE_EGAM;
+			vga_video_mem_term = 0xb8000 + VGA_OFFSET;
+			*display_desc = "EGA+";
+			request_region(0x3b0,16,"ega");
+		}
+		else
+		{
+			vga_video_type = VIDEO_TYPE_MDA;
+			vga_video_mem_term = 0xb2000 + VGA_OFFSET;
+			*display_desc = "*MDA";
+			request_region(0x3b0,12,"mda");
+			request_region(0x3bf, 1,"mda");
+		}
+	}
+	else				/* If not, it is color. */
+	{
+		vga_can_do_color = 1;
+		vga_video_mem_base = 0xb8000  + VGA_OFFSET;
+		vga_video_port_reg	= 0x3d4;
+		vga_video_port_val	= 0x3d5;
+		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
+		{
+			int i ;
+
+			vga_video_mem_term = 0xc0000 + VGA_OFFSET;
+
+			if (!ORIG_VIDEO_ISVGA) {
+				vga_video_type = VIDEO_TYPE_EGAC;
+				*display_desc = "EGA";
+				request_region(0x3c0,32,"ega");
+			} else {
+				vga_video_type = VIDEO_TYPE_VGAC;
+				*display_desc = "VGA+";
+				request_region(0x3c0,32,"vga+");
+
+#ifdef VGA_CAN_DO_64KB
+				/*
+				 * get 64K rather than 32K of video RAM.
+				 * This doesn't actually work on all "VGA"
+				 * controllers (it seems like setting MM=01
+				 * and COE=1 isn't necessarily a good idea)
+				 */
+				vga_video_mem_base = 0xa0000  + VGA_OFFSET;
+				vga_video_mem_term = 0xb0000  + VGA_OFFSET;
+				outb_p (6, 0x3ce) ;
+				outb_p (6, 0x3cf) ;
+#endif
+
+				/*
+				 * Normalise the palette registers, to point
+				 * the 16 screen colours to the first 16
+				 * DAC entries.
+				 */
+
+				for (i=0; i<16; i++) {
+					inb_p (0x3da) ;
+					outb_p (i, 0x3c0) ;
+					outb_p (i, 0x3c0) ;
+				}
+				outb_p (0x20, 0x3c0) ;
+
+				/* now set the DAC registers back to their
+				 * default values */
+
+				for (i=0; i<16; i++) {
+					outb_p (color_table[i], 0x3c8) ;
+					outb_p (default_red[i], 0x3c9) ;
+					outb_p (default_grn[i], 0x3c9) ;
+					outb_p (default_blu[i], 0x3c9) ;
+				}
+			}
+		}
+		else
+		{
+			vga_video_type = VIDEO_TYPE_CGA;
+			vga_video_mem_term = 0xba000 + VGA_OFFSET;
+			*display_desc = "*CGA";
+			request_region(0x3d4,2,"cga");
+		}
+	}
+
+	vga_hardscroll_enabled = (vga_hardscroll_disabled_by_init ? 0 :
+	  (vga_video_type == VIDEO_TYPE_EGAC
+	    || vga_video_type == VIDEO_TYPE_VGAC
+	    || vga_video_type == VIDEO_TYPE_EGAM));
+	vga_has_wrapped = 0;
+
+	if (vga_video_type == VIDEO_TYPE_VGAC
+	    || vga_video_type == VIDEO_TYPE_EGAC
+	    || vga_video_type == VIDEO_TYPE_EGAM)
+	{
+		vga_default_font_height = ORIG_VIDEO_POINTS;
+		video_font_height = ORIG_VIDEO_POINTS;
+		/* This may be suboptimal but is a safe bet - go with it */
+		video_scan_lines =
+			video_font_height * vga_video_num_lines;
+	}
+
+	if (!console_show_logo)
+	    console_show_logo = vgacon_show_logo;
+
+	return kmem_start;
+}
+
+
+static void vgacon_init(struct vc_data *conp)
+{
+    conp->vc_cols = vga_video_num_columns;
+    conp->vc_rows = vga_video_num_lines;
+    conp->vc_can_do_color = vga_can_do_color;
+}
+
+static int vgacon_deinit(struct vc_data *conp)
+{
+    return 0;
+}
+
+
+/* ====================================================================== */
+
+static int vgacon_clear(struct vc_data *conp, int sy, int sx, int height,
+			      int width)
+{
+    int rows;
+    unsigned long dest;
+
+    if (console_blanked)
+	return 0;
+
+    dest = vga_video_mem_base + sy*vga_video_size_row + sx*2;
+    if (sx == 0 && width == vga_video_num_columns)      
+	vga_memsetw((void *)dest, conp->vc_video_erase_char, height * width);
+    else
+        for (rows = height; rows-- ; dest += vga_video_size_row)
+	    vga_memsetw((void *)dest, conp->vc_video_erase_char, width);
+    return 0;
+}
+
+
+static int vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos)
+{
+    u_short *p;
+
+    if (console_blanked)
+	    return 0;
+
+    p = (u_short *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2);
+    vga_writew(conp->vc_attr << 8 | c, p);
+    return 0;
+}
+
+
+static int vgacon_putcs(struct vc_data *conp, const char *s, int count,
+		       int ypos, int xpos)
+{
+    u_short *p;
+    u_short sattr;
+
+    if (console_blanked)
+	    return 0;
+
+    p = (u_short *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2);
+    sattr = conp->vc_attr << 8;
+    while (count--)
+	vga_writew(sattr | *s++, p++);
+    return 0;
+}
+
+
+static int vgacon_cursor(struct vc_data *conp, int mode)
+{
+    switch (mode) {
+	case CM_ERASE:
+	    write_vga(14, (vga_video_mem_term - vga_video_mem_base - 1)>>1);
+	    break;
+
+	case CM_MOVE:
+	case CM_DRAW:
+	    write_vga(14, conp->vc_y*vga_video_num_columns+conp->vc_x);
+	    break;
+    }
+    return 0;
+}
+
+
+static int vgacon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
+{
+    if (console_blanked)
+	return 0;
+
+    vgacon_cursor(conp, CM_ERASE);
+
+    switch (dir) {
+	case SM_UP:
+	    if (count > conp->vc_rows)	/* Maximum realistic size */
+		count = conp->vc_rows;
+	    vgacon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+	    vgacon_clear(conp, b-count, 0, count, conp->vc_cols);
+	    break;
+
+	case SM_DOWN:
+	    if (count > conp->vc_rows)	/* Maximum realistic size */
+		count = conp->vc_rows;
+	    /*
+	     *  Fixed bmove() should end Arno's frustration with copying?
+	     *  Confucius says:
+	     *	Man who copies in wrong direction, end up with trashed
+	     *	data
+	     */
+	    vgacon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+	    vgacon_clear(conp, t, 0, count, conp->vc_cols);
+	    break;
+
+	case SM_LEFT:
+	    vgacon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
+	    vgacon_clear(conp, 0, b-count, conp->vc_rows, count);
+	    break;
+
+	case SM_RIGHT:
+	    vgacon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
+	    vgacon_clear(conp, 0, t, conp->vc_rows, count);
+	    break;
+    }
+
+    return 0;
+}
+
+
+static int vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+		       int height, int width)
+{
+    unsigned long src, dst;
+    int rows;
+
+    if (console_blanked)
+	return 0;
+
+    if (sx == 0 && dx == 0 && width == vga_video_num_columns) {
+	src = vga_video_mem_base + sy * vga_video_size_row;
+	dst = vga_video_mem_base + dy * vga_video_size_row;
+	vga_memmovew((unsigned short *)dst, (unsigned short *)src,
+		     height * width);
+    } else if (dy < sy || (dy == sy && dx < sx)) {
+	src = vga_video_mem_base + sy * vga_video_size_row + sx * 2;
+	dst = vga_video_mem_base + dy * vga_video_size_row + dx * 2;
+	for (rows = height; rows-- ;) {
+	    vga_memmovew((unsigned short *)dst, (unsigned short *)src, width);
+	    src += vga_video_size_row;
+	    dst += vga_video_size_row;
+	}
+    } else {
+	src = vga_video_mem_base + (sy+height-1) * vga_video_size_row + sx * 2;
+	dst = vga_video_mem_base + (dy+height-1) * vga_video_size_row + dx * 2;
+	for (rows = height; rows-- ;) {
+	    vga_memmovew((unsigned short *)dst, (unsigned short *)src, width);
+	    src -= vga_video_size_row;
+	    dst -= vga_video_size_row;
+	}
+    }
+    return 0;
+}
+
+
+static int vgacon_switch(struct vc_data *conp)
+{
+    return 0;
+}
+
+
+static int vgacon_blank(int blank)
+{
+    if (blank) {
+	vga_memsetw((void *)vga_video_mem_base, BLANK, vga_video_screen_size/2);
+	return 0;
+    } else {
+	/* Tell console.c that it has to restore the screen itself */
+	return(1);
+    }
+    return 0;
+}
+
+
+static int vgacon_get_font(struct vc_data *conp, int *w, int *h, char *data)
+{
+    /* TODO */
+    return -ENOSYS;
+}
+
+
+static int vgacon_set_font(struct vc_data *conp, int w, int h, char *data)
+{
+    /* TODO */
+    return -ENOSYS;
+}
+
+static int vgacon_set_palette(struct vc_data *conp, unsigned char *table)
+{
+	int i, j ;
+
+	if (vga_video_type != VIDEO_TYPE_VGAC || console_blanked ||
+	    vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+		return -EINVAL;
+
+	for (i=j=0; i<16; i++) {
+		outb_p (table[i], dac_reg) ;
+		outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
+		outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
+		outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
+	}
+	return 0;
+}
+
+static int vgacon_scrolldelta(int lines)
+{
+    /* TODO */
+    return -ENOSYS;
+}
+
+
+__initfunc(static int vgacon_show_logo( void ))
+{
+    int height = 0;
+    char *p;
+
+    printk(linux_serial_image);
+    for (p = linux_serial_image; *p; p++)
+	if (*p == '\n')
+	    height++;
+    return height;
+}
+
+
+
+/*
+ *  The console `switch' structure for the VGA based console
+ */
+
+struct consw vga_con = {
+    vgacon_startup, vgacon_init, vgacon_deinit, vgacon_clear, vgacon_putc,
+    vgacon_putcs, vgacon_cursor, vgacon_scroll, vgacon_bmove, vgacon_switch,
+    vgacon_blank, vgacon_get_font, vgacon_set_font, vgacon_set_palette,
+    vgacon_scrolldelta
+};

Greetings,

						Geert

--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/{m68k~Amiga,PPC~CHRP}  http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium

