diff options
Diffstat (limited to 'drivers/video/vfb.c')
| -rw-r--r-- | drivers/video/vfb.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 64ee78c3c12b..072638a9528a 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 23 | 23 | ||
| 24 | #include <asm/uaccess.h> | ||
| 25 | #include <linux/fb.h> | 24 | #include <linux/fb.h> |
| 26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 27 | 26 | ||
| @@ -38,6 +37,48 @@ static void *videomemory; | |||
| 38 | static u_long videomemorysize = VIDEOMEMSIZE; | 37 | static u_long videomemorysize = VIDEOMEMSIZE; |
| 39 | module_param(videomemorysize, ulong, 0); | 38 | module_param(videomemorysize, ulong, 0); |
| 40 | 39 | ||
| 40 | /********************************************************************** | ||
| 41 | * | ||
| 42 | * Memory management | ||
| 43 | * | ||
| 44 | **********************************************************************/ | ||
| 45 | static void *rvmalloc(unsigned long size) | ||
| 46 | { | ||
| 47 | void *mem; | ||
| 48 | unsigned long adr; | ||
| 49 | |||
| 50 | size = PAGE_ALIGN(size); | ||
| 51 | mem = vmalloc_32(size); | ||
| 52 | if (!mem) | ||
| 53 | return NULL; | ||
| 54 | |||
| 55 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
| 56 | adr = (unsigned long) mem; | ||
| 57 | while (size > 0) { | ||
| 58 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
| 59 | adr += PAGE_SIZE; | ||
| 60 | size -= PAGE_SIZE; | ||
| 61 | } | ||
| 62 | |||
| 63 | return mem; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void rvfree(void *mem, unsigned long size) | ||
| 67 | { | ||
| 68 | unsigned long adr; | ||
| 69 | |||
| 70 | if (!mem) | ||
| 71 | return; | ||
| 72 | |||
| 73 | adr = (unsigned long) mem; | ||
| 74 | while ((long) size > 0) { | ||
| 75 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
| 76 | adr += PAGE_SIZE; | ||
| 77 | size -= PAGE_SIZE; | ||
| 78 | } | ||
| 79 | vfree(mem); | ||
| 80 | } | ||
| 81 | |||
| 41 | static struct fb_var_screeninfo vfb_default __initdata = { | 82 | static struct fb_var_screeninfo vfb_default __initdata = { |
| 42 | .xres = 640, | 83 | .xres = 640, |
| 43 | .yres = 480, | 84 | .yres = 480, |
| @@ -372,7 +413,33 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, | |||
| 372 | static int vfb_mmap(struct fb_info *info, | 413 | static int vfb_mmap(struct fb_info *info, |
| 373 | struct vm_area_struct *vma) | 414 | struct vm_area_struct *vma) |
| 374 | { | 415 | { |
| 375 | return -EINVAL; | 416 | unsigned long start = vma->vm_start; |
| 417 | unsigned long size = vma->vm_end - vma->vm_start; | ||
| 418 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
| 419 | unsigned long page, pos; | ||
| 420 | |||
| 421 | if (offset + size > info->fix.smem_len) { | ||
| 422 | return -EINVAL; | ||
| 423 | } | ||
| 424 | |||
| 425 | pos = (unsigned long)info->fix.smem_start + offset; | ||
| 426 | |||
| 427 | while (size > 0) { | ||
| 428 | page = vmalloc_to_pfn((void *)pos); | ||
| 429 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { | ||
| 430 | return -EAGAIN; | ||
| 431 | } | ||
| 432 | start += PAGE_SIZE; | ||
| 433 | pos += PAGE_SIZE; | ||
| 434 | if (size > PAGE_SIZE) | ||
| 435 | size -= PAGE_SIZE; | ||
| 436 | else | ||
| 437 | size = 0; | ||
| 438 | } | ||
| 439 | |||
| 440 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
| 441 | return 0; | ||
| 442 | |||
| 376 | } | 443 | } |
| 377 | 444 | ||
| 378 | #ifndef MODULE | 445 | #ifndef MODULE |
| @@ -407,7 +474,7 @@ static int __init vfb_probe(struct platform_device *dev) | |||
| 407 | /* | 474 | /* |
| 408 | * For real video cards we use ioremap. | 475 | * For real video cards we use ioremap. |
| 409 | */ | 476 | */ |
| 410 | if (!(videomemory = vmalloc(videomemorysize))) | 477 | if (!(videomemory = rvmalloc(videomemorysize))) |
| 411 | return retval; | 478 | return retval; |
| 412 | 479 | ||
| 413 | /* | 480 | /* |
| @@ -430,6 +497,8 @@ static int __init vfb_probe(struct platform_device *dev) | |||
| 430 | 497 | ||
| 431 | if (!retval || (retval == 4)) | 498 | if (!retval || (retval == 4)) |
| 432 | info->var = vfb_default; | 499 | info->var = vfb_default; |
| 500 | vfb_fix.smem_start = (unsigned long) videomemory; | ||
| 501 | vfb_fix.smem_len = videomemorysize; | ||
| 433 | info->fix = vfb_fix; | 502 | info->fix = vfb_fix; |
| 434 | info->pseudo_palette = info->par; | 503 | info->pseudo_palette = info->par; |
| 435 | info->par = NULL; | 504 | info->par = NULL; |
| @@ -453,7 +522,7 @@ err2: | |||
| 453 | err1: | 522 | err1: |
| 454 | framebuffer_release(info); | 523 | framebuffer_release(info); |
| 455 | err: | 524 | err: |
| 456 | vfree(videomemory); | 525 | rvfree(videomemory, videomemorysize); |
| 457 | return retval; | 526 | return retval; |
| 458 | } | 527 | } |
| 459 | 528 | ||
| @@ -463,7 +532,7 @@ static int vfb_remove(struct platform_device *dev) | |||
| 463 | 532 | ||
| 464 | if (info) { | 533 | if (info) { |
| 465 | unregister_framebuffer(info); | 534 | unregister_framebuffer(info); |
| 466 | vfree(videomemory); | 535 | rvfree(videomemory, videomemorysize); |
| 467 | framebuffer_release(info); | 536 | framebuffer_release(info); |
| 468 | } | 537 | } |
| 469 | return 0; | 538 | return 0; |
