0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/module.h>
0017 #include <linux/slab.h>
0018 #include <linux/fb.h>
0019 #include <linux/vmalloc.h>
0020 #include <video/vga.h>
0021
0022 struct regstate {
0023 __u8 *vga_font0;
0024 __u8 *vga_font1;
0025 __u8 *vga_text;
0026 __u8 *vga_cmap;
0027 __u8 *attr;
0028 __u8 *crtc;
0029 __u8 *gfx;
0030 __u8 *seq;
0031 __u8 misc;
0032 };
0033
0034 static inline unsigned char vga_rcrtcs(void __iomem *regbase, unsigned short iobase,
0035 unsigned char reg)
0036 {
0037 vga_w(regbase, iobase + 0x4, reg);
0038 return vga_r(regbase, iobase + 0x5);
0039 }
0040
0041 static inline void vga_wcrtcs(void __iomem *regbase, unsigned short iobase,
0042 unsigned char reg, unsigned char val)
0043 {
0044 vga_w(regbase, iobase + 0x4, reg);
0045 vga_w(regbase, iobase + 0x5, val);
0046 }
0047
0048 static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
0049 {
0050 struct regstate *saved = (struct regstate *) state->vidstate;
0051 int i;
0052 u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
0053 unsigned short iobase;
0054
0055
0056 misc = vga_r(state->vgabase, VGA_MIS_R);
0057 iobase = (misc & 1) ? 0x3d0 : 0x3b0;
0058
0059 vga_r(state->vgabase, iobase + 0xa);
0060 vga_w(state->vgabase, VGA_ATT_W, 0x00);
0061 attr10 = vga_rattr(state->vgabase, 0x10);
0062 vga_r(state->vgabase, iobase + 0xa);
0063 vga_w(state->vgabase, VGA_ATT_W, 0x20);
0064
0065 if (attr10 & 1)
0066 return;
0067
0068
0069 gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
0070 gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
0071 gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
0072 seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
0073 seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
0074
0075
0076 seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
0077 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
0078 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
0079 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
0080
0081
0082 if (state->flags & VGA_SAVE_FONT0) {
0083 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
0084 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0085 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
0086 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0087 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0088 for (i = 0; i < 4 * 8192; i++)
0089 saved->vga_font0[i] = vga_r(fbbase, i);
0090 }
0091
0092
0093 if (state->flags & VGA_SAVE_FONT1) {
0094 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
0095 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0096 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
0097 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0098 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0099 for (i = 0; i < state->memsize; i++)
0100 saved->vga_font1[i] = vga_r(fbbase, i);
0101 }
0102
0103
0104 if (state->flags & VGA_SAVE_TEXT) {
0105 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
0106 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0107 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
0108 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0109 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0110 for (i = 0; i < 8192; i++)
0111 saved->vga_text[i] = vga_r(fbbase, i);
0112
0113 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
0114 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0115 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
0116 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0117 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0118 for (i = 0; i < 8192; i++)
0119 saved->vga_text[8192+i] = vga_r(fbbase + 2 * 8192, i);
0120 }
0121
0122
0123 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
0124 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
0125
0126 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
0127 vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
0128 vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
0129
0130
0131 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
0132 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
0133 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
0134
0135 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
0136 }
0137
0138 static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
0139 {
0140 struct regstate *saved = (struct regstate *) state->vidstate;
0141 int i;
0142 u8 gr1, gr3, gr4, gr5, gr6, gr8;
0143 u8 seq1, seq2, seq4;
0144
0145
0146 gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE);
0147 gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE);
0148 gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
0149 gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
0150 gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
0151 gr8 = vga_rgfx(state->vgabase, VGA_GFX_BIT_MASK);
0152 seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
0153 seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
0154
0155
0156 seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
0157 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
0158 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
0159 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
0160
0161 if (state->depth == 4) {
0162 vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, 0x0);
0163 vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff);
0164 vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00);
0165 }
0166
0167
0168 if (state->flags & VGA_SAVE_FONT0) {
0169 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
0170 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0171 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
0172 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0173 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0174 for (i = 0; i < 4 * 8192; i++)
0175 vga_w(fbbase, i, saved->vga_font0[i]);
0176 }
0177
0178
0179 if (state->flags & VGA_SAVE_FONT1) {
0180 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
0181 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0182 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
0183 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0184 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0185 for (i = 0; i < state->memsize; i++)
0186 vga_w(fbbase, i, saved->vga_font1[i]);
0187 }
0188
0189
0190 if (state->flags & VGA_SAVE_TEXT) {
0191 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
0192 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0193 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
0194 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0195 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0196 for (i = 0; i < 8192; i++)
0197 vga_w(fbbase, i, saved->vga_text[i]);
0198
0199 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
0200 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
0201 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
0202 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
0203 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
0204 for (i = 0; i < 8192; i++)
0205 vga_w(fbbase, i, saved->vga_text[8192+i]);
0206 }
0207
0208
0209 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
0210 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
0211 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
0212
0213
0214 vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1);
0215 vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3);
0216 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
0217 vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
0218 vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
0219 vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, gr8);
0220
0221 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
0222 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
0223 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
0224 }
0225
0226 static void save_vga_mode(struct vgastate *state)
0227 {
0228 struct regstate *saved = (struct regstate *) state->vidstate;
0229 unsigned short iobase;
0230 int i;
0231
0232 saved->misc = vga_r(state->vgabase, VGA_MIS_R);
0233 if (saved->misc & 1)
0234 iobase = 0x3d0;
0235 else
0236 iobase = 0x3b0;
0237
0238 for (i = 0; i < state->num_crtc; i++)
0239 saved->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
0240
0241 vga_r(state->vgabase, iobase + 0xa);
0242 vga_w(state->vgabase, VGA_ATT_W, 0x00);
0243 for (i = 0; i < state->num_attr; i++) {
0244 vga_r(state->vgabase, iobase + 0xa);
0245 saved->attr[i] = vga_rattr(state->vgabase, i);
0246 }
0247 vga_r(state->vgabase, iobase + 0xa);
0248 vga_w(state->vgabase, VGA_ATT_W, 0x20);
0249
0250 for (i = 0; i < state->num_gfx; i++)
0251 saved->gfx[i] = vga_rgfx(state->vgabase, i);
0252
0253 for (i = 0; i < state->num_seq; i++)
0254 saved->seq[i] = vga_rseq(state->vgabase, i);
0255 }
0256
0257 static void restore_vga_mode(struct vgastate *state)
0258 {
0259 struct regstate *saved = (struct regstate *) state->vidstate;
0260 unsigned short iobase;
0261 int i;
0262
0263 vga_w(state->vgabase, VGA_MIS_W, saved->misc);
0264
0265 if (saved->misc & 1)
0266 iobase = 0x3d0;
0267 else
0268 iobase = 0x3b0;
0269
0270
0271 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
0272 saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
0273
0274
0275 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
0276
0277
0278 vga_r(state->vgabase, iobase + 0xa);
0279 vga_w(state->vgabase, VGA_ATT_W, 0x00);
0280
0281 for (i = 2; i < state->num_seq; i++)
0282 vga_wseq(state->vgabase, i, saved->seq[i]);
0283
0284
0285
0286 vga_wcrtcs(state->vgabase, iobase, 17, saved->crtc[17] & ~0x80);
0287 for (i = 0; i < state->num_crtc; i++)
0288 vga_wcrtcs(state->vgabase, iobase, i, saved->crtc[i]);
0289
0290 for (i = 0; i < state->num_gfx; i++)
0291 vga_wgfx(state->vgabase, i, saved->gfx[i]);
0292
0293 for (i = 0; i < state->num_attr; i++) {
0294 vga_r(state->vgabase, iobase + 0xa);
0295 vga_wattr(state->vgabase, i, saved->attr[i]);
0296 }
0297
0298
0299 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
0300
0301 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
0302 saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5));
0303
0304
0305 vga_r(state->vgabase, iobase + 0xa);
0306 vga_w(state->vgabase, VGA_ATT_W, 0x20);
0307 }
0308
0309 static void save_vga_cmap(struct vgastate *state)
0310 {
0311 struct regstate *saved = (struct regstate *) state->vidstate;
0312 int i;
0313
0314 vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
0315
0316
0317 vga_w(state->vgabase, VGA_PEL_IR, 0x00);
0318 for (i = 0; i < 768; i++)
0319 saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
0320 }
0321
0322 static void restore_vga_cmap(struct vgastate *state)
0323 {
0324 struct regstate *saved = (struct regstate *) state->vidstate;
0325 int i;
0326
0327 vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
0328
0329
0330 vga_w(state->vgabase, VGA_PEL_IW, 0x00);
0331 for (i = 0; i < 768; i++)
0332 vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]);
0333 }
0334
0335 static void vga_cleanup(struct vgastate *state)
0336 {
0337 if (state->vidstate != NULL) {
0338 struct regstate *saved = (struct regstate *) state->vidstate;
0339
0340 vfree(saved->vga_font0);
0341 vfree(saved->vga_font1);
0342 vfree(saved->vga_text);
0343 vfree(saved->vga_cmap);
0344 vfree(saved->attr);
0345 kfree(saved);
0346 state->vidstate = NULL;
0347 }
0348 }
0349
0350 int save_vga(struct vgastate *state)
0351 {
0352 struct regstate *saved;
0353
0354 saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
0355
0356 if (saved == NULL)
0357 return 1;
0358
0359 state->vidstate = (void *)saved;
0360
0361 if (state->flags & VGA_SAVE_CMAP) {
0362 saved->vga_cmap = vmalloc(768);
0363 if (!saved->vga_cmap) {
0364 vga_cleanup(state);
0365 return 1;
0366 }
0367 save_vga_cmap(state);
0368 }
0369
0370 if (state->flags & VGA_SAVE_MODE) {
0371 int total;
0372
0373 if (state->num_attr < 21)
0374 state->num_attr = 21;
0375 if (state->num_crtc < 25)
0376 state->num_crtc = 25;
0377 if (state->num_gfx < 9)
0378 state->num_gfx = 9;
0379 if (state->num_seq < 5)
0380 state->num_seq = 5;
0381 total = state->num_attr + state->num_crtc +
0382 state->num_gfx + state->num_seq;
0383
0384 saved->attr = vmalloc(total);
0385 if (!saved->attr) {
0386 vga_cleanup(state);
0387 return 1;
0388 }
0389 saved->crtc = saved->attr + state->num_attr;
0390 saved->gfx = saved->crtc + state->num_crtc;
0391 saved->seq = saved->gfx + state->num_gfx;
0392
0393 save_vga_mode(state);
0394 }
0395
0396 if (state->flags & VGA_SAVE_FONTS) {
0397 void __iomem *fbbase;
0398
0399
0400 if (state->memsize && state->memsize < 4 * 8192) {
0401 vga_cleanup(state);
0402 return 1;
0403 }
0404 if (!state->memsize)
0405 state->memsize = 8 * 8192;
0406
0407 if (!state->membase)
0408 state->membase = 0xA0000;
0409
0410 fbbase = ioremap(state->membase, state->memsize);
0411
0412 if (!fbbase) {
0413 vga_cleanup(state);
0414 return 1;
0415 }
0416
0417
0418
0419
0420 if (state->flags & VGA_SAVE_FONT0) {
0421 saved->vga_font0 = vmalloc(4 * 8192);
0422 if (!saved->vga_font0) {
0423 iounmap(fbbase);
0424 vga_cleanup(state);
0425 return 1;
0426 }
0427 }
0428
0429
0430
0431
0432 if (state->flags & VGA_SAVE_FONT1) {
0433 saved->vga_font1 = vmalloc(state->memsize);
0434 if (!saved->vga_font1) {
0435 iounmap(fbbase);
0436 vga_cleanup(state);
0437 return 1;
0438 }
0439 }
0440
0441
0442
0443 if (state->flags & VGA_SAVE_TEXT) {
0444 saved->vga_text = vmalloc(8192 * 2);
0445 if (!saved->vga_text) {
0446 iounmap(fbbase);
0447 vga_cleanup(state);
0448 return 1;
0449 }
0450 }
0451
0452 save_vga_text(state, fbbase);
0453 iounmap(fbbase);
0454 }
0455 return 0;
0456 }
0457
0458 int restore_vga(struct vgastate *state)
0459 {
0460 if (state->vidstate == NULL)
0461 return 1;
0462
0463 if (state->flags & VGA_SAVE_MODE)
0464 restore_vga_mode(state);
0465
0466 if (state->flags & VGA_SAVE_FONTS) {
0467 void __iomem *fbbase = ioremap(state->membase, state->memsize);
0468
0469 if (!fbbase) {
0470 vga_cleanup(state);
0471 return 1;
0472 }
0473 restore_vga_text(state, fbbase);
0474 iounmap(fbbase);
0475 }
0476
0477 if (state->flags & VGA_SAVE_CMAP)
0478 restore_vga_cmap(state);
0479
0480 vga_cleanup(state);
0481 return 0;
0482 }
0483
0484 EXPORT_SYMBOL(save_vga);
0485 EXPORT_SYMBOL(restore_vga);
0486
0487 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
0488 MODULE_DESCRIPTION("VGA State Save/Restore");
0489 MODULE_LICENSE("GPL");
0490