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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [kern/] [sys_generic.c] - Blame information for rev 649

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      sys/kern/sys_generic.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: sys_generic.c,v 1.22 1999/11/29 22:02:14 deraadt Exp $        */
34
/*      $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $     */
35
 
36
/*
37
 * Copyright (c) 1996 Theo de Raadt
38
 * Copyright (c) 1982, 1986, 1989, 1993
39
 *      The Regents of the University of California.  All rights reserved.
40
 * (c) UNIX System Laboratories, Inc.
41
 * All or some portions of this file are derived from material licensed
42
 * to the University of California by American Telephone and Telegraph
43
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
44
 * the permission of UNIX System Laboratories, Inc.
45
 *
46
 * Redistribution and use in source and binary forms, with or without
47
 * modification, are permitted provided that the following conditions
48
 * are met:
49
 * 1. Redistributions of source code must retain the above copyright
50
 *    notice, this list of conditions and the following disclaimer.
51
 * 2. Redistributions in binary form must reproduce the above copyright
52
 *    notice, this list of conditions and the following disclaimer in the
53
 *    documentation and/or other materials provided with the distribution.
54
 * 3. All advertising materials mentioning features or use of this software
55
 *    must display the following acknowledgement:
56
 *      This product includes software developed by the University of
57
 *      California, Berkeley and its contributors.
58
 * 4. Neither the name of the University nor the names of its contributors
59
 *    may be used to endorse or promote products derived from this software
60
 *    without specific prior written permission.
61
 *
62
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72
 * SUCH DAMAGE.
73
 *
74
 *      @(#)sys_generic.c       8.5 (Berkeley) 1/21/94
75
 */
76
 
77
#include <sys/param.h>
78
#ifndef __ECOS
79
#include <sys/systm.h>
80
#include <sys/filedesc.h>
81
#endif // __ECOS
82
#include <sys/ioctl.h>
83
#ifdef __ECOS
84
#include <cyg/io/file.h>
85
#else // __ECOS
86
#include <sys/file.h>
87
#include <sys/proc.h>
88
#include <sys/resourcevar.h>
89
#endif // __ECOS
90
#include <sys/socketvar.h>
91
#ifndef __ECOS
92
#include <sys/signalvar.h>
93
#include <sys/kernel.h>
94
#include <sys/uio.h>
95
#include <sys/stat.h>
96
#endif // __ECOS
97
#include <sys/malloc.h>
98
#ifndef __ECOS
99
#include <sys/poll.h>
100
#endif // __ECOS
101
#ifdef KTRACE
102
#include <sys/ktrace.h>
103
#endif
104
 
105
#ifndef __ECOS
106
#include <sys/mount.h>
107
#endif // __ECOS
108
#include <sys/syscallargs.h>
109
 
110
#ifndef __ECOS
111
int selscan __P((struct proc *, fd_set *, fd_set *, int, register_t *));
112
int seltrue __P((dev_t, int, struct proc *));
113
void pollscan __P((struct proc *, struct pollfd *, int, register_t *));
114
#endif // __ECOS
115
 
116
/*
117
 * Read system call.
118
 */
119
#ifdef __ECOS
120
int
121
sys_read(struct sys_read_args *uap, register_t *retval)
122
#else
123
/* ARGSUSED */
124
int
125
sys_read(p, v, retval)
126
        struct proc *p;
127
        void *v;
128
        register_t *retval;
