root/drivers/video/fbdev/vga16fb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rmw
  2. setmode
  3. selectmask
  4. setmask
  5. setop
  6. setsr
  7. setcolor
  8. getindex
  9. setindex
  10. vga16fb_pan_var
  11. vga16fb_update_fix
  12. vga16fb_clock_chip
  13. vga16fb_open
  14. vga16fb_release
  15. vga16fb_check_var
  16. vga16fb_set_par
  17. ega16_setpalette
  18. vga16_setpalette
  19. vga16fb_setcolreg
  20. vga16fb_pan_display
  21. vga_vesa_blank
  22. vga_vesa_unblank
  23. vga_pal_blank
  24. vga16fb_blank
  25. vga_8planes_fillrect
  26. vga16fb_fillrect
  27. vga_8planes_copyarea
  28. vga16fb_copyarea
  29. vga_8planes_imageblit
  30. vga_imageblit_expand
  31. vga_imageblit_color
  32. vga16fb_imageblit
  33. vga16fb_destroy
  34. vga16fb_setup
  35. vga16fb_probe
  36. vga16fb_remove
  37. vga16fb_init
  38. vga16fb_exit

   1 /*
   2  * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
   3  * 
   4  * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
   5  * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
   6  * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
   7  *
   8  * This file is subject to the terms and conditions of the GNU General
   9  * Public License.  See the file COPYING in the main directory of this
  10  * archive for more details.  
  11  */
  12 
  13 #include <linux/module.h>
  14 #include <linux/kernel.h>
  15 #include <linux/errno.h>
  16 #include <linux/string.h>
  17 #include <linux/mm.h>
  18 #include <linux/delay.h>
  19 #include <linux/fb.h>
  20 #include <linux/ioport.h>
  21 #include <linux/init.h>
  22 #include <linux/platform_device.h>
  23 #include <linux/screen_info.h>
  24 
  25 #include <asm/io.h>
  26 #include <video/vga.h>
  27 
  28 #define VGA_FB_PHYS 0xA0000
  29 #define VGA_FB_PHYS_LEN 65536
  30 
  31 #define MODE_SKIP4      1
  32 #define MODE_8BPP       2
  33 #define MODE_CFB        4
  34 #define MODE_TEXT       8
  35 
  36 /* --------------------------------------------------------------------- */
  37 
  38 /*
  39  * card parameters
  40  */
  41 
  42 struct vga16fb_par {
  43         /* structure holding original VGA register settings when the
  44            screen is blanked */
  45         struct {
  46                 unsigned char   SeqCtrlIndex;     /* Sequencer Index reg.   */
  47                 unsigned char   CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
  48                 unsigned char   CrtMiscIO;        /* Miscellaneous register */
  49                 unsigned char   HorizontalTotal;  /* CRT-Controller:00h */
  50                 unsigned char   HorizDisplayEnd;  /* CRT-Controller:01h */
  51                 unsigned char   StartHorizRetrace;/* CRT-Controller:04h */
  52                 unsigned char   EndHorizRetrace;  /* CRT-Controller:05h */
  53                 unsigned char   Overflow;         /* CRT-Controller:07h */
  54                 unsigned char   StartVertRetrace; /* CRT-Controller:10h */
  55                 unsigned char   EndVertRetrace;   /* CRT-Controller:11h */
  56                 unsigned char   ModeControl;      /* CRT-Controller:17h */
  57                 unsigned char   ClockingMode;     /* Seq-Controller:01h */
  58         } vga_state;
  59         struct vgastate state;
  60         unsigned int ref_count;
  61         int palette_blanked, vesa_blanked, mode, isVGA;
  62         u8 misc, pel_msk, vss, clkdiv;
  63         u8 crtc[VGA_CRT_C];
  64 };
  65 
  66 /* --------------------------------------------------------------------- */
  67 
  68 static struct fb_var_screeninfo vga16fb_defined = {
  69         .xres           = 640,
  70         .yres           = 480,
  71         .xres_virtual   = 640,
  72         .yres_virtual   = 480,
  73         .bits_per_pixel = 4,    
  74         .activate       = FB_ACTIVATE_TEST,
  75         .height         = -1,
  76         .width          = -1,
  77         .pixclock       = 39721,
  78         .left_margin    = 48,
  79         .right_margin   = 16,
  80         .upper_margin   = 33,
  81         .lower_margin   = 10,
  82         .hsync_len      = 96,
  83         .vsync_len      = 2,
  84         .vmode          = FB_VMODE_NONINTERLACED,
  85 };
  86 
  87 /* name should not depend on EGA/VGA */
  88 static const struct fb_fix_screeninfo vga16fb_fix = {
  89         .id             = "VGA16 VGA",
  90         .smem_start     = VGA_FB_PHYS,
  91         .smem_len       = VGA_FB_PHYS_LEN,
  92         .type           = FB_TYPE_VGA_PLANES,
  93         .type_aux       = FB_AUX_VGA_PLANES_VGA4,
  94         .visual         = FB_VISUAL_PSEUDOCOLOR,
  95         .xpanstep       = 8,
  96         .ypanstep       = 1,
  97         .line_length    = 640 / 8,
  98         .accel          = FB_ACCEL_NONE
  99 };
 100 
 101 /* The VGA's weird architecture often requires that we read a byte and
 102    write a byte to the same location.  It doesn't matter *what* byte
 103    we write, however.  This is because all the action goes on behind
 104    the scenes in the VGA's 32-bit latch register, and reading and writing
 105    video memory just invokes latch behavior.
 106 
 107    To avoid race conditions (is this necessary?), reading and writing
 108    the memory byte should be done with a single instruction.  One
 109    suitable instruction is the x86 bitwise OR.  The following
 110    read-modify-write routine should optimize to one such bitwise
 111    OR. */
 112 static inline void rmw(volatile char __iomem *p)
 113 {
 114         readb(p);
 115         writeb(1, p);
 116 }
 117 
 118 /* Set the Graphics Mode Register, and return its previous value.
 119    Bits 0-1 are write mode, bit 3 is read mode. */
 120 static inline int setmode(int mode)
 121 {
 122         int oldmode;
 123         
 124         oldmode = vga_io_rgfx(VGA_GFX_MODE);
 125         vga_io_w(VGA_GFX_D, mode);
 126         return oldmode;
 127 }
 128 
 129 /* Select the Bit Mask Register and return its value. */
 130 static inline int selectmask(void)
 131 {
 132         return vga_io_rgfx(VGA_GFX_BIT_MASK);
 133 }
 134 
 135 /* Set the value of the Bit Mask Register.  It must already have been
 136    selected with selectmask(). */
 137 static inline void setmask(int mask)
 138 {
 139         vga_io_w(VGA_GFX_D, mask);
 140 }
 141 
 142 /* Set the Data Rotate Register and return its old value. 
 143    Bits 0-2 are rotate count, bits 3-4 are logical operation
 144    (0=NOP, 1=AND, 2=OR, 3=XOR). */
 145 static inline int setop(int op)
 146 {
 147         int oldop;
 148         
 149         oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
 150         vga_io_w(VGA_GFX_D, op);
 151         return oldop;
 152 }
 153 
 154 /* Set the Enable Set/Reset Register and return its old value.  
 155    The code here always uses value 0xf for this register. */
 156 static inline int setsr(int sr)
 157 {
 158         int oldsr;
 159 
 160         oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
 161         vga_io_w(VGA_GFX_D, sr);
 162         return oldsr;
 163 }
 164 
 165 /* Set the Set/Reset Register and return its old value. */
 166 static inline int setcolor(int color)
 167 {
 168         int oldcolor;
 169 
 170         oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
 171         vga_io_w(VGA_GFX_D, color);
 172         return oldcolor;
 173 }
 174 
 175 /* Return the value in the Graphics Address Register. */
 176 static inline int getindex(void)
 177 {
 178         return vga_io_r(VGA_GFX_I);
 179 }
 180 
 181 /* Set the value in the Graphics Address Register. */
 182 static inline void setindex(int index)
 183 {
 184         vga_io_w(VGA_GFX_I, index);
 185 }
 186 
 187 static void vga16fb_pan_var(struct fb_info *info, 
 188                             struct fb_var_screeninfo *var)
 189 {
 190         struct vga16fb_par *par = info->par;
 191         u32 xoffset, pos;
 192 
 193         xoffset = var->xoffset;
 194         if (info->var.bits_per_pixel == 8) {
 195                 pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2;
 196         } else if (par->mode & MODE_TEXT) {
 197                 int fh = 16; // FIXME !!! font height. Fugde for now.
 198                 pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3;
 199         } else {
 200                 if (info->var.nonstd)
 201                         xoffset--;
 202                 pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3;
 203         }
 204         vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8);
 205         vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF);
 206         /* if we support CFB4, then we must! support xoffset with pixel
 207          * granularity if someone supports xoffset in bit resolution */
 208         vga_io_r(VGA_IS1_RC);           /* reset flip-flop */
 209         vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
 210         if (info->var.bits_per_pixel == 8)
 211                 vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
 212         else
 213                 vga_io_w(VGA_ATT_IW, xoffset & 7);
 214         vga_io_r(VGA_IS1_RC);
 215         vga_io_w(VGA_ATT_IW, 0x20);
 216 }
 217 
 218 static void vga16fb_update_fix(struct fb_info *info)
 219 {
 220         if (info->var.bits_per_pixel == 4) {
 221                 if (info->var.nonstd) {
 222                         info->fix.type = FB_TYPE_PACKED_PIXELS;
 223                         info->fix.line_length = info->var.xres_virtual / 2;
 224                 } else {
 225                         info->fix.type = FB_TYPE_VGA_PLANES;
 226                         info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4;
 227                         info->fix.line_length = info->var.xres_virtual / 8;
 228                 }
 229         } else if (info->var.bits_per_pixel == 0) {
 230                 info->fix.type = FB_TYPE_TEXT;
 231                 info->fix.type_aux = FB_AUX_TEXT_CGA;
 232                 info->fix.line_length = info->var.xres_virtual / 4;
 233         } else {        /* 8bpp */
 234                 if (info->var.nonstd) {
 235                         info->fix.type = FB_TYPE_VGA_PLANES;
 236                         info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8;
 237                         info->fix.line_length = info->var.xres_virtual / 4;
 238                 } else {
 239                         info->fix.type = FB_TYPE_PACKED_PIXELS;
 240                         info->fix.line_length = info->var.xres_virtual;
 241                 }
 242         }
 243 }
 244 
 245 static void vga16fb_clock_chip(struct vga16fb_par *par,
 246                                unsigned int pixclock,
 247                                const struct fb_info *info,
 248                                int mul, int div)
 249 {
 250         static const struct {
 251                 u32 pixclock;
 252                 u8  misc;
 253                 u8  seq_clock_mode;
 254         } *ptr, *best, vgaclocks[] = {
 255                 { 79442 /* 12.587 */, 0x00, 0x08},
 256                 { 70616 /* 14.161 */, 0x04, 0x08},
 257                 { 39721 /* 25.175 */, 0x00, 0x00},
 258                 { 35308 /* 28.322 */, 0x04, 0x00},
 259                 {     0 /* bad */,    0x00, 0x00}};
 260         int err;
 261 
 262         pixclock = (pixclock * mul) / div;
 263         best = vgaclocks;
 264         err = pixclock - best->pixclock;
 265         if (err < 0) err = -err;
 266         for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {
 267                 int tmp;
 268 
 269                 tmp = pixclock - ptr->pixclock;
 270                 if (tmp < 0) tmp = -tmp;
 271                 if (tmp < err) {
 272                         err = tmp;
 273                         best = ptr;
 274                 }
 275         }
 276         par->misc |= best->misc;
 277         par->clkdiv = best->seq_clock_mode;
 278         pixclock = (best->pixclock * div) / mul;                
 279 }
 280                                
 281 #define FAIL(X) return -EINVAL
 282 
 283 static int vga16fb_open(struct fb_info *info, int user)
 284 {
 285         struct vga16fb_par *par = info->par;
 286 
 287         if (!par->ref_count) {
 288                 memset(&par->state, 0, sizeof(struct vgastate));
 289                 par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
 290                         VGA_SAVE_CMAP;
 291                 save_vga(&par->state);
 292         }
 293         par->ref_count++;
 294 
 295         return 0;
 296 }
 297 
 298 static int vga16fb_release(struct fb_info *info, int user)
 299 {
 300         struct vga16fb_par *par = info->par;
 301 
 302         if (!par->ref_count)
 303                 return -EINVAL;
 304 
 305         if (par->ref_count == 1)
 306                 restore_vga(&par->state);
 307         par->ref_count--;
 308 
 309         return 0;
 310 }
 311 
 312 static int vga16fb_check_var(struct fb_var_screeninfo *var,
 313                              struct fb_info *info)
 314 {
 315         struct vga16fb_par *par = info->par;
 316         u32 xres, right, hslen, left, xtotal;
 317         u32 yres, lower, vslen, upper, ytotal;
 318         u32 vxres, xoffset, vyres, yoffset;
 319         u32 pos;
 320         u8 r7, rMode;
 321         int shift;
 322         int mode;
 323         u32 maxmem;
 324 
 325         par->pel_msk = 0xFF;
 326 
 327         if (var->bits_per_pixel == 4) {
 328                 if (var->nonstd) {
 329                         if (!par->isVGA)
 330                                 return -EINVAL;
 331                         shift = 3;
 332                         mode = MODE_SKIP4 | MODE_CFB;
 333                         maxmem = 16384;
 334                         par->pel_msk = 0x0F;
 335                 } else {
 336                         shift = 3;
 337                         mode = 0;
 338                         maxmem = 65536;
 339                 }
 340         } else if (var->bits_per_pixel == 8) {
 341                 if (!par->isVGA)
 342                         return -EINVAL; /* no support on EGA */
 343                 shift = 2;
 344                 if (var->nonstd) {
 345                         mode = MODE_8BPP | MODE_CFB;
 346                         maxmem = 65536;
 347                 } else {
 348                         mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB;
 349                         maxmem = 16384;
 350                 }
 351         } else
 352                 return -EINVAL;
 353 
 354         xres = (var->xres + 7) & ~7;
 355         vxres = (var->xres_virtual + 0xF) & ~0xF;
 356         xoffset = (var->xoffset + 7) & ~7;
 357         left = (var->left_margin + 7) & ~7;
 358         right = (var->right_margin + 7) & ~7;
 359         hslen = (var->hsync_len + 7) & ~7;
 360 
 361         if (vxres < xres)
 362                 vxres = xres;
 363         if (xres + xoffset > vxres)
 364                 xoffset = vxres - xres;
 365 
 366         var->xres = xres;
 367         var->right_margin = right;
 368         var->hsync_len = hslen;
 369         var->left_margin = left;
 370         var->xres_virtual = vxres;
 371         var->xoffset = xoffset;
 372 
 373         xres >>= shift;
 374         right >>= shift;
 375         hslen >>= shift;
 376         left >>= shift;
 377         vxres >>= shift;
 378         xtotal = xres + right + hslen + left;
 379         if (xtotal >= 256)
 380                 FAIL("xtotal too big");
 381         if (hslen > 32)
 382                 FAIL("hslen too big");
 383         if (right + hslen + left > 64)
 384                 FAIL("hblank too big");
 385         par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;
 386         par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;
 387         par->crtc[VGA_CRTC_H_DISP] = xres - 1;
 388         pos = xres + right;
 389         par->crtc[VGA_CRTC_H_SYNC_START] = pos;
 390         pos += hslen;
 391         par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;
 392         pos += left - 2; /* blank_end + 2 <= total + 5 */
 393         par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
 394         if (pos & 0x20)
 395                 par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;
 396 
 397         yres = var->yres;
 398         lower = var->lower_margin;
 399         vslen = var->vsync_len;
 400         upper = var->upper_margin;
 401         vyres = var->yres_virtual;
 402         yoffset = var->yoffset;
 403 
 404         if (yres > vyres)
 405                 vyres = yres;
 406         if (vxres * vyres > maxmem) {
 407                 vyres = maxmem / vxres;
 408                 if (vyres < yres)
 409                         return -ENOMEM;
 410         }
 411         if (yoffset + yres > vyres)
 412                 yoffset = vyres - yres;
 413         var->yres = yres;
 414         var->lower_margin = lower;
 415         var->vsync_len = vslen;
 416         var->upper_margin = upper;
 417         var->yres_virtual = vyres;
 418         var->yoffset = yoffset;
 419 
 420         if (var->vmode & FB_VMODE_DOUBLE) {
 421                 yres <<= 1;
 422                 lower <<= 1;
 423                 vslen <<= 1;
 424                 upper <<= 1;
 425         }
 426         ytotal = yres + lower + vslen + upper;
 427         if (ytotal > 1024) {
 428                 ytotal >>= 1;
 429                 yres >>= 1;
 430                 lower >>= 1;
 431                 vslen >>= 1;
 432                 upper >>= 1;
 433                 rMode = 0x04;
 434         } else
 435                 rMode = 0x00;
 436         if (ytotal > 1024)
 437                 FAIL("ytotal too big");
 438         if (vslen > 16)
 439                 FAIL("vslen too big");
 440         par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
 441         r7 = 0x10;      /* disable linecompare */
 442         if (ytotal & 0x100) r7 |= 0x01;
 443         if (ytotal & 0x200) r7 |= 0x20;
 444         par->crtc[VGA_CRTC_PRESET_ROW] = 0;
 445         par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;    /* 1 scanline, no linecmp */
 446         if (var->vmode & FB_VMODE_DOUBLE)
 447                 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
 448         par->crtc[VGA_CRTC_CURSOR_START] = 0x20;
 449         par->crtc[VGA_CRTC_CURSOR_END]   = 0x00;
 450         if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB)
 451                 xoffset--;
 452         pos = yoffset * vxres + (xoffset >> shift);
 453         par->crtc[VGA_CRTC_START_HI]     = pos >> 8;
 454         par->crtc[VGA_CRTC_START_LO]     = pos & 0xFF;
 455         par->crtc[VGA_CRTC_CURSOR_HI]    = 0x00;
 456         par->crtc[VGA_CRTC_CURSOR_LO]    = 0x00;
 457         pos = yres - 1;
 458         par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;
 459         par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;
 460         if (pos & 0x100)
 461                 r7 |= 0x0A;     /* 0x02 -> DISP_END, 0x08 -> BLANK_START */
 462         if (pos & 0x200) {
 463                 r7 |= 0x40;     /* 0x40 -> DISP_END */
 464                 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
 465         }
 466         pos += lower;
 467         par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;
 468         if (pos & 0x100)
 469                 r7 |= 0x04;
 470         if (pos & 0x200)
 471                 r7 |= 0x80;
 472         pos += vslen;
 473         par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */
 474         pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
 475         par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
 476                      but some SVGA chips requires all 8 bits to set */
 477         if (vxres >= 512)
 478                 FAIL("vxres too long");
 479         par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
 480         if (mode & MODE_SKIP4)
 481                 par->crtc[VGA_CRTC_UNDERLINE] = 0x5F;   /* 256, cfb8 */
 482         else
 483                 par->crtc[VGA_CRTC_UNDERLINE] = 0x1F;   /* 16, vgap */
 484         par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3);
 485         par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
 486         par->crtc[VGA_CRTC_OVERFLOW] = r7;
 487 
 488         par->vss = 0x00;        /* 3DA */
 489 
 490         par->misc = 0xE3;       /* enable CPU, ports 0x3Dx, positive sync */
 491         if (var->sync & FB_SYNC_HOR_HIGH_ACT)
 492                 par->misc &= ~0x40;
 493         if (var->sync & FB_SYNC_VERT_HIGH_ACT)
 494                 par->misc &= ~0x80;
 495         
 496         par->mode = mode;
 497 
 498         if (mode & MODE_8BPP)
 499                 /* pixel clock == vga clock / 2 */
 500                 vga16fb_clock_chip(par, var->pixclock, info, 1, 2);
 501         else
 502                 /* pixel clock == vga clock */
 503                 vga16fb_clock_chip(par, var->pixclock, info, 1, 1);
 504         
 505         var->red.offset = var->green.offset = var->blue.offset = 
 506         var->transp.offset = 0;
 507         var->red.length = var->green.length = var->blue.length =
 508                 (par->isVGA) ? 6 : 2;
 509         var->transp.length = 0;
 510         var->activate = FB_ACTIVATE_NOW;
 511         var->height = -1;
 512         var->width = -1;
 513         var->accel_flags = 0;
 514         return 0;
 515 }
 516 #undef FAIL
 517 
 518 static int vga16fb_set_par(struct fb_info *info)
 519 {
 520         struct vga16fb_par *par = info->par;
 521         u8 gdc[VGA_GFX_C];
 522         u8 seq[VGA_SEQ_C];
 523         u8 atc[VGA_ATT_C];
 524         int fh, i;
 525 
 526         seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv;
 527         if (par->mode & MODE_TEXT)
 528                 seq[VGA_SEQ_PLANE_WRITE] = 0x03;
 529         else
 530                 seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
 531         seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
 532         if (par->mode & MODE_TEXT)
 533                 seq[VGA_SEQ_MEMORY_MODE] = 0x03;
 534         else if (par->mode & MODE_SKIP4)
 535                 seq[VGA_SEQ_MEMORY_MODE] = 0x0E;
 536         else
 537                 seq[VGA_SEQ_MEMORY_MODE] = 0x06;
 538 
 539         gdc[VGA_GFX_SR_VALUE] = 0x00;
 540         gdc[VGA_GFX_SR_ENABLE] = 0x00;
 541         gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
 542         gdc[VGA_GFX_DATA_ROTATE] = 0x00;
 543         gdc[VGA_GFX_PLANE_READ] = 0;
 544         if (par->mode & MODE_TEXT) {
 545                 gdc[VGA_GFX_MODE] = 0x10;
 546                 gdc[VGA_GFX_MISC] = 0x06;
 547         } else {
 548                 if (par->mode & MODE_CFB)
 549                         gdc[VGA_GFX_MODE] = 0x40;
 550                 else
 551                         gdc[VGA_GFX_MODE] = 0x00;
 552                 gdc[VGA_GFX_MISC] = 0x05;
 553         }
 554         gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
 555         gdc[VGA_GFX_BIT_MASK] = 0xFF;
 556 
 557         for (i = 0x00; i < 0x10; i++)
 558                 atc[i] = i;
 559         if (par->mode & MODE_TEXT)
 560                 atc[VGA_ATC_MODE] = 0x04;
 561         else if (par->mode & MODE_8BPP)
 562                 atc[VGA_ATC_MODE] = 0x41;
 563         else
 564                 atc[VGA_ATC_MODE] = 0x81;
 565         atc[VGA_ATC_OVERSCAN] = 0x00;   /* 0 for EGA, 0xFF for VGA */
 566         atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
 567         if (par->mode & MODE_8BPP)
 568                 atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1;
 569         else
 570                 atc[VGA_ATC_PEL] = info->var.xoffset & 7;
 571         atc[VGA_ATC_COLOR_PAGE] = 0x00;
 572         
 573         if (par->mode & MODE_TEXT) {
 574                 fh = 16; // FIXME !!! Fudge font height. 
 575                 par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] 
 576                                                & ~0x1F) | (fh - 1);
 577         }
 578 
 579         vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01);
 580 
 581         /* Enable graphics register modification */
 582         if (!par->isVGA) {
 583                 vga_io_w(EGA_GFX_E0, 0x00);
 584                 vga_io_w(EGA_GFX_E1, 0x01);
 585         }
 586         
 587         /* update misc output register */
 588         vga_io_w(VGA_MIS_W, par->misc);
 589         
 590         /* synchronous reset on */
 591         vga_io_wseq(0x00, 0x01);
 592 
 593         if (par->isVGA)
 594                 vga_io_w(VGA_PEL_MSK, par->pel_msk);
 595 
 596         /* write sequencer registers */
 597         vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20);
 598         for (i = 2; i < VGA_SEQ_C; i++) {
 599                 vga_io_wseq(i, seq[i]);
 600         }
 601         
 602         /* synchronous reset off */
 603         vga_io_wseq(0x00, 0x03);
 604 
 605         /* deprotect CRT registers 0-7 */
 606         vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
 607 
 608         /* write CRT registers */
 609         for (i = 0; i < VGA_CRTC_REGS; i++) {
 610                 vga_io_wcrt(i, par->crtc[i]);
 611         }
 612         
 613         /* write graphics controller registers */
 614         for (i = 0; i < VGA_GFX_C; i++) {
 615                 vga_io_wgfx(i, gdc[i]);
 616         }
 617         
 618         /* write attribute controller registers */
 619         for (i = 0; i < VGA_ATT_C; i++) {
 620                 vga_io_r(VGA_IS1_RC);           /* reset flip-flop */
 621                 vga_io_wattr(i, atc[i]);
 622         }
 623 
 624         /* Wait for screen to stabilize. */
 625         mdelay(50);
 626 
 627         vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]);
 628 
 629         vga_io_r(VGA_IS1_RC);
 630         vga_io_w(VGA_ATT_IW, 0x20);
 631 
 632         vga16fb_update_fix(info);
 633         return 0;
 634 }
 635 
 636 static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 637 {
 638         static const unsigned char map[] = { 000, 001, 010, 011 };
 639         int val;
 640         
 641         if (regno >= 16)
 642                 return;
 643         val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
 644         vga_io_r(VGA_IS1_RC);   /* ! 0x3BA */
 645         vga_io_wattr(regno, val);
 646         vga_io_r(VGA_IS1_RC);   /* some clones need it */
 647         vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */
 648 }
 649 
 650 static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 651 {
 652         outb(regno,       VGA_PEL_IW);
 653         outb(red   >> 10, VGA_PEL_D);
 654         outb(green >> 10, VGA_PEL_D);
 655         outb(blue  >> 10, VGA_PEL_D);
 656 }
 657 
 658 static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 659                              unsigned blue, unsigned transp,
 660                              struct fb_info *info)
 661 {
 662         struct vga16fb_par *par = info->par;
 663         int gray;
 664 
 665         /*
 666          *  Set a single color register. The values supplied are
 667          *  already rounded down to the hardware's capabilities
 668          *  (according to the entries in the `var' structure). Return
 669          *  != 0 for invalid regno.
 670          */
 671         
 672         if (regno >= 256)
 673                 return 1;
 674 
 675         gray = info->var.grayscale;
 676         
 677         if (gray) {
 678                 /* gray = 0.30*R + 0.59*G + 0.11*B */
 679                 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
 680         }
 681         if (par->isVGA) 
 682                 vga16_setpalette(regno,red,green,blue);
 683         else
 684                 ega16_setpalette(regno,red,green,blue);
 685         return 0;
 686 }
 687 
 688 static int vga16fb_pan_display(struct fb_var_screeninfo *var,
 689                                struct fb_info *info) 
 690 {
 691         vga16fb_pan_var(info, var);
 692         return 0;
 693 }
 694 
 695 /* The following VESA blanking code is taken from vgacon.c.  The VGA
 696    blanking code was originally by Huang shi chao, and modified by
 697    Christoph Rimek (chrimek@toppoint.de) and todd j. derr
 698    (tjd@barefoot.org) for Linux. */
 699 
 700 static void vga_vesa_blank(struct vga16fb_par *par, int mode)
 701 {
 702         unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
 703         unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
 704         
 705         /* save original values of VGA controller registers */
 706         if(!par->vesa_blanked) {
 707                 par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
 708                 //sti();
 709 
 710                 par->vga_state.HorizontalTotal = vga_io_rcrt(0x00);     /* HorizontalTotal */
 711                 par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01);     /* HorizDisplayEnd */
 712                 par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04);   /* StartHorizRetrace */
 713                 par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05);     /* EndHorizRetrace */
 714                 par->vga_state.Overflow = vga_io_rcrt(0x07);            /* Overflow */
 715                 par->vga_state.StartVertRetrace = vga_io_rcrt(0x10);    /* StartVertRetrace */
 716                 par->vga_state.EndVertRetrace = vga_io_rcrt(0x11);      /* EndVertRetrace */
 717                 par->vga_state.ModeControl = vga_io_rcrt(0x17); /* ModeControl */
 718                 par->vga_state.ClockingMode = vga_io_rseq(0x01);        /* ClockingMode */
 719         }
 720 
 721         /* assure that video is enabled */
 722         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
 723         vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
 724 
 725         /* test for vertical retrace in process.... */
 726         if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
 727                 vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
 728 
 729         /*
 730          * Set <End of vertical retrace> to minimum (0) and
 731          * <Start of vertical Retrace> to maximum (incl. overflow)
 732          * Result: turn off vertical sync (VSync) pulse.
 733          */
 734         if (mode & FB_BLANK_VSYNC_SUSPEND) {
 735                 vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
 736                 vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
 737                 /* bits 9,10 of vert. retrace */
 738                 vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
 739         }
 740 
 741         if (mode & FB_BLANK_HSYNC_SUSPEND) {
 742                 /*
 743                  * Set <End of horizontal retrace> to minimum (0) and
 744                  *  <Start of horizontal Retrace> to maximum
 745                  * Result: turn off horizontal sync (HSync) pulse.
 746                  */
 747                 vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
 748                 vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
 749         }
 750 
 751         /* restore both index registers */
 752         outb_p(SeqCtrlIndex, VGA_SEQ_I);
 753         outb_p(CrtCtrlIndex, VGA_CRT_IC);
 754 }
 755 
 756 static void vga_vesa_unblank(struct vga16fb_par *par)
 757 {
 758         unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
 759         unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
 760         
 761         /* restore original values of VGA controller registers */
 762         vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
 763 
 764         /* HorizontalTotal */
 765         vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
 766         /* HorizDisplayEnd */
 767         vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd);
 768         /* StartHorizRetrace */
 769         vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace);
 770         /* EndHorizRetrace */
 771         vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace);
 772         /* Overflow */
 773         vga_io_wcrt(0x07, par->vga_state.Overflow);
 774         /* StartVertRetrace */
 775         vga_io_wcrt(0x10, par->vga_state.StartVertRetrace);
 776         /* EndVertRetrace */
 777         vga_io_wcrt(0x11, par->vga_state.EndVertRetrace);
 778         /* ModeControl */
 779         vga_io_wcrt(0x17, par->vga_state.ModeControl);
 780         /* ClockingMode */
 781         vga_io_wseq(0x01, par->vga_state.ClockingMode);
 782 
 783         /* restore index/control registers */
 784         vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
 785         vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
 786 }
 787 
 788 static void vga_pal_blank(void)
 789 {
 790         int i;
 791 
 792         for (i=0; i<16; i++) {
 793                 outb_p(i, VGA_PEL_IW);
 794                 outb_p(0, VGA_PEL_D);
 795                 outb_p(0, VGA_PEL_D);
 796                 outb_p(0, VGA_PEL_D);
 797         }
 798 }
 799 
 800 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
 801 static int vga16fb_blank(int blank, struct fb_info *info)
 802 {
 803         struct vga16fb_par *par = info->par;
 804 
 805         switch (blank) {
 806         case FB_BLANK_UNBLANK:                          /* Unblank */
 807                 if (par->vesa_blanked) {
 808                         vga_vesa_unblank(par);
 809                         par->vesa_blanked = 0;
 810                 }
 811                 if (par->palette_blanked) {
 812                         par->palette_blanked = 0;
 813                 }
 814                 break;
 815         case FB_BLANK_NORMAL:                           /* blank */
 816                 vga_pal_blank();
 817                 par->palette_blanked = 1;
 818                 break;
 819         default:                        /* VESA blanking */
 820                 vga_vesa_blank(par, blank);
 821                 par->vesa_blanked = 1;
 822                 break;
 823         }
 824         return 0;
 825 }
 826 
 827 static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 828 {
 829         u32 dx = rect->dx, width = rect->width;
 830         char oldindex = getindex();
 831         char oldmode = setmode(0x40);
 832         char oldmask = selectmask();
 833         int line_ofs, height;
 834         char oldop, oldsr;
 835         char __iomem *where;
 836 
 837         dx /= 4;
 838         where = info->screen_base + dx + rect->dy * info->fix.line_length;
 839 
 840         if (rect->rop == ROP_COPY) {
 841                 oldop = setop(0);
 842                 oldsr = setsr(0);
 843 
 844                 width /= 4;
 845                 line_ofs = info->fix.line_length - width;
 846                 setmask(0xff);
 847 
 848                 height = rect->height;
 849 
 850                 while (height--) {
 851                         int x;
 852 
 853                         /* we can do memset... */
 854                         for (x = width; x > 0; --x) {
 855                                 writeb(rect->color, where);
 856                                 where++;
 857                         }
 858                         where += line_ofs;
 859                 }
 860         } else {
 861                 char oldcolor = setcolor(0xf);
 862                 int y;
 863 
 864                 oldop = setop(0x18);
 865                 oldsr = setsr(0xf);
 866                 setmask(0x0F);
 867                 for (y = 0; y < rect->height; y++) {
 868                         rmw(where);
 869                         rmw(where+1);
 870                         where += info->fix.line_length;
 871                 }
 872                 setcolor(oldcolor);
 873         }
 874         setmask(oldmask);
 875         setsr(oldsr);
 876         setop(oldop);
 877         setmode(oldmode);
 878         setindex(oldindex);
 879 }
 880 
 881 static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 882 {
 883         int x, x2, y2, vxres, vyres, width, height, line_ofs;
 884         char __iomem *dst;
 885 
 886         vxres = info->var.xres_virtual;
 887         vyres = info->var.yres_virtual;
 888 
 889         if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres)
 890                 return;
 891 
 892         /* We could use hardware clipping but on many cards you get around
 893          * hardware clipping by writing to framebuffer directly. */
 894 
 895         x2 = rect->dx + rect->width;
 896         y2 = rect->dy + rect->height;
 897         x2 = x2 < vxres ? x2 : vxres;
 898         y2 = y2 < vyres ? y2 : vyres;
 899         width = x2 - rect->dx;
 900 
 901         switch (info->fix.type) {
 902         case FB_TYPE_VGA_PLANES:
 903                 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
 904 
 905                         height = y2 - rect->dy;
 906                         width = rect->width/8;
 907 
 908                         line_ofs = info->fix.line_length - width;
 909                         dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length;
 910 
 911                         switch (rect->rop) {
 912                         case ROP_COPY:
 913                                 setmode(0);
 914                                 setop(0);
 915                                 setsr(0xf);
 916                                 setcolor(rect->color);
 917                                 selectmask();
 918 
 919                                 setmask(0xff);
 920 
 921                                 while (height--) {
 922                                         for (x = 0; x < width; x++) {
 923                                                 writeb(0, dst);
 924                                                 dst++;
 925                                         }
 926                                         dst += line_ofs;
 927                                 }
 928                                 break;
 929                         case ROP_XOR:
 930                                 setmode(0);
 931                                 setop(0x18);
 932                                 setsr(0xf);
 933                                 setcolor(0xf);
 934                                 selectmask();
 935 
 936                                 setmask(0xff);
 937                                 while (height--) {
 938                                         for (x = 0; x < width; x++) {
 939                                                 rmw(dst);
 940                                                 dst++;
 941                                         }
 942                                         dst += line_ofs;
 943                                 }
 944                                 break;
 945                         }
 946                 } else 
 947                         vga_8planes_fillrect(info, rect);
 948                 break;
 949         case FB_TYPE_PACKED_PIXELS:
 950         default:
 951                 cfb_fillrect(info, rect);
 952                 break;
 953         }
 954 }
 955 
 956 static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 957 {
 958         char oldindex = getindex();
 959         char oldmode = setmode(0x41);
 960         char oldop = setop(0);
 961         char oldsr = setsr(0xf);
 962         int height, line_ofs, x;
 963         u32 sx, dx, width;
 964         char __iomem *dest;
 965         char __iomem *src;
 966 
 967         height = area->height;
 968 
 969         sx = area->sx / 4;
 970         dx = area->dx / 4;
 971         width = area->width / 4;
 972 
 973         if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) {
 974                 line_ofs = info->fix.line_length - width;
 975                 dest = info->screen_base + dx + area->dy * info->fix.line_length;
 976                 src = info->screen_base + sx + area->sy * info->fix.line_length;
 977                 while (height--) {
 978                         for (x = 0; x < width; x++) {
 979                                 readb(src);
 980                                 writeb(0, dest);
 981                                 src++;
 982                                 dest++;
 983                         }
 984                         src += line_ofs;
 985                         dest += line_ofs;
 986                 }
 987         } else {
 988                 line_ofs = info->fix.line_length - width;
 989                 dest = info->screen_base + dx + width +
 990                         (area->dy + height - 1) * info->fix.line_length;
 991                 src = info->screen_base + sx + width +
 992                         (area->sy + height - 1) * info->fix.line_length;
 993                 while (height--) {
 994                         for (x = 0; x < width; x++) {
 995                                 --src;
 996                                 --dest;
 997                                 readb(src);
 998                                 writeb(0, dest);
 999                         }
1000                         src -= line_ofs;
1001                         dest -= line_ofs;
1002                 }
1003         }
1004 
1005         setsr(oldsr);
1006         setop(oldop);
1007         setmode(oldmode);
1008         setindex(oldindex);
1009 }
1010 
1011 static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1012 {
1013         u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 
1014         int x, x2, y2, old_dx, old_dy, vxres, vyres;
1015         int height, width, line_ofs;
1016         char __iomem *dst = NULL;
1017         char __iomem *src = NULL;
1018 
1019         vxres = info->var.xres_virtual;
1020         vyres = info->var.yres_virtual;
1021 
1022         if (area->dx > vxres || area->sx > vxres || area->dy > vyres ||
1023             area->sy > vyres)
1024                 return;
1025 
1026         /* clip the destination */
1027         old_dx = area->dx;
1028         old_dy = area->dy;
1029 
1030         /*
1031          * We could use hardware clipping but on many cards you get around
1032          * hardware clipping by writing to framebuffer directly.
1033          */
1034         x2 = area->dx + area->width;
1035         y2 = area->dy + area->height;
1036         dx = area->dx > 0 ? area->dx : 0;
1037         dy = area->dy > 0 ? area->dy : 0;
1038         x2 = x2 < vxres ? x2 : vxres;
1039         y2 = y2 < vyres ? y2 : vyres;
1040         width = x2 - dx;
1041         height = y2 - dy;
1042 
1043         if (sx + dx < old_dx || sy + dy < old_dy)
1044                 return;
1045 
1046         /* update sx1,sy1 */
1047         sx += (dx - old_dx);
1048         sy += (dy - old_dy);
1049 
1050         /* the source must be completely inside the virtual screen */
1051         if (sx + width > vxres || sy + height > vyres)
1052                 return;
1053 
1054         switch (info->fix.type) {
1055         case FB_TYPE_VGA_PLANES:
1056                 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
1057                         width = width/8;
1058                         line_ofs = info->fix.line_length - width;
1059 
1060                         setmode(1);
1061                         setop(0);
1062                         setsr(0xf);
1063 
1064                         if (dy < sy || (dy == sy && dx < sx)) {
1065                                 dst = info->screen_base + (dx/8) + dy * info->fix.line_length;
1066                                 src = info->screen_base + (sx/8) + sy * info->fix.line_length;
1067                                 while (height--) {
1068                                         for (x = 0; x < width; x++) {
1069                                                 readb(src);
1070                                                 writeb(0, dst);
1071                                                 dst++;
1072                                                 src++;
1073                                         }
1074                                         src += line_ofs;
1075                                         dst += line_ofs;
1076                                 }
1077                         } else {
1078                                 dst = info->screen_base + (dx/8) + width + 
1079                                         (dy + height - 1) * info->fix.line_length;
1080                                 src = info->screen_base + (sx/8) + width + 
1081                                         (sy + height  - 1) * info->fix.line_length;
1082                                 while (height--) {
1083                                         for (x = 0; x < width; x++) {
1084                                                 dst--;
1085                                                 src--;
1086                                                 readb(src);
1087                                                 writeb(0, dst);
1088                                         }
1089                                         src -= line_ofs;
1090                                         dst -= line_ofs;
1091                                 }
1092                         }
1093                 } else 
1094                         vga_8planes_copyarea(info, area);
1095                 break;
1096         case FB_TYPE_PACKED_PIXELS:
1097         default:
1098                 cfb_copyarea(info, area);
1099                 break;
1100         }
1101 }
1102 
1103 #define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
1104 #define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
1105                          0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
1106 
1107 #if defined(__LITTLE_ENDIAN)
1108 static const u16 transl_l[] = TRANS_MASK_LOW;
1109 static const u16 transl_h[] = TRANS_MASK_HIGH;
1110 #elif defined(__BIG_ENDIAN)
1111 static const u16 transl_l[] = TRANS_MASK_HIGH;
1112 static const u16 transl_h[] = TRANS_MASK_LOW;
1113 #else
1114 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
1115 #endif
1116 
1117 static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
1118 {
1119         char oldindex = getindex();
1120         char oldmode = setmode(0x40);
1121         char oldop = setop(0);
1122         char oldsr = setsr(0);
1123         char oldmask = selectmask();
1124         const char *cdat = image->data;
1125         u32 dx = image->dx;
1126         char __iomem *where;
1127         int y;
1128 
1129         dx /= 4;
1130         where = info->screen_base + dx + image->dy * info->fix.line_length;
1131 
1132         setmask(0xff);
1133         writeb(image->bg_color, where);
1134         readb(where);
1135         selectmask();
1136         setmask(image->fg_color ^ image->bg_color);
1137         setmode(0x42);
1138         setop(0x18);
1139         for (y = 0; y < image->height; y++, where += info->fix.line_length)
1140                 writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);
1141         setmask(oldmask);
1142         setsr(oldsr);
1143         setop(oldop);
1144         setmode(oldmode);
1145         setindex(oldindex);
1146 }
1147 
1148 static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
1149 {
1150         char __iomem *where = info->screen_base + (image->dx/8) +
1151                 image->dy * info->fix.line_length;
1152         struct vga16fb_par *par = info->par;
1153         char *cdat = (char *) image->data;
1154         char __iomem *dst;
1155         int x, y;
1156 
1157         switch (info->fix.type) {
1158         case FB_TYPE_VGA_PLANES:
1159                 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
1160                         if (par->isVGA) {
1161                                 setmode(2);
1162                                 setop(0);
1163                                 setsr(0xf);
1164                                 setcolor(image->fg_color);
1165                                 selectmask();
1166                                 
1167                                 setmask(0xff);
1168                                 writeb(image->bg_color, where);
1169                                 rmb();
1170                                 readb(where); /* fill latches */
1171                                 setmode(3);
1172                                 wmb();
1173                                 for (y = 0; y < image->height; y++) {
1174                                         dst = where;
1175                                         for (x = image->width/8; x--;) 
1176                                                 writeb(*cdat++, dst++);
1177                                         where += info->fix.line_length;
1178                                 }
1179                                 wmb();
1180                         } else {
1181                                 setmode(0);
1182                                 setop(0);
1183                                 setsr(0xf);
1184                                 setcolor(image->bg_color);
1185                                 selectmask();
1186                                 
1187                                 setmask(0xff);
1188                                 for (y = 0; y < image->height; y++) {
1189                                         dst = where;
1190                                         for (x=image->width/8; x--;){
1191                                                 rmw(dst);
1192                                                 setcolor(image->fg_color);
1193                                                 selectmask();
1194                                                 if (*cdat) {
1195                                                         setmask(*cdat++);
1196                                                         rmw(dst++);
1197                                                 }
1198                                         }
1199                                         where += info->fix.line_length;
1200                                 }
1201                         }
1202                 } else 
1203                         vga_8planes_imageblit(info, image);
1204                 break;
1205         case FB_TYPE_PACKED_PIXELS:
1206         default:
1207                 cfb_imageblit(info, image);
1208                 break;
1209         }
1210 }
1211 
1212 static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
1213 {
1214         /*
1215          * Draw logo 
1216          */
1217         struct vga16fb_par *par = info->par;
1218         char __iomem *where =
1219                 info->screen_base + image->dy * info->fix.line_length +
1220                 image->dx/8;
1221         const char *cdat = image->data;
1222         char __iomem *dst;
1223         int x, y;
1224 
1225         switch (info->fix.type) {
1226         case FB_TYPE_VGA_PLANES:
1227                 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
1228                     par->isVGA) {
1229                         setsr(0xf);
1230                         setop(0);
1231                         setmode(0);
1232                         
1233                         for (y = 0; y < image->height; y++) {
1234                                 for (x = 0; x < image->width; x++) {
1235                                         dst = where + x/8;
1236 
1237                                         setcolor(*cdat);
1238                                         selectmask();
1239                                         setmask(1 << (7 - (x % 8)));
1240                                         fb_readb(dst);
1241                                         fb_writeb(0, dst);
1242 
1243                                         cdat++;
1244                                 }
1245                                 where += info->fix.line_length;
1246                         }
1247                 }
1248                 break;
1249         case FB_TYPE_PACKED_PIXELS:
1250                 cfb_imageblit(info, image);
1251                 break;
1252         default:
1253                 break;
1254         }
1255 }
1256                                 
1257 static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
1258 {
1259         if (image->depth == 1)
1260                 vga_imageblit_expand(info, image);
1261         else
1262                 vga_imageblit_color(info, image);
1263 }
1264 
1265 static void vga16fb_destroy(struct fb_info *info)
1266 {
1267         iounmap(info->screen_base);
1268         fb_dealloc_cmap(&info->cmap);
1269         /* XXX unshare VGA regions */
1270         framebuffer_release(info);
1271 }
1272 
1273 static struct fb_ops vga16fb_ops = {
1274         .owner          = THIS_MODULE,
1275         .fb_open        = vga16fb_open,
1276         .fb_release     = vga16fb_release,
1277         .fb_destroy     = vga16fb_destroy,
1278         .fb_check_var   = vga16fb_check_var,
1279         .fb_set_par     = vga16fb_set_par,
1280         .fb_setcolreg   = vga16fb_setcolreg,
1281         .fb_pan_display = vga16fb_pan_display,
1282         .fb_blank       = vga16fb_blank,
1283         .fb_fillrect    = vga16fb_fillrect,
1284         .fb_copyarea    = vga16fb_copyarea,
1285         .fb_imageblit   = vga16fb_imageblit,
1286 };
1287 
1288 #ifndef MODULE
1289 static int __init vga16fb_setup(char *options)
1290 {
1291         char *this_opt;
1292         
1293         if (!options || !*options)
1294                 return 0;
1295         
1296         while ((this_opt = strsep(&options, ",")) != NULL) {
1297                 if (!*this_opt) continue;
1298         }
1299         return 0;
1300 }
1301 #endif
1302 
1303 static int vga16fb_probe(struct platform_device *dev)
1304 {
1305         struct fb_info *info;
1306         struct vga16fb_par *par;
1307         int i;
1308         int ret = 0;
1309 
1310         printk(KERN_DEBUG "vga16fb: initializing\n");
1311         info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
1312 
1313         if (!info) {
1314                 ret = -ENOMEM;
1315                 goto err_fb_alloc;
1316         }
1317         info->apertures = alloc_apertures(1);
1318         if (!info->apertures) {
1319                 ret = -ENOMEM;
1320                 goto err_ioremap;
1321         }
1322 
1323         /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
1324         info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
1325 
1326         if (!info->screen_base) {
1327                 printk(KERN_ERR "vga16fb: unable to map device\n");
1328                 ret = -ENOMEM;
1329                 goto err_ioremap;
1330         }
1331 
1332         printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
1333         par = info->par;
1334 
1335         par->isVGA = screen_info.orig_video_isVGA;
1336         par->palette_blanked = 0;
1337         par->vesa_blanked = 0;
1338 
1339         i = par->isVGA? 6 : 2;
1340         
1341         vga16fb_defined.red.length   = i;
1342         vga16fb_defined.green.length = i;
1343         vga16fb_defined.blue.length  = i;       
1344 
1345         /* name should not depend on EGA/VGA */
1346         info->fbops = &vga16fb_ops;
1347         info->var = vga16fb_defined;
1348         info->fix = vga16fb_fix;
1349         /* supports rectangles with widths of multiples of 8 */
1350         info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
1351         info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
1352                 FBINFO_HWACCEL_YPAN;
1353 
1354         i = (info->var.bits_per_pixel == 8) ? 256 : 16;
1355         ret = fb_alloc_cmap(&info->cmap, i, 0);
1356         if (ret) {
1357                 printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
1358                 ret = -ENOMEM;
1359                 goto err_alloc_cmap;
1360         }
1361 
1362         if (vga16fb_check_var(&info->var, info)) {
1363                 printk(KERN_ERR "vga16fb: unable to validate variable\n");
1364                 ret = -EINVAL;
1365                 goto err_check_var;
1366         }
1367 
1368         vga16fb_update_fix(info);
1369 
1370         info->apertures->ranges[0].base = VGA_FB_PHYS;
1371         info->apertures->ranges[0].size = VGA_FB_PHYS_LEN;
1372 
1373         if (register_framebuffer(info) < 0) {
1374                 printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
1375                 ret = -EINVAL;
1376                 goto err_check_var;
1377         }
1378 
1379         fb_info(info, "%s frame buffer device\n", info->fix.id);
1380         platform_set_drvdata(dev, info);
1381 
1382         return 0;
1383 
1384  err_check_var:
1385         fb_dealloc_cmap(&info->cmap);
1386  err_alloc_cmap:
1387         iounmap(info->screen_base);
1388  err_ioremap:
1389         framebuffer_release(info);
1390  err_fb_alloc:
1391         return ret;
1392 }
1393 
1394 static int vga16fb_remove(struct platform_device *dev)
1395 {
1396         struct fb_info *info = platform_get_drvdata(dev);
1397 
1398         if (info)
1399                 unregister_framebuffer(info);
1400 
1401         return 0;
1402 }
1403 
1404 static struct platform_driver vga16fb_driver = {
1405         .probe = vga16fb_probe,
1406         .remove = vga16fb_remove,
1407         .driver = {
1408                 .name = "vga16fb",
1409         },
1410 };
1411 
1412 static struct platform_device *vga16fb_device;
1413 
1414 static int __init vga16fb_init(void)
1415 {
1416         int ret;
1417 #ifndef MODULE
1418         char *option = NULL;
1419 
1420         if (fb_get_options("vga16fb", &option))
1421                 return -ENODEV;
1422 
1423         vga16fb_setup(option);
1424 #endif
1425         ret = platform_driver_register(&vga16fb_driver);
1426 
1427         if (!ret) {
1428                 vga16fb_device = platform_device_alloc("vga16fb", 0);
1429 
1430                 if (vga16fb_device)
1431                         ret = platform_device_add(vga16fb_device);
1432                 else
1433                         ret = -ENOMEM;
1434 
1435                 if (ret) {
1436                         platform_device_put(vga16fb_device);
1437                         platform_driver_unregister(&vga16fb_driver);
1438                 }
1439         }
1440 
1441         return ret;
1442 }
1443 
1444 static void __exit vga16fb_exit(void)
1445 {
1446         platform_device_unregister(vga16fb_device);
1447         platform_driver_unregister(&vga16fb_driver);
1448 }
1449 
1450 MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
1451 MODULE_LICENSE("GPL");
1452 module_init(vga16fb_init);
1453 module_exit(vga16fb_exit);
1454 
1455 
1456 /*
1457  * Overrides for Emacs so that we follow Linus's tabbing style.
1458  * ---------------------------------------------------------------------------
1459  * Local variables:
1460  * c-basic-offset: 8
1461  * End:
1462  */
1463 

/* [<][>][^][v][top][bottom][index][help] */