patch-2.3.14 linux/drivers/video/clgenfb.c

Next file: linux/drivers/video/clgenfb.h
Previous file: linux/drivers/video/chipsfb.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.13/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
@@ -1,7 +1,38 @@
 /*
- * Based on retz3fb.c and clgen.c
+ * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets
+ *
+ * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ *
+ * Contributors (thanks, all!)
+ *
+ *      Jeff Rugen:
+ *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
+ *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
+ *
+ *	Geert Uytterhoeven:
+ *	Excellent code review.
+ *
+ *	Lars Hecking:
+ *	Amiga updates and testing.
+ *
+ * Original clgenfb author:  Frank Neumann
+ *
+ * Based on retz3fb.c and clgen.c:
+ *      Copyright (C) 1997 Jes Sorensen
+ *      Copyright (C) 1996 Frank Neumann
+ *
+ ***************************************************************
+ *
+ * Format this code with GNU indent '-kr -i8 -pcs' options.
+ *
+ * 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.
+ *
  */
- 
+
+#define CLGEN_VERSION "1.9.4.1"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -11,12 +42,22 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/zorro.h>
 #include <linux/init.h>
-#include <asm/amigahw.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/io.h>
+#ifdef CONFIG_ZORRO
+#include <linux/zorro.h>
+#endif
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+#ifdef CONFIG_AMIGA
+#include <asm/amigahw.h>
+#endif
+#ifdef CONFIG_FB_OF
+#include <asm/prom.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-mfb.h>
@@ -26,125 +67,322 @@
 #include <video/fbcon-cfb32.h>
 
 #include "clgenfb.h"
+#include "vga.h"
 
-#define CLGEN_VERSION "1.4 ?"
-/* #define DEBUG if(1) */
-#define DEBUG if(0)
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+
+/* enable debug output? */
+/* #define CLGEN_DEBUG 1 */
+
+/* disable runtime assertions? */
+/* #define CLGEN_NDEBUG */
+
+
+/* debug output */
+#ifdef CLGEN_DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+/* debugging assertions */
+#ifndef CLGEN_NDEBUG
+#define assert(expr) \
+        if(!(expr)) { \
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+        #expr,__FILE__,__FUNCTION__,__LINE__); \
+        *(int*)0 = 0;\
+        }
+#else
+#define assert(expr)
+#endif
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
 
-/* board types */
-#define BT_NONE     0
-#define BT_SD64     1
-#define BT_PICCOLO  2
-#define BT_PICASSO  3
-#define BT_SPECTRUM 4
-#define BT_PICASSO4 5
+#ifdef TRUE
+#undef TRUE
+#endif
+#ifdef FALSE
+#undef FALSE
+#endif
+#define TRUE  1
+#define FALSE 0
+
+#define MB_ (1024*1024)
 
 #define MAX_NUM_BOARDS 7
 
-#define TRUE  1
-#define FALSE 0 
 
-struct clgenfb_par
-{
-    struct fb_var_screeninfo var;
+/* board types */
+typedef enum {
+	BT_NONE = 0,
+	BT_SD64,
+	BT_PICCOLO,
+	BT_PICASSO,
+	BT_SPECTRUM,
+	BT_PICASSO4,	/* GD5446 */
+	BT_ALPINE,	/* GD543x/4x */
+	BT_GD5480,
+} clgen_board_t;
+
+
+
+/*
+ * per-board-type information, used for enumerating and abstracting
+ * chip-specific information
+ * NOTE: MUST be in the same order as clgen_board_t in order to
+ * use direct indexing on this array
+ * NOTE: '__initdata' cannot be used as some of this info
+ * is required at runtime.  Maybe separate into an init-only and
+ * a run-time table?
+ */
+static const struct clgen_board_info_rec {
+	clgen_board_t btype;	/* chipset enum, not strictly necessary, as
+				 * clgen_board_info[] is directly indexed
+				 * by this value */
+	char *name;		/* ASCII name of chipset */
+	long maxclock;		/* maximum video clock */
+	unsigned write_sr1f : 1; /* write SR1F during init_vgachip() */
+	unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
+	unsigned char sr07;	/* SR07 VGA register value */
+	unsigned char sr1f;	/* SR1F VGA register value */
+} clgen_board_info[] = {
+	{ BT_NONE, }, /* dummy record */
+	{ BT_SD64,
+		"CL SD64",
+		140000,		/* the SD64/P4 have a higher max. videoclock */
+		TRUE,		
+		TRUE,		
+		0xf0,		
+		0x20 },		
+	{ BT_PICCOLO,
+		"CL Piccolo",
+		90000,		
+		TRUE,
+		FALSE,
+		0x80,
+		0x22 },
+	{ BT_PICASSO,
+		"CL Picasso",
+		90000,
+		TRUE,
+		FALSE,
+		0x20,
+		0x22 },
+	{ BT_SPECTRUM,
+		"CL Spectrum",
+		90000,
+		TRUE,
+		FALSE,
+		0x80,
+		0x22 },
+	{ BT_PICASSO4,
+		"CL Picasso4",
+		140000,		/* the SD64/P4 have a higher max. videoclock */
+		FALSE,
+		TRUE,
+		0x20,
+		0 },
+	{ BT_ALPINE,
+		"CL Alpine",
+		110000,		/* 135100 for some, 85500 for others */
+		TRUE,
+		TRUE,
+		0xA0,
+		0x1C },
+	{ BT_GD5480,
+		"CL GD5480",
+		90000,
+		TRUE,
+		TRUE,
+		0x10,
+		0x1C },
+};
+
 
-    __u32 line_length;  /* in BYTES! */
-    __u32 visual;
-    __u32 type;
-
-    long freq;
-    long nom;
-    long den;
-    long div;
-
-    long HorizRes;   /* The x resolution in pixel */
-    long HorizTotal;
-    long HorizDispEnd;
-    long HorizBlankStart;
-    long HorizBlankEnd;
-    long HorizSyncStart;
-    long HorizSyncEnd;
-
-    long VertRes;   /* the physical y resolution in scanlines */
-    long VertTotal;
-    long VertDispEnd;
-    long VertSyncStart;
-    long VertSyncEnd;
-    long VertBlankStart;
-    long VertBlankEnd;
+#ifdef CONFIG_PCI
+/* the list of PCI devices for which we probe, and the
+ * order in which we do it */
+static const struct {
+	clgen_board_t btype;
+	unsigned short device;
+} clgen_pci_probe_list[] __initdata = {
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5436 },
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5434_8 },
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5434_4 },
+	{ BT_ALPINE, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
+	{ BT_GD5480, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
+	{ BT_PICASSO4, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
 };
+#endif /* CONFIG_PCI */
+
+
+
+#ifdef CONFIG_ZORRO
+static const struct {
+	clgen_board_t btype;
+	int key, key2;
+} clgen_zorro_probe_list[] __initdata = {
+	{ BT_SD64,
+		ZORRO_PROD_HELFRICH_SD64_RAM,
+		ZORRO_PROD_HELFRICH_SD64_REG },
+	{ BT_PICCOLO,
+		ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+		ZORRO_PROD_HELFRICH_PICCOLO_REG },
+	{ BT_PICASSO,
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG },
+	{ BT_SPECTRUM,
+		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG },
+	{ BT_PICASSO4,
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
+		0 },
+};
+#endif /* CONFIG_ZORRO */
+
+
+
+struct clgenfb_par {
+	struct fb_var_screeninfo var;
+
+	__u32 line_length;	/* in BYTES! */
+	__u32 visual;
+	__u32 type;
+
+	long freq;
+	long nom;
+	long den;
+	long div;
+	long multiplexing;
+	long mclk;
+	long divMCLK;
+
+	long HorizRes;		/* The x resolution in pixel */
+	long HorizTotal;
+	long HorizDispEnd;
+	long HorizBlankStart;
+	long HorizBlankEnd;
+	long HorizSyncStart;
+	long HorizSyncEnd;
+
+	long VertRes;		/* the physical y resolution in scanlines */
+	long VertTotal;
+	long VertDispEnd;
+	long VertSyncStart;
+	long VertSyncEnd;
+	long VertBlankStart;
+	long VertBlankEnd;
+};
+
+
+
+#ifdef CLGEN_DEBUG
+typedef enum {
+        CRT,
+        SEQ
+} clgen_dbg_reg_class_t;
+#endif                          /* CLGEN_DEBUG */
+
+
+
 
 /* info about board */
-struct clgenfb_info
-{
-    struct fb_info_gen gen;
+struct clgenfb_info {
+	struct fb_info_gen gen;
 
-    int keyRAM;  /* RAM, REG zorro board keys */
-    int keyREG;
-    unsigned long fbmem;
-    volatile unsigned char *regs;
-    unsigned long mem;
-    unsigned long size;
-    int btype;
-    int smallboard;
-    unsigned char SFR; /* Shadow of special function register */
-
-    unsigned long fbmem_phys;
-    unsigned long fbregs_phys;
-    
-    struct clgenfb_par currentmode;
-    union {
+	caddr_t fbmem;
+	caddr_t regs;
+	caddr_t mem;
+	unsigned long size;
+	clgen_board_t btype;
+	int smallboard;
+	unsigned char SFR;	/* Shadow of special function register */
+
+	unsigned long fbmem_phys;
+	unsigned long fbregs_phys;
+
+	struct clgenfb_par currentmode;
+	union {
 #ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
+		u16 cfb16[16];
 #endif
 #ifdef FBCON_HAS_CFB24
-	u32 cfb24[16];
+		u32 cfb24[16];
 #endif
 #ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
+		u32 cfb32[16];
+#endif
+	} fbcon_cmap;
+
+#ifdef CONFIG_ZORRO
+	int keyRAM;		/* RAM, REG zorro board keys */
+	int keyREG;
+#endif
+
+#ifdef CONFIG_PCI
+	struct pci_dev *pdev;
 #endif
-    } fbcon_cmap;
 };
 
+
+
+
 static struct display disp;
 
-static struct clgenfb_info boards[MAX_NUM_BOARDS];  /* the boards */
-static struct clgenfb_info *fb_info=NULL;  /* pointer to current board */
+static struct clgenfb_info boards[MAX_NUM_BOARDS];	/* the boards */
+
+static unsigned clgen_def_mode = 0;
+
+
 
 /*
  *    Predefined Video Modes
  */
 
-static struct fb_videomode clgenfb_predefined[] __initdata =
+static const struct {
+	const char *name;
+	struct fb_var_screeninfo var;
+} clgenfb_predefined[] __initdata =
+
 {
-	{   "Autodetect", /* autodetect mode */
-	    { 0 }
+	{"Autodetect",		/* autodetect mode */
+	 {0}
 	},
 
-	{   "640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
-	    { 
-		640, 480, 640, 480, 0, 0, 8, 0, 
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
-		0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
+	{"640x480",		/* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
+	 {
+		 640, 480, 640, 480, 0, 0, 8, 0,
+		 {0, 8, 0},
+		 {0, 8, 0},
+		 {0, 8, 0},
+		 {0, 0, 0},
+	       0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2,
+     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	 }
 	},
 
-	/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
 	/* 
-	    Modeline from XF86Config:
-	    Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
-	*/
-	{
-	    "1024x768",
-	    { 
-		1024, 768, 1024, 768, 0, 0, 8, 0, 
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
-		0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
+	   Modeline from XF86Config:
+	   Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
+	 */
+	{"1024x768",		/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
+		{
+			1024, 768, 1024, 768, 0, 0, 8, 0,
+			{0, 8, 0},
+			{0, 8, 0},
+			{0, 8, 0},
+			{0, 0, 0},
+	      0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
+     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+		}
 	}
 };
 
@@ -155,135 +393,187 @@
  *    Frame Buffer Name
  */
 
-static char clgenfb_name[16] = "CLgen";
+static const char *clgenfb_name = "CLgen";
 
 /****************************************************************************/
 /**** BEGIN PROTOTYPES ******************************************************/
 
+
 /*--- Interface used by the world ------------------------------------------*/
-void clgenfb_init(void);
-void clgenfb_setup(char *options, int *ints);
-int clgenfb_open(struct fb_info *info, int user);
-int clgenfb_release(struct fb_info *info, int user);
-int clgenfb_ioctl(struct inode *inode, struct file *file, 
-		  unsigned int cmd, unsigned long arg, int con, 
-		  struct fb_info *info);
+int clgenfb_init (void);
+int clgenfb_setup (char *options);
+
+#ifdef MODULE
+static void clgenfb_cleanup (struct clgenfb_info *info);
+#endif
+
+static int clgenfb_open (struct fb_info *info, int user);
+static int clgenfb_release (struct fb_info *info, int user);
+static int clgenfb_ioctl (struct inode *inode, struct file *file,
+		   unsigned int cmd, unsigned long arg, int con,
+		   struct fb_info *info);
+#if defined(CONFIG_FB_OF)
+int clgen_of_init (struct device_node *dp);
+#endif
 
 /* function table of the above functions */
 static struct fb_ops clgenfb_ops =
 {
-    clgenfb_open,
-    clgenfb_release,
-    fbgen_get_fix,   /* using the generic functions */
-    fbgen_get_var,   /* makes things much easier... */
-    fbgen_set_var,
-    fbgen_get_cmap,
-    fbgen_set_cmap,
-    fbgen_pan_display,
-    clgenfb_ioctl,
-    NULL
+	clgenfb_open,
+	clgenfb_release,
+	fbgen_get_fix,		/* using the generic functions */
+	fbgen_get_var,		/* makes things much easier... */
+	fbgen_set_var,
+	fbgen_get_cmap,
+	fbgen_set_cmap,
+	fbgen_pan_display,
+	clgenfb_ioctl,
+	NULL
 };
 
 /*--- Hardware Specific Routines -------------------------------------------*/
-static void clgen_detect(void);
-static int  clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
+static void clgen_detect (void);
+static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
 			     struct fb_info_gen *info);
-static int  clgen_decode_var(const struct fb_var_screeninfo *var, void *par,
+static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
 			     struct fb_info_gen *info);
-static int  clgen_encode_var(struct fb_var_screeninfo *var, const void *par,
+static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
 			     struct fb_info_gen *info);
-static void clgen_get_par(void *par, struct fb_info_gen *info);
-static void clgen_set_par(const void *par, struct fb_info_gen *info);
-static int  clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info);
-static int  clgen_setcolreg(unsigned regno, unsigned red, unsigned green,
+static void clgen_get_par (void *par, struct fb_info_gen *info);
+static void clgen_set_par (const void *par, struct fb_info_gen *info);
+static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
+			    unsigned *blue, unsigned *transp,
+			    struct fb_info *info);
+static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
 			    unsigned blue, unsigned transp,
 			    struct fb_info *info);
-static int  clgen_pan_display(const struct fb_var_screeninfo *var,
+static int clgen_pan_display (const struct fb_var_screeninfo *var,
 			      struct fb_info_gen *info);
-static int  clgen_blank(int blank_mode, struct fb_info_gen *info);
+static int clgen_blank (int blank_mode, struct fb_info_gen *info);
 
-static void clgen_set_disp(const void *par, struct display *disp,
-			   struct fb_info_gen *info);
+static void clgen_set_disp (const void *par, struct display *disp,
+			    struct fb_info_gen *info);
 
 /* function table of the above functions */
-static struct fbgen_hwswitch clgen_hwswitch = 
+static struct fbgen_hwswitch clgen_hwswitch =
 {
-    clgen_detect,
-    clgen_encode_fix,
-    clgen_decode_var,
-    clgen_encode_var,
-    clgen_get_par,
-    clgen_set_par,
-    clgen_getcolreg, 
-    clgen_setcolreg,
-    clgen_pan_display,
-    clgen_blank,
-    clgen_set_disp
+	clgen_detect,
+	clgen_encode_fix,
+	clgen_decode_var,
+	clgen_encode_var,
+	clgen_get_par,
+	clgen_set_par,
+	clgen_getcolreg,
+	clgen_setcolreg,
+	clgen_pan_display,
+	clgen_blank,
+	clgen_set_disp
 };
 
 /* Text console acceleration */
 
 #ifdef FBCON_HAS_CFB8
-static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, 
+static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
 				int dy, int dx, int height, int width);
-static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, 
+static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
 				int sy, int sx, int height, int width);
 
-static struct display_switch fbcon_clgen_8 = {
-    fbcon_cfb8_setup,
-    fbcon_clgen8_bmove,
-    fbcon_clgen8_clear,
-    fbcon_cfb8_putc,
-    fbcon_cfb8_putcs,
-    fbcon_cfb8_revc,
-    NULL,
-    NULL,
-    fbcon_cfb8_clear_margins,
-    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+static struct display_switch fbcon_clgen_8 =
+{
+	fbcon_cfb8_setup,
+	fbcon_clgen8_bmove,
+	fbcon_clgen8_clear,
+	fbcon_cfb8_putc,
+	fbcon_cfb8_putcs,
+	fbcon_cfb8_revc,
+	NULL,
+	NULL,
+	fbcon_cfb8_clear_margins,
+	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
+};
+#endif
+#ifdef FBCON_HAS_CFB16
+static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width);
+static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+static struct display_switch fbcon_clgen_16 =
+{
+	fbcon_cfb16_setup,
+	fbcon_clgen16_bmove,
+	fbcon_clgen16_clear,
+	fbcon_cfb16_putc,
+	fbcon_cfb16_putcs,
+	fbcon_cfb16_revc,
+	NULL,
+	NULL,
+	fbcon_cfb16_clear_margins,
+	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width);
+static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+static struct display_switch fbcon_clgen_32 =
+{
+	fbcon_cfb32_setup,
+	fbcon_clgen32_bmove,
+	fbcon_clgen32_clear,
+	fbcon_cfb32_putc,
+	fbcon_cfb32_putcs,
+	fbcon_cfb32_revc,
+	NULL,
+	NULL,
+	fbcon_cfb32_clear_margins,
+	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
 };
 #endif
 
 
 
 /*--- Internal routines ----------------------------------------------------*/
-static void init_vgachip(void);
-static void switch_monitor(int on);
-
-static void		WGen( int regnum, unsigned char val );
-static unsigned char	RGen( int regnum );
-static void		WSeq( unsigned char regnum, unsigned char val );
-static unsigned char	RSeq( unsigned char regnum );
-static void		WCrt( unsigned char regnum, unsigned char val );
-static unsigned char	RCrt( unsigned char regnum );
-static void		WGfx( unsigned char regnum, unsigned char val );
-static unsigned char	RGfx( unsigned char regnum );
-static void		WAttr( unsigned char regnum, unsigned char val );
-static void		AttrOn( void );
-static unsigned char	RAttr( unsigned char regnum );
-static void		WHDR( unsigned char val );
-static unsigned char	RHDR( void );
-static void		WSFR( unsigned char val );
-static void		WSFR2( unsigned char val );
-static void		WClut( unsigned char regnum, unsigned char red, 
-						     unsigned char green, 
-						     unsigned char blue );
-static void		RClut( unsigned char regnum, unsigned char *red, 
-						     unsigned char *green, 
-						     unsigned char *blue );
-static void		clgen_WaitBLT( void );
-static void		clgen_BitBLT (u_short curx, u_short cury,
-				      u_short destx, u_short desty,
-				      u_short width, u_short height, 
-				      u_short line_length);
-static void		clgen_RectFill (u_short x, u_short y,
-					u_short width, u_short height,
-					u_char color, u_short line_length);
-
-static void		bestclock(long freq, long *best, 
-				  long *nom, long *den, 
-				  long *div, long maxfreq);
+static void init_vgachip (struct clgenfb_info *fb_info);
+static void switch_monitor (struct clgenfb_info *fb_info, int on);
+static void WGen (const struct clgenfb_info *fb_info,
+		  int regnum, unsigned char val);
+static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum);
+static void AttrOn (const struct clgenfb_info *fb_info);
+static void WHDR (const struct clgenfb_info *fb_info, unsigned char val);
+static void WSFR (struct clgenfb_info *fb_info, unsigned char val);
+static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val);
+static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
+		   unsigned char green,
+		   unsigned char blue);
+static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
+		   unsigned char *green,
+		   unsigned char *blue);
+static void clgen_WaitBLT (caddr_t regbase);
+static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury,
+			  u_short destx, u_short desty,
+			  u_short width, u_short height,
+			  u_short line_length);
+static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y,
+			    u_short width, u_short height,
+			    u_char color, u_short line_length);
+
+static void bestclock (long freq, long *best,
+		       long *nom, long *den,
+		       long *div, long maxfreq);
+
+#ifdef CONFIG_PCI
+static struct pci_dev *clgen_pci_dev_get (clgen_board_t *btype);
+static unsigned int clgen_get_memsize (caddr_t regbase);
+static int clgen_pci_setup (struct clgenfb_info *fb_info, clgen_board_t *btype);
+#endif				/* CONFIG_PCI */
+
+#ifdef CLGEN_DEBUG
+static void clgen_dump (void);
+static void clgen_dbg_reg_dump (caddr_t regbase);
+static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...);
+static void clgen_dbg_print_byte (const char *name, unsigned char val);
+#endif /* CLGEN_DEBUG */
 
 /*** END   PROTOTYPES ********************************************************/
 /*****************************************************************************/
