ia64/xen-unstable

view linux-2.6.7-xen-sparse/drivers/xen/evtchn/evtchn.c @ 1820:3d4f8eb89670

bitkeeper revision 1.1106.1.2 (40faa780dekT3E5arFwcbQDu1MbX6g)

Cleaned up Xen's instruction emulator.
author kaf24@scramble.cl.cam.ac.uk
date Sun Jul 18 16:38:24 2004 +0000 (2004-07-18)
parents 002fc84add90
children 6f08c0b6c8cd 3b0ab2e570a0 dae98734f12e
line source
1 /******************************************************************************
2 * evtchn.c
3 *
4 * Xenolinux driver for receiving and demuxing event-channel signals.
5 *
6 * Copyright (c) 2004, K A Fraser
7 */
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15 #include <linux/errno.h>
16 #include <linux/fs.h>
17 #include <linux/errno.h>
18 #include <linux/miscdevice.h>
19 #include <linux/major.h>
20 #include <linux/proc_fs.h>
21 #include <linux/stat.h>
22 #include <linux/poll.h>
23 #include <linux/irq.h>
24 #include <linux/init.h>
25 #include <linux/gfp.h>
26 #include <asm-xen/evtchn.h>
28 #if 0
29 /* NB. This must be shared amongst drivers if more things go in /dev/xen */
30 static devfs_handle_t xen_dev_dir;
31 #endif
33 /* Only one process may open /dev/xen/evtchn at any time. */
34 static unsigned long evtchn_dev_inuse;
36 /* Notification ring, accessed via /dev/xen/evtchn. */
37 #define RING_SIZE 2048 /* 2048 16-bit entries */
38 #define RING_MASK(_i) ((_i)&(RING_SIZE-1))
39 static u16 *ring;
40 static unsigned int ring_cons, ring_prod, ring_overflow;
42 /* Processes wait on this queue via /dev/xen/evtchn when ring is empty. */
43 static DECLARE_WAIT_QUEUE_HEAD(evtchn_wait);
44 static struct fasync_struct *evtchn_async_queue;
46 /* Which ports is user-space bound to? */
47 static u32 bound_ports[32];
49 static spinlock_t lock;
51 void evtchn_device_upcall(int port)
52 {
54 spin_lock(&lock);
56 mask_evtchn(port);
57 clear_evtchn(port);
59 if ( ring != NULL )
60 {
61 if ( (ring_prod - ring_cons) < RING_SIZE )
62 {
63 ring[RING_MASK(ring_prod)] = (u16)port;
64 if ( ring_cons == ring_prod++ )
65 {
66 wake_up_interruptible(&evtchn_wait);
67 kill_fasync(&evtchn_async_queue, SIGIO, POLL_IN);
68 }
69 }
70 else
71 {
72 ring_overflow = 1;
73 }
74 }
76 spin_unlock(&lock);
77 }
79 static void __evtchn_reset_buffer_ring(void)
80 {
81 /* Initialise the ring to empty. Clear errors. */
82 ring_cons = ring_prod = ring_overflow = 0;
83 }
85 static ssize_t evtchn_read(struct file *file, char *buf,
86 size_t count, loff_t *ppos)
87 {
88 int rc;
89 unsigned int c, p, bytes1 = 0, bytes2 = 0;
90 DECLARE_WAITQUEUE(wait, current);
92 add_wait_queue(&evtchn_wait, &wait);
94 count &= ~1; /* even number of bytes */
96 if ( count == 0 )
97 {
98 rc = 0;
99 goto out;
100 }
102 if ( count > PAGE_SIZE )
103 count = PAGE_SIZE;
105 for ( ; ; )
106 {
107 set_current_state(TASK_INTERRUPTIBLE);
109 if ( (c = ring_cons) != (p = ring_prod) )
110 break;
112 if ( ring_overflow )
113 {
114 rc = -EFBIG;
115 goto out;
116 }
118 if ( file->f_flags & O_NONBLOCK )
119 {
120 rc = -EAGAIN;
121 goto out;
122 }
124 if ( signal_pending(current) )
125 {
126 rc = -ERESTARTSYS;
127 goto out;
128 }
130 schedule();
131 }
133 /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
134 if ( ((c ^ p) & RING_SIZE) != 0 )
135 {
136 bytes1 = (RING_SIZE - RING_MASK(c)) * sizeof(u16);
137 bytes2 = RING_MASK(p) * sizeof(u16);
138 }
139 else
140 {
141 bytes1 = (p - c) * sizeof(u16);
142 bytes2 = 0;
143 }
145 /* Truncate chunks according to caller's maximum byte count. */
146 if ( bytes1 > count )
147 {
148 bytes1 = count;
149 bytes2 = 0;
150 }
151 else if ( (bytes1 + bytes2) > count )
152 {
153 bytes2 = count - bytes1;
154 }
156 if ( copy_to_user(buf, &ring[RING_MASK(c)], bytes1) ||
157 ((bytes2 != 0) && copy_to_user(&buf[bytes1], &ring[0], bytes2)) )
158 {
159 rc = -EFAULT;
160 goto out;
161 }
163 ring_cons += (bytes1 + bytes2) / sizeof(u16);
165 rc = bytes1 + bytes2;
167 out:
168 __set_current_state(TASK_RUNNING);
169 remove_wait_queue(&evtchn_wait, &wait);
170 return rc;
171 }
173 static ssize_t evtchn_write(struct file *file, const char *buf,
174 size_t count, loff_t *ppos)
175 {
176 int rc, i;
177 u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
179 if ( kbuf == NULL )
180 return -ENOMEM;
182 count &= ~1; /* even number of bytes */
184 if ( count == 0 )
185 {
186 rc = 0;
187 goto out;
188 }
190 if ( count > PAGE_SIZE )
191 count = PAGE_SIZE;
193 if ( copy_from_user(kbuf, buf, count) != 0 )
194 {
195 rc = -EFAULT;
196 goto out;
197 }
199 spin_lock_irq(&lock);
200 for ( i = 0; i < (count/2); i++ )
201 if ( test_bit(kbuf[i], (unsigned long *)&bound_ports[0]) )
202 unmask_evtchn(kbuf[i]);
203 spin_unlock_irq(&lock);
205 rc = count;
207 out:
208 free_page((unsigned long)kbuf);
209 return rc;
210 }
212 static int evtchn_ioctl(struct inode *inode, struct file *file,
213 unsigned int cmd, unsigned long arg)
214 {
215 int rc = 0;
217 spin_lock_irq(&lock);
219 switch ( cmd )
220 {
221 case EVTCHN_RESET:
222 __evtchn_reset_buffer_ring();
223 break;
224 case EVTCHN_BIND:
225 if ( !test_and_set_bit(arg, (unsigned long *)&bound_ports[0]) )
226 unmask_evtchn(arg);
227 else
228 rc = -EINVAL;
229 break;
230 case EVTCHN_UNBIND:
231 if ( test_and_clear_bit(arg, (unsigned long *)&bound_ports[0]) )
232 mask_evtchn(arg);
233 else
234 rc = -EINVAL;
235 break;
236 default:
237 rc = -ENOSYS;
238 break;
239 }
241 spin_unlock_irq(&lock);
243 return rc;
244 }
246 static unsigned int evtchn_poll(struct file *file, poll_table *wait)
247 {
248 unsigned int mask = POLLOUT | POLLWRNORM;
249 poll_wait(file, &evtchn_wait, wait);
250 if ( ring_cons != ring_prod )
251 mask |= POLLIN | POLLRDNORM;
252 if ( ring_overflow )
253 mask = POLLERR;
254 return mask;
255 }
257 static int evtchn_fasync(int fd, struct file *filp, int on)
258 {
259 return fasync_helper(fd, filp, on, &evtchn_async_queue);
260 }
262 static int evtchn_open(struct inode *inode, struct file *filp)
263 {
264 u16 *_ring;
266 if ( test_and_set_bit(0, &evtchn_dev_inuse) )
267 return -EBUSY;
269 /* Allocate outside locked region so that we can use GFP_KERNEL. */
270 if ( (_ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL )
271 return -ENOMEM;
273 spin_lock_irq(&lock);
274 ring = _ring;
275 __evtchn_reset_buffer_ring();
276 spin_unlock_irq(&lock);
278 MOD_INC_USE_COUNT;
280 return 0;
281 }
283 static int evtchn_release(struct inode *inode, struct file *filp)
284 {
285 int i;
287 spin_lock_irq(&lock);
288 if ( ring != NULL )
289 {
290 free_page((unsigned long)ring);
291 ring = NULL;
292 }
293 for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
294 if ( test_and_clear_bit(i, (unsigned long *)&bound_ports[0]) )
295 mask_evtchn(i);
296 spin_unlock_irq(&lock);
298 evtchn_dev_inuse = 0;
300 MOD_DEC_USE_COUNT;
302 return 0;
303 }
305 static struct file_operations evtchn_fops = {
306 owner: THIS_MODULE,
307 read: evtchn_read,
308 write: evtchn_write,
309 ioctl: evtchn_ioctl,
310 poll: evtchn_poll,
311 fasync: evtchn_fasync,
312 open: evtchn_open,
313 release: evtchn_release
314 };
316 static struct miscdevice evtchn_miscdev = {
317 .minor = EVTCHN_MINOR,
318 .name = "evtchn",
319 .devfs_name = "misc/evtchn",
320 .fops = &evtchn_fops
321 };
323 static int __init evtchn_init(void)
324 {
325 #if 0
326 devfs_handle_t symlink_handle;
327 int err, pos;
328 char link_dest[64];
329 #endif
330 int err;
332 /* (DEVFS) create '/dev/misc/evtchn'. */
333 err = misc_register(&evtchn_miscdev);
334 if ( err != 0 )
335 {
336 printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
337 return err;
338 }
340 #if 0
341 /* (DEVFS) create directory '/dev/xen'. */
342 xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
344 /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
345 pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
346 &link_dest[3],
347 sizeof(link_dest) - 3);
348 if ( pos >= 0 )
349 strncpy(&link_dest[pos], "../", 3);
351 /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
352 (void)devfs_mk_symlink(xen_dev_dir,
353 "evtchn",
354 DEVFS_FL_DEFAULT,
355 &link_dest[pos],
356 &symlink_handle,
357 NULL);
359 /* (DEVFS) automatically destroy the symlink with its destination. */
360 devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
361 #endif
363 printk("Event-channel device installed.\n");
365 return 0;
366 }
368 static void evtchn_cleanup(void)
369 {
370 misc_deregister(&evtchn_miscdev);
371 }
373 module_init(evtchn_init);
374 module_exit(evtchn_cleanup);