OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc64/] [solaris/] [ioctl.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* $Id: ioctl.c,v 1.17 2002/02/08 03:57:14 davem Exp $
2
 * ioctl.c: Solaris ioctl emulation.
3
 *
4
 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5
 * Copyright (C) 1997,1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
6
 *
7
 * Streams & timod emulation based on code
8
 * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
9
 *
10
 * 1999-08-19 Implemented solaris 'm' (mag tape) and
11
 *            'O' (openprom) ioctls, by Jason Rappleye
12
 *             (rappleye@ccr.buffalo.edu)
13
 */
14
 
15
#include <linux/types.h>
16
#include <linux/kernel.h>
17
#include <linux/sched.h>
18
#include <linux/smp.h>
19
#include <linux/smp_lock.h>
20
#include <linux/syscalls.h>
21
#include <linux/ioctl.h>
22
#include <linux/fs.h>
23
#include <linux/file.h>
24
#include <linux/netdevice.h>
25
#include <linux/mtio.h>
26
#include <linux/time.h>
27
#include <linux/rcupdate.h>
28
#include <linux/compat.h>
29
 
30
#include <net/sock.h>
31
#include <net/net_namespace.h>
32
 
33
#include <asm/uaccess.h>
34
#include <asm/termios.h>
35
#include <asm/openpromio.h>
36
 
37
#include "conv.h"
38
#include "socksys.h"
39
 
40
extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd,
41
        u32 arg);
42
asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
43
 
44
extern int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
45
                        char __user *data_buf, int data_len, int flags);
46
extern int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, int __user *ctl_len,
47
                        char __user *data_buf, int data_maxlen, int __user *data_len, int *flags);
48
 
49
/* termio* stuff {{{ */
50
 
51
struct solaris_termios {
52
        u32     c_iflag;
53
        u32     c_oflag;
54
        u32     c_cflag;
55
        u32     c_lflag;
56
        u8      c_cc[19];
57
};
58
 
59
struct solaris_termio {
60
        u16     c_iflag;
61
        u16     c_oflag;
62
        u16     c_cflag;
63
        u16     c_lflag;
64
        s8      c_line;
65
        u8      c_cc[8];
66
};
67
 
68
struct solaris_termiox {
69
        u16     x_hflag;
70
        u16     x_cflag;
71
        u16     x_rflag[5];
72
        u16     x_sflag;
73
};
74
 
75
static u32 solaris_to_linux_cflag(u32 cflag)
76
{
77
        cflag &= 0x7fdff000;
78
        if (cflag & 0x200000) {
79
                int baud = cflag & 0xf;
80
                cflag &= ~0x20000f;
81
                switch (baud) {
82
                case 0: baud = B57600; break;
83
                case 1: baud = B76800; break;
84
                case 2: baud = B115200; break;
85
                case 3: baud = B153600; break;
86
                case 4: baud = B230400; break;
87
                case 5: baud = B307200; break;
88
                case 6: baud = B460800; break;
89
                }
90
                cflag |= CBAUDEX | baud;
91
        }
92
        return cflag;
93
}
94
 
95
static u32 linux_to_solaris_cflag(u32 cflag)
96
{
97
        cflag &= ~(CMSPAR | CIBAUD);
98
        if (cflag & CBAUDEX) {
99
                int baud = cflag & CBAUD;
100
                cflag &= ~CBAUD;
101
                switch (baud) {
102
                case B57600: baud = 0; break;
103
                case B76800: baud = 1; break;
104
                case B115200: baud = 2; break;
105
                case B153600: baud = 3; break;
106
                case B230400: baud = 4; break;
107
                case B307200: baud = 5; break;
108
                case B460800: baud = 6; break;
109
                case B614400: baud = 7; break;
110
                case B921600: baud = 8; break;
111
#if 0           
112
                case B1843200: baud = 9; break;
113
#endif
114
                }
115
                cflag |= 0x200000 | baud;
116
        }
117
        return cflag;
118
}
119
 
