Browse Source

[PATCH] Update cyblafb driver

This is a major update to the cyblafb framebuffer driver. Most
of the stuff has been tested in the mm tree.

Main advantages:
============
  - vxres > xres support
  - ywrap and xpan support
  - much faster for almost all modes (e.g. 1280x1024-16bpp
     draws more than 41 full screens of text instead of about 25
     full screens of text per second on authors Epia 5000)
  - module init/exit code fixed
  - bugs triggered by console rotation fixed
  - lots of minor improvements
  - startup modes suitable for high performance scrolling
     in all directions

This diff  also contains a lot of white space fixes.

No side effects are possible, only one single graphics core is affected.

Signed-off-by: Knut Petersen <Knut_Petersen@t-online.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Knut Petersen 19 years ago
parent
commit
44637a12f8

+ 0 - 1
Documentation/fb/cyblafb/bugs

@@ -11,4 +11,3 @@ Untested features
 
 
 All LCD stuff is untested. If it worked in tridentfb, it should work in
 All LCD stuff is untested. If it worked in tridentfb, it should work in
 cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
 cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
-

+ 28 - 29
Documentation/fb/cyblafb/fb.modes

@@ -14,142 +14,141 @@
 #
 #
 
 
 mode "640x480-50"
 mode "640x480-50"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 47619 4294967256 24 17 0 216 3
     timings 47619 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "640x480-60"
 mode "640x480-60"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 39682 4294967256 24 17 0 216 3
     timings 39682 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "640x480-70"
 mode "640x480-70"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 34013 4294967256 24 17 0 216 3
     timings 34013 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "640x480-72"
 mode "640x480-72"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 33068 4294967256 24 17 0 216 3
     timings 33068 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "640x480-75"
 mode "640x480-75"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 31746 4294967256 24 17 0 216 3
     timings 31746 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "640x480-80"
 mode "640x480-80"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 29761 4294967256 24 17 0 216 3
     timings 29761 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "640x480-85"
 mode "640x480-85"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 28011 4294967256 24 17 0 216 3
     timings 28011 4294967256 24 17 0 216 3
 endmode
 endmode
 
 
 mode "800x600-50"
 mode "800x600-50"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 30303 96 24 14 0 136 11
     timings 30303 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "800x600-60"
 mode "800x600-60"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 25252 96 24 14 0 136 11
     timings 25252 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "800x600-70"
 mode "800x600-70"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 21645 96 24 14 0 136 11
     timings 21645 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "800x600-72"
 mode "800x600-72"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 21043 96 24 14 0 136 11
     timings 21043 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "800x600-75"
 mode "800x600-75"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 20202 96 24 14 0 136 11
     timings 20202 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "800x600-80"
 mode "800x600-80"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 18939 96 24 14 0 136 11
     timings 18939 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "800x600-85"
 mode "800x600-85"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 17825 96 24 14 0 136 11
     timings 17825 96 24 14 0 136 11
 endmode
 endmode
 
 
 mode "1024x768-50"
 mode "1024x768-50"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 19054 144 24 29 0 120 3
     timings 19054 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1024x768-60"
 mode "1024x768-60"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 15880 144 24 29 0 120 3
     timings 15880 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1024x768-70"
 mode "1024x768-70"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 13610 144 24 29 0 120 3
     timings 13610 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1024x768-72"
 mode "1024x768-72"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 13232 144 24 29 0 120 3
     timings 13232 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1024x768-75"
 mode "1024x768-75"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 12703 144 24 29 0 120 3
     timings 12703 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1024x768-80"
 mode "1024x768-80"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 11910 144 24 29 0 120 3
     timings 11910 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1024x768-85"
 mode "1024x768-85"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 11209 144 24 29 0 120 3
     timings 11209 144 24 29 0 120 3
 endmode
 endmode
 
 
 mode "1280x1024-50"
 mode "1280x1024-50"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 11114 232 16 39 0 160 3
     timings 11114 232 16 39 0 160 3
 endmode
 endmode
 
 
 mode "1280x1024-60"
 mode "1280x1024-60"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 9262 232 16 39 0 160 3
     timings 9262 232 16 39 0 160 3
 endmode
 endmode
 
 
 mode "1280x1024-70"
 mode "1280x1024-70"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 7939 232 16 39 0 160 3
     timings 7939 232 16 39 0 160 3
 endmode
 endmode
 
 
 mode "1280x1024-72"
 mode "1280x1024-72"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 7719 232 16 39 0 160 3
     timings 7719 232 16 39 0 160 3
 endmode
 endmode
 
 
 mode "1280x1024-75"
 mode "1280x1024-75"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 7410 232 16 39 0 160 3
     timings 7410 232 16 39 0 160 3
 endmode
 endmode
 
 
 mode "1280x1024-80"
 mode "1280x1024-80"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 6946 232 16 39 0 160 3
     timings 6946 232 16 39 0 160 3
 endmode
 endmode
 
 
 mode "1280x1024-85"
 mode "1280x1024-85"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 6538 232 16 39 0 160 3
     timings 6538 232 16 39 0 160 3
 endmode
 endmode
-

+ 0 - 1
Documentation/fb/cyblafb/performance

@@ -77,4 +77,3 @@ patch that speeds up kernel bitblitting a lot ( > 20%).
 |	    |		      | 		|		  |
 |	    |		      | 		|		  |
 |	    |		      | 		|		  |
 |	    |		      | 		|		  |
 +-----------+-----------------+-----------------+-----------------+
 +-----------+-----------------+-----------------+-----------------+
-

+ 2 - 3
Documentation/fb/cyblafb/todo

@@ -22,11 +22,10 @@ accelerated color blitting	Who needs it? The console driver does use color
 				everything else is done using color expanding
 				everything else is done using color expanding
 				blitting of 1bpp character bitmaps.
 				blitting of 1bpp character bitmaps.
 
 
-xpanning			Who needs it?
-
 ioctls				Who needs it?
 ioctls				Who needs it?
 
 
-TV-out				Will be done later
+TV-out				Will be done later. Use "vga= " at boot time
+				to set a suitable video mode.
 
 
 ???				Feel free to contact me if you have any
 ???				Feel free to contact me if you have any
 				feature requests
 				feature requests

+ 22 - 11
Documentation/fb/cyblafb/usage

@@ -40,6 +40,16 @@ Selecting Modes
 	None of the modes possible to select as startup modes are affected by
 	None of the modes possible to select as startup modes are affected by
 	the problems described at the end of the next subsection.
 	the problems described at the end of the next subsection.
 
 
+	For all startup modes cyblafb chooses a virtual x resolution of 2048,
+	the only exception is mode 1280x1024 in combination with 32 bpp. This
+	allows ywrap scrolling for all those modes if rotation is 0 or 2, and
+	also fast scrolling if rotation is 1 or 3. The default virtual y reso-
+	lution is 4096 for bpp == 8, 2048 for bpp==16 and 1024 for bpp == 32,
+	again with the only exception of 1280x1024 at 32 bpp.
+
+	Please do set your video memory size to 8 Mb in the Bios setup. Other
+	values will work, but performace is decreased for a lot of modes.
+
 	Mode changes using fbset
 	Mode changes using fbset
 	========================
 	========================
 
 
@@ -54,20 +64,26 @@ Selecting Modes
 		- if a flat panel is found, cyblafb does not allow you
 		- if a flat panel is found, cyblafb does not allow you
 		  to program a resolution higher than the physical
 		  to program a resolution higher than the physical
 		  resolution of the flat panel monitor
 		  resolution of the flat panel monitor
-		- cyblafb does not allow xres to differ from xres_virtual
 		- cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp
 		- cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp
 		  and (currently) 24 bit modes use a doubled vclk internally,
 		  and (currently) 24 bit modes use a doubled vclk internally,
 		  the dotclock limit as seen by fbset is 115 MHz for those
 		  the dotclock limit as seen by fbset is 115 MHz for those
 		  modes and 230 MHz for 8 and 16 bpp modes.
 		  modes and 230 MHz for 8 and 16 bpp modes.
+		- cyblafb will allow you to select very high resolutions as
+		  long as the hardware can be programmed to these modes. The
+		  documented limit 1600x1200 is not enforced, but don't expect
+		  perfect signal quality.
 
 
-	Any request that violates the rules given above will be ignored and
-	fbset will return an error.
+	Any request that violates the rules given above will be either changed
+	to something the hardware supports or an error value will be returned.
 
 
 	If you program a virtual y resolution higher than the hardware limit,
 	If you program a virtual y resolution higher than the hardware limit,
 	cyblafb will silently decrease that value to the highest possible
 	cyblafb will silently decrease that value to the highest possible
-	value.
+	value. The same is true for a virtual x resolution that is not
+	supported by the hardware. Cyblafb tries to adapt vyres first because
+	vxres decides if ywrap scrolling is possible or not.
 
 
-	Attempts to disable acceleration are ignored.
+	Attempts to disable acceleration are ignored, I believe that this is
+	safe.
 
 
 	Some video modes that should work do not work as expected. If you use
 	Some video modes that should work do not work as expected. If you use
 	the standard fb.modes, fbset 640x480-60 will program that mode, but
 	the standard fb.modes, fbset 640x480-60 will program that mode, but
@@ -129,10 +145,6 @@ mode		640x480 or 800x600 or 1024x768 or 1280x1024
 verbosity	0 is the default, increase to at least 2 for every
 verbosity	0 is the default, increase to at least 2 for every
 		bug report!
 		bug report!
 
 
-vesafb		allows cyblafb to be loaded after vesafb has been
-		loaded. See sections "Module unloading ...".
-
-
 Development hints
 Development hints
 =================
 =================
 
 
@@ -195,7 +207,7 @@ a graphics mode.
 After booting, load cyblafb without any mode and bpp parameter and assign
 After booting, load cyblafb without any mode and bpp parameter and assign
 cyblafb to individual ttys using con2fb, e.g.:
 cyblafb to individual ttys using con2fb, e.g.:
 
 
-	modprobe cyblafb vesafb=1
+	modprobe cyblafb
 	con2fb /dev/fb1 /dev/tty1
 	con2fb /dev/fb1 /dev/tty1
 
 
 Unloading cyblafb works without problems after you assign vesafb to all
 Unloading cyblafb works without problems after you assign vesafb to all
@@ -203,4 +215,3 @@ ttys again, e.g.:
 
 
 	con2fb /dev/fb0 /dev/tty1
 	con2fb /dev/fb0 /dev/tty1
 	rmmod cyblafb
 	rmmod cyblafb
-

+ 29 - 0
Documentation/fb/cyblafb/whatsnew

@@ -0,0 +1,29 @@
+0.62
+====
+
+      - the vesafb parameter has been removed as I decided to allow the
+      	feature without any special parameter.
+
+      - Cyblafb does not use the vga style of panning any longer, now the
+      	"right view" register in the graphics engine IO space is used. Without
+	that change it was impossible to use all available memory, and without
+	access to all available memory it is impossible to ywrap.
+
+      - The imageblit function now uses hardware acceleration for all font
+        widths. Hardware blitting across pixel column 2048 is broken in the
+	cyberblade/i1 graphics core, but we work around that hardware bug.
+
+      - modes with vxres != xres are supported now.
+
+      - ywrap scrolling is supported now and the default. This is a big
+        performance gain.
+
+      - default video modes use vyres > yres and vxres > xres to allow
+        almost optimal scrolling speed for normal and rotated screens
+
+      - some features mainly usefull for debugging the upper layers of the
+        framebuffer system have been added, have a look at the code
+
+      - fixed: Oops after unloading cyblafb when reading /proc/io*
+
+      - we work around some bugs of the higher framebuffer layers.

+ 1 - 1
drivers/video/Kconfig

@@ -1151,7 +1151,7 @@ config FB_VOODOO1
 
 
 config FB_CYBLA
 config FB_CYBLA
 	tristate "Cyberblade/i1 support"
 	tristate "Cyberblade/i1 support"
-	depends on FB && PCI
+	depends on FB && PCI && X86_32 && !64BIT
 	select FB_CFB_IMAGEBLIT
 	select FB_CFB_IMAGEBLIT
 	select VIDEO_SELECT
 	select VIDEO_SELECT
 	---help---
 	---help---

+ 874 - 649
drivers/video/cyblafb.c

@@ -7,11 +7,12 @@
  *	tridentfb.c by Jani Monoses
  *	tridentfb.c by Jani Monoses
  *	see files above for further credits
  *	see files above for further credits
  *
  *
- * TODO:
- *
  */
  */
 
 
 #define CYBLAFB_DEBUG 0
 #define CYBLAFB_DEBUG 0
+#define CYBLAFB_KD_GRAPHICS_QUIRK 1
+
+#define CYBLAFB_PIXMAPSIZE 8192
 
 
 #include <linux/config.h>
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/module.h>
@@ -22,7 +23,7 @@
 #include <asm/types.h>
 #include <asm/types.h>
 #include <video/cyblafb.h>
 #include <video/cyblafb.h>
 
 
