/* * File Name : mmap.c * This includes the functions required for the memeory mapping system call. * Work done for final project, Course: CIS5930 * Course Name: Linux Kernel Programming & Device Driver Programming * Written by: Veena Adityan and Arthi Gokarn. * Submitted to: Dr. Baker * Date: 06/20/2003 * Copyright 2003 */ #include "pixelsmart.h" /* * Common VMA ops. */ extern struct pixelsmart *psmart; void pixelsmart_vma_open(struct vm_area_struct *vma) { MOD_INC_USE_COUNT; } void pixelsmart_vma_close(struct vm_area_struct *vma) { MOD_DEC_USE_COUNT; } /* * To prevent extension of the mapping, cause a bus signal to be sent to the * faulting process. */ struct page *pixelsmart_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) { return NOPAGE_SIGBUS; } static struct vm_operations_struct pixelsmart_vm_ops = { open: pixelsmart_vma_open, close: pixelsmart_vma_close, nopage: pixelsmart_vma_nopage, }; /* * Called by the memory map system call */ int pixelsmart_mmap(struct file *filp, struct vm_area_struct *vma) { struct video_device *dev = video_devdata(filp); struct pixelsmart *pstv = dev->priv; unsigned long off ; unsigned long physical; unsigned long vsize; unsigned long psize; if (down_interruptible(&pstv->sem)) return -ERESTARTSYS; off = vma->vm_pgoff << PAGE_SHIFT; physical = psmart->pixelsmart_adr + off; vsize = vma->vm_end - vma->vm_start; #ifdef DEBUG printk("<1>mmap 4 vsize= %ld\n, vm_end = %ld, vm_start = %ld, vm_pgoff=%ld",vsize,vma->vm_end,vma->vm_start,vma->vm_pgoff); #endif psize = 0x4000 - off; if(vsize > psize){ up(&pstv->sem); return -EINVAL; } if(remap_page_range(vma->vm_start, physical , vsize, vma->vm_page_prot)){ up(&pstv->sem); return -EAGAIN; } vma->vm_ops = &pixelsmart_vm_ops; pixelsmart_vma_open(vma); up(&pstv->sem); return 0; }