linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 1/3: FBDEV: VGA State Save/Restore module
@ 2002-12-04 18:41 Petr Vandrovec
  2002-12-05  1:05 ` Antonino Daplas
  0 siblings, 1 reply; 7+ messages in thread
From: Petr Vandrovec @ 2002-12-04 18:41 UTC (permalink / raw)
  To: Antonino Daplas; +Cc: Linux Kernel Mailing List, linux-fbdev-devel

On  4 Dec 02 at 22:26, Antonino Daplas wrote:
> +static void vga_cleanup(struct fb_vgastate *state)
> +{
> +   if (state->fbbase)
> +       iounmap(state->fbbase);
> +}

Nobody is setting state->fbbase to NULL, so 
"save_vga(SAVE_FONT); restore_vga(); save_vga(0); restore_vga();"
will badly die. I think that you should change save prototype to
int fb_save_vga(int whattosave, struct fb_vgastate* state);, and at
the beginning of save you should do "memset(state, 0, sizeof(*state));"

And fbbase should not be in state variable, as this value is valid
only during duration of save or restore, not outside of them. Pass it
to function which needs it as an explicit argument.

It looks easier to me to make fb_vgastate larger structure with
crt/seq/cmap fields embeded, instead of kmallocing these portions.
Or at least allocate them together depending on 'whattosave' flag,
doing four kmalloc() to allocate about 64 bytes is waste of resources.

And do not use kmalloc() for > 4KB regions, use vmalloc (in
fonts save).

> +       state->attr = kmalloc(state->num_attr, GFP_KERNEL);
> +       state->crtc = kmalloc(state->num_crtc, GFP_KERNEL);
> +       state->gfx = kmalloc(state->num_gfx, GFP_KERNEL);
> +       state->seq = kmalloc(state->num_seq, GFP_KERNEL);
...
> +       state->vga_font0 = kmalloc(8192 * 8, GFP_KERNEL);
...
> +       state->vga_font1 = kmalloc(8192 * 8, GFP_KERNEL);
...
> +       state->vga_text = kmalloc(8192 * 4, GFP_KERNEL);

And if my VGA documentation is correct, you are saving random
data into vga_text: first 8192 chars interleaved with
8192 bytes of garbage, plus attributes from chars 8192-16383 interleaved
with 8192 bytes of garbage. 

When you program hardware to get access to planes (vga 16 color 
graphics mode), every second byte from plane 0 contains character, 
and every second byte from plane 1 contains character attribute 
(it is that way because of bit A0 selects plane, while A15-A1.0 
selects memory address, so odd in memory addresses are unreachable 
in vga text mode).

And if you are using standard hardware, then font data live only in
plane 2, plane 3 is unused on VGA hardware in text mode. I think that
you should either save whole 256KB of memory, without deeper understanding,
or you should just save FONT 0 (first 32*256 bytes from plane 2) if you
want to save memory and you know that console was driven by vgacon in
text mode.
                                                Petr Vandrovec
                                                vandrove@vc.cvut.cz
                                                

^ permalink raw reply	[flat|nested] 7+ messages in thread
* Re: [PATCH 1/3: FBDEV: VGA State Save/Restore module
@ 2002-12-04 22:33 Petr Vandrovec
  2002-12-05  2:53 ` Antonino Daplas
  2002-12-05 17:39 ` James Simmons
  0 siblings, 2 replies; 7+ messages in thread
From: Petr Vandrovec @ 2002-12-04 22:33 UTC (permalink / raw)
  To: Antonino Daplas; +Cc: Linux Kernel Mailing List, Linux Fbdev development list

On  5 Dec 02 at 6:05, Antonino Daplas wrote:
> On Wed, 2002-12-04 at 23:41, Petr Vandrovec wrote:
> > On  4 Dec 02 at 22:26, Antonino Daplas wrote:
> [...]
> > And if my VGA documentation is correct, you are saving random
> > data into vga_text: first 8192 chars interleaved with
> > 8192 bytes of garbage, plus attributes from chars 8192-16383 interleaved
> > with 8192 bytes of garbage. 
> >
> Right, I'm not sure about this part too.  The docs say that this is true
> for EGA compatible hardware.  How about non-compliant hardware?  

Like non-VGA? Like CGA/MDA? I thought that non-VGA/non-EGA adapters are 
out of scope of this document ;-)
  
> > And if you are using standard hardware, then font data live only in
> > plane 2, plane 3 is unused on VGA hardware in text mode. I think that
> > you should either save whole 256KB of memory, without deeper understanding,
> > or you should just save FONT 0 (first 32*256 bytes from plane 2) if you

> Only if saving the first character map in plane 2.  Hardware can have as
> much as 8 character maps per plane, each 8K in size for 64K.  The same
> setup is true for plane 3 fonts.

How you select them? Mine doc says that font block 0 begins in plane 2
at offset 0, block 1 at offset 16KB, 2 at 32K, 3 at 48K, 4 at 8K, 5 at 24K,
6 at 40K, and last, 7th, at 56KB, and sequencer has two threebit fields...

> > want to save memory and you know that console was driven by vgacon in
> > text mode.
> To save memory, apps can explicitly choose what to save, but I don't
> want to go finer than that, ie. save character maps 2,3,5  of plane 2
> and 1,2,3 of plane 3.  The current way of saving the text mode map may
> be a bit wasteful, but better than being bitten by hardware that's
> non-EGA compliant.  

Look at vgacon. Uses font block 0,2,3 from plane 2 when built
without BROKEN_GRAPHICS_PROGRAMS, or 0,1 when built with 
BROKEN_GRAPHICS_PROGRAMS. So if you want just restore vgacon environment,
save only these 4 blocks (4*8K = 32K). Or you want to save whole
VGA memory, and then save whole 256KB, without tricks while saving
planes 0 & 1.
                                            Petr Vandrovec
                                            vandrove@vc.cvut.cz
                                            

^ permalink raw reply	[flat|nested] 7+ messages in thread
* [PATCH 1/3: FBDEV: VGA State Save/Restore module
@ 2002-12-04 17:26 Antonino Daplas
  0 siblings, 0 replies; 7+ messages in thread
From: Antonino Daplas @ 2002-12-04 17:26 UTC (permalink / raw)
  To: Linux Fbdev development list; +Cc: Linux Kernel Mailing List

[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]

Hi,

Attached is a patch against linux-2.5.50 + James Simmons fbdev.diff to
save and restore the VGA state. This includes character maps (plane
0-3), the colormap, and the video mode.  This can be used in fb_open()
and fb_release() to go back to VGA text/graphics mode.

Usage:

struct fb_vgastate state;

/* To save VGA state */
state.flags = VGA_SAVE_MODE | VGA_SAVE_CMAP | VGA_SAVE_FONTS;
fb_save_vga(&state);

/* To restore VGA state */
fb_restore_vga(&state);

Limitations:
1.  Restoring the VGA state from high-resolution graphics mode may
result in a corrupt display which can be corrected by switching
consoles.  May need a screen redraw at this point.  Restoring from VGA
graphics mode to text mode and vice versa is okay.

2. Assumes some things about the hardware which is not universally
correct:  VGA memory base is at 0xA0000, memory size is 64KB, the
hardware palette is readable, etc. 

Any comments welcome.

Tony

PS:  Please reverse the early patch I submitted if it was applied --
vgastate.diff





[-- Attachment #2: vgastate1.diff --]
[-- Type: text/x-patch, Size: 16077 bytes --]

diff -Naur linux-2.5.50-js/drivers/video/Makefile linux/drivers/video/Makefile
--- linux-2.5.50-js/drivers/video/Makefile	2002-12-04 15:15:25.000000000 +0000
+++ linux/drivers/video/Makefile	2002-12-04 15:14:40.000000000 +0000
@@ -6,7 +6,7 @@
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
 export-objs    	:= fbmem.o fbcmap.o fbmon.o modedb.o softcursor.o cfbfillrect.o \
-		   cfbcopyarea.o cfbimgblt.o cyber2000fb.o 
+		   cfbcopyarea.o cfbimgblt.o cyber2000fb.o vgastate.o
 
 # Each configuration option enables a list of files.
 
diff -Naur linux-2.5.50-js/drivers/video/vgastate.c linux/drivers/video/vgastate.c
--- linux-2.5.50-js/drivers/video/vgastate.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/drivers/video/vgastate.c	2002-12-04 15:14:17.000000000 +0000
@@ -0,0 +1,438 @@
+/*
+ * linux/include/video/vgastate.c -- VGA state save/restore
+ *
+ * Copyright 2002 James Simmons
+ * 
+ * Copyright history from vga16fb.c:
+ *	Copyright 1999 Ben Pfaff and Petr Vandrovec
+ *	Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
+ *	Based on VESA framebuffer (c) 1998 Gerd Knorr
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.  
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+
+#include "vga.h"
+
+static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, 
+				       unsigned char reg)
+{
+	vga_w(regbase, iobase + 0x4, reg);
+	return vga_r(regbase, iobase + 0x5);
+}
+
+static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, 
+			      unsigned char reg, unsigned char val)
+{
+	vga_w(regbase, iobase + 0x4, reg);
+	vga_w(regbase, iobase + 0x5, val);
+}
+
+static void save_vga_text(struct fb_vgastate *state)
+{
+	int i;
+	u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
+
+	/* if in graphics mode, no need to save */
+	attr10 = vga_rattr(state->vgabase, 0x10);
+	if (attr10 & 1)
+		return;
+	
+	/* save regs */
+	misc = vga_r(state->vgabase, VGA_MIS_R);
+	gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
+	gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
+	gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
+	seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
+	seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
+	
+	/* force graphics mode */
+	vga_w(state->vgabase, VGA_MIS_W, misc | 1);
+
+	/* blank screen */
+	seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
+
+	/* save font 0 */
+	if (state->flags & VGA_SAVE_FONT0) {
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 8 * 8192; i++) 
+			state->vga_font0[i] = vga_r(state->fbbase, i);
+	}
+	/* save font 1 */
+	if (state->flags & VGA_SAVE_FONT1) {
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 8 * 8192; i++) 
+			state->vga_font1[i] = vga_r(state->fbbase, i);
+	}
+	/* save font 2 */
+	if (state->flags & VGA_SAVE_TEXT) {
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 2 * 8192; i++) 
+			state->vga_text[i] = vga_r(state->fbbase, i);
+
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 2 * 8192; i++) 
+			state->vga_text[i] = vga_r(state->fbbase + 
+						    2 * 8192, i);
+	}
+
+	/* restore regs */
+	vga_wattr(state->vgabase, 0x10, attr10);
+
+	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
+	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
+
+	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
+	vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
+	vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
+	vga_w(state->vgabase, VGA_MIS_W, misc);
+
+	/* unblank screen */
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
+
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
+}
+
+static void restore_vga_text(struct fb_vgastate *state)
+{
+	int i;
+	u8 misc, gr1, gr3, gr4, gr5, gr6, gr8; 
+	u8 seq1, seq2, seq4;
+
+	/* save regs */
+	misc = vga_r(state->vgabase, VGA_MIS_R);
+	gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE);
+	gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE);
+	gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
+	gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
+	gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
+	gr8 = vga_rgfx(state->vgabase, VGA_GFX_BIT_MASK);
+	seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
+	seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
+	
+	/* force graphics mode */
+	vga_w(state->vgabase, VGA_MIS_W, misc | 1);
+
+	/* blank screen */
+	seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
+
+	if (state->depth == 4) {
+		vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff);
+		vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00);
+	}
+	/* restore font 0 */
+	if (state->flags & VGA_SAVE_FONT0) {
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 8 * 8192; i++) 
+			vga_w(state->fbbase, i, state->vga_font0[i]);
+	}
+	/* restore font 1 */
+	if (state->flags & VGA_SAVE_FONT1) {
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 8 * 8192; i++) 
+			vga_w(state->fbbase, i, state->vga_font1[i]);
+	}
+	/* restore font 2 */
+	if (state->flags & VGA_SAVE_TEXT) {
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 2 * 8192; i++) 
+			vga_w(state->fbbase, i, state->vga_text[i]);
+		
+		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
+		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
+		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
+		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
+		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
+		for (i = 0; i < 2 * 8192; i++) 
+			vga_w(state->fbbase + 2 * 8192, i, 
+			      state->vga_text[i]);
+	}
+	/* unblank screen */
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
+
+	/* restore regs */
+	vga_w(state->vgabase, VGA_MIS_W, misc);
+
+	vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1);
+	vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3);
+	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
+	vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
+	vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
+	vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, gr8);
+
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
+	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
+	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
+}
+			      
+static void save_vga_mode(struct fb_vgastate *state)
+{
+	unsigned short iobase;
+	int i;
+
+	state->misc = vga_r(state->vgabase, VGA_MIS_R);
+	if (state->misc & 1)
+		iobase = 0x3d0;
+	else
+		iobase = 0x3b0;
+
+	for (i = 0; i < state->num_crtc; i++) 
+		state->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
+	
+	vga_r(state->vgabase, iobase + 0xa); 
+	vga_w(state->vgabase, VGA_ATT_W, 0x00);
+	for (i = 0; i < state->num_attr; i++) {
+		vga_r(state->vgabase, iobase + 0xa);
+		state->attr[i] = vga_rattr(state->vgabase, i);
+	}
+	vga_r(state->vgabase, iobase + 0xa);
+	vga_w(state->vgabase, VGA_ATT_W, 0x20);
+
+	for (i = 0; i < state->num_gfx; i++) 
+		state->gfx[i] = vga_rgfx(state->vgabase, i);
+
+	for (i = 0; i < state->num_seq; i++) 
+		state->seq[i] = vga_rseq(state->vgabase, i);
+}
+
+static void restore_vga_mode(struct fb_vgastate *state)
+{
+	unsigned short iobase;
+	int i;
+
+	vga_w(state->vgabase, VGA_MIS_W, state->misc);
+
+	if (state->misc & 1)
+		iobase = 0x3d0;
+	else
+		iobase = 0x3b0;
+
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, 
+		 state->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+
+	for (i = 2; i < state->num_seq; i++) 
+		vga_wseq(state->vgabase, i, state->seq[i]);
+
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
+
+	/* unprotect vga regs */
+	vga_wcrtcs(state->vgabase, iobase, 17, state->crtc[17] & ~0x80);
+	for (i = 0; i < state->num_crtc; i++) 
+		vga_wcrtcs(state->vgabase, iobase, i, state->crtc[i]);
+	
+	for (i = 0; i < state->num_gfx; i++) 
+		vga_wgfx(state->vgabase, i, state->gfx[i]);
+
+	vga_r(state->vgabase, iobase + 0xa);
+	vga_w(state->vgabase, VGA_ATT_W, 0x00);
+	for (i = 0; i < state->num_attr; i++) {
+		vga_r(state->vgabase, iobase + 0xa);
+		vga_wattr(state->vgabase, i, state->attr[i]);
+	}
+
+	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, 
+		 state->seq[VGA_SEQ_CLOCK_MODE]);
+
+	vga_r(state->vgabase, iobase + 0xa);
+	vga_w(state->vgabase, VGA_ATT_W, 0x20);
+}
+
+static void save_vga_cmap(struct fb_vgastate *state)
+{
+	int i;
+
+	vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
+	
+	/* assumes DAC is readable and writable */
+	vga_w(state->vgabase, VGA_PEL_IR, 0x00);
+	for (i = 0; i < 768; i++)
+		state->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
+}
+
+static void restore_vga_cmap(struct fb_vgastate *state)
+{
+	int i;
+
+	vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
+
+	vga_w(state->vgabase, VGA_PEL_IW, 0x00);
+	for (i = 0; i < 768; i++)
+		vga_w(state->vgabase, VGA_PEL_D, state->vga_cmap[i]);
+}
+
+static void vga_cleanup(struct fb_vgastate *state)
+{
+	if (state->vga_font0) 
+		kfree(state->vga_font0);
+	if (state->vga_font1) 
+		kfree(state->vga_font1);
+	if (state->vga_text)
+		kfree(state->vga_text);
+	if (state->fbbase)
+		iounmap(state->fbbase);
+	if (state->vga_cmap)
+		kfree(state->vga_cmap);
+	if (state->attr)
+		kfree(state->attr);
+	if (state->crtc)
+		kfree(state->crtc);
+	if (state->gfx)
+		kfree(state->gfx);
+	if (state->seq)
+		kfree(state->seq);
+}
+		
+int fb_save_vga(struct fb_vgastate *state)
+{
+	state->vga_font0 = NULL;
+	state->vga_font1 = NULL;
+	state->vga_text = NULL;
+	state->vga_cmap = NULL;
+	state->attr = NULL;
+	state->crtc = NULL;
+	state->gfx = NULL;
+	state->seq = NULL;
+		
+	if (state->flags & VGA_SAVE_CMAP) {
+		state->vga_cmap = kmalloc(768, GFP_KERNEL);
+		if (!state->vga_cmap) {
+			vga_cleanup(state);
+			return 1;
+		}
+		save_vga_cmap(state);
+	}
+
+	if (state->flags & VGA_SAVE_MODE) {
+		if (state->num_attr < 21)
+			state->num_attr = 21;
+		if (state->num_crtc < 25)
+			state->num_crtc = 25;
+		if (state->num_gfx < 9)
+			state->num_gfx = 9;
+		if (state->num_seq < 5)
+			state->num_seq = 5;
+		state->attr = kmalloc(state->num_attr, GFP_KERNEL);
+		state->crtc = kmalloc(state->num_crtc, GFP_KERNEL);
+		state->gfx = kmalloc(state->num_gfx, GFP_KERNEL);
+		state->seq = kmalloc(state->num_seq, GFP_KERNEL);
+		if (!state->attr || !state->crtc || !state->gfx ||
+		    !state->seq) {
+			vga_cleanup(state);
+			return 1;
+		}
+		save_vga_mode(state);
+	}
+
+	if (state->flags & VGA_SAVE_FONT0) {
+		state->vga_font0 = kmalloc(8192 * 8, GFP_KERNEL);
+		if (!state->vga_font0) {
+			vga_cleanup(state);
+			return 1;
+		}
+	}
+	if (state->flags & VGA_SAVE_FONT1) {
+		state->vga_font1 = kmalloc(8192 * 8, GFP_KERNEL);
+		if (!state->vga_font1) {
+			vga_cleanup(state);
+			return 1;
+		}
+	}
+	if (state->flags & VGA_SAVE_TEXT) {
+		state->vga_text = kmalloc(8192 * 4, GFP_KERNEL);
+		if (!state->vga_text) {
+			vga_cleanup(state);
+			return 1;
+		}
+	}
+	if (state->flags & VGA_SAVE_FONTS) {
+		state->fbbase = ioremap(0xA0000, 8 * 8192);
+		if (!state->fbbase) {
+			vga_cleanup(state);
+			return 1;
+		}
+		save_vga_text(state);
+		iounmap(state->fbbase);
+		state->fbbase = NULL;
+	}
+	return 0;
+}
+
+int fb_restore_vga (struct fb_vgastate *state)
+{
+	if (state->flags & VGA_SAVE_MODE)
+		restore_vga_mode(state);
+
+	if (state->flags & VGA_SAVE_FONTS) {
+		state->fbbase = ioremap(0xA0000, 8 * 8192);
+		if (!state->fbbase) {
+			vga_cleanup(state);
+			return 1;
+		}
+		restore_vga_text(state);
+	}
+
+	if (state->flags & VGA_SAVE_CMAP)
+		restore_vga_cmap(state);
+
+	vga_cleanup(state);
+	return 0;
+}
+
+#ifdef MODULE
+int init_module(void) { return 0; };
+void cleanup_module(void) {};
+#endif
+
+EXPORT_SYMBOL(fb_save_vga);
+EXPORT_SYMBOL(fb_restore_vga);
+
+MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
+MODULE_DESCRIPTION("VGA State Save/Restore");
+MODULE_LICENSE("GPL");
+
diff -Naur linux-2.5.50-js/include/linux/fb.h linux/include/linux/fb.h
--- linux-2.5.50-js/include/linux/fb.h	2002-12-04 15:07:13.000000000 +0000
+++ linux/include/linux/fb.h	2002-12-04 15:20:00.000000000 +0000
@@ -321,6 +321,37 @@
 	struct fb_image	image;	/* Cursor image */
 };
 
+/* VGA State Save and Restore */
+#define VGA_SAVE_FONT0 1  /* save/restore plane 2 fonts   */
+#define VGA_SAVE_FONT1 2  /* save/restore plane 3 fonts   */
+#define VGA_SAVE_TEXT  4  /* save/restore plane 0/1 fonts */
+#define VGA_SAVE_FONTS 7  /* save/restore all fonts       */
+#define VGA_SAVE_MODE  8  /* save/restore video mode      */
+#define VGA_SAVE_CMAP  16 /* save/restore color map/DAC  */
+
+struct fb_vgastate {
+	caddr_t vgabase;         /* mmio base, if supported                 */
+	__u32 flags;             /* what state/s to save (see VGA_SAVE_*)   */ 
+	__u32 depth;             /* current fb depth, not important         */
+	__u32 num_attr;          /* number of att registers, 0 for default  */
+	__u32 num_crtc;          /* number of crt registers, 0 for default  */
+	__u32 num_gfx;           /* number of gfx registers, 0 for default  */
+	__u32 num_seq;           /* number of seq registers, 0 for default  */
+	caddr_t fbbase;          /*    -- DO NOT ALTER STARTING HERE --     */
+	__u8 *vga_font0;         
+	__u8 *vga_font1;         
+	__u8 *vga_text;         
+	__u8 *vga_cmap;          
+	__u8 *attr;               
+	__u8 *crtc;              
+	__u8 *gfx;               
+	__u8 *seq;               
+	__u8 misc;               
+};
+
+extern int fb_save_vga(struct fb_vgastate *state);
+extern int fb_restore_vga(struct fb_vgastate *state);
+
 #ifdef __KERNEL__
 
 #include <linux/fs.h>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-12-05 17:39 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-04 18:41 [PATCH 1/3: FBDEV: VGA State Save/Restore module Petr Vandrovec
2002-12-05  1:05 ` Antonino Daplas
  -- strict thread matches above, loose matches on Subject: below --
2002-12-04 22:33 Petr Vandrovec
2002-12-05  2:53 ` Antonino Daplas
2002-12-05  2:41   ` Petr Vandrovec
2002-12-05 17:39 ` James Simmons
2002-12-04 17:26 Antonino Daplas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).