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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sparc64/] [solaris/] [timod.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: timod.c,v 1.1.1.1 2004-04-15 01:33:57 phoenix Exp $
2
 * timod.c: timod emulation.
3
 *
4
 * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
5
 *
6
 * Streams & timod emulation based on code
7
 * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
8
 *
9
 */
10
 
11
#include <linux/types.h>
12
#include <linux/kernel.h>
13
#include <linux/sched.h>
14
#include <linux/smp.h>
15
#include <linux/smp_lock.h>
16
#include <linux/ioctl.h>
17
#include <linux/fs.h>
18
#include <linux/file.h>
19
#include <linux/netdevice.h>
20
#include <linux/poll.h>
21
 
22
#include <net/sock.h>
23
 
24
#include <asm/uaccess.h>
25
#include <asm/termios.h>
26
 
27
#include "conv.h"
28
#include "socksys.h"
29
 
30
extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
31
        unsigned long arg);
32
extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
33
        u32 arg);
34
asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
35
 
36
static spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
37
static char * page = NULL ;
38
 
39
#ifndef DEBUG_SOLARIS_KMALLOC
40
 
41
#define mykmalloc kmalloc
42
#define mykfree kfree
43
 
44
#else
45
 
46
void * mykmalloc(size_t s, int gfp)
47
{
48
        static char * page;
49
        static size_t free;
50
        void * r;
51
        s = ((s + 63) & ~63);
52
        if( s > PAGE_SIZE ) {
53
                SOLD("too big size, calling real kmalloc");
54
                return kmalloc(s, gfp);
55
        }
56
        if( s > free ) {
57
                /* we are wasting memory, but we don't care */
58
                page = (char *)__get_free_page(gfp);
59
                free = PAGE_SIZE;
60
        }
61
        r = page;
62
        page += s;
63
        free -= s;
64
        return r;
65
}
66
 
67
void mykfree(void *p)
68
{
69
}
70
 
71
#endif
72
 
73
#ifndef DEBUG_SOLARIS
74
 
75
#define BUF_SIZE        PAGE_SIZE
76
#define PUT_MAGIC(a,m)
77
#define SCHECK_MAGIC(a,m)
78
#define BUF_OFFSET      0
79
#define MKCTL_TRAILER   0
80
 
81
#else
82
 
83
#define BUF_SIZE        (PAGE_SIZE-2*sizeof(u64))
84
#define BUFPAGE_MAGIC   0xBADC0DEDDEADBABEL
85
#define MKCTL_MAGIC     0xDEADBABEBADC0DEDL
86
#define PUT_MAGIC(a,m)  do{(*(u64*)(a))=(m);}while(0)
87
#define SCHECK_MAGIC(a,m)       do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
88
                                __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
89
#define BUF_OFFSET      sizeof(u64)
90
#define MKCTL_TRAILER   sizeof(u64)
91
 
92
#endif
93
 
94
static char *getpage( void )
95
{
96
        char *r;
97
        SOLD("getting page");
98
        spin_lock(&timod_pagelock);
99
        if (page) {
100
                r = page;
101
                page = NULL;
102
                spin_unlock(&timod_pagelock);
103
                SOLD("got cached");
104
                return r + BUF_OFFSET;
105
        }
106
        spin_unlock(&timod_pagelock);
107
        SOLD("getting new");
108
        r = (char *)__get_free_page(GFP_KERNEL);
109
        PUT_MAGIC(r,BUFPAGE_MAGIC);
110
        PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
111
        return r + BUF_OFFSET;
112
}
113
 
114
static void putpage(char *p)
115
{
116
        SOLD("putting page");
117
        p = p - BUF_OFFSET;
118
        SCHECK_MAGIC(p,BUFPAGE_MAGIC);
119
        SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
120
        spin_lock(&timod_pagelock);
121
        if (page) {
122
                spin_unlock(&timod_pagelock);
123
                free_page((unsigned long)p);
124
                SOLD("freed it");
125
        } else {
126
                page = p;
127
                spin_unlock(&timod_pagelock);
128
                SOLD("cached it");
129
        }
130
}
131
 
