2 * linux/drivers/video/vgastate.c -- VGA state save/restore
4 * Copyright 2002 James Simmons
6 * Copyright history from vga16fb.c:
7 * Copyright 1999 Ben Pfaff and Petr Vandrovec
8 * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
9 * Based on VESA framebuffer (c) 1998 Gerd Knorr
11 * This file is subject to the terms and conditions of the GNU General
12 * Public License. See the file COPYING in the main directory of this
13 * archive for more details.
16 #include <linux/module.h>
17 #include <linux/slab.h>
19 #include <linux/vmalloc.h>
20 #include <video/vga.h>
34 static inline unsigned char vga_rcrtcs(void __iomem
*regbase
, unsigned short iobase
,
37 vga_w(regbase
, iobase
+ 0x4, reg
);
38 return vga_r(regbase
, iobase
+ 0x5);
41 static inline void vga_wcrtcs(void __iomem
*regbase
, unsigned short iobase
,
42 unsigned char reg
, unsigned char val
)
44 vga_w(regbase
, iobase
+ 0x4, reg
);
45 vga_w(regbase
, iobase
+ 0x5, val
);
48 static void save_vga_text(struct vgastate
*state
, void __iomem
*fbbase
)
50 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
52 u8 misc
, attr10
, gr4
, gr5
, gr6
, seq1
, seq2
, seq4
;
53 unsigned short iobase
;
55 /* if in graphics mode, no need to save */
56 misc
= vga_r(state
->vgabase
, VGA_MIS_R
);
57 iobase
= (misc
& 1) ? 0x3d0 : 0x3b0;
59 vga_r(state
->vgabase
, iobase
+ 0xa);
60 vga_w(state
->vgabase
, VGA_ATT_W
, 0x00);
61 attr10
= vga_rattr(state
->vgabase
, 0x10);
62 vga_r(state
->vgabase
, iobase
+ 0xa);
63 vga_w(state
->vgabase
, VGA_ATT_W
, 0x20);
69 gr4
= vga_rgfx(state
->vgabase
, VGA_GFX_PLANE_READ
);
70 gr5
= vga_rgfx(state
->vgabase
, VGA_GFX_MODE
);
71 gr6
= vga_rgfx(state
->vgabase
, VGA_GFX_MISC
);
72 seq2
= vga_rseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
);
73 seq4
= vga_rseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
);
76 seq1
= vga_rseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
);
77 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x1);
78 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
, seq1
| 1 << 5);
79 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x3);
81 /* save font at plane 2 */
82 if (state
->flags
& VGA_SAVE_FONT0
) {
83 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x4);
84 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
85 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x2);
86 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
87 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
88 for (i
= 0; i
< 4 * 8192; i
++)
89 saved
->vga_font0
[i
] = vga_r(fbbase
, i
);
92 /* save font at plane 3 */
93 if (state
->flags
& VGA_SAVE_FONT1
) {
94 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x8);
95 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
96 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x3);
97 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
98 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
99 for (i
= 0; i
< state
->memsize
; i
++)
100 saved
->vga_font1
[i
] = vga_r(fbbase
, i
);
103 /* save font at plane 0/1 */
104 if (state
->flags
& VGA_SAVE_TEXT
) {
105 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x1);
106 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
107 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x0);
108 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
109 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
110 for (i
= 0; i
< 8192; i
++)
111 saved
->vga_text
[i
] = vga_r(fbbase
, i
);
113 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x2);
114 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
115 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x1);
116 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
117 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
118 for (i
= 0; i
< 8192; i
++)
119 saved
->vga_text
[8192+i
] = vga_r(fbbase
+ 2 * 8192, i
);
123 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, seq2
);
124 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, seq4
);
126 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, gr4
);
127 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, gr5
);
128 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, gr6
);
131 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x1);
132 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
, seq1
& ~(1 << 5));
133 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x3);
135 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
, seq1
);
138 static void restore_vga_text(struct vgastate
*state
, void __iomem
*fbbase
)
140 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
142 u8 gr1
, gr3
, gr4
, gr5
, gr6
, gr8
;
146 gr1
= vga_rgfx(state
->vgabase
, VGA_GFX_SR_ENABLE
);
147 gr3
= vga_rgfx(state
->vgabase
, VGA_GFX_DATA_ROTATE
);
148 gr4
= vga_rgfx(state
->vgabase
, VGA_GFX_PLANE_READ
);
149 gr5
= vga_rgfx(state
->vgabase
, VGA_GFX_MODE
);
150 gr6
= vga_rgfx(state
->vgabase
, VGA_GFX_MISC
);
151 gr8
= vga_rgfx(state
->vgabase
, VGA_GFX_BIT_MASK
);
152 seq2
= vga_rseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
);
153 seq4
= vga_rseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
);
156 seq1
= vga_rseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
);
157 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x1);
158 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
, seq1
| 1 << 5);
159 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x3);
161 if (state
->depth
== 4) {
162 vga_wgfx(state
->vgabase
, VGA_GFX_DATA_ROTATE
, 0x0);
163 vga_wgfx(state
->vgabase
, VGA_GFX_BIT_MASK
, 0xff);
164 vga_wgfx(state
->vgabase
, VGA_GFX_SR_ENABLE
, 0x00);
167 /* restore font at plane 2 */
168 if (state
->flags
& VGA_SAVE_FONT0
) {
169 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x4);
170 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
171 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x2);
172 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
173 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
174 for (i
= 0; i
< 4 * 8192; i
++)
175 vga_w(fbbase
, i
, saved
->vga_font0
[i
]);
178 /* restore font at plane 3 */
179 if (state
->flags
& VGA_SAVE_FONT1
) {
180 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x8);
181 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
182 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x3);
183 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
184 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
185 for (i
= 0; i
< state
->memsize
; i
++)
186 vga_w(fbbase
, i
, saved
->vga_font1
[i
]);
189 /* restore font at plane 0/1 */
190 if (state
->flags
& VGA_SAVE_TEXT
) {
191 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x1);
192 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
193 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x0);
194 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
195 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
196 for (i
= 0; i
< 8192; i
++)
197 vga_w(fbbase
, i
, saved
->vga_text
[i
]);
199 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, 0x2);
200 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, 0x6);
201 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, 0x1);
202 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, 0x0);
203 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, 0x5);
204 for (i
= 0; i
< 8192; i
++)
205 vga_w(fbbase
, i
, saved
->vga_text
[8192+i
]);
209 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x1);
210 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
, seq1
& ~(1 << 5));
211 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x3);
214 vga_wgfx(state
->vgabase
, VGA_GFX_SR_ENABLE
, gr1
);
215 vga_wgfx(state
->vgabase
, VGA_GFX_DATA_ROTATE
, gr3
);
216 vga_wgfx(state
->vgabase
, VGA_GFX_PLANE_READ
, gr4
);
217 vga_wgfx(state
->vgabase
, VGA_GFX_MODE
, gr5
);
218 vga_wgfx(state
->vgabase
, VGA_GFX_MISC
, gr6
);
219 vga_wgfx(state
->vgabase
, VGA_GFX_BIT_MASK
, gr8
);
221 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
, seq1
);
222 vga_wseq(state
->vgabase
, VGA_SEQ_PLANE_WRITE
, seq2
);
223 vga_wseq(state
->vgabase
, VGA_SEQ_MEMORY_MODE
, seq4
);
226 static void save_vga_mode(struct vgastate
*state
)
228 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
229 unsigned short iobase
;
232 saved
->misc
= vga_r(state
->vgabase
, VGA_MIS_R
);
238 for (i
= 0; i
< state
->num_crtc
; i
++)
239 saved
->crtc
[i
] = vga_rcrtcs(state
->vgabase
, iobase
, i
);
241 vga_r(state
->vgabase
, iobase
+ 0xa);
242 vga_w(state
->vgabase
, VGA_ATT_W
, 0x00);
243 for (i
= 0; i
< state
->num_attr
; i
++) {
244 vga_r(state
->vgabase
, iobase
+ 0xa);
245 saved
->attr
[i
] = vga_rattr(state
->vgabase
, i
);
247 vga_r(state
->vgabase
, iobase
+ 0xa);
248 vga_w(state
->vgabase
, VGA_ATT_W
, 0x20);
250 for (i
= 0; i
< state
->num_gfx
; i
++)
251 saved
->gfx
[i
] = vga_rgfx(state
->vgabase
, i
);
253 for (i
= 0; i
< state
->num_seq
; i
++)
254 saved
->seq
[i
] = vga_rseq(state
->vgabase
, i
);
257 static void restore_vga_mode(struct vgastate
*state
)
259 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
260 unsigned short iobase
;
263 vga_w(state
->vgabase
, VGA_MIS_W
, saved
->misc
);
270 /* turn off display */
271 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
,
272 saved
->seq
[VGA_SEQ_CLOCK_MODE
] | 0x20);
274 /* disable sequencer */
275 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x01);
277 /* enable palette addressing */
278 vga_r(state
->vgabase
, iobase
+ 0xa);
279 vga_w(state
->vgabase
, VGA_ATT_W
, 0x00);
281 for (i
= 2; i
< state
->num_seq
; i
++)
282 vga_wseq(state
->vgabase
, i
, saved
->seq
[i
]);
285 /* unprotect vga regs */
286 vga_wcrtcs(state
->vgabase
, iobase
, 17, saved
->crtc
[17] & ~0x80);
287 for (i
= 0; i
< state
->num_crtc
; i
++)
288 vga_wcrtcs(state
->vgabase
, iobase
, i
, saved
->crtc
[i
]);
290 for (i
= 0; i
< state
->num_gfx
; i
++)
291 vga_wgfx(state
->vgabase
, i
, saved
->gfx
[i
]);
293 for (i
= 0; i
< state
->num_attr
; i
++) {
294 vga_r(state
->vgabase
, iobase
+ 0xa);
295 vga_wattr(state
->vgabase
, i
, saved
->attr
[i
]);
298 /* reenable sequencer */
299 vga_wseq(state
->vgabase
, VGA_SEQ_RESET
, 0x03);
300 /* turn display on */
301 vga_wseq(state
->vgabase
, VGA_SEQ_CLOCK_MODE
,
302 saved
->seq
[VGA_SEQ_CLOCK_MODE
] & ~(1 << 5));
304 /* disable video/palette source */
305 vga_r(state
->vgabase
, iobase
+ 0xa);
306 vga_w(state
->vgabase
, VGA_ATT_W
, 0x20);
309 static void save_vga_cmap(struct vgastate
*state
)
311 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
314 vga_w(state
->vgabase
, VGA_PEL_MSK
, 0xff);
316 /* assumes DAC is readable and writable */
317 vga_w(state
->vgabase
, VGA_PEL_IR
, 0x00);
318 for (i
= 0; i
< 768; i
++)
319 saved
->vga_cmap
[i
] = vga_r(state
->vgabase
, VGA_PEL_D
);
322 static void restore_vga_cmap(struct vgastate
*state
)
324 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
327 vga_w(state
->vgabase
, VGA_PEL_MSK
, 0xff);
329 /* assumes DAC is readable and writable */
330 vga_w(state
->vgabase
, VGA_PEL_IW
, 0x00);
331 for (i
= 0; i
< 768; i
++)
332 vga_w(state
->vgabase
, VGA_PEL_D
, saved
->vga_cmap
[i
]);
335 static void vga_cleanup(struct vgastate
*state
)
337 if (state
->vidstate
!= NULL
) {
338 struct regstate
*saved
= (struct regstate
*) state
->vidstate
;
340 vfree(saved
->vga_font0
);
341 vfree(saved
->vga_font1
);
342 vfree(saved
->vga_text
);
343 vfree(saved
->vga_cmap
);
346 state
->vidstate
= NULL
;
350 int save_vga(struct vgastate
*state
)
352 struct regstate
*saved
;
354 saved
= kzalloc(sizeof(struct regstate
), GFP_KERNEL
);
359 state
->vidstate
= (void *)saved
;
361 if (state
->flags
& VGA_SAVE_CMAP
) {
362 saved
->vga_cmap
= vmalloc(768);
363 if (!saved
->vga_cmap
) {
367 save_vga_cmap(state
);
370 if (state
->flags
& VGA_SAVE_MODE
) {
373 if (state
->num_attr
< 21)
374 state
->num_attr
= 21;
375 if (state
->num_crtc
< 25)
376 state
->num_crtc
= 25;
377 if (state
->num_gfx
< 9)
379 if (state
->num_seq
< 5)
381 total
= state
->num_attr
+ state
->num_crtc
+
382 state
->num_gfx
+ state
->num_seq
;
384 saved
->attr
= vmalloc(total
);
389 saved
->crtc
= saved
->attr
+ state
->num_attr
;
390 saved
->gfx
= saved
->crtc
+ state
->num_crtc
;
391 saved
->seq
= saved
->gfx
+ state
->num_gfx
;
393 save_vga_mode(state
);
396 if (state
->flags
& VGA_SAVE_FONTS
) {
397 void __iomem
*fbbase
;
399 /* exit if window is less than 32K */
400 if (state
->memsize
&& state
->memsize
< 4 * 8192) {
405 state
->memsize
= 8 * 8192;
408 state
->membase
= 0xA0000;
410 fbbase
= ioremap(state
->membase
, state
->memsize
);
418 * save only first 32K used by vgacon
420 if (state
->flags
& VGA_SAVE_FONT0
) {
421 saved
->vga_font0
= vmalloc(4 * 8192);
422 if (!saved
->vga_font0
) {
429 * largely unused, but if required by the caller
430 * we'll just save everything.
432 if (state
->flags
& VGA_SAVE_FONT1
) {
433 saved
->vga_font1
= vmalloc(state
->memsize
);
434 if (!saved
->vga_font1
) {
441 * Save 8K at plane0[0], and 8K at plane1[16K]
443 if (state
->flags
& VGA_SAVE_TEXT
) {
444 saved
->vga_text
= vmalloc(8192 * 2);
445 if (!saved
->vga_text
) {
452 save_vga_text(state
, fbbase
);
458 int restore_vga(struct vgastate
*state
)
460 if (state
->vidstate
== NULL
)
463 if (state
->flags
& VGA_SAVE_MODE
)
464 restore_vga_mode(state
);
466 if (state
->flags
& VGA_SAVE_FONTS
) {
467 void __iomem
*fbbase
= ioremap(state
->membase
, state
->memsize
);
473 restore_vga_text(state
, fbbase
);
477 if (state
->flags
& VGA_SAVE_CMAP
)
478 restore_vga_cmap(state
);
484 EXPORT_SYMBOL(save_vga
);
485 EXPORT_SYMBOL(restore_vga
);
487 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
488 MODULE_DESCRIPTION("VGA State Save/Restore");
489 MODULE_LICENSE("GPL");