import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / cris / kernel / sys_cris.c
1 /*
2  * linux/arch/cris/kernel/sys_cris.c
3  *
4  * This file contains various random system calls that
5  * have a non-standard calling sequence on some platforms.
6  * Since we don't have to do any backwards compatibility, our
7  * versions are done in the most "normal" way possible.
8  *
9  */
10
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/mm.h>
14 #include <linux/smp.h>
15 #include <linux/smp_lock.h>
16 #include <linux/sem.h>
17 #include <linux/msg.h>
18 #include <linux/shm.h>
19 #include <linux/stat.h>
20 #include <linux/mman.h>
21 #include <linux/file.h>
22
23 #include <asm/uaccess.h>
24 #include <asm/ipc.h>
25 #include <asm/segment.h>
26
27 /*
28  * sys_pipe() is the normal C calling standard for creating
29  * a pipe. It's not the way Unix traditionally does this, though.
30  */
31 asmlinkage int sys_pipe(unsigned long * fildes)
32 {
33         int fd[2];
34         int error;
35
36         lock_kernel();
37         error = do_pipe(fd);
38         unlock_kernel();
39         if (!error) {
40                 if (copy_to_user(fildes, fd, 2*sizeof(int)))
41                         error = -EFAULT;
42         }
43         return error;
44 }
45
46 /* common code for old and new mmaps */
47 static inline long
48 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
49         unsigned long flags, unsigned long fd, unsigned long pgoff)
50 {
51         int error = -EBADF;
52         struct file * file = NULL;
53
54         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
55         if (!(flags & MAP_ANONYMOUS)) {
56                 file = fget(fd);
57                 if (!file)
58                         goto out;
59         }
60
61         down_write(&current->mm->mmap_sem);
62         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
63         up_write(&current->mm->mmap_sem);
64
65         if (file)
66                 fput(file);
67 out:
68         return error;
69 }
70
71 asmlinkage unsigned long old_mmap(unsigned long *args)
72 {        
73         unsigned long buffer[6];
74         int err = -EFAULT;
75
76         if (copy_from_user(&buffer, args, sizeof(buffer)))
77                 goto out;
78
79         err = -EINVAL;
80         if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
81                 goto out;
82
83         err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3],
84                        buffer[4], buffer[5] >> PAGE_SHIFT);
85 out:
86         return err;
87 }
88
89 asmlinkage long
90 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
91           unsigned long flags, unsigned long fd, unsigned long pgoff)
92 {
93         return do_mmap2(addr, len, prot, flags, fd, pgoff);
94 }
95
96 /*
97  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
98  *
99  * This is really horribly ugly. (same as arch/i386)
100  */
101
102 asmlinkage int sys_ipc (uint call, int first, int second,
103                         int third, void *ptr, long fifth)
104 {
105         int version, ret;
106
107         version = call >> 16; /* hack for backward compatibility */
108         call &= 0xffff;
109
110         switch (call) {
111         case SEMOP:
112                 return sys_semtimedop (first, (struct sembuf *)ptr, second, NULL);
113         case SEMTIMEDOP:
114                 return sys_semtimedop (first, (struct sembuf *)ptr, second,
115                                        (const struct timespec *)fifth);
116         case SEMGET:
117                 return sys_semget (first, second, third);
118         case SEMCTL: {
119                 union semun fourth;
120                 if (!ptr)
121                         return -EINVAL;
122                 if (get_user(fourth.__pad, (void **) ptr))
123                         return -EFAULT;
124                 return sys_semctl (first, second, third, fourth);
125         }
126
127         case MSGSND:
128                 return sys_msgsnd (first, (struct msgbuf *) ptr, 
129                                    second, third);
130         case MSGRCV:
131                 switch (version) {
132                 case 0: {
133                         struct ipc_kludge tmp;
134                         if (!ptr)
135                                 return -EINVAL;
136                         
137                         if (copy_from_user(&tmp,
138                                            (struct ipc_kludge *) ptr, 
139                                            sizeof (tmp)))
140                                 return -EFAULT;
141                         return sys_msgrcv (first, tmp.msgp, second,
142                                            tmp.msgtyp, third);
143                 }
144                 default:
145                         return sys_msgrcv (first,
146                                            (struct msgbuf *) ptr,
147                                            second, fifth, third);
148                 }
149         case MSGGET:
150                 return sys_msgget ((key_t) first, second);
151         case MSGCTL:
152                 return sys_msgctl (first, second, (struct msqid_ds *) ptr);
153
154         case SHMAT: {
155                 ulong raddr;
156                 ret = sys_shmat (first, (char *) ptr, second, &raddr);
157                 if (ret)
158                         return ret;
159                 return put_user (raddr, (ulong *) third);
160         }
161         case SHMDT: 
162                 return sys_shmdt ((char *)ptr);
163         case SHMGET:
164                 return sys_shmget (first, second, third);
165         case SHMCTL:
166                 return sys_shmctl (first, second,
167                                    (struct shmid_ds *) ptr);
168         default:
169                 return -ENOSYS;
170         }
171 }
172
173 /* apparently this is legacy - if we don't need this in Linux/CRIS we can remove it. */
174
175 asmlinkage int sys_pause(void)
176 {
177         current->state = TASK_INTERRUPTIBLE;
178         schedule();
179         return -ERESTARTNOHAND;
180 }