132
static struct T_primsg *timod_mkctl(int size)
133
{
134
        struct T_primsg *it;
135
 
136
        SOLD("creating primsg");
137
        it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
138
        if (it) {
139
                SOLD("got it");
140
                it->pri = MSG_HIPRI;
141
                it->length = size;
142
                PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
143
        }
144
        return it;
145
}
146
 
147
static void timod_wake_socket(unsigned int fd)
148
{
149
        struct socket *sock;
150
 
151
        SOLD("wakeing socket");
152
        sock = &current->files->fd[fd]->f_dentry->d_inode->u.socket_i;
153
        wake_up_interruptible(&sock->wait);
154
        read_lock(&sock->sk->callback_lock);
155
        if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
156
                __kill_fasync(sock->fasync_list, SIGIO, POLL_IN);
157
        read_unlock(&sock->sk->callback_lock);
158
        SOLD("done");
159
}
160
 
161
static void timod_queue(unsigned int fd, struct T_primsg *it)
162
{
163
        struct sol_socket_struct *sock;
164
 
165
        SOLD("queuing primsg");
166
        sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
167
        it->next = sock->pfirst;
168
        sock->pfirst = it;
169
        if (!sock->plast)
170
                sock->plast = it;
171
        timod_wake_socket(fd);
172
        SOLD("done");
173
}
174
 
175
static void timod_queue_end(unsigned int fd, struct T_primsg *it)
176
{
177
        struct sol_socket_struct *sock;
178
 
179
        SOLD("queuing primsg at end");
180
        sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
181
        it->next = NULL;
182
        if (sock->plast)
183
                sock->plast->next = it;
184
        else
185
                sock->pfirst = it;
186
        sock->plast = it;
187
        SOLD("done");
188
}
189
 
190
static void timod_error(unsigned int fd, int prim, int terr, int uerr)
191
{
192
        struct T_primsg *it;
193
 
194
        SOLD("making error");
195
        it = timod_mkctl(sizeof(struct T_error_ack));
196
        if (it) {
197
                struct T_error_ack *err = (struct T_error_ack *)&it->type;
198
 
199
                SOLD("got it");
200
                err->PRIM_type = T_ERROR_ACK;
201
                err->ERROR_prim = prim;
202
                err->TLI_error = terr;
203
                err->UNIX_error = uerr; /* FIXME: convert this */
204
                timod_queue(fd, it);
205
        }
206
        SOLD("done");
207
}
208
 
209
static void timod_ok(unsigned int fd, int prim)
210
{
211
        struct T_primsg *it;
212
        struct T_ok_ack *ok;
213
 
214
        SOLD("creating ok ack");
215
        it = timod_mkctl(sizeof(*ok));
216
        if (it) {
217
                SOLD("got it");
218
                ok = (struct T_ok_ack *)&it->type;
219
                ok->PRIM_type = T_OK_ACK;
220
                ok->CORRECT_prim = prim;
221
                timod_queue(fd, it);
222
        }
223
        SOLD("done");
224
}
225
 
226
static int timod_optmgmt(unsigned int fd, int flag, char *opt_buf, int opt_len, int do_ret)
227
{
228
        int error, failed;
229
        int ret_space, ret_len;
230
        long args[5];
231
        char *ret_pos,*ret_buf;
232
        int (*sys_socketcall)(int, unsigned long *) =
233
                (int (*)(int, unsigned long *))SYS(socketcall);
234
        mm_segment_t old_fs = get_fs();
235
 
236
        SOLD("entry");
237
        SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret));
238
        if (!do_ret && (!opt_buf || opt_len <= 0))
239
                return 0;
240
        SOLD("getting page");
241
        ret_pos = ret_buf = getpage();
242
        ret_space = BUF_SIZE;
243
        ret_len = 0;
244
 
245
        error = failed = 0;
246
        SOLD("looping");
247
        while(opt_len >= sizeof(struct opthdr)) {
248
                struct opthdr *opt;
249
                int orig_opt_len;
250
                SOLD("loop start");
251
                opt = (struct opthdr *)ret_pos;
252
                if (ret_space < sizeof(struct opthdr)) {
253
                        failed = TSYSERR;
254
                        break;
255
                }
256
                SOLD("getting opthdr");
257
                if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
258
                        opt->len > opt_len) {
259
                        failed = TBADOPT;
260
                        break;
261
                }