120
static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg)
121
{
122
        struct solaris_termio __user *p = A(arg);
123
        int ret;
124
 
125
        ret = sys_ioctl(fd, cmd, (unsigned long)p);
126
        if (!ret) {
127
                u32 cflag;
128
 
129
                if (__get_user (cflag, &p->c_cflag))
130
                        return -EFAULT;
131
                cflag = linux_to_solaris_cflag(cflag);
132
                if (__put_user (cflag, &p->c_cflag))
133
                        return -EFAULT;
134
        }
135
        return ret;
136
}
137
 
138
static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg)
139
{
140
        int ret;
141
        struct solaris_termio s;
142
        mm_segment_t old_fs = get_fs();
143
 
144
        if (copy_from_user (&s, (struct solaris_termio __user *)A(arg), sizeof(struct solaris_termio)))
145
                return -EFAULT;
146
        s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
147
        set_fs(KERNEL_DS);
148
        ret = sys_ioctl(fd, cmd, (unsigned long)&s);
149
        set_fs(old_fs);
150
        return ret;
151
}
152
 
153
static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg)
154
{
155
        int ret;
156
        struct solaris_termios s;
157
        mm_segment_t old_fs = get_fs();
158
 
159
        set_fs(KERNEL_DS);
160
        ret = sys_ioctl(fd, cmd, (unsigned long)&s);
161
        set_fs(old_fs);
162
        if (!ret) {
163
                struct solaris_termios __user *p = A(arg);
164
                if (put_user (s.c_iflag, &p->c_iflag) ||
165
                    __put_user (s.c_oflag, &p->c_oflag) ||
166
                    __put_user (linux_to_solaris_cflag(s.c_cflag), &p->c_cflag) ||
167
                    __put_user (s.c_lflag, &p->c_lflag) ||
168
                    __copy_to_user (p->c_cc, s.c_cc, 16) ||
169
                    __clear_user (p->c_cc + 16, 2))
170
                        return -EFAULT;
171
        }
172
        return ret;
173
}
174
 
175
static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg)
176
{
177
        int ret;
178
        struct solaris_termios s;
179
        struct solaris_termios __user *p = A(arg);
180
        mm_segment_t old_fs = get_fs();
181
 
182
        set_fs(KERNEL_DS);
183
        ret = sys_ioctl(fd, TCGETS, (unsigned long)&s);
184
        set_fs(old_fs);
185
        if (ret) return ret;
186
        if (put_user (s.c_iflag, &p->c_iflag) ||
187
            __put_user (s.c_oflag, &p->c_oflag) ||
188
            __put_user (s.c_cflag, &p->c_cflag) ||
189
            __put_user (s.c_lflag, &p->c_lflag) ||
190
            __copy_from_user (s.c_cc, p->c_cc, 16))
191
                return -EFAULT;
192
        s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
193
        set_fs(KERNEL_DS);
194
        ret = sys_ioctl(fd, cmd, (unsigned long)&s);
195
        set_fs(old_fs);
196
        return ret;
197
}
198
 