@@ -292,302 +582,477 @@
 static int opencount = 0;
 
 /*--- Open /dev/fbx ---------------------------------------------------------*/
-int clgenfb_open(struct fb_info *info, int user)
+static int clgenfb_open (struct fb_info *info, int user)
 {
-    MOD_INC_USE_COUNT;
-    if (opencount++ == 0) switch_monitor(1);
-    return 0;
+	MOD_INC_USE_COUNT;
+	if (opencount++ == 0)
+		switch_monitor ((struct clgenfb_info *) info, 1);
+	return 0;
 }
 
 /*--- Close /dev/fbx --------------------------------------------------------*/
-int clgenfb_release(struct fb_info *info, int user)
+static int clgenfb_release (struct fb_info *info, int user)
 {
-    if (--opencount == 0) switch_monitor(0);
-    MOD_DEC_USE_COUNT;
-    return 0;
+	if (--opencount == 0)
+		switch_monitor ((struct clgenfb_info *) info, 0);
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 /*--- handle /dev/fbx ioctl calls ------------------------------------------*/
-int clgenfb_ioctl(struct inode *inode, struct file *file,
-                  unsigned int cmd, unsigned long arg, int con,
-                  struct fb_info *info)
-{
-    printk(">clgenfb_ioctl()\n");
-    /* Nothing exciting here... */
-    printk("<clgenfb_ioctl()\n");
-    return -EINVAL;
+static int clgenfb_ioctl (struct inode *inode, struct file *file,
+		   unsigned int cmd, unsigned long arg, int con,
+		   struct fb_info *info)
+{
+	DPRINTK ("ENTER\n");
+	/* Nothing exciting here... */
+	DPRINTK ("EXIT\n");
+	return -EINVAL;
 }
-
 /**** END   Interface used by the World *************************************/
 /****************************************************************************/
 /**** BEGIN Hardware specific Routines **************************************/
 
-static void clgen_detect(void)
+static void clgen_detect (void)
 {
-    printk(">clgen_detect()\n");
-    printk("<clgen_detect()\n");
+	DPRINTK ("ENTER\n");
+	DPRINTK ("EXIT\n");
 }
 
-static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
-			    struct fb_info_gen *info)
+static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
+			     struct fb_info_gen *info)
 {
-    struct clgenfb_par  *_par  = (struct clgenfb_par*) par;
-    struct clgenfb_info *_info = (struct clgenfb_info*)info;
-    
-    memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-    strcpy(fix->id, clgenfb_name);
-	
-    fix->smem_start	= (char*)_info->fbmem_phys;
-    
-    /* monochrome: only 1 memory plane */
-    /* 8 bit and above: Use whole memory area */
-    fix->smem_len       = _par->var.bits_per_pixel == 1 ? _info->size / 4 
-							: _info->size;
-    fix->type		= _par->type;
-    fix->type_aux	= 0;
-    fix->visual		= _par->visual;
-    fix->xpanstep	= 1;
-    fix->ypanstep	= 1;
-    fix->ywrapstep	= 0;
-    fix->line_length	= _par->line_length;
-    fix->mmio_start	= (char *)_info->fbregs_phys;
-    fix->mmio_len	= 0x10000;
-    fix->accel		= FB_ACCEL_NONE;
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
+
+	memset (fix, 0, sizeof (struct fb_fix_screeninfo));
+	strcpy (fix->id, clgenfb_name);
+
+	if (_info->btype == BT_GD5480) {
+		/* Select proper byte-swapping aperture */
+		switch (_par->var.bits_per_pixel) {
+		case 1:
+		case 8:
+			fix->smem_start = (char *) _info->fbmem_phys;
+			break;
+		case 16:
+			fix->smem_start = (char *) _info->fbmem_phys + 1 * MB_;
+			break;
+		case 24:
+		case 32:
+			fix->smem_start = (char *) _info->fbmem_phys + 2 * MB_;
+			break;
+		}
+	} else {
+		fix->smem_start = (char *) _info->fbmem_phys;
+	}
 
-    return 0;
+	/* monochrome: only 1 memory plane */
+	/* 8 bit and above: Use whole memory area */
+	fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4
+	    : _info->size;
+	fix->type = _par->type;
+	fix->type_aux = 0;
+	fix->visual = _par->visual;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->line_length = _par->line_length;
+
+	/* FIXME: map region at 0xB8000 if available, fill in here */
+	fix->mmio_start = (char *) NULL;
+	fix->mmio_len = 0;
+	fix->accel = FB_ACCEL_NONE;
+
+	DPRINTK ("EXIT\n");
+	return 0;
 }
 
-static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par,
-			    struct fb_info_gen *info)
-{
-    long freq;
-    int  xres, hfront, hsync, hback;
-    int  yres, vfront, vsync, vback;
-    int  nom,den; /* translyting from pixels->bytes */
-    int  i;
-    static struct
-    {
-	int xres,yres;
-    }
-    modes[] = { {1600,1280}, {1280,1024}, {1024,768}, 
-		{800,600}, {640,480}, {-1,-1} };
-
-    struct clgenfb_par *_par = (struct clgenfb_par *)par;
-
-    fb_info = (struct clgenfb_info*)info;
-    printk("clgen_decode_var()\n");
-
-    printk("Requested: %dx%dx%d\n", var->xres,var->yres,var->bits_per_pixel);
-    printk("  virtual: %dx%d\n", var->xres_virtual,var->yres_virtual);
-    printk("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
-    printk("grayscale: %d\n", var->grayscale);
-#if 0
-    printk(" activate: 0x%x\n", var->activate);
-    printk(" pixclock: %d\n", var->pixclock);
-    printk("  htiming: %d;%d  %d\n", var->left_margin,var->right_margin,var->hsync_len);
-    printk("  vtiming: %d;%d  %d\n", var->upper_margin,var->lower_margin,var->vsync_len);
-    printk("     sync: 0x%x\n", var->sync);
-    printk("    vmode: 0x%x\n", var->vmode);
-#endif
-
-    _par->var = *var;
-
-    switch (var->bits_per_pixel)
-    {
-    case 1:  nom = 4; den = 8; break;   /* 8 pixel per byte, only 1/4th of mem usable */
-    case 8:  nom = 1; den = 1; break;   /* 1 pixel == 1 byte */
-    case 16: nom = 2; den = 1; break;   /* 2 bytes per pixel */
-    case 24: nom = 3; den = 1; break;   /* 3 bytes per pixel */
-    case 32: nom = 4; den = 1; break;	/* 4 bytes per pixel */
-    default:
-	printk("clgen: mode %dx%dx%d rejected...color depth not supported.\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return -EINVAL;
-    }
 
-    if (_par->var.xres*nom/den * _par->var.yres > fb_info->size)
-    {
-	printk("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return -EINVAL;
-    }
-    
-    /* use highest possible virtual resolution */
-    if (_par->var.xres_virtual == -1 &&
-	_par->var.yres_virtual == -1)
-    {
-	printk("clgen: using maximum available virtual resolution\n");
-	for (i=0; modes[i].xres != -1; i++)
-	{
-	    if (modes[i].xres*nom/den * modes[i].yres < fb_info->size/2)
+
+/* Get a good MCLK value */
+static long clgen_get_mclk (long freq, int bpp, long *div)
+{
+	long mclk;
+
+	assert (div != NULL);
+
+	/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
+	 * Assume a 64-bit data path for now.  The formula is: 
+	 * ((B * PCLK * 2)/W) * 1.2
+	 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
+	mclk = ((bpp / 8) * freq * 2) / 4;
+	mclk = (mclk * 12) / 10;
+	if (mclk < 50000)
+		mclk = 50000;
+	DPRINTK ("Use MCLK of %ld kHz\n", mclk);
+
+	/* Calculate value for SR1F.  Multiply by 2 so we can round up. */
+	mclk = ((mclk * 16) / 14318);
+	mclk = (mclk + 1) / 2;
+	DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
+
+	/* Determine if we should use MCLK instead of VCLK, and if so, what we
+	   * should divide it by to get VCLK */
+	switch (freq) {
+	case 24751 ... 25249:
+		*div = 2;
+		DPRINTK ("Using VCLK = MCLK/2\n");
+		break;
+	case 49501 ... 50499:
+		*div = 1;
+		DPRINTK ("Using VCLK = MCLK\n");
+		break;
+	default:
+		*div = 0;
 		break;
 	}
-	if (modes[i].xres == -1)
+
+	return mclk;
+}
+
+static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
+			     struct fb_info_gen *info)
+{
+	long freq;
+	long maxclock;
+	int xres, hfront, hsync, hback;
+	int yres, vfront, vsync, vback;
+	int nom, den;		/* translyting from pixels->bytes */
+	int i;
+	static struct {
+		int xres, yres;
+	} modes[] = { {
+			1600, 1280
+	}, {
+		1280, 1024
+	}, {
+		1024, 768
+	},
 	{
-	    printk("clgen: could not find a virtual resolution that fits into video memory!!\n");
-	    return -EINVAL;
-	}
-	_par->var.xres_virtual = modes[i].xres;
-	_par->var.yres_virtual = modes[i].yres;
+		800, 600
+	}, {
+		640, 480
+	}, {
+		-1, -1
+	}
+	};
+
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	assert (var != NULL);
+	assert (par != NULL);
+	assert (info != NULL);
+
+	DPRINTK ("ENTER\n");
+
+	DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel);
+	DPRINTK ("  virtual: %dx%d\n", var->xres_virtual, var->yres_virtual);
+	DPRINTK ("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
+	DPRINTK ("grayscale: %d\n", var->grayscale);
+
+	memset (par, 0, sizeof (struct clgenfb_par));
+
+	_par->var = *var;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		nom = 4;
+		den = 8;
+		break;		/* 8 pixel per byte, only 1/4th of mem usable */
+	case 2 ... 8:
+		_par->var.bits_per_pixel = 8;
+		nom = 1;
+		den = 1;
+		break;		/* 1 pixel == 1 byte */
+	case 9 ... 16:
+		_par->var.bits_per_pixel = 16;
+		nom = 2;
+		den = 1;
+		break;		/* 2 bytes per pixel */
+	case 17 ... 24:
+		_par->var.bits_per_pixel = 24;
+		nom = 3;
+		den = 1;
+		break;		/* 3 bytes per pixel */
+	case 25 ... 32:
+		_par->var.bits_per_pixel = 32;
+		nom = 4;
+		den = 1;
+		break;		/* 4 bytes per pixel */
+	default:
+		printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK ("EXIT - EINVAL error\n");
+		return -EINVAL;
+	}
+
+	if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) {
+		printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK ("EXIT - EINVAL error\n");
+		return -EINVAL;
+	}
+	/* use highest possible virtual resolution */
+	if (_par->var.xres_virtual == -1 &&
+	    _par->var.yres_virtual == -1) {
+		printk ("clgen: using maximum available virtual resolution\n");
+		for (i = 0; modes[i].xres != -1; i++) {
+			if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2)
+				break;
+		}
+		if (modes[i].xres == -1) {
+			printk ("clgen: could not find a virtual resolution that fits into video memory!!\n");
+			DPRINTK ("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+		_par->var.xres_virtual = modes[i].xres;
+		_par->var.yres_virtual = modes[i].yres;
 
-	printk("clgen: virtual resolution set to maximum of %dx%d\n",
-		_par->var.xres_virtual, _par->var.yres_virtual);
-    }
-    else if (_par->var.xres_virtual == -1)
-    {
-    }
-    else if (_par->var.yres_virtual == -1)
-    {
-    }
+		printk ("clgen: virtual resolution set to maximum of %dx%d\n",
+			_par->var.xres_virtual, _par->var.yres_virtual);
+	} else if (_par->var.xres_virtual == -1) {
+		/* FIXME: maximize X virtual resolution only */
+	} else if (_par->var.yres_virtual == -1) {
+		/* FIXME: maximize Y virtual resolution only */
+	}
+	if (_par->var.xoffset < 0)
+		_par->var.xoffset = 0;
+	if (_par->var.yoffset < 0)
+		_par->var.yoffset = 0;
+
+	/* truncate xoffset and yoffset to maximum if too high */
+	if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres)
+		_par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1;
+
+	if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres)
+		_par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		_par->line_length = _par->var.xres_virtual / 8;
+		_par->visual = FB_VISUAL_MONO10;
+		break;
 
-    if (_par->var.xoffset < 0) _par->var.xoffset = 0;
-    if (_par->var.yoffset < 0) _par->var.yoffset = 0;
-	
-    /* truncate xoffset and yoffset to maximum if too high */
-    if (_par->var.xoffset > _par->var.xres_virtual-_par->var.xres)
-	_par->var.xoffset = _par->var.xres_virtual-_par->var.xres -1;
-
-    if (_par->var.yoffset > _par->var.yres_virtual-_par->var.yres)
-	_par->var.yoffset = _par->var.yres_virtual-_par->var.yres -1;
-
-    switch (var->bits_per_pixel)
-    {
-    case 1:
-	_par->line_length	= _par->var.xres_virtual / 8;
-	_par->visual		= FB_VISUAL_MONO10;
-	break;
-
-    case 8:
-	_par->line_length 	= _par->var.xres_virtual;
-	_par->visual		= FB_VISUAL_PSEUDOCOLOR;
-	_par->var.red.offset    = 0;
-	_par->var.red.length    = 6;
-	_par->var.green.offset  = 0;
-	_par->var.green.length  = 6;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 6;
-	break;
-
-    case 16:
-	_par->line_length	= _par->var.xres_virtual * 2;
-	_par->visual		= FB_VISUAL_DIRECTCOLOR;
-	_par->var.red.offset    = 10;
-	_par->var.red.length    = 5;
-	_par->var.green.offset  = 5;
-	_par->var.green.length  = 5;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 5;
-	break;
-
-    case 24:
-	_par->line_length	= _par->var.xres_virtual * 3;
-	_par->visual		= FB_VISUAL_DIRECTCOLOR;
-	_par->var.red.offset    = 16;
-	_par->var.red.length    = 8;
-	_par->var.green.offset  = 8;
-	_par->var.green.length  = 8;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 8;
-	break;
-
-    case 32:
-	_par->line_length	= _par->var.xres_virtual * 4;
-	_par->visual		= FB_VISUAL_DIRECTCOLOR;
-	_par->var.red.offset    = 16;
-	_par->var.red.length    = 8;
-	_par->var.green.offset  = 8;
-	_par->var.green.length  = 8;
-	_par->var.blue.offset   = 0;
-	_par->var.blue.length   = 8;
-	break;
-    }
-    _par->var.red.msb_right = 0;
-    _par->var.green.msb_right = 0;
-    _par->var.blue.msb_right = 0;
-    _par->var.transp.offset = 0;
-    _par->var.transp.length = 0;
-    _par->var.transp.msb_right = 0;
-
-    _par->type		= FB_TYPE_PACKED_PIXELS;
-
-    /* convert from ps to kHz */
-    freq = 1000000000 / var->pixclock;
-
-    DEBUG printk("desired pixclock: %ld kHz\n", freq);	
-
-    /* the SD64/P4 have a higher max. videoclock */
-    bestclock(freq, &_par->freq, &_par->nom, &_par->den, &_par->div, 
-		fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4
-		? 140000 : 90000);
-
-    DEBUG printk("Best possible values for given frequency: best: %ld kHz  nom: %ld  den: %ld  div: %ld\n", 
-		 _par->freq, _par->nom, _par->den, _par->div);
-
-    xres   = _par->var.xres;
-    hfront = _par->var.right_margin;
-    hsync  = _par->var.hsync_len;
-    hback  = _par->var.left_margin;
-
-    yres   = _par->var.yres;
-    vfront = _par->var.lower_margin;
-    vsync  = _par->var.vsync_len;
-    vback  = _par->var.upper_margin;
-    
-    if (_par->var.vmode & FB_VMODE_DOUBLE)
-    {
-    	yres   *= 2;
-    	vfront *= 2;
-    	vsync  *= 2;
-    	vback  *= 2;
-    }
-    else if (_par->var.vmode & FB_VMODE_INTERLACED)
-    {
-    	yres   = ++yres   / 2;
-    	vfront = ++vfront / 2;
-    	vsync  = ++vsync  / 2;
-    	vback  = ++vback  / 2;
-    }
-
-    _par->HorizRes        = xres;
-    _par->HorizTotal      = (xres + hfront + hsync + hback)/8 - 5;
-    _par->HorizDispEnd    = xres/8 - 1;
-    _par->HorizBlankStart = xres/8;
-    _par->HorizBlankEnd   = _par->HorizTotal+5; /* does not count with "-5" */
-    _par->HorizSyncStart  = (xres + hfront)/8 + 1;
-    _par->HorizSyncEnd    = (xres + hfront + hsync)/8 + 1;
-
-    _par->VertRes         = yres;
-    _par->VertTotal       = yres + vfront + vsync + vback -2;
-    _par->VertDispEnd     = yres - 1;
-    _par->VertBlankStart  = yres;
-    _par->VertBlankEnd    = _par->VertTotal;
-    _par->VertSyncStart   = yres + vfront - 1;
-    _par->VertSyncEnd     = yres + vfront + vsync - 1;
-
-    if (_par->VertTotal >= 1024)
-    {
-	printk(KERN_WARNING "clgen: ERROR: VerticalTotal >= 1024; special treatment required! (TODO)\n");
-	return -EINVAL;
-    }
+	case 8:
+		_par->line_length = _par->var.xres_virtual;
+		_par->visual = FB_VISUAL_PSEUDOCOLOR;
+		_par->var.red.offset = 0;
+		_par->var.red.length = 6;
+		_par->var.green.offset = 0;
+		_par->var.green.length = 6;
+		_par->var.blue.offset = 0;
+		_par->var.blue.length = 6;
+		break;
+
+	case 16:
+		_par->line_length = _par->var.xres_virtual * 2;
+		_par->visual = FB_VISUAL_DIRECTCOLOR;
+#ifdef CONFIG_PREP
+		_par->var.red.offset = 2;
+		_par->var.green.offset = -3;
+		_par->var.blue.offset = 8;
+#else
+		_par->var.red.offset = 10;
+		_par->var.green.offset = 5;
+		_par->var.blue.offset = 0;
+#endif
+		_par->var.red.length = 5;
+		_par->var.green.length = 5;
+		_par->var.blue.length = 5;
+		break;
+
+	case 24:
+		_par->line_length = _par->var.xres_virtual * 3;
+		_par->visual = FB_VISUAL_DIRECTCOLOR;
+#ifdef CONFIG_PREP
+		_par->var.red.offset = 8;
+		_par->var.green.offset = 16;
+		_par->var.blue.offset = 24;
+#else
+		_par->var.red.offset = 16;
+		_par->var.green.offset = 8;
+		_par->var.blue.offset = 0;
+#endif
+		_par->var.red.length = 8;
+		_par->var.green.length = 8;
+		_par->var.blue.length = 8;
+		break;
+
+	case 32:
+		_par->line_length = _par->var.xres_virtual * 4;
+		_par->visual = FB_VISUAL_DIRECTCOLOR;
+#ifdef CONFIG_PREP
+		_par->var.red.offset = 8;
+		_par->var.green.offset = 16;
+		_par->var.blue.offset = 24;
+#else
+		_par->var.red.offset = 16;
+		_par->var.green.offset = 8;
+		_par->var.blue.offset = 0;
+#endif
+		_par->var.red.length = 8;
+		_par->var.green.length = 8;
+		_par->var.blue.length = 8;
+		break;
+
+	default:
+		assert (0);
+		/* should never occur */
+		break;
+	}
+
+	_par->var.red.msb_right =
+	    _par->var.green.msb_right =
+	    _par->var.blue.msb_right =
+	    _par->var.transp.offset =
+	    _par->var.transp.length =
+	    _par->var.transp.msb_right = 0;
+
+	_par->type = FB_TYPE_PACKED_PIXELS;
+
+	/* convert from ps to kHz */
+	freq = 1000000000 / var->pixclock;
+
+	DPRINTK ("desired pixclock: %ld kHz\n", freq);
+
+	maxclock = clgen_board_info[fb_info->btype].maxclock;
+	_par->multiplexing = 0;
+
+	/* If the frequency is greater than we can support, we might be able
+	 * to use multiplexing for the video mode */
+	if (freq > maxclock) {
+		switch (fb_info->btype) {
+		case BT_ALPINE:
+		case BT_GD5480:
+			_par->multiplexing = 1;
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
+			DPRINTK ("EXIT - return -EINVAL\n");
+			return -EINVAL;
+		}
+	}
+#if 0
+	/* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
+	 * the VCLK is double the pixel clock. */
+	switch (var->bits_per_pixel) {
+	case 16:
+	case 32:
+		if (_par->HorizRes <= 800)
+			freq /= 2;	/* Xbh has this type of clock for 32-bit */
+		break;
+	}
+#endif
 