262
                SOLD("got opthdr");
263
                if (flag == T_NEGOTIATE) {
264
                        char *buf;
265
 
266
                        SOLD("handling T_NEGOTIATE");
267
                        buf = ret_pos + sizeof(struct opthdr);
268
                        if (ret_space < opt->len + sizeof(struct opthdr) ||
269
                                copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) {
270
                                failed = TSYSERR;
271
                                break;
272
                        }
273
                        SOLD("got optdata");
274
                        args[0] = fd;
275
                        args[1] = opt->level;
276
                        args[2] = opt->name;
277
                        args[3] = (long)buf;
278
                        args[4] = opt->len;
279
                        SOLD("calling SETSOCKOPT");
280
                        set_fs(KERNEL_DS);
281
                        error = sys_socketcall(SYS_SETSOCKOPT, args);
282
                        set_fs(old_fs);
283
                        if (error) {
284
                                failed = TBADOPT;
285
                                break;
286
                        }
287
                        SOLD("SETSOCKOPT ok");
288
                }
289
                orig_opt_len = opt->len;
290
                opt->len = ret_space - sizeof(struct opthdr);
291
                if (opt->len < 0) {
292
                        failed = TSYSERR;
293
                        break;
294
                }
295
                args[0] = fd;
296
                args[1] = opt->level;
297
                args[2] = opt->name;
298
                args[3] = (long)(ret_pos+sizeof(struct opthdr));
299
                args[4] = (long)&opt->len;
300
                SOLD("calling GETSOCKOPT");
301
                set_fs(KERNEL_DS);
302
                error = sys_socketcall(SYS_GETSOCKOPT, args);
303
                set_fs(old_fs);;
304
                if (error) {
305
                        failed = TBADOPT;
306
                        break;
307
                }
308
                SOLD("GETSOCKOPT ok");
309
                ret_space -= sizeof(struct opthdr) + opt->len;
310
                ret_len += sizeof(struct opthdr) + opt->len;
311
                ret_pos += sizeof(struct opthdr) + opt->len;
312
                opt_len -= sizeof(struct opthdr) + orig_opt_len;
313
                opt_buf += sizeof(struct opthdr) + orig_opt_len;
314
                SOLD("loop end");
315
        }
316
        SOLD("loop done");
317
        if (do_ret) {
318
                SOLD("generating ret msg");
319
                if (failed)
320
                        timod_error(fd, T_OPTMGMT_REQ, failed, -error);
321
                else {
322
                        struct T_primsg *it;
323
                        it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
324
                        if (it) {
325
                                struct T_optmgmt_ack *ack =
326
                                        (struct T_optmgmt_ack *)&it->type;
327
                                SOLD("got primsg");
328
                                ack->PRIM_type = T_OPTMGMT_ACK;
329
                                ack->OPT_length = ret_len;
330
                                ack->OPT_offset = sizeof(struct T_optmgmt_ack);
331
                                ack->MGMT_flags = (failed ? T_FAILURE : flag);
332
                                memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack),
333
                                        ret_buf, ret_len);
334
                                timod_queue(fd, it);
335
                        }
336
                }
337
        }
338
        SOLDD(("put_page %p\n", ret_buf));
339
        putpage(ret_buf);
340
        SOLD("done");
341
        return 0;
342
}
343
 
344
int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
345
                        char *data_buf, int data_len, int flags)
346
{
347
        int ret, error, terror;
348
        char *buf;
349
        struct file *filp;
350
        struct inode *ino;
351
        struct sol_socket_struct *sock;
352
        mm_segment_t old_fs = get_fs();
353
        long args[6];
354
        int (*sys_socketcall)(int, unsigned long *) =
355
                (int (*)(int, unsigned long *))SYS(socketcall);
356
        int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int) =
357
                (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))SYS(sendto);
358
        filp = current->files->fd[fd];
359
        ino = filp->f_dentry->d_inode;
360
        sock = (struct sol_socket_struct *)filp->private_data;