199
static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg)
200
{
201
        switch (cmd & 0xff) {
202
        case 1: /* TCGETA */
203
                return linux_to_solaris_termio(fd, TCGETA, arg);
204
        case 2: /* TCSETA */
205
                return solaris_to_linux_termio(fd, TCSETA, arg);
206
        case 3: /* TCSETAW */
207
                return solaris_to_linux_termio(fd, TCSETAW, arg);
208
        case 4: /* TCSETAF */
209
                return solaris_to_linux_termio(fd, TCSETAF, arg);
210
        case 5: /* TCSBRK */
211
                return sys_ioctl(fd, TCSBRK, arg);
212
        case 6: /* TCXONC */
213
                return sys_ioctl(fd, TCXONC, arg);
214
        case 7: /* TCFLSH */
215
                return sys_ioctl(fd, TCFLSH, arg);
216
        case 13: /* TCGETS */
217
                return linux_to_solaris_termios(fd, TCGETS, arg);
218
        case 14: /* TCSETS */
219
                return solaris_to_linux_termios(fd, TCSETS, arg);
220
        case 15: /* TCSETSW */
221
                return solaris_to_linux_termios(fd, TCSETSW, arg);
222
        case 16: /* TCSETSF */
223
                return solaris_to_linux_termios(fd, TCSETSF, arg);
224
        case 103: /* TIOCSWINSZ */
225
                return sys_ioctl(fd, TIOCSWINSZ, arg);
226
        case 104: /* TIOCGWINSZ */
227
                return sys_ioctl(fd, TIOCGWINSZ, arg);
228
        }
229
        return -ENOSYS;
230
}
231
 
232
static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg)
233
{
234
        switch (cmd & 0xff) {
235
        case 20: /* TIOCGPGRP */
236
                return sys_ioctl(fd, TIOCGPGRP, arg);
237
        case 21: /* TIOCSPGRP */
238
                return sys_ioctl(fd, TIOCSPGRP, arg);
239
        }
240
        return -ENOSYS;
241
}
242
 
243
/* }}} */
244
 
245
/* A pseudo STREAMS support {{{ */
246
 
247
struct strioctl {
248
        int cmd, timeout, len;
249
        u32 data;
250
};
251
 
252
struct solaris_si_sockparams {
253
        int sp_family;
254
        int sp_type;
255
        int sp_protocol;
256
};
257
 
258
struct solaris_o_si_udata {
259
        int tidusize;
260
        int addrsize;
261
        int optsize;
262
        int etsdusize;
263
        int servtype;
264
        int so_state;
265
        int so_options;
266
        int tsdusize;
267
};
268
 
269
struct solaris_si_udata {
270
        int tidusize;
271
        int addrsize;
272
        int optsize;
273
        int etsdusize;
274
        int servtype;
275
        int so_state;
276
        int so_options;
277
        int tsdusize;
278
        struct solaris_si_sockparams sockparams;
279
};
280
 
281
#define SOLARIS_MODULE_TIMOD    0
282
#define SOLARIS_MODULE_SOCKMOD  1
283
#define SOLARIS_MODULE_MAX      2
284
 
285
static struct module_info {
286
        const char *name;
287
        /* can be expanded further if needed */
288
} module_table[ SOLARIS_MODULE_MAX + 1 ] = {
289
        /* the ordering here must match the module numbers above! */
290
        { "timod" },
291
        { "sockmod" },
292
        { NULL }
293
};
294
 
295
static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
296
{
297
        struct inode *ino;
298
        struct fdtable *fdt;
299
        /* I wonder which of these tests are superfluous... --patrik */
300
        rcu_read_lock();
301
        fdt = files_fdtable(current->files);
302
        if (! fdt->fd[fd] ||
303
            ! fdt->fd[fd]->f_path.dentry ||
304
            ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) ||
305
            ! S_ISSOCK(ino->i_mode)) {
306
                rcu_read_unlock();
307
                return TBADF;
308
        }
309
        rcu_read_unlock();
310
 