-    return 0;
+	bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div,
+		   maxclock);
+	_par->mclk = clgen_get_mclk (freq, var->bits_per_pixel, &_par->divMCLK);
+
+	xres = _par->var.xres;
+	hfront = _par->var.right_margin;
+	hsync = _par->var.hsync_len;
+	hback = _par->var.left_margin;
+
+	yres = _par->var.yres;
+	vfront = _par->var.lower_margin;
+	vsync = _par->var.vsync_len;
+	vback = _par->var.upper_margin;
+
+	if (_par->var.vmode & FB_VMODE_DOUBLE) {
+		yres *= 2;
+		vfront *= 2;
+		vsync *= 2;
+		vback *= 2;
+	} else if (_par->var.vmode & FB_VMODE_INTERLACED) {
+		yres = ++yres / 2;
+		vfront = ++vfront / 2;
+		vsync = ++vsync / 2;
+		vback = ++vback / 2;
+	}
+	_par->HorizRes = xres;
+	_par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
+	_par->HorizDispEnd = xres / 8 - 1;
+	_par->HorizBlankStart = xres / 8;
+	_par->HorizBlankEnd = _par->HorizTotal + 5;	/* does not count with "-5" */
+	_par->HorizSyncStart = (xres + hfront) / 8 + 1;
+	_par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
+
+	_par->VertRes = yres;
+	_par->VertTotal = yres + vfront + vsync + vback - 2;
+	_par->VertDispEnd = yres - 1;
+	_par->VertBlankStart = yres;
+	_par->VertBlankEnd = _par->VertTotal;
+	_par->VertSyncStart = yres + vfront - 1;
+	_par->VertSyncEnd = yres + vfront + vsync - 1;
+
+	if (_par->VertRes >= 1024) {
+		_par->VertTotal /= 2;
+		_par->VertSyncStart /= 2;
+		_par->VertSyncEnd /= 2;
+		_par->VertDispEnd /= 2;
+	}
+	if (_par->multiplexing) {
+		_par->HorizTotal /= 2;
+		_par->HorizSyncStart /= 2;
+		_par->HorizSyncEnd /= 2;
+		_par->HorizDispEnd /= 2;
+	}
+	if (_par->VertRes >= 1280) {
+		printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
+		DPRINTK ("EXIT - EINVAL error\n");
+		return -EINVAL;
+	}
+	DPRINTK ("EXIT\n");
+	return 0;
 }
 
 
-static int clgen_encode_var(struct fb_var_screeninfo *var, const void *par,
-			    struct fb_info_gen *info)
+static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
+			     struct fb_info_gen *info)
 {
-    *var = ((struct clgenfb_par*)par)->var;
-    return 0;
+	DPRINTK ("ENTER\n");
+
+	*var = ((struct clgenfb_par *) par)->var;
+
+	DPRINTK ("EXIT\n");
+	return 0;
 }
 
 /* get current video mode */
-static void clgen_get_par(void *par, struct fb_info_gen *info)
+static void clgen_get_par (void *par, struct fb_info_gen *info)
 {
-    struct clgenfb_par *_par  = (struct clgenfb_par*)par;
-    struct clgenfb_info*_info = (struct clgenfb_info*)fb_info;
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
 
-    *_par = _info->currentmode;   
+	*_par = _info->currentmode;
+
+	DPRINTK ("EXIT\n");
+}
+
+static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div)
+{
+	assert (fb_info != NULL);
+
+	if (div == 2) {
+		/* VCLK = MCLK/2 */
+		unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
+		vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1);
+		vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
+	} else if (div == 1) {
+		/* VCLK = MCLK */
+		unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
+		vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1);
+		vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
+	} else {
+		vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f);
+	}
 }
 
 /*************************************************************************
@@ -595,1072 +1060,1672 @@
 
 	actually writes the values for a new video mode into the hardware,
 **************************************************************************/
-static void clgen_set_par(const void *par, struct fb_info_gen *info)
+static void clgen_set_par (const void *par, struct fb_info_gen *info)
 {
-    unsigned char tmp;
-    int offset = 0;
-    struct clgenfb_par *_par = (struct clgenfb_par*)par;
-
-    printk(KERN_INFO">clgen_set_par()\n");
-    printk(KERN_INFO"Requested mode: %dx%dx%d\n",
-		    _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
-    printk(KERN_INFO"pixclock: %d\n", _par->var.pixclock);
-    
-    fb_info = (struct clgenfb_info *)info;
-
-    /* unlock register CRT0..CRT7 */
-    WCrt(CRT11, 0x20); /* previously: 0x00) */
-
-    /* if DEBUG is set, all parameters get output before writing */
-    DEBUG printk("CRT0: %ld\n", _par->HorizTotal); 
-    WCrt(CRT0, _par->HorizTotal);
-
-    DEBUG printk("CRT1: %ld\n", _par->HorizDispEnd); 
-    WCrt(CRT1, _par->HorizDispEnd);
-
-    DEBUG printk("CRT2: %ld\n", _par->HorizBlankStart); 
-    WCrt(CRT2, _par->HorizBlankStart);
-
-    DEBUG printk("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /*  + 128: Compatible read */
-    WCrt(CRT3, 128 + (_par->HorizBlankEnd % 32));
-
-    DEBUG printk("CRT4: %ld\n", _par->HorizSyncStart);
-    WCrt(CRT4, _par->HorizSyncStart);
-
-    tmp = _par->HorizSyncEnd % 32;
-    if (_par->HorizBlankEnd & 32)	
-    	tmp += 128;
-    DEBUG printk("CRT5: %d\n", tmp); 
-    WCrt(CRT5, tmp);
-
-    DEBUG printk("CRT6: %ld\n", _par->VertTotal & 0xff); 
-    WCrt(CRT6, (_par->VertTotal & 0xff));
-
-    tmp = 16;  /* LineCompare bit #9 */
-    if (_par->VertTotal      & 256) tmp |= 1;
-    if (_par->VertDispEnd    & 256) tmp |= 2;
-    if (_par->VertSyncStart  & 256) tmp |= 4;
-    if (_par->VertBlankStart & 256) tmp |= 8;
-    if (_par->VertTotal      & 512) tmp |= 32;
-    if (_par->VertDispEnd    & 512) tmp |= 64;
-    if (_par->VertSyncStart  & 512) tmp |= 128;
-    DEBUG printk("CRT7: %d\n", tmp);
-    WCrt(CRT7, tmp);
-
-    tmp = 0x40; /* LineCompare bit #8 */
-    if (_par->VertBlankStart & 512)		tmp |= 0x20;
-    if (_par->var.vmode & FB_VMODE_DOUBLE)	tmp |= 0x80;
-    DEBUG printk("CRT9: %d\n", tmp);
-    WCrt(CRT9, tmp);
-
-    DEBUG printk("CRT10: %ld\n", _par->VertSyncStart & 0xff);
-    WCrt(CRT10, (_par->VertSyncStart & 0xff));
-
-    DEBUG printk("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16);
-    WCrt(CRT11, (_par->VertSyncEnd % 16 + 64 + 32));
-
-    DEBUG printk("CRT12: %ld\n", _par->VertDispEnd & 0xff);
-    WCrt(CRT12, (_par->VertDispEnd & 0xff));
-
-    DEBUG printk("CRT15: %ld\n", _par->VertBlankStart & 0xff);
-    WCrt(CRT15, (_par->VertBlankStart & 0xff));
-
-    DEBUG printk("CRT16: %ld\n", _par->VertBlankEnd & 0xff);
-    WCrt(CRT16, (_par->VertBlankEnd & 0xff));
-
-    DEBUG printk("CRT18: 0xff\n");
-    WCrt(CRT18, 0xff);
-
-    tmp = 0;
-    if (_par->var.vmode & FB_VMODE_INTERLACED)	tmp |= 1;
-    if (_par->HorizBlankEnd & 64)		tmp |= 16;
-    if (_par->HorizBlankEnd & 128)		tmp |= 32;
-    if (_par->VertBlankEnd  & 256)		tmp |= 64;
-    if (_par->VertBlankEnd  & 512)		tmp |= 128;
-    
-    DEBUG printk("CRT1a: %d\n", tmp);
-    WCrt(CRT1A, tmp);
-
-    /* set VCLK0 */
-    /* hardware RefClock: 14.31818 MHz */
-    /* formula: VClk = (OSC * N) / (D * (1+P)) */
-    /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
-
-    WSeq(SEQRB, _par->nom);
-    tmp = _par->den<<1; 
-    if (_par->div != 0) tmp |= 1;
-
-    if (fb_info->btype == BT_SD64)
-    	tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
-    
-    WSeq(SEQR1B, tmp);
-
-    WCrt(CRT17, 0xc3); /* mode control: CRTC enable, ROTATE(?), 16bit address wrap, no compat. */
-
-/* HAEH?	WCrt(CRT11, 0x20);  * previously: 0x00  unlock CRT0..CRT7 */
-
-    /* don't know if it would hurt to also program this if no interlaced */
-    /* mode is used, but I feel better this way.. :-) */
-    if (_par->var.vmode & FB_VMODE_INTERLACED)
-    	WCrt(CRT19, _par->HorizTotal / 2);
-    else
-    	WCrt(CRT19, 0x00);	/* interlace control */
-
-    WSeq(SEQR3, 0);
-
-    /* adjust horizontal/vertical sync type (low/high) */
-    tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
-    if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)  tmp |= 0x40;
-    if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT) tmp |= 0x80;
-    WGen(MISC_W, tmp);
-
-    WCrt(CRT8,    0);      /* Screen A Preset Row-Scan register */
-    WCrt(CRTA,    0);      /* text cursor on and start line */
-    WCrt(CRTB,   31);      /* text cursor end line */
-
-    /* programming for different color depths */
-    if (_par->var.bits_per_pixel == 1)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 1 bit deep display\n");
-#if 0
-    	/* restore first 2 color registers for mono mode */
-    	WClut( 0, 0x00, 0x00, 0x00);  /* background: black */
-	WClut( 1, 0x3f, 0x3f, 0x3f);  /* foreground: white */
+	unsigned char tmp;
+	int offset = 0;
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
+	DPRINTK ("Requested mode: %dx%dx%d\n",
+	       _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
+	DPRINTK ("pixclock: %d\n", _par->var.pixclock);
+
+
+	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */
+
+	/* if debugging is enabled, all parameters get output before writing */
+	DPRINTK ("CRT0: %ld\n", _par->HorizTotal);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal);
+
+	DPRINTK ("CRT1: %ld\n", _par->HorizDispEnd);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd);
+
+	DPRINTK ("CRT2: %ld\n", _par->HorizBlankStart);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart);
+
+	DPRINTK ("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32);	/*  + 128: Compatible read */
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32));
+
+	DPRINTK ("CRT4: %ld\n", _par->HorizSyncStart);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart);
+
+	tmp = _par->HorizSyncEnd % 32;
+	if (_par->HorizBlankEnd & 32)
+		tmp += 128;
+	DPRINTK ("CRT5: %d\n", tmp);
+	vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp);
+
+	DPRINTK ("CRT6: %ld\n", _par->VertTotal & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff));
+
+	tmp = 16;		/* LineCompare bit #9 */
+	if (_par->VertTotal & 256)
+		tmp |= 1;
+	if (_par->VertDispEnd & 256)
+		tmp |= 2;
+	if (_par->VertSyncStart & 256)
+		tmp |= 4;
+	if (_par->VertBlankStart & 256)
+		tmp |= 8;
+	if (_par->VertTotal & 512)
+		tmp |= 32;
+	if (_par->VertDispEnd & 512)
+		tmp |= 64;
+	if (_par->VertSyncStart & 512)
+		tmp |= 128;
+	DPRINTK ("CRT7: %d\n", tmp);
+	vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp);
+
+	tmp = 0x40;		/* LineCompare bit #8 */
+	if (_par->VertBlankStart & 512)
+		tmp |= 0x20;
+	if (_par->var.vmode & FB_VMODE_DOUBLE)
+		tmp |= 0x80;
+	DPRINTK ("CRT9: %d\n", tmp);
+	vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp);
+
+	DPRINTK ("CRT10: %ld\n", _par->VertSyncStart & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff));
+
+	DPRINTK ("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32));
+
+	DPRINTK ("CRT12: %ld\n", _par->VertDispEnd & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff));
+
+	DPRINTK ("CRT15: %ld\n", _par->VertBlankStart & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff));
+
+	DPRINTK ("CRT16: %ld\n", _par->VertBlankEnd & 0xff);
+	vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff));
+
+	DPRINTK ("CRT18: 0xff\n");
+	vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff);
+
+	tmp = 0;
+	if (_par->var.vmode & FB_VMODE_INTERLACED)
+		tmp |= 1;
+	if (_par->HorizBlankEnd & 64)
+		tmp |= 16;
+	if (_par->HorizBlankEnd & 128)
+		tmp |= 32;
+	if (_par->VertBlankEnd & 256)
+		tmp |= 64;
+	if (_par->VertBlankEnd & 512)
+		tmp |= 128;
+
+	DPRINTK ("CRT1a: %d\n", tmp);
+	vga_wcrt (fb_info->regs, CL_CRT1A, tmp);
+
+	/* set VCLK0 */
+	/* hardware RefClock: 14.31818 MHz */
+	/* formula: VClk = (OSC * N) / (D * (1+P)) */
+	/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
+
+	vga_wseq (fb_info->regs, CL_SEQRB, _par->nom);
+	tmp = _par->den << 1;
+	if (_par->div != 0)
+		tmp |= 1;
+
+	if ((fb_info->btype == BT_SD64) ||
+	    (fb_info->btype == BT_ALPINE) ||
+	    (fb_info->btype == BT_GD5480))
+		tmp |= 0x80;	/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
+
+	DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
+	vga_wseq (fb_info->regs, CL_SEQR1B, tmp);
+
+	if (_par->VertRes >= 1024)
+		/* 1280x1024 */
+		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7);
+	else
+		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 
+		 * address wrap, no compat. */
+		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);
+
+/* HAEH?        vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);  * previously: 0x00  unlock VGA_CRTC_H_TOTAL..CRT7 */
+
+	/* don't know if it would hurt to also program this if no interlaced */
+	/* mode is used, but I feel better this way.. :-) */
+	if (_par->var.vmode & FB_VMODE_INTERLACED)
+		vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2);
+	else
+		vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00);	/* interlace control */
+
+	vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0);
+
+	/* adjust horizontal/vertical sync type (low/high) */
+	tmp = 0x03;		/* enable display memory & CRTC I/O address for color mode */
+	if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		tmp |= 0x40;
+	if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		tmp |= 0x80;
+	WGen (fb_info, VGA_MIS_W, tmp);
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0);	/* Screen A Preset Row-Scan register */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0);	/* text cursor on and start line */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31);	/* text cursor end line */
+
+	/* programming for different color depths */
+	if (_par->var.bits_per_pixel == 1) {
+		DPRINTK ("clgen: preparing for 1 bit deep display\n");
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0);	/* mode register */
+
+		/* Extended Sequencer Mode */
+		switch (fb_info->btype) {
+		case BT_SD64:
+			/* setting the SEQRF on SD64 is not necessary (only during init) */
+			DPRINTK ("(for SD64)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf0);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a);		/*  MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			DPRINTK ("(for Piccolo)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x80);
+/* ### ueberall 0x22? */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* evtl d0 bei 1 bit? avoid FIFO underruns..? */
+			break;
+
+		case BT_PICASSO:
+			DPRINTK ("(for Picasso)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x20);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 22 MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xd0);	/* ## vorher d0 avoid FIFO underruns..? */
+			break;
+
+		case BT_SPECTRUM:
+			DPRINTK ("(for Spectrum)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x80);
+/* ### ueberall 0x22? */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* evtl d0? avoid FIFO underruns..? */
+			break;
+
+		case BT_PICASSO4:
+			DPRINTK ("(for Picasso 4)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x20);
+/*                      vga_wseq(fb_info->regs, CL_SEQR1F, 0x1c); */
+/* SEQRF not being set here...  vga_wseq(fb_info->regs, CL_SEQRF, 0xd0); */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			if (_par->multiplexing)
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
+			else
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa1);
+			/* We already set SRF and SR1F */
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x11);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: unknown Board\n");
+			break;
+		}
+
+		WGen (fb_info, VGA_PEL_MSK, 0x01);	/* pixel mask: pass-through for first plane */
+		if (_par->multiplexing)
+			WHDR (fb_info, 0x4a);	/* hidden dac reg: 1280x1024 */
+		else
+			WHDR (fb_info, 0);	/* hidden dac: nothing */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06);	/* memory mode: odd/even, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01);	/* plane mask: only write to first plane */
+		offset = _par->var.xres_virtual / 16;
+	} else if (_par->var.bits_per_pixel == 8) {
+		DPRINTK ("clgen: preparing for 8 bit deep display\n");
+		switch (fb_info->btype) {
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf1);	/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d);		/* MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x81);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			break;
+
+		case BT_PICASSO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x21);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			break;
+
+		case BT_SPECTRUM:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x81);
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			break;
+
+		case BT_PICASSO4:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x21);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);	/* ### INCOMPLETE!! */
+/*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			if (_par->multiplexing)
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
+			else
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa1);
+			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
+			/* We already set SRF and SR1F */
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x11);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: unknown Board\n");
+			break;
+		}
+
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
+		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
+		if (_par->multiplexing)
+			WHDR (fb_info, 0x4a);	/* hidden dac reg: 1280x1024 */
+		else
+			WHDR (fb_info, 0);	/* hidden dac: nothing */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
+		offset = _par->var.xres_virtual / 8;
+	} else if (_par->var.bits_per_pixel == 16) {
+		DPRINTK ("clgen: preparing for 16 bit deep display\n");
+		switch (fb_info->btype) {
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf7);	/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e);		/* MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_SPECTRUM:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO4:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
+/*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			if (_par->HorizRes >= 1024)
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
+			else
+				vga_wseq (fb_info->regs, CL_SEQR7, 0xa3);
+			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x17);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "CLGEN: unknown Board\n");
+			break;
+		}
+
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
+		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
+#ifdef CONFIG_PCI
+		WHDR (fb_info, 0xc0);	/* Copy Xbh */
+#elif CONFIG_ZORRO
+		WHDR (fb_info, 0xa0);	/* hidden dac reg: nothing special */
 #endif