129
#endif
130
{
131
#ifndef __ECOS
132
        register struct sys_read_args /* {
133
                syscallarg(int) fd;
134
                syscallarg(void *) buf;
135
                syscallarg(size_t) nbyte;
136
        } */ *uap = v;
137
        register struct filedesc *fdp = p->p_fd;
138
#endif
139
        struct file *fp;
140
        struct uio auio;
141
        struct iovec aiov;
142
        long cnt, error = 0;
143
#ifdef KTRACE
144
        struct iovec ktriov;
145
#endif
146
 
147
#ifdef __ECOS
148
        if (getfp((u_int)SCARG(uap, fd), &fp) ||
149
#else
150
        if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
151
            (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
152
#endif
153
            (fp->f_flag & FREAD) == 0)
154
                return (EBADF);
155
        /* Don't allow nbyte to be larger than max return val */
156
        if (SCARG(uap, nbyte) > SSIZE_MAX)
157
                return(EINVAL);
158
        aiov.iov_base = (caddr_t)SCARG(uap, buf);
159
        aiov.iov_len = SCARG(uap, nbyte);
160
        auio.uio_iov = &aiov;
161
        auio.uio_iovcnt = 1;
162
        auio.uio_resid = SCARG(uap, nbyte);
163
        auio.uio_rw = UIO_READ;
164
        auio.uio_segflg = UIO_USERSPACE;
165
#ifndef __ECOS
166
        auio.uio_procp = p;
167
#endif
168
#ifdef KTRACE
169
        /*
170
         * if tracing, save a copy of iovec
171
         */
172
        if (KTRPOINT(p, KTR_GENIO))
173
                ktriov = aiov;
174
#endif
175
        cnt = SCARG(uap, nbyte);
176
#ifdef __ECOS
177
        error = (*fp->f_ops->fo_read)(fp, &auio);
178
#else
179
        error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
180
#endif
181
        if (error)
182
#ifdef __ECOS
183
                if (auio.uio_resid != cnt && (
184
#else
185
                if (auio.uio_resid != cnt && (error == ERESTART ||
186
#endif
187
                    error == EINTR || error == EWOULDBLOCK))
188
                        error = 0;
189
        cnt -= auio.uio_resid;
190
#ifdef KTRACE
191
        if (KTRPOINT(p, KTR_GENIO) && error == 0)
192
                ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
193
                    cnt, error);
194
#endif
195
        *retval = cnt;
196
        return (error);
197
}
198
 
199
 
200
#ifndef __ECOS
201
/*
202
 * Scatter read system call.
203
 */
204
int
205
sys_readv(p, v, retval)
206
        struct proc *p;
207
        void *v;
208
        register_t *retval;
209
{
210
        register struct sys_readv_args /* {
211
                syscallarg(int) fd;
212
                syscallarg(struct iovec *) iovp;
213
                syscallarg(int) iovcnt;
214
        } */ *uap = v;
215
        register struct file *fp;
216
        register struct filedesc *fdp = p->p_fd;
217
        struct uio auio;
218
        register struct iovec *iov;
219
        struct iovec *needfree;
220
        struct iovec aiov[UIO_SMALLIOV];
221
        long i, cnt, error = 0;
222
        u_int iovlen;
223
#ifdef KTRACE
224
        struct iovec *ktriov = NULL;
225
#endif
226
 
227
        if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
228
            (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
229
            (fp->f_flag & FREAD) == 0)
230
                return (EBADF);
231
        if (SCARG(uap, iovcnt) <= 0)
232
                return (EINVAL);
233
        /* note: can't use iovlen until iovcnt is validated */
234
        iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
235
        if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
236
                if (SCARG(uap, iovcnt) > IOV_MAX)
237
                        return (EINVAL);
238
                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
239
                needfree = iov;
240
        } else {
241
                iov = aiov;
242
                needfree = NULL;
243
        }
244
        auio.uio_iov = iov;
245
        auio.uio_iovcnt = SCARG(uap, iovcnt);
246
        auio.uio_rw = UIO_READ;
247
        auio.uio_segflg = UIO_USERSPACE;
248
        auio.uio_procp = p;
249
        error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
250
        if (error)
251
                goto done;
252
        auio.uio_resid = 0;
253
        for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
254
                /* Don't allow sum > SSIZE_MAX */
255
                if (iov->iov_len > SSIZE_MAX ||
256
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
257
                        error = EINVAL;
258
                        goto done;
259
                }
260
        }
261
#ifdef KTRACE
262
        /*
263
         * if tracing, save a copy of iovec
264
         */
265
        if (KTRPOINT(p, KTR_GENIO))  {
266
                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
267
                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
268
        }
269
#endif
270
        cnt = auio.uio_resid;
271
        error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
272
        if (error)
273
                if (auio.uio_resid != cnt && (error == ERESTART ||
274
                    error == EINTR || error == EWOULDBLOCK))
275
                        error = 0;
276
        cnt -= auio.uio_resid;
277
#ifdef KTRACE
278
        if (ktriov != NULL) {
279
                if (error == 0)
280
                        ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
281
                            cnt, error);
282
                FREE(ktriov, M_TEMP);
283
        }