311
        switch (cmd & 0xff) {
312
        case 109: /* SI_SOCKPARAMS */
313
        {
314
                struct solaris_si_sockparams si;
315
                if (copy_from_user (&si, A(arg), sizeof(si)))
316
                        return (EFAULT << 8) | TSYSERR;
317
 
318
                /* Should we modify socket ino->socket_i.ops and type? */
319
                return 0;
320
        }
321
        case 110: /* SI_GETUDATA */
322
        {
323
                int etsdusize, servtype;
324
                struct solaris_si_udata __user *p = A(arg);
325
                switch (SOCKET_I(ino)->type) {
326
                case SOCK_STREAM:
327
                        etsdusize = 1;
328
                        servtype = 2;
329
                        break;
330
                default:
331
                        etsdusize = -2;
332
                        servtype = 3;
333
                        break;
334
                }
335
                if (put_user(16384, &p->tidusize) ||
336
                    __put_user(sizeof(struct sockaddr), &p->addrsize) ||
337
                    __put_user(-1, &p->optsize) ||
338
                    __put_user(etsdusize, &p->etsdusize) ||
339
                    __put_user(servtype, &p->servtype) ||
340
                    __put_user(0, &p->so_state) ||
341
                    __put_user(0, &p->so_options) ||
342
                    __put_user(16384, &p->tsdusize) ||
343
                    __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_family) ||
344
                    __put_user(SOCKET_I(ino)->type, &p->sockparams.sp_type) ||
345
                    __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_protocol))
346
                        return (EFAULT << 8) | TSYSERR;
347
                return 0;
348
        }
349
        case 101: /* O_SI_GETUDATA */
350
        {
351
                int etsdusize, servtype;
352
                struct solaris_o_si_udata __user *p = A(arg);
353
                switch (SOCKET_I(ino)->type) {
354
                case SOCK_STREAM:
355
                        etsdusize = 1;
356
                        servtype = 2;
357
                        break;
358
                default:
359
                        etsdusize = -2;
360
                        servtype = 3;
361
                        break;
362
                }
363
                if (put_user(16384, &p->tidusize) ||
364
                    __put_user(sizeof(struct sockaddr), &p->addrsize) ||
365
                    __put_user(-1, &p->optsize) ||
366
                    __put_user(etsdusize, &p->etsdusize) ||
367
                    __put_user(servtype, &p->servtype) ||
368
                    __put_user(0, &p->so_state) ||
369
                    __put_user(0, &p->so_options) ||
370
                    __put_user(16384, &p->tsdusize))
371
                        return (EFAULT << 8) | TSYSERR;
372
                return 0;
373
        }
374
        case 102: /* SI_SHUTDOWN */
375
        case 103: /* SI_LISTEN */
376
        case 104: /* SI_SETMYNAME */
377
        case 105: /* SI_SETPEERNAME */
378
        case 106: /* SI_GETINTRANSIT */
379
        case 107: /* SI_TCL_LINK */
380
        case 108: /* SI_TCL_UNLINK */
381
                ;
382
        }
383
        return TNOTSUPPORT;
384
}
385
 
386
static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
387
                                    int len, int __user *len_p)