-	WGfx(GR5,     0);      /* mode register */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
+		offset = _par->var.xres_virtual / 4;
+	} else if (_par->var.bits_per_pixel == 32) {
+		DPRINTK ("clgen: preparing for 24/32 bit deep display\n");
+		switch (fb_info->btype) {
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xf9);	/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e);		/* MCLK select */
+			break;
+
+		case BT_PICCOLO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_SPECTRUM:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
+			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
+			break;
+
+		case BT_PICASSO4:
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
+/*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
+			break;
+
+		case BT_ALPINE:
+			DPRINTK (" (for GD543x)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0xa9);
+			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
+			break;
+
+		case BT_GD5480:
+			DPRINTK (" (for GD5480)\n");
+			vga_wseq (fb_info->regs, CL_SEQR7, 0x19);
+			/* We already set SRF and SR1F */
+			break;
+
+		default:
+			printk (KERN_WARNING "clgen: unknown Board\n");
+			break;
+		}
+
+		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
+		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
+		WHDR (fb_info, 0xc5);	/* hidden dac reg: 8-8-8 mode (24 or 32) */
+		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
+		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
+		offset = _par->var.xres_virtual / 4;
+	} else
+		printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
+			_par->var.bits_per_pixel);
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff);
+	tmp = 0x22;
+	if (offset & 0x100)
+		tmp |= 0x10;	/* offset overflow bit */
+
+	vga_wcrt (fb_info->regs, CL_CRT1B, tmp);	/* screen start addr #16-18, fastpagemode cycles */
+
+	if (fb_info->btype == BT_SD64 ||
+	    fb_info->btype == BT_PICASSO4 ||
+	    fb_info->btype == BT_ALPINE ||
+	    fb_info->btype == BT_GD5480)
+		vga_wcrt (fb_info->regs, CL_CRT1D, 0x00);	/* screen start address bit 19 */
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0);	/* text cursor location high */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0);	/* text cursor location low */
+	vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0);	/* underline row scanline = at very bottom */
+
+	vga_wattr (fb_info->regs, VGA_ATC_MODE, 1);	/* controller mode */
+	vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0);		/* overscan (border) color */
+	vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15);	/* color plane enable */
+	vga_wattr (fb_info->regs, CL_AR33, 0);	/* pixel panning */
+	vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0);	/* color select */
+
+	/* [ EGS: SetOffset(); ] */
+	/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
+	AttrOn (fb_info);
+
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0);	/* set/reset register */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0);		/* set/reset enable */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0);	/* color compare */
+	vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0);	/* data rotate */
+	vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0);	/* read map select */
+	vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1);	/* miscellaneous register */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15);	/* color don't care */
+	vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255);	/* bit mask */
+
+	vga_wseq (fb_info->regs, CL_SEQR12, 0x0);	/* graphics cursor attributes: nothing special */
+
+	/* finally, turn on everything - turn off "FullBandwidth" bit */
+	/* also, set "DotClock%2" bit where requested */
+	tmp = 0x01;
+
+/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
+    if (var->vmode & FB_VMODE_CLOCK_HALVE)
+	tmp |= 0x08;
+*/
+
+	vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp);
+	DPRINTK ("CL_SEQR1: %d\n", tmp);
+
+	fb_info->currentmode = *_par;
+
+	DPRINTK ("virtual offset: (%d,%d)\n", _par->var.xoffset, _par->var.yoffset);
+	/* pan to requested offset */
+	clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info);
+
+#ifdef CLGEN_DEBUG
+	clgen_dump ();
+#endif
+
+	DPRINTK ("EXIT\n");
+	return;
+}
+
+static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
+			    unsigned *blue, unsigned *transp,
+			    struct fb_info *info)
+{
+	unsigned char bred, bgreen, bblue;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	if (regno > 255)
+		return -EINVAL;
+
+	RClut (fb_info, regno, &bred, &bgreen, &bblue);
+
+	*red = (bred << 10) | (bred << 4) | (bred >> 2);
+	*green = (bgreen << 10) | (bgreen << 4) | (bgreen >> 2);
+	*blue = (bblue << 10) | (bblue << 4) | (bblue >> 2);
+	*transp = 0;
+
+	return 0;
+}
+
+static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	if (regno > 255)
+		return -EINVAL;
+
+	switch (fb_info->currentmode.var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10);
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		assert (regno < 16);
+#ifdef CONFIG_PREP
+		fb_info->fbcon_cmap.cfb16[regno] =
+		    ((red & 0xf800) >> 9) |
+		    ((green & 0xf800) >> 14) |
+		    ((green & 0xf800) << 2) |
+		    ((blue & 0xf800) >> 3);
+#else
+		fb_info->fbcon_cmap.cfb16[regno] =
+		    ((red & 0xf800) >> 1) |
+		    ((green & 0xf800) >> 6) |
+		    ((blue & 0xf800) >> 11);
+#endif
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		assert (regno < 16);
+#ifdef CONFIG_PREP
+		fb_info->fbcon_cmap.cfb32[regno] =
+		    ((red & 0xff00)) |
+		    ((green & 0xff00) << 8) |
+		    ((blue & 0xff00) << 16);
+#endif
+		fb_info->fbcon_cmap.cfb32[regno] =
+		    ((red & 0xff00) << 8) |
+		    ((green & 0xff00)) |
+		    ((blue & 0xff00) >> 8);
+#endif
+	}
+
+	return 0;
+}
+
+/*************************************************************************
+	clgen_pan_display()
+
+	performs display panning - provided hardware permits this
+**************************************************************************/
+static int clgen_pan_display (const struct fb_var_screeninfo *var,
+			      struct fb_info_gen *info)
+{
+	int xoffset = 0;
+	int yoffset = 0;
+	unsigned long base;
+	unsigned char tmp = 0, tmp2 = 0, xpix;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER\n");
+
+	/* no range checks for xoffset and yoffset,   */
+	/* as fbgen_pan_display has already done this */
+
+	fb_info->currentmode.var.xoffset = var->xoffset;
+	fb_info->currentmode.var.yoffset = var->yoffset;
+
+	xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
+	yoffset = var->yoffset;
+
+	base = yoffset * fb_info->currentmode.line_length + xoffset;
+
+	if (fb_info->currentmode.var.bits_per_pixel == 1) {
+		/* base is already correct */
+		xpix = (unsigned char) (var->xoffset % 8);
+	} else {
+		base /= 4;
+		xpix = (unsigned char) ((xoffset % 4) * 2);
+	}
+
+	/* lower 8 + 8 bits of screen start address */
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
+
+	/* construct bits 16, 17 and 18 of screen start address */
+	if (base & 0x10000)
+		tmp |= 0x01;
+	if (base & 0x20000)
+		tmp |= 0x04;
+	if (base & 0x40000)
+		tmp |= 0x08;
+
+	tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp;	/* 0xf2 is %11110010, exclude tmp bits */
+	vga_wcrt (fb_info->regs, CL_CRT1B, tmp2);
+
+	/* construct bit 19 of screen start address */
+	if (clgen_board_info[fb_info->btype].scrn_start_bit19) {
+		tmp2 = 0;
+		if (base & 0x80000)
+			tmp2 = 0x80;
+		vga_wcrt (fb_info->regs, CL_CRT1D, tmp2);
+	}
+
+	/* write pixel panning value to AR33; this does not quite work in 8bpp */
+	/* ### Piccolo..? Will this work? */
+	if (fb_info->currentmode.var.bits_per_pixel == 1)
+		vga_wattr (fb_info->regs, CL_AR33, xpix);
+
+
+	DPRINTK ("EXIT\n");
+	return (0);
+}
+
+
+static int clgen_blank (int blank_mode, struct fb_info_gen *info)
+{
+	/*
+	 *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+	 *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+	 *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+	 *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+	 *  and powerdown modes on hardware that supports disabling hsync/vsync:
+	 *    blank_mode == 2: suspend vsync
+	 *    blank_mode == 3: suspend hsync
+	 *    blank_mode == 4: powerdown
+	 */
+	unsigned char val;
+	static int current_mode = 0;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+
+	DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
+
+	if (current_mode == blank_mode) {
+		DPRINTK ("EXIT, returning 0\n");
+		return 0;
+	}
+
+	/* Undo current */
+	switch (current_mode) {
+	case 0:		/* Screen is normal */
+		break;
+	case 1:		/* Screen is blanked */
+		val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
+		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf);	/* clear "FullBandwidth" bit */
+		break;
+	case 2:		/* vsync suspended */
+	case 3:		/* hsync suspended */
+	case 4:		/* sceen is powered down */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x00);
+		break;
+	default:
+		DPRINTK ("EXIT, returning 1\n");
+		return 1;
+	}
+
+	/* set new */
+	switch (blank_mode) {
+	case 0:		/* Unblank screen */
+		break;
+	case 1:		/* Blank screen */
+		val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
+		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20);	/* set "FullBandwidth" bit */
+		break;
+	case 2:		/* suspend vsync */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x04);
+		break;
+	case 3:		/* suspend hsync */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x02);
+		break;
+	case 4:		/* powerdown */
+		vga_wgfx (fb_info->regs, CL_GRE, 0x06);
+		break;
+	default:
+		DPRINTK ("EXIT, returning 1\n");
+		return 1;
+	}
+
+	current_mode = blank_mode;
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+/**** END   Hardware specific Routines **************************************/
+/****************************************************************************/
+/**** BEGIN Internal Routines ***********************************************/
+
+static void __init init_vgachip (struct clgenfb_info *fb_info)
+{
+	const struct clgen_board_info_rec *bi;
 	
-	/* Extended Sequencer Mode */
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    /* setting the SEQRF on SD64 is not necessary (only during init) */
-	    DEBUG printk(KERN_INFO "(for SD64)\n");
-	    WSeq(SEQR7,  0xf0);
-	    WSeq(SEQR1F, 0x1a);     /*  MCLK select */
-	    break;
+	DPRINTK ("ENTER\n");
 
-	case BT_PICCOLO:
-	    DEBUG printk(KERN_INFO "(for Piccolo)\n");
-	    WSeq(SEQR7, 0x80);
-/* ### ueberall 0x22? */
-	    WSeq(SEQR1F, 0x22);     /* ##vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
-	    break;
+	assert (fb_info != NULL);
+	
+	bi = &clgen_board_info[fb_info->btype];
 
+	/* reset board globally */
+	switch (fb_info->btype) {
+	case BT_PICCOLO:
+		WSFR (fb_info, 0x01);
+		udelay (500);
+		WSFR (fb_info, 0x51);
+		udelay (500);
+		break;
 	case BT_PICASSO:
-	    DEBUG printk(KERN_INFO "(for Picasso)\n");
-	    WSeq(SEQR7, 0x20);
-	    WSeq(SEQR1F, 0x22);     /* ##vorher 22 MCLK select */
-	    WSeq(SEQRF, 0xd0);    /* ## vorher d0 avoid FIFO underruns..? */
-	    break;
-
+		WSFR2 (fb_info, 0xff);
+		udelay (500);
+		break;
+	case BT_SD64:
 	case BT_SPECTRUM:
-	    DEBUG printk(KERN_INFO "(for Spectrum)\n");
-	    WSeq(SEQR7, 0x80);
-/* ### ueberall 0x22? */
-	    WSeq(SEQR1F, 0x22);     /* ##vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* evtl d0? avoid FIFO underruns..? */
-	    break;
+		WSFR (fb_info, 0x1f);
+		udelay (500);
+		WSFR (fb_info, 0x4f);
+		udelay (500);
+		break;
+	case BT_PICASSO4:
+		vga_wcrt (fb_info->regs, CL_CRT51, 0x00);	/* disable flickerfixer */
+		udelay (100000);
+		vga_wgfx (fb_info->regs, CL_GR2F, 0x00);	/* from Klaus' NetBSD driver: */
+		vga_wgfx (fb_info->regs, CL_GR33, 0x00);	/* put blitter into 542x compat */
+		vga_wgfx (fb_info->regs, CL_GR31, 0x00);	/* mode */
+		break;
+
+	case BT_GD5480:
+		vga_wgfx (fb_info->regs, CL_GR2F, 0x00);	/* from Klaus' NetBSD driver: */
+		break;
+
+	case BT_ALPINE:
+		/* Nothing to do to reset the board. */
+		break;
+
+	default:
+		printk (KERN_ERR "clgen: Warning: Unknown board type\n");
+		break;
+	}
+
+	/* "pre-set" a RAMsize; if the test succeeds, double it */
+	if (fb_info->btype == BT_SD64 ||
+	    fb_info->btype == BT_PICASSO4)
+		fb_info->size = 0x400000;
+	else
+		fb_info->size = 0x200000;
+
+	/* assume it's a "large memory" board (2/4 MB) */
+	fb_info->smallboard = FALSE;
+
+	/* the P4 is not fully initialized here; I rely on it having been */
+	/* inited under AmigaOS already, which seems to work just fine    */
+	/* (Klaus advised to do it this way)                              */
+
+	if (fb_info->btype != BT_PICASSO4) {
+		WGen (fb_info, CL_VSSM, 0x10);	/* EGS: 0x16 */
+		WGen (fb_info, CL_POS102, 0x01);
+		WGen (fb_info, CL_VSSM, 0x08);	/* EGS: 0x0e */
+
+		if (fb_info->btype != BT_SD64)
+			WGen (fb_info, CL_VSSM2, 0x01);
+
+		vga_wseq (fb_info->regs, CL_SEQR0, 0x03);	/* reset sequencer logic */
+
+		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21);	/* FullBandwidth (video off) and 8/9 dot clock */
+		WGen (fb_info, VGA_MIS_W, 0xc1);	/* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
+
+/*      vga_wgfx (fb_info->regs, CL_GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
+		vga_wseq (fb_info->regs, CL_SEQR6, 0x12);	/* unlock all extension registers */
+
+		vga_wgfx (fb_info->regs, CL_GR31, 0x04);	/* reset blitter */
+
+		switch (fb_info->btype) {
+		case BT_GD5480:
+			vga_wseq (fb_info->regs, CL_SEQRF, 0x98);
+			break;
+		case BT_ALPINE:
+			break;
+		case BT_SD64:
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);
+			break;
+		default:
+			vga_wseq (fb_info->regs, CL_SEQR16, 0x0f);
+			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);
+			break;
+		}
+	}
+	vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: nothing */
+	vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00);	/* character map select: doesn't even matter in gx mode */
+	vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e);	/* memory mode: chain-4, no odd/even, ext. memory */
+
+	/* controller-internal base address of video memory */
+	vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07);
+
+	/*  vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
+
+	vga_wseq (fb_info->regs, CL_SEQR10, 0x00);		/* graphics cursor X position (incomplete; position gives rem. 3 bits */
+	vga_wseq (fb_info->regs, CL_SEQR11, 0x00);		/* graphics cursor Y position (..."... ) */
+	vga_wseq (fb_info->regs, CL_SEQR12, 0x00);		/* graphics cursor attributes */
+	vga_wseq (fb_info->regs, CL_SEQR13, 0x00);		/* graphics cursor pattern address */
+
+	/* writing these on a P4 might give problems..  */
+	if (fb_info->btype != BT_PICASSO4) {
+		vga_wseq (fb_info->regs, CL_SEQR17, 0x00);		/* configuration readback and ext. color */
+		vga_wseq (fb_info->regs, CL_SEQR18, 0x02);		/* signature generator */
+	}
+
+	/* MCLK select etc. */
+	if (bi->write_sr1f)
+		vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f);
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00);	/* Screen A preset row scan: none */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20);	/* Text cursor start: disable text cursor */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00);	/* Text cursor end: - */
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00);	/* Screen start address high: 0 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00);	/* Screen start address low: 0 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00);	/* text cursor location high: 0 */
+	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00);	/* text cursor location low: 0 */
+
+	vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00);	/* Underline Row scanline: - */
+	vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);	/* mode control: timing enable, byte mode, no compat modes */
+	vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00);	/* Line Compare: not needed */
+	/* ### add 0x40 for text modes with > 30 MHz pixclock */
+	vga_wcrt (fb_info->regs, CL_CRT1B, 0x02);	/* ext. display controls: ext.adr. wrap */
+
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00);	/* Set/Reset registes: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00);	/* Set/Reset enable: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00);	/* Color Compare: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00);	/* Data Rotate: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00);	/* Read Map Select: - */
+	vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00);	/* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
+	vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01);	/* Miscellaneous: memory map base address, graphics mode */
+	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f);	/* Color Don't care: involve all planes */
+	vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff);	/* Bit Mask: no mask at all */
+	if (fb_info->btype == BT_ALPINE)
+		vga_wgfx (fb_info->regs, CL_GRB, 0x20);	/* (5434 can't have bit 3 set for bitblt) */
+	else
+		vga_wgfx (fb_info->regs, CL_GRB, 0x28);	/* Graphics controller mode extensions: finer granularity, 8byte data latches */
+
+	vga_wgfx (fb_info->regs, CL_GRC, 0xff);	/* Color Key compare: - */
+	vga_wgfx (fb_info->regs, CL_GRD, 0x00);	/* Color Key compare mask: - */
+	vga_wgfx (fb_info->regs, CL_GRE, 0x00);	/* Miscellaneous control: - */
+	/*  vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */
+/*  vga_wgfx (fb_info->regs, CL_GR11, 0x00); */
+
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00);	/* Attribute Controller palette registers: "identity mapping" */
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e);
+	vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f);
+
+	vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01);	/* Attribute Controller mode: graphics mode */
+	vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00);	/* Overscan color reg.: reg. 0 */
+	vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f);	/* Color Plane enable: Enable all 4 planes */
+/* ###  vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */
+	vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00);	/* Color Select: - */
+
+	WGen (fb_info, VGA_PEL_MSK, 0xff);	/* Pixel mask: no mask */
+
+	if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480)
+		WGen (fb_info, VGA_MIS_W, 0xc3);	/* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
+
+	vga_wgfx (fb_info->regs, CL_GR31, 0x04);	/* BLT Start/status: Blitter reset */
+	vga_wgfx (fb_info->regs, CL_GR31, 0x00);	/* - " -           : "end-of-reset" */
+
+	/* CLUT setup */
+	WClut (fb_info, 0, 0x00, 0x00, 0x00);	/* background: black */
+	WClut (fb_info, 1, 0x3f, 0x3f, 0x3f);	/* foreground: white */
+	WClut (fb_info, 2, 0x00, 0x20, 0x00);
+	WClut (fb_info, 3, 0x00, 0x20, 0x20);
+	WClut (fb_info, 4, 0x20, 0x00, 0x00);
+	WClut (fb_info, 5, 0x20, 0x00, 0x20);
+	WClut (fb_info, 6, 0x20, 0x10, 0x00);
+	WClut (fb_info, 7, 0x20, 0x20, 0x20);
+	WClut (fb_info, 8, 0x10, 0x10, 0x10);
+	WClut (fb_info, 9, 0x10, 0x10, 0x30);
+	WClut (fb_info, 10, 0x10, 0x30, 0x10);
+	WClut (fb_info, 11, 0x10, 0x30, 0x30);
+	WClut (fb_info, 12, 0x30, 0x10, 0x10);
+	WClut (fb_info, 13, 0x30, 0x10, 0x30);
+	WClut (fb_info, 14, 0x30, 0x30, 0x10);
+	WClut (fb_info, 15, 0x30, 0x30, 0x30);
+
+	/* the rest a grey ramp */
+	{
+		int i;
+
+		for (i = 16; i < 256; i++)
+			WClut (fb_info, i, i >> 2, i >> 2, i >> 2);
+	}
+
+
+	/* misc... */
+	WHDR (fb_info, 0);	/* Hidden DAC register: - */
+
+	printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size);
+	DPRINTK ("EXIT\n");
+	return;
+}
+
+static void switch_monitor (struct clgenfb_info *fb_info, int on)
+{
+#ifdef CONFIG_ZORRO /* only works on Zorro boards */
+	static int IsOn = 0;	/* XXX not ok for multiple boards */
+
+	DPRINTK ("ENTER\n");
+
+	if (fb_info->btype == BT_PICASSO4)
+		return;		/* nothing to switch */
+	if (fb_info->btype == BT_ALPINE)
+		return;		/* nothing to switch */
+	if (fb_info->btype == BT_GD5480)
+		return;		/* nothing to switch */
+	if (fb_info->btype == BT_PICASSO) {
+		if ((on && !IsOn) || (!on && IsOn))
+			WSFR (fb_info, 0xff);
+
+		DPRINTK ("EXIT\n");
+		return;
+	}
+	if (on) {
+		switch (fb_info->btype) {
+		case BT_SD64:
+			WSFR (fb_info, fb_info->SFR | 0x21);
+			break;
+		case BT_PICCOLO:
+			WSFR (fb_info, fb_info->SFR | 0x28);
+			break;
+		case BT_SPECTRUM:
+			WSFR (fb_info, 0x6f);
+			break;
+		default: /* do nothing */ break;
+		}
+	} else {
+		switch (fb_info->btype) {
+		case BT_SD64:
+			WSFR (fb_info, fb_info->SFR & 0xde);
+			break;
+		case BT_PICCOLO:
+			WSFR (fb_info, fb_info->SFR & 0xd7);
+			break;
+		case BT_SPECTRUM:
+			WSFR (fb_info, 0x4f);
+			break;
+		default: /* do nothing */ break;
+		}
+	}
+	
+	DPRINTK ("EXIT\n");
+#endif /* CONFIG_ZORRO */
+}
+
+static void clgen_set_disp (const void *par, struct display *disp,
+			    struct fb_info_gen *info)
+{
+	struct clgenfb_par *_par = (struct clgenfb_par *) par;
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
+	int accel_text;
+
+	DPRINTK ("ENTER\n");
+	
+	assert (_par != NULL);
+	assert (fb_info != NULL);
+	
+	accel_text = _par->var.accel_flags & FB_ACCELF_TEXT;
+
+	printk ("Cirrus Logic video mode: ");
+	disp->screen_base = (char *) fb_info->fbmem;
+	switch (_par->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+	case 1:
+		printk ("monochrome\n");
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem;
+		disp->dispsw = &fbcon_mfb;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		printk ("8 bit color depth\n");
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem;
+		if (accel_text)
+			disp->dispsw = &fbcon_clgen_8;
+		else
+			disp->dispsw = &fbcon_cfb8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		printk ("16 bit color depth\n");
+		if (accel_text)
+			disp->dispsw = &fbcon_clgen_16;
+		else
+			disp->dispsw = &fbcon_cfb16;
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem + 1 * MB_;
+		disp->dispsw_data = fb_info->fbcon_cmap.cfb16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		printk ("24 bit color depth\n");
+		disp->dispsw = &fbcon_cfb24;
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
+		disp->dispsw_data = fb_info->fbcon_cmap.cfb24;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		printk ("32 bit color depth\n");
+		if (accel_text)
+			disp->dispsw = &fbcon_clgen_32;
+		else
+			disp->dispsw = &fbcon_cfb32;
+		if (fb_info->btype == BT_GD5480)
+			disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
+		disp->dispsw_data = fb_info->fbcon_cmap.cfb32;
+		break;
+#endif
+
+	default:
+		printk ("unsupported color depth\n");
+		disp->dispsw = &fbcon_dummy;
+		disp->dispsw_data = NULL;
+		break;
+	}
+
+	DPRINTK ("EXIT\n");
+}
+
+#ifdef FBCON_HAS_CFB8
+static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
+				int dy, int dx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p);
+	sy *= fontheight (p);
+	dx *= fontwidth (p);
+	dy *= fontheight (p);
+	width *= fontwidth (p);
+	height *= fontheight (p);
+
+	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
+		      (unsigned short) dx, (unsigned short) dy,
+		      (unsigned short) width, (unsigned short) height,
+		      fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
+				int sy, int sx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+	unsigned short col;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p);
+	sy *= fontheight (p);
+	width *= fontwidth (p);
+	height *= fontheight (p);
+
+	col = attr_bgcol_ec (p, conp);
+	col &= 0xff;
+
+	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
+			(unsigned short) width, (unsigned short) height,
+			col, fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif
+
+#ifdef FBCON_HAS_CFB16
+static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	sy *= fontheight (p);
+	dx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	dy *= fontheight (p);
+	width *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	height *= fontheight (p);
+
+	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
+		      (unsigned short) dx, (unsigned short) dy,
+		      (unsigned short) width, (unsigned short) height,
+		      fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+	unsigned short col;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
+	sy *= fontheight (p);
+	width *= fontwidth (p) * 2;	/* 2 bytes/pixel? */
+	height *= fontheight (p);
+
+	col = attr_bgcol_ec (p, conp);
+	col &= 0xff;
+
+	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
+			(unsigned short) width, (unsigned short) height,
+			col, fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif
+
+#ifdef FBCON_HAS_CFB32
+static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
+				 int dy, int dx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	sy *= fontheight (p);
+	dx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	dy *= fontheight (p);
+	width *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	height *= fontheight (p);
+
+	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
+		      (unsigned short) dx, (unsigned short) dy,
+		      (unsigned short) width, (unsigned short) height,
+		      fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width)
+{
+	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
+
+	unsigned short col;
+
+	DPRINTK ("ENTER\n");
+
+	sx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
+	sy *= fontheight (p);
+	width *= fontwidth (p) * 4;	/* 4 bytes/pixel? */
+	height *= fontheight (p);
+
+	col = attr_bgcol_ec (p, conp);
+	col &= 0xff;
+
+	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
+			(unsigned short) width, (unsigned short) height,
+			col, fb_info->currentmode.line_length);
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif				/* FBCON_HAS_CFB32 */
+
+
+
+
+#ifdef CONFIG_PREP
+#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
+#define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
+static void __init get_prep_addrs (unsigned long *display, unsigned long *registers)
+{
+	DPRINTK ("ENTER\n");
+
+	*display = PREP_VIDEO_BASE;
+	*registers = (unsigned long) PREP_IO_BASE;
+
+	DPRINTK ("EXIT\n");
+}
+
+#endif				/* CONFIG_PREP */
+
+
+
+
+#ifdef CONFIG_FB_OF
+static void __init get_of_addrs (const struct device_node *dp,
+			  unsigned long *display, unsigned long *registers)
+{
+	int i;
+
+	DPRINTK ("ENTER\n");
+
+	/* Map in frame buffer and registers */
+	for (i = 0; i < dp->n_addrs; ++i) {
+		unsigned long addr = dp->addrs[i].address;
+		unsigned long size = dp->addrs[i].size;
+		printk ("dp->addrs[%d].address = $lx, dp->addrs[%d].size = %lx\n",
+			i, addr, i, size);
+		if (size >= 0x800000) {
+			*display = addr;
+		} else {
+			*registers = addr;
+		}
+	}
+
+	DPRINTK ("EXIT\n");
+}
+#endif				/* CONFIG_FB_OF */
+
+
+
+
+#ifdef CONFIG_PCI
+/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
+ * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
+ * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
+ * seem to have. */
+static unsigned int __init clgen_get_memsize (caddr_t regbase)
+{
+	unsigned long mem = 1 * MB_;
+	unsigned char SRF;
+
+	DPRINTK ("ENTER\n");
+
+	SRF = vga_rseq (regbase, CL_SEQRF);
+	if ((SRF & 0x18) == 0x18) {
+		/* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
+		   * on the 5430. */
+		mem *= 2;
+	}
+	if (SRF & 0x80) {
+		/* If DRAM bank switching is enabled, there must be twice as much
+		   * memory installed. (4MB on the 5434) */
+		mem *= 2;
+	}
+	return mem;
+
+	DPRINTK ("EXIT\n");
+}
+
+
+
+static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype)
+{
+	struct pci_dev *pdev = NULL;
+	int i;
+
+	DPRINTK ("ENTER\n");
+	
+	for (i = 0; i < arraysize(clgen_pci_probe_list) && !pdev; i++)
+		pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS,
+					clgen_pci_probe_list[i].device, NULL);
+	
+	if (pdev)
+		*btype = clgen_pci_probe_list[i].btype;
+
+	DPRINTK ("EXIT, returning %p\n", pdev);
+	return pdev;
+}
+
+
 