-#define VERSION "0.54"
+#define VERSION "0.62"
 
 
 struct cyblafb_par {
 struct cyblafb_par {
 	u32 pseudo_pal[16];
 	u32 pseudo_pal[16];
@@ -32,7 +33,9 @@ struct cyblafb_par {
 static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
 static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
 	.id = "CyBla",
 	.id = "CyBla",
 	.type = FB_TYPE_PACKED_PIXELS,
 	.type = FB_TYPE_PACKED_PIXELS,
+	.xpanstep = 1,
 	.ypanstep = 1,
 	.ypanstep = 1,
+	.ywrapstep = 1,
 	.visual = FB_VISUAL_PSEUDOCOLOR,
 	.visual = FB_VISUAL_PSEUDOCOLOR,
 	.accel = FB_ACCEL_NONE,
 	.accel = FB_ACCEL_NONE,
 };
 };
@@ -43,8 +46,9 @@ static int ref __devinitdata = 75;
 static int fp __devinitdata;
 static int fp __devinitdata;
 static int crt __devinitdata;
 static int crt __devinitdata;
 static int memsize __devinitdata;
 static int memsize __devinitdata;
-static int vesafb __devinitdata;
 
 
+static int basestride;
+static int vesafb;
 static int nativex;
 static int nativex;
 static int center;
 static int center;
 static int stretch;
 static int stretch;
@@ -52,26 +56,50 @@ static int pciwb = 1;
 static int pcirb = 1;
 static int pcirb = 1;
 static int pciwr = 1;
 static int pciwr = 1;
 static int pcirr = 1;
 static int pcirr = 1;
+static int disabled;
 static int verbosity;
 static int verbosity;
 static int displaytype;
 static int displaytype;
 
 
-static void __iomem * io_virt; // iospace virtual memory address
-
-module_param(mode,charp,0);
-module_param(bpp,int,0);
-module_param(ref,int,0);
-module_param(fp,int,0);
-module_param(crt,int,0);
-module_param(nativex,int,0);
-module_param(center,int,0);
-module_param(stretch,int,0);
-module_param(pciwb,int,0);
-module_param(pcirb,int,0);
-module_param(pciwr,int,0);
-module_param(pcirr,int,0);
-module_param(memsize,int,0);
-module_param(verbosity,int,0);
-module_param(vesafb,int,0);
+static void __iomem *io_virt;	// iospace virtual memory address
+
+module_param(mode, charp, 0);
+module_param(bpp, int, 0);
+module_param(ref, int, 0);
+module_param(fp, int, 0);
+module_param(crt, int, 0);
+module_param(nativex, int, 0);
+module_param(center, int, 0);
+module_param(stretch, int, 0);
+module_param(pciwb, int, 0);
+module_param(pcirb, int, 0);
+module_param(pciwr, int, 0);
+module_param(pcirr, int, 0);
+module_param(memsize, int, 0);
+module_param(verbosity, int, 0);
+
+//=========================================
+//
+// Well, we have to fix the upper layers.
+// Until this has been done, we work around
+// the bugs.
+//
+//=========================================
+
+#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG)
+	if (disabled) { \
+		printk("********\n");\
+		dump_stack();\
+		return val;\
+	}
+
+#elif CYBLAFB_KD_GRAPHICS_QUIRK
+#define KD_GRAPHICS_RETURN(val)\
+	if (disabled) {\
+		return val;\
+	}
+#else
+#define KD_GRAPHICS_RETURN(val)
+#endif
 
 
 //=========================================
 //=========================================
 //
 //
@@ -79,10 +107,10 @@ module_param(vesafb,int,0);
 //
 //
 //=========================================
 //=========================================
 
 
-#define out8(r,v) writeb(v,io_virt+r)
-#define out32(r,v) writel(v,io_virt+r)
-#define in8(r) readb(io_virt+r)
-#define in32(r) readl(io_virt+r)
+#define out8(r, v) writeb(v, io_virt + r)
+#define out32(r, v) writel(v, io_virt + r)
+#define in8(r) readb(io_virt + r)
+#define in32(r) readl(io_virt + r)
 
 
 //======================================
 //======================================
 //
 //
@@ -90,47 +118,47 @@ module_param(vesafb,int,0);
 //
 //
 //======================================
 //======================================
 
 
-static inline unsigned char read3X4(int reg)
+static inline u8 read3X4(u32 reg)
 {
 {
-	out8(0x3D4,reg);
+	out8(0x3D4, reg);
 	return in8(0x3D5);
 	return in8(0x3D5);
 }
 }
 
 
-static inline unsigned char read3C4(int reg)
+static inline u8 read3C4(u32 reg)
 {
 {
-	out8(0x3C4,reg);
+	out8(0x3C4, reg);
 	return in8(0x3C5);
 	return in8(0x3C5);
 }
 }
 
 
-static inline unsigned char read3CE(int reg)
+static inline u8 read3CE(u32 reg)
 {
 {
-	out8(0x3CE,reg);
+	out8(0x3CE, reg);
 	return in8(0x3CF);
 	return in8(0x3CF);
 }
 }
 
 
-static inline void write3X4(int reg,unsigned char val)
+static inline void write3X4(u32 reg, u8 val)
 {
 {
-	out8(0x3D4,reg);
-	out8(0x3D5,val);
+	out8(0x3D4, reg);
+	out8(0x3D5, val);
 }
 }
 
 
-static inline void write3C4(int reg,unsigned char val)
+static inline void write3C4(u32 reg, u8 val)
 {
 {
-	out8(0x3C4,reg);
-	out8(0x3C5,val);
+	out8(0x3C4, reg);
+	out8(0x3C5, val);
 }
 }
 
 
-static inline void write3CE(int reg,unsigned char val)
+static inline void write3CE(u32 reg, u8 val)
 {
 {
-	out8(0x3CE,reg);
-	out8(0x3CF,val);
+	out8(0x3CE, reg);
+	out8(0x3CF, val);
 }
 }
 
 
-static inline void write3C0(int reg,unsigned char val)
+static inline void write3C0(u32 reg, u8 val)
 {
 {
-	in8(0x3DA);	// read to reset index
-	out8(0x3C0,reg);
-	out8(0x3C0,val);
+	in8(0x3DA);		// read to reset index
+	out8(0x3C0, reg);
+	out8(0x3C0, val);
 }
 }
 
 
 //=================================================
 //=================================================
@@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val)
 //
 //
 //=================================================
 //=================================================
 
 
-static inline void enable_mmio(void)
+static void enable_mmio(void)
 {
 {
-	int tmp;
+	u8 tmp;
 
 
-	outb(0x0B,0x3C4);
+	outb(0x0B, 0x3C4);
 	inb(0x3C5);		// Set NEW mode
 	inb(0x3C5);		// Set NEW mode
-	outb(SR0E,0x3C4);	// write enable a lot of extended ports
-	outb(0x80,0x3C5);
+	outb(SR0E, 0x3C4);	// write enable a lot of extended ports
+	outb(0x80, 0x3C5);
 
 
-	outb(SR11,0x3C4);	// write enable those extended ports that
-	outb(0x87,0x3C5);	// are not affected by SR0E_New
+	outb(SR11, 0x3C4);	// write enable those extended ports that
+	outb(0x87, 0x3C5);	// are not affected by SR0E_New
 
 
-	outb(CR1E,0x3d4);	// clear write protect bit for port 0x3c2
-	tmp=inb(0x3d5) & 0xBF;
-	outb(CR1E,0x3d4);
-	outb(tmp,0x3d5);
+	outb(CR1E, 0x3d4);	// clear write protect bit for port 0x3c2
+	tmp = inb(0x3d5) & 0xBF;
+	outb(CR1E, 0x3d4);
+	outb(tmp, 0x3d5);
 
 
-	outb(CR39,0x3D4);
-	outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched
+	outb(CR39, 0x3D4);
+	outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio
 }
 }
 
 
 //=================================================
 //=================================================
 //
 //
 // Set pixel clock VCLK1
 // Set pixel clock VCLK1
-//   - multipliers set elswhere
-//   - freq in units of 0.01 MHz
+// - multipliers set elswhere
+// - freq in units of 0.01 MHz
+//
+// Hardware bug: SR18 >= 250 is broken for the
+//		 cyberblade/i1
 //
 //
 //=================================================
 //=================================================
 
 
 static void set_vclk(struct cyblafb_par *par, int freq)
 static void set_vclk(struct cyblafb_par *par, int freq)
 {
 {
-	u32 m,n,k;
-	int f,fi,d,di;
-	u8 lo=0,hi=0;
+	u32 m, n, k;
+	int f, fi, d, di;
+	u8 lo = 0, hi = 0;
 
 
 	d = 2000;
 	d = 2000;
 	k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
 	k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
-	for(m = 0;m<64;m++)
-	for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 !
-		fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12);
-		if ((di = abs(fi - freq)) < d) {
-			d = di;
-			f = fi;
-			lo = (u8) n;
-			hi = (u8) ((k<<6) | m);
+	for (m = 0; m < 64; m++)
+		for (n = 0; n < 250; n++) {
+			fi = (int)(((5864727 * (n + 8)) /
+				    ((m + 2) * (1 << k))) >> 12);
+			if ((di = abs(fi - freq)) < d) {
+				d = di;
+				f = fi;
+				lo = (u8) n;
+				hi = (u8) ((k << 6) | m);
+			}
 		}
 		}
-	}
-	write3C4(SR19,hi);
-	write3C4(SR18,lo);
-	if(verbosity > 1)
+	write3C4(SR19, hi);
+	write3C4(SR18, lo);
+	if (verbosity > 0)
 		output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
 		output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
-		freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+		       freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo);
 }
 }
 
 
 //================================================
 //================================================
@@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq)
 //
 //
 //================================================
 //================================================
 
 
-static void cyblafb_setup_GE(int pitch,int bpp)
+static void cyblafb_setup_GE(int pitch, int bpp)
 {
 {
-	int base = (pitch>>3)<<20;
+	KD_GRAPHICS_RETURN();
 
 
 	switch (bpp) {
 	switch (bpp) {
-		case  8: base |= (0<<29); break;
-		case 15: base |= (5<<29); break;
-		case 16: base |= (1<<29); break;
-		case 24:
-		case 32: base |= (2<<29); break;
+	case 8:
+		basestride = ((pitch >> 3) << 20) | (0 << 29);
+		break;
+	case 15:
+		basestride = ((pitch >> 3) << 20) | (5 << 29);
+		break;
+	case 16:
+		basestride = ((pitch >> 3) << 20) | (1 << 29);
+		break;
+	case 24:
+	case 32:
+		basestride = ((pitch >> 3) << 20) | (2 << 29);
+		break;
 	}
 	}
 
 
-	write3X4(CR36,0x90);	// reset GE
-	write3X4(CR36,0x80);	// enable GE
-
-	out32(GE24,1<<7);	// reset all GE pointers
-	out32(GE24,0);
-
-	write3X4(CR2D,0x00);	// GE Timinigs, no delays
-
-	out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133
-	out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133
-	out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133
-	out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133
-	out32(GEC8,base); // Source Stride / Buffer Base 0, p 133
-	out32(GECC,base); // Source Stride / Buffer Base 1, p 133
-	out32(GED0,base); // Source Stride / Buffer Base 2, p 133
-	out32(GED4,base); // Source Stride / Buffer Base 3, p 133
-	out32(GE6C,0);	  // Pattern and Style, p 129, ok
+	write3X4(CR36, 0x90);	// reset GE
+	write3X4(CR36, 0x80);	// enable GE
+	out32(GE24, 1 << 7);	// reset all GE pointers by toggling
+	out32(GE24, 0); 	//   d7 of GE24
+	write3X4(CR2D, 0x00);	// GE Timinigs, no delays
+	out32(GE6C, 0); 	// Pattern and Style, p 129, ok
 }
 }
 
 
 //=====================================================================
 //=====================================================================
 //
 //