388
{
389
        int ret;
390
 
391
        switch (cmd & 0xff) {
392
        case 141: /* TI_OPTMGMT */
393
        {
394
                int i;
395
                u32 prim;
396
                SOLD("TI_OPMGMT entry");
397
                ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0);
398
                SOLD("timod_putmsg() returned");
399
                if (ret)
400
                        return (-ret << 8) | TSYSERR;
401
                i = MSG_HIPRI;
402
                SOLD("calling timod_getmsg()");
403
                ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
404
                SOLD("timod_getmsg() returned");
405
                if (ret)
406
                        return (-ret << 8) | TSYSERR;
407
                SOLD("ret ok");
408
                if (get_user(prim, (u32 __user *)A(arg)))
409
                        return (EFAULT << 8) | TSYSERR;
410
                SOLD("got prim");
411
                if (prim == T_ERROR_ACK) {
412
                        u32 tmp, tmp2;
413
                        SOLD("prim is T_ERROR_ACK");
414
                        if (get_user(tmp, (u32 __user *)A(arg)+3) ||
415
                            get_user(tmp2, (u32 __user *)A(arg)+2))
416
                                return (EFAULT << 8) | TSYSERR;
417
                        return (tmp2 << 8) | tmp;
418
                }
419
                SOLD("TI_OPMGMT return 0");
420
                return 0;
421
        }
422
        case 142: /* TI_BIND */
423
        {
424
                int i;
425
                u32 prim;
426
                SOLD("TI_BIND entry");
427
                ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0);
428
                SOLD("timod_putmsg() returned");
429
                if (ret)
430
                        return (-ret << 8) | TSYSERR;
431
                len = 1024; /* Solaris allows arbitrary return size */
432
                i = MSG_HIPRI;
433
                SOLD("calling timod_getmsg()");
434
                ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
435
                SOLD("timod_getmsg() returned");
436
                if (ret)
437
                        return (-ret << 8) | TSYSERR;
438
                SOLD("ret ok");
439
                if (get_user(prim, (u32 __user *)A(arg)))
440
                        return (EFAULT << 8) | TSYSERR;
441
                SOLD("got prim");
442
                if (prim == T_ERROR_ACK) {
443
                        u32 tmp, tmp2;
444
                        SOLD("prim is T_ERROR_ACK");
445
                        if (get_user(tmp, (u32 __user *)A(arg)+3) ||
446
                            get_user(tmp2, (u32 __user *)A(arg)+2))
447
                                return (EFAULT << 8) | TSYSERR;
448
                        return (tmp2 << 8) | tmp;
449
                }
450
                SOLD("no ERROR_ACK requested");
451
                if (prim != T_OK_ACK)
452
                        return TBADSEQ;
453
                SOLD("OK_ACK requested");
454
                i = MSG_HIPRI;
455
                SOLD("calling timod_getmsg()");
456
                ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
457
                SOLD("timod_getmsg() returned");
458
                if (ret)
459
                        return (-ret << 8) | TSYSERR;
460
                SOLD("TI_BIND return ok");
461
                return 0;
462
        }
463
        case 140: /* TI_GETINFO */
464
        case 143: /* TI_UNBIND */
465
        case 144: /* TI_GETMYNAME */
466
        case 145: /* TI_GETPEERNAME */
467
        case 146: /* TI_SETMYNAME */
468
        case 147: /* TI_SETPEERNAME */
469
                ;
470
        }
471
        return TNOTSUPPORT;
472
}
473
 
