patch-2.4.22 linux-2.4.22/drivers/sgi/char/shmiq.c

Next file: linux-2.4.22/drivers/sgi/char/streamable.c
Previous file: linux-2.4.22/drivers/sgi/char/sgiserial.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/drivers/sgi/char/shmiq.c linux-2.4.22/drivers/sgi/char/shmiq.c
@@ -1,473 +0,0 @@
-/*
- * shmiq.c: shared memory input queue driver
- * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
- *
- * We implement /dev/shmiq, /dev/qcntlN here
- * this is different from IRIX that has shmiq as a misc
- * streams device and the and qcntl devices as a major device.
- *
- * minor number 0 implements /dev/shmiq,
- * any other number implements /dev/qcntl${minor-1}
- *
- * /dev/shmiq is used by the X server for two things:
- *
- *    1. for I_LINK()ing trough ioctl the file handle of a
- *       STREAMS device.
- *
- *    2. To send STREAMS-commands to the devices with the
- *       QIO ioctl interface.
- *
- * I have not yet figured how to make multiple X servers share
- * /dev/shmiq for having different servers running.  So, for now
- * I keep a kernel-global array of inodes that are pushed into
- * /dev/shmiq.
- *
- * /dev/qcntlN is used by the X server for two things:
- *
- *    1. Issuing the QIOCATTACH for mapping the shared input
- *       queue into the address space of the X server (yeah, yeah,
- *       I did not invent this interface).
- *
- *    2. used by select.  I bet it is used for checking for events on
- *       the queue.
- *
- * Now the problem is that there does not seem anything that
- * establishes a connection between /dev/shmiq and the qcntlN file.  I
- * need an strace from an X server that runs on a machine with more
- * than one keyboard.  And this is a problem since the file handles
- * are pushed in /dev/shmiq, while the events should be dispatched to
- * the /dev/qcntlN device.
- *
- * Until then, I just allow for 1 qcntl device.
- *
- */
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/sched.h>
-#include <linux/file.h>
-#include <linux/interrupt.h>
-#include <linux/poll.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-
-#include <asm/shmiq.h>
-#include <asm/gfx.h>
-#include <asm/mman.h>
-#include <asm/uaccess.h>
-#include <asm/poll.h>
-#include "graphics.h"
-
-/* we are not really getting any more than a few files in the shmiq */
-#define MAX_SHMIQ_DEVS 10
-
-/*
- * One per X server running, not going to get very big.
- * Even if we have this we now assume just 1 /dev/qcntl can be
- * active, I need to find how this works on multi-headed machines.
- */
-#define MAX_SHMI_QUEUES 4
-
-static struct {
-	int                 used;
-	struct file         *filp;
-	struct shmiqsetcpos cpos;
-} shmiq_pushed_devices [MAX_SHMIQ_DEVS];
-
-/* /dev/qcntlN attached memory regions, location and size of the event queue */
-static struct {
-	int    opened;		/* if this device has been opened */
-	void   *shmiq_vaddr;	/* mapping in kernel-land */
-	int    tail;		/* our copy of the shmiq->tail */
-	int    events;
-	int    mapped;
-
-	wait_queue_head_t    proc_list;
-	struct fasync_struct *fasync;
-} shmiqs [MAX_SHMI_QUEUES];
-
-void
-shmiq_push_event (struct shmqevent *e)
-{
-	struct sharedMemoryInputQueue *s;
-	int    device = 0;	/* FIXME: here is the assumption /dev/shmiq == /dev/qcntl0 */
-	int    tail_next;
-
-	if (!shmiqs [device].mapped)
-		return;
-	s = shmiqs [device].shmiq_vaddr;
-
-	s->flags = 0;
-	if (s->tail != shmiqs [device].tail){
-		s->flags |= SHMIQ_CORRUPTED;
-		return;
-	}
-	tail_next = (s->tail + 1) % (shmiqs [device].events);
-
-	if (tail_next == s->head){
-		s->flags |= SHMIQ_OVERFLOW;
-		return;
-	}
-
-	e->un.time = jiffies;
-	s->events [s->tail] = *e;
-	printk ("KERNEL: dev=%d which=%d type=%d flags=%d\n",
-		e->data.device, e->data.which, e->data.type, e->data.flags);
-	s->tail = tail_next;
-	shmiqs [device].tail = tail_next;
-	kill_fasync (&shmiqs [device].fasync, SIGIO, POLL_IN);
-	wake_up_interruptible (&shmiqs [device].proc_list);
-}
-
-static int
-shmiq_manage_file (struct file *filp)
-{
-	int i;
-
-	if (!filp->f_op || !filp->f_op->ioctl)
-		return -ENOSR;
-
-	for (i = 0; i < MAX_SHMIQ_DEVS; i++){
-		if (shmiq_pushed_devices [i].used)
-			continue;
-		if ((*filp->f_op->ioctl)(filp->f_dentry->d_inode, filp, SHMIQ_ON, i) != 0)
-			return -ENOSR;
-		shmiq_pushed_devices [i].used = 1;
-		shmiq_pushed_devices [i].filp = filp;
-		shmiq_pushed_devices [i].cpos.x = 0;
-		shmiq_pushed_devices [i].cpos.y = 0;
-		return i;
-	}
-	return -ENOSR;
-}
-
-static int
-shmiq_forget_file (unsigned long fdes)
-{
-	struct file *filp;
-
-	if (fdes > MAX_SHMIQ_DEVS)
-		return -EINVAL;
-
-	if (!shmiq_pushed_devices [fdes].used)
-		return -EINVAL;
-
-	filp = shmiq_pushed_devices [fdes].filp;
-	if (filp){
-		(*filp->f_op->ioctl)(filp->f_dentry->d_inode, filp, SHMIQ_OFF, 0);
-		shmiq_pushed_devices [fdes].filp = 0;
-		fput (filp);
-	}
-	shmiq_pushed_devices [fdes].used = 0;
-
-	return 0;
-}
-
-static int
-shmiq_sioc (int device, int cmd, struct strioctl *s)
-{
-	switch (cmd){
-	case QIOCGETINDX:
-		/*
-		 * Ok, we just return the index they are providing us
-		 */
-		printk ("QIOCGETINDX: returning %d\n", *(int *)s->ic_dp);
-		return 0;
-
-	case QIOCIISTR: {
-		struct muxioctl *mux = (struct muxioctl *) s->ic_dp;
-
-		printk ("Double indirect ioctl: [%d, %x\n", mux->index, mux->realcmd);
-		return -EINVAL;
-	}
-
-	case QIOCSETCPOS: {
-		if (copy_from_user (&shmiq_pushed_devices [device].cpos, s->ic_dp,
-				    sizeof (struct shmiqsetcpos)))
-			return -EFAULT;
-		return 0;
-	}
-	}
-	printk ("Unknown I_STR request for shmiq device: 0x%x\n", cmd);
-	return -EINVAL;
-}
-
-static int
-shmiq_ioctl (struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg)
-{
-	struct file *file;
-	struct strioctl sioc;
-	int v;
-
-	switch (cmd){
-		/*
-		 * They are giving us the file descriptor for one
-		 * of their streams devices
-		 */
-
-	case I_LINK:
-		file = fget (arg);
-		if (!file)
-			goto bad_file;
-
-		v = shmiq_manage_file (file);
-		if (v<0)
-			fput(file);
-		return v;
-
-		/*
-		 * Remove a device from our list of managed
-		 * stream devices
-		 */
-	case I_UNLINK:
-		v = shmiq_forget_file (arg);
-		return v;
-
-	case I_STR:
-		v = get_sioc (&sioc, arg);
-		if (v)
-			return v;
-
-		/* FIXME: This forces device = 0 */
-		return shmiq_sioc (0, sioc.ic_cmd, &sioc);
-	}
-
-	return -EINVAL;
-
-bad_file:
-	return -EBADF;
-}
-
-extern long sys_munmap(unsigned long addr, size_t len);
-
-static int
-qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg, int minor)
-{
-	struct shmiqreq req;
-	struct vm_area_struct *vma;
-	int v;
-
-	switch (cmd) {
-		/*
-		 * The address space is already mapped as a /dev/zero
-		 * mapping.  FIXME: check that /dev/zero is what the user
-		 * had mapped before :-)
-		 */
-		case QIOCATTACH: {
-			unsigned long vaddr;
-			int s;
-
-			v = verify_area (VERIFY_READ, (void *) arg,
-			                 sizeof (struct shmiqreq));
-			if (v)
-				return v;
-			if (copy_from_user(&req, (void *) arg, sizeof (req)))
-				return -EFAULT;
-			/*
-			 * Do not allow to attach to another region if it has
-			 * already been attached
-			 */
-			if (shmiqs [minor].mapped) {
-				printk("SHMIQ:The thingie is already mapped\n");
-				return -EINVAL;
-			}
-
-			vaddr = (unsigned long) req.user_vaddr;
-			vma = find_vma (current->mm, vaddr);
-			if (!vma) {
-				printk ("SHMIQ: could not find %lx the vma\n",
-				        vaddr);
-				return -EINVAL;
-			}
-			s = req.arg * sizeof (struct shmqevent) +
-			    sizeof (struct sharedMemoryInputQueue);
-			v = sys_munmap (vaddr, s);
-			down_write(&current->mm->mmap_sem);
-			do_munmap(current->mm, vaddr, s);
-			do_mmap(filp, vaddr, s, PROT_READ | PROT_WRITE,
-			        MAP_PRIVATE|MAP_FIXED, 0);
-			up_write(&current->mm->mmap_sem);
-			shmiqs[minor].events = req.arg;
-			shmiqs[minor].mapped = 1;
-
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-struct page *
-shmiq_nopage (struct vm_area_struct *vma, unsigned long address,
-              int write_access)
-{
-	/* Do not allow for mremap to expand us */
-	return NULL;
-}
-
-static struct vm_operations_struct qcntl_mmap = {
-	nopage:	shmiq_nopage,		/* our magic no-page fault handler */
-};
-
-static int
-shmiq_qcntl_mmap (struct file *file, struct vm_area_struct *vma)
-{
-	int           minor = MINOR (file->f_dentry->d_inode->i_rdev), error;
-	unsigned int  size;
-	unsigned long mem, start;
-
-	/* mmap is only supported on the qcntl devices */
-	if (minor-- == 0)
-		return -EINVAL;
-
-	if (vma->vm_pgoff != 0)
-		return -EINVAL;
-
-	size  = vma->vm_end - vma->vm_start;
-	start = vma->vm_start;
-	lock_kernel();
-	mem = (unsigned long) shmiqs [minor].shmiq_vaddr =  vmalloc_uncached (size);
-	if (!mem) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-
-	/* Prevent the swapper from considering these pages for swap and touching them */
-	vma->vm_flags    |= (VM_SHM  | VM_LOCKED | VM_IO);
-	vma->vm_ops = &qcntl_mmap;
-
-	/* Uncache the pages */
-	vma->vm_page_prot = PAGE_USERIO;
-
-	error = vmap_page_range (vma->vm_start, size, mem);
-
-	shmiqs [minor].tail = 0;
-	/* Init the shared memory input queue */
-	memset (shmiqs [minor].shmiq_vaddr, 0, size);
-	unlock_kernel();
-
-	return error;
-}
-
-static int
-shmiq_qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int minor = MINOR (inode->i_rdev);
-
-	if (minor-- == 0)
-		return shmiq_ioctl (inode, filp, cmd, arg);
-
-	return qcntl_ioctl (inode, filp, cmd, arg, minor);
-}
-
-static unsigned int
-shmiq_qcntl_poll (struct file *filp, poll_table *wait)
-{
-	struct sharedMemoryInputQueue *s;
-	int minor = MINOR (filp->f_dentry->d_inode->i_rdev);
-
-	if (minor-- == 0)
-		return 0;
-
-	if (!shmiqs [minor].mapped)
-		return 0;
-
-	poll_wait (filp, &shmiqs [minor].proc_list, wait);
-	s = shmiqs [minor].shmiq_vaddr;
-	if (s->head != s->tail)
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static int
-shmiq_qcntl_open (struct inode *inode, struct file *filp)
-{
-	int minor = MINOR (inode->i_rdev);
-
-	if (minor == 0)
-		return 0;
-
-	minor--;
-	if (minor > MAX_SHMI_QUEUES)
-		return -EINVAL;
-	if (shmiqs [minor].opened)
-		return -EBUSY;
-
-	lock_kernel ();
-	shmiqs [minor].opened      = 1;
-	shmiqs [minor].shmiq_vaddr = 0;
-	unlock_kernel ();
-
-	return 0;
-}
-
-static int
-shmiq_qcntl_fasync (int fd, struct file *file, int on)
-{
-	int retval;
-	int minor = MINOR (file->f_dentry->d_inode->i_rdev);
-
-	retval = fasync_helper (fd, file, on, &shmiqs [minor].fasync);
-	if (retval < 0)
-		return retval;
-	return 0;
-}
-
-static int
-shmiq_qcntl_close (struct inode *inode, struct file *filp)
-{
-	int minor = MINOR (inode->i_rdev);
-	int j;
-
-	if (minor-- == 0){
-		for (j = 0; j < MAX_SHMIQ_DEVS; j++)
-			shmiq_forget_file (j);
-	}
-
-	if (minor > MAX_SHMI_QUEUES)
-		return -EINVAL;
-	if (shmiqs [minor].opened == 0)
-		return -EINVAL;
-
-	lock_kernel ();
-	shmiq_qcntl_fasync (-1, filp, 0);
-	shmiqs [minor].opened      = 0;
-	shmiqs [minor].mapped      = 0;
-	shmiqs [minor].events      = 0;
-	shmiqs [minor].fasync      = 0;
-	vfree (shmiqs [minor].shmiq_vaddr);
-	shmiqs [minor].shmiq_vaddr = 0;
-	unlock_kernel ();
-
-	return 0;
-}
-
-
-static struct file_operations shmiq_fops =
-{
-	poll:		shmiq_qcntl_poll,
-	ioctl:		shmiq_qcntl_ioctl,
-	mmap:		shmiq_qcntl_mmap,
-	open:		shmiq_qcntl_open,
-	release:	shmiq_qcntl_close,
-	fasync:		shmiq_qcntl_fasync,
-};
-
-void
-shmiq_init (void)
-{
-	printk ("SHMIQ setup\n");
-	devfs_register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops);
-	devfs_register (NULL, "shmiq", DEVFS_FL_DEFAULT,
-			SHMIQ_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,
-			&shmiq_fops, NULL);
-	devfs_register_series (NULL, "qcntl%u", 2, DEVFS_FL_DEFAULT,
-			       SHMIQ_MAJOR, 1,
-			       S_IFCHR | S_IRUSR | S_IWUSR,
-			       &shmiq_fops, NULL);
-}
-
-EXPORT_SYMBOL(shmiq_init);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)