-// Although this is a .fb_sync function that could be enabled in
-// cyblafb_ops, we do not include it there. We sync immediately before
-// new GE operations to improve performance.
+// Cyberblade specific syncing
+//
+//   A timeout might be caused by disabled mmio.
+//   Cause:
+//     - bit CR39 & 1 == 0 upon return, X trident driver bug
+//     - kdm bug (KD_GRAPHICS not set on first switch)
+//     - kernel design flaw (it believes in the correctness
+//	 of kdm/X
+//   First we try to sync ignoring that problem, as most of the
+//   time that will succeed immediately and the enable_mmio()
+//   would only degrade performance.
 //
 //
 //=====================================================================
 //=====================================================================
 
 
 static int cyblafb_sync(struct fb_info *info)
 static int cyblafb_sync(struct fb_info *info)
 {
 {
-	int status, i=100000;
-	while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+	u32 status, i = 100000;
+
+	KD_GRAPHICS_RETURN(0);
+
+	while (((status = in32(GE20)) & 0xFe800000) && i != 0)
 		i--;
 		i--;
 
 
 	if (i == 0) {
 	if (i == 0) {
-		// The timeout might be caused by disabled mmio.
-		// Cause:
-		//   - bit CR39 & 1 == 0 upon return, X trident driver bug
-		//   - kdm bug (KD_GRAPHICS not set on first switch)
-		//   - kernel design flaw (it believes in the correctness
-		//     of kdm/X
-		// So we make sure that mmio is enabled first ...
 		enable_mmio();
 		enable_mmio();
-//		show_trace(NULL,&status);
-		i=1000000;
-		while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+		i = 1000000;
+		while (((status = in32(GE20)) & 0xFA800000) && i != 0)
 			i--;
 			i--;
 		if (i == 0) {
 		if (i == 0) {
-			output("GE Timeout, status: %x\n",status);
-			if(status & 0x80000000)
+			output("GE Timeout, status: %x\n", status);
+			if (status & 0x80000000)
 				output("Bresenham Engine : Busy\n");
 				output("Bresenham Engine : Busy\n");
-			if(status & 0x40000000)
+			if (status & 0x40000000)
 				output("Setup Engine     : Busy\n");
 				output("Setup Engine     : Busy\n");
-			if(status & 0x20000000)
+			if (status & 0x20000000)
 				output("SP / DPE         : Busy\n");
 				output("SP / DPE         : Busy\n");
-			if(status & 0x10000000)
+			if (status & 0x10000000)
 				output("Memory Interface : Busy\n");
 				output("Memory Interface : Busy\n");
-			if(status & 0x08000000)
+			if (status & 0x08000000)
 				output("Com Lst Proc     : Busy\n");
 				output("Com Lst Proc     : Busy\n");
-			if(status & 0x04000000)
+			if (status & 0x04000000)
 				output("Block Write      : Busy\n");
 				output("Block Write      : Busy\n");
-			if(status & 0x02000000)
+			if (status & 0x02000000)
 				output("Command Buffer   : Full\n");
 				output("Command Buffer   : Full\n");
-			if(status & 0x01000000)
+			if (status & 0x01000000)
 				output("RESERVED         : Busy\n");
 				output("RESERVED         : Busy\n");
-			if(status & 0x00800000)
+			if (status & 0x00800000)
 				output("PCI Write Buffer : Busy\n");
 				output("PCI Write Buffer : Busy\n");
 			cyblafb_setup_GE(info->var.xres,
 			cyblafb_setup_GE(info->var.xres,
 					 info->var.bits_per_pixel);
 					 info->var.bits_per_pixel);
@@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info)
 //
 //
 //==============================
 //==============================
 
 
-static void cyblafb_fillrect(struct fb_info * info,
-			     const struct fb_fillrect *fr)
+static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr)
 {
 {
-	int bpp = info->var.bits_per_pixel;
-	int col;
+	u32 bpp = info->var.bits_per_pixel, col, desty, height;
+
+	KD_GRAPHICS_RETURN();
 
 
 	switch (bpp) {
 	switch (bpp) {
-		default:
-		case 8: col = fr->color;
-			col |= col <<8;
-			col |= col <<16;
-			break;
-		case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
-			 col |= col <<16;
-			 break;
-		case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
-			 break;
+	default:
+	case 8:
+		col = fr->color;
+		col |= col << 8;
+		col |= col << 16;
+		break;
+	case 16:
+		col = ((u32 *) (info->pseudo_palette))[fr->color];
+		col |= col << 16;
+		break;
+	case 32:
+		col = ((u32 *) (info->pseudo_palette))[fr->color];
+		break;
 	}
 	}
 
 
-	cyblafb_sync(info);
-
-	out32(GE60,col);
-	out32(GE48,fr->rop ? 0x66:ROP_S);
-	out32(GE44,0x20000000|1<<19|1<<4|2<<2);
-	out32(GE08,point(fr->dx,fr->dy));
-	out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1));
-
+	desty = fr->dy;
+	height = fr->height;
+	while (height) {
+		out32(GEB8, basestride | ((desty * info->var.xres_virtual *
+					   bpp) >> 6));
+		out32(GE60, col);
+		out32(GE48, fr->rop ? 0x66 : ROP_S);
+		out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+		out32(GE08, point(fr->dx, 0));
+		out32(GE0C, point(fr->dx + fr->width - 1,
+				  height > 4096 ? 4095 : height - 1));
+		if (likely(height <= 4096))
+			return;
+		desty += 4096;
+		height -= 4096;
+	}
 }
 }
 
 
-//==============================
+//================================================
 //
 //
 // Cyberblade specific copyarea
 // Cyberblade specific copyarea
 //
 //
-//==============================
+// This function silently assumes that it never
+// will be called with width or height exceeding
+// 4096.
+//
+//================================================
 
 
-static void cyblafb_copyarea(struct fb_info *info,
-			     const struct fb_copyarea *ca)
+static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
 {
 {
-	__u32 s1,s2,d1,d2;
-	int direction;
+	u32 s1, s2, d1, d2, direction;
+
+	KD_GRAPHICS_RETURN();
+
+	s1 = point(ca->sx, 0);
+	s2 = point(ca->sx + ca->width - 1, ca->height - 1);
+	d1 = point(ca->dx, 0);
+	d2 = point(ca->dx + ca->width - 1, ca->height - 1);
 
 
-	s1 = point(ca->sx,ca->sy);
-	s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1);
-	d1 = point(ca->dx,ca->dy);
-	d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1);
 	if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
 	if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
 		direction = 0;
 		direction = 0;
 	else
 	else
 		direction = 2;
 		direction = 2;
 
 
-	cyblafb_sync(info);
-
-	out32(GE44,0xa0000000|1<<19|1<<2|direction);
-	out32(GE00,direction?s2:s1);
-	out32(GE04,direction?s1:s2);
-	out32(GE08,direction?d2:d1);
-	out32(GE0C,direction?d1:d2);
-
+	out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual *
+				   info->var.bits_per_pixel) >> 6));
+	out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual *
+				   info->var.bits_per_pixel) >> 6));
+	out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction);
+	out32(GE00, direction ? s2 : s1);
+	out32(GE04, direction ? s1 : s2);
+	out32(GE08, direction ? d2 : d1);
+	out32(GE0C, direction ? d1 : d2);
 }
 }
 
 
 //=======================================================================
 //=======================================================================
 //
 //
 // Cyberblade specific imageblit
 // Cyberblade specific imageblit
 //
 //
-// Accelerated for the most usual case, blitting 1-bit deep character
-// character images. Everything else is passed to the generic imageblit.
+// Accelerated for the most usual case, blitting 1 - bit deep
+// character images. Everything else is passed to the generic imageblit
+// unless it is so insane that it is better to printk an alert.
+//
+// Hardware bug: _Never_ blit across pixel column 2048, that will lock
+// the system. We split those blit requests into three blitting
+// operations.
 //
 //
 //=======================================================================
 //=======================================================================
 
 
 static void cyblafb_imageblit(struct fb_info *info,
 static void cyblafb_imageblit(struct fb_info *info,
 			      const struct fb_image *image)
 			      const struct fb_image *image)
 {
 {
-
 	u32 fgcol, bgcol;
 	u32 fgcol, bgcol;
+	u32 *pd = (u32 *) image->data;
+	u32 bpp = info->var.bits_per_pixel;
 
 
-	int i;
-	int bpp = info->var.bits_per_pixel;
-	int index = 0;
-	int index_end=image->height * image->width / 8;
-	int width_dds=image->width / 32;
-	int width_dbs=image->width % 32;
-
-	if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 ||
-	    image->width % 8 != 0 || image->width == 0 || image->height == 0) {
-		cfb_imageblit(info,image);
+	KD_GRAPHICS_RETURN();
+
+	// Used only for drawing the penguine (image->depth > 1)
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+	// That should never happen, but it would be fatal
+	if (image->width == 0 || image->height == 0) {
+		output("imageblit: width/height 0 detected\n");
 		return;
 		return;
 	}
 	}
 
 
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		fgcol = ((u32*)(info->pseudo_palette))[image->fg_color];
-		bgcol = ((u32*)(info->pseudo_palette))[image->bg_color];
+		fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color];
+		bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color];
 	} else {
 	} else {
 		fgcol = image->fg_color;
 		fgcol = image->fg_color;
 		bgcol = image->bg_color;
 		bgcol = image->bg_color;
 	}
 	}
 
 
 	switch (bpp) {
 	switch (bpp) {
-		case 8:
-			fgcol |= fgcol <<8; fgcol |= fgcol <<16;
-			bgcol |= bgcol <<8; bgcol |= bgcol <<16;
-			break;
-		case 16:
-			fgcol |= fgcol <<16;
-			bgcol |= bgcol <<16;
-			break;
-		default:
-			 break;
+	case 8:
+		fgcol |= fgcol << 8;
+		bgcol |= bgcol << 8;
+	case 16:
+		fgcol |= fgcol << 16;
+		bgcol |= bgcol << 16;
+	default:
+		break;
 	}
 	}
 
 
-	cyblafb_sync(info);
-
-	out32(GE60,fgcol);
-	out32(GE64,bgcol);
-	out32(GE44,0xa0000000 | 1<<20 | 1<<19);
-	out32(GE08,point(image->dx,image->dy));
-	out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1));
+	out32(GEB8, basestride | ((image->dy * info->var.xres_virtual *
+				   bpp) >> 6));
+	out32(GE60, fgcol);
+	out32(GE64, bgcol);
+
+	if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) {
+		u32 dds = ((image->width + 31) >> 5) * image->height;
+		out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+		out32(GE08, point(image->dx, 0));
+		out32(GE0C, point(image->dx + image->width - 1,
+				  image->height - 1));
+		while (dds--)
+			out32(GE9C, *pd++);
+	} else {
+		int i, j;
+		u32 ddstotal = (image->width + 31) >> 5;
+		u32 ddsleft = (2048 - image->dx + 31) >> 5;
+		u32 skipleft = ddstotal - ddsleft;
+
+		out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+		out32(GE08, point(image->dx, 0));
+		out32(GE0C, point(2048 - 1, image->height - 1));
+		for (i = 0; i < image->height; i++) {
+			for (j = 0; j < ddsleft; j++)
+				out32(GE9C, *pd++);
+			pd += skipleft;
+		}
 
 
-	while(index < index_end) {
-		const char *p = image->data + index;
-		for(i=0;i<width_dds;i++) {
-			out32(GE9C,*(u32*)p);
-			p+=4;
-			index+=4;
+		if (image->dx % 32) {
+			out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+			out32(GE08, point(2048, 0));
+			if (image->width > ddsleft << 5)
+				out32(GE0C, point(image->dx + (ddsleft << 5) -
+						  1, image->height - 1));
+			else
+				out32(GE0C, point(image->dx + image->width - 1,
+						  image->height - 1));
+			pd = ((u32 *) image->data) + ddstotal - skipleft - 1;
+			for (i = 0; i < image->height; i++) {
+				out32(GE9C, swab32(swab32(*pd) << ((32 -
+					    (image->dx & 31)) & 31)));
+				pd += ddstotal;
+			}
 		}
 		}
-		switch(width_dbs) {
-		case 0: break;
-		case 8:	out32(GE9C,*(u8*)p);
-			index+=1;
-			break;
-		case 16: out32(GE9C,*(u16*)p);
-			index+=2;
-			break;
-		case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16);
-			index+=3;
-			break;
+
+		if (skipleft) {
+			out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+			out32(GE08, point(image->dx + (ddsleft << 5), 0));
+			out32(GE0C, point(image->dx + image->width - 1,
+					  image->height - 1));
+			pd = (u32 *) image->data;
+			for (i = 0; i < image->height; i++) {
+				pd += ddsleft;
+				for (j = 0; j < skipleft; j++)
+					out32(GE9C, *pd++);
+			}
 		}
 		}
 	}
 	}
 }
 }
