summaryrefslogtreecommitdiffstats
path: root/drivers/sgi/char/usema.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sgi/char/usema.c')
-rw-r--r--drivers/sgi/char/usema.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c
index dfef772eb..262f5724f 100644
--- a/drivers/sgi/char/usema.c
+++ b/drivers/sgi/char/usema.c
@@ -27,6 +27,197 @@
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/dcache.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/smp_lock.h>
+#include <asm/usioctl.h>
+#include <asm/mman.h>
+#include <asm/uaccess.h>
+
+struct irix_usema {
+ struct file *filp;
+ struct wait_queue *proc_list;
+};
+
+static int
+sgi_usema_attach (usattach_t * attach, struct irix_usema *usema)
+{
+ int newfd;
+ newfd = get_unused_fd();
+ if (newfd < 0)
+ return newfd;
+
+ current->files->fd [newfd] = usema->filp;
+ usema->filp->f_count++;
+ /* Is that it? */
+ printk("UIOCATTACHSEMA: new usema fd is %d", newfd);
+ return newfd;
+}
+
+static int
+sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct irix_usema *usema = file->private_data;
+ int retval;
+
+ printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
+ current->comm, current->pid, cmd, arg);
+
+ switch(cmd) {
+ case UIOCATTACHSEMA: {
+ /* They pass us information about the semaphore to
+ which they wish to be attached, and we create&return
+ a new fd corresponding to the appropriate semaphore.
+ */
+ usattach_t *attach = (usattach_t *)arg;
+ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
+ if (retval) {
+ printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
+ "verify_area failure",
+ current->comm, current->pid);
+ return retval;
+ }
+ if (usema == 0)
+ return -EINVAL;
+
+ printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid);
+ /* XXX what is attach->us_handle for? */
+ return sgi_usema_attach(attach, usema);
+ break;
+ }
+ case UIOCABLOCK: /* XXX make `async' */
+ case UIOCNOIBLOCK: /* XXX maybe? */
+ case UIOCBLOCK: {
+ /* Block this process on the semaphore */
+ usattach_t *attach = (usattach_t *)arg;
+
+ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
+ if (retval) {
+ printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
+ "verify_area failure",
+ current->comm, current->pid);
+ return retval;
+ }
+ printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
+ current->pid, usema);
+ if (cmd == UIOCNOIBLOCK)
+ interruptible_sleep_on(&usema->proc_list);
+ else
+ sleep_on(&usema->proc_list);
+ return 0;
+ }
+ case UIOCAUNBLOCK: /* XXX make `async' */
+ case UIOCUNBLOCK: {
+ /* Wake up all process waiting on this semaphore */
+ usattach_t *attach = (usattach_t *)arg;
+
+ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
+ if (retval) {
+ printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
+ "verify_area failure",
+ current->comm, current->pid);
+ return retval;
+ }
+
+ printk("[%s:%d] releasing usema %p",
+ current->comm, current->pid, usema);
+ wake_up(&usema->proc_list);
+ return 0;
+ }
+ }
+ return -ENOSYS;
+}
+
+static unsigned int
+sgi_usemaclone_poll(struct file *filp, poll_table *wait)
+{
+ struct irix_usema *usema = filp->private_data;
+
+ printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema);
+
+ return 0;
+}
+
+static int
+sgi_usemaclone_open(struct inode *inode, struct file *filp)
+{
+ struct irix_usema *usema;
+
+ usema = kmalloc (sizeof (struct irix_usema), GFP_KERNEL);
+ if (!usema)
+ return -ENOMEM;
+
+ usema->filp = filp;
+ usema->proc_list = NULL;
+ filp->private_data = usema;
+ return 0;
+}
+
+static int
+sgi_usemaclone_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+struct file_operations sgi_usemaclone_fops = {
+ NULL, /* llseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ sgi_usemaclone_poll, /* poll */
+ sgi_usemaclone_ioctl, /* ioctl */
+ NULL, /* mmap */
+ sgi_usemaclone_open, /* open */
+ sgi_usemaclone_release, /* release */
+ NULL, /* fsync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL /* lock */
+};
+
+static struct miscdevice dev_usemaclone = {
+ SGI_USEMACLONE, "usemaclone", &sgi_usemaclone_fops
+};
+
+void
+usema_init(void)
+{
+ printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE);
+ misc_register(&dev_usemaclone);
+}
+/*
+ * usema.c: software semaphore driver (see IRIX's usema(7M))
+ * written 1997 Mike Shaver (shaver@neon.ingenia.ca)
+ * 1997 Miguel de Icaza (miguel@kernel.org)
+ *
+ * This file contains the implementation of /dev/usemaclone,
+ * the devices used by IRIX's us* semaphore routines.
+ *
+ * /dev/usemaclone is used to create a new semaphore device, and then
+ * the semaphore is manipulated via ioctls.
+ *
+ * At least for the zero-contention case, lock set and unset as well
+ * as semaphore P and V are done in userland, which makes things a
+ * little bit better. I suspect that the ioctls are used to register
+ * the process as blocking, etc.
+ *
+ * Much inspiration and structure stolen from Miguel's shmiq work.
+ *
+ * For more information:
+ * usema(7m), usinit(3p), usnewsema(3p)
+ * /usr/include/sys/usioctl.h
+ *
+*/
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/major.h>
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/dcache.h>