361
        SOLD("entry");
362
        if (get_user(ret, (int *)A(ctl_buf)))
363
                return -EFAULT;
364
        switch (ret) {
365
        case T_BIND_REQ:
366
        {
367
                struct T_bind_req req;
368
 
369
                SOLDD(("bind %016lx(%016lx)\n", sock, filp));
370
                SOLD("T_BIND_REQ");
371
                if (sock->state != TS_UNBND) {
372
                        timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
373
                        return 0;
374
                }
375
                SOLD("state ok");
376
                if (copy_from_user(&req, ctl_buf, sizeof(req))) {
377
                        timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
378
                        return 0;
379
                }
380
                SOLD("got ctl req");
381
                if (req.ADDR_offset && req.ADDR_length) {
382
                        if (req.ADDR_length > BUF_SIZE) {
383
                                timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
384
                                return 0;
385
                        }
386
                        SOLD("req size ok");
387
                        buf = getpage();
388
                        if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
389
                                timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
390
                                putpage(buf);
391
                                return 0;
392
                        }
393
                        SOLD("got ctl data");
394
                        args[0] = fd;
395
                        args[1] = (long)buf;
396
                        args[2] = req.ADDR_length;
397
                        SOLD("calling BIND");
398
                        set_fs(KERNEL_DS);
399
                        error = sys_socketcall(SYS_BIND, args);
400
                        set_fs(old_fs);
401
                        putpage(buf);
402
                        SOLD("BIND returned");
403
                } else
404
                        error = 0;
405
                if (!error) {
406
                        struct T_primsg *it;
407
                        if (req.CONIND_number) {
408
                                args[0] = fd;
409
                                args[1] = req.CONIND_number;
410
                                SOLD("calling LISTEN");
411
                                set_fs(KERNEL_DS);
412
                                error = sys_socketcall(SYS_LISTEN, args);
413
                                set_fs(old_fs);
414
                                SOLD("LISTEN done");
415
                        }
416
                        it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
417
                        if (it) {
418
                                struct T_bind_ack *ack;
419
 
420
                                ack = (struct T_bind_ack *)&it->type;
421
                                ack->PRIM_type = T_BIND_ACK;
422
                                ack->ADDR_offset = sizeof(*ack);
423
                                ack->ADDR_length = sizeof(struct sockaddr);
424
                                ack->CONIND_number = req.CONIND_number;
425
                                args[0] = fd;
426
                                args[1] = (long)(ack+sizeof(*ack));
427
                                args[2] = (long)&ack->ADDR_length;
428
                                set_fs(KERNEL_DS);
429
                                sys_socketcall(SYS_GETSOCKNAME,args);
430
                                set_fs(old_fs);
431
                                sock->state = TS_IDLE;
432
                                timod_ok(fd, T_BIND_REQ);
433
                                timod_queue_end(fd, it);
434
                                SOLD("BIND done");
435
                                return 0;
436
                        }
437
                }
438
                SOLD("some error");
439
                switch (error) {
440
                        case -EINVAL:
441
                                terror = TOUTSTATE;
442
                                error = 0;
443
                                break;
444
                        case -EACCES:
445
                                terror = TACCES;
446
                                error = 0;
447
                                break;
448
                        case -EADDRNOTAVAIL:
449
                        case -EADDRINUSE:
450
                                terror = TNOADDR;
451
                                error = 0;
452
                                break;
453
                        default:
454
                                terror = TSYSERR;
455
                                break;
456
                }
457
                timod_error(fd, T_BIND_REQ, terror, -error);
458
                SOLD("BIND done");
459
                return 0;
460
        }
461
        case T_CONN_REQ:
462
        {
463
                struct T_conn_req req;
464
                unsigned short oldflags;
465
                struct T_primsg *it;
466
                SOLD("T_CONN_REQ");
467
                if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
468
                        timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
469
                        return 0;
470
                }
471
                SOLD("state ok");
472
                if (copy_from_user(&req, ctl_buf, sizeof(req))) {
473
                        timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
474
                        return 0;
475
                }
476
                SOLD("got ctl req");