@@ -443,7 +526,6 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 			     struct fb_info *info)
 			     struct fb_info *info)
 {
 {
 	int bpp = var->bits_per_pixel;
 	int bpp = var->bits_per_pixel;
-	int s,t,maxvyres;
 
 
 	//
 	//
 	// we try to support 8, 16, 24 and 32 bpp modes,
 	// we try to support 8, 16, 24 and 32 bpp modes,
@@ -453,9 +535,9 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 	// (This is what tridentfb does ... will be changed in the future)
 	// (This is what tridentfb does ... will be changed in the future)
 	//
 	//
 	//
 	//
-	if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+	if (bpp % 8 != 0 || bpp < 8 || bpp > 32)
 		bpp = 8;
 		bpp = 8;
-	if (bpp == 24 )
+	if (bpp == 24)
 		bpp = var->bits_per_pixel = 32;
 		bpp = var->bits_per_pixel = 32;
 
 
 	//
 	//
@@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 		return -EINVAL;
 		return -EINVAL;
 
 
 	//
 	//
-	// xres != xres_virtual is broken, fail if such an
-	// unusual mode is requested
+	// we do not allow vclk to exceed 230 MHz. If the requested
+	// vclk is too high, we default to 200 MHz
 	//
 	//
-	if (var->xres != var->xres_virtual)
-		return -EINVAL;
+	if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000)
+		var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000;
 
 
 	//
 	//
-	// we do not allow vclk to exceed 230 MHz
+	// enforce (h|v)sync_len limits
 	//
 	//
-	if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
-		return -EINVAL;
+	var->hsync_len &= ~7;
+	if(var->hsync_len > 248)
+		var->hsync_len = 248;
+
+	var->vsync_len &= 15;
 
 
 	//
 	//
-	// calc max yres_virtual that would fit in memory
-	// and max yres_virtual that could be used for scrolling
-	// and use minimum of the results as maxvyres
-	//
-	// adjust vyres_virtual to maxvyres if necessary
-	// fail if requested yres is bigger than maxvyres
+	// Enforce horizontal and vertical hardware limits.
+	// 1600x1200 is mentioned as a maximum, but higher resolutions could
+	// work with slow refresh, small margins and short sync.
 	//
 	//
-	s = (0x1fffff / (var->xres * bpp/8)) + var->yres;
-	t = info->fix.smem_len / (var->xres * bpp/8);
-	maxvyres = t < s ? t : s;
-	if (maxvyres < var->yres_virtual)
-		var->yres_virtual=maxvyres;
-	if (maxvyres < var->yres)
+	var->xres &= ~7;
+
+	if (((var->xres + var->left_margin + var->right_margin +
+			var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||
+			((var->yres + var->upper_margin + var->lower_margin +
+			var->vsync_len) > 2047))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	switch (bpp) {
-		case 8:
-			var->red.offset = 0;
-			var->green.offset = 0;
-			var->blue.offset = 0;
-			var->red.length = 6;
-			var->green.length = 6;
-			var->blue.length = 6;
-			break;
-		case 16:
-			var->red.offset = 11;
-			var->green.offset = 5;
-			var->blue.offset = 0;
-			var->red.length = 5;
-			var->green.length = 6;
-			var->blue.length = 5;
-			break;
-		case 32:
-			var->red.offset = 16;
-			var->green.offset = 8;
-			var->blue.offset = 0;
-			var->red.length = 8;
-			var->green.length = 8;
-			var->blue.length = 8;
-			break;
-		default:
+	if ((var->xres > 1600) || (var->yres > 1200))
+		output("Mode %dx%d exceeds documented limits.\n",
+					   var->xres, var->yres);
+	//
+	// try to be smart about (x|y)res_virtual problems.
+	//
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	if (bpp == 8 || bpp == 16) {
+		if (var->xres_virtual > 4088)
+			var->xres_virtual = 4088;
+	} else {
+		if (var->xres_virtual > 2040)
+			var->xres_virtual = 2040;
+	}
+	var->xres_virtual &= ~7;
+	while (var->xres_virtual * var->yres_virtual * bpp / 8 >
+	       info->fix.smem_len) {
+		if (var->yres_virtual > var->yres)
+			var->yres_virtual--;
+		else if (var->xres_virtual > var->xres)
+			var->xres_virtual -= 8;
+		else
 			return -EINVAL;
 			return -EINVAL;
 	}
 	}
 
 
-	return 0;
+	switch (bpp) {
+	case 8:
+		var->red.offset = 0;
+		var->green.offset = 0;
+		var->blue.offset = 0;
+		var->red.length = 6;
+		var->green.length = 6;
+		var->blue.length = 6;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 
+	return 0;
 }
 }
 
 
 //=====================================================================
 //=====================================================================
@@ -543,23 +653,25 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 // it, so it is also safe to be used here. BTW: datasheet CR0E on page
 // it, so it is also safe to be used here. BTW: datasheet CR0E on page
 // 90 really is CR1E, the real CRE is documented on page 72.
 // 90 really is CR1E, the real CRE is documented on page 72.
 //
 //
+// BUT:
+//
+// As of internal version 0.60 we do not use vga panning any longer.
+// Vga panning did not allow us the use of all available video memory
+// and thus prevented ywrap scrolling. We do use the "right view"
+// register now.
+//
+//
 //=====================================================================
 //=====================================================================
 
 
 static int cyblafb_pan_display(struct fb_var_screeninfo *var,
 static int cyblafb_pan_display(struct fb_var_screeninfo *var,
 			       struct fb_info *info)
 			       struct fb_info *info)
 {
 {
-	unsigned int offset;
+	KD_GRAPHICS_RETURN(0);
 
 
-	offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32;
 	info->var.xoffset = var->xoffset;
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
 	info->var.yoffset = var->yoffset;
-
-	write3X4(CR0D,offset & 0xFF);
-	write3X4(CR0C,(offset & 0xFF00) >> 8);
-	write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11));
-	write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17));
-	write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15));
-
+	out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *
+		    var->xres_virtual)) * var->bits_per_pixel / 32));
 	return 0;
 	return 0;
 }
 }
 
 
@@ -578,56 +690,96 @@ static void regdump(struct cyblafb_par *par)
 		return;
 		return;
 
 
 	printk("\n");
 	printk("\n");
-	for(i=0; i<=0xff; i++) {
-		outb(i,0x3d4);
-		printk("CR%02x=%02x ",i,inb(0x3d5));
-		if (i%16==15)
+	for (i = 0; i <= 0xff; i++) {
+		outb(i, 0x3d4);
+		printk("CR%02x=%02x ", i, inb(0x3d5));
+		if (i % 16 == 15)
 			printk("\n");
 			printk("\n");
 	}
 	}
 
 
-	outb(0x30,0x3ce);
-	outb(inb(0x3cf) | 0x40,0x3cf);
-	for(i=0; i<=0x1f; i++) {
-		if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) {
-			outb(i,0x3d4);
-			printk("CR%02x=%02x ",i,inb(0x3d5));
+	outb(0x30, 0x3ce);
+	outb(inb(0x3cf) | 0x40, 0x3cf);
+	for (i = 0; i <= 0x1f; i++) {
+		if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11
+		    || i == 0x16) {
+			outb(i, 0x3d4);
+			printk("CR%02x=%02x ", i, inb(0x3d5));
 		} else
 		} else
 			printk("------- ");
 			printk("------- ");
-		if (i%16==15)
+		if (i % 16 == 15)
 			printk("\n");
 			printk("\n");
 	}
 	}
-	outb(0x30,0x3ce);
-	outb(inb(0x3cf) & 0xbf,0x3cf);
+	outb(0x30, 0x3ce);
+	outb(inb(0x3cf) & 0xbf, 0x3cf);
 
 
 	printk("\n");
 	printk("\n");
-	for(i=0; i<=0x7f; i++) {
-		outb(i,0x3ce);
-		printk("GR%02x=%02x ",i,inb(0x3cf));
-		if (i%16==15)
+	for (i = 0; i <= 0x7f; i++) {
+		outb(i, 0x3ce);
+		printk("GR%02x=%02x ", i, inb(0x3cf));
+		if (i % 16 == 15)
 			printk("\n");
 			printk("\n");
 	}
 	}
 
 
 	printk("\n");
 	printk("\n");
-	for(i=0; i<=0xff; i++) {
-		outb(i,0x3c4);
-		printk("SR%02x=%02x ",i,inb(0x3c5));
-		if (i%16==15)
+	for (i = 0; i <= 0xff; i++) {
+		outb(i, 0x3c4);
+		printk("SR%02x=%02x ", i, inb(0x3c5));
+		if (i % 16 == 15)
 			printk("\n");
 			printk("\n");
 	}
 	}
 
 
 	printk("\n");
 	printk("\n");
-	for(i=0; i <= 0x1F; i++) {
-		inb(0x3da); // next access is index!
-		outb(i,0x3c0);
-		printk("AR%02x=%02x ",i,inb(0x3c1));
-		if (i%16==15)
+	for (i = 0; i <= 0x1F; i++) {
+		inb(0x3da);	// next access is index!
+		outb(i, 0x3c0);
+		printk("AR%02x=%02x ", i, inb(0x3c1));
+		if (i % 16 == 15)
 			printk("\n");
 			printk("\n");
 	}
 	}
 	printk("\n");
 	printk("\n");
 
 
-	inb(0x3DA);			// reset internal flag to 3c0 index
-	outb(0x20,0x3C0);		// enable attr
+	inb(0x3DA);		// reset internal flag to 3c0 index
+	outb(0x20, 0x3C0);	// enable attr
+
+	return;
+}
+
+//=======================================================================
+//
+// Save State
+//
+// This function is called while a switch to KD_TEXT is in progress,
+// before any of the other functions are called.
+//
+//=======================================================================
 
 
+static void cyblafb_save_state(struct fb_info *info)
+{
+	struct cyblafb_par *par = info->par;
+	if (verbosity > 0)
+		output("Switching to KD_TEXT\n");
+	disabled = 0;
+	regdump(par);
+	enable_mmio();
+	return;
+}
+
+//=======================================================================
+//
+// Restore State
+//
+// This function is called while a switch to KD_GRAPHICS is in progress,
+// We have to turn on vga style panning registers again because the
+// trident driver of X does not know about GE10.
+//
+//=======================================================================
+
+static void cyblafb_restore_state(struct fb_info *info)
+{
+	if (verbosity > 0)
+		output("Switching to KD_GRAPHICS\n");
+	out32(GE10, 0);
+	disabled = 1;
 	return;
 	return;
 }
 }
 
 
@@ -640,32 +792,34 @@ static void regdump(struct cyblafb_par *par)
 static int cyblafb_set_par(struct fb_info *info)
 static int cyblafb_set_par(struct fb_info *info)
 {
 {
 	struct cyblafb_par *par = info->par;
 	struct cyblafb_par *par = info->par;
-	u32
-	htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch,
-		vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend;
+	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart,
+	    hblankend, preendfetch, vtotal, vdispend, vsyncstart,
+	    vsyncend, vblankstart, vblankend;
 	struct fb_var_screeninfo *var = &info->var;
 	struct fb_var_screeninfo *var = &info->var;
 	int bpp = var->bits_per_pixel;
 	int bpp = var->bits_per_pixel;
 	int i;
 	int i;
 
 
+	KD_GRAPHICS_RETURN(0);
+
 	if (verbosity > 0)
 	if (verbosity > 0)
 		output("Switching to new mode: "
 		output("Switching to new mode: "
 		       "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
 		       "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
-			var->xres,var->yres,var->xres_virtual,
-			var->yres_virtual,var->bits_per_pixel,var->pixclock,
-			var->left_margin,var->right_margin,var->upper_margin,
-			var->lower_margin,var->hsync_len,var->vsync_len);
+		       var->xres, var->yres, var->xres_virtual,
+		       var->yres_virtual, var->bits_per_pixel, var->pixclock,
+		       var->left_margin, var->right_margin, var->upper_margin,
+		       var->lower_margin, var->hsync_len, var->vsync_len);
 
 
 	htotal = (var->xres + var->left_margin + var->right_margin +
 	htotal = (var->xres + var->left_margin + var->right_margin +
-						 var->hsync_len) / 8 - 5;
-	hdispend = var->xres/8 - 1;
-	hsyncstart = (var->xres + var->right_margin)/8;
-	hsyncend = var->hsync_len/8;
+		  var->hsync_len) / 8 - 5;
+	hdispend = var->xres / 8 - 1;
+	hsyncstart = (var->xres + var->right_margin) / 8;
+	hsyncend = var->hsync_len / 8;
 	hblankstart = hdispend + 1;
 	hblankstart = hdispend + 1;
 	hblankend = htotal + 3; // should be htotal + 5, bios does it this way
 	hblankend = htotal + 3; // should be htotal + 5, bios does it this way
-	preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3);
+	preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);
 
 
 	vtotal = var->yres + var->upper_margin + var->lower_margin +
 	vtotal = var->yres + var->upper_margin + var->lower_margin +
-						 var->vsync_len - 2;
+							var->vsync_len - 2;
 	vdispend = var->yres - 1;
 	vdispend = var->yres - 1;
 	vsyncstart = var->yres + var->lower_margin;
 	vsyncstart = var->yres + var->lower_margin;
 	vblankstart = var->yres;
 	vblankstart = var->yres;
@@ -674,101 +828,99 @@ static int cyblafb_set_par(struct fb_info *info)
 
 
 	enable_mmio();		// necessary! ... check X ...
 	enable_mmio();		// necessary! ... check X ...
 
 
-	write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+	write3X4(CR11, read3X4(CR11) & 0x7F);	// unlock cr00 .. cr07
 
 
-	write3CE(GR30,8);
+	write3CE(GR30, 8);
 
 
 	if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
 	if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
 
 
 		// stretch or center ?
 		// stretch or center ?
 
 
-		out8(0x3C2,0xEB);
+		out8(0x3C2, 0xEB);
 
 
-		write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+		write3CE(GR30, read3CE(GR30) | 0x81);	// shadow mode on
 
 
 		if (center) {
 		if (center) {
-			write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80);
-			write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80);
-		}
-		else if (stretch) {
-			write3CE(GR5D,0);
-			write3CE(GR52,(read3CE(GR52) & 0x7C) | 1);
-			write3CE(GR53,(read3CE(GR53) & 0x7C) | 1);
+			write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80);
+			write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80);
+		} else if (stretch) {
+			write3CE(GR5D, 0);
+			write3CE(GR52, (read3CE(GR52) & 0x7C) | 1);
+			write3CE(GR53, (read3CE(GR53) & 0x7C) | 1);
 		}
 		}
 
 
 	} else {
 	} else {
-		out8(0x3C2,0x2B);
-		write3CE(GR30,8);
+		out8(0x3C2, 0x2B);
+		write3CE(GR30, 8);
 	}
 	}
 
 
 	//
 	//
 	// Setup CRxx regs
 	// Setup CRxx regs
 	//
 	//
 
 
