Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * linux/drivers/video/vgastate.c -- VGA state save/restore
0003  *
0004  * Copyright 2002 James Simmons
0005  *
0006  * Copyright history from vga16fb.c:
0007  *  Copyright 1999 Ben Pfaff and Petr Vandrovec
0008  *  Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
0009  *  Based on VESA framebuffer (c) 1998 Gerd Knorr
0010  *
0011  * This file is subject to the terms and conditions of the GNU General
0012  * Public License.  See the file COPYING in the main directory of this
0013  * archive for more details.
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     /* if in graphics mode, no need to save */
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     /* save regs */
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     /* blank screen */
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     /* save font at plane 2 */
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     /* save font at plane 3 */
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     /* save font at plane 0/1 */
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     /* restore regs */
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     /* unblank screen */
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     /* save regs */
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     /* blank screen */
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     /* restore font at plane 2 */
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     /* restore font at plane 3 */
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     /* restore font at plane 0/1 */
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     /* unblank screen */
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     /* restore regs */
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     /* turn off display */
0271     vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
0272          saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
0273 
0274     /* disable sequencer */
0275     vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
0276 
0277     /* enable palette addressing */
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     /* unprotect vga regs */
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     /* reenable sequencer */
0299     vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
0300     /* turn display on */
0301     vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
0302          saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5));
0303 
0304     /* disable video/palette source */
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     /* assumes DAC is readable and writable */
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     /* assumes DAC is readable and writable */
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         /* exit if window is less than 32K */
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          * save only first 32K used by vgacon
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          * largely unused, but if required by the caller
0430          * we'll just save everything.
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          * Save 8K at plane0[0], and 8K at plane1[16K]
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