284
#endif
285
        *retval = cnt;
286
done:
287
        if (needfree)
288
                FREE(needfree, M_IOV);
289
        return (error);
290
}
291
#endif
292
 
293
/*
294
 * Write system call
295
 */
296
#ifdef __ECOS
297
int
298
sys_write(struct sys_write_args *uap, register_t *retval)
299
#else
300
int
301
sys_write(p, v, retval)
302
        struct proc *p;
303
        void *v;
304
        register_t *retval;
305
#endif
306
{
307
#ifndef __ECOS
308
        register struct sys_write_args /* {
309
                syscallarg(int) fd;
310
                syscallarg(void *) buf;
311
                syscallarg(size_t) nbyte;
312
        } */ *uap = v;
313
        register struct filedesc *fdp = p->p_fd;
314
#endif
315
        struct file *fp;
316
        struct uio auio;
317
        struct iovec aiov;
318
        long cnt, error = 0;
319
#ifdef KTRACE
320
        struct iovec ktriov;
321
#endif
322
 
323
#ifdef __ECOS
324
        if (getfp((u_int)SCARG(uap, fd), &fp) ||
325
#else
326
        if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
327
            (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
328
#endif
329
            (fp->f_flag & FWRITE) == 0)
330
                return (EBADF);
331
        /* Don't allow nbyte to be larger than max return val */
332
        if (SCARG(uap, nbyte) > SSIZE_MAX)
333
                return(EINVAL);
334
        aiov.iov_base = (caddr_t)SCARG(uap, buf);
335
        aiov.iov_len = SCARG(uap, nbyte);
336
        auio.uio_iov = &aiov;
337
        auio.uio_iovcnt = 1;
338
        auio.uio_resid = SCARG(uap, nbyte);
339
        auio.uio_rw = UIO_WRITE;
340
        auio.uio_segflg = UIO_USERSPACE;
341
#ifndef __ECOS
342
        auio.uio_procp = p;
343
#endif
344
#ifdef KTRACE
345
        /*
346
         * if tracing, save a copy of iovec
347
         */
348
        if (KTRPOINT(p, KTR_GENIO))
349
                ktriov = aiov;
350
#endif
351
        cnt = SCARG(uap, nbyte);
352
#ifdef __ECOS
353
        error = (*fp->f_ops->fo_write)(fp, &auio);
354
#else
355
        error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
356
#endif
357
        if (error) {
358
#ifdef __ECOS
359
                if (auio.uio_resid != cnt &&
360
                    (error == EINTR || error == EWOULDBLOCK))
361
                        error = 0;
362
#else
363
                if (auio.uio_resid != cnt && (error == ERESTART ||
364
                    error == EINTR || error == EWOULDBLOCK))
365
                        error = 0;
366
                if (error == EPIPE)
367
                        psignal(p, SIGPIPE);
368
#endif
369
        }
370
        cnt -= auio.uio_resid;
371
#ifdef KTRACE
372
        if (KTRPOINT(p, KTR_GENIO) && error == 0)
373
                ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
374
                    &ktriov, cnt, error);
375
#endif
376
        *retval = cnt;
377
        return (error);
378
}
379
 
380
#ifndef __ECOS
381
/*
382
 * Gather write system call
383
 */
384
int
385
sys_writev(p, v, retval)
386
        struct proc *p;
387
        void *v;
388
        register_t *retval;
