net: convert /proc/net/rt_acct to seq_file
[safe/jmp/linux-2.6] / drivers / video / vga16fb.c
index b46454c..5b29389 100644 (file)
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/tty.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
 
 #include <asm/io.h>
 #include <video/vga.h>
 
-#define GRAPHICS_ADDR_REG VGA_GFX_I    /* Graphics address register. */
-#define GRAPHICS_DATA_REG VGA_GFX_D    /* Graphics data register. */
-
-#define SET_RESET_INDEX        VGA_GFX_SR_VALUE        /* Set/Reset Register index. */
-#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE       /* Enable Set/Reset Register index. */
-#define DATA_ROTATE_INDEX      VGA_GFX_DATA_ROTATE     /* Data Rotate Register index. */
-#define GRAPHICS_MODE_INDEX    VGA_GFX_MODE            /* Graphics Mode Register index. */
-#define BIT_MASK_INDEX         VGA_GFX_BIT_MASK        /* Bit Mask Register index. */
-
-#define dac_reg        (VGA_PEL_IW)
-#define dac_val        (VGA_PEL_D)
-
 #define VGA_FB_PHYS 0xA0000
 #define VGA_FB_PHYS_LEN 65536
 
  * card parameters
  */
 
-static struct fb_info vga16fb; 
-
-static struct vga16fb_par {
+struct vga16fb_par {
        /* structure holding original VGA register settings when the
            screen is blanked */
        struct {
-               unsigned char   SeqCtrlIndex;           /* Sequencer Index reg.   */
-               unsigned char   CrtCtrlIndex;           /* CRT-Contr. Index reg.  */
-               unsigned char   CrtMiscIO;              /* Miscellaneous register */
-               unsigned char   HorizontalTotal;        /* CRT-Controller:00h */
-               unsigned char   HorizDisplayEnd;        /* CRT-Controller:01h */
-               unsigned char   StartHorizRetrace;      /* CRT-Controller:04h */
-               unsigned char   EndHorizRetrace;        /* CRT-Controller:05h */
-               unsigned char   Overflow;               /* CRT-Controller:07h */
-               unsigned char   StartVertRetrace;       /* CRT-Controller:10h */
-               unsigned char   EndVertRetrace;         /* CRT-Controller:11h */
-               unsigned char   ModeControl;            /* CRT-Controller:17h */
-               unsigned char   ClockingMode;           /* Seq-Controller:01h */
+               unsigned char   SeqCtrlIndex;     /* Sequencer Index reg.   */
+               unsigned char   CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
+               unsigned char   CrtMiscIO;        /* Miscellaneous register */
+               unsigned char   HorizontalTotal;  /* CRT-Controller:00h */
+               unsigned char   HorizDisplayEnd;  /* CRT-Controller:01h */
+               unsigned char   StartHorizRetrace;/* CRT-Controller:04h */
+               unsigned char   EndHorizRetrace;  /* CRT-Controller:05h */
+               unsigned char   Overflow;         /* CRT-Controller:07h */
+               unsigned char   StartVertRetrace; /* CRT-Controller:10h */
+               unsigned char   EndVertRetrace;   /* CRT-Controller:11h */
+               unsigned char   ModeControl;      /* CRT-Controller:17h */
+               unsigned char   ClockingMode;     /* Seq-Controller:01h */
        } vga_state;
        struct vgastate state;
-       atomic_t ref_count;
+       unsigned int ref_count;
        int palette_blanked, vesa_blanked, mode, isVGA;
        u8 misc, pel_msk, vss, clkdiv;
        u8 crtc[VGA_CRT_C];
-} vga16_par;
+};
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo vga16fb_defined = {
+static struct fb_var_screeninfo vga16fb_defined __initdata = {
        .xres           = 640,
        .yres           = 480,
        .xres_virtual   = 640,
@@ -108,7 +95,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = {
        .visual         = FB_VISUAL_PSEUDOCOLOR,
        .xpanstep       = 8,
        .ypanstep       = 1,
-       .line_length    = 640/8,
+       .line_length    = 640 / 8,
        .accel          = FB_ACCEL_NONE
 };
 
@@ -135,23 +122,22 @@ static inline int setmode(int mode)
 {
        int oldmode;
        
-       vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX);
-       oldmode = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, mode);
+       oldmode = vga_io_rgfx(VGA_GFX_MODE);
+       vga_io_w(VGA_GFX_D, mode);
        return oldmode;
 }
 
 /* Select the Bit Mask Register and return its value. */
 static inline int selectmask(void)
 {
-       return vga_io_rgfx(BIT_MASK_INDEX);
+       return vga_io_rgfx(VGA_GFX_BIT_MASK);
 }
 
 /* Set the value of the Bit Mask Register.  It must already have been
    selected with selectmask(). */
 static inline void setmask(int mask)
 {
-       vga_io_w(GRAPHICS_DATA_REG, mask);
+       vga_io_w(VGA_GFX_D, mask);
 }
 
 /* Set the Data Rotate Register and return its old value. 
@@ -161,9 +147,8 @@ static inline int setop(int op)
 {
        int oldop;
        
-       vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX);
-       oldop = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, op);
+       oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
+       vga_io_w(VGA_GFX_D, op);
        return oldop;
 }
 
@@ -173,9 +158,8 @@ static inline int setsr(int sr)
 {
        int oldsr;
 
-       vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX);
-       oldsr = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, sr);
+       oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
+       vga_io_w(VGA_GFX_D, sr);
        return oldsr;
 }
 
@@ -184,28 +168,27 @@ static inline int setcolor(int color)
 {
        int oldcolor;
 
-       vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX);
-       oldcolor = vga_io_r(GRAPHICS_DATA_REG);
-       vga_io_w(GRAPHICS_DATA_REG, color);
+       oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
+       vga_io_w(VGA_GFX_D, color);
        return oldcolor;
 }
 
 /* Return the value in the Graphics Address Register. */
 static inline int getindex(void)
 {
-       return vga_io_r(GRAPHICS_ADDR_REG);
+       return vga_io_r(VGA_GFX_I);
 }
 
 /* Set the value in the Graphics Address Register. */
 static inline void setindex(int index)
 {
-       vga_io_w(GRAPHICS_ADDR_REG, index);
+       vga_io_w(VGA_GFX_I, index);
 }
 
 static void vga16fb_pan_var(struct fb_info *info, 
                            struct fb_var_screeninfo *var)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        u32 xoffset, pos;
 
        xoffset = var->xoffset;