474
static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg)
475
{
476
        char *p;
477
        int ret;
478
        mm_segment_t old_fs;
479
        struct strioctl si;
480
        struct inode *ino;
481
        struct sol_socket_struct *sock;
482
        struct module_info *mi;
483
 
484
        ino = filp->f_path.dentry->d_inode;
485
        if (!S_ISSOCK(ino->i_mode))
486
                return -EBADF;
487
        sock = filp->private_data;
488
        if (! sock) {
489
                printk("solaris_S: NULL private_data\n");
490
                return -EBADF;
491
        }
492
        if (sock->magic != SOLARIS_SOCKET_MAGIC) {
493
                printk("solaris_S: invalid magic\n");
494
                return -EBADF;
495
        }
496
 
497
 
498
        switch (cmd & 0xff) {
499
        case 1: /* I_NREAD */
500
                return -ENOSYS;
501
        case 2: /* I_PUSH */
502
        {
503
                p = getname (A(arg));
504
                if (IS_ERR (p))
505
                        return PTR_ERR(p);
506
                ret = -EINVAL;
507
                for (mi = module_table; mi->name; mi++) {
508
                        if (strcmp(mi->name, p) == 0) {
509
                                sol_module m;
510
                                if (sock->modcount >= MAX_NR_STREAM_MODULES) {
511
                                        ret = -ENXIO;
512
                                        break;
513
                                }
514
                                m = (sol_module) (mi - module_table);
515
                                sock->module[sock->modcount++] = m;
516
                                ret = 0;
517
                                break;
518
                        }
519
                }
520
                putname (p);
521
                return ret;
522
        }
523
        case 3: /* I_POP */
524
                if (sock->modcount <= 0) return -EINVAL;
525
                sock->modcount--;
526
                return 0;
527
        case 4: /* I_LOOK */
528
        {
529
                const char *p;
530
                if (sock->modcount <= 0) return -EINVAL;
531
                p = module_table[(unsigned)sock->module[sock->modcount]].name;
532
                if (copy_to_user (A(arg), p, strlen(p)))
533
                        return -EFAULT;
534
                return 0;
535
        }
536
        case 5: /* I_FLUSH */
537
                return 0;
538
        case 8: /* I_STR */
539
                if (copy_from_user(&si, A(arg), sizeof(struct strioctl)))
540
                        return -EFAULT;
541
                /* We ignore what module is actually at the top of stack. */
542
                switch ((si.cmd >> 8) & 0xff) {
543
                case 'I':
544
                        return solaris_sockmod(fd, si.cmd, si.data);
545
                case 'T':
546
                        return solaris_timod(fd, si.cmd, si.data, si.len,
547
                                &((struct strioctl __user *)A(arg))->len);
548
                default:
549
                        return solaris_ioctl(fd, si.cmd, si.data);
550
                }
551
        case 9: /* I_SETSIG */
552
                return sys_ioctl(fd, FIOSETOWN, current->pid);
553
        case 10: /* I_GETSIG */
554
                old_fs = get_fs();
555
                set_fs(KERNEL_DS);
556
                sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret);
557
                set_fs(old_fs);
558
                if (ret == current->pid) return 0x3ff;
559
                else return -EINVAL;
560
        case 11: /* I_FIND */
561
        {
562
                int i;
563
                p = getname (A(arg));
564
                if (IS_ERR (p))
565
                        return PTR_ERR(p);
566
                ret = 0;
567
                for (i = 0; i < sock->modcount; i++) {
568
                        unsigned m = sock->module[i];
569
                        if (strcmp(module_table[m].name, p) == 0) {
570
                                ret = 1;
571
                                break;
572
                        }
573
                }
574
                putname (p);
575
                return ret;
576
        }
577
        case 19: /* I_SWROPT */
578
        case 32: /* I_SETCLTIME */
579
                return 0;        /* Lie */
580
        }
581
        return -ENOSYS;
582
}
583
 
584
static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg)
585
{
586
        switch (cmd & 0xff) {
587
        case 0: /* SIOCSHIWAT */
588
        case 2: /* SIOCSLOWAT */
589
                return 0; /* We don't support them */
590
        case 1: /* SIOCGHIWAT */
591
        case 3: /* SIOCGLOWAT */
592
                if (put_user (0, (u32 __user *)A(arg)))
593
                        return -EFAULT;
594
                return 0; /* Lie */
595
        case 7: /* SIOCATMARK */
596
                return sys_ioctl(fd, SIOCATMARK, arg);
597
        case 8: /* SIOCSPGRP */
598
                return sys_ioctl(fd, SIOCSPGRP, arg);
599
        case 9: /* SIOCGPGRP */
600
                return sys_ioctl(fd, SIOCGPGRP, arg);
601
        }
602
        return -ENOSYS;
603
}
604
 
605
static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg)
606
{
607
        switch (cmd & 0xff) {
608
        case 10: /* SIOCADDRT */
609
                return compat_sys_ioctl(fd, SIOCADDRT, arg);
610
        case 11: /* SIOCDELRT */
611
                return compat_sys_ioctl(fd, SIOCDELRT, arg);
612
        }
613
        return -ENOSYS;
614
}
615
 
616
static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
617
{
618
        switch (cmd & 0xff) {
619
        case 12: /* SIOCSIFADDR */
620
                return compat_sys_ioctl(fd, SIOCSIFADDR, arg);
621
        case 13: /* SIOCGIFADDR */
622
                return compat_sys_ioctl(fd, SIOCGIFADDR, arg);
623
        case 14: /* SIOCSIFDSTADDR */
624
                return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg);
625
        case 15: /* SIOCGIFDSTADDR */
626
                return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg);
627
        case 16: /* SIOCSIFFLAGS */
628
                return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg);