477
                if (ctl_len > BUF_SIZE) {
478
                        timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
479
                        return 0;
480
                }
481
                SOLD("req size ok");
482
                buf = getpage();
483
                if (copy_from_user(buf, ctl_buf, ctl_len)) {
484
                        timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
485
                        putpage(buf);
486
                        return 0;
487
                }
488
#ifdef DEBUG_SOLARIS            
489
                {
490
                        char * ptr = buf;
491
                        int len = ctl_len;
492
                        printk("returned data (%d bytes): ",len);
493
                        while( len-- ) {
494
                                if (!(len & 7))
495
                                        printk(" ");
496
                                printk("%02x",(unsigned char)*ptr++);
497
                        }
498
                        printk("\n");
499
                }
500
#endif
501
                SOLD("got ctl data");
502
                args[0] = fd;
503
                args[1] = (long)buf+req.DEST_offset;
504
                args[2] = req.DEST_length;
505
                oldflags = filp->f_flags;
506
                filp->f_flags &= ~O_NONBLOCK;
507
                SOLD("calling CONNECT");
508
                set_fs(KERNEL_DS);
509
                error = sys_socketcall(SYS_CONNECT, args);
510
                set_fs(old_fs);
511
                filp->f_flags = oldflags;
512
                SOLD("CONNECT done");
513
                if (!error) {
514
                        struct T_conn_con *con;
515
                        SOLD("no error");
516
                        it = timod_mkctl(ctl_len);
517
                        if (!it) {
518
                                putpage(buf);
519
                                return -ENOMEM;
520
                        }
521
                        con = (struct T_conn_con *)&it->type;
522
#ifdef DEBUG_SOLARIS                    
523
                        {
524
                                char * ptr = buf;
525
                                int len = ctl_len;
526
                                printk("returned data (%d bytes): ",len);
527
                                while( len-- ) {
528
                                        if (!(len & 7))
529
                                                printk(" ");
530
                                        printk("%02x",(unsigned char)*ptr++);
531
                                }
532
                                printk("\n");
533
                        }
534
#endif
535
                        memcpy(con, buf, ctl_len);
536
                        SOLD("copied ctl_buf");
537
                        con->PRIM_type = T_CONN_CON;
538
                        sock->state = TS_DATA_XFER;
539
                } else {
540
                        struct T_discon_ind *dis;
541
                        SOLD("some error");
542
                        it = timod_mkctl(sizeof(*dis));
543
                        if (!it) {
544
                                putpage(buf);
545
                                return -ENOMEM;
546
                        }
547
                        SOLD("got primsg");
548
                        dis = (struct T_discon_ind *)&it->type;
549
                        dis->PRIM_type = T_DISCON_IND;
550
                        dis->DISCON_reason = -error;    /* FIXME: convert this as in iABI_errors() */
551
                        dis->SEQ_number = 0;
552
                }
553
                putpage(buf);
554
                timod_ok(fd, T_CONN_REQ);
555
                it->pri = 0;
556
                timod_queue_end(fd, it);
557
                SOLD("CONNECT done");
558
                return 0;
559
        }
560
        case T_OPTMGMT_REQ:
561
        {
562
                struct T_optmgmt_req req;
563
                SOLD("OPTMGMT_REQ");
564
                if (copy_from_user(&req, ctl_buf, sizeof(req)))
565
                        return -EFAULT;
566
                SOLD("got req");
567
                return timod_optmgmt(fd, req.MGMT_flags,
568
                                req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,
569
                                req.OPT_length, 1);
570
        }
571
        case T_UNITDATA_REQ:
572
        {
573
                struct T_unitdata_req req;
574
 
575
                int err;
576
                SOLD("T_UNITDATA_REQ");
577
                if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) {
578
                        timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
579
                        return 0;
580
                }
581
                SOLD("state ok");
582
                if (copy_from_user(&req, ctl_buf, sizeof(req))) {
583
                        timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
584
                        return 0;
585
                }
586
                SOLD("got ctl req");
