1 /*
2  * linux/arch/mips/kernel/ipc.c
3  *
4  * This file contains various random system calls that
5  * have a non-standard calling sequence on the Linux/MIPS
6  * platform.
7  */
8 #include <linux/errno.h>
9 #include <linux/sched.h>
10 #include <linux/mm.h>
11 #include <linux/smp.h>
12 #include <linux/smp_lock.h>
13 #include <linux/sem.h>
14 #include <linux/msg.h>
15 #include <linux/shm.h>
16 
17 #include <asm/ipc.h>
18 #include <asm/uaccess.h>
19 
20 /*
21  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
22  *
23  * This is really horribly ugly.
24  */
sys_ipc(uint call,int first,int second,int third,void * ptr,long fifth)25 asmlinkage int sys_ipc (uint call, int first, int second,
26 			int third, void *ptr, long fifth)
27 {
28 	int version, ret;
29 
30 	version = call >> 16; /* hack for backward compatibility */
31 	call &= 0xffff;
32 
33 	switch (call) {
34 	case SEMOP:
35 		return sys_semtimedop (first, (struct sembuf *)ptr, second,
36 		                       NULL);
37 	case SEMTIMEDOP:
38 		return sys_semtimedop (first, (struct sembuf *)ptr, second,
39 		                       (const struct timespec *)fifth);
40 	case SEMGET:
41 		return sys_semget (first, second, third);
42 	case SEMCTL: {
43 		union semun fourth;
44 		if (!ptr)
45 			return -EINVAL;
46 		if (get_user(fourth.__pad, (void **) ptr))
47 			return -EFAULT;
48 		return sys_semctl (first, second, third, fourth);
49 	}
50 
51 	case MSGSND:
52 		return sys_msgsnd (first, (struct msgbuf *) ptr,
53 				   second, third);
54 	case MSGRCV:
55 		switch (version) {
56 		case 0: {
57 			struct ipc_kludge tmp;
58 			if (!ptr)
59 				return -EINVAL;
60 
61 			if (copy_from_user(&tmp,
62 					   (struct ipc_kludge *) ptr,
63 					   sizeof (tmp)))
64 				return -EFAULT;
65 			return sys_msgrcv (first, tmp.msgp, second,
66 					   tmp.msgtyp, third);
67 		}
68 		default:
69 			return sys_msgrcv (first,
70 					   (struct msgbuf *) ptr,
71 					   second, fifth, third);
72 		}
73 	case MSGGET:
74 		return sys_msgget ((key_t) first, second);
75 	case MSGCTL:
76 		return sys_msgctl (first, second, (struct msqid_ds *) ptr);
77 
78 	case SHMAT:
79 		switch (version) {
80 		default: {
81 			ulong raddr;
82 			ret = sys_shmat (first, (char *) ptr, second, &raddr);
83 			if (ret)
84 				return ret;
85 			return put_user (raddr, (ulong *) third);
86 		}
87 		case 1:	/* iBCS2 emulator entry point */
88 			if (!segment_eq(get_fs(), get_ds()))
89 				return -EINVAL;
90 			return sys_shmat (first, (char *) ptr, second, (ulong *) third);
91 		}
92 	case SHMDT:
93 		return sys_shmdt ((char *)ptr);
94 	case SHMGET:
95 		return sys_shmget (first, second, third);
96 	case SHMCTL:
97 		return sys_shmctl (first, second,
98 				   (struct shmid_ds *) ptr);
99 	default:
100 		return -ENOSYS;
101 	}
102 }
103