-	case BT_PICASSO4:
-	    DEBUG printk(KERN_INFO "(for Picasso 4)\n");
-	    WSeq(SEQR7, 0x20);
-/*	    WSeq(SEQR1F, 0x1c); */
-/* SEQRF not being set here...	WSeq(SEQRF, 0xd0); */
-	    break;
 
-	default:
-	    printk(KERN_WARNING "clgen: unknown Board\n");
-	    break;
-	}
+static void __init get_pci_addrs (const struct pci_dev *pdev,
+			   unsigned long *display, unsigned long *registers)
+{
+	assert (pdev != NULL);
+	assert (display != NULL);
+	assert (registers != NULL);
 
-	WGen(M_3C6,0x01);     /* pixel mask: pass-through for first plane */
-	WHDR(0);              /* hidden dac reg: nothing special */
-	WSeq(SEQR4,  0x06);     /* memory mode: odd/even, ext. memory */
-	WSeq(SEQR2, 0x01);      /* plane mask: only write to first plane */
-	offset 			= _par->var.xres_virtual / 16;
-    }
-    else if (_par->var.bits_per_pixel == 8)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 8 bit deep display\n");
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    WSeq(SEQR7,  0xf1); /* Extended Sequencer Mode: 256c col. mode */
-	    WSeq(SEQR1F, 0x1d);     /* MCLK select */
-	    break;
+	DPRINTK ("ENTER\n");
 
-	case BT_PICCOLO:
-	    WSeq(SEQR7, 0x81);
-	    WSeq(SEQR1F, 0x22);     /* ### vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    break;
+	*display = 0;
+	*registers = 0;
 
-	case BT_PICASSO:
-	    WSeq(SEQR7, 0x21);
-	    WSeq(SEQR1F, 0x22);     /* ### vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    break;
+	/* This is a best-guess for now */
 
-	case BT_SPECTRUM:
-	    WSeq(SEQR7, 0x81);
-	    WSeq(SEQR1F, 0x22);     /* ### vorher 1c MCLK select */
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    break;
 
-	case BT_PICASSO4:
-	    WSeq(SEQR7, 0x21);
-	    WSeq(SEQRF, 0xb8); /* ### INCOMPLETE!! */
-/*	    WSeq(SEQR1F, 0x1c); */
-	    break;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
 
-	default:
-	    printk(KERN_WARNING "clgen: unknown Board\n");
-	    break;
+        *display = pdev->base_address[0];
+        if ((*display & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+                *registers = *display;
+                *display = pdev->base_address[1];
+         } else {
+                *registers = pdev->base_address[1];
 	}
 
-	WGfx(GR5,    64);     /* mode register: 256 color mode */
-	WGen(M_3C6,0xff);     /* pixel mask: pass-through all planes */
-	WHDR(0);              /* hidden dac reg: nothing special */
-	WSeq(SEQR4,  0x0a);     /* memory mode: chain4, ext. memory */
-	WSeq(SEQR2,  0xff);     /* plane mask: enable writing to all 4 planes */
-	offset 			= _par->var.xres_virtual / 8;
-    }
-    else if (_par->var.bits_per_pixel == 16)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 16 bit deep display\n");
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    WSeq(SEQR7,  0xf7); /* Extended Sequencer Mode: 256c col. mode */
-	    WSeq(SEQR1F, 0x1e);     /* MCLK select */
-	    break;
-
-	case BT_PICCOLO:
-	    WSeq(SEQR7, 0x87);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+#else
 
-	case BT_PICASSO:
-	    WSeq(SEQR7, 0x27);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+	if (pdev->resource[0].flags & IORESOURCE_IOPORT) {
+		*display = pdev->resource[1].start;
+		*registers = pdev->resource[0].start;
+	} else {
+		*display = pdev->resource[0].start;
+		*registers = pdev->resource[1].start;
+	}
 
-	case BT_SPECTRUM:
-	    WSeq(SEQR7, 0x87);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+#endif		/* kernel older than 2.3.13 */
 
-	case BT_PICASSO4:
-	    WSeq(SEQR7, 0x27);
-/*	    WSeq(SEQR1F, 0x1c);  */
-	    break;
+	assert (*display != 0);
 
-	default:
-	    printk(KERN_WARNING "CLGEN: unknown Board\n");
-	    break;
-	}
+	DPRINTK ("EXIT\n");
+}
 
-	WGfx(GR5,    64);     /* mode register: 256 color mode */
-	WGen(M_3C6,0xff);     /* pixel mask: pass-through all planes */
-	WHDR(0xa0);           /* hidden dac reg: nothing special */
-	WSeq(SEQR4,  0x0a);     /* memory mode: chain4, ext. memory */
-	WSeq(SEQR2,  0xff);     /* plane mask: enable writing to all 4 planes */
-	offset 			= _par->var.xres_virtual / 4;
-    }
-    else if (_par->var.bits_per_pixel == 32)
-    {
-	DEBUG printk(KERN_INFO "clgen: preparing for 24/32 bit deep display\n");
-	switch(fb_info->btype)
-	{
-	case BT_SD64:
-	    WSeq(SEQR7,  0xf9); /* Extended Sequencer Mode: 256c col. mode */
-	    WSeq(SEQR1F, 0x1e);     /* MCLK select */
-	    break;
 
-	case BT_PICCOLO:
-	    WSeq(SEQR7, 0x85);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
 
-	case BT_PICASSO:
-	    WSeq(SEQR7, 0x25);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
 
-	case BT_SPECTRUM:
-	    WSeq(SEQR7, 0x85);
-	    WSeq(SEQRF, 0xb0);    /* Fast Page-Mode writes */
-	    WSeq(SEQR1F, 0x22);     /* MCLK select */
-	    break;
+static int __init clgen_pci_setup (struct clgenfb_info *info,
+				   clgen_board_t *btype)
+{
+#ifdef CONFIG_FB_OF
+	struct device_node *dp;
+#endif				/* CONFIG_FB_OF */
+	struct pci_dev *pdev;
+	unsigned long board_addr, board_size;
+	u16 tmp16;
 
-	case BT_PICASSO4:
-	    WSeq(SEQR7, 0x25);
-/*	    WSeq(SEQR1F, 0x1c);  */
-	    break;
+	DPRINTK ("ENTER\n");
 
-	default:
-	    printk(KERN_WARNING "clgen: unknown Board\n");
-	    break;
+	pdev = clgen_pci_dev_get (btype);
+	if (!pdev) {
+		printk (KERN_ERR " Couldn't find PCI device\n");
+		DPRINTK ("EXIT, returning 1\n");
+		return 1;
 	}
+	DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
+		 pdev->resource[0].start, *btype);
+	DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
 
-	WGfx(GR5,    64);     /* mode register: 256 color mode */
-	WGen(M_3C6,0xff);     /* pixel mask: pass-through all planes */
-	WHDR(0xc5);           /* hidden dac reg: 8-8-8 mode (24 or 32) */
-	WSeq(SEQR4,  0x0a);     /* memory mode: chain4, ext. memory */
-	WSeq(SEQR2,  0xff);     /* plane mask: enable writing to all 4 planes */
-	offset			= _par->var.xres_virtual / 4;
-    }
-    else
-	printk(KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
-		_par->var.bits_per_pixel);
-
-    WCrt(CRT13, offset & 0xff);
-    tmp = 0x22;
-    if (offset & 0x100) tmp |= 0x10; /* offset overflow bit */
-    	
-    WCrt(CRT1B,tmp);    /* screen start addr #16-18, fastpagemode cycles */
-
-    if (fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4)
-    	WCrt(CRT1D, 0x00);   /* screen start address bit 19 */
-
-    WCrt(CRTE,    0);      /* text cursor location high */
-    WCrt(CRTF,    0);      /* text cursor location low */
-    WCrt(CRT14,   0);      /* underline row scanline = at very bottom */
-
-    WAttr(AR10,  1);      /* controller mode */
-    WAttr(AR11,  0);      /* overscan (border) color */
-    WAttr(AR12, 15);      /* color plane enable */
-    WAttr(AR33,  0);      /* pixel panning */
-    WAttr(AR14,  0);      /* color select */
-
-    /* [ EGS: SetOffset(); ] */
-    /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
-    AttrOn();
-
-    WGfx(GR0,    0);      /* set/reset register */
-    WGfx(GR1,    0);      /* set/reset enable */
-    WGfx(GR2,    0);      /* color compare */
-    WGfx(GR3,    0);      /* data rotate */
-    WGfx(GR4,    0);      /* read map select */
-    WGfx(GR6,    1);      /* miscellaneous register */
-    WGfx(GR7,   15);      /* color don't care */
-    WGfx(GR8,  255);      /* bit mask */
-
-    WSeq(SEQR12,  0x0);     /* graphics cursor attributes: nothing special */
-
-    /* finally, turn on everything - turn off "FullBandwidth" bit */
-    /* also, set "DotClock%2" bit where requested */
-    tmp = 0x01;
+	info->pdev = pdev;
 
-/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
-    if (var->vmode & FB_VMODE_CLOCK_HALVE)
-	tmp |= 0x08;
-*/
+#ifdef CONFIG_PREP
+	/* Xbh does this, though 0 seems to be the init value */
+	pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 0x00000000);
+#endif
 
-    WSeq(SEQR1, tmp);
-    DEBUG printk("SEQR1: %d\n", tmp);
+	pci_read_config_word (pdev, PCI_COMMAND, &tmp16);
+	if (!(tmp16 & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))) {
+		tmp16 |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+		pci_write_config_word (pdev, PCI_COMMAND, tmp16);
+	}
+
+#ifdef CONFIG_FB_OF
+	/* Ok, so its an ugly hack, since we could have passed it down from
+	 * clgen_of_init() if we'd done it right. */
+	DPRINTK ("Attempt to get OF info for MacPicasso\n");
+	dp = find_devices ("MacPicasso");
+	if (dp != 0) {
+		if (dp->n_addrs != 2) {
+			printk (KERN_ERR "expecting 2 address for clgen (got %d)\n", dp->n_addrs);
+			DPRINTK ("EXIT, returning 1\n");
+			return 1;
+		}
+		get_of_addrs (dp, &board_addr, &info->fbregs_phys);
+	} else
+#endif
+	{
 
-#if 0
-    DEBUG printk(KERN_INFO "clgen: clearing display...");
-    clgen_RectFill(0, 0, _par->HorizRes, _par->VertRes, 0, _par->line_length);
-    clgen_WaitBLT();
-    DEBUG printk("done.\n");
+#ifdef CONFIG_PREP
+		get_prep_addrs (&board_addr, &info->fbregs_phys);
+#else				/* CONFIG_PREP */
+		DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
+		get_pci_addrs (pdev, &board_addr, &info->fbregs_phys);
+#endif				/* CONFIG_PREP */
+	}
+
+	DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys);
+
+#ifdef CONFIG_PREP
+	/* PReP dies if we ioremap the IO registers, but it works w/out... */
+	info->regs = (char *) info->fbregs_phys;
+#else
+	info->regs = 0;		/* FIXME: this forces VGA.  alternatives? */
 #endif
 
-    fb_info->currentmode = *_par;
+	if (*btype == BT_GD5480) {
+		board_size = 32 * MB_;
+	} else {
+		board_size = clgen_get_memsize (info->regs);
+	}
+	info->fbmem = ioremap (board_addr, board_size);
+	info->fbmem_phys = board_addr;
+
+	printk (" RAM (%lu MB) at $%lx, ", board_size / 0x100000, board_addr);
 
-    printk("virtual offset: (%d,%d)\n", _par->var.xoffset,_par->var.yoffset);
-    /* pan to requested offset */
-    clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen*)fb_info);
+	printk (KERN_INFO "Cirrus Logic chipset on PCI bus\n");
 
-    DEBUG printk("<clgen_set_par()\n");
-    return;
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
 }
+#endif				/* CONFIG_PCI */
 
-static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-    unsigned char bred, bgreen, bblue;
 
-    if (regno > 255)
-	return (1);
 
-    fb_info = (struct clgenfb_info *)info;
 
-    RClut(regno, &bred, &bgreen, &bblue);
+#ifdef CONFIG_ZORRO
+static int __init clgen_zorro_find (int *key_o, int *key2_o, clgen_board_t *btype)
+{
+	int i, key = 0;
+	
+	assert (key_o != NULL);
+	assert (btype != NULL);
 
-    *red = (bred<<10) | (bred<<4) | (bred>>2);
-    *green = (bgreen<<10) | (bgreen<<4) | (bgreen>>2);
-    *blue = (bblue<<10) | (bblue<<4) | (bblue>>2);
-    *transp = 0;
-    return (0);
+	for (i = 0; i < arraysize(clgen_zorro_probe_list) && !key; i++)
+		key = zorro_find (clgen_zorro_probe_list[i].key, 0, 0);
+
+	if (key) {
+		*key_o = key;
+		if (clgen_zorro_probe_list[i].key2)
+			*key2_o = zorro_find (clgen_zorro_probe_list[i].key2, 0, 0);
+		else
+			*key2_o = 0;
+		*btype = clgen_zorro_probe_list[i].btype;
+		
+		printk (KERN_INFO "clgen: %s board detected; ",
+			clgen_board_info[*btype].name);
+		
+		return 0;
+	}
+	
+	printk (KERN_NOTICE "clgen: no supported board found.\n");
+	return -1;
 }
 