-	write3X4(CR00,htotal & 0xFF);
-	write3X4(CR01,hdispend & 0xFF);
-	write3X4(CR02,hblankstart & 0xFF);
-	write3X4(CR03,hblankend & 0x1F);
-	write3X4(CR04,hsyncstart & 0xFF);
-	write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2));
-	write3X4(CR06,vtotal & 0xFF);
-	write3X4(CR07,(vtotal & 0x100) >> 8 |
-		      (vdispend & 0x100) >> 7 |
-		      (vsyncstart & 0x100) >> 6 |
-		      (vblankstart & 0x100) >> 5 |
-		      0x10 |
-		      (vtotal & 0x200) >> 4 |
-		      (vdispend & 0x200) >> 3 |
-		      (vsyncstart & 0x200) >> 2);
-	write3X4(CR08,0);
-	write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 |  // FIX !!!
-		      ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
-	write3X4(CR0A,0);  // Init to some reasonable default
-	write3X4(CR0B,0);  // Init to some reasonable default
-	write3X4(CR0C,0);  // Offset 0
-	write3X4(CR0D,0);  // Offset 0
-	write3X4(CR0E,0);  // Init to some reasonable default
-	write3X4(CR0F,0);  // Init to some reasonable default
-	write3X4(CR10,vsyncstart & 0xFF);
-	write3X4(CR11,(vsyncend & 0x0F));
-	write3X4(CR12,vdispend & 0xFF);
-	write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF);
-	write3X4(CR14,0x40);  // double word mode
-	write3X4(CR15,vblankstart & 0xFF);
-	write3X4(CR16,vblankend & 0xFF);
-	write3X4(CR17,0xC3);
-	write3X4(CR18,0xFF);
+	write3X4(CR00, htotal & 0xFF);
+	write3X4(CR01, hdispend & 0xFF);
+	write3X4(CR02, hblankstart & 0xFF);
+	write3X4(CR03, hblankend & 0x1F);
+	write3X4(CR04, hsyncstart & 0xFF);
+	write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
+	write3X4(CR06, vtotal & 0xFF);
+	write3X4(CR07, (vtotal & 0x100) >> 8 |
+		       (vdispend & 0x100) >> 7 |
+		       (vsyncstart & 0x100) >> 6 |
+		       (vblankstart & 0x100) >> 5 |
+		       0x10 |
+		       (vtotal & 0x200) >> 4 |
+		       (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2);
+	write3X4(CR08, 0);
+	write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 |	// FIX !!!
+		       ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
+	write3X4(CR0A, 0);	// Init to some reasonable default
+	write3X4(CR0B, 0);	// Init to some reasonable default
+	write3X4(CR0C, 0);	// Offset 0
+	write3X4(CR0D, 0);	// Offset 0
+	write3X4(CR0E, 0);	// Init to some reasonable default
+	write3X4(CR0F, 0);	// Init to some reasonable default
+	write3X4(CR10, vsyncstart & 0xFF);
+	write3X4(CR11, (vsyncend & 0x0F));
+	write3X4(CR12, vdispend & 0xFF);
+	write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF);
+	write3X4(CR14, 0x40);	// double word mode
+	write3X4(CR15, vblankstart & 0xFF);
+	write3X4(CR16, vblankend & 0xFF);
+	write3X4(CR17, 0xE3);
+	write3X4(CR18, 0xFF);
 	//	 CR19: needed for interlaced modes ... ignore it for now
 	//	 CR19: needed for interlaced modes ... ignore it for now
-	write3X4(CR1A,0x07); // Arbitration Control Counter 1
-	write3X4(CR1B,0x07); // Arbitration Control Counter 2
-	write3X4(CR1C,0x07); // Arbitration Control Counter 3
-	write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-)
-	write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
+	write3X4(CR1A, 0x07);	// Arbitration Control Counter 1
+	write3X4(CR1B, 0x07);	// Arbitration Control Counter 2
+	write3X4(CR1C, 0x07);	// Arbitration Control Counter 3
+	write3X4(CR1D, 0x00);	// Don't know, doesn't hurt ; -)
+	write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
 	//	 CR1F: do not set, contains BIOS info about memsize
 	//	 CR1F: do not set, contains BIOS info about memsize
-	write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode
-	write3X4(CR21,0x20); // enable linear memory access
+	write3X4(CR20, 0x20);	// enabe wr buf, disable 16bit planar mode
+	write3X4(CR21, 0x20);	// enable linear memory access
 	//	 CR22: RO cpu latch readback
 	//	 CR22: RO cpu latch readback
 	//	 CR23: ???
 	//	 CR23: ???
 	//	 CR24: RO AR flag state
 	//	 CR24: RO AR flag state
 	//	 CR25: RAMDAC rw timing, pclk buffer tristate control ????
 	//	 CR25: RAMDAC rw timing, pclk buffer tristate control ????
 	//	 CR26: ???
 	//	 CR26: ???
-	write3X4(CR27,(vdispend & 0x400) >> 6 |
-		      (vsyncstart & 0x400) >> 5 |
-		      (vblankstart & 0x400) >> 4 |
-		      (vtotal & 0x400) >> 3 |
-		      0x8);
+	write3X4(CR27, (vdispend & 0x400) >> 6 |
+		       (vsyncstart & 0x400) >> 5 |
+		       (vblankstart & 0x400) >> 4 |
+		       (vtotal & 0x400) >> 3 |
+		       0x8);
 	//	 CR28: ???
 	//	 CR28: ???
-	write3X4(CR29,(read3X4(CR29) & 0xCF) |
-		      ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4));
-	write3X4(CR2A,read3X4(CR2A) | 0x40);
-	write3X4(CR2B,(htotal & 0x100) >> 8 |
-		      (hdispend & 0x100) >> 7 |
-		      // (0x00 & 0x100) >> 6 |	 hinterlace para bit 8 ???
-		      (hsyncstart & 0x100) >> 5 |
-		      (hblankstart & 0x100) >> 4);
+	write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *
+			bpp) / (4 * 16)) & 0x300) >> 4));
+	write3X4(CR2A, read3X4(CR2A) | 0x40);
+	write3X4(CR2B, (htotal & 0x100) >> 8 |
+		       (hdispend & 0x100) >> 7 |
+		       // (0x00 & 0x100) >> 6 |   hinterlace para bit 8 ???
+		       (hsyncstart & 0x100) >> 5 |
+		       (hblankstart & 0x100) >> 4);
 	//	 CR2C: ???
 	//	 CR2C: ???
 	//	 CR2D: initialized in cyblafb_setup_GE()
 	//	 CR2D: initialized in cyblafb_setup_GE()
-	write3X4(CR2F,0x92); // conservative, better signal quality
+	write3X4(CR2F, 0x92);	// conservative, better signal quality
 	//	 CR30: reserved
 	//	 CR30: reserved
 	//	 CR31: reserved
 	//	 CR31: reserved
 	//	 CR32: reserved
 	//	 CR32: reserved
@@ -777,96 +929,116 @@ static int cyblafb_set_par(struct fb_info *info)
 	//	 CR35: disabled in CR36
 	//	 CR35: disabled in CR36
 	//	 CR36: initialized in cyblafb_setup_GE
 	//	 CR36: initialized in cyblafb_setup_GE
 	//	 CR37: i2c, ignore for now
 	//	 CR37: i2c, ignore for now
-	write3X4(CR38,(bpp == 8) ? 0x00 :	//
-		      (bpp == 16) ? 0x05 :	// highcolor
-		      (bpp == 24) ? 0x29 :	// packed 24bit truecolor
-		      (bpp == 32) ? 0x09 : 0);	// truecolor, 16 bit pixelbus
-	write3X4(CR39,0x01 |			// MMIO enable
-		      (pcirb ? 0x02 : 0) | // pci read burst enable
-		      (pciwb ? 0x04 : 0)); // pci write burst enable
-	write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase
-		      (pcirr ? 0x40 : 0) | // pci read retry enable
-		      (pciwr ? 0x80 : 0)); // pci write retry enable
-	write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0);
-	write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
-	write3X4(CR58,0x82);	// Bios does this .... don't know more
+	write3X4(CR38, (bpp == 8) ? 0x00 :	//
+		       (bpp == 16) ? 0x05 :	// highcolor
+		       (bpp == 24) ? 0x29 :	// packed 24bit truecolor
+		       (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus
+	write3X4(CR39, 0x01 |	// MMIO enable
+		       (pcirb ? 0x02 : 0) |	// pci read burst enable
+		       (pciwb ? 0x04 : 0));	// pci write burst enable
+	write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase
+		       (pcirr ? 0x40 : 0) |	// pci read retry enable
+		       (pciwr ? 0x80 : 0));	// pci write retry enable
+	write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2
+					    : 0);
+	write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
+	write3X4(CR58, 0x82);	// Bios does this .... don't know more
 	//
 	//
 	// Setup SRxx regs
 	// Setup SRxx regs
 	//
 	//
-	write3C4(SR00,3);
-	write3C4(SR01,1);	//set char clock 8 dots wide
-	write3C4(SR02,0x0F);	//enable 4 maps needed in chain4 mode
-	write3C4(SR03,0);	//no character map select
-	write3C4(SR04,0x0E);	//memory mode: ext mem, even, chain4
+	write3C4(SR00, 3);
+	write3C4(SR01, 1);	//set char clock 8 dots wide
+	write3C4(SR02, 0x0F);	//enable 4 maps needed in chain4 mode
+	write3C4(SR03, 0);	//no character map select
+	write3C4(SR04, 0x0E);	//memory mode: ext mem, even, chain4
 
 
-	out8(0x3C4,0x0b);
+	out8(0x3C4, 0x0b);
 	in8(0x3C5);		// Set NEW mode
 	in8(0x3C5);		// Set NEW mode
-	write3C4(SR0D,0x00);	// test ... check
+	write3C4(SR0D, 0x00);	// test ... check
 
 
-	set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
-		 info->var.pixclock); //SR18,SR19
+	set_vclk(par, (bpp == 32 ? 200000000 : 100000000)
+					/ info->var.pixclock);	//SR18, SR19
 
 
 	//
 	//
 	// Setup GRxx regs
 	// Setup GRxx regs
 	//
 	//
-	write3CE(GR00,0x00);	// test ... check
-	write3CE(GR01,0x00);	// test ... check
-	write3CE(GR02,0x00);	// test ... check
-	write3CE(GR03,0x00);	// test ... check
-	write3CE(GR04,0x00);	// test ... check
-	write3CE(GR05,0x40);	// no CGA compat,allow 256 col
-	write3CE(GR06,0x05);	// graphics mode
-	write3CE(GR07,0x0F);	// planes?
-	write3CE(GR08,0xFF);	// test ... check
-	write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4
-	write3CE(GR20,0xC0);	// test ... check
-	write3CE(GR2F,0xA0);	// PCLK = VCLK, no skew,
+	write3CE(GR00, 0x00);	// test ... check
+	write3CE(GR01, 0x00);	// test ... check
+	write3CE(GR02, 0x00);	// test ... check
+	write3CE(GR03, 0x00);	// test ... check
+	write3CE(GR04, 0x00);	// test ... check
+	write3CE(GR05, 0x40);	// no CGA compat, allow 256 col
+	write3CE(GR06, 0x05);	// graphics mode
+	write3CE(GR07, 0x0F);	// planes?
+	write3CE(GR08, 0xFF);	// test ... check
+	write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4
+	write3CE(GR20, 0xC0);	// test ... check
+	write3CE(GR2F, 0xA0);	// PCLK = VCLK, no skew,
 
 
 	//
 	//
 	// Setup ARxx regs
 	// Setup ARxx regs
 	//
 	//
-	for(i = 0;i < 0x10;i++) // set AR00 .. AR0f
-		write3C0(i,i);
-	write3C0(AR10,0x41);	// graphics mode and support 256 color modes
-	write3C0(AR12,0x0F);	// planes
-	write3C0(AR13,0);	// horizontal pel panning
+	for (i = 0; i < 0x10; i++)	// set AR00 .. AR0f
+		write3C0(i, i);
+	write3C0(AR10, 0x41);	// graphics mode and support 256 color modes
+	write3C0(AR12, 0x0F);	// planes
+	write3C0(AR13, 0);	// horizontal pel panning
 	in8(0x3DA);		// reset internal flag to 3c0 index
 	in8(0x3DA);		// reset internal flag to 3c0 index
-	out8(0x3C0,0x20);	// enable attr
+	out8(0x3C0, 0x20);	// enable attr
 
 
 	//
 	//
 	// Setup hidden RAMDAC command register
 	// Setup hidden RAMDAC command register
 	//
 	//
