summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/ipc.c')
-rw-r--r--arch/mips/kernel/ipc.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/arch/mips/kernel/ipc.c b/arch/mips/kernel/ipc.c
new file mode 100644
index 000000000..336965acf
--- /dev/null
+++ b/arch/mips/kernel/ipc.c
@@ -0,0 +1,109 @@
+/*
+ * linux/arch/mips/kernel/ipc.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/MIPS
+ * platform.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly. FIXME: Get rid of this wrapper.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
+{
+#ifdef CONFIG_SYSVIPC
+ int version;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ if (call <= SEMCTL)
+ switch (call) {
+ case SEMOP:
+ return sys_semop (first, (struct sembuf *)ptr, second);
+ case SEMGET:
+ return sys_semget (first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ int err;
+ if (!ptr)
+ return -EINVAL;
+ if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
+ return err;
+ get_from_user(fourth.__pad, ptr);
+ return sys_semctl (first, second, third, fourth);
+ }
+ default:
+ return -EINVAL;
+ }
+ if (call <= MSGCTL)
+ switch (call) {
+ case MSGSND:
+ return sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+ int err;
+ if (!ptr)
+ return -EINVAL;
+ if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
+ return err;
+ memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
+ sizeof (tmp));
+ return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ }
+ case 1: default:
+ return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget ((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ default:
+ return -EINVAL;
+ }
+ if (call <= SHMCTL)
+ switch (call) {
+ case SHMAT:
+ switch (version) {
+ case 0: default: {
+ ulong raddr;
+ int err;
+ if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
+ return err;
+ err = sys_shmat (first, (char *) ptr, second, &raddr);
+ if (err)
+ return err;
+ put_user (raddr, (ulong *) third);
+ return 0;
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (get_fs() != get_ds())
+ return -EINVAL;
+ return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ }
+ case SHMDT:
+ return sys_shmdt ((char *)ptr);
+ case SHMGET:
+ return sys_shmget (first, second, third);
+ case SHMCTL:
+ return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ default:
+ return -EINVAL;
+ }
+ return -EINVAL;
+#else /* CONFIG_SYSVIPC */
+ return -ENOSYS;
+#endif /* CONFIG_SYSVIPC */
+}