-static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp, 
-			   struct fb_info *info)
+
+
+static int __init clgen_zorro_setup (struct clgenfb_info *info,
+				     clgen_board_t *btype)
 {
-    if (regno > 255)
-	return (1);
+	int key = 0, key2 = 0;
+	const struct ConfigDev *cd = NULL;
+	const struct ConfigDev *cd2 = NULL;
+	unsigned long board_addr, board_size;
+	
+	assert (info != NULL);
+	assert (btype != NULL);
 
-    fb_info = (struct clgenfb_info *)info;
-    
-    /* "transparent" stuff is completely ignored. */
-    WClut(regno, red>>10, green>>10, blue>>10);
+	if (clgen_zorro_find (&key, &key2, btype))
+		return -1;
 
-    return (0);
-}
+	assert (key > 0);
+	assert (key2 >= 0);
+	assert (*btype != BT_NONE);
+	
+	info->keyRAM = key;
+	info->keyREG = key2;
+	cd = zorro_get_board (key);
+	board_addr = (unsigned long) cd->cd_BoardAddr;
+	board_size = (unsigned long) cd->cd_BoardSize;
+	printk (" RAM (%lu MB) at $%lx, ", board_size / 0x100000, board_addr);
+
+	if (*btype == BT_PICASSO4) {
+		printk (" REG at $%lx\n", board_addr + 0x600000);
+
+		/* To be precise, for the P4 this is not the */
+		/* begin of the board, but the begin of RAM. */
+		/* for P4, map in its address space in 2 chunks (### TEST! ) */
+		/* (note the ugly hardcoded 16M number) */
+		info->regs = ioremap (board_addr, 16777216);
+		DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
+		info->regs += 0x600000;
+		info->fbregs_phys = board_addr + 0x600000;
+
+		info->fbmem_phys = board_addr + 16777216;
+		info->fbmem = ioremap (info->fbmem_phys, 16777216);
+	} else {
+		cd2 = zorro_get_board (key2);
+		printk (" REG at $%lx\n", (unsigned long) cd2->cd_BoardAddr);
+
+		info->fbmem_phys = board_addr;
+		if (board_addr > 0x01000000)
+			info->fbmem = ioremap (board_addr, board_size);
+		else
+			info->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
 
-/*************************************************************************
-	clgen_pan_display()
+		/* set address for REG area of board */
+		info->regs = (caddr_t) ZTWO_VADDR (cd2->cd_BoardAddr);
+		info->fbregs_phys = (unsigned long) cd2->cd_BoardAddr;
 
-	performs display panning - provided hardware permits this
-**************************************************************************/
-static int clgen_pan_display(const struct fb_var_screeninfo *var,
-			     struct fb_info_gen *info)
-{
-    int xoffset = 0;
-    int yoffset = 0;
-    unsigned long base;
-    unsigned char tmp = 0, tmp2 = 0, xpix;
-
-    fb_info = (struct clgenfb_info*)fb_info;
-
-    /* no range checks for xoffset and yoffset,   */
-    /* as fbgen_pan_display has already done this */
-
-    fb_info->currentmode.var.xoffset = var->xoffset;
-    fb_info->currentmode.var.yoffset = var->yoffset;
-
-    xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
-    yoffset = var->yoffset;
-
-    base = yoffset * fb_info->currentmode.line_length + xoffset;
-
-    if (fb_info->currentmode.var.bits_per_pixel == 1)
-    {
-	/* base is already correct */
-	xpix = (unsigned char)(var->xoffset % 8);
-    }
-    else
-    {
-	base /= 4;
-	xpix = (unsigned char)((xoffset % 4) * 2);
-    }
-
-    /* lower 8 + 8 bits of screen start address */
-    WCrt(CRTD, (unsigned char)(base & 0xff));
-    WCrt(CRTC, (unsigned char)(base >> 8));
-
-    /* construct bits 16, 17 and 18 of screen start address */
-    if (base & 0x10000) tmp |= 0x01;
-    if (base & 0x20000) tmp |= 0x04;
-    if (base & 0x40000) tmp |= 0x08;
-
-    tmp2 = (RCrt(CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
-    WCrt(CRT1B, tmp2);
-    /* construct bit 19 of screen start address (only on SD64) */
-    if (fb_info->btype == BT_SD64 ||
-	fb_info->btype == BT_PICASSO4)
-    {
-	tmp2 = 0;
-	if (base & 0x80000) tmp2 = 0x80;
-	WCrt(CRT1D, tmp2);
-    }
-
-    /* write pixel panning value to AR33; this does not quite work in 8bpp */
-    /* ### Piccolo..? Will this work? */
-    if (fb_info->currentmode.var.bits_per_pixel == 1)
-	WAttr(AR33, xpix);
-
-    return(0);
-}
-
-
-static int clgen_blank(int blank_mode, struct fb_info_gen *info)
-{
-    unsigned char val;
-    printk(">clgen_blank(%d)\n",blank_mode);
-
-    fb_info = (struct clgenfb_info *)info;
-
-    val = RSeq(SEQR1);
-    if (blank_mode)
-	WSeq(SEQR1, val | 0x20); /* set "FullBandwidth" bit */
-    else
-	WSeq(SEQR1, val & 0xdf); /* clear "FullBandwidth" bit */
+		DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
+	}
+
+	/* mark this board as "autoconfigured" */
+	zorro_config_board (key, 0);
+	if (*btype != BT_PICASSO4)
+		zorro_config_board (key2, 0);
 
-    printk("<clgen_blank()\n");
-    return 0;
+	printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
+	
+	return 0;
 }
+#endif /* CONFIG_ZORRO */
 
-/**** END   Hardware specific Routines **************************************/
-/****************************************************************************/
-/**** BEGIN Internal Routines ***********************************************/
 
-static void init_vgachip(void)
+
+/********************************************************************/
+/* clgenfb_init() - master initialization function                  */
+/********************************************************************/
+int __init clgenfb_init(void)
 {
-    printk(">init_vgachip()\n");
+	int err;
 
-    /* reset board globally */
-    switch(fb_info->btype)
-    {
-    case BT_SD64:     WSFR(0x1f);  udelay(500); WSFR(0x4f); udelay(500); break;
-    case BT_PICCOLO:  WSFR(0x01);  udelay(500); WSFR(0x51); udelay(500); break;
-    case BT_PICASSO:  WSFR2(0xff); udelay(500);				 break;
-    case BT_SPECTRUM: WSFR(0x1f);  udelay(500); WSFR(0x4f); udelay(500); break;
-    case BT_PICASSO4: 
-	WCrt(CRT51, 0x00); /* disable flickerfixer */
-	udelay(100000);
-	WGfx(GR2F, 0x00); /* from Klaus' NetBSD driver: */
-	WGfx(GR33, 0x00); /* put blitter into 542x compat */
-	WGfx(GR31, 0x00); /* mode */
-	break;
-
-    default:
-	printk(KERN_ERR "clgen: Warning: Unknown board type\n");
-	break;
-    }
-
-    /* "pre-set" a RAMsize; if the test succeeds, double it */
-    if (fb_info->btype == BT_SD64 ||
-        fb_info->btype == BT_PICASSO4)
-        fb_info->size = 0x400000;
-    else
-        fb_info->size = 0x200000;
-
-    /* assume it's a "large memory" board (2/4 MB) */
-    fb_info->smallboard = FALSE;
-
-    /* the P4 is not fully initialized here; I rely on it having been */
-    /* inited under AmigaOS already, which seems to work just fine    */
-    /* (Klaus advised to do it this way)                              */
-
-    if (fb_info->btype != BT_PICASSO4)
-    {
-	WGen(VSSM, 0x10);  /* EGS: 0x16 */
-	WGen(POS102, 0x01);
-	WGen(VSSM, 0x08);  /* EGS: 0x0e */
-
-	if(fb_info->btype != BT_SD64)
-		WGen(VSSM2, 0x01);
-
-	WSeq(SEQR0, 0x03);  /* reset sequencer logic */
-
-	WSeq(SEQR1, 0x21);  /* FullBandwidth (video off) and 8/9 dot clock */
-	WGen(MISC_W, 0xc1);  /* polarity (-/-), disable access to display memory, CRTC base address: color */
+	clgen_board_t btype = BT_NONE;
+	struct clgenfb_info *fb_info = NULL;
 
-/*	WGfx(GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
-	WSeq(SEQR6, 0x12);   /* unlock all extension registers */
+	DPRINTK ("ENTER\n");
 
-	WGfx(GR31, 0x04);  /* reset blitter */
+	printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n");
 
-	if (fb_info->btype == BT_SD64)
-	{
-	    WSeq(SEQRF, 0xb8);  /* 4 MB Ram SD64, disable CRT fifo(!), 64 bit bus */
+	fb_info = &boards[0];	/* FIXME support multiple boards ... */
+
+#ifdef CONFIG_PCI
+	if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */
+		DPRINTK ("EXIT, returning -ENXIO\n");
+		return -ENXIO;
 	}
-	else
-	{
-	    WSeq(SEQR16, 0x0f); /* Perf. Tuning: Fix value..(?) */
-	    WSeq(SEQRF, 0xb0); /* 2 MB DRAM, 8level write buffer, 32bit bus */
+
+#elif CONFIG_ZORRO
+	if (clgen_zorro_setup (fb_info, &btype)) {
+		DPRINTK ("EXIT, returning -ENXIO\n");
+		return -ENXIO;
 	}
-    }
 
-    WSeq(SEQR2, 0xff);  /* plane mask: nothing */
-    WSeq(SEQR3, 0x00);  /* character map select: doesn't even matter in gx mode */
-    WSeq(SEQR4, 0x0e);  /* memory mode: chain-4, no odd/even, ext. memory */
-
-    /* controller-internal base address of video memory */
-    switch(fb_info->btype)
-    {
-    case BT_SD64:     WSeq(SEQR7, 0xf0); break;
-    case BT_PICCOLO:  WSeq(SEQR7, 0x80); break;
-    case BT_SPECTRUM: WSeq(SEQR7, 0x80); break;
-    case BT_PICASSO:  WSeq(SEQR7, 0x20); break;
-    case BT_PICASSO4: WSeq(SEQR7, 0x20); break;
-    }
-
-/*  WSeq(SEQR8, 0x00);*/  /* EEPROM control: shouldn't be necessary to write to this at all.. */
-
-    WSeq(SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
-    WSeq(SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
-    WSeq(SEQR12, 0x00); /* graphics cursor attributes */
-    WSeq(SEQR13, 0x00); /* graphics cursor pattern address */
-
-    /* writing these on a P4 might give problems..  */
-    if (fb_info->btype != BT_PICASSO4)
-    {
-	WSeq(SEQR17, 0x00); /* configuration readback and ext. color */
-	WSeq(SEQR18, 0x02); /* signature generator */
-    }
-
-    /* MCLK select etc. */
-    switch(fb_info->btype)
-    {
-    case BT_PICCOLO:
-    case BT_PICASSO:
-    case BT_SPECTRUM:  WSeq(SEQR1F, 0x22); break;
-    case BT_SD64:      WSeq(SEQR1F, 0x20); break;
-    case BT_PICASSO4:/*WSeq(SEQR1F, 0x1c); */ break;
-    }
-
-    WCrt(CRT8, 0x00);  /* Screen A preset row scan: none */
-    WCrt(CRTA, 0x20);  /* Text cursor start: disable text cursor */
-    WCrt(CRTB, 0x00);  /* Text cursor end: - */
-    WCrt(CRTC, 0x00);  /* Screen start address high: 0 */
-    WCrt(CRTD, 0x00);  /* Screen start address low: 0 */
-    WCrt(CRTE, 0x00);  /* text cursor location high: 0 */
-    WCrt(CRTF, 0x00);  /* text cursor location low: 0 */
-
-    WCrt(CRT14, 0x00); /* Underline Row scanline: - */
-    WCrt(CRT17, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
-    WCrt(CRT18, 0x00); /* Line Compare: not needed */
-    /* ### add 0x40 for text modes with > 30 MHz pixclock */
-    WCrt(CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
-
-    WGfx(GR0, 0x00); /* Set/Reset registes: - */
-    WGfx(GR1, 0x00); /* Set/Reset enable: - */
-    WGfx(GR2, 0x00); /* Color Compare: - */
-    WGfx(GR3, 0x00); /* Data Rotate: - */
-    WGfx(GR4, 0x00); /* Read Map Select: - */
-    WGfx(GR5, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
-    WGfx(GR6, 0x01); /* Miscellaneous: memory map base address, graphics mode */
-    WGfx(GR7, 0x0f); /* Color Don't care: involve all planes */
-    WGfx(GR8, 0xff); /* Bit Mask: no mask at all */
-    WGfx(GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
-
-    WGfx(GRC, 0xff); /* Color Key compare: - */
-    WGfx(GRD, 0x00); /* Color Key compare mask: - */
-    WGfx(GRE, 0x00); /* Miscellaneous control: - */
-/*  WGfx(GR10, 0x00);*/ /* Background color byte 1: - */
-/*  WGfx(GR11, 0x00); */
-
-    WAttr(AR0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
-    WAttr(AR1, 0x01);
-    WAttr(AR2, 0x02);
-    WAttr(AR3, 0x03);
-    WAttr(AR4, 0x04);
-    WAttr(AR5, 0x05);
-    WAttr(AR6, 0x06);
-    WAttr(AR7, 0x07);
-    WAttr(AR8, 0x08);
-    WAttr(AR9, 0x09);
-    WAttr(ARA, 0x0a);
-    WAttr(ARB, 0x0b);
-    WAttr(ARC, 0x0c);
-    WAttr(ARD, 0x0d);
-    WAttr(ARE, 0x0e);
-    WAttr(ARF, 0x0f);
-
-    WAttr(AR10, 0x01); /* Attribute Controller mode: graphics mode */
-    WAttr(AR11, 0x00); /* Overscan color reg.: reg. 0 */
-    WAttr(AR12, 0x0f); /* Color Plane enable: Enable all 4 planes */
-/* ### 	WAttr(AR33, 0x00); * Pixel Panning: - */
-    WAttr(AR14, 0x00); /* Color Select: - */
-
-    WGen(M_3C6, 0xff); /* Pixel mask: no mask */
-
-    WGen(MISC_W, 0xc3); /* polarity (-/-), enable display mem, CRTC i/o base = color */
-
-    WGfx(GR31, 0x04); /* BLT Start/status: Blitter reset */
-    WGfx(GR31, 0x00); /* - " -           : "end-of-reset" */
-
-    /* CLUT setup */
-    WClut( 0, 0x00, 0x00, 0x00);  /* background: black */
-    WClut( 1, 0x3f, 0x3f, 0x3f);  /* foreground: white */
-    WClut( 2, 0x00, 0x20, 0x00);
-    WClut( 3, 0x00, 0x20, 0x20);
-    WClut( 4, 0x20, 0x00, 0x00);
-    WClut( 5, 0x20, 0x00, 0x20);
-    WClut( 6, 0x20, 0x10, 0x00);
-    WClut( 7, 0x20, 0x20, 0x20);
-    WClut( 8, 0x10, 0x10, 0x10);
-    WClut( 9, 0x10, 0x10, 0x30);
-    WClut(10, 0x10, 0x30, 0x10);
-    WClut(11, 0x10, 0x30, 0x30);
-    WClut(12, 0x30, 0x10, 0x10);
-    WClut(13, 0x30, 0x10, 0x30);
-    WClut(14, 0x30, 0x30, 0x10);
-    WClut(15, 0x30, 0x30, 0x30);
+#else
+#error Unsupported bus.  Supported: PCI, Zorro
+#endif				/* !CONFIG_PCI, !CONFIG_ZORRO */
 
-    /* the rest a grey ramp */
-    {
-	int i;
+	/* sanity checks */
+	assert (btype != BT_NONE);
+	assert (btype == clgen_board_info[btype].btype);
 
-	for (i = 16; i < 256; i++)
-	    WClut(i, i>>2, i>>2, i>>2);
-    }
+	fb_info->btype = btype;
 
+	DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
 
-    /* misc... */
-    WHDR(0); /* Hidden DAC register: - */
+	init_vgachip (fb_info);
 
-#if 0
-    /* check for 1/2 MB Piccolo/Picasso/Spectrum resp. 2/4 MB SD64 */
-    /* DRAM register has already been pre-set for "large", so it is*/
-    /* only modified if we find that this is a "small" version */
-    {
-	unsigned volatile char *ram = fb_info->fbmem;
-	int i, flag = 0;
+	/* set up a few more things, register framebuffer driver etc */
+	fb_info->gen.parsize = sizeof (struct clgenfb_par);
+	fb_info->gen.fbhw = &clgen_hwswitch;
 
-	ram += (fb_info->size >> 1);
+	strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name,
+		 sizeof (fb_info->gen.info.modename));
+	fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0;
 
-	for (i = 0; i < 256; i++)
-	    ram[i] = (unsigned char)i;
+	fb_info->gen.info.node = -1;
+	fb_info->gen.info.fbops = &clgenfb_ops;
+	fb_info->gen.info.disp = &disp;
+	fb_info->gen.info.changevar = NULL;
+	fb_info->gen.info.switch_con = &fbgen_switch;
+	fb_info->gen.info.updatevar = &fbgen_update_var;
+	fb_info->gen.info.blank = &fbgen_blank;
+	fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
 
-	for (i = 0; i < 256; i++)
-	{
-	    if (ram[i] != i)
-		flag = 1;
-	}
+	/* now that we know the board has been registered n' stuff, we */
+	/* can finally initialize it to a default mode */
+	clgenfb_default = clgenfb_predefined[clgen_def_mode].var;
+	clgenfb_default.activate = FB_ACTIVATE_NOW;
+	clgenfb_default.yres_virtual = 480 * 3;		/* for fast scrolling (YPAN-Mode) */
+	err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen);
 
-	/* if the DRAM test failed, halve RAM value */
-	if (flag)
-	{
-	    fb_info->size /= 2;
-	    fb_info->smallboard = TRUE;
-	    switch(fb_info->btype)
-	    {
-	    case BT_SD64:     WSeq(SEQRF, 0x38); break; /* 2 MB Ram SD64 */
-	    case BT_PICASSO4: WSeq(SEQRF, 0x38); break; /* ### like SD64? */
-	    case BT_PICCOLO:
-	    case BT_PICASSO:
-	    case BT_SPECTRUM: WSeq(SEQRF, 0x30); break; /* 1 MB DRAM */
-	    default:
-		printk(KERN_WARNING "clgen: Uuhh..could not determine RAM size!\n");
-	    }
-	}
-
-    }
-#endif
-    printk(KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size);
-    printk("<init_vgachip()\n");
-    return;
-}
-
-static void switch_monitor(int on)
-{
-    static int IsOn = 0;    /* XXX not ok for multiple boards */
-
-    if (fb_info->btype == BT_PICASSO4) return; /* nothing to switch */
-    if (fb_info->btype == BT_PICASSO)
-    {
-	if ((on && !IsOn) || (!on && IsOn))
-	    WSFR(0xff);
-	return;
-    }    
-    if (on)
-        switch(fb_info->btype)
-	{
-        case BT_SD64:     WSFR(fb_info->SFR | 0x21);	break;
-        case BT_PICCOLO:  WSFR(fb_info->SFR | 0x28);	break;
-        case BT_SPECTRUM: WSFR(0x6f);			break;
+	if (err) {
+		DPRINTK ("EXIT, returning -EINVAL\n");
+		return -EINVAL;
 	}
-    else
-        switch(fb_info->btype)
-	{
-        case BT_SD64:     WSFR(fb_info->SFR & 0xde);	break;
-        case BT_PICCOLO:  WSFR(fb_info->SFR & 0xd7);	break;
-        case BT_SPECTRUM: WSFR(0x4f);			break;
-	}
-}
-
-static void clgen_set_disp(const void *par, struct display *disp,
-			   struct fb_info_gen *info)
-{
-    struct clgenfb_par *_par = (struct clgenfb_par*) par;
-    struct clgenfb_info *info2 = (struct clgenfb_info *)info;
-
-    printk("clgen_set_disp(): ");
-    disp->screen_base = info2->fbmem;
-    switch (_par->var.bits_per_pixel)
-    {
-#ifdef FBCON_HAS_MFB
-    case 1:
-	printk("monochrome\n");
-	disp->dispsw = &fbcon_mfb;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB8
-    case 8:
-	printk("8 bit color depth\n");
-	disp->dispsw = &fbcon_clgen_8;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB16
-    case 16:
-	printk("16 bit color depth\n");
-	disp->dispsw = &fbcon_cfb16;
-	disp->dispsw_data = info2->fbcon_cmap.cfb16;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB24
-    case 24:
-	printk("24 bit color depth\n");
-	disp->dispsw = &fbcon_cfb24;
-	disp->dispsw_data = info2->fbcon_cmap.cfb24;
-	break;
-#endif
-#ifdef FBCON_HAS_CFB32
-    case 32:
-	printk("32 bit color depth\n");
-	disp->dispsw = &fbcon_cfb32;
-	disp->dispsw_data = info2->fbcon_cmap.cfb32;
-	break;
-#endif
 
-    default:
-	printk("unsupported color depth\n");
-	disp->dispsw = &fbcon_dummy;
-	break;
-    }
-}
+	disp.var = clgenfb_default;
+	fbgen_set_disp (-1, &fb_info->gen);
+	fbgen_install_cmap (0, &fb_info->gen);
 
-static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, 
-				int dy, int dx, int height, int width)
-{
-    sx     *= fontwidth(p);
-    sy     *= fontheight(p);
-    dx     *= fontwidth(p);
-    dy     *= fontheight(p);
-    width  *= fontwidth(p);
-    height *= fontheight(p);
-
-    fb_info = (struct clgenfb_info*)p->fb_info;
-
-    clgen_BitBLT((unsigned short)sx, (unsigned short)sy,
-		 (unsigned short)dx, (unsigned short)dy,
-		 (unsigned short)width, (unsigned short)height,
-		 fb_info->currentmode.line_length);
-    clgen_WaitBLT();
+	err = register_framebuffer (&fb_info->gen.info);
+	if (err) {
+		printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err);
+		DPRINTK ("EXIT, returning -EINVAL\n");
+		return -EINVAL;
+	}
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
 }
 
-static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, 
-				int sy, int sx, int height, int width)
-{
-    unsigned short col;
-    
-    fb_info = (struct clgenfb_info*)p->fb_info;
-
-    sx     *= fontwidth(p);
-    sy     *= fontheight(p);
-    width  *= fontwidth(p);
-    height *= fontheight(p);
-
-    col = attr_bgcol_ec(p, conp);
-    col &= 0xff;
-
-    clgen_RectFill((unsigned short)sx, (unsigned short)sy,
-		    (unsigned short)width,(unsigned short)height,
-		     col, fb_info->currentmode.line_length);
-    clgen_WaitBLT();
-}
 
 
-/********************************************************************/
-/* clgenfb_init() - master initialization function                  */
-/********************************************************************/
-void __init clgenfb_init(void)
+#if defined(CONFIG_FB_OF)
+int __init clgen_of_init (struct device_node *dp)
 {
-    const struct ConfigDev *cd  = NULL;
-    const struct ConfigDev *cd2 = NULL;
-    int err;
-    int btype;
-    int key,key2;
-    unsigned long board_addr,board_size;
-
-    printk(">clgenfb_init()\n");
-    printk(KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n");
-
-    btype = -1;
-
-    if ((key = zorro_find(ZORRO_PROD_HELFRICH_SD64_RAM, 0, 0)))
-    {
-	key2 = zorro_find(ZORRO_PROD_HELFRICH_SD64_REG, 0, 0);
-        btype = BT_SD64;
-        printk(KERN_INFO "clgen: SD64 board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_RAM, 0, 0)))
-    {
-        key2      = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_REG, 0, 0);
-    	btype = BT_PICCOLO;
-    	printk(KERN_INFO "clgen: Piccolo board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 0, 0)))
-    {
-        key2      = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 0, 0);
-	btype = BT_PICASSO;
-    	printk(KERN_INFO "clgen: Picasso II board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 0, 0)))
-    {
-        key2      = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 0, 0);
-        btype = BT_SPECTRUM;
-        printk(KERN_INFO "clgen: Spectrum board detected; ");
-    }
-    else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 0, 0)))
-    {
-        btype = BT_PICASSO4;
-        printk(KERN_INFO "clgen: Picasso 4 board detected; ");
-    }
-    else
-    {
-	printk(KERN_NOTICE "clgen: no supported board found.\n");
-	return;
-    }
-    
-    fb_info = &boards[0]; /* FIXME support multiple boards ...*/
-    
-    fb_info->keyRAM = key;
-    fb_info->keyREG = key2;
-    fb_info->btype  = btype;
-    
-    cd = zorro_get_board(key);
-    board_addr = (unsigned long)cd->cd_BoardAddr;
-    board_size = (unsigned long)cd->cd_BoardSize;
-    printk(" RAM (%lu MB) at $%lx, ", board_size/0x100000, board_addr);
-
-    if (btype == BT_PICASSO4)
-    {
-	printk(" REG at $%lx\n", board_addr + 0x600000);
-
-        /* To be precise, for the P4 this is not the */
-        /* begin of the board, but the begin of RAM. */
-	/* for P4, map in its address space in 2 chunks (### TEST! ) */
-	/* (note the ugly hardcoded 16M number) */
-	fb_info->regs = ioremap(board_addr, 16777216);
-        DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs);
-	fb_info->regs += 0x600000;
-	fb_info->fbregs_phys = board_addr + 0x600000;
-
-	fb_info->fbmem_phys = board_addr + 16777216;
-	fb_info->fbmem = ioremap(fb_info->fbmem_phys, 16777216);
-	DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
-    }
-    else
-    {
-        cd2 = zorro_get_board(key2);
-        printk(" REG at $%lx\n", (unsigned long)cd2->cd_BoardAddr);
-
-	fb_info->fbmem_phys = board_addr;
-        if (board_addr > 0x01000000)
-	    fb_info->fbmem = ioremap(board_addr, board_size);
-	else
-	    fb_info->fbmem = ZTWO_VADDR(board_addr);
-
-        /* set address for REG area of board */
-	fb_info->regs = (unsigned char *)ZTWO_VADDR(cd2->cd_BoardAddr);
-	fb_info->fbregs_phys = (unsigned long) cd2->cd_BoardAddr;
-
-        DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs);
-	DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
-    }
-
-    init_vgachip();
-
-    /* set up a few more things, register framebuffer driver etc */
-    fb_info->gen.parsize         = sizeof(struct clgenfb_par);
-    fb_info->gen.fbhw            = &clgen_hwswitch;
-    strcpy (fb_info->gen.info.modename, clgenfb_name);
-    fb_info->gen.info.node       = -1;
-    fb_info->gen.info.fbops      = &clgenfb_ops;
-    fb_info->gen.info.disp       = &disp;
-    fb_info->gen.info.changevar  = NULL;
-    fb_info->gen.info.switch_con = &fbgen_switch;
-    fb_info->gen.info.updatevar  = &fbgen_update_var;
-    fb_info->gen.info.blank      = &fbgen_blank;
-    fb_info->gen.info.flags	 = FBINFO_FLAG_DEFAULT;
-    
-    /* mark this board as "autoconfigured" */
-    zorro_config_board(key, 0);
-    if (btype != BT_PICASSO4)
-	zorro_config_board(key2, 0);
-
-    /* now that we know the board has been registered n' stuff, we */
-    /* can finally initialize it to a default mode (640x480) */
-    clgenfb_default = clgenfb_predefined[1].var;
-    clgenfb_default.activate = FB_ACTIVATE_NOW;
-    clgenfb_default.yres_virtual = 480*3; /* for fast scrolling (YPAN-Mode) */
-    err = fbgen_do_set_var(&clgenfb_default, 1, &fb_info->gen);
+	int rc;
+	
+	DPRINTK ("ENTER\n");
 
-    if (err)
-	return;
+	rc = clgenfb_init ();
 
-    disp.var = clgenfb_default;
-    fbgen_set_disp(-1, &fb_info->gen);
-    fbgen_install_cmap(0, &fb_info->gen);
-
-    err = register_framebuffer(&fb_info->gen.info);
-    if (err)
-    {
-	printk(KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err);
-	return;
-    }
+	DPRINTK ("EXIT, returning %d\n", rc);
 
-    printk("<clgenfb_init()\n");
-    return;
+	return rc;
 }
+#endif				/* CONFIG_FB_OF */
+
+
 
     /*
-     *  Cleanup
+     *  Cleanup (only needed for module)
      */
-
-void clgenfb_cleanup(struct clgenfb_info *info)
+#ifdef MODULE
+static void clgenfb_cleanup (struct clgenfb_info *info)
 {
-    printk(">clgenfb_cleanup()\n");
+	DPRINTK ("ENTER\n");
 
-    fb_info = info;
+#ifdef CONFIG_ZORRO
+	switch_monitor (info, 0);
 
-    switch_monitor(0);
+	zorro_unconfig_board (info->keyRAM, 0);
+	if (info->btype != BT_PICASSO4)
+		zorro_unconfig_board (info->keyREG, 0);
+#endif				/* CONFIG_ZORRO */
 
-    zorro_unconfig_board(info->keyRAM, 0);
-    if (fb_info->btype != BT_PICASSO4)
-	zorro_unconfig_board(info->keyREG, 0);
+	unregister_framebuffer ((struct fb_info *) info);
+	printk ("Framebuffer unregistered\n");
 
-    unregister_framebuffer(&info->gen.info);
-    printk("Framebuffer unregistered\n");
-    printk("<clgenfb_cleanup()\n");
+	DPRINTK ("EXIT\n");
 }
+#endif
 
 
-/* A strtok which returns empty strings, too */
-static char *strtoke(char *s,const char *ct)
-{
-	char *sbegin, *send;
-	static char *ssave = NULL;
 
-	sbegin  = s ? s : ssave;
-	if (!sbegin)
-		return NULL;
-	if (*sbegin == '\0') {
-		ssave = NULL;
-		return NULL;
+
+#ifndef MODULE
+int __init clgenfb_setup(char *options) {
+	char *this_opt, s[32];
+	int i;
+	
+	DPRINTK ("ENTER\n");
+	
+	if (!options || !*options)
+		return 0;
+	
+	for (this_opt = strtok (options, ","); this_opt != NULL;
+	     this_opt = strtok (NULL, ",")) {
+		if (!*this_opt) continue;
+		
+		DPRINTK("clgenfb_setup: option '%s'\n", this_opt);
+		
+		for (i = 0; i < NUM_TOTAL_MODES; i++) {
+			sprintf (s, "mode:%s", clgenfb_predefined[i].name);
+			if (strcmp (this_opt, s) == 0)
+				clgen_def_mode = i;
+		}
 	}
-	send = strpbrk(sbegin, ct);
-	if (send && *send != '\0')
-		*send++ = '\0';
-	ssave = send;
-	return sbegin;
+	return 0;
 }
+#endif
+
 
-/*****************************************************************/
-/* clgenfb_setup() might be used later for parsing possible      */
-/* arguments to the video= bootstrap parameter. Right now, there */
-/* is nothing I do here.                                         */
-/*****************************************************************/
-void __init clgenfb_setup(char *options, int *ints)
-{
-//    char *this_opt;
 
-//    printk("clgenfb_setup(): options: %s\n", options);	
-}
 
 
     /*
@@ -1668,20 +2733,34 @@
      */
 
 #ifdef MODULE
-int init_module(void)
+MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@pobox.com>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
+
+int init_module (void)
 {
-    printk("init_module()\n");
-    clgenfb_init();
-    return 0;
+#if defined(CONFIG_FB_OF)
+/* Nothing to do, must be called from offb */
+	return 0;
+#else
+	int i;
+	
+	DPRINTK ("ENTER\n");
+	i = clgenfb_init ();
+	DPRINTK ("EXIT\n");
+	return i;
+#endif
 }
 
-void cleanup_module(void)
+void cleanup_module (void)
 {
-    printk("module_cleanup()\n");
-    clgenfb_cleanup(fb_info);
+	DPRINTK ("ENTER\n");
+
+	clgenfb_cleanup (&boards[0]);	/* FIXME: support multiple boards */
+
+	DPRINTK ("EXIT\n");
 }
-#endif /* MODULE */
 
+#endif				/* MODULE */
 
 
 /**********************************************************************/
@@ -1692,241 +2771,174 @@
 /**********************************************************************/
 
 /*** WGen() - write into one of the external/general registers ***/
-void WGen(int regnum, unsigned char val)
+static void WGen (const struct clgenfb_info *fb_info,
+		  int regnum, unsigned char val)
 {
-	unsigned volatile char *reg = fb_info->regs + regnum;
+	unsigned long regofs = 0;
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* Picasso II specific hack */
-/*		if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */
-		if (regnum == M_3C7_W || regnum == M_3C9)
-			reg += 0xfff;
+/*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
+		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
+			regofs = 0xfff;
 	}
 
-	*reg = val;
+	vga_w (fb_info->regs, regofs + regnum, val);
 }
 
 /*** RGen() - read out one of the external/general registers ***/
-unsigned char RGen(int regnum)
+static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum)
 {
-	unsigned volatile char *reg = fb_info->regs + regnum;
+	unsigned long regofs = 0;
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* Picasso II specific hack */
-/*		if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */
-		if (regnum == M_3C7_W || regnum == M_3C9)
-			reg += 0xfff;
+/*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
+		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
+			regofs = 0xfff;
 	}
 
-	return *reg;
-}
-
-/*** WSeq() - write into a register of the sequencer ***/
-void WSeq(unsigned char regnum, unsigned char val)
-{
-	fb_info->regs[SEQRX]   = regnum;
-	fb_info->regs[SEQRX+1] = val;
-}
-
-/*** RSeq() - read out one of the Sequencer registers ***/
-unsigned char RSeq(unsigned char regnum)
-{
-	fb_info->regs[SEQRX] = regnum;
-	return fb_info->regs[SEQRX+1];
-}
-
-/*** WCrt() - write into a register of the CRT controller ***/
-void WCrt(unsigned char regnum, unsigned char val)
-{
-	fb_info->regs[CRTX]   = regnum;
-	fb_info->regs[CRTX+1] = val;
-}
-
-/*** RCrt() - read out one of the CRT controller registers ***/
-unsigned char RCrt(unsigned char regnum)
-{
-	fb_info->regs[CRTX] = regnum;
-	return fb_info->regs[CRTX+1];
-}
-
-/*** WGfx() - write into a register of the Gfx controller ***/
-void WGfx(unsigned char regnum, unsigned char val)
-{
-	fb_info->regs[GRX]   = regnum;
-	fb_info->regs[GRX+1] = val;
-}
-
-/*** RGfx() - read out one of the Gfx controller registers ***/
-unsigned char RGfx(unsigned char regnum)
-{
-	fb_info->regs[GRX] = regnum;
-	return fb_info->regs[GRX+1];
+	return vga_r (fb_info->regs, regofs + regnum);
 }
 
-/*** WAttr() - write into a register of the Attribute controller ***/
-void WAttr(unsigned char regnum, unsigned char val)
+/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
+static void AttrOn (const struct clgenfb_info *fb_info)
 {
-	/* if the next access to the attribute controller is a data write access, */
-	/* simply write back the information that was already there before, so that */
-	/* the next write access after that will be an index write. */
-	if (RCrt(CRT24) & 0x80)
-		/* can't use WAttr() here - we would go into a recursive loop otherwise */
-		fb_info->regs[ARX] = fb_info->regs[ARX+1];
-
-	if (RCrt(CRT24) & 0x80)
-		printk(KERN_WARNING "clgen: *** AttrIdx BAD!***\n");
+	assert (fb_info != NULL);
 
-	/* now, first set index and after that the value - both to the same address (!) */
-	fb_info->regs[ARX] = regnum;
-	fb_info->regs[ARX] = val;
-}
+	DPRINTK ("ENTER\n");
 
-/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
-void AttrOn()
-{
-	if (RCrt(CRT24) & 0x80)
+	if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) {
 		/* if we're just in "write value" mode, write back the */
 		/* same value as before to not modify anything */
-		fb_info->regs[ARX] = fb_info->regs[ARX+1];
-
+		vga_w (fb_info->regs, VGA_ATT_IW,
+		       vga_r (fb_info->regs, VGA_ATT_R));
+	}
 	/* turn on video bit */
-/*	fb_info->regs[ARX] = 0x20; */
-	fb_info->regs[ARX] = 0x33;
+/*      vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */
+	vga_w (fb_info->regs, VGA_ATT_IW, 0x33);
 
 	/* dummy write on Reg0 to be on "write index" mode next time */
-	fb_info->regs[ARX] = 0x00;
-}
-
-/*** RAttr() - read out a register of the Attribute controller ***/
-unsigned char RAttr(unsigned char regnum)
-{
-	/* (explanation see above in WAttr() ) */
-	if (RCrt(CRT24) & 0x80)
-		fb_info->regs[ARX] = fb_info->regs[ARX+1];
+	vga_w (fb_info->regs, VGA_ATT_IW, 0x00);
 
-	fb_info->regs[ARX] = regnum;
-	return fb_info->regs[ARX+1];
+	DPRINTK ("EXIT\n");
 }
 
-
 /*** WHDR() - write into the Hidden DAC register ***/
 /* as the HDR is the only extension register that requires special treatment 
  * (the other extension registers are accessible just like the "ordinary"
  * registers of their functional group) here is a specialized routine for 
  * accessing the HDR
  */
-void WHDR(unsigned char val)
+static void WHDR (const struct clgenfb_info *fb_info, unsigned char val)
 {
 	unsigned char dummy;
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* Klaus' hint for correct access to HDR on some boards */
 		/* first write 0 to pixel mask (3c6) */
-		WGen(M_3C6, 0x00); udelay(200);
+		WGen (fb_info, VGA_PEL_MSK, 0x00);
+		udelay (200);
 		/* next read dummy from pixel address (3c8) */
-		dummy = RGen(M_3C8); udelay(200);
+		dummy = RGen (fb_info, VGA_PEL_IW);
+		udelay (200);
 	}
-
 	/* now do the usual stuff to access the HDR */
 
-	dummy = RGen(M_3C6); udelay(200);
-	dummy = RGen(M_3C6); udelay(200);
-	dummy = RGen(M_3C6); udelay(200);
-	dummy = RGen(M_3C6); udelay(200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
+	dummy = RGen (fb_info, VGA_PEL_MSK);
+	udelay (200);
 
-	WGen(M_3C6, val); udelay(200);
+	WGen (fb_info, VGA_PEL_MSK, val);
+	udelay (200);
 
-	if(fb_info->btype == BT_PICASSO)
-	{
+	if (fb_info->btype == BT_PICASSO) {
 		/* now first reset HDR access counter */
-		dummy = RGen(M_3C8); udelay(200);
+		dummy = RGen (fb_info, VGA_PEL_IW);
+		udelay (200);
 
 		/* and at the end, restore the mask value */
 		/* ## is this mask always 0xff? */
-		WGen(M_3C6, 0xff); udelay(200);
+		WGen (fb_info, VGA_PEL_MSK, 0xff);
+		udelay (200);
 	}
 }
 
-/*** RHDR() - read out the Hidden DAC register ***/
-/* I hope this does not break on the GD5428 - cannot test it. */
-/* (Is there any board for the Amiga that uses the 5428 ?) */
-unsigned char RHDR()
-{
-	unsigned char dummy;
-
-	dummy = RGen(M_3C6);
-	dummy = RGen(M_3C6);
-	dummy = RGen(M_3C6);
-	dummy = RGen(M_3C6);
-
-	return RGen(M_3C6);
-}
 
 
 /*** WSFR() - write to the "special function register" (SFR) ***/
-void WSFR(unsigned char val)
+static void WSFR (struct clgenfb_info *fb_info, unsigned char val)
 {
-	fb_info->SFR          = val;
-	fb_info->regs[0x8000] = val;
+#ifdef CONFIG_ZORRO
+	assert (fb_info->regs != NULL);
+	fb_info->SFR = val;
+	writeb (val, fb_info->regs + 0x8000);
+#endif
 }
 
 /* The Picasso has a second register for switching the monitor bit */
-void WSFR2(unsigned char val)
+static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val)
 {
+#ifdef CONFIG_ZORRO
 	/* writing an arbitrary value to this one causes the monitor switcher */
 	/* to flip to Amiga display */
-	fb_info->SFR          = val;
-	fb_info->regs[0x9000] = val;
+	assert (fb_info->regs != NULL);
+	fb_info->SFR = val;
+	writeb (val, fb_info->regs + 0x9000);
+#endif
 }
 
+
 /*** WClut - set CLUT entry (range: 0..63) ***/
-void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue)
+static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
+	    unsigned char green, unsigned char blue)
 {
-	unsigned int data = 0x3c9;
+	unsigned int data = VGA_PEL_D;
 
 	/* address write mode register is not translated.. */
-	fb_info->regs[0x3c8] = regnum;
+	vga_w (fb_info->regs, VGA_PEL_IW, regnum);
 
-	if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4)
-	{
+	if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
+	    fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
 		/* but DAC data register IS, at least for Picasso II */
-		if(fb_info->btype == BT_PICASSO)
+		if (fb_info->btype == BT_PICASSO)
 			data += 0xfff;
-		fb_info->regs[data] = red;
-		fb_info->regs[data] = green;
-		fb_info->regs[data] = blue;
-	}
-	else
-	{
-		fb_info->regs[data] = blue;
-		fb_info->regs[data] = green;
-		fb_info->regs[data] = red;
+		vga_w (fb_info->regs, data, red);
+		vga_w (fb_info->regs, data, green);
+		vga_w (fb_info->regs, data, blue);
+	} else {
+		vga_w (fb_info->regs, data, blue);
+		vga_w (fb_info->regs, data, green);
+		vga_w (fb_info->regs, data, red);
 	}
 }
 
+
+
 /*** RClut - read CLUT entry (range 0..63) ***/
-void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue)
+static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
+	    unsigned char *green, unsigned char *blue)
 {
-	unsigned int data = 0x3c9;
+	unsigned int data = VGA_PEL_D;
 
-	fb_info->regs[0x3c7] = regnum;
+	vga_w (fb_info->regs, VGA_PEL_IR, regnum);
 
-	if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4)
-	{
-		if(fb_info->btype == BT_PICASSO)
+	if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
+	    fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
+		if (fb_info->btype == BT_PICASSO)
 			data += 0xfff;
-		*red   = fb_info->regs[data];
-		*green = fb_info->regs[data];
-		*blue  = fb_info->regs[data];
-	}
-	else
-	{
-		*blue  = fb_info->regs[data];
-		*green = fb_info->regs[data];
-		*red   = fb_info->regs[data];
+		*red = vga_r (fb_info->regs, data);
+		*green = vga_r (fb_info->regs, data);
+		*blue = vga_r (fb_info->regs, data);
+	} else {
+		*blue = vga_r (fb_info->regs, data);
+		*green = vga_r (fb_info->regs, data);
+		*red = vga_r (fb_info->regs, data);
 	}
 }
 
@@ -1937,11 +2949,12 @@
 	Wait for the BitBLT engine to complete a possible earlier job
 *********************************************************************/
 
-void clgen_WaitBLT()
+/* FIXME: use interrupts instead */
+extern inline void clgen_WaitBLT (caddr_t regbase)
 {
 	/* now busy-wait until we're done */
-	while (RGfx(GR31) & 0x08)
-		;
+	while (vga_rgfx (regbase, CL_GR31) & 0x08)
+		/* do nothing */ ;
 }
 
 /*******************************************************************
@@ -1950,90 +2963,87 @@
 	perform accelerated "scrolling"
 ********************************************************************/
 
-void clgen_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
-		u_short width, u_short height, u_short line_length)
+static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty,
+		   u_short width, u_short height, u_short line_length)
 {
 	u_short nwidth, nheight;
 	u_long nsrc, ndest;
 	u_char bltmode;
 
+	DPRINTK ("ENTER\n");
+
 	nwidth = width - 1;
 	nheight = height - 1;
 
 	bltmode = 0x00;
 	/* if source adr < dest addr, do the Blt backwards */
-	if (cury <= desty)
-	{
-		if (cury == desty)
-		{
+	if (cury <= desty) {
+		if (cury == desty) {
 			/* if src and dest are on the same line, check x */
 			if (curx < destx)
 				bltmode |= 0x01;
-		}
-		else
+		} else
 			bltmode |= 0x01;
 	}
-
-	if (!bltmode)
-	{
+	if (!bltmode) {
 		/* standard case: forward blitting */
 		nsrc = (cury * line_length) + curx;
 		ndest = (desty * line_length) + destx;
-	}
-	else
-	{
+	} else {
 		/* this means start addresses are at the end, counting backwards */
 		nsrc = cury * line_length + curx + nheight * line_length + nwidth;
 		ndest = desty * line_length + destx + nheight * line_length + nwidth;
 	}
 
-//	clgen_WaitBLT(); /* ### NOT OK for multiple boards! */
+        clgen_WaitBLT(regbase);
 
 	/*
-		run-down of registers to be programmed:
-		destination pitch
-		source pitch
-		BLT width/height
-		source start
-		destination start
-		BLT mode
-		BLT ROP
-		GR0 / GR1: "fill color"
-		start/stop
-	*/
+	   run-down of registers to be programmed:
+	   destination pitch
+	   source pitch
+	   BLT width/height
+	   source start
+	   destination start
+	   BLT mode
+	   BLT ROP
+	   VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
+	   start/stop
+	 */
 
 	/* pitch: set to line_length */
-	WGfx(GR24, line_length & 0xff);	/* dest pitch low */
-	WGfx(GR25, (line_length >> 8));	/* dest pitch hi */
-	WGfx(GR26, line_length & 0xff);	/* source pitch low */
-	WGfx(GR27, (line_length >> 8));	/* source pitch hi */
+	vga_wgfx (regbase, CL_GR24, line_length & 0xff);	/* dest pitch low */
+	vga_wgfx (regbase, CL_GR25, (line_length >> 8));	/* dest pitch hi */
+	vga_wgfx (regbase, CL_GR26, line_length & 0xff);	/* source pitch low */
+	vga_wgfx (regbase, CL_GR27, (line_length >> 8));	/* source pitch hi */
 
 	/* BLT width: actual number of pixels - 1 */
-	WGfx(GR20, nwidth & 0xff);	/* BLT width low */
-	WGfx(GR21, (nwidth >> 8));	/* BLT width hi */
+	vga_wgfx (regbase, CL_GR20, nwidth & 0xff);	/* BLT width low */
+	vga_wgfx (regbase, CL_GR21, (nwidth >> 8));	/* BLT width hi */
 
 	/* BLT height: actual number of lines -1 */
-	WGfx(GR22, nheight & 0xff);	/* BLT height low */
-	WGfx(GR23, (nheight >> 8));	/* BLT width hi */
+	vga_wgfx (regbase, CL_GR22, nheight & 0xff);	/* BLT height low */
+	vga_wgfx (regbase, CL_GR23, (nheight >> 8));	/* BLT width hi */
 
 	/* BLT destination */
-	WGfx(GR28, (u_char)(ndest & 0xff));	/* BLT dest low */
-	WGfx(GR29, (u_char)(ndest >> 8));	/* BLT dest mid */
-	WGfx(GR2A, (u_char)(ndest >> 16));	/* BLT dest hi */
+	vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff));	/* BLT dest low */
+	vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8));	/* BLT dest mid */
+	vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16));	/* BLT dest hi */
 
 	/* BLT source */