-	in8(0x3C8);  // these reads are
-	in8(0x3C6);  // necessary to
-	in8(0x3C6);  // unmask the RAMDAC
-	in8(0x3C6);  // command reg, otherwise
-	in8(0x3C6);  // we would write the pixelmask reg!
-	out8(0x3C6,(bpp ==  8) ? 0x00 : 	// 256 colors
-		   (bpp == 15) ? 0x10 : 	//
-		   (bpp == 16) ? 0x30 : 	// hicolor
-		   (bpp == 24) ? 0xD0 : 	// truecolor
-		   (bpp == 32) ? 0xD0 : 0);	// truecolor
+	in8(0x3C8);		// these reads are
+	in8(0x3C6);		// necessary to
+	in8(0x3C6);		// unmask the RAMDAC
+	in8(0x3C6);		// command reg, otherwise
+	in8(0x3C6);		// we would write the pixelmask reg!
+	out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors
+	     (bpp == 15) ? 0x10 :	//
+	     (bpp == 16) ? 0x30 :	// hicolor
+	     (bpp == 24) ? 0xD0 :	// truecolor
+	     (bpp == 32) ? 0xD0 : 0);	// truecolor
 	in8(0x3C8);
 	in8(0x3C8);
 
 
 	//
 	//
 	// GR31 is not mentioned in the datasheet
 	// GR31 is not mentioned in the datasheet
 	//
 	//
 	if (displaytype == DISPLAY_FP)
 	if (displaytype == DISPLAY_FP)
-		write3CE(GR31,(read3CE(GR31) & 0x8F) |
+		write3CE(GR31, (read3CE(GR31) & 0x8F) |
 			 ((info->var.yres > 1024) ? 0x50 :
 			 ((info->var.yres > 1024) ? 0x50 :
-			 (info->var.yres >   768) ? 0x30 :
-			 (info->var.yres >   600) ? 0x20 :
-			 (info->var.yres >   480) ? 0x10 : 0));
+			  (info->var.yres > 768) ? 0x30 :
+			  (info->var.yres > 600) ? 0x20 :
+			  (info->var.yres > 480) ? 0x10 : 0));
 
 
 	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
 	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
 				      : FB_VISUAL_TRUECOLOR;
 				      : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = info->var.xres * (bpp >> 3);
-	info->cmap.len = (bpp == 8) ? 256: 16;
+	info->fix.line_length = info->var.xres_virtual * (bpp >> 3);
+	info->cmap.len = (bpp == 8) ? 256 : 16;
 
 
 	//
 	//
 	// init acceleration engine
 	// init acceleration engine
 	//
 	//
-	cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+	cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);
+
+	//
+	// Set/clear flags to allow proper scroll mode selection.
+	//
+	if (var->xres == var->xres_virtual)
+		info->flags &= ~FBINFO_HWACCEL_XPAN;
+	else
+		info->flags |= FBINFO_HWACCEL_XPAN;
+
+	if (var->yres == var->yres_virtual)
+		info->flags &= ~FBINFO_HWACCEL_YPAN;
+	else
+		info->flags |= FBINFO_HWACCEL_YPAN;
+
+	if (info->fix.smem_len !=
+	    var->xres_virtual * var->yres_virtual * bpp / 8)
+		info->flags &= ~FBINFO_HWACCEL_YWRAP;
+	else
+		info->flags |= FBINFO_HWACCEL_YWRAP;
 
 
 	regdump(par);
 	regdump(par);
 
 
@@ -885,27 +1057,27 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 {
 {
 	int bpp = info->var.bits_per_pixel;
 	int bpp = info->var.bits_per_pixel;
 
 
+	KD_GRAPHICS_RETURN(0);
+
 	if (regno >= info->cmap.len)
 	if (regno >= info->cmap.len)
 		return 1;
 		return 1;
 
 
 	if (bpp == 8) {
 	if (bpp == 8) {
-		out8(0x3C6,0xFF);
-		out8(0x3C8,regno);
-		out8(0x3C9,red>>10);
-		out8(0x3C9,green>>10);
-		out8(0x3C9,blue>>10);
-
-	} else if (bpp == 16)				// RGB 565
-		((u32*)info->pseudo_palette)[regno] =
-			(red & 0xF800) |
-			((green & 0xFC00) >> 5) |
-			((blue & 0xF800) >> 11);
-	else if (bpp == 32)				// ARGB 8888
-		((u32*)info->pseudo_palette)[regno] =
-			((transp & 0xFF00) <<16) |
-			((red & 0xFF00) << 8) |
-			((green & 0xFF00)) |
-			((blue & 0xFF00)>>8);
+		out8(0x3C6, 0xFF);
+		out8(0x3C8, regno);
+		out8(0x3C9, red >> 10);
+		out8(0x3C9, green >> 10);
+		out8(0x3C9, blue >> 10);
+
+	} else if (bpp == 16)	// RGB 565
+		((u32 *) info->pseudo_palette)[regno] =
+		    (red & 0xF800) |
+		    ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+	else if (bpp == 32)	// ARGB 8888
+		((u32 *) info->pseudo_palette)[regno] =
+		    ((transp & 0xFF00) << 16) |
+		    ((red & 0xFF00) << 8) |
+		    ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -918,40 +1090,41 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
 
 static int cyblafb_blank(int blank_mode, struct fb_info *info)
 static int cyblafb_blank(int blank_mode, struct fb_info *info)
 {
 {
-	unsigned char PMCont,DPMSCont;
+	unsigned char PMCont, DPMSCont;
+
+	KD_GRAPHICS_RETURN(0);
 
 
 	if (displaytype == DISPLAY_FP)
 	if (displaytype == DISPLAY_FP)
 		return 0;
 		return 0;
 
 
-	out8(0x83C8,0x04); 		// DPMS Control
+	out8(0x83C8, 0x04);	// DPMS Control
 	PMCont = in8(0x83C6) & 0xFC;
 	PMCont = in8(0x83C6) & 0xFC;
 
 
 	DPMSCont = read3CE(GR23) & 0xFC;
 	DPMSCont = read3CE(GR23) & 0xFC;
 
 
-	switch (blank_mode)
-	{
-	case FB_BLANK_UNBLANK:       // Screen: On, HSync: On, VSync: On
-	case FB_BLANK_NORMAL:	     // Screen: Off, HSync: On, VSync: On
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:	// Screen: On, HSync: On, VSync: On
+	case FB_BLANK_NORMAL:	// Screen: Off, HSync: On, VSync: On
 		PMCont |= 0x03;
 		PMCont |= 0x03;
 		DPMSCont |= 0x00;
 		DPMSCont |= 0x00;
 		break;
 		break;
-	case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
+	case FB_BLANK_HSYNC_SUSPEND:	// Screen: Off, HSync: Off, VSync: On
 		PMCont |= 0x02;
 		PMCont |= 0x02;
 		DPMSCont |= 0x01;
 		DPMSCont |= 0x01;
 		break;
 		break;
-	case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
+	case FB_BLANK_VSYNC_SUSPEND:	// Screen: Off, HSync: On, VSync: Off
 		PMCont |= 0x02;
 		PMCont |= 0x02;
 		DPMSCont |= 0x02;
 		DPMSCont |= 0x02;
 		break;
 		break;
-	case FB_BLANK_POWERDOWN:     // Screen: Off, HSync: Off, VSync: Off
+	case FB_BLANK_POWERDOWN:	// Screen: Off, HSync: Off, VSync: Off
 		PMCont |= 0x00;
 		PMCont |= 0x00;
 		DPMSCont |= 0x03;
 		DPMSCont |= 0x03;
 		break;
 		break;
 	}
 	}
 
 
-	write3CE(GR23,DPMSCont);
-	out8(0x83C8,4);
-	out8(0x83C6,PMCont);
+	write3CE(GR23, DPMSCont);
+	out8(0x83C8, 4);
+	out8(0x83C6, PMCont);
 	//
 	//
 	// let fbcon do a softblank for us
 	// let fbcon do a softblank for us
 	//
 	//
@@ -959,15 +1132,18 @@ static int cyblafb_blank(int blank_mode, struct fb_info *info)
 }
 }
 
 
 static struct fb_ops cyblafb_ops __devinitdata = {
 static struct fb_ops cyblafb_ops __devinitdata = {
-	.owner	= THIS_MODULE,
+	.owner = THIS_MODULE,
 	.fb_setcolreg = cyblafb_setcolreg,
 	.fb_setcolreg = cyblafb_setcolreg,
 	.fb_pan_display = cyblafb_pan_display,
 	.fb_pan_display = cyblafb_pan_display,
 	.fb_blank = cyblafb_blank,
 	.fb_blank = cyblafb_blank,
 	.fb_check_var = cyblafb_check_var,
 	.fb_check_var = cyblafb_check_var,
 	.fb_set_par = cyblafb_set_par,
 	.fb_set_par = cyblafb_set_par,
 	.fb_fillrect = cyblafb_fillrect,
 	.fb_fillrect = cyblafb_fillrect,
-	.fb_copyarea= cyblafb_copyarea,
+	.fb_copyarea = cyblafb_copyarea,
 	.fb_imageblit = cyblafb_imageblit,
 	.fb_imageblit = cyblafb_imageblit,
+	.fb_sync = cyblafb_sync,
+	.fb_restore_state = cyblafb_restore_state,
+	.fb_save_state = cyblafb_save_state,
 };
 };
 
 
 //==========================================================================
 //==========================================================================
@@ -986,74 +1162,89 @@ static struct fb_ops cyblafb_ops __devinitdata = {
 
 
 static int __devinit getstartupmode(struct fb_info *info)
 static int __devinit getstartupmode(struct fb_info *info)
 {
 {
-	u32	htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,
-		vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend,
-		cr00,cr01,cr02,cr03,cr04,cr05,cr2b,
-		cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27,
-		cr38,
-		sr0d,sr18,sr19,
-		gr0f,
-		fi,pxclkdiv,vclkdiv,tmp,i;
+	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend,
+	    vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend,
+	    cr00, cr01, cr02, cr03, cr04, cr05, cr2b,
+	    cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27,
+	    cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i;
 
 
 	struct modus {
 	struct modus {
-		int xres; int yres; int vyres; int bpp; int pxclk;
-		int left_margin; int right_margin; int upper_margin;
-		int lower_margin; int hsync_len; int vsync_len;
-	}  modedb[5] = {
-		{   0,	  0, 8000, 0, 0,   0,  0,  0, 0,   0,  0},
-		{ 640,	480, 3756, 0, 0, -40, 24, 17, 0, 216,  3},
-		{ 800,	600, 3221, 0, 0,  96, 24, 14, 0, 136, 11},
-		{1024,	768, 2815, 0, 0, 144, 24, 29, 0, 120,  3},
-		{1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160,  3}
+		int xres; int vxres; int yres; int vyres;
+		int bpp; int pxclk;
+		int left_margin; int right_margin;
+		int upper_margin; int lower_margin;
+		int hsync_len; int vsync_len;
+	} modedb[5] = {
+		{
+		0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, {
+		640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, {
+		800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, {
+		1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, {
+		1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3}
 	};
 	};
 
 
-	outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5);
-	outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5);
-	outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5);
-	outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5);
-	outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5);
-	outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5);
-	outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5);
-	outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5);
-	outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5);
-	outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5);
-	outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf);
-
-	htotal	    = cr00 | (cr2b & 0x01) << 8;
-	hdispend    = cr01 | (cr2b & 0x02) << 7;
+	outb(0x00, 0x3d4); cr00 = inb(0x3d5);
+	outb(0x01, 0x3d4); cr01 = inb(0x3d5);
+	outb(0x02, 0x3d4); cr02 = inb(0x3d5);
+	outb(0x03, 0x3d4); cr03 = inb(0x3d5);
+	outb(0x04, 0x3d4); cr04 = inb(0x3d5);
+	outb(0x05, 0x3d4); cr05 = inb(0x3d5);
+	outb(0x06, 0x3d4); cr06 = inb(0x3d5);
+	outb(0x07, 0x3d4); cr07 = inb(0x3d5);
+	outb(0x09, 0x3d4); cr09 = inb(0x3d5);
+	outb(0x10, 0x3d4); cr10 = inb(0x3d5);
+	outb(0x11, 0x3d4); cr11 = inb(0x3d5);
+	outb(0x12, 0x3d4); cr12 = inb(0x3d5);
+	outb(0x15, 0x3d4); cr15 = inb(0x3d5);
+	outb(0x16, 0x3d4); cr16 = inb(0x3d5);
+	outb(0x27, 0x3d4); cr27 = inb(0x3d5);
+	outb(0x2b, 0x3d4); cr2b = inb(0x3d5);
+	outb(0x38, 0x3d4); cr38 = inb(0x3d5);
+
+	outb(0x0b, 0x3c4);
+	inb(0x3c5);
+
+	outb(0x0d, 0x3c4); sr0d = inb(0x3c5);
+	outb(0x18, 0x3c4); sr18 = inb(0x3c5);
+	outb(0x19, 0x3c4); sr19 = inb(0x3c5);
+	outb(0x0f, 0x3ce); gr0f = inb(0x3cf);
+
+	htotal = cr00 | (cr2b & 0x01) << 8;
+	hdispend = cr01 | (cr2b & 0x02) << 7;
 	hblankstart = cr02 | (cr2b & 0x10) << 4;
 	hblankstart = cr02 | (cr2b & 0x10) << 4;