587
#ifdef DEBUG_SOLARIS            
588
                {
589
                        char * ptr = ctl_buf+req.DEST_offset;
590
                        int len = req.DEST_length;
591
                        printk("socket address (%d bytes): ",len);
592
                        while( len-- ) {
593
                                char c;
594
                                if (get_user(c,ptr))
595
                                        printk("??");
596
                                else
597
                                        printk("%02x",(unsigned char)c);
598
                                ptr++;
599
                        }
600
                        printk("\n");
601
                }
602
#endif          
603
                err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr*)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length);
604
                if (err == data_len)
605
                        return 0;
606
                if(err >= 0) {
607
                        printk("timod: sendto failed to send all the data\n");
608
                        return 0;
609
                }
610
                timod_error(fd, T_CONN_REQ, TSYSERR, -err);
611
                return 0;
612
        }
613
        default:
614
                printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret);
615
                break;
616
        }
617
        return -EINVAL;
618
}
619
 
620
int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len,
621
                        char *data_buf, int data_maxlen, s32 *data_len, int *flags_p)
622
{
623
        int error;
624
        int oldflags;
625
        struct file *filp;
626
        struct inode *ino;
627
        struct sol_socket_struct *sock;
628
        struct T_unitdata_ind udi;
629
        mm_segment_t old_fs = get_fs();
630
        long args[6];
631
        char *tmpbuf;
632
        int tmplen;
633
        int (*sys_socketcall)(int, unsigned long *) =
634
                (int (*)(int, unsigned long *))SYS(socketcall);
635
        int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *);
636
 
637
        SOLD("entry");
638
        SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
639
        filp = current->files->fd[fd];
640
        ino = filp->f_dentry->d_inode;
641
        sock = (struct sol_socket_struct *)filp->private_data;
642
        SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
643
        if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM
644
                && sock->state == TS_IDLE) {
645
                SOLD("calling LISTEN");
646
                args[0] = fd;
647
                args[1] = -1;
648
                set_fs(KERNEL_DS);
649
                sys_socketcall(SYS_LISTEN, args);
650
                set_fs(old_fs);
651
                SOLD("LISTEN done");
652
        }
653
        if (!(filp->f_flags & O_NONBLOCK)) {
654
                poll_table wait_table, *wait;
655
 
656
                poll_initwait(&wait_table);
657
                wait = &wait_table;
658
                for(;;) {
659
                        SOLD("loop");
660
                        set_current_state(TASK_INTERRUPTIBLE);
661
                        /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
662
                        /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
663
                        /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
664
                        /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */
665
                        /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */
666
                        /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */
667
                        if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI))
668
                                break;
669
                        SOLD("cond 1 passed");
670
                        if (
671
                        #if 1
672
                                *flags_p != MSG_HIPRI &&
673
                        #endif
674
                                ((filp->f_op->poll(filp, wait) & POLLIN) ||
675
                                (filp->f_op->poll(filp, NULL) & POLLIN) ||
676
                                signal_pending(current))
677
                        ) {
678
                                break;
679
                        }
680
                        if( *flags_p == MSG_HIPRI ) {
681
                                SOLD("avoiding lockup");
682
                                break ;
683
                        }
684
                        if(wait_table.error) {
685
                                SOLD("wait-table error");
686
                                poll_freewait(&wait_table);
687
                                return wait_table.error;
688
                        }
689
                        SOLD("scheduling");
690
                        schedule();
691
                }
692
                SOLD("loop done");
693
                current->state = TASK_RUNNING;
694
                poll_freewait(&wait_table);
695
                if (signal_pending(current)) {
696
                        SOLD("signal pending");
697
                        return -EINTR;
698
                }
699
        }
700
        if (ctl_maxlen >= 0 && sock->pfirst) {
701
                struct T_primsg *it = sock->pfirst;
702
                int l = min_t(int, ctl_maxlen, it->length);
703
                SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
704
                SOLD("purting ctl data");
705
                if(copy_to_user(ctl_buf,
706
                        (char*)&it->type + sock->offset, l))
707
                        return -EFAULT;
708
                SOLD("pur it");
709
                if(put_user(l, ctl_len))
710
                        return -EFAULT;
711
                SOLD("set ctl_len");
712
                *flags_p = it->pri;
713
                it->length -= l;
714
                if (it->length) {
715
                        SOLD("more ctl");
716
                        sock->offset += l;
717
                        return MORECTL;
718
                } else {
719
                        SOLD("removing message");
720
                        sock->pfirst = it->next;
721
                        if (!sock->pfirst)
722
                                sock->plast = NULL;
723
                        SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));