-	WGfx(GR2C, (u_char)(nsrc & 0xff));	/* BLT src low */
-	WGfx(GR2D, (u_char)(nsrc >> 8));	/* BLT src mid */
-	WGfx(GR2E, (u_char)(nsrc >> 16));	/* BLT src hi */
+	vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff));	/* BLT src low */
+	vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8));		/* BLT src mid */
+	vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16));	/* BLT src hi */
 
 	/* BLT mode */
-	WGfx(GR30, bltmode);	/* BLT mode */
+	vga_wgfx (regbase, CL_GR30, bltmode);	/* BLT mode */
 
 	/* BLT ROP: SrcCopy */
-	WGfx(GR32, 0x0d);	/* BLT ROP */
+	vga_wgfx (regbase, CL_GR32, 0x0d);		/* BLT ROP */
 
 	/* and finally: GO! */
-	WGfx(GR31, 0x02);	/* BLT Start/status */
+	vga_wgfx (regbase, CL_GR31, 0x02);		/* BLT Start/status */
+
+	DPRINTK ("EXIT\n");
 }
 
 /*******************************************************************
@@ -2042,56 +3052,78 @@
 	perform accelerated rectangle fill
 ********************************************************************/
 
-void clgen_RectFill (u_short x, u_short y, u_short width, u_short height,
-                     u_char color, u_short line_length)
+static void clgen_RectFill (struct clgenfb_info *fb_info,
+		     u_short x, u_short y, u_short width, u_short height,
+		     u_char color, u_short line_length)
 {
 	u_short nwidth, nheight;
 	u_long ndest;
+	u_char op;
+
+	DPRINTK ("ENTER\n");
 
 	nwidth = width - 1;
 	nheight = height - 1;
 
 	ndest = (y * line_length) + x;
 
-//	clgen_WaitBLT(); /* ### NOT OK for multiple boards! */
+        clgen_WaitBLT(fb_info->regs);
 
 	/* pitch: set to line_length */
-	WGfx(GR24, line_length & 0xff);	/* dest pitch low */
-	WGfx(GR25, (line_length >> 8));	/* dest pitch hi */
-	WGfx(GR26, line_length & 0xff);	/* source pitch low */
-	WGfx(GR27, (line_length >> 8));	/* source pitch hi */
+	vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff);	/* dest pitch low */
+	vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8));	/* dest pitch hi */
+	vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff);	/* source pitch low */
+	vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8));	/* source pitch hi */
 
 	/* BLT width: actual number of pixels - 1 */
