diff options
-rw-r--r-- | arch/mips/kernel/sysirix.c | 119 | ||||
-rw-r--r-- | drivers/sgi/char/usema.c | 195 | ||||
-rw-r--r-- | include/asm-mips/shmiq.h | 4 | ||||
-rw-r--r-- | include/asm-mips/usioctl.h | 26 | ||||
-rw-r--r-- | include/linux/major.h | 1 | ||||
-rw-r--r-- | include/linux/miscdevice.h | 3 |
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); |