libata-scsi: be tolerant of 12-byte ATAPI commands in 16-byte CDBs
[pandora-kernel.git] / drivers / video / vfb.c
index 77eed1f..072638a 100644 (file)
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/tty.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
-#include <asm/uaccess.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 
@@ -39,6 +37,48 @@ static void *videomemory;
 static u_long videomemorysize = VIDEOMEMSIZE;
 module_param(videomemorysize, ulong, 0);
 
+/**********************************************************************
+ *
+ * Memory management
+ *
+ **********************************************************************/
+static void *rvmalloc(unsigned long size)
+{
+       void *mem;
+       unsigned long adr;
+
+       size = PAGE_ALIGN(size);
+       mem = vmalloc_32(size);
+       if (!mem)
+               return NULL;
+
+       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+       adr = (unsigned long) mem;
+       while (size > 0) {
+               SetPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+       unsigned long adr;
+
+       if (!mem)
+               return;
+
+       adr = (unsigned long) mem;
+       while ((long) size > 0) {
+               ClearPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+       vfree(mem);
+}
+
 static struct fb_var_screeninfo vfb_default __initdata = {
        .xres =         640,
        .yres =         480,
@@ -85,13 +125,15 @@ static int vfb_mmap(struct fb_info *info,
                    struct vm_area_struct *vma);
 
 static struct fb_ops vfb_ops = {
+       .fb_read        = fb_sys_read,
+       .fb_write       = fb_sys_write,
        .fb_check_var   = vfb_check_var,
        .fb_set_par     = vfb_set_par,
        .fb_setcolreg   = vfb_setcolreg,
        .fb_pan_display = vfb_pan_display,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = sys_fillrect,
+       .fb_copyarea    = sys_copyarea,
+       .fb_imageblit   = sys_imageblit,
        .fb_mmap        = vfb_mmap,
 };
 
@@ -371,7 +413,33 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
 static int vfb_mmap(struct fb_info *info,
                    struct vm_area_struct *vma)
 {
-       return -EINVAL;
+       unsigned long start = vma->vm_start;
+       unsigned long size = vma->vm_end - vma->vm_start;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       unsigned long page, pos;
+
+       if (offset + size > info->fix.smem_len) {
+               return -EINVAL;
+       }
+
+       pos = (unsigned long)info->fix.smem_start + offset;
+
+       while (size > 0) {
+               page = vmalloc_to_pfn((void *)pos);
+               if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+                       return -EAGAIN;
+               }
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+
+       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
+       return 0;
+
 }
 
 #ifndef MODULE
@@ -398,12 +466,6 @@ static int __init vfb_setup(char *options)
      *  Initialisation
      */
 
-static void vfb_platform_release(struct device *device)
-{
-       // This is called when the reference count goes to zero.
-       dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n");
-}
-
 static int __init vfb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
@@ -412,7 +474,7 @@ static int __init vfb_probe(struct platform_device *dev)
        /*
         * For real video cards we use ioremap.
         */
-       if (!(videomemory = vmalloc(videomemorysize)))
+       if (!(videomemory = rvmalloc(videomemorysize)))
                return retval;
 
        /*
@@ -435,6 +497,8 @@ static int __init vfb_probe(struct platform_device *dev)
 
        if (!retval || (retval == 4))
                info->var = vfb_default;
+       vfb_fix.smem_start = (unsigned long) videomemory;
+       vfb_fix.smem_len = videomemorysize;
        info->fix = vfb_fix;
        info->pseudo_palette = info->par;
        info->par = NULL;
@@ -458,7 +522,7 @@ err2:
 err1:
        framebuffer_release(info);
 err:
-       vfree(videomemory);
+       rvfree(videomemory, videomemorysize);
        return retval;
 }
 
@@ -468,7 +532,7 @@ static int vfb_remove(struct platform_device *dev)
 
        if (info) {
                unregister_framebuffer(info);
-               vfree(videomemory);
+               rvfree(videomemory, videomemorysize);
                framebuffer_release(info);
        }
        return 0;
@@ -482,13 +546,7 @@ static struct platform_driver vfb_driver = {
        },
 };
 
-static struct platform_device vfb_device = {
-       .name   = "vfb",
-       .id     = 0,
-       .dev    = {
-               .release = vfb_platform_release,
-       }
-};
+static struct platform_device *vfb_device;
 
 static int __init vfb_init(void)
 {
@@ -508,10 +566,19 @@ static int __init vfb_init(void)
        ret = platform_driver_register(&vfb_driver);
 
        if (!ret) {
-               ret = platform_device_register(&vfb_device);
-               if (ret)
+               vfb_device = platform_device_alloc("vfb", 0);
+
+               if (vfb_device)
+                       ret = platform_device_add(vfb_device);
+               else
+                       ret = -ENOMEM;
+
+               if (ret) {
+                       platform_device_put(vfb_device);
                        platform_driver_unregister(&vfb_driver);
+               }
        }
+
        return ret;
 }
 
@@ -520,7 +587,7 @@ module_init(vfb_init);
 #ifdef MODULE
 static void __exit vfb_exit(void)
 {
-       platform_device_unregister(&vfb_device);
+       platform_device_unregister(vfb_device);
        platform_driver_unregister(&vfb_driver);
 }