diff -ruP linux-2.4.20/drivers/video/Config.in linux-2.4.20.mw/drivers/video/Config.in
--- linux-2.4.20/drivers/video/Config.in	Fri Nov 29 00:53:15 2002
+++ linux-2.4.20.mw/drivers/video/Config.in	Sat May  3 15:02:10 2003
@@ -188,15 +188,16 @@
 	 bool '    Leo (ZX) support' CONFIG_FB_LEO
       fi
    fi
-   if [ "$CONFIG_SPARC32" = "y" ]; then
+   if [ "$ARCH" = "sparc" ]; then
       if [ "$CONFIG_PCI" != "n" ]; then
 	 bool '  PCI framebuffers' CONFIG_FB_PCI
 	 if [ "$CONFIG_FB_PCI" != "n" ]; then
 	    bool '    IGA 168x display support' CONFIG_FB_IGA
+	    tristate '    IGS 168x display support' CONFIG_FB_IGS
 	 fi
       fi
    fi
-   if [ "$CONFIG_SPARC64" = "y" ]; then
+   if [ "$ARCH" = "sparc64" ]; then
       if [ "$CONFIG_PCI" != "n" ]; then
 	 bool '  PCI framebuffers' CONFIG_FB_PCI
 	 if [ "$CONFIG_FB_PCI" != "n" ]; then
diff -ruP linux-2.4.20/drivers/video/Makefile linux-2.4.20.mw/drivers/video/Makefile
--- linux-2.4.20/drivers/video/Makefile	Fri Nov 29 00:53:15 2002
+++ linux-2.4.20.mw/drivers/video/Makefile	Sat May  3 15:01:53 2003
@@ -51,6 +51,7 @@
 obj-$(CONFIG_FB_RADEON)		  += radeonfb.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o
 obj-$(CONFIG_FB_IGA)              += igafb.o
+obj-$(CONFIG_FB_IGS)              += igsfb.o fbgen.o
 obj-$(CONFIG_FB_CONTROL)          += controlfb.o
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
 obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
diff -ruP linux-2.4.20/drivers/video/fbmem.c linux-2.4.20.mw/drivers/video/fbmem.c
--- linux-2.4.20/drivers/video/fbmem.c	Fri Nov 29 00:53:15 2002
+++ linux-2.4.20.mw/drivers/video/fbmem.c	Sat May  3 15:01:58 2003
@@ -564,7 +564,7 @@
 	struct fb_info *info = registered_fb[fbidx];
 	struct fb_ops *fb = info->fbops;
 	unsigned long off;
-#if !defined(__sparc__) || defined(__sparc_v9__)
+#if !defined(__sparc__) || defined(__sparc_v9__) || defined(CONFIG_PCI)
 	struct fb_fix_screeninfo fix;
 	struct fb_var_screeninfo var;
 	unsigned long start;
@@ -586,12 +586,12 @@
 		return res;
 	}
 
-#if defined(__sparc__) && !defined(__sparc_v9__)
+#if defined(__sparc__) && !defined(__sparc_v9__) && !defined(CONFIG_PCI)
 	/* Should never get here, all fb drivers should have their own
 	   mmap routines */
 	return -EINVAL;
 #else
-	/* !sparc32... */
+	/* !sparc32... Only Javastation */
 
 	lock_kernel();
 	fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
@@ -618,7 +618,7 @@
 	vma->vm_pgoff = off >> PAGE_SHIFT;
 	/* This is an IO map - tell maydump to skip this VMA */
 	vma->vm_flags |= VM_IO;