389
{
390
        register struct sys_writev_args /* {
391
                syscallarg(int) fd;
392
                syscallarg(struct iovec *) iovp;
393
                syscallarg(int) iovcnt;
394
        } */ *uap = v;
395
        register struct file *fp;
396
        register struct filedesc *fdp = p->p_fd;
397
        struct uio auio;
398
        register struct iovec *iov;
399
        struct iovec *needfree;
400
        struct iovec aiov[UIO_SMALLIOV];
401
        long i, cnt, error = 0;
402
        u_int iovlen;
403
#ifdef KTRACE
404
        struct iovec *ktriov = NULL;
405
#endif
406
 
407
        if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
408
            (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
409
            (fp->f_flag & FWRITE) == 0)
410
                return (EBADF);
411
        if (SCARG(uap, iovcnt) <= 0)
412
                return (EINVAL);
413
        /* note: can't use iovlen until iovcnt is validated */
414
        iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
415
        if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
416
                if (SCARG(uap, iovcnt) > IOV_MAX)
417
                        return (EINVAL);
418
                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
419
                needfree = iov;
420
        } else {
421
                iov = aiov;
422
                needfree = NULL;
423
        }
424
        auio.uio_iov = iov;
425
        auio.uio_iovcnt = SCARG(uap, iovcnt);
426
        auio.uio_rw = UIO_WRITE;
427
        auio.uio_segflg = UIO_USERSPACE;
428
        auio.uio_procp = p;
429
        error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
430
        if (error)
431
                goto done;
432
        auio.uio_resid = 0;
433
        for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
434
                /* Don't allow sum > SSIZE_MAX */
435
                if (iov->iov_len > SSIZE_MAX ||
436
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
437
                        error = EINVAL;
438
                        goto done;
439
                }
440
        }
441
#ifdef KTRACE
442
        /*
443
         * if tracing, save a copy of iovec
444
         */
445
        if (KTRPOINT(p, KTR_GENIO))  {
446
                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
447
                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
448
        }
449
#endif
450
        cnt = auio.uio_resid;
451
        error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
452
        if (error) {
453
                if (auio.uio_resid != cnt && (error == ERESTART ||
454
                    error == EINTR || error == EWOULDBLOCK))
455
                        error = 0;
456
                if (error == EPIPE)
457
                        psignal(p, SIGPIPE);
458
        }
459
        cnt -= auio.uio_resid;
460
#ifdef KTRACE
461
        if (ktriov != NULL) {
462
                if (error == 0)
463
                        ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
464
                                ktriov, cnt, error);
465
                FREE(ktriov, M_TEMP);
466
        }
467
#endif
468
        *retval = cnt;
469
done:
470
        if (needfree)
471
                FREE(needfree, M_IOV);
472
        return (error);
473
}
474
#endif
475
 
476
/*
477
 * Ioctl system call
478
 */
479
#ifdef __ECOS
480
int
481
sys_ioctl(struct sys_ioctl_args *uap, register_t *retval)
482
#else
483
/* ARGSUSED */
484
int
485
sys_ioctl(p, v, retval)
486
        struct proc *p;
487
        void *v;
488
        register_t *retval;