-	hblankend   = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
-	hsyncstart  = cr04 | (cr2b & 0x08) << 5;
-	hsyncend    = cr05 & 0x1f;
+	hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
+	hsyncstart = cr04 | (cr2b & 0x08) << 5;
+	hsyncend = cr05 & 0x1f;
 
 
 	modedb[0].xres = hblankstart * 8;
 	modedb[0].xres = hblankstart * 8;
 	modedb[0].hsync_len = hsyncend * 8;
 	modedb[0].hsync_len = hsyncend * 8;
 	modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
 	modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
 	modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
 	modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
-		modedb[0].right_margin - modedb[0].hsync_len;
-
-	vtotal	    = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
-			   | (cr27 & 0x80) << 3;
-	vdispend    = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
-			   | (cr27 & 0x10) << 6;
-	vsyncstart  = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
-			   | (cr27 & 0x20) << 5;
-	vsyncend    = cr11 & 0x0f;
+	    modedb[0].right_margin - modedb[0].hsync_len;
+
+	vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
+	    | (cr27 & 0x80) << 3;
+	vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
+	    | (cr27 & 0x10) << 6;
+	vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
+	    | (cr27 & 0x20) << 5;
+	vsyncend = cr11 & 0x0f;
 	vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
 	vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
-			   | (cr27 & 0x40) << 4;
-	vblankend   = cr16;
+	    | (cr27 & 0x40) << 4;
+	vblankend = cr16;
 
 
-	modedb[0].yres	       = vdispend + 1;
-	modedb[0].vsync_len    = vsyncend;
+	modedb[0].yres = vdispend + 1;
+	modedb[0].vsync_len = vsyncend;
 	modedb[0].lower_margin = vsyncstart - modedb[0].yres;
 	modedb[0].lower_margin = vsyncstart - modedb[0].yres;
 	modedb[0].upper_margin = vtotal - modedb[0].yres -
 	modedb[0].upper_margin = vtotal - modedb[0].yres -
-		modedb[0].lower_margin - modedb[0].vsync_len + 2;
+	    modedb[0].lower_margin - modedb[0].vsync_len + 2;
 
 
 	tmp = cr38 & 0x3c;
 	tmp = cr38 & 0x3c;
 	modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
 	modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
-			tmp == 8 ? 32 : 8;
+	    tmp == 8 ? 32 : 8;
 
 
-	fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+	fi = ((5864727 * (sr18 + 8)) /
+	      (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12;
 	pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
 	pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
 	tmp = sr0d & 0x06;
 	tmp = sr0d & 0x06;
 	vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
 	vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
@@ -1062,10 +1253,10 @@ static int __devinit getstartupmode(struct fb_info *info)
 	if (verbosity > 0)
 	if (verbosity > 0)
 		output("detected startup mode: "
 		output("detected startup mode: "
 		       "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
 		       "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
-		       modedb[0].xres,modedb[0].yres,modedb[0].xres,
-		       modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin,
-		       modedb[0].right_margin,modedb[0].upper_margin,
-		       modedb[0].lower_margin,modedb[0].hsync_len,
+		       modedb[0].xres, modedb[0].yres, modedb[0].xres,
+		       modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin,
+		       modedb[0].right_margin, modedb[0].upper_margin,
+		       modedb[0].lower_margin, modedb[0].hsync_len,
 		       modedb[0].vsync_len);
 		       modedb[0].vsync_len);
 
 
 	//
 	//
@@ -1073,36 +1264,39 @@ static int __devinit getstartupmode(struct fb_info *info)
 	// do not want to do it in another way!
 	// do not want to do it in another way!
 	//
 	//
 
 
-	tryagain:
+      tryagain:
 
 
 	i = (mode == NULL) ? 0 :
 	i = (mode == NULL) ? 0 :
-	    !strncmp(mode,"640x480",7) ? 1 :
-	    !strncmp(mode,"800x600",7) ? 2 :
-	    !strncmp(mode,"1024x768",8) ? 3 :
-	    !strncmp(mode,"1280x1024",9) ? 4 : 0;
+	    !strncmp(mode, "640x480", 7) ? 1 :
+	    !strncmp(mode, "800x600", 7) ? 2 :
+	    !strncmp(mode, "1024x768", 8) ? 3 :
+	    !strncmp(mode, "1280x1024", 9) ? 4 : 0;
 
 
 	ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
 	ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
 
 
-	if(i==0) {
+	if (i == 0) {
 		info->var.pixclock = modedb[i].pxclk;
 		info->var.pixclock = modedb[i].pxclk;
 		info->var.bits_per_pixel = modedb[i].bpp;
 		info->var.bits_per_pixel = modedb[i].bpp;
 	} else {
 	} else {
 		info->var.pixclock = (100000000 /
 		info->var.pixclock = (100000000 /
-			((modedb[i].left_margin + modedb[i].xres +
-			  modedb[i].right_margin + modedb[i].hsync_len
-			 ) * (
-			  modedb[i].upper_margin + modedb[i].yres +
-			  modedb[i].lower_margin + modedb[i].vsync_len
-			 ) *
-			  ref / 10000
-			));
+				      ((modedb[i].left_margin +
+					modedb[i].xres +
+					modedb[i].right_margin +
+					modedb[i].hsync_len) *
+				       (modedb[i].upper_margin +
+					modedb[i].yres +
+					modedb[i].lower_margin +
+					modedb[i].vsync_len) * ref / 10000));
 		info->var.bits_per_pixel = bpp;
 		info->var.bits_per_pixel = bpp;
 	}
 	}
 
 
 	info->var.left_margin = modedb[i].left_margin;
 	info->var.left_margin = modedb[i].left_margin;
 	info->var.right_margin = modedb[i].right_margin;
 	info->var.right_margin = modedb[i].right_margin;
 	info->var.xres = modedb[i].xres;
 	info->var.xres = modedb[i].xres;
-	info->var.xres_virtual = modedb[i].xres;
+	if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32))
+		info->var.xres_virtual = modedb[i].vxres;
+	else
+		info->var.xres_virtual = modedb[i].xres;
 	info->var.xoffset = 0;
 	info->var.xoffset = 0;
 	info->var.hsync_len = modedb[i].hsync_len;
 	info->var.hsync_len = modedb[i].hsync_len;
 	info->var.upper_margin = modedb[i].upper_margin;
 	info->var.upper_margin = modedb[i].upper_margin;
@@ -1114,33 +1308,32 @@ static int __devinit getstartupmode(struct fb_info *info)
 	info->var.sync = 0;
 	info->var.sync = 0;
 	info->var.vmode = FB_VMODE_NONINTERLACED;
 	info->var.vmode = FB_VMODE_NONINTERLACED;
 
 
-	if(cyblafb_check_var(&info->var,info)) {
-		// 640x480-8@75 should really never fail. One case would
+	if (cyblafb_check_var(&info->var, info)) {
+		// 640x480 - 8@75 should really never fail. One case would
 		// be fp == 1 and nativex < 640 ... give up then
 		// be fp == 1 and nativex < 640 ... give up then
-		if(i==1 && bpp == 8 && ref == 75){
+		if (i == 1 && bpp == 8 && ref == 75) {
 			output("Can't find a valid mode :-(\n");
 			output("Can't find a valid mode :-(\n");
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 		// Our detected mode is unlikely to fail. If it does,
 		// Our detected mode is unlikely to fail. If it does,
-		// try 640x480-8@75 ...
-		if(i==0) {
-			mode="640x480";
-			bpp=8;
-			ref=75;
+		// try 640x480 - 8@75 ...
+		if (i == 0) {
+			mode = "640x480";
+			bpp = 8;
+			ref = 75;
 			output("Detected mode failed check_var! "
 			output("Detected mode failed check_var! "
-			       "Trying 640x480-8@75\n");
+			       "Trying 640x480 - 8@75\n");
 			goto tryagain;
 			goto tryagain;
 		}
 		}
 		// A specified video mode failed for some reason.
 		// A specified video mode failed for some reason.
 		// Try the startup mode first
 		// Try the startup mode first
 		output("Specified mode '%s' failed check! "
 		output("Specified mode '%s' failed check! "
-			"Falling back to startup mode.\n",mode);
-		mode=NULL;
+		       "Falling back to startup mode.\n", mode);
+		mode = NULL;
 		goto tryagain;
 		goto tryagain;
 	}
 	}
 
 
 	return 0;
 	return 0;
-
 }
 }
 
 
 //========================================================
 //========================================================
@@ -1160,21 +1353,28 @@ static unsigned int __devinit get_memsize(void)
 	else {
 	else {
 		tmp = read3X4(CR1F) & 0x0F;
 		tmp = read3X4(CR1F) & 0x0F;
 		switch (tmp) {
 		switch (tmp) {
-			case 0x03: k = 1 * Mb; break;
-			case 0x07: k = 2 * Mb; break;
-			case 0x0F: k = 4 * Mb; break;
-			case 0x04: k = 8 * Mb; break;
-			default:
-				k = 1 * Mb;
-				output("Unknown memory size code %x in CR1F."
-				       " We default to 1 Mb for now, please"
-				       " do provide a memsize parameter!\n",
-				       tmp);
+		case 0x03:
+			k = 1 * 1024 * 1024;
+			break;
+		case 0x07:
+			k = 2 * 1024 * 1024;
+			break;
+		case 0x0F:
+			k = 4 * 1024 * 1024;
+			break;
+		case 0x04:
+			k = 8 * 1024 * 1024;
+			break;
+		default:
+			k = 1 * 1024 * 1024;
+			output("Unknown memory size code %x in CR1F."
+			       " We default to 1 Mb for now, please"
+			       " do provide a memsize parameter!\n", tmp);
 		}
 		}
 	}
 	}
 
 
 	if (verbosity > 0)
 	if (verbosity > 0)
-		output("framebuffer size = %d Kb\n",k/Kb);
+		output("framebuffer size = %d Kb\n", k / Kb);
 	return k;
 	return k;
 }
 }
 
 
@@ -1192,7 +1392,7 @@ static unsigned int __devinit get_displaytype(void)
 		return DISPLAY_FP;
 		return DISPLAY_FP;
 	if (crt)
 	if (crt)
 		return DISPLAY_CRT;
 		return DISPLAY_CRT;
-	return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+	return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
 }
 }
 
 
 //=====================================
 //=====================================
@@ -1203,7 +1403,7 @@ static unsigned int __devinit get_displaytype(void)
 
 
 static int __devinit get_nativex(void)
 static int __devinit get_nativex(void)
 {
 {
-	int x,y,tmp;
+	int x, y, tmp;
 
 
 	if (nativex)
 	if (nativex)
 		return nativex;
 		return nativex;
@@ -1211,29 +1411,45 @@ static int __devinit get_nativex(void)
 	tmp = (read3CE(GR52) >> 4) & 3;
 	tmp = (read3CE(GR52) >> 4) & 3;
 
 
 	switch (tmp) {
 	switch (tmp) {
-		case 0:  x = 1280; y = 1024; break;
-		case 2:  x = 1024; y = 768;  break;
-		case 3:  x = 800;  y = 600;  break;
-		case 4:  x = 1400; y = 1050; break;
-		case 1:
-		default: x = 640;  y = 480;  break;
+	case 0: x = 1280; y = 1024;
+		break;
+	case 2: x = 1024; y = 768;
+		break;
+	case 3: x = 800;  y = 600;
+		break;
+	case 4: x = 1400; y = 1050;
+		break;
+	case 1:
+	default:
+		x = 640; y = 480;
+		break;
 	}
 	}
 
 
 	if (verbosity > 0)
 	if (verbosity > 0)
-		output("%dx%d flat panel found\n",x,y);
+		output("%dx%d flat panel found\n", x, y);
 	return x;
 	return x;
 }
 }
 
 
-static int __devinit cybla_pci_probe(struct pci_dev * dev,
-				     const struct pci_device_id * id)
+static int __devinit cybla_pci_probe(struct pci_dev *dev,
+				     const struct pci_device_id *id)
 {
 {
 	struct fb_info *info;
 	struct fb_info *info;
 	struct cyblafb_par *par;
 	struct cyblafb_par *par;
 
 
-	info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev);
-
+	info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev);
 	if (!info)
 	if (!info)
-		goto errout_alloc;
+		goto errout_alloc_info;
+
+	info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL);
+	if (!info->pixmap.addr) {
+		output("allocation of pixmap buffer failed!\n");
+		goto errout_alloc_pixmap;
+	}
+	info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4;
+	info->pixmap.buf_align = 4;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 4;
 
 
 	par = info->par;
 	par = info->par;
 	par->ops = cyblafb_ops;
 	par->ops = cyblafb_ops;