-#if defined(__sparc_v9__)
+#if defined(__sparc_v9__) || defined(__sparc__) && defined(CONFIG_PCI)
 	vma->vm_flags |= (VM_SHM | VM_LOCKED);
 	if (io_remap_page_range(vma->vm_start, off,
 				vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
diff -ruP linux-2.4.20/drivers/video/igsfb.c linux-2.4.20.mw/drivers/video/igsfb.c
--- linux-2.4.20/drivers/video/igsfb.c	Thu Jan  1 01:00:00 1970
+++ linux-2.4.20.mw/drivers/video/igsfb.c	Sat May  3 15:02:09 2003
@@ -0,0 +1,1433 @@
+/*
+ * linux/drivers/video/igsfb.c -- Framebuffer for IGA 1682 
+ *
+ * Based on skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * 18 Nov 2002  - Jasper van der Neut <jasper@dnd.utwente.nl>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/nvram.h>
+#include <linux/kd.h>
+#include <linux/vt_kern.h>
+
+#include <asm/io.h>
+
+#ifdef __sparc__
+#include <asm/pbm.h>
+#include <asm/pcic.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#include "igsfb.h"
+
+static struct igsfb_info fb_info;
+static struct igsfb_par current_par;
+static int current_par_valid = 0;
+static struct display disp;
+static struct fb_ops igsfb_ops;
+
+static struct fb_var_screeninfo default_var;
+
+static int opencount = 0;
+
+static int currcon = 0;
+static int inverse = 0;
+
+int igsfb_init(void);
+int igsfb_setup(char *);
+
+static char igsfb_name[16] = "IGS 1682";
+static char fontname[40] __initdata = "SUN8x16";
+
+
+struct fb_var_screeninfo default_var_1024x768 __initdata = {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	1024, 768, 1024, 768, 0, 0, 8, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+
+
+static const u_char crtc_idx[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
+};
+
+
+/*
+struct fbgen_hwswitch {
+//    void (*detect)(void);
+//    int (*encode_fix)(struct fb_fix_screeninfo *fix, const void *par,
+		      struct fb_info_gen *info);
+//    int (*decode_var)(const struct fb_var_screeninfo *var, void *par,
+		      struct fb_info_gen *info);
+ //   int (*encode_var)(struct fb_var_screeninfo *var, const void *par,
+		      struct fb_info_gen *info);
+  //  void (*get_par)(void *par, struct fb_info_gen *info);
+    void (*set_par)(const void *par, struct fb_info_gen *info);
+    int (*getcolreg)(unsigned regno, unsigned *red, unsigned *green,
+		     unsigned *blue, unsigned *transp, struct fb_info *info);
+    int (*setcolreg)(unsigned regno, unsigned red, unsigned green,
+		     unsigned blue, unsigned transp, struct fb_info *info);
+//    int (*pan_display)(const struct fb_var_screeninfo *var,
+		       struct fb_info_gen *info);
+    int (*blank)(int blank_mode, struct fb_info_gen *info);
+    void (*set_disp)(const void *par, struct display *disp,
+		     struct fb_info_gen *info);
+};
+*/
+
+static void igsfb_detect(void);
+static int igsfb_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
+							struct fb_info_gen *info);
+static int igsfb_decode_var(const struct fb_var_screeninfo *var, void *par,
+							struct fb_info_gen *info);
+static int igsfb_encode_var(struct fb_var_screeninfo *var, const void *par,
+							struct fb_info_gen *info);
+static void igsfb_get_par(void *par, struct fb_info_gen *info);
+static int igsfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+						   unsigned *blue, unsigned *transp, struct fb_info *info);
+
+/* Round unsigned int val up to multiple of num */
+
+#define roundup(val,num)	((val + num - 1) & ~(num - 1))
+
+/* Memory-mapped I/O functions for Sparc PCI */
+
+#define pci_inb(info, reg)        readb(info->io_base + (reg))
+#define pci_outb(info, val, reg)  writeb(val, info->io_base + (reg))
+
+static inline unsigned int igsfb_inb(struct igsfb_info *info, unsigned int reg,
+									 unsigned int idx)
+{
+	pci_outb(info, idx, reg);
+	return pci_inb(info, reg + 1);
+}
+
+static inline void igsfb_outb(struct igsfb_info *info, unsigned int reg, unsigned int idx,
+							  unsigned char val)
+{
+	pci_outb(info, idx, reg);
+	pci_outb(info, val, reg + 1);
+}
+
+/* ------------------- chipset specific functions -------------------------- */
+
+#if 0
+struct fb_var_screeninfo var;	/* variable infos. yoffset and vmode */
+									/* are updated by fbcon.c */
+struct fb_cmap cmap;			/* colormap */
+char *screen_base;				/* pointer to top of virtual screen */
+									/* (virtual address) */
+int visual;
+int type;						/* see FB_TYPE_* */
+int type_aux;					/* Interleave for interleaved Planes */
+u_short ypanstep;				/* zero if no hardware ypan */
+u_short ywrapstep;				/* zero if no hardware ywrap */
+u_long line_length;				/* length of a line in bytes */
+u_short can_soft_blank;			/* zero if no hardware blanking */
+u_short inverse;				/* != 0 text black on white as default */
+struct display_switch *dispsw;	/* low level operations */
+void *dispsw_data;				/* optional dispsw helper data */
+#endif
+
+static void debug_display(struct display *disp)
+{
+
+	printk("base: %lx, linelength %lu\n", (long unsigned int) disp->screen_base, disp->line_length);
+	printk("var.xres: %d\n", disp->var.xres);
+}
+
+
+static void debug_colmode(void)
+{
+	unsigned int f1, f2, f3, mode;
+	struct igsfb_info *igsinfo = &fb_info;
+
+	f3 = igsfb_inb(igsinfo, IGS_PORT_GRFX, IGS_FETCH1);
+	f1 = ((f3 & 0x30) << 4) + igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_OFFSET);
+	f2 = ((f3 & 0x03) << 8) + igsfb_inb(igsinfo, IGS_PORT_GRFX, IGS_FETCH0);
+
+	mode = igsfb_inb(igsinfo, IGS_PORT_GRFX, IGS_SEQ_MISC);
+
+	printk("debug_colmode: [linelen = %x] (%x, %x, %x, %x)\n", f1 << 8, f1, f2, f3, mode);
+
+}
+
+static void debug_par(struct igsfb_par *par)
+{
+#if 0
+	u16 width;					/* Visible width */
+	u16 htotal;					/* Total width */
+	u16 hbstart;				/* Start blank */
+	u16 hbend;					/* End blank */
+	u16 hrstart;				/* Start sync */
+	u16 hrend;					/* End sync */
+
+	u16 height;					/* Visible height */
+	u16 vtotal;					/* Total height */
+	u16 vbstart;				/* Start blank */
+	u16 vbend;					/* End blank */
+	u16 vrstart;				/* Start sync */
+	u16 vrend;					/* End sync */
+
+	u16 linelen;				/* Length of scanline in bytes (width x bpp) */
+
+	u32 vclock_mult;
+	u32 vclock_div;
+	u32 mclock_mult;
+#endif
+
+	printk(KERN_INFO "horizontal: %d (%d) %d %d (%d) %d\n", par->width, par->hbstart,
+		   par->hrstart, par->hrend, par->hbend, par->htotal);
+	printk(KERN_INFO "vertical: %d (%d) %d %d (%d) %d\n", par->height, par->vbstart,
+		   par->vrstart, par->vrend, par->vbend, par->vtotal);
+	printk(KERN_INFO "linelen: %d (mult=%x,div=%x)\n", par->linelen, par->vclock_mult,
+		   par->vclock_div);
+}
+
+
+
+/*
+ *  Very important functionality for the JavaEngine1 computer:
+ *  make screen border black (usign special IGA registers) 
+ */
+static void igsfb_blank_border(struct igsfb_info *igsinfo)
+{
+	int i;
+
+#if 0
+	/*
+	 * PROM does this for us, so keep this code as a reminder
+	 * about required read from 0x3DA and writing of 0x20 in the end.
+	 */
+	(void) pci_inb(info, 0x3DA);	/* required for every access */
+	pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
+	(void) pci_inb(info, IGA_ATTR_CTL + 1);
+	pci_outb(info, 0x38, IGA_ATTR_CTL);
+	pci_outb(info, 0x20, IGA_ATTR_CTL);	/* re-enable visual */
+#endif
+	/*
+	 * This does not work as it was designed because the overscan
+	 * color is looked up in the palette. Therefore, under X11
+	 * overscan changes color.
+	 */
+	for (i = 0; i < 3; i++) {
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x58 + i, 0);
+	}
+}
+
+
+static void igsfb_detect(void)
+{
+	/*
+	 *  This function should detect the current video mode settings and store
+	 *  it as the default video mode
+	 */
+
+	struct igsfb_par par;
+
+	debug("enter");
+
+	igsfb_get_par(&par, (struct fb_info_gen *) &fb_info);
+/*    debug_par(&par); */
+	igsfb_encode_var(&default_var, &par, (struct fb_info_gen *) &fb_info);
+/*    debug_par(&par); */
+}
+
+static int igsfb_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
+							struct fb_info_gen *info)
+{
+	struct igsfb_par *igspar = (struct igsfb_par *) par;
+	struct igsfb_info *igsinfo = (struct igsfb_info *) info;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+	strcpy(fix->id, igsfb_name);
+
+	fix->smem_start = igsinfo->fb_base;
+	fix->smem_len = igsinfo->ram_amount;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	fix->ypanstep = 1;
+
+	switch (8 * igspar->linelen / igspar->width) {
+	case 8:
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 16:
+	case 24:
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 32:
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		break;
+	default:
+		output("unknown color depth!!!\n");
+	}
+	fix->line_length = igspar->linelen;
+
+	/* mmio ?? */
+
+	return 0;
+}
+
+/* 
+ * Taken from cyber2000fb.c with some minor adjustments
+ *
+ * fpll = fvco / div2
+ * fpll = fref * mult / ( div1 * div2 )
+ *
+ * fref = 14.31818 MHz -> 69841ps
+ * fvco must be between 115 and 260 MHz -> 8695ps >= vco_ps >= 3847ps
+ * mult[7:0] = CRTC_VMULT<7:0> + 1
+ * div1[4:0] = CRTC_VDIV<4:0> + 1
+ * div2[1:0] = CRTC_VDIV<7:6> (0 -> 1, 1 -> 2, 2 -> 4, 3 -> 6)
+ *
+ * formula:
+ * vco_ps = pll_ps / div2
+ * pll_ref_ps = pll_ps * mult / ( div1 * div2 ) = vco_ps * mult / div1
+ *
+ */
+static int igsfb_decode_clock(const struct fb_var_screeninfo *var, struct igsfb_par *par,
+							  const struct fb_info_gen *info)
+{
+	const struct igsfb_info *igsinfo = (const struct igsfb_info *) info;
+
+	unsigned long req_pll_ps = var->pixclock;
+
+	unsigned long div2, vco_ps;
+	unsigned long t_div1, t_rr, t_mult, t_vco_ps;
+	unsigned long best_div1, best_mult;
+	long best_diff, diff;
+
+	/* From the win98 driver it looks like 1682 should support
+	 * a pixclock of 100 MHz (1280x1024-8bpp@75Hz), probably
+	 * at least 130 MHz, because of overhead.
+	 * The clock of the CyberPro20x0 is programmable up to 206 MHz,
+	 * but is the 1682 too?
+	 * Play it safe, use 100 MHz max (1152x864@75Hz ~= 99 MHz)
+	 */
+	if (req_pll_ps < 10000) {
+		output("Limiting pixclock to 100 MHz, use the source if you know better\n");
+		req_pll_ps = 10000;
+	}
+
+	/* 
+	 * Step 1:
+	 *  Find a vco_ps, so 3847 =< vco_ps_ps =< 8695
+	 */
+	for (div2 = 0; div2 < sizeof(igsinfo->divisors); div2++) {
+		vco_ps = req_pll_ps / igsinfo->divisors[div2];
+		if (vco_ps >= 3847 && vco_ps <= 8695) {
+			break;
+		}
+	}
+	if (div2 >= sizeof(igsinfo->divisors)) {
+		output("pixclock out of range\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Step 2:
+	 *  Given vco_ps and ref_ps, find:
+	 *    vco_ps * 0.995 < vco_ps_calc < vco_ps * 1.005
+	 *  where { 1 < best_div1 < 32, 1 < best_mult < 256 }
+	 *    vco_ps_calc = best_div1 / (ref_ps * best_mult)
+	 */
+	best_diff = 0x7fffffff;
+	best_mult = 32;
+	best_div1 = 255;
+	for (t_div1 = 32; t_div1 > 1; t_div1 -= 1) {
+
+		/*
+		 * Find the multiplier for this divisor.
+		 * Add half divisor to get good rounding
+		 */
+		t_rr = 2 * igsinfo->ref_pll_ps * t_div1;
+		t_mult = (t_rr + vco_ps) / (2 * vco_ps);
+
+		/*
+		 * Is the multiplier within the correct range?
+		 */
+		if (t_mult > 256 || t_mult < 2) {
+			continue;
+		}
+
+		/*
+		 * Calculate the actual clock period from this multiplier
+		 * and divisor, and estimate the error.
+		 */
+		t_vco_ps = (t_rr + t_mult) / (2 * t_mult);
+		diff = vco_ps - t_vco_ps;
+		if (diff < 0) {
+			diff = -diff;
+		}
+		if (diff < best_diff) {
+			best_diff = diff;
+			best_mult = t_mult;
+			best_div1 = t_div1;
+		}
+
+		/*
+		 * If we hit an exact value, there is no point in continuing.
+		 */
+		if (diff == 0) {
+			break;
+		}
+	}
+
+	/*
+	 * Step 3:
+	 *  combine values
+	 */
+	par->vclock_mult = best_mult - 1;
+	par->vclock_div = div2 << 6 | (best_div1 - 1);
+
+	return 0;
+}
+
+static int igsfb_decode_var(const struct fb_var_screeninfo *var, void *par,
+							struct fb_info_gen *info)
+{
+	struct igsfb_par *igspar = (struct igsfb_par *) par;
+
+#if 1
+	if (igspar == NULL) {
+		printk("par is NULL !!!!");
+	}
+
+
+	*igspar = current_par;
+
+	igspar->width = roundup(var->xres, 8);
+	igspar->height = roundup(var->yres, 4);
+	igspar->htotal = roundup(igspar->width * 4 / 3, 8);
+	igspar->vtotal = roundup(igspar->height * 21 / 20, 2);
+
+	igspar->linelen = igspar->width * (roundup(var->bits_per_pixel, 8) / 8);
+
+	if ((igspar->htotal > 2080) || (igspar->width < 640)) {	/* (255 + 5) * 8 */
+		return -EINVAL;
+	}
+	if ((igspar->vtotal > 2047) || (igspar->height < 480)) {	/* 2^11 - 1 */
+		return -EINVAL;
+	}
+
+	igspar->hrstart = roundup(igspar->width + (igspar->htotal - igspar->width) / 6, 8);
+	igspar->hrend = roundup(igspar->hrstart + (igspar->htotal - igspar->width) / 2, 8);
+
+	igspar->hbstart = igspar->width + 8;
+	igspar->hbend = igspar->htotal - 32;
+
+	igspar->vrstart = igspar->height + 3;
+	igspar->vrend = igspar->vrstart + 8;
+
+	igspar->vbstart = igspar->height + 1;
+	igspar->vbend = igspar->vtotal - 2;
+
+
+/*	debug_par(igspar); */
+	return 0;
+#else
+	/*
+	 *  Get the video params out of 'var'. If a value doesn't fit, round it up,
+	 *  if it's too big, return -EINVAL.
+	 *
+	 *  Suggestion: Round up in the following order: bits_per_pixel, xres,
+	 *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+	 *  bitfields, horizontal timing, vertical timing.
+	 */
+
+	struct igsfb_par new_par;
+	memset(&new_par, 0, sizeof(struct igsfb_par));
+
+	new_par.width = roundup(var->xres, 8);
+	new_par.height = roundup(var->yres, 4);
+	new_par.htotal = roundup(new_par.width * 5 / 4, 8);
+	new_par.vtotal = roundup(new_par.height * 21 / 20, 4);
+
+	if ((new_par.htotal > 2080) || (new_par.width < 640)) {	/* (255 + 5) * 8 */
+		return -EINVAL;
+	}
+	if ((new_par.vtotal > 2047) || (new_par.height < 480)) {	/* 2^11 - 1 */
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "w=%d, h=%d\n", new_par.htotal, new_par.vtotal);
+
+	new_par.hrstart = roundup(new_par.width + (new_par.htotal - new_par.width) / 6, 8);
+	new_par.hrend = roundup(new_par.hrstart + (4 * (new_par.htotal - new_par.width)) / 6, 8);
+
+	new_par.hbstart = new_par.width + 8;
+	new_par.hbend = new_par.htotal - 32;
+
+	new_par.vrstart = new_par.height + 3;
+	new_par.vrend = new_par.vrstart + 8;
+
+	new_par.vbstart = new_par.height + 1;
+	new_par.vbend = new_par.vtotal - 2;
+
+	if (igsfb_decode_clock(var, &new_par, info) < 0) {
+		return -EINVAL;
+	}
+	new_par.mclock_mult = new_par.vclock_mult;
+	new_par.mclock_div = new_par.vclock_div;
+
+	printk(KERN_INFO "mult=%x, div=%x\n", new_par.vclock_mult, new_par.vclock_div);
+
+	/* FIXME: support more than 8,16,24,32bpp */
+	new_par.linelen = new_par.width * (roundup(var->bits_per_pixel, 8) / 8);
+
+	/* FIXME: support interlaces modes */
+	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) {
+		printk(PFX "FIXME: interlaced modes not supported");
+		return -EINVAL;
+	}
+#if 0
+	/* pixclock in picos, htotal in pixels, vtotal in scanlines */
+	if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) {
+		return -EINVAL;
+	}
+#endif
+
+	*igspar = new_par;
+#endif
+	return 0;
+}
+
+static int igsfb_encode_var(struct fb_var_screeninfo *var, const void *par,
+							struct fb_info_gen *info)
+{
+	struct igsfb_par *igspar = (struct igsfb_par *) par;
+	struct igsfb_info *igsinfo = &fb_info;
+
+	unsigned char div1 = (igspar->vclock_div & 0xc0) >> 6;
+	unsigned char div2 = (igspar->vclock_div & 0x1f);
+
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+	var->xres = igspar->width;
+	var->yres = igspar->height;
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+	var->bits_per_pixel = (8 * igspar->linelen) / var->xres;
+	var->height = -1;
+	var->width = -1;
+	var->pixclock = (igsinfo->ref_pll_ps * (igspar->vclock_mult + 1)) / ((div2 + 1) * div1);
+	var->left_margin = igspar->htotal - igspar->hrend;
+	var->right_margin = igspar->hrstart - igspar->width;
+	var->upper_margin = igspar->vtotal - igspar->vrend;
+	var->lower_margin = igspar->vrstart - igspar->height;
+	var->hsync_len = igspar->hrend - igspar->hrstart;
+	var->vsync_len = igspar->vrend - igspar->vrstart;
+	var->sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
+	var->vmode = FB_VMODE_NONINTERLACED;	/* FIXME: read from par */
+
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		var->red.offset = 8;
+		var->red.length = 8;
+		var->green.offset = 16;
+		var->green.length = 8;
+		var->blue.offset = 24;
+		var->blue.length = 8;
+		break;
+#endif
+	default:
+		output("mode %dx%d-%d rejected, color depth not supported.\n",
+			   var->xres, var->yres, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	fb_info.gen.info.var = *var;
+
+	return 0;
+}
+
+static void igsfb_get_par(void *par, struct fb_info_gen *info)
+{
+	/*
+	 *  Fill the hardware's 'par' structure.
+	 */
+	struct igsfb_par *igspar = (struct igsfb_par *) par;
+	struct igsfb_info *igsinfo = (struct igsfb_info *) info;
+
+	if (!current_par_valid) {
+
+		unsigned int reg_hbend, reg_hrend;
+		unsigned int reg_crtc_ofl, reg_crtc_scn, reg_grfx_ofl;
+
+		memset(&current_par, 0, sizeof(struct igsfb_par));
+
+		current_par.htotal = (igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HTOTAL) + 5) << 3;
+		current_par.width = (igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_WIDTH) + 1) << 3;
+		current_par.hbstart = igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HBSTART);
+		current_par.hrstart = igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HRSTART);
+
+		reg_hbend = igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HBEND);
+		reg_hrend = igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HREND);
+
+		current_par.hbend =	(current_par.hbstart & 0xffc0) + (((reg_hrend & 0x80) >> 2) | (reg_hbend & 0x1F));
+		current_par.hrend = (current_par.hrstart & 0xffe0) + (reg_hrend & 0x1F);
+
+		if (current_par.hrend < current_par.hrstart) {
+			current_par.hrend += 0x20;
+		}
+		if (current_par.hbend < current_par.hbstart) {
+			current_par.hbend += 0x40;
+		}
+
+		current_par.hbstart <<= 3;
+		current_par.hbend <<= 3;
+		current_par.hrstart <<= 3;
+		current_par.hrend <<= 3;
+
+		reg_crtc_ofl = igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VOFL);
+		reg_crtc_scn = igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_SCANLINE);
+		reg_grfx_ofl = igsfb_inb(igsinfo, IGS_PORT_GRFX, IGS_GRFX_VOFL);
+
+		current_par.vtotal = (((reg_grfx_ofl & 0x01) << 10) +
+							  ((reg_crtc_ofl & 0x20) <<  4) +
+							  ((reg_crtc_ofl & 0x01) <<  8) +
+							  igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VTOTAL)) + 2;
+		current_par.vbstart = ((reg_grfx_ofl & 0x08) << 7) +
+							  ((reg_crtc_scn & 0x20) << 4) +
+							  ((reg_crtc_ofl & 0x08) << 5) +
+							  igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VBSTART);
+		current_par.vrstart = ((reg_grfx_ofl & 0x04) << 8) +
+							  ((reg_crtc_ofl & 0x80) << 2) +
+							  ((reg_crtc_ofl & 0x04) << 6) +
+							  igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VRSTART);
+		current_par.height = (((reg_grfx_ofl & 0x02) << 9) +
+							  ((reg_crtc_ofl & 0x40) << 3) +
+							  ((reg_crtc_ofl & 0x02) << 7) +
+							  igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HEIGHT)) + 1;
+		current_par.vbend = (current_par.vbstart & 0xff00) +
+							(igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VBEND) & 0xff);
+		current_par.vrend = (current_par.vrstart & 0xfff0) +
+							(igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VREND) & 0x0f);
+
+		if (current_par.vbend < current_par.vbstart) {
+			current_par.vbend += 0x0100;
+		}
+		if (current_par.vrend < current_par.vrstart) {
+			current_par.vrend += 0x0010;
+		}
+
+		current_par.linelen = 8 * (((igsfb_inb(igsinfo, IGS_PORT_GRFX, IGS_FETCH1) & 0x30) << 4) +
+							         igsfb_inb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_OFFSET));
+
+		current_par.vclock_mult = igsfb_inb(igsinfo, IGS_PORT_GRFX, VCLK_MULT);
+		current_par.vclock_div  = igsfb_inb(igsinfo, IGS_PORT_GRFX, VCLK_DIV);
+		current_par.mclock_mult = igsfb_inb(igsinfo, IGS_PORT_GRFX, MCLK_MULT);
+		current_par.mclock_div  = igsfb_inb(igsinfo, IGS_PORT_GRFX, MCLK_DIV);
+
+		current_par_valid = 1;
+	}
+	*igspar = current_par;
+}
+
+static void igsfb_set_par(const void *par, struct fb_info_gen *info)
+{
+	/*
+	 *  Set the hardware according to 'par'.
+	 */
+	struct igsfb_par *igspar = (struct igsfb_par *) par;
+	struct igsfb_info *igsinfo = &fb_info;
+
+	unsigned int w1, w2, mode;
+	unsigned int vtotal;
+	unsigned int vheight;
+
+	mode = 1;
+
+	current_par.htotal = igspar->htotal;
+	current_par.width = igspar->width;
+	current_par.hbstart = igspar->hbstart;
+	current_par.hrstart = igspar->hrstart;
+	current_par.hbend = igspar->hbend;
+	current_par.hrend = igspar->hrend;
+
+	current_par.vtotal = igspar->vtotal;
+	current_par.height = igspar->height;
+	current_par.vbstart = igspar->vbstart;
+	current_par.vrstart = igspar->vrstart;
+	current_par.vbend = igspar->vbend;
+	current_par.vrend = igspar->vrend;
+
+	vheight = current_par.height - 1;
+	vtotal = current_par.vtotal - 2;
+
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, 0x11, 0);	/* enable write */
+
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HTOTAL, (current_par.htotal >> 3) - 5);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_WIDTH, (current_par.width >> 3) - 1);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HBSTART, current_par.hbstart >> 3);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HRSTART, current_par.hrstart >> 3);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HBEND, ((current_par.hbend >> 3) & 0x1F));
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HREND, 
+			(((current_par.hbend >> 3) & 0x20) << 2) | ((current_par.hrend >> 3) & 0x1F));
+
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VTOTAL, vtotal & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VRSTART, current_par.vrstart & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_HEIGHT, vheight & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VBSTART, current_par.vbstart & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VBEND, current_par.vbend & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VREND, current_par.vrend & 0x000f);
+
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_VOFL,
+			   ((vtotal >> 8) & 0x01) |
+			   ((vheight >> 7) & 0x02) |
+			   ((current_par.vrstart >> 6) & 0x04) |
+			   ((current_par.vbstart >> 5) & 0x08) |
+			   ((vtotal >> 4) & 0x20) |
+			   ((vheight >> 3) & 0x40) | ((current_par.vrstart >> 2) & 0x80) | (0x10));
+
+	igsfb_outb(igsinfo, IGS_PORT_GRFX, IGS_GRFX_VOFL,
+			   ((vtotal >> 10) & 0x01) |
+			   ((vheight >> 9) & 0x02) |
+			   ((current_par.vrstart >> 8) & 0x04) | ((current_par.vbstart >> 7) & 0x08));
+
+	current_par.linelen = igspar->linelen;
+
+	w1 = current_par.linelen / 8;
+	w2 = w1 + 1;
+
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, IGS_CRTC_OFFSET, w1 & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_GRFX, IGS_FETCH0, w2 & 0x00ff);
+	igsfb_outb(igsinfo, IGS_PORT_GRFX, IGS_FETCH1,
+			   ((w1 & 0x0300) >> 4) | ((w2 & 0x0300) >> 8));
+
+	{
+		unsigned char ramdac = igsfb_inb(igsinfo, IGS_PORT_GRFX, 0x56);
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x56, ramdac | 0x04);
+	}
+
+	switch (current_par.linelen / current_par.width) {
+
+	case 1:
+		mode = 1;
+		pci_outb(igsinfo, 0x04, 0x3c6);	/* 6 bit dac */
+		break;
+	case 2:
+		mode = 2;
+		pci_outb(igsinfo, 0x16, 0x3c6);	/* bypass & 8 bit dac */
+		break;
+	case 3:
+		mode = 4;
+		pci_outb(igsinfo, 0x16, 0x3c6);	/* bypass & 8 bit dac */
+		break;
+	case 4:
+		mode = 3;
+		pci_outb(igsinfo, 0x16, 0x3c6);	/* bypass & 8 bit dac */
+		break;
+	}
+
+	{
+		unsigned char ramdac = igsfb_inb(igsinfo, IGS_PORT_GRFX, 0x56);
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x56, ramdac & ~0x04);
+	}
+
+	igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x77, mode);
+}
+
+static int igsfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+						   unsigned *blue, unsigned *transp, struct fb_info *info)
+{
+	struct igsfb_info *igsinfo = (struct igsfb_info *) info;
+
+	if (regno > igsinfo->cmap_len) {
+		return 1;
+	}
+
+	*red = igsinfo->palette[regno].red;
+	*green = igsinfo->palette[regno].green;
+	*blue = igsinfo->palette[regno].blue;
+	*transp = 0;
+
+	return 0;
+}
+
+static int igsfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+						   unsigned blue, unsigned transp, struct fb_info *info)
+{
+	/*
+	 *  Set a single color register. The values supplied have a 16 bit
+	 *  magnitude.
+	 *  Return != 0 for invalid regno.
+	 */
+
+	struct igsfb_info *igsinfo = &fb_info;
+
+	if (regno >= igsinfo->cmap_len) {
+		return 1;
+	}
+
+	igsinfo->palette[regno].red = red;
+	igsinfo->palette[regno].green = green;
+	igsinfo->palette[regno].blue = blue;
+
+#ifdef FBCON_HAS_CFB8
+	if (igsinfo->gen.info.var.bits_per_pixel == 8) {
+		pci_outb(igsinfo, regno, 0x3c8);
+		pci_outb(igsinfo, red >> 8, 0x3c9);
+		pci_outb(igsinfo, green >> 8, 0x3c9);
+		pci_outb(igsinfo, blue >> 8, 0x3c9);
+	}
+#endif
+	if (regno < 16) {
+		switch (igsinfo->gen.info.var.bits_per_pixel) {
+
+#ifdef FBCON_HAS_CFB16
+		case 16:				/* RGB 565 */
+#if 0
+			igsinfo->fbcon_cmap.cfb16[regno] =
+				((red & 0xf800) >> 0) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+#else
+			/* We do the byteswapping ourselves:
+			   rrrrrggg gggbbbbb  -> gggbbbbb rrrrrggg */
+			igsinfo->fbcon_cmap.cfb16[regno] =
+				((green & 0x1c00) << 3) | ((blue & 0xf800) >> 3) |
+				((red & 0xf800) >> 8) | ((green & 0xe000) >> 13);
+#endif
+			break;
+#endif
+#ifdef FBCON_HAS_CFB24			/* RGB 888 */
+		case 24:
+			igsinfo->fbcon_cmap.cfb24[regno] =
+				((red & 0xff00) >> 8) | ((green & 0xff00)) | ((blue & 0xff00) << 8);
+			break;
+#endif
+#ifdef FBCON_HAS_CFB32			/* RGBA 8888 */
+		case 32:
+			igsinfo->fbcon_cmap.cfb32[regno] =
+				((red & 0xff00) << 0) | ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
+			break;
+#endif
+		}
+	}
+	return 0;
+}
+
+static int igsfb_pan_display(const struct fb_var_screeninfo *var,
+                             struct fb_info_gen *info)
+{
+	/*
+	 *  Pan (or wrap, depending on the `vmode' field) the display using the
+	 *  `xoffset' and `yoffset' fields of the `var' structure.
+	 *  If the values don't fit, return -EINVAL.
+	 */
+	
+	struct igsfb_info *igsinfo = &fb_info;
+	
+	unsigned long base = var->yoffset * var->xres_virtual + var->xoffset;
+	base *= (var->bits_per_pixel + 7) >> 3;
+	base >>= 2;
+
+	if (base >= (1 << 20)) {
+		return -EINVAL;
+	}
+
+	igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x10, (base >> 16) | 0x0f);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, 0x0c, (base >> 8) | 0xff);
+	igsfb_outb(igsinfo, IGS_PORT_CRTC, 0x0d, base | 0xff);
+
+	return 0;
+}
+
+static int xxx_blank(int blank_mode, const struct fb_info *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
+	 */
+
+	/* ... */
+	return 0;
+}
+
+static void igsfb_set_disp(const void *par, struct display *disp, struct fb_info_gen *info)
+{
+	/*
+	 *  Fill in a pointer with the virtual address of the mapped frame buffer.
+	 *  Fill in a pointer to appropriate low level text console operations (and
+	 *  optionally a pointer to help data) for the video mode `par' of your
+	 *  video hardware. These can be generic software routines, or hardware
+	 *  accelerated routines specifically tailored for your hardware.
+	 *  If you don't have any appropriate operations, you must fill in a
+	 *  pointer to dummy operations, and there will be no text output.
+	 */
+
+	struct igsfb_info *igsinfo = (struct igsfb_info *) info;
+
+	igsfb_encode_var(&disp->var, &current_par, &igsinfo->gen);
+	disp->screen_base = (char *) igsinfo->fb_base;
+
+	switch (disp->var.bits_per_pixel) {
+
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		disp->dispsw = &fbcon_cfb8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		disp->dispsw = &fbcon_cfb16;
+		disp->dispsw_data = igsinfo->fbcon_cmap.cfb16;	/* console palette */
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		disp->dispsw = &fbcon_cfb24;
+		disp->dispsw_data = igsinfo->fbcon_cmap.cfb24;	/* console palette */
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		disp->dispsw = &fbcon_cfb32;
+		disp->dispsw_data = igsinfo->fbcon_cmap.cfb32;	/* console palette */
+		break;
+#endif
+	default:
+		disp->dispsw = &fbcon_dummy;
+		disp->dispsw_data = NULL;
+		output("Installing dummy (bbp=%d\n", disp->var.bits_per_pixel);
+	}
+
+}
+
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+
+static struct fbgen_hwswitch igsfb_switch = {
+	igsfb_detect,
+	igsfb_encode_fix,
+	igsfb_decode_var,
+	igsfb_encode_var,
+	igsfb_get_par,
+	igsfb_set_par,
+	igsfb_getcolreg,
+	igsfb_setcolreg,
+	igsfb_pan_display,
+	NULL,
+	igsfb_set_disp
+};
+/*
+    xxx_detect, xxx_encode_fix, xxx_decode_var, igsfb_encode_var, igsfb_get_par,
+    xxx_set_par, igsfb_getcolreg, igsfb_setcolreg, xxx_pan_display, xxx_blank,
+    igsfb_set_disp
+*/
+
+
+/* ------------ Hardware Independent Functions ------------ */
+
+
+	/*
+	 *  Initialization
+	 */
+
+int __init igsfb_init(void)
+{
+	struct pci_dev *pdev = NULL;
+	struct igsfb_info *igsinfo = NULL;
+/*	extern int con_is_present(void); */
+	unsigned long addr = 0;
+	int igs2000 = 0;
+
+	/* Do not attach when we have a serial console */
+/*	if (!con_is_present()) {
+		return -ENXIO;
+	}
+*/
+	pdev = pci_find_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0);
+	if (pdev == NULL) {
+		pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
+		if (pdev == NULL) {
+			return -ENXIO;
+		}
+		igs2000 = 1;
+	}
+	output("pcidev");
+
+	igsinfo = &fb_info;
+	/*kmalloc(sizeof(struct igsfb_info), GFP_ATOMIC); */
+	if (!igsinfo) {
+		output("can't alloc fb_info_iga\n");
+		return -ENOMEM;
+	}
+	memset(igsinfo, 0, sizeof(struct igsfb_info));
+	output("pcidev at (%lx), end(%lx)\n", pdev->resource[0].start, pdev->resource[0].end);
+
+
+
+	if ((addr = pdev->resource[0].start) == 0) {
+		output("no memory found for device\n");
+		/* kfree(igsinfo); */
+		return -ENXIO;
+	}
+
+	if ((igsinfo->fb_base = (u32) ioremap(addr, 8 * 1024 * 1024)) == 0) {
+		output(KERN_ERR PFX "can't remap %lx[2M]\n", addr);
+		/*kfree(igsinfo); */
+		return -ENXIO;
+	}
+
+	igsinfo->fb_base_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
+
+#if 0
+	igsinfo->bg_base_phys = igsinfo->fb_base_phys + 0x00400000;	/* big endian ! */
+	output("[%x]->[%x]\n", igsinfo->fb_base_phys, igsinfo->bg_base_phys);
+#if 1
+	if ((igsinfo->bg_base = (u32) ioremap(igsinfo->bg_base_phys, 2 * 1024 * 1024)) == 0) {
+		output(KERN_ERR PFX "can't remap %lx[2M]\n", igsinfo->bg_base_phys);
+		/*kfree(igsinfo); */
+		return -ENXIO;
+	}
+#endif
+#endif
+
+#ifdef __sparc__
+
+	if (igs2000) {
+		igsinfo->io_base_phys = (addr & PCI_BASE_ADDRESS_MEM_MASK) | 0x00800000;
+	} else {
+		igsinfo->io_base_phys = 0x30000000;	/* Magic from the PROM */
+	}
+	if ((igsinfo->io_base = (u32) ioremap(igsinfo->io_base_phys, 0x1000)) == 0) {
+		output(KERN_ERR PFX "can't remap %lx[4K]\n", (unsigned long) igsinfo->io_base_phys);
+		iounmap((void *) igsinfo->fb_base);
+/*		kfree(igsinfo); */
+		return -ENXIO;
+	}
+
+	igsinfo->mmap_map = kmalloc(4 * sizeof(*igsinfo->mmap_map), GFP_ATOMIC);
+	if (!igsinfo->mmap_map) {
+		output("igafb_init: can't alloc mmap_map\n");
+		iounmap((void *) igsinfo->io_base);
+		iounmap((void *) igsinfo->fb_base);
+/*        kfree(igsinfo);*/
+		return -ENOMEM;
+	}
+
+	memset(igsinfo->mmap_map, 0, 4 * sizeof(*igsinfo->mmap_map));
+
+	output("found device & remapped\n");
+
+#if 1
+	/*
+	   * Set default vmode and cmode from PROM properties.
+	 */
+	{
+		struct pcidev_cookie *cookie = pdev->sysdata;
+		int node = cookie->prom_node;
+		int width = prom_getintdefault(node, "width", 1024);
+		int height = prom_getintdefault(node, "height", 768);
+		int depth = prom_getintdefault(node, "depth", 16);
+		switch (width) {
+		case 1024:
+			if (height == 768)
+				default_var = default_var_1024x768;
+			break;
+		default:
+			break;
+		}
+
+		switch (depth) {
+		case 8:
+			default_var.bits_per_pixel = 8;
+			break;
+		case 16:
+			default_var.bits_per_pixel = 16;
+			break;
+		case 24:
+			default_var.bits_per_pixel = 24;
+			break;
+		case 32:
+			default_var.bits_per_pixel = 32;
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+
+#endif
+
+
+
+
+	igsinfo->ram_amount = 0x200000;
+	igsinfo->cmap_len = 256;
+
+
+
+	{
+		int j, k;
+		for (j = 0; j < 16; j++) {
+			k = color_table[j];
+			igsinfo->palette[j].red = default_red[k];
+			igsinfo->palette[j].green = default_grn[k];
+			igsinfo->palette[j].blue = default_blu[k];
+		}
+	}
+
+
+	output("color palette filled\n");
+
+
+	igsinfo->gen.fbhw = &igsfb_switch;
+	igsinfo->gen.parsize = sizeof(struct igsfb_par);
+	strcpy(igsinfo->gen.info.modename, igsfb_name);
+	igsinfo->gen.info.changevar = NULL;
+	igsinfo->gen.info.node = -1;
+	igsinfo->gen.info.fbops = &igsfb_ops;
+	igsinfo->gen.info.disp = &disp;
+	igsinfo->gen.info.switch_con = &fbgen_switch;
+	igsinfo->gen.info.updatevar = &fbgen_update_var;
+	igsinfo->gen.info.blank = &fbgen_blank;
+	igsinfo->gen.info.flags = FBINFO_FLAG_DEFAULT;
+	igsinfo->gen.info.fontname[0] = '\0';
+	strcpy(igsinfo->gen.info.fontname, fontname);
+
+
+	output("igsinfo filled\n");
+	igsinfo->gen.fbhw->detect();
+
+
+
+	/* This should give a reasonable default video mode */
+	fbgen_get_var(&disp.var, -1, &igsinfo->gen.info);
+/*	disp.var = default_var; */
+	disp.var.activate = FB_ACTIVATE_NOW;
+	fbgen_do_set_var(&disp.var, 1, &igsinfo->gen);
+	output("set_var");
+	fbgen_set_disp(-1, &igsinfo->gen);
+	output("cmap");
+	fbgen_install_cmap(0, &igsinfo->gen);
+
+	output("setup video mode\n");
+
+/*    debug_display(igsinfo->gen.info.disp); */
+
+	if (register_framebuffer(&igsinfo->gen.info) < 0) {
+		return -EINVAL;
+	}
+	output("reg complete\n");
+
+	output("fb%d: %s frame buffer device\n", GET_FB_IDX(igsinfo->gen.info.node),
+		   igsinfo->gen.info.modename);
+
+#ifdef __sparc__
+
+
+#if 0
+	{
+		unsigned char bigen = igsfb_inb(igsinfo, IGS_PORT_GRFX, 0x3c);
+		printk("3cf-3c = %x\n", bigen);
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x3c, bigen | 0x04);
+		bigen = igsfb_inb(igsinfo, IGS_PORT_GRFX, 0x3f);
+		printk("3cf-3f = %x\n", bigen);
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x3f, 0x55);
+	}
+#else
+	{
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x3d, 0x30);
+		igsfb_outb(igsinfo, IGS_PORT_GRFX, 0x3f, 0x2A);
+	}
+#endif
+
+	igsfb_blank_border(igsinfo);
+
+	/*
+	 * Add /dev/fb mmap values.
+	 */
+#if 1
+	/* First region is for video memory */
+	igsinfo->mmap_map[0].voff = 0x0;
+	igsinfo->mmap_map[0].poff = igsinfo->fb_base_phys & PAGE_MASK;
+	igsinfo->mmap_map[0].size = (4 * igsinfo->ram_amount) & PAGE_MASK;
+	igsinfo->mmap_map[0].prot_mask = SRMMU_CACHE;
+	igsinfo->mmap_map[0].prot_flag = SRMMU_WRITE;
+
+#else
+	/* Second region is for I/O ports */
+	igsinfo->mmap_map[0].voff = 0x0;
+	igsinfo->mmap_map[0].poff = igsinfo->bg_base_phys & PAGE_MASK;
+	igsinfo->mmap_map[0].size = igsinfo->ram_amount & PAGE_MASK;
+	igsinfo->mmap_map[0].prot_mask = SRMMU_CACHE;
+	igsinfo->mmap_map[0].prot_flag = SRMMU_WRITE;
+#endif
+	/* Second region is for I/O ports */
+	igsinfo->mmap_map[1].voff = igsinfo->fb_base_phys & PAGE_MASK;
+	igsinfo->mmap_map[1].poff = igsinfo->io_base_phys & PAGE_MASK;
+	igsinfo->mmap_map[1].size = PAGE_SIZE * 2;	/* X wants 2 pages */
+	igsinfo->mmap_map[1].prot_mask = SRMMU_CACHE;
+	igsinfo->mmap_map[1].prot_flag = SRMMU_WRITE;
+#endif							/* __sparc__ */
+
+
+	/*fb_info = *igsinfo;   */
+
+	/* uncomment this if your driver cannot be unloaded */
+	/* MOD_INC_USE_COUNT; */
+	return 0;
+}
+
+
+	/*
+	 *  Cleanup
+	 */
+void __exit igsfb_cleanup(void)
+{
+	/*
+	 *  If your driver supports multiple boards, you should unregister and
+	 *  clean up all instances.
+	 */
+	printk("cleanup\n");
+	unregister_framebuffer(&fb_info.gen.info);
+	printk("cleanup 1\n");
+	iounmap((void *) fb_info.io_base);
+	printk("cleanup 2\n");
+	iounmap((void *) fb_info.fb_base);
+	printk("cleanup 3\n");
+
+}
+
+   /*
+      *  Setup
+    */
+
+#ifdef MODULE
+int __init igsfb_setup(char *options)
+{
+	/* Parse user speficied options (`video=xxxfb:') */
+	return 0;
+}
+#endif
+
+
+/* ------------------------------------------------------------------------- */
+
+
+	/*
+	 *  Frame buffer operations
+	 */
+
+/* If all you need is that - just don't define ->fb_open */
+static int igsfb_open(struct fb_info *info, int user)
+{
+	opencount++;
+	return 0;
+}
+
+/* If all you need is that - just don't define ->fb_release */
+static int igsfb_release(struct fb_info *info, int user)
+{
+	opencount--;
+	return 0;
+}
+
+#if 1
+/* #ifdef __sparc__ */
+static int igsfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+	struct igsfb_info *igsinfo = (struct igsfb_info *) info;
+	unsigned int size, page, map_size = 0;
+	unsigned long map_offset = 0;
+	int i;
+
+	if (!igsinfo->mmap_map)
+		return -ENXIO;
+
+	size = vma->vm_end - vma->vm_start;
+
+//	debug("mmap: request for size:%x\n", size);
+
+	/* To stop the swapper from even considering these pages. */
+	vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+	/* Each page, see which map applies */
+	for (page = 0; page < size;) {
+		map_size = 0;
+		for (i = 0; igsinfo->mmap_map[i].size; i++) {
+			unsigned long start = igsinfo->mmap_map[i].voff;
+			unsigned long end = start + igsinfo->mmap_map[i].size;
+			unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
+
+			if (start > offset)
+				continue;
+			if (offset >= end)
+				continue;
+
+			map_size = igsinfo->mmap_map[i].size - (offset - start);
+			map_offset = igsinfo->mmap_map[i].poff + (offset - start);
+			break;
+		}
+		if (!map_size) {
+			page += PAGE_SIZE;
+			continue;
+		}
+		if (page + map_size > size) {
+			map_size = size - page;
+		}
+
+		pgprot_val(vma->vm_page_prot) &= ~(igsinfo->mmap_map[i].prot_mask);
+		pgprot_val(vma->vm_page_prot) |= igsinfo->mmap_map[i].prot_flag;
+
+
+		if (remap_page_range(vma->vm_start + page, map_offset, map_size, vma->vm_page_prot)) {
+			return -EAGAIN;
+		}
+
+		page += map_size;
+	}
+
+	if (!map_size) {
+		return -EINVAL;
+	}
+
+	vma->vm_flags |= VM_IO;
+
+	if (!igsinfo->mmaped) {
+		int lastconsole = 0;
+
+		if (info->display_fg)
+			lastconsole = info->display_fg->vc_num;
+		igsinfo->mmaped = 1;
+		if (igsinfo->consolecnt && fb_display[lastconsole].fb_info == info) {
+			igsinfo->vtconsole = lastconsole;
+			vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
+		}
+	}
+	return 0;
+}
+#endif							/* __sparc__ */
+
+
+
+
+
+	/*
+	 *  In most cases the `generic' routines (fbgen_*) should be satisfactory.
+	 *  However, you're free to fill in your own replacements.
+	 */
+
+static struct fb_ops igsfb_ops = {
+	owner:THIS_MODULE,
+#if 0
+	fb_open:igsfb_open,
+	fb_release:igsfb_release,
+#endif
+	fb_get_fix:fbgen_get_fix,
+	fb_get_var:fbgen_get_var,
+	fb_set_var:fbgen_set_var,
+	fb_get_cmap:fbgen_get_cmap,
+	fb_set_cmap:fbgen_set_cmap,
+	fb_pan_display:fbgen_pan_display,
+#if 0
+	fb_ioctl:fbgen_ioctl,		/* optional */
+#endif
+	fb_mmap:igsfb_mmap,
+};
+
+
+
+/* ------------------------------------------------------------------------- */
+
+
+	/*
+	 *  Modularization
+	 */
+
+#ifdef MODULE
+
+MODULE_LICENSE("GPL");
+
+#if 0
+int __init init_module(void)
+{
+	return igsfb_init();
+}
+#endif
+
+module_init(igsfb_init);
+
+#if 0
+void cleanup_module(void)
+{
+	printk("cleanup\n");
+	igsfb_cleanup();
+}
+#endif
+
+#endif							/* MODULE */
+
+module_exit(igsfb_cleanup);
diff -ruP linux-2.4.20/drivers/video/igsfb.h linux-2.4.20.mw/drivers/video/igsfb.h
--- linux-2.4.20/drivers/video/igsfb.h	Thu Jan  1 01:00:00 1970
+++ linux-2.4.20.mw/drivers/video/igsfb.h	Sat May  3 15:02:09 2003
@@ -0,0 +1,189 @@
+/*
+ * igsfb.h - Constants for igsfb
+ *
+ * Nov 2002 - Jasper van der Neut <jasper@dnd.utwente.nl>
+ * 
+ */
+
+#ifndef IGSFB_DEBUG
+#define IGSFB_DEBUG 1
+#endif
+ 
+#if IGSFB_DEBUG
+#define debug(f, a...)   printk("%s:" f,  __FUNCTION__ , ## a)
+#else
+#define debug(f, a...)
+#endif
+ 
+#define output(f, a...) printk("igsfb: " f, ## a)
+ 
+ 
+#include <asm/types.h>
+
+#define PFX	"igsfb "
+
+#define REF_PLL_PS		69841L
+
+#define IGS_PORT_CRTC	0x3d4
+
+#define IGS_CRTC_HTOTAL		0x00
+#define IGS_CRTC_WIDTH		0x01
+#define IGS_CRTC_HBSTART	0x02
+#define IGS_CRTC_HBEND		0x03
+#define HBEND_MASK				0x1f
+#define IGS_CRTC_HRSTART	0x04
+#define IGS_CRTC_HREND		0x05
+#define HREND_MASK				0x1f
+#define HBEND_MASK_MSB			0x80
+#define IGS_CRTC_VTOTAL		0x06
+#define IGS_CRTC_VOFL		0x07	/* See comment below */
+#define VTOTAL_MASK_8			0x01
+#define VDEEND_MASK_8			0x02
+#define VRSTART_MASK_8			0x04
+#define VBSTART_MASK_8			0x08
+#define LINECOMP_MASK_8			0x10
+#define VTOTAL_MASK_9			0x20
+#define VDEEND_MASK_9			0x40
+#define VRSTART_MASK_9			0x80
+#define IGS_CRTC_SCANLINE	0x09	/* See comment below */
+#define VBSTART_MASK_9			0x20
+#define LINECOMP_MASK_9			0x40
+#define IGS_CRTC_VRSTART	0x10
+#define IGS_CRTC_VREND		0x11
+#define VREND_MASK				0x0F
+#define REG_PROTECT				0x80
+#define IGS_CRTC_HEIGHT		0x12
+#define IGS_CRTC_OFFSET		0x13
+
+#define IGS_CRTC_VBSTART	0x15
+#define IGS_CRTC_VBEND		0x16
+
+
+#define IGS_PORT_GRFX	0x3ce			/* 0x3ce IDX, 0x3cf DATA */
+
+/* IGS_VERT_OFL
+ bit
+  5: Enabled for interlaced modes
+  4: LINECOMP[10], [9] in CRTC[9]/6, [8] in CRTC[7]/4, [7:0] in CRTC[18]
+  3:  VBSTART[10], [9] in CRTC[9]/5, [8] in CRTC[7]/3, [7:0] in CRTC[15]
+  2:  VRSTART[10], [9] in CRTC[7]/7, [8] in CRTC[7]/2, [7:0] in CRTC[10]
+  1:   VDEEND[10], [9] in CRTC[7]/6, [8] in CRTC[7]/1, [7:0] in CRTC[12]
+  0:   VTOTAL[10], [9] in CRTC[7]/5, [8] in CRTC[7]/0, [7:0] in CRTC[6]
+*/
+#define IGS_GRFX_VOFL		0x11		/* Vertical overflow */
+#define VID_INTERLACED			0x20
+
+#define IGS_FETCH0			0x14		/* Number of memoryfetch [9:0] */
+#define IGS_FETCH1			0x15		/* Overflow offset[9:8], memfetch[9:8] */
+#define MEM_OFL_MASK			0x03	/* Overflow from CRTC[13] */
+#define OFF_OFL_MASK			0x30
+
+#define IGS_SPRITE_CTL		0x56
+#define FLUSHWB					0x10	/* Flush write buffer */
+#define RCKINV					0x40	/* RAMDAC in phase */
+
+#define IGS_SEQ_MISC		0x77		/* MSL[3:0] */
+#define MSL_STD					0x00	/* IBM standard */
+#define MSL_8BPP_PAL			0x01	/*  8bpp palette */
+#define MSL_8BPP				0x09	/*  8bpp (3,3,2) */
+#define MSL_12BPP				0x10	/* 12bpp (4,4,4) */
+#define MSL_15BPP				0x06	/* 15bpp (5,5,5) */
+#define MSL_16BPP				0x02	/* 16bpp (5,6,5) */
+#define MSL_24BPP				0x04	/* 24bpp */
+#define MSL_32BPP				0x03	/* 32bpp */
+
+#define VCLK_MULT			0xb0		/* VMD[7:0] */
+#define VCLK_DIV			0xb1		/* VPD[1:0], VFSEL, VND[4:0] */
+#define VCLK_DIV_CNT_MASK		0x1f
+#define VCLK_DIV_VFSEL			0x20
+#define VCLK_DIV_DIV_MASK		0xc0
+
+#define MCLK_MULT			0xb2		/* MMD[7:0] */
+#define MCLK_DIV			0xb3		/* MPD[1:0], MFSEL, MND[4:0] */
+#define MCLK_DIV_CNT_MASK		0x1f
+#define MCLK_DIV_VFSEL			0x20
+#define MCLK_DIV_DIV_MASK		0xc0
+
+#define MISC_CLK			0xb9		/* use bus clock for mem clock if bit x 1 */
+
+struct pci_mmap_map {
+    unsigned long voff;
+    unsigned long poff;
+    unsigned long size;
+    unsigned long prot_flag;
+    unsigned long prot_mask;
+};
+
+struct igsfb_info {
+
+		struct fb_info_gen gen;
+		
+		u32 io_base_phys;
+		u32 io_base;
+		
+		u32 fb_base_phys;
+		u32 fb_base;
+
+		u32 bg_base_phys;
+		u32 bg_base;
+		
+		u32 ram_amount;
+		
+		u32 ref_pll_ps;			/* 14.31818 MHz */
+		u8	divisors[4];		/* 1, 2, 4, 6 */
+		
+		struct display disp;
+/*		struct display_switch dispw; */
+		
+		struct { u_short blue, green, red, pad; } palette[256];
+		
+		unsigned int cmap_len;
+		struct pci_mmap_map *mmap_map;
+
+		
+		union {
+#ifdef FBCON_HAS_CFB16
+			u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+			u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+			u32 cfb32[16];
+#endif
+		} fbcon_cmap;
+
+#if 1		
+/* #ifdef __sparc__ */
+    u8 open;
+    u8 mmaped;
+    int vtconsole;
+    int consolecnt;
+#endif
+
+};
+
+
+struct igsfb_par {
+	u16 width;		/* Visible width */
+	u16 htotal;		/* Total width */
+	u16 hbstart;		/* Start blank */
+	u16 hbend;		/* End blank */
+	u16 hrstart;		/* Start sync */
+	u16 hrend;		/* End sync */
+	
+	u16 height;		/* Visible height */
+	u16 vtotal;		/* Total height */
+	u16 vbstart;		/* Start blank */
+	u16 vbend;		/* End blank */
+	u16 vrstart;		/* Start sync */
+	u16 vrend;		/* End sync */
+	
+	u16 linelen;		/* Length of scanline in bytes (width x bpp) */
+	
+	u32 vclock_mult;
+	u32 vclock_div;
+	u32 mclock_mult;
+	u32 mclock_div;
+};
+
diff -ruP linux-2.4.20/drivers/video/xx linux-2.4.20.mw/drivers/video/xx
--- linux-2.4.20/drivers/video/xx	Thu Jan  1 01:00:00 1970
+++ linux-2.4.20.mw/drivers/video/xx	Sat May  3 15:01:43 2003
@@ -0,0 +1,14 @@
+#ifndef IGSFB_DEBUG
+#define IGSFB_DEBUG 1
+#endif
+ 
+#if IGSFB_DEBUG
+#define debug(f, a...)   printk("%s:" f,  __FUNCTION__ , ## a)
+#else
+#define debug(f, a...)
+#endif
+ 
+#define output(f, a...) printk("igsfb: " f, ## a)
+ 
+ 
+
