ia64/xen-unstable

view linux-2.6-xen-sparse/arch/xen/kernel/devmem.c @ 7514:5a4893a537ca

Minor driver code changes/rearrangement to reduce ia64-specific patches
Signed-off by: Dan Magenheimer <dan.magenheimer@hp.com>
author djm@kirby.fc.hp.com
date Fri Nov 04 10:40:29 2005 -0600 (2005-11-04)
parents 61b3b357d827
children 9f4efb238f5b
line source
1 /*
2 * Originally from linux/drivers/char/mem.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * Added devfs support.
7 * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
8 * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
9 */
11 #include <linux/config.h>
12 #include <linux/mm.h>
13 #include <linux/miscdevice.h>
14 #include <linux/slab.h>
15 #include <linux/vmalloc.h>
16 #include <linux/mman.h>
17 #include <linux/random.h>
18 #include <linux/init.h>
19 #include <linux/raw.h>
20 #include <linux/tty.h>
21 #include <linux/capability.h>
22 #include <linux/smp_lock.h>
23 #include <linux/devfs_fs_kernel.h>
24 #include <linux/ptrace.h>
25 #include <linux/device.h>
26 #include <asm/pgalloc.h>
27 #include <asm/uaccess.h>
28 #include <asm/io.h>
29 #include <asm/hypervisor.h>
31 static inline int uncached_access(struct file *file)
32 {
33 if (file->f_flags & O_SYNC)
34 return 1;
35 /* Xen sets correct MTRR type on non-RAM for us. */
36 return 0;
37 }
39 /*
40 * This funcion reads the *physical* memory. The f_pos points directly to the
41 * memory location.
42 */
43 static ssize_t read_mem(struct file * file, char __user * buf,
44 size_t count, loff_t *ppos)
45 {
46 unsigned long i, p = *ppos;
47 ssize_t read = -EFAULT;
48 void *v;
50 if ((v = ioremap(p, count)) == NULL) {
51 /*
52 * Some programs (e.g., dmidecode) groove off into weird RAM
53 * areas where no table scan possibly exist (because Xen will
54 * have stomped on them!). These programs get rather upset if
55 * we let them know that Xen failed their access, so we fake
56 * out a read of all zeroes. :-)
57 */
58 for (i = 0; i < count; i++)
59 if (put_user(0, buf+i))
60 return -EFAULT;
61 return count;
62 }
63 if (copy_to_user(buf, v, count))
64 goto out;
66 read = count;
67 *ppos += read;
68 out:
69 iounmap(v);
70 return read;
71 }
73 static ssize_t write_mem(struct file * file, const char __user * buf,
74 size_t count, loff_t *ppos)
75 {
76 unsigned long p = *ppos;
77 ssize_t written = -EFAULT;
78 void *v;
80 if ((v = ioremap(p, count)) == NULL)
81 return -EFAULT;
82 if (copy_to_user(v, buf, count))
83 goto out;
85 written = count;
86 *ppos += written;
87 out:
88 iounmap(v);
89 return written;
90 }
92 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
93 {
94 if (uncached_access(file))
95 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
97 if (direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
98 vma->vm_end - vma->vm_start,
99 vma->vm_page_prot, DOMID_IO))
100 return -EAGAIN;
102 return 0;
103 }
105 /*
106 * The memory devices use the full 32/64 bits of the offset, and so we cannot
107 * check against negative addresses: they are ok. The return value is weird,
108 * though, in that case (0).
109 *
110 * also note that seeking relative to the "end of file" isn't supported:
111 * it has no meaning, so it returns -EINVAL.
112 */
113 static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
114 {
115 loff_t ret;
117 down(&file->f_dentry->d_inode->i_sem);
118 switch (orig) {
119 case 0:
120 file->f_pos = offset;
121 ret = file->f_pos;
122 force_successful_syscall_return();
123 break;
124 case 1:
125 file->f_pos += offset;
126 ret = file->f_pos;
127 force_successful_syscall_return();
128 break;
129 default:
130 ret = -EINVAL;
131 }
132 up(&file->f_dentry->d_inode->i_sem);
133 return ret;
134 }
136 static int open_mem(struct inode * inode, struct file * filp)
137 {
138 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
139 }
141 struct file_operations mem_fops = {
142 .llseek = memory_lseek,
143 .read = read_mem,
144 .write = write_mem,
145 .mmap = mmap_mem,
146 .open = open_mem,
147 };
149 /*
150 * Local variables:
151 * c-file-style: "linux"
152 * indent-tabs-mode: t
153 * c-indent-level: 8
154 * c-basic-offset: 8
155 * tab-width: 8
156 * End:
157 */