489
#endif
490
{
491
#ifndef __ECOS
492
        register struct sys_ioctl_args /* {
493
                syscallarg(int) fd;
494
                syscallarg(u_long) com;
495
                syscallarg(caddr_t) data;
496
        } */ *uap = v;
497
        register struct filedesc *fdp;
498
#endif
499
        int tmp;
500
        struct file *fp;
501
        register u_long com;
502
        register int error;
503
        register u_int size;
504
        caddr_t data, memp;
505
#define STK_PARAMS      128
506
        char stkbuf[STK_PARAMS];
507
 
508
#ifdef __ECOS
509
        if (getfp(SCARG(uap, fd), &fp))
510
#else
511
        fdp = p->p_fd;
512
        if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
513
            (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
514
#endif
515
                return (EBADF);
516
 
517
        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
518
                return (EBADF);
519
 
520
#ifdef __ECOS
521
        com = SCARG(uap, com);
522
#else
523
        switch (com = SCARG(uap, com)) {
524
        case FIONCLEX:
525
                fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
526
                return (0);
527
        case FIOCLEX:
528
                fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
529
                return (0);
530
        }
531
#endif
532
 
533
        /*
534
         * Interpret high order word to find amount of data to be
535
         * copied to/from the user's address space.
536
         */
537
        size = IOCPARM_LEN(com);
538
#ifndef __ECOS
539
        if (size > IOCPARM_MAX)
540
                return (ENOTTY);
541
#endif
542
        memp = NULL;
543
        if (size > sizeof (stkbuf)) {
544
                memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
545
                data = memp;
546
        } else
547
                data = stkbuf;
548
        if (com&IOC_IN) {
549
                if (size) {
550
                        error = copyin(SCARG(uap, data), data, (u_int)size);
551
                        if (error) {
552
                                if (memp)
553
                                        free(memp, M_IOCTLOPS);
554
                                return (error);
555
                        }
556
                } else
557
                        *(caddr_t *)data = SCARG(uap, data);
558
        } else if ((com&IOC_OUT) && size)
559
                /*
560
                 * Zero the buffer so the user always
561
                 * gets back something deterministic.
562
                 */
563
                bzero(data, size);
564
        else if (com&IOC_VOID)
565
                *(caddr_t *)data = SCARG(uap, data);
566
 
567
        switch (com) {
568
 
569
        case FIONBIO:
570
                if ((tmp = *(int *)data) != 0)
571
                        fp->f_flag |= FNONBLOCK;
572
                else
573
                        fp->f_flag &= ~FNONBLOCK;
574
#ifdef __ECOS
575
                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (CYG_ADDRWORD)&tmp);
576
#else
577
                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
578
#endif
579
                break;
580
 
581
        case FIOASYNC:
582
                if ((tmp = *(int *)data) != 0)
583
                        fp->f_flag |= FASYNC;
584
                else
585
                        fp->f_flag &= ~FASYNC;
586
#ifdef __ECOS
587
                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (CYG_ADDRWORD)&tmp);
588
#else
589
                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
590
#endif
591
                break;
592
 
593
#ifndef __ECOS
594
        case FIOSETOWN:
595
                tmp = *(int *)data;
596
                if (fp->f_type == DTYPE_SOCKET) {
597
                        struct socket *so = (struct socket *)fp->f_data;
598
 
599
                        so->so_pgid = tmp;
600
                        so->so_siguid = p->p_cred->p_ruid;
601
                        so->so_sigeuid = p->p_ucred->cr_uid;
602
                        error = 0;
603
                        break;
604
                }
605
                if (tmp <= 0) {
606
                        tmp = -tmp;
607
                } else {
608
                        struct proc *p1 = pfind(tmp);
609
                        if (p1 == 0) {
610
                                error = ESRCH;
611
                                break;
612
                        }
613
                        tmp = p1->p_pgrp->pg_id;
614
                }
615
                error = (*fp->f_ops->fo_ioctl)
616
                        (fp, TIOCSPGRP, (caddr_t)&tmp, p);
617
                break;
618
 
619
        case FIOGETOWN:
620
                if (fp->f_type == DTYPE_SOCKET) {
621
                        error = 0;
622
                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
623
                        break;
624
                }
625
                error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
626
                *(int *)data = -*(int *)data;
627
                break;
628
#endif
629
        default:
630
#ifdef __ECOS
631
                error = (*fp->f_ops->fo_ioctl)(fp, com, (CYG_ADDRWORD)data);
632
#else
633
                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
634
#endif
635
                /*
636
                 * Copy any data to user, size was
637
                 * already set and checked above.
638
                 */
639
                if (error == 0 && (com&IOC_OUT) && size)
640
                        error = copyout(data, SCARG(uap, data), (u_int)size);
641
                break;
642
        }
643
        if (memp)
644
                free(memp, M_IOCTLOPS);
645
        return (error);
646
}
647
 
648
#ifndef __ECOS
649
int     selwait, nselcoll;
650
 
651
/*
652
 * Select system call.
653
 */
654
int
655
sys_select(p, v, retval)
656
        register struct proc *p;
657
        void *v;
