summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/kernel/sysirix.c119
-rw-r--r--drivers/sgi/char/usema.c195
-rw-r--r--include/asm-mips/shmiq.h4
-rw-r--r--include/asm-mips/usioctl.h26
-rw-r--r--include/linux/major.h1
-rw-r--r--include/linux/miscdevice.h3
6 files changed, 310 insertions, 38 deletions
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index c1b672e76..6aae9bb7e 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -1,4 +1,4 @@
-/* $Id: sysirix.c,v 1.3 1997/07/20 15:32:25 ralf Exp $
+/* $Id: sysirix.c,v 1.4 1997/08/06 19:15:08 miguel Exp $
* sysirix.c: IRIX system call emulation.
*
* Copyright (C) 1996 David S. Miller
@@ -29,7 +29,9 @@
/* 2,300 lines of complete and utter shit coming up... */
/* The sysmp commands supported thus far. */
-#define MP_PGSIZE 14 /* Return system page size in v1. */
+#define MP_NPROCS 1 /* # processor in complex */
+#define MP_NAPROCS 2 /* # active processors in complex */
+#define MP_PGSIZE 14 /* Return system page size in v1. */
asmlinkage int irix_sysmp(struct pt_regs *regs)
{
@@ -45,7 +47,12 @@ asmlinkage int irix_sysmp(struct pt_regs *regs)
case MP_PGSIZE:
error = PAGE_SIZE;
break;
-
+ case MP_NPROCS:
+ error = NPROCS;
+ break;
+ case MP_NAPROCS:
+ error = NPROCS;
+ break;
default:
printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
current->comm, current->pid, (int)cmd);
@@ -228,12 +235,17 @@ extern asmlinkage int sys_getsid(pid_t pid);
extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
extern int getrusage(struct task_struct *p, int who, struct rusage *ru);
+extern char *prom_getenv(char *name);
+extern long prom_setenv(char *name, char *value);
/* The syssgi commands supported thus far. */
#define SGI_SYSID 1 /* Return unique per-machine identifier. */
#define SGI_RDNAME 6 /* Return string name of a process. */
+#define SGI_SETNVRAM 8 /* Set PROM variable. */
+#define SGI_GETNVRAM 9 /* Get PROM variable. */
#define SGI_SETPGID 21 /* Set process group id. */
#define SGI_SYSCONF 22 /* POSIX sysconf garbage. */
+#define SGI_PATHCONF 24 /* POSIX sysconf garbage. */
#define SGI_SETGROUPS 40 /* POSIX sysconf garbage. */
#define SGI_GETGROUPS 41 /* POSIX sysconf garbage. */
#define SGI_RUSAGE 56 /* BSD style rusage(). */
@@ -246,40 +258,73 @@ extern int getrusage(struct task_struct *p, int who, struct rusage *ru);
asmlinkage int irix_syssgi(struct pt_regs *regs)
{
- unsigned long cmd;
- int retval, base = 0;
-
- lock_kernel();
- if(regs->regs[2] == 1000)
- base = 1;
-
- cmd = regs->regs[base + 4];
- switch(cmd) {
- case SGI_SYSID: {
- char *buf = (char *) regs->regs[base + 5];
-
- /* XXX Use ethernet addr.... */
- retval = clear_user(buf, 64);
- break;
- }
-
- case SGI_RDNAME: {
- int pid = (int) regs->regs[base + 5];
- char *buf = (char *) regs->regs[base + 6];
- struct task_struct *p;
-
- retval = verify_area(VERIFY_WRITE, buf, 16);
- if(retval)
- break;
- for_each_task(p) {
- if(p->pid == pid)
- goto found0;
- }
- retval = -ESRCH;
-
- found0:
- copy_to_user(buf, p->comm, 16);
- retval = 0;
+ unsigned long cmd;
+ int retval, base = 0;
+
+ lock_kernel();
+ if(regs->regs[2] == 1000)
+ base = 1;
+
+ cmd = regs->regs[base + 4];
+ switch(cmd) {
+ case SGI_SYSID: {
+ char *buf = (char *) regs->regs[base + 5];
+
+ /* XXX Use ethernet addr.... */
+ retval = clear_user(buf, 64);
+ break;
+ }
+
+ case SGI_RDNAME: {
+ int pid = (int) regs->regs[base + 5];
+ char *buf = (char *) regs->regs[base + 6];
+ struct task_struct *p;
+
+ retval = verify_area(VERIFY_WRITE, buf, 16);
+ if(retval)
+ break;
+ for_each_task(p) {
+ if(p->pid == pid)
+ goto found0;
+ }
+ retval = -ESRCH;
+
+ found0:
+ /* XXX Need to check sizes. */
+ copy_to_user(buf, p->comm, 16);
+ retval = 0;
+ break;
+ }
+
+ case SGI_GETNVRAM: {
+ char *name = (char *) regs->regs[base+5];
+ char *buf = (char *) regs->regs[base+6];
+ char *value;
+ retval = verify_area(VERIFY_WRITE, buf, 128);
+ if (retval)
+ break;
+ value = prom_getenv(name);
+ if (!value) {
+ retval = -EINVAL;
+ break;
+ }
+ /* Do I strlen() for the length? */
+ copy_to_user(buf, value, 128);
+ retval = 0;
+ break;
+ }
+
+ case SGI_SETNVRAM: {
+ char *name = (char *) regs->regs[base+5];
+ char *buf = (char *) regs->regs[base+6];
+ retval = prom_setenv(name, buf);
+ /* XXX make sure retval conforms to syssgi(2) */
+ printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",
+ current->comm, current->pid,
+ name, value, retval);
+ if (retval == PROM_ENOENT)
+ retval = -ENOENT;
+ break;
}
case SGI_SETPGID: {
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c
new file mode 100644
index 000000000..5c92221a2
--- /dev/null
+++ b/drivers/sgi/char/usema.c
@@ -0,0 +1,195 @@
+/*
+ * usema.c: software semaphore driver (see IRIX's usema(7M))
+ * written 1997 Mike Shaver (shaver@neon.ingenia.ca)
+ *
+ * This file contains the implementation of /dev/usema and /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 on /dev/usema. I'm sure
+ * it'll make more sense when I get it working. =) The devices are
+ * only accessed by the libc routines, apparently,
+ *
+ * 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.
+ *
+ * The minor number for the usema descriptor used to poll and block
+ * such determines which semaphore you're manipulating, so I think you're
+ * limited to (1 << MINORBITS - 1) semaphores active at a given time.
+ *
+ * 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 <asm/smp_lock.h>
+#include <asm/usioctl.h>
+#include <asm/mman.h>
+
+#define NUM_USEMAS (1 << MINORBITS - 1)
+
+static struct irix_usema{
+ int used;
+ struct wait_queue *proc_list;
+} usema_list[NUM_USEMAS];
+
+/*
+ * Generate and return a descriptor for a new semaphore.
+ */
+
+static int
+sgi_usemaclone_open(struct inode *inode, struct file *filp)
+{
+ int semanum;
+ printk("[%s:%d] wants a new usema",
+ current->comm, current->pid);
+ for (semanum = 0;
+ semanum < NUM_USEMAS && !usema_list[semanum].used;
+ semanum++)
+ /* nothing */;
+ if (usema_list[semanum].used) {
+ printk("usemaclone: no more usemas left for process %d",
+ current->pid);
+ return -EBUSY;
+ }
+ /* XXX is this the right way to do it? */
+ inode->i_dev = MKDEV(USEMA_MAJOR, semanum);
+ usema_list[semanum].used = 1;
+ return 0;
+}
+
+/*
+ * Generate another descriptor for an existing semaphore.
+ */
+
+static int
+sgi_usema_attach(usattach_t * attach, int semanum) {
+ int newfd;
+ /* create a new fd for this process with major/minor
+ correct, I guess. */
+ newfd = -ENOSYS;
+ return newfd;
+}
+
+static int
+sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int retval;
+ printk("[%s:%d] wants ioctl 0x%xd (arg 0x%xd)",
+ 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;
+ int newfd;
+ int semanum;
+ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
+ if (retval) {
+ printk("[%s:%d] sgi_usema_ioctl(UIOATTACHSEMA): "
+ "verify_area failure",
+ current->comm, current->pid);
+ return retval;
+ }
+ semanum = MINOR(attach->us_dev);
+ if (semanum == 0) {
+ /* This shouldn't happen (tm).
+ A minor of zero indicates that there's no
+ semaphore created for the given descriptor...
+ in which case there's nothing to which to attach.
+ */
+ return -EINVAL;
+ }
+ printk("UIOATTACHSEMA: attaching usema %d to process %d\n",
+ semanum, current->pid);
+ return sgi_usema_attach(attach, semanum);
+ break;
+ }
+ case UIOCBLOCK: {
+ /* Block this process on the semaphore */
+ /* I'll probably just pretend they're polling */
+ printk("UIOCBLOCK: (not) putting process %d to sleep",
+ current->pid);
+ }
+ case UIOCUNBLOCK: {
+ /* Wake up all process waiting on this semaphore */
+ }
+ return -ENOSYS;
+}
+
+static int
+sgi_usema_poll(struct file *filp, poll_table *wait)
+{
+ int semanum = MINOR(filp->f_dentry->d_inode->i_rdev);
+ printk("[%s:%d] wants to poll usema %d",
+ current->comm, current->pid, semanum);
+ /* I have to figure out what the behaviour is when:
+ - polling and the lock is free
+ - the lock becomes free and there's a process polling it
+ And I have to figure out the poll() semantics. =)
+ */
+ return -ENOSYS;
+}
+
+struct file_operations sgi_usema_fops = {
+ NULL, /* llseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ sgi_usema_poll, /* poll */
+ sgi_usema_ioctl, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* release */
+ NULL, /* fsync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL /* lock */
+};
+
+struct file_operations sgi_usemaclone_fops = {
+ NULL, /* llseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ sgi_usemaclone_open, /* open */
+ NULL, /* 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);
+ register_chrdev(USEMA_MAJOR, "usema", &sgi_usema_fops);
+ printk("usema device registered (major %d)\n",
+ USEMA_MAJOR);
+ memset((void *)usema_list, 0, sizeof(struct irix_usema) * NUM_USEMAS);
+}
diff --git a/include/asm-mips/shmiq.h b/include/asm-mips/shmiq.h
index 2e845113f..d07633d79 100644
--- a/include/asm-mips/shmiq.h
+++ b/include/asm-mips/shmiq.h
@@ -174,8 +174,10 @@ typedef struct {
char *nothing_for_now;
} idevInfo;
+#define IDEV_KEYMAP_NAME_LEN 15
+
typedef struct {
- char name [16];
+ char name[IDEV_KEYMAP_NAME_LEN+1];
} idevKeymapDesc;
#define IDEVINITDEVICE _IOW('i', 51, unsigned int)
diff --git a/include/asm-mips/usioctl.h b/include/asm-mips/usioctl.h
new file mode 100644
index 000000000..b4edeb5cf
--- /dev/null
+++ b/include/asm-mips/usioctl.h
@@ -0,0 +1,26 @@
+/*
+ * usema/usemaclone-related stuff.
+ *
+ * `Inspired' by IRIX's sys/usioctl.h
+ *
+ * Mike.
+ */
+
+/* ioctls */
+#define UIOC ('u' << 16 | 's' << 8)
+
+#define UIOCATTACHSEMA (UIOC|2) /* attach to sema */
+#define UIOCBLOCK (UIOC|3) /* block sync "intr"? */
+#define UIOCABLOCK (UIOC|4) /* block async */
+#define UIOCNOIBLOCK (UIOC|5) /* block sync "intr"?
+ How is this different from
+ UIOCNOIBLOCK? */
+#define UIOCUNBLOCK (UIOC|6) /* unblock sync */
+#define UIOCAUNBLOCK (UIOC|7) /* unblock async */
+#define UIOCINIT (UIOC|8) /* init sema (async) */
+
+typedef struct usattach_s {
+ dev_t us_dev; /* attach dev */
+ void *us_handle; /* userland semaphore handle */
+} usattach_t;
+
diff --git a/include/linux/major.h b/include/linux/major.h
index d72e6c2be..9daaad805 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -59,6 +59,7 @@
#define AZTECH_CDROM_MAJOR 29
#define GRAPHDEV_MAJOR 29 /* SparcLinux & Linux/68k /dev/fb */
#define SHMIQ_MAJOR 85 /* Linux/mips, SGI /dev/shmiq */
+#define USEMA_MAJOR 86 /* Linux/MIPS, SGI /dev/usema */
#define CM206_CDROM_MAJOR 32
#define IDE2_MAJOR 33
#define IDE3_MAJOR 34
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 4886d464c..75d69db93 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -19,6 +19,9 @@
#define SGI_GFX_MINOR 148
#define SGI_STREAMS_MOUSE 149
#define SGI_STREAMS_KEYBOARD 150
+/* drivers/sgi/char/usema.c */
+#define SGI_USEMA 151
+#define SGI_USEMACLONE 152
extern int misc_init(void);