ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / um / drivers / mmapper_kern.c
1 /*
2  * arch/um/drivers/mmapper_kern.c
3  *
4  * BRIEF MODULE DESCRIPTION
5  *
6  * Copyright (C) 2000 RidgeRun, Inc.
7  * Author: RidgeRun, Inc.
8  *         Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
9  *
10  */
11 #include <linux/kdev_t.h>
12 #include <linux/time.h>
13 #include <linux/devfs_fs_kernel.h>
14 #include <linux/module.h>
15 #include <linux/mm.h> 
16 #include <linux/slab.h>
17 #include <linux/init.h> 
18 #include <linux/smp_lock.h>
19 #include <asm/uaccess.h>
20 #include <asm/irq.h>
21 #include <asm/pgtable.h>
22 #include "mem_user.h"
23 #include "user_util.h"
24  
25 /* These are set in mmapper_init, which is called at boot time */
26 static unsigned long mmapper_size;
27 static unsigned long p_buf = 0;
28 static char *v_buf = NULL;
29
30 static ssize_t
31 mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos)
32 {
33         if(*ppos > mmapper_size)
34                 return -EINVAL;
35
36         if(count + *ppos > mmapper_size)
37                 count = count + *ppos - mmapper_size;
38
39         if(count < 0)
40                 return -EINVAL;
41  
42         copy_to_user(buf,&v_buf[*ppos],count);
43         
44         return count;
45 }
46
47 static ssize_t
48 mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
49 {
50         if(*ppos > mmapper_size)
51                 return -EINVAL;
52
53         if(count + *ppos > mmapper_size)
54                 count = count + *ppos - mmapper_size;
55
56         if(count < 0)
57                 return -EINVAL;
58
59         copy_from_user(&v_buf[*ppos],buf,count);
60         
61         return count;
62 }
63
64 static int 
65 mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
66          unsigned long arg)
67 {
68         return(-ENOIOCTLCMD);
69 }
70
71 static int 
72 mmapper_mmap(struct file *file, struct vm_area_struct * vma)
73 {
74         int ret = -EINVAL;
75         int size;
76
77         lock_kernel();
78         if (vma->vm_pgoff != 0)
79                 goto out;
80         
81         size = vma->vm_end - vma->vm_start;
82         if(size > mmapper_size) return(-EFAULT);
83
84         /* XXX A comment above remap_page_range says it should only be
85          * called when the mm semaphore is held
86          */
87         if (remap_page_range(vma, vma->vm_start, p_buf, size, 
88                              vma->vm_page_prot))
89                 goto out;
90         ret = 0;
91 out:
92         unlock_kernel();
93         return ret;
94 }
95
96 static int
97 mmapper_open(struct inode *inode, struct file *file)
98 {
99         return 0;
100 }
101
102 static int 
103 mmapper_release(struct inode *inode, struct file *file)
104 {
105         return 0;
106 }
107
108 static struct file_operations mmapper_fops = {
109         .owner          = THIS_MODULE,
110         .read           = mmapper_read,
111         .write          = mmapper_write,
112         .ioctl          = mmapper_ioctl,
113         .mmap           = mmapper_mmap,
114         .open           = mmapper_open,
115         .release        = mmapper_release,
116 };
117
118 static int __init mmapper_init(void)
119 {
120         printk(KERN_INFO "Mapper v0.1\n");
121
122         v_buf = (char *) find_iomem("mmapper", &mmapper_size);
123         if(mmapper_size == 0) return(0);
124
125         p_buf = __pa(v_buf);
126
127         devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper");
128         devfs_mk_symlink("mmapper0", "mmapper");
129         return(0);
130 }
131
132 static void mmapper_exit(void)
133 {
134 }
135
136 module_init(mmapper_init);
137 module_exit(mmapper_exit);
138
139 MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
140 MODULE_DESCRIPTION("DSPLinux simulator mmapper driver");
141 /*
142  * ---------------------------------------------------------------------------
143  * Local variables:
144  * c-file-style: "linux"
145  * End:
146  */