629
        case 17: /* SIOCGIFFLAGS */
630
                return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg);
631
        case 18: /* SIOCSIFMEM */
632
                return compat_sys_ioctl(fd, SIOCSIFMEM, arg);
633
        case 19: /* SIOCGIFMEM */
634
                return compat_sys_ioctl(fd, SIOCGIFMEM, arg);
635
        case 20: /* SIOCGIFCONF */
636
                return compat_sys_ioctl(fd, SIOCGIFCONF, arg);
637
        case 21: /* SIOCSIFMTU */
638
                return compat_sys_ioctl(fd, SIOCSIFMTU, arg);
639
        case 22: /* SIOCGIFMTU */
640
                return compat_sys_ioctl(fd, SIOCGIFMTU, arg);
641
        case 23: /* SIOCGIFBRDADDR */
642
                return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg);
643
        case 24: /* SIOCSIFBRDADDR */
644
                return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg);
645
        case 25: /* SIOCGIFNETMASK */
646
                return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg);
647
        case 26: /* SIOCSIFNETMASK */
648
                return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg);
649
        case 27: /* SIOCGIFMETRIC */
650
                return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg);
651
        case 28: /* SIOCSIFMETRIC */
652
                return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg);
653
        case 30: /* SIOCSARP */
654
                return compat_sys_ioctl(fd, SIOCSARP, arg);
655
        case 31: /* SIOCGARP */
656
                return compat_sys_ioctl(fd, SIOCGARP, arg);
657
        case 32: /* SIOCDARP */
658
                return compat_sys_ioctl(fd, SIOCDARP, arg);
659
        case 52: /* SIOCGETNAME */
660
        case 53: /* SIOCGETPEER */
661
                {
662
                        struct sockaddr uaddr;
663
                        int uaddr_len = sizeof(struct sockaddr), ret;
664
                        long args[3];
665
                        mm_segment_t old_fs = get_fs();
666
                        int (*sys_socketcall)(int, unsigned long *) =
667
                                (int (*)(int, unsigned long *))SYS(socketcall);
668
 
669
                        args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len;
670
                        set_fs(KERNEL_DS);
671
                        ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME,
672
                                        args);
673
                        set_fs(old_fs);
674
                        if (ret >= 0) {
675
                                if (copy_to_user(A(arg), &uaddr, uaddr_len))
676
                                        return -EFAULT;
677
                        }
678
                        return ret;
679
                }
680
#if 0           
681
        case 86: /* SIOCSOCKSYS */
682
                return socksys_syscall(fd, arg);
683
#endif          
684
        case 87: /* SIOCGIFNUM */
685
                {
686
                        struct net_device *d;
687
                        int i = 0;
688
 
689
                        read_lock_bh(&dev_base_lock);
690
                        for_each_netdev(&init_net, d)
691
                                i++;
692
                        read_unlock_bh(&dev_base_lock);
693
 
694
                        if (put_user (i, (int __user *)A(arg)))
695
                                return -EFAULT;
696
                        return 0;
697
                }
698
        }
699
        return -ENOSYS;
700
}
701
 
702
static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
703
{
704
        int ret;
705
 
706
        switch (cmd & 0xff) {
707
        case 1: /* MTIOCTOP */
708
                ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
709
                break;
710
        case 2: /* MTIOCGET */
711
                ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
712
                break;
713
        case 3: /* MTIOCGETDRIVETYPE */
714
        case 4: /* MTIOCPERSISTENT */
715
        case 5: /* MTIOCPERSISTENTSTATUS */
716
        case 6: /* MTIOCLRERR */
717
        case 7: /* MTIOCGUARANTEEDORDER */
718
        case 8: /* MTIOCRESERVE */
719
        case 9: /* MTIOCRELEASE */
720
        case 10: /* MTIOCFORCERESERVE */
721
        case 13: /* MTIOCSTATE */
722
        case 14: /* MTIOCREADIGNOREILI */
723
        case 15: /* MTIOCREADIGNOREEOFS */
724
        case 16: /* MTIOCSHORTFMK */
725
        default:
726
                ret = -ENOSYS; /* linux doesn't support these */
727
                break;
728
        };
729
 
730
        return ret;
731
}
732
 