724
                        mykfree(it);
725
                        sock->offset = 0;
726
                        SOLD("ctl done");
727
                        return 0;
728
                }
729
        }
730
        *flags_p = 0;
731
        if (ctl_maxlen >= 0) {
732
                SOLD("ACCEPT perhaps?");
733
                if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) {
734
                        struct T_conn_ind ind;
735
                        char *buf = getpage();
736
                        int len = BUF_SIZE;
737
 
738
                        SOLD("trying ACCEPT");
739
                        if (put_user(ctl_maxlen - sizeof(ind), ctl_len))
740
                                return -EFAULT;
741
                        args[0] = fd;
742
                        args[1] = (long)buf;
743
                        args[2] = (long)&len;
744
                        oldflags = filp->f_flags;
745
                        filp->f_flags |= O_NONBLOCK;
746
                        SOLD("calling ACCEPT");
747
                        set_fs(KERNEL_DS);
748
                        error = sys_socketcall(SYS_ACCEPT, args);
749
                        set_fs(old_fs);
750
                        filp->f_flags = oldflags;
751
                        if (error < 0) {
752
                                SOLD("some error");
753
                                putpage(buf);
754
                                return error;
755
                        }
756
                        if (error) {
757
                                SOLD("connect");
758
                                putpage(buf);
759
                                if (sizeof(ind) > ctl_maxlen) {
760
                                        SOLD("generating CONN_IND");
761
                                        ind.PRIM_type = T_CONN_IND;
762
                                        ind.SRC_length = len;
763
                                        ind.SRC_offset = sizeof(ind);
764
                                        ind.OPT_length = ind.OPT_offset = 0;
765
                                        ind.SEQ_number = error;
766
                                        if(copy_to_user(ctl_buf, &ind, sizeof(ind))||
767
                                           put_user(sizeof(ind)+ind.SRC_length,ctl_len))
768
                                                return -EFAULT;
769
                                        SOLD("CONN_IND created");
770
                                }
771
                                if (data_maxlen >= 0)
772
                                        put_user(0, data_len);
773
                                SOLD("CONN_IND done");
774
                                return 0;
775
                        }
776
                        if (len>ctl_maxlen) {
777
                                SOLD("data don't fit");
778
                                putpage(buf);
779
                                return -EFAULT;         /* XXX - is this ok ? */
780
                        }
781
                        if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){
782
                                SOLD("can't copy data");
783
                                putpage(buf);
784
                                return -EFAULT;
785
                        }
786
                        SOLD("ACCEPT done");
787
                        putpage(buf);
788
                }
789
        }
790
        SOLD("checking data req");
791
        if (data_maxlen <= 0) {
792
                if (data_maxlen == 0)
793
                        put_user(0, data_len);
794
                if (ctl_maxlen >= 0)
795
                        put_user(0, ctl_len);
796
                return -EAGAIN;
797
        }
798
        SOLD("wants data");
799
        if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
800
                SOLD("udi fits");
801
                tmpbuf = ctl_buf + sizeof(udi);
802
                tmplen = ctl_maxlen - sizeof(udi);
803
        } else {
804
                SOLD("udi does not fit");
805
                tmpbuf = NULL;
806
                tmplen = 0;
807
        }
808
        if (put_user(tmplen, ctl_len))
809
                return -EFAULT;
810
        SOLD("set ctl_len");
811
        oldflags = filp->f_flags;
812
        filp->f_flags |= O_NONBLOCK;
813
        SOLD("calling recvfrom");
814
        sys_recvfrom = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
815
        error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr*)tmpbuf, ctl_len);
816
        filp->f_flags = oldflags;
817
        if (error < 0)
818
                return error;
819
        SOLD("error >= 0" ) ;
820
        if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
821
                SOLD("generating udi");
822
                udi.PRIM_type = T_UNITDATA_IND;
823
                get_user(udi.SRC_length, ctl_len);