658
        register_t *retval;
659
{
660
        register struct sys_select_args /* {
661
                syscallarg(int) nd;
662
                syscallarg(fd_set *) in;
663
                syscallarg(fd_set *) ou;
664
                syscallarg(fd_set *) ex;
665
                syscallarg(struct timeval *) tv;
666
        } */ *uap = v;
667
        fd_set bits[6], *pibits[3], *pobits[3];
668
        struct timeval atv;
669
        int s, ncoll, error = 0, timo;
670
        u_int ni;
671
 
672
        if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
673
                /* forgiving; slightly wrong */
674
                SCARG(uap, nd) = p->p_fd->fd_nfiles;
675
        }
676
        ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
677
        if (SCARG(uap, nd) > FD_SETSIZE) {
678
                caddr_t mbits;
679
 
680
                if ((mbits = malloc(ni * 6, M_TEMP, M_WAITOK)) == NULL) {
681
                        error = EINVAL;
682
                        goto cleanup;
683
                }
684
                bzero(mbits, ni * 6);
685
                pibits[0] = (fd_set *)&mbits[ni * 0];
686
                pibits[1] = (fd_set *)&mbits[ni * 1];
687
                pibits[2] = (fd_set *)&mbits[ni * 2];
688
                pobits[0] = (fd_set *)&mbits[ni * 3];
689
                pobits[1] = (fd_set *)&mbits[ni * 4];
690
                pobits[2] = (fd_set *)&mbits[ni * 5];
691
        } else {
692
                bzero((caddr_t)bits, sizeof(bits));
693
                pibits[0] = &bits[0];
694
                pibits[1] = &bits[1];
695
                pibits[2] = &bits[2];
696
                pobits[0] = &bits[3];
697
                pobits[1] = &bits[4];
698
                pobits[2] = &bits[5];
699
        }
700
 
701
#define getbits(name, x) \
702
        if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
703
            (caddr_t)pibits[x], ni))) \
704
                goto done;
705
        getbits(in, 0);
706
        getbits(ou, 1);
707
        getbits(ex, 2);
708
#undef  getbits
709
 
710
        if (SCARG(uap, tv)) {
711
                error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
712
                        sizeof (atv));
713
                if (error)
714
                        goto done;
715
                if (itimerfix(&atv)) {
716
                        error = EINVAL;
717
                        goto done;
718
                }
719
                s = splclock();
720
                timeradd(&atv, &time, &atv);
721
                timo = hzto(&atv);
722
                /*
723
                 * Avoid inadvertently sleeping forever.
724
                 */
725
                if (timo == 0)
726
                        timo = 1;
727
                splx(s);
728
        } else
729
                timo = 0;
730
retry:
731
        ncoll = nselcoll;
732
        p->p_flag |= P_SELECT;
733
        error = selscan(p, pibits[0], pobits[0], SCARG(uap, nd), retval);
734
        if (error || *retval)
735
                goto done;
736
        s = splhigh();
737
        /* this should be timercmp(&time, &atv, >=) */
738
        if (SCARG(uap, tv) && (time.tv_sec > atv.tv_sec ||
739
            (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) {
740
                splx(s);
741
                goto done;
742
        }
743
        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
744
                splx(s);
745
                goto retry;
746
        }
747
        p->p_flag &= ~P_SELECT;
748
        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
749
        splx(s);
750
        if (error == 0)
751
                goto retry;
752
done:
753
        p->p_flag &= ~P_SELECT;
754
        /* select is not restarted after signals... */
755
        if (error == ERESTART)
756
                error = EINTR;
757
        if (error == EWOULDBLOCK)
758
                error = 0;
759
#define putbits(name, x) \
760
        if (SCARG(uap, name) && (error2 = copyout((caddr_t)pobits[x], \
761
            (caddr_t)SCARG(uap, name), ni))) \
762
                error = error2;
763
        if (error == 0) {
764
                int error2;
765
 
766
                putbits(in, 0);
767
                putbits(ou, 1);
768
                putbits(ex, 2);
769
#undef putbits
770
        }
771
 
772
cleanup:
773
        if (pibits[0] != &bits[0])
774
                free(pibits[0], M_TEMP);
775
        return (error);
776
}
777
 