-	WGfx(GR20, nwidth & 0xff);	/* BLT width low */
-	WGfx(GR21, (nwidth >> 8));	/* BLT width hi */
+	vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff);	/* BLT width low */
+	vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8));	/* BLT width hi */
 
 	/* BLT height: actual number of lines -1 */
-	WGfx(GR22, nheight & 0xff);	/* BLT height low */
-	WGfx(GR23, (nheight >> 8));	/* BLT width hi */
+	vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff);		/* BLT height low */
+	vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8));		/* BLT width hi */
 
 	/* BLT destination */
-	WGfx(GR28, (u_char)(ndest & 0xff));	/* BLT dest low */
-	WGfx(GR29, (u_char)(ndest >> 8));	/* BLT dest mid */
-	WGfx(GR2A, (u_char)(ndest >> 16));	/* BLT dest hi */
+	vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff));	/* BLT dest low */
+	vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8));	/* BLT dest mid */
+	vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16));		/* BLT dest hi */
 
 	/* BLT source: set to 0 (is a dummy here anyway) */
-	WGfx(GR2C, 0x00);	/* BLT src low */
-	WGfx(GR2D, 0x00);	/* BLT src mid */
-	WGfx(GR2E, 0x00);	/* BLT src hi */
+	vga_wgfx (fb_info->regs, CL_GR2C, 0x00);	/* BLT src low */
+	vga_wgfx (fb_info->regs, CL_GR2D, 0x00);	/* BLT src mid */
+	vga_wgfx (fb_info->regs, CL_GR2E, 0x00);	/* BLT src hi */
 
 	/* This is a ColorExpand Blt, using the */
 	/* same color for foreground and background */
-	WGfx(GR0, color);	/* foreground color */
-	WGfx(GR1, color);	/* background color */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color);	/* foreground color */
+	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color);	/* background color */
 
+	op = 0xc0;
+	if (fb_info->currentmode.var.bits_per_pixel == 16) {
+		vga_wgfx (fb_info->regs, CL_GR10, color);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR11, color);	/* background color */
+		op = 0x50;
+		op = 0xd0;
+	} else if (fb_info->currentmode.var.bits_per_pixel == 32) {
+		vga_wgfx (fb_info->regs, CL_GR10, color);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR11, color);	/* background color */
+		vga_wgfx (fb_info->regs, CL_GR12, color);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR13, color);	/* background color */
+		vga_wgfx (fb_info->regs, CL_GR14, 0);	/* foreground color */
+		vga_wgfx (fb_info->regs, CL_GR15, 0);	/* background color */
+		op = 0x50;
+		op = 0xf0;
+	}
 	/* BLT mode: color expand, Enable 8x8 copy (faster?) */
-	WGfx(GR30, 0xc0);	/* BLT mode */
+	vga_wgfx (fb_info->regs, CL_GR30, op);	/* BLT mode */
 
 	/* BLT ROP: SrcCopy */
-	WGfx(GR32, 0x0d);	/* BLT ROP */
+	vga_wgfx (fb_info->regs, CL_GR32, 0x0d);	/* BLT ROP */
 
 	/* and finally: GO! */
-	WGfx(GR31, 0x02);	/* BLT Start/status */
+	vga_wgfx (fb_info->regs, CL_GR31, 0x02);	/* BLT Start/status */
+
+	DPRINTK ("EXIT\n");
 }
 
 /**************************************************************************
@@ -2099,70 +3131,283 @@
  * desired pixel clock
  **************************************************************************/
 #define abs(x) ((x)<0 ? -(x) : (x))
-static void bestclock(long freq, long *best, long *nom,
-		      long *den, long *div,  long maxfreq)
+static void bestclock (long freq, long *best, long *nom,
+		       long *den, long *div, long maxfreq)
 {
-    long n, h, d, f;
+	long n, h, d, f;
 
-    *nom = 0;
-    *den = 0;
-    *div = 0;
-
-    if (freq < 8000)
-	freq = 8000;
-
-    if (freq > maxfreq)
-	freq = maxfreq;
-
-    *best = 0;
-    f = freq * 10;
-
-    for(n = 32; n < 128; n++)
-    {
-        d = (143181 * n) / f;
-	if ( (d >= 7) && (d <= 63) )
-        {
-            if (d > 31)
-            	d = (d / 2) * 2;
-            h = (14318 * n) / d;
-            if ( abs(h - freq) < abs(*best - freq) )
-            {
-                *best = h;
-		*nom = n;
-		if (d < 32)
-		{
-                    *den = d;
-                    *div = 0;
+	assert (best != NULL);
+	assert (nom != NULL);
+	assert (den != NULL);
+	assert (div != NULL);
+	assert (maxfreq > 0);
+
+	*nom = 0;
+	*den = 0;
+	*div = 0;
+
+	DPRINTK ("ENTER\n");
+
+	if (freq < 8000)
+		freq = 8000;
+
+	if (freq > maxfreq)
+		freq = maxfreq;
+
+	*best = 0;
+	f = freq * 10;
+
+	for (n = 32; n < 128; n++) {
+		d = (143181 * n) / f;
+		if ((d >= 7) && (d <= 63)) {
+			if (d > 31)
+				d = (d / 2) * 2;
+			h = (14318 * n) / d;
+			if (abs (h - freq) < abs (*best - freq)) {
+				*best = h;
+				*nom = n;
+				if (d < 32) {
+					*den = d;
+					*div = 0;
+				} else {
+					*den = d / 2;
+					*div = 1;
+				}
+			}
 		}
-		else
-		{
-                    *den = d / 2;
-		    *div = 1;
+		d = ((143181 * n) + f - 1) / f;
+		if ((d >= 7) && (d <= 63)) {
+			if (d > 31)
+				d = (d / 2) * 2;
+			h = (14318 * n) / d;
+			if (abs (h - freq) < abs (*best - freq)) {
+				*best = h;
+				*nom = n;
+				if (d < 32) {
+					*den = d;
+					*div = 0;
+				} else {
+					*den = d / 2;
+					*div = 1;
+				}
+			}
 		}
-            }
-        }
-        d = ( (143181 * n)+f-1) / f;
-        if ( (d >= 7) && (d <= 63) )
-	{
-	    if (d > 31)
-    		d = (d / 2) * 2;
-	    h = (14318 * n) / d;
-	    if ( abs(h - freq) < abs(*best - freq) )
-	    {
-    	        *best = h;
-    	        *nom = n;
-            	if (d < 32)
-		{
-    	            *den = d;
-        	    *div = 0;
-	        }
-    	        else
-    	        {
-    	            *den = d / 2;
-	            *div = 1;
-	        }
-	    }
 	}
-    }
+
+	DPRINTK ("Best possible values for given frequency:\n");
+	DPRINTK ("        best: %ld kHz  nom: %ld  den: %ld  div: %ld\n",
+		 freq, *nom, *den, *div);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+
+
+
+
+/* -------------------------------------------------------------------------
+ *
+ * debugging functions
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef CLGEN_DEBUG
+
+/**
+ * clgen_dbg_print_byte
+ * @name: name associated with byte value to be displayed
+ * @val: byte value to be displayed
+ *
+ * DESCRIPTION:
+ * Display an indented string, along with a hexidecimal byte value, and
+ * its decoded bits.  Bits 7 through 0 are listed in left-to-right
+ * order.
+ */
+
+static
+void clgen_dbg_print_byte (const char *name, unsigned char val)
+{
+	DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
+		 name, val,
+		 val & 0x80 ? '1' : '0',
+		 val & 0x40 ? '1' : '0',
+		 val & 0x20 ? '1' : '0',
+		 val & 0x10 ? '1' : '0',
+		 val & 0x08 ? '1' : '0',
+		 val & 0x04 ? '1' : '0',
+		 val & 0x02 ? '1' : '0',
+		 val & 0x01 ? '1' : '0');
+}
+
+
+
+/**
+ * clgen_dbg_print_regs
+ * @base: If using newmmio, the newmmio base address, otherwise %NULL
+ * @reg_class: type of registers to read: %CRT, or %SEQ
+ *
+ * DESCRIPTION:
+ * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
+ * old-style I/O ports are queried for information, otherwise MMIO is
+ * used at the given @base address to query the information.
+ */
+
+static
+void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...)
+{
+	va_list list;
+	unsigned char val = 0;
+	unsigned reg;
+	char *name;
+
+	va_start (list, reg_class);
+
+	name = va_arg (list, char *);
+	while (name != NULL) {
+		reg = va_arg (list, int);
+
+		switch (reg_class) {
+		case CRT:
+			val = vga_rcrt (regbase, (unsigned char) reg);
+			break;
+		case SEQ:
+			val = vga_rseq (regbase, (unsigned char) reg);
+			break;
+		default:
+			/* should never occur */
+			assert (0);
+			break;
+		}
+
+		clgen_dbg_print_byte (name, val);
+
+		name = va_arg (list, char *);
+	}
+
+	va_end (list);
+}
+
+
+
+
+
+/**
+ * clgen_dump
+ * @clgeninfo:
+ *
+ * DESCRIPTION:
+ */
+ 
+static
+void clgen_dump (void)
+{
+	clgen_dbg_reg_dump (NULL);
+}
+
+
+
+/**
+ * clgen_dbg_reg_dump
+ * @base: If using newmmio, the newmmio base address, otherwise %NULL
+ *
+ * DESCRIPTION:
+ * Dumps a list of interesting VGA and CLGEN registers.  If @base is %NULL,
+ * old-style I/O ports are queried for information, otherwise MMIO is
+ * used at the given @base address to query the information.
+ */
+
+static
+void clgen_dbg_reg_dump (caddr_t regbase)
+{
+	DPRINTK ("CLGEN VGA CRTC register dump:\n");
+
+	clgen_dbg_print_regs (regbase, CRT,
+			   "CR00", 0x00,
+			   "CR01", 0x01,
+			   "CR02", 0x02,
+			   "CR03", 0x03,
+			   "CR04", 0x04,
+			   "CR05", 0x05,
+			   "CR06", 0x06,
+			   "CR07", 0x07,
+			   "CR08", 0x08,
+			   "CR09", 0x09,
+			   "CR0A", 0x0A,
+			   "CR0B", 0x0B,
+			   "CR0C", 0x0C,
+			   "CR0D", 0x0D,
+			   "CR0E", 0x0E,
+			   "CR0F", 0x0F,
+			   "CR10", 0x10,
+			   "CR11", 0x11,
+			   "CR12", 0x12,
+			   "CR13", 0x13,
+			   "CR14", 0x14,
+			   "CR15", 0x15,
+			   "CR16", 0x16,
+			   "CR17", 0x17,
+			   "CR18", 0x18,
+			   "CR22", 0x22,
+			   "CR24", 0x24,
+			   "CR26", 0x26,
+			   "CR2D", 0x2D,
+			   "CR2E", 0x2E,
+			   "CR2F", 0x2F,
+			   "CR30", 0x30,
+			   "CR31", 0x31,
+			   "CR32", 0x32,
+			   "CR33", 0x33,
+			   "CR34", 0x34,
+			   "CR35", 0x35,
+			   "CR36", 0x36,
+			   "CR37", 0x37,
+			   "CR38", 0x38,
+			   "CR39", 0x39,
+			   "CR3A", 0x3A,
+			   "CR3B", 0x3B,
+			   "CR3C", 0x3C,
+			   "CR3D", 0x3D,
+			   "CR3E", 0x3E,
+			   "CR3F", 0x3F,
+			   NULL);
+
+	DPRINTK ("\n");
+
+	DPRINTK ("CLGEN VGA SEQ register dump:\n");
+
+	clgen_dbg_print_regs (regbase, SEQ,
+			   "SR00", 0x00,
+			   "SR01", 0x01,
+			   "SR02", 0x02,
+			   "SR03", 0x03,
+			   "SR04", 0x04,
+			   "SR08", 0x08,
+			   "SR09", 0x09,
+			   "SR0A", 0x0A,
+			   "SR0B", 0x0B,
+			   "SR0D", 0x0D,
+			   "SR10", 0x10,
+			   "SR11", 0x11,
+			   "SR12", 0x12,
+			   "SR13", 0x13,
+			   "SR14", 0x14,
+			   "SR15", 0x15,
+			   "SR16", 0x16,
+			   "SR17", 0x17,
+			   "SR18", 0x18,
+			   "SR19", 0x19,
+			   "SR1A", 0x1A,
+			   "SR1B", 0x1B,
+			   "SR1C", 0x1C,
+			   "SR1D", 0x1D,
+			   "SR1E", 0x1E,
+			   "SR1F", 0x1F,
+			   NULL);
+
+	DPRINTK ("\n");
 }
 
+
+#endif				/* CLGEN_DEBUG */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)