824
                udi.SRC_offset = sizeof(udi);
825
                udi.OPT_length = udi.OPT_offset = 0;
826
                copy_to_user(ctl_buf, &udi, sizeof(udi));
827
                put_user(sizeof(udi)+udi.SRC_length, ctl_len);
828
                SOLD("udi done");
829
        } else
830
                put_user(0, ctl_len);
831
        put_user(error, data_len);
832
        SOLD("done");
833
        return 0;
834
}
835
 
836
asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
837
{
838
        struct file *filp;
839
        struct inode *ino;
840
        struct strbuf *ctlptr, *datptr;
841
        struct strbuf ctl, dat;
842
        int *flgptr;
843
        int flags;
844
        int error = -EBADF;
845
 
846
        SOLD("entry");
847
        lock_kernel();
848
        if(fd >= NR_OPEN) goto out;
849
 
850
        filp = current->files->fd[fd];
851
        if(!filp) goto out;
852
 
853
        ino = filp->f_dentry->d_inode;
854
        if (!ino) goto out;
855
 
856
        if (!ino->i_sock)
857
                goto out;
858
 
859
        ctlptr = (struct strbuf *)A(arg1);
860
        datptr = (struct strbuf *)A(arg2);
861
        flgptr = (int *)A(arg3);
862
 
863
        error = -EFAULT;
864
 
865
        if (ctlptr) {
866
                if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) ||
867
                    put_user(-1,&ctlptr->len))
868
                        goto out;
869
        } else
870
                ctl.maxlen = -1;
871
 
872
        if (datptr) {
873
                if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) ||
874
                    put_user(-1,&datptr->len))
875
                        goto out;
876
        } else
877
                dat.maxlen = -1;
878
 
879
        if (get_user(flags,flgptr))
880
                goto out;
881
 
882
        switch (flags) {
883
        case 0:
884
        case MSG_HIPRI:
885
        case MSG_ANY:
886
        case MSG_BAND:
887
                break;
888
        default:
889
                error = -EINVAL;
890
                goto out;
891
        }
892
 
893
        error = timod_getmsg(fd,(char*)A(ctl.buf),ctl.maxlen,&ctlptr->len,
894
                                (char*)A(dat.buf),dat.maxlen,&datptr->len,&flags);
895
 
896
        if (!error && put_user(flags,flgptr))
897
                error = -EFAULT;
898
out:
899
        unlock_kernel();
900
        SOLD("done");
901
        return error;
902
}
903
 
904
asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
905
{
906
        struct file *filp;
907
        struct inode *ino;
908
        struct strbuf *ctlptr, *datptr;
909
        struct strbuf ctl, dat;
910
        int flags = (int) arg3;
911
        int error = -EBADF;
912
 
913
        SOLD("entry");
914
        lock_kernel();
915
        if(fd >= NR_OPEN) goto out;
916
 
917
        filp = current->files->fd[fd];
918
        if(!filp) goto out;
919
 
920
        ino = filp->f_dentry->d_inode;
921
        if (!ino) goto out;
922
 
923
        if (!ino->i_sock &&
924
                (MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1))
925
                goto out;
926
 
927
        ctlptr = (struct strbuf *)A(arg1);
928
        datptr = (struct strbuf *)A(arg2);
929
 
930
        error = -EFAULT;
931
 
932
        if (ctlptr) {
933
                if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))
934
                        goto out;
935
                if (ctl.len < 0 && flags) {
936
                        error = -EINVAL;
937
                        goto out;
938
                }
939
        } else {
940
                ctl.len = 0;
941
                ctl.buf = 0;
942
        }
943
 
944
        if (datptr) {
945
                if (copy_from_user(&dat,datptr,sizeof(dat)))
946
                        goto out;
947
        } else {
948
                dat.len = 0;
949
                dat.buf = 0;
950
        }
951
 
952
        error = timod_putmsg(fd,(char*)A(ctl.buf),ctl.len,
953
                                (char*)A(dat.buf),dat.len,flags);
954
out:
955
        unlock_kernel();
956
        SOLD("done");
957
        return error;
958
}

powered by: WebSVN 2.1.0

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