778
int
779
selscan(p, ibits, obits, nfd, retval)
780
        struct proc *p;
781
        fd_set *ibits, *obits;
782
        int nfd;
783
        register_t *retval;
784
{
785
        caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits;
786
        register struct filedesc *fdp = p->p_fd;
787
        register int msk, i, j, fd;
788
        register fd_mask bits;
789
        struct file *fp;
790
        int ni, n = 0;
791
        static int flag[3] = { FREAD, FWRITE, 0 };
792
 
793
        /*
794
         * if nfd > FD_SETSIZE then the fd_set's contain nfd bits (rounded
795
         * up to the next byte) otherwise the fd_set's are normal sized.
796
         */
797
        ni = sizeof(fd_set);
798
        if (nfd > FD_SETSIZE)
799
                ni = howmany(nfd, NFDBITS) * sizeof(fd_mask);
800
 
801
        for (msk = 0; msk < 3; msk++) {
802
                fd_set *pibits = (fd_set *)&cibits[msk*ni];
803
                fd_set *pobits = (fd_set *)&cobits[msk*ni];
804
 
805
                for (i = 0; i < nfd; i += NFDBITS) {
806
                        bits = pibits->fds_bits[i/NFDBITS];
807
                        while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
808
                                bits &= ~(1 << j);
809
                                fp = fdp->fd_ofiles[fd];
810
                                if (fp == NULL)
811
                                        return (EBADF);
812
                                if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
813
                                        FD_SET(fd, pobits);
814
                                        n++;
815
                                }
816
                        }
817
                }
818
        }
819
        *retval = n;
820
        return (0);
821
}
822
 
823
/*ARGSUSED*/
824
int
825
seltrue(dev, flag, p)
826
        dev_t dev;
827
        int flag;
828
        struct proc *p;
829
{
830
 
831
        return (1);
832
}
833
 
834
/*
835
 * Record a select request.
836
 */
837
void
838
selrecord(selector, sip)
839
        struct proc *selector;
840
        struct selinfo *sip;
841
{
842
        struct proc *p;
843
        pid_t mypid;
844
 
845
        mypid = selector->p_pid;
846
        if (sip->si_selpid == mypid)
847
                return;
848
        if (sip->si_selpid && (p = pfind(sip->si_selpid)) &&
849
            p->p_wchan == (caddr_t)&selwait)
850
                sip->si_flags |= SI_COLL;
851
        else
852
                sip->si_selpid = mypid;
853
}
854
 
855
/*
856
 * Do a wakeup when a selectable event occurs.
857
 */
858
void
859
selwakeup(sip)
860
        register struct selinfo *sip;
861
{
862
        register struct proc *p;
863
        int s;
864
 
865
        if (sip->si_selpid == 0)
866
                return;
867
        if (sip->si_flags & SI_COLL) {
868
                nselcoll++;
869
                sip->si_flags &= ~SI_COLL;
870
                wakeup((caddr_t)&selwait);
871
        }
872
        p = pfind(sip->si_selpid);
873
        sip->si_selpid = 0;
874
        if (p != NULL) {
875
                s = splhigh();
876
                if (p->p_wchan == (caddr_t)&selwait) {
877
                        if (p->p_stat == SSLEEP)
878
                                setrunnable(p);
879
                        else
880
                                unsleep(p);
881
                } else if (p->p_flag & P_SELECT)
882
                        p->p_flag &= ~P_SELECT;
883
                splx(s);
884
        }
885
}
886
 
887
void
888
pollscan(p, pl, nfd, retval)
889
        struct proc *p;
890
        struct pollfd *pl;
891
        int nfd;
892
        register_t *retval;