733
static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
734
{
735
        int ret = -EINVAL;
736
 
737
        switch (cmd & 0xff) {
738
        case 1: /* OPROMGETOPT */
739
                ret = sys_ioctl(fd, OPROMGETOPT, arg);
740
                break;
741
        case 2: /* OPROMSETOPT */
742
                ret = sys_ioctl(fd, OPROMSETOPT, arg);
743
                break;
744
        case 3: /* OPROMNXTOPT */
745
                ret = sys_ioctl(fd, OPROMNXTOPT, arg);
746
                break;
747
        case 4: /* OPROMSETOPT2 */
748
                ret = sys_ioctl(fd, OPROMSETOPT2, arg);
749
                break;
750
        case 5: /* OPROMNEXT */
751
                ret = sys_ioctl(fd, OPROMNEXT, arg);
752
                break;
753
        case 6: /* OPROMCHILD */
754
                ret = sys_ioctl(fd, OPROMCHILD, arg);
755
                break;
756
        case 7: /* OPROMGETPROP */
757
                ret = sys_ioctl(fd, OPROMGETPROP, arg);
758
                break;
759
        case 8: /* OPROMNXTPROP */
760
                ret = sys_ioctl(fd, OPROMNXTPROP, arg);
761
                break;
762
        case 9: /* OPROMU2P */
763
                ret = sys_ioctl(fd, OPROMU2P, arg);
764
                break;
765
        case 10: /* OPROMGETCONS */
766
                ret = sys_ioctl(fd, OPROMGETCONS, arg);
767
                break;
768
        case 11: /* OPROMGETFBNAME */
769
                ret = sys_ioctl(fd, OPROMGETFBNAME, arg);
770
                break;
771
        case 12: /* OPROMGETBOOTARGS */
772
                ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg);
773
                break;
774
        case 13: /* OPROMGETVERSION */
775
        case 14: /* OPROMPATH2DRV */
776
        case 15: /* OPROMDEV2PROMNAME */
777
        case 16: /* OPROMPROM2DEVNAME */
778
        case 17: /* OPROMGETPROPLEN */
779
        default:
780
                ret = -EINVAL;
781
                break;
782
        };
783
        return ret;
784
}
785
 
786
/* }}} */
787
 
788
asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
789
{
790
        struct file *filp;
791
        int error = -EBADF;
792
 
793
        filp = fget(fd);
794
        if (!filp)
795
                goto out;
796
 
797
        lock_kernel();
798
        error = -EFAULT;
799
        switch ((cmd >> 8) & 0xff) {
800
        case 'S': error = solaris_S(filp, fd, cmd, arg); break;
801
        case 'T': error = solaris_T(fd, cmd, arg); break;
802
        case 'i': error = solaris_i(fd, cmd, arg); break;
803
        case 'r': error = solaris_r(fd, cmd, arg); break;
804
        case 's': error = solaris_s(fd, cmd, arg); break;
805
        case 't': error = solaris_t(fd, cmd, arg); break;
806
        case 'f': error = sys_ioctl(fd, cmd, arg); break;
807
        case 'm': error = solaris_m(fd, cmd, arg); break;
808
        case 'O': error = solaris_O(fd, cmd, arg); break;
809
        default:
810
                error = -ENOSYS;
811
                break;
812
        }
813
        unlock_kernel();
814
        fput(filp);
815
out:
816
        if (error == -ENOSYS) {
817
                unsigned char c = cmd>>8;
818
 
819
                if (c < ' ' || c > 126) c = '.';
820
                printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n",
821
                       (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
822
                error = -EINVAL;
823
        }
824
        return error;
825
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.