@@ -1246,26 +1462,31 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 		output("could not enable device!\n");
 		output("could not enable device!\n");
 		goto errout_enable;
 		goto errout_enable;
 	}
 	}
-
 	// might already be requested by vga console or vesafb,
 	// might already be requested by vga console or vesafb,
 	// so we do care about success
 	// so we do care about success
-	request_region(0x3c0,32,"cyblafb");
+	if (!request_region(0x3c0, 0x20, "cyblafb")) {
+		output("region 0x3c0/0x20 already reserved\n");
+		vesafb |= 1;
 
 
+	}
 	//
 	//
 	// Graphics Engine Registers
 	// Graphics Engine Registers
 	//
 	//
-	request_region(GEBase,0x100,"cyblafb");
+	if (!request_region(GEBase, 0x100, "cyblafb")) {
+		output("region %#x/0x100 already reserved\n", GEBase);
+		vesafb |= 2;
+	}
 
 
 	regdump(par);
 	regdump(par);
 
 
 	enable_mmio();
 	enable_mmio();
 
 
 	// setup MMIO region
 	// setup MMIO region
-	info->fix.mmio_start = pci_resource_start(dev,1);
+	info->fix.mmio_start = pci_resource_start(dev, 1);
 	info->fix.mmio_len = 0x20000;
 	info->fix.mmio_len = 0x20000;
 
 
 	if (!request_mem_region(info->fix.mmio_start,
 	if (!request_mem_region(info->fix.mmio_start,
-				info->fix.mmio_len,"cyblafb")) {
+				info->fix.mmio_len, "cyblafb")) {
 		output("request_mem_region failed for mmio region!\n");
 		output("request_mem_region failed for mmio region!\n");
 		goto errout_mmio_reqmem;
 		goto errout_mmio_reqmem;
 	}
 	}
@@ -1276,18 +1497,17 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 		output("ioremap failed for mmio region\n");
 		output("ioremap failed for mmio region\n");
 		goto errout_mmio_remap;
 		goto errout_mmio_remap;
 	}
 	}
-
 	// setup framebuffer memory ... might already be requested
 	// setup framebuffer memory ... might already be requested
 	// by vesafb. Not to fail in case of an unsuccessful request
 	// by vesafb. Not to fail in case of an unsuccessful request
-	// is useful for the development cycle
-	info->fix.smem_start = pci_resource_start(dev,0);
+	// is useful if both are loaded.
+	info->fix.smem_start = pci_resource_start(dev, 0);
 	info->fix.smem_len = get_memsize();
 	info->fix.smem_len = get_memsize();
 
 
 	if (!request_mem_region(info->fix.smem_start,
 	if (!request_mem_region(info->fix.smem_start,
-				info->fix.smem_len,"cyblafb")) {
-		output("request_mem_region failed for smem region!\n");
-		if (!vesafb)
-			goto errout_smem_req;
+				info->fix.smem_len, "cyblafb")) {
+		output("region %#lx/%#x already reserved\n",
+		       info->fix.smem_start, info->fix.smem_len);
+		vesafb |= 4;
 	}
 	}
 
 
 	info->screen_base = ioremap_nocache(info->fix.smem_start,
 	info->screen_base = ioremap_nocache(info->fix.smem_start,
@@ -1300,31 +1520,30 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 
 
 	displaytype = get_displaytype();
 	displaytype = get_displaytype();
 
 
-	if(displaytype == DISPLAY_FP)
+	if (displaytype == DISPLAY_FP)
 		nativex = get_nativex();
 		nativex = get_nativex();
 
 
-	//
-	// FBINFO_HWACCEL_YWRAP    .... does not work (could be made to work?)
-	// FBINFO_PARTIAL_PAN_OK   .... is not ok
-	// FBINFO_READS_FAST	   .... is necessary for optimal scrolling
-	//
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN
-		      | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT
-		      | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST;
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_COPYAREA
+		    | FBINFO_HWACCEL_FILLRECT
+		    | FBINFO_HWACCEL_IMAGEBLIT
+		    | FBINFO_READS_FAST
+//		    | FBINFO_PARTIAL_PAN_OK
+		    | FBINFO_MISC_ALWAYS_SETPAR;
 
 
 	info->pseudo_palette = par->pseudo_pal;
 	info->pseudo_palette = par->pseudo_pal;
 
 
-	if(getstartupmode(info))
+	if (getstartupmode(info))
 		goto errout_findmode;
 		goto errout_findmode;
 
 
-	fb_alloc_cmap(&info->cmap,256,0);
+	fb_alloc_cmap(&info->cmap, 256, 0);
 
 
 	if (register_framebuffer(info)) {
 	if (register_framebuffer(info)) {
 		output("Could not register CyBla framebuffer\n");
 		output("Could not register CyBla framebuffer\n");
 		goto errout_register;
 		goto errout_register;
 	}
 	}
 
 
-	pci_set_drvdata(dev,info);
+	pci_set_drvdata(dev, info);
 
 
 	//
 	//
 	// normal exit and error paths
 	// normal exit and error paths
@@ -1332,23 +1551,24 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 
 
 	return 0;
 	return 0;
 
 
- errout_register:
- errout_findmode:
+      errout_register:
+      errout_findmode:
 	iounmap(info->screen_base);
 	iounmap(info->screen_base);
- errout_smem_remap:
-	release_mem_region(info->fix.smem_start,
-			   info->fix.smem_len);
- errout_smem_req:
+      errout_smem_remap:
+	if (!(vesafb & 4))
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
 	iounmap(io_virt);
 	iounmap(io_virt);
- errout_mmio_remap:
-	release_mem_region(info->fix.mmio_start,
-			   info->fix.mmio_len);
- errout_mmio_reqmem:
-//	release_region(0x3c0,32);
- errout_enable:
+      errout_mmio_remap:
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+      errout_mmio_reqmem:
+	if (!(vesafb & 1))
+		release_region(0x3c0, 32);
+      errout_enable:
+	kfree(info->pixmap.addr);
+      errout_alloc_pixmap:
 	framebuffer_release(info);
 	framebuffer_release(info);
- errout_alloc:
-	output("CyblaFB version %s aborting init.\n",VERSION);
+      errout_alloc_info:
+	output("CyblaFB version %s aborting init.\n", VERSION);
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 
@@ -1359,35 +1579,41 @@ static void __devexit cybla_pci_remove(struct pci_dev *dev)
 	unregister_framebuffer(info);
 	unregister_framebuffer(info);
 	iounmap(io_virt);
 	iounmap(io_virt);
 	iounmap(info->screen_base);
 	iounmap(info->screen_base);
-	release_mem_region(info->fix.smem_start,info->fix.smem_len);
-	release_mem_region(info->fix.mmio_start,info->fix.mmio_len);
+	if (!(vesafb & 4))
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
 	fb_dealloc_cmap(&info->cmap);
 	fb_dealloc_cmap(&info->cmap);
+	if (!(vesafb & 2))
+		release_region(GEBase, 0x100);
+	if (!(vesafb & 1))
+		release_region(0x3c0, 32);
+	kfree(info->pixmap.addr);
 	framebuffer_release(info);
 	framebuffer_release(info);
-	output("CyblaFB version %s normal exit.\n",VERSION);
+	output("CyblaFB version %s normal exit.\n", VERSION);
 }
 }
 
 
 //
 //
 // List of boards that we are trying to support
 // List of boards that we are trying to support
 //
 //
 static struct pci_device_id cybla_devices[] = {
 static struct pci_device_id cybla_devices[] = {
-	{PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+	{PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0,}
 	{0,}
 };
 };
 
 
-MODULE_DEVICE_TABLE(pci,cybla_devices);
+MODULE_DEVICE_TABLE(pci, cybla_devices);
 
 
 static struct pci_driver cyblafb_pci_driver = {
 static struct pci_driver cyblafb_pci_driver = {
-	.name		= "cyblafb",
-	.id_table	= cybla_devices,
-	.probe		= cybla_pci_probe,
-	.remove 	= __devexit_p(cybla_pci_remove)
+	.name = "cyblafb",
+	.id_table = cybla_devices,
+	.probe = cybla_pci_probe,
+	.remove = __devexit_p(cybla_pci_remove)
 };
 };
 
 
 //=============================================================
 //=============================================================
 //
 //
 // kernel command line example:
 // kernel command line example:
 //
 //
-//	video=cyblafb:1280x1024,bpp=16,ref=50 ...
+//	video=cyblafb:1280x1024, bpp=16, ref=50 ...
 //
 //
 // modprobe command line example:
 // modprobe command line example:
 //
 //
@@ -1401,45 +1627,44 @@ static int __devinit cyblafb_init(void)
 	char *options = NULL;
 	char *options = NULL;
 	char *opt;
 	char *opt;
 
 
-	if (fb_get_options("cyblafb",&options))
+	if (fb_get_options("cyblafb", &options))
 		return -ENODEV;
 		return -ENODEV;
 
 
 	if (options && *options)
 	if (options && *options)
-		while((opt = strsep(&options,",")) != NULL ) {
-			if (!*opt) continue;
-			else if (!strncmp(opt,"bpp=",4))
-				bpp = simple_strtoul(opt+4,NULL,0);
-			else if (!strncmp(opt,"ref=",4))
-				ref = simple_strtoul(opt+4,NULL,0);
-			else if (!strncmp(opt,"fp",2))
+		while ((opt = strsep(&options, ",")) != NULL) {
+			if (!*opt)
+				continue;
+			else if (!strncmp(opt, "bpp=", 4))
+				bpp = simple_strtoul(opt + 4, NULL, 0);
+			else if (!strncmp(opt, "ref=", 4))
+				ref = simple_strtoul(opt + 4, NULL, 0);
+			else if (!strncmp(opt, "fp", 2))
 				displaytype = DISPLAY_FP;
 				displaytype = DISPLAY_FP;
-			else if (!strncmp(opt,"crt",3))
+			else if (!strncmp(opt, "crt", 3))
 				displaytype = DISPLAY_CRT;
 				displaytype = DISPLAY_CRT;
-			else if (!strncmp(opt,"nativex=",8))
-				nativex = simple_strtoul(opt+8,NULL,0);
-			else if (!strncmp(opt,"center",6))
+			else if (!strncmp(opt, "nativex=", 8))
+				nativex = simple_strtoul(opt + 8, NULL, 0);
+			else if (!strncmp(opt, "center", 6))
 				center = 1;
 				center = 1;
-			else if (!strncmp(opt,"stretch",7))
+			else if (!strncmp(opt, "stretch", 7))
 				stretch = 1;
 				stretch = 1;
-			else if (!strncmp(opt,"pciwb=",6))
-				pciwb = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"pcirb=",6))
-				pcirb = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"pciwr=",6))
-				pciwr = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"pcirr=",6))
-				pcirr = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"memsize=",8))
-				memsize = simple_strtoul(opt+8,NULL,0);
-			else if (!strncmp(opt,"verbosity=",10))
-				verbosity = simple_strtoul(opt+10,NULL,0);
-			else if (!strncmp(opt,"vesafb",6))
-				vesafb = 1;
+			else if (!strncmp(opt, "pciwb=", 6))
+				pciwb = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "pcirb=", 6))
+				pcirb = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "pciwr=", 6))
+				pciwr = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "pcirr=", 6))
+				pcirr = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "memsize=", 8))
+				memsize = simple_strtoul(opt + 8, NULL, 0);
+			else if (!strncmp(opt, "verbosity=", 10))
+				verbosity = simple_strtoul(opt + 10, NULL, 0);
 			else
 			else
 				mode = opt;
 				mode = opt;
 		}
 		}
 #endif
 #endif
-	output("CyblaFB version %s initializing\n",VERSION);
+	output("CyblaFB version %s initializing\n", VERSION);
 	return pci_module_init(&cyblafb_pci_driver);
 	return pci_module_init(&cyblafb_pci_driver);
 }
 }
 
 

+ 4 - 0
include/video/cyblafb.h

@@ -153,6 +153,10 @@
 #define GE04	(GEBase+0x04)	// source 2, p 111
 #define GE04	(GEBase+0x04)	// source 2, p 111
 #define GE08	(GEBase+0x08)	// destination 1, p 111
 #define GE08	(GEBase+0x08)	// destination 1, p 111
 #define GE0C	(GEBase+0x0C)	// destination 2, p 112
 #define GE0C	(GEBase+0x0C)	// destination 2, p 112
+#define GE10	(GEBase+0x10)	// right view base & enable, p 112
+#define GE13	(GEBase+0x13)	// left view base & enable, p 112
+#define GE18	(GEBase+0x18)	// block write start address, p 112
+#define GE1C	(GEBase+0x1C)	// block write end address, p 112
 #define GE20	(GEBase+0x20)	// engine status, p 113
 #define GE20	(GEBase+0x20)	// engine status, p 113
 #define GE24	(GEBase+0x24)	// reset all GE pointers
 #define GE24	(GEBase+0x24)	// reset all GE pointers
 #define GE44	(GEBase+0x44)	// command register, p 126
 #define GE44	(GEBase+0x44)	// command register, p 126