893
{
894
        register struct filedesc *fdp = p->p_fd;
895
        register int msk, i;
896
        struct file *fp;
897
        int x, n = 0;
898
        static int flag[3] = { FREAD, FWRITE, 0 };
899
        static int pflag[3] = { POLLIN|POLLRDNORM, POLLOUT, POLLERR };
900
 
901
        /*
902
         * XXX: We need to implement the rest of the flags.
903
         */
904
        for (i = 0; i < nfd; i++) {
905
                /* Check the file descriptor. */
906
                if (pl[i].fd < 0)
907
                        continue;
908
                if (pl[i].fd >= fdp->fd_nfiles) {
909
                        pl[i].revents = POLLNVAL;
910
                        n++;
911
                        continue;
912
                }
913
 
914
                fp = fdp->fd_ofiles[pl[i].fd];
915
                if (fp == NULL) {
916
                        pl[i].revents = POLLNVAL;
917
                        n++;
918
                        continue;
919
                }
920
                for (x = msk = 0; msk < 3; msk++) {
921
                        if (pl[i].events & pflag[msk]) {
922
                                if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
923
                                        pl[i].revents |= pflag[msk] &
924
                                            pl[i].events;
925
                                        x++;
926
                                }
927
                        }
928
                }
929
                if (x)
930
                        n++;
931
        }
932
        *retval = n;
933
}
934
 
935
/*
936
 * We are using the same mechanism as select only we encode/decode args
937
 * differently.
938
 */
939
int
940
sys_poll(p, v, retval)
941
        register struct proc *p;
942
        void *v;
943
        register_t *retval;
944
{
945
        struct sys_poll_args *uap = v;
946
        size_t sz;
947
        struct pollfd pfds[4], *pl = pfds;
948
        int msec = SCARG(uap, timeout);
949
        struct timeval atv;
950
        int timo, ncoll, i, s, error, error2;
951
        extern int nselcoll, selwait;
952
 
953
        /* Standards say no more than MAX_OPEN; this is possibly better. */
954
        if (SCARG(uap, nfds) > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur,
955
            maxfiles))
956
                return (EINVAL);
957
 
958
        sz = sizeof(struct pollfd) * SCARG(uap, nfds);
959
 
960
        /* optimize for the default case, of a small nfds value */
961
        if (sz > sizeof(pfds))
962
                pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK);
963
 
964
        if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0)
965
                goto bad;
966
 
967
        for (i = 0; i < SCARG(uap, nfds); i++)
968
                pl[i].revents = 0;
969
 
970
        if (msec != -1) {
971
                atv.tv_sec = msec / 1000;
972
                atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000;
973
 
974
                if (itimerfix(&atv)) {
975
                        error = EINVAL;
976
                        goto done;
977
                }
978
                s = splclock();
979
                timeradd(&atv, &time, &atv);
980
                timo = hzto(&atv);
981
                /*
982
                 * Avoid inadvertently sleeping forever.
983
                 */
984
                if (timo == 0)
985
                        timo = 1;
986
                splx(s);
987
        } else
988
                timo = 0;
989
 
990
retry:
991
        ncoll = nselcoll;
992
        p->p_flag |= P_SELECT;
993
        pollscan(p, pl, SCARG(uap, nfds), retval);
994
        if (*retval)
995
                goto done;
996
        s = splhigh();
997
        if (timo && timercmp(&time, &atv, >=)) {
998
                splx(s);
999
                goto done;
1000
        }
1001
        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
1002
                splx(s);
1003
                goto retry;
1004
        }
1005
        p->p_flag &= ~P_SELECT;
1006
        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo);
1007
        splx(s);
1008
        if (error == 0)
1009
                goto retry;
1010
 
1011
done:
1012
        p->p_flag &= ~P_SELECT;
1013
        /* poll is not restarted after signals... */
1014
        if (error == ERESTART)
1015
                error = EINTR;
1016
        if (error == EWOULDBLOCK)
1017
                error = 0;
1018
        if ((error2 = copyout(pl, SCARG(uap, fds), sz)) != 0)
1019
                error = error2;
1020
bad:
1021
        if (pl != pfds)
1022
                free((char *) pl, M_TEMP);
1023
        return (error);
1024
}
1025
#endif

powered by: WebSVN 2.1.0

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