@@ -265,7 +248,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
                               const struct fb_info *info,
                               int mul, int div)
 {
-       static struct {
+       static const struct {
                u32 pixclock;
                u8  misc;
                u8  seq_clock_mode;
@@ -300,29 +283,29 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
 
 static int vga16fb_open(struct fb_info *info, int user)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
-       int cnt = atomic_read(&par->ref_count);
+       struct vga16fb_par *par = info->par;
 
-       if (!cnt) {
+       if (!par->ref_count) {
                memset(&par->state, 0, sizeof(struct vgastate));
                par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
                        VGA_SAVE_CMAP;
                save_vga(&par->state);
        }
-       atomic_inc(&par->ref_count);
+       par->ref_count++;
+
        return 0;
 }
 
 static int vga16fb_release(struct fb_info *info, int user)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
-       int cnt = atomic_read(&par->ref_count);
+       struct vga16fb_par *par = info->par;
 
-       if (!cnt)
+       if (!par->ref_count)
                return -EINVAL;
-       if (cnt == 1)
+
+       if (par->ref_count == 1)
                restore_vga(&par->state);
-       atomic_dec(&par->ref_count);
+       par->ref_count--;
 
        return 0;
 }
@@ -330,7 +313,7 @@ static int vga16fb_release(struct fb_info *info, int user)
 static int vga16fb_check_var(struct fb_var_screeninfo *var,
                             struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        u32 xres, right, hslen, left, xtotal;
        u32 yres, lower, vslen, upper, ytotal;
        u32 vxres, xoffset, vyres, yoffset;
@@ -535,7 +518,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var,
 
 static int vga16fb_set_par(struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        u8 gdc[VGA_GFX_C];
        u8 seq[VGA_SEQ_C];
        u8 atc[VGA_ATT_C];
@@ -653,7 +636,7 @@ static int vga16fb_set_par(struct fb_info *info)
 
 static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 {
-       static unsigned char map[] = { 000, 001, 010, 011 };
+       static const unsigned char map[] = { 000, 001, 010, 011 };
        int val;
        
        if (regno >= 16)
@@ -667,17 +650,17 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b
 
 static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 {
-       outb(regno,       dac_reg);
-       outb(red   >> 10, dac_val);
-       outb(green >> 10, dac_val);
-       outb(blue  >> 10, dac_val);
+       outb(regno,       VGA_PEL_IW);
+       outb(red   >> 10, VGA_PEL_D);
+       outb(green >> 10, VGA_PEL_D);
+       outb(blue  >> 10, VGA_PEL_D);
 }
 
 static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                             unsigned blue, unsigned transp,
                             struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        int gray;
 
        /*
@@ -706,15 +689,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 static int vga16fb_pan_display(struct fb_var_screeninfo *var,
                               struct fb_info *info) 
 {
-       if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-           var->yoffset + info->var.yres > info->var.yres_virtual)
-               return -EINVAL;
-
        vga16fb_pan_var(info, var);
-
-       info->var.xoffset = var->xoffset;
-       info->var.yoffset = var->yoffset;
-       info->var.vmode &= ~FB_VMODE_YWRAP;
        return 0;
 }
 
@@ -722,28 +697,15 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var,
    blanking code was originally by Huang shi chao, and modified by
    Christoph Rimek (chrimek@toppoint.de) and todd j. derr
    (tjd@barefoot.org) for Linux. */
-#define attrib_port            VGA_ATC_IW
-#define seq_port_reg           VGA_SEQ_I
-#define seq_port_val           VGA_SEQ_D
-#define gr_port_reg            VGA_GFX_I
-#define gr_port_val            VGA_GFX_D
-#define video_misc_rd          VGA_MIS_R
-#define video_misc_wr          VGA_MIS_W
-#define vga_video_port_reg     VGA_CRT_IC
-#define vga_video_port_val     VGA_CRT_DC
 
 static void vga_vesa_blank(struct vga16fb_par *par, int mode)
 {
-       unsigned char SeqCtrlIndex;
-       unsigned char CrtCtrlIndex;
+       unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+       unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
        
-       //cli();
-       SeqCtrlIndex = vga_io_r(seq_port_reg);
-       CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
        /* save original values of VGA controller registers */
        if(!par->vesa_blanked) {
-               par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd);
+               par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
                //sti();
 
                par->vga_state.HorizontalTotal = vga_io_rcrt(0x00);     /* HorizontalTotal */
@@ -759,12 +721,11 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
 
        /* assure that video is enabled */
        /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
-       //cli();
        vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
 
        /* test for vertical retrace in process.... */
        if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
-               vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef);
+               vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
 
        /*
         * Set <End of vertical retrace> to minimum (0) and
@@ -772,12 +733,10 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
         * Result: turn off vertical sync (VSync) pulse.
         */
        if (mode & FB_BLANK_VSYNC_SUSPEND) {
-               outb_p(0x10,vga_video_port_reg);        /* StartVertRetrace */
-               outb_p(0xff,vga_video_port_val);        /* maximum value */
-               outb_p(0x11,vga_video_port_reg);        /* EndVertRetrace */
-               outb_p(0x40,vga_video_port_val);        /* minimum (bits 0..3)  */
-               outb_p(0x07,vga_video_port_reg);        /* Overflow */
-               outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+               vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
+               vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
+               /* bits 9,10 of vert. retrace */
+               vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
        }
 
        if (mode & FB_BLANK_HSYNC_SUSPEND) {
@@ -786,29 +745,22 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
                 *  <Start of horizontal Retrace> to maximum
                 * Result: turn off horizontal sync (HSync) pulse.
                 */
-               outb_p(0x04,vga_video_port_reg);        /* StartHorizRetrace */
-               outb_p(0xff,vga_video_port_val);        /* maximum */
-               outb_p(0x05,vga_video_port_reg);        /* EndHorizRetrace */
-               outb_p(0x00,vga_video_port_val);        /* minimum (0) */
+               vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
+               vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
        }
 
        /* restore both index registers */
-       outb_p(SeqCtrlIndex,seq_port_reg);
-       outb_p(CrtCtrlIndex,vga_video_port_reg);
-       //sti();
+       outb_p(SeqCtrlIndex, VGA_SEQ_I);
+       outb_p(CrtCtrlIndex, VGA_CRT_IC);
 }
 
 static void vga_vesa_unblank(struct vga16fb_par *par)
 {
-       unsigned char SeqCtrlIndex;
-       unsigned char CrtCtrlIndex;
+       unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+       unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
        
-       //cli();
-       SeqCtrlIndex = vga_io_r(seq_port_reg);
-       CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
        /* restore original values of VGA controller registers */
-       vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO);
+       vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
 
        /* HorizontalTotal */
        vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
@@ -830,9 +782,8 @@ static void vga_vesa_unblank(struct vga16fb_par *par)
        vga_io_wseq(0x01, par->vga_state.ClockingMode);
 
        /* restore index/control registers */
-       vga_io_w(seq_port_reg, SeqCtrlIndex);
-       vga_io_w(vga_video_port_reg, CrtCtrlIndex);
-       //sti();
+       vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
+       vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
 }
 
 static void vga_pal_blank(void)
@@ -840,17 +791,17 @@ static void vga_pal_blank(void)
        int i;
 
        for (i=0; i<16; i++) {
-               outb_p (i, dac_reg) ;
-               outb_p (0, dac_val) ;
-               outb_p (0, dac_val) ;
-               outb_p (0, dac_val) ;
+               outb_p(i, VGA_PEL_IW);
+               outb_p(0, VGA_PEL_D);
+               outb_p(0, VGA_PEL_D);
+               outb_p(0, VGA_PEL_D);
        }
 }
 
 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
 static int vga16fb_blank(int blank, struct fb_info *info)
 {
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
 
        switch (blank) {
        case FB_BLANK_UNBLANK:                          /* Unblank */
@@ -1090,12 +1041,15 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
        width = x2 - dx;
        height = y2 - dy;
 
+       if (sx + dx < old_dx || sy + dy < old_dy)
+               return;
+
        /* update sx1,sy1 */
        sx += (dx - old_dx);
        sy += (dy - old_dy);
 
        /* the source must be completely inside the virtual screen */
-       if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
+       if (sx + width > vxres || sy + height > vyres)
                return;
 
        switch (info->fix.type) {
@@ -1148,23 +1102,19 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
        }
 }
 
-#ifdef __LITTLE_ENDIAN
-static unsigned int transl_l[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_h[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
-#else
-#ifdef __BIG_ENDIAN
-static unsigned int transl_h[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_l[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
+#define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
+#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
+                        0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
+
+#if defined(__LITTLE_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_LOW;
+static const u16 transl_h[] = TRANS_MASK_HIGH;
+#elif defined(__BIG_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_HIGH;
+static const u16 transl_h[] = TRANS_MASK_LOW;
 #else
 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
 #endif
-#endif
 
 static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
 {
@@ -1201,7 +1151,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im
 {
        char __iomem *where = info->screen_base + (image->dx/8) +
                image->dy * info->fix.line_length;
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        char *cdat = (char *) image->data;
        char __iomem *dst;
        int x, y;
@@ -1266,7 +1216,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima
        /*
         * Draw logo 
         */
-       struct vga16fb_par *par = (struct vga16fb_par *) info->par;
+       struct vga16fb_par *par = info->par;
        char __iomem *where =
                info->screen_base + image->dy * info->fix.line_length +
                image->dx/8;
@@ -1326,7 +1276,6 @@ static struct fb_ops vga16fb_ops = {
        .fb_fillrect    = vga16fb_fillrect,
        .fb_copyarea    = vga16fb_copyarea,
        .fb_imageblit   = vga16fb_imageblit,
-       .fb_cursor      = soft_cursor,
 };
 
 #ifndef MODULE
@@ -1344,91 +1293,152 @@ static int vga16fb_setup(char *options)
 }
 #endif
 
-static int __init vga16fb_init(void)
+static int __init vga16fb_probe(struct platform_device *dev)
 {
+       struct fb_info *info;
+       struct vga16fb_par *par;
        int i;
-       int ret;
-#ifndef MODULE
-       char *option = NULL;
-
-       if (fb_get_options("vga16fb", &option))
-               return -ENODEV;
+       int ret = 0;
 
-       vga16fb_setup(option);
-#endif
        printk(KERN_DEBUG "vga16fb: initializing\n");
+       info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
+
+       if (!info) {
+               ret = -ENOMEM;
+               goto err_fb_alloc;
+       }
 
        /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
+       info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
 
-       vga16fb.screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS);
-       if (!vga16fb.screen_base) {
+       if (!info->screen_base) {
                printk(KERN_ERR "vga16fb: unable to map device\n");
                ret = -ENOMEM;
                goto err_ioremap;
        }
-       printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base);
 
-       vga16_par.isVGA = ORIG_VIDEO_ISVGA;
-       vga16_par.palette_blanked = 0;
-       vga16_par.vesa_blanked = 0;
+       printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
+       par = info->par;
+
+       par->isVGA = screen_info.orig_video_isVGA;
+       par->palette_blanked = 0;
+       par->vesa_blanked = 0;
 
-       i = vga16_par.isVGA? 6 : 2;
+       i = par->isVGA? 6 : 2;
        
        vga16fb_defined.red.length   = i;
        vga16fb_defined.green.length = i;
        vga16fb_defined.blue.length  = i;       
 
        /* name should not depend on EGA/VGA */
-       vga16fb.fbops = &vga16fb_ops;
-       vga16fb.var = vga16fb_defined;
-       vga16fb.fix = vga16fb_fix;
-       vga16fb.par = &vga16_par;
-       vga16fb.flags = FBINFO_FLAG_DEFAULT |
+       info->fbops = &vga16fb_ops;
+       info->var = vga16fb_defined;
+       info->fix = vga16fb_fix;
+       /* supports rectangles with widths of multiples of 8 */
+       info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
+       info->flags = FBINFO_FLAG_DEFAULT |
                FBINFO_HWACCEL_YPAN;
 
-       i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16;
-       ret = fb_alloc_cmap(&vga16fb.cmap, i, 0);
+       i = (info->var.bits_per_pixel == 8) ? 256 : 16;
+       ret = fb_alloc_cmap(&info->cmap, i, 0);
        if (ret) {
                printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
                ret = -ENOMEM;
                goto err_alloc_cmap;
        }
 
-       if (vga16fb_check_var(&vga16fb.var, &vga16fb)) {
+       if (vga16fb_check_var(&info->var, info)) {
                printk(KERN_ERR "vga16fb: unable to validate variable\n");
                ret = -EINVAL;
                goto err_check_var;
        }
 
-       vga16fb_update_fix(&vga16fb);
+       vga16fb_update_fix(info);
 
-       if (register_framebuffer(&vga16fb) < 0) {
+       if (register_framebuffer(info) < 0) {
                printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
                ret = -EINVAL;
                goto err_check_var;
        }
 
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
-              vga16fb.node, vga16fb.fix.id);
+              info->node, info->fix.id);
+       platform_set_drvdata(dev, info);
 
        return 0;
 
  err_check_var:
-       fb_dealloc_cmap(&vga16fb.cmap);
+       fb_dealloc_cmap(&info->cmap);
  err_alloc_cmap:
-       iounmap(vga16fb.screen_base);
+       iounmap(info->screen_base);
  err_ioremap:
+       framebuffer_release(info);
+ err_fb_alloc:
+       return ret;
+}
+
+static int vga16fb_remove(struct platform_device *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+
+       if (info) {
+               unregister_framebuffer(info);
+               iounmap(info->screen_base);
+               fb_dealloc_cmap(&info->cmap);
+       /* XXX unshare VGA regions */
+               framebuffer_release(info);
+       }
+
+       return 0;
+}
+
+static struct platform_driver vga16fb_driver = {
+       .probe = vga16fb_probe,
+       .remove = vga16fb_remove,
+       .driver = {
+               .name = "vga16fb",
+       },
+};
+
+static struct platform_device *vga16fb_device;
+
+static int __init vga16fb_init(void)
+{
+       int ret;
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("vga16fb", &option))
+               return -ENODEV;
+
+       vga16fb_setup(option);
+#endif
+       ret = platform_driver_register(&vga16fb_driver);
+
+       if (!ret) {
+               vga16fb_device = platform_device_alloc("vga16fb", 0);
+
+               if (vga16fb_device)
+                       ret = platform_device_add(vga16fb_device);
+               else
+                       ret = -ENOMEM;
+
+               if (ret) {
+                       platform_device_put(vga16fb_device);
+                       platform_driver_unregister(&vga16fb_driver);
+               }
+       }
+
        return ret;
 }
 
 static void __exit vga16fb_exit(void)
 {
-    unregister_framebuffer(&vga16fb);
-    iounmap(vga16fb.screen_base);
-    fb_dealloc_cmap(&vga16fb.cmap);
-    /* XXX unshare VGA regions */
+       platform_device_unregister(vga16fb_device);
+       platform_driver_unregister(&vga16fb_driver);
 }
 
+MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
 MODULE_LICENSE("GPL");
 module_init(vga16fb_init);
 module_exit(vga16fb_exit);