source: rtems/c/src/exec/libcsupport/src/libio.c @ e2d79559

4.104.114.84.95
Last change on this file since e2d79559 was e2d79559, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 9, 1997 at 2:05:50 PM

Added ka9q tcpip stack and network driver for the gen68360. This effort
was done based on the 3.6.0 release and had to be autoconf'ed locally.
It is turned on is the bsp enables it and it is not explicitly disabled
via the configure option --disable-tcpip. As many warnings as possible
were removed locally after the code was merged. Only the gen68360
and mvme136 bsps were compiled this way.

The ka9q port and network driver were submitted by Eric Norum
(eric@…).

The network demo programs are not included in the tree at this point.

  • Property mode set to 100644
File size: 11.9 KB
Line 
1/*
2 *  Provide UNIX/POSIX-like io system calls for RTEMS using the
3 *  RTEMS IO manager
4 *
5 *  $Id$
6 */
7
8#include <rtems.h>
9#include <rtems/assoc.h>                /* assoc.h not included by rtems.h */
10
11#include <stdio.h>                      /* O_RDONLY, et.al. */
12#include <fcntl.h>                      /* O_RDONLY, et.al. */
13#include <assert.h>
14
15#if ! defined(O_NDELAY)
16# if defined(solaris2)
17#  define O_NDELAY O_NONBLOCK
18# elif defined(RTEMS_NEWLIB)
19#  define O_NDELAY _FNBIO
20# endif
21#endif
22
23
24#include <errno.h>
25#include <string.h>                     /* strcmp */
26#include <unistd.h>
27#include <stdlib.h>                     /* calloc() */
28
29#include "libio.h"                      /* libio.h not pulled in by rtems */
30
31/*
32 * Semaphore to protect the io table
33 */
34
35Objects_Id rtems_libio_semaphore;
36
37#define RTEMS_LIBIO_SEM         rtems_build_name('L', 'B', 'I', 'O')
38#define RTEMS_LIBIO_IOP_SEM(n)  rtems_build_name('L', 'B', 'I', n)
39
40unsigned32     rtems_libio_number_iops;
41rtems_libio_t *rtems_libio_iops;
42rtems_libio_t *rtems_libio_last_iop;
43
44#define rtems_libio_iop(fd)    ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
45                                       &rtems_libio_iops[fd] : 0)
46
47#define rtems_libio_check_fd(fd) \
48    do { \
49        if ((unsigned32) (fd) >= rtems_libio_number_iops) \
50        { \
51            errno = EBADF; \
52            return -1; \
53        } \
54    } while (0)
55
56#define rtems_libio_check_buffer(buffer) \
57    do { \
58        if ((buffer) == 0) \
59        { \
60            errno = EINVAL; \
61            return -1; \
62        } \
63    } while (0)
64
65#define rtems_libio_check_count(count) \
66    do { \
67        if ((count) == 0) \
68        { \
69            return 0; \
70        } \
71    } while (0)
72
73#define rtems_libio_check_permissions(iop, flag) \
74    do { \
75        if (((iop)->flags & (flag)) == 0) \
76        { \
77              errno = EINVAL; \
78              return -1; \
79        } \
80    } while (0)
81
82/*
83 * External I/O handlers
84 *
85 * Space for all possible handlers is preallocated
86 * to speed up dispatch to external handlers.
87 */
88
89static rtems_libio_handler_t handlers[15];
90
91void
92rtems_register_libio_handler(
93    int                         handler_flag,
94    const rtems_libio_handler_t *handler
95)
96{
97  int handler_index = rtems_file_descriptor_type_index(handler_flag);
98
99  if ((handler_index < 0) || (handler_index >= 15))
100    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
101  handlers[handler_index] = *handler;
102}
103
104
105void
106rtems_libio_config(
107    rtems_configuration_table *config,
108    unsigned32                 max_fds
109)
110{
111    rtems_libio_number_iops = max_fds;
112
113    /*
114     * tweak config to reflect # of semaphores we will need
115     */
116
117    /* one for iop table */
118    config->RTEMS_api_configuration->maximum_semaphores += 1; 
119    config->RTEMS_api_configuration->maximum_semaphores += max_fds;
120}
121
122/*
123 * Called by bsp startup code to init the libio area.
124 */
125
126void
127rtems_libio_init(void)
128{
129    rtems_status_code rc;
130
131    if (rtems_libio_number_iops > 0)
132    {
133        rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
134                                                    sizeof(rtems_libio_t));
135        if (rtems_libio_iops == NULL)
136            rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
137
138        rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
139    }
140
141    rc = rtems_semaphore_create(
142      RTEMS_LIBIO_SEM,
143      1,
144      RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
145      RTEMS_NO_PRIORITY,
146      &rtems_libio_semaphore
147    );
148    if (rc != RTEMS_SUCCESSFUL)
149        rtems_fatal_error_occurred(rc);
150}
151
152/*
153 * Convert RTEMS status to a UNIX errno
154 */
155
156rtems_assoc_t errno_assoc[] = {
157    { "OK",        RTEMS_SUCCESSFUL,       0 },
158    { "TIMEOUT",   RTEMS_TIMEOUT,          ETIME },
159    { "NO MEMORY", RTEMS_NO_MEMORY,        ENOMEM },
160    { "NO DEVICE", RTEMS_UNSATISFIED,      ENOSYS },
161    { 0, 0, 0 },
162};
163
164static unsigned32
165rtems_libio_errno(rtems_status_code code)
166{
167    int rc;
168   
169    if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
170    {
171        errno = rc;
172        return -1;
173    }
174    return 0;
175}
176
177/*
178 * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
179 */
180
181rtems_assoc_t access_modes_assoc[] = {
182    { "READ",     LIBIO_FLAGS_READ,  O_RDONLY },
183    { "WRITE",    LIBIO_FLAGS_WRITE, O_WRONLY },
184    { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
185    { 0, 0, 0 },
186};
187
188rtems_assoc_t status_flags_assoc[] = {
189    { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
190    { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
191    { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
192    { 0, 0, 0 },
193};
194
195static unsigned32
196rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
197{
198    unsigned32 flags = 0;
199    unsigned32 access_modes;
200
201    /*
202     * Access mode is a small integer
203     */
204   
205    access_modes = fcntl_flags & O_ACCMODE;
206    fcntl_flags &= ~O_ACCMODE;
207    flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
208
209    /*
210     * Everything else is single bits
211     */
212
213    flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
214    return flags;
215}
216
217
218static rtems_libio_t *
219rtems_libio_allocate(void)
220{
221    rtems_libio_t *iop;
222    rtems_status_code rc;
223   
224    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
225
226    for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
227        if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
228        {
229            /*
230             * Got one; create a semaphore for it
231             */
232
233            rc = rtems_semaphore_create(
234              RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
235              1,
236              RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
237              RTEMS_NO_PRIORITY,
238              &iop->sem
239            );
240            if (rc != RTEMS_SUCCESSFUL)
241                goto failed;
242           
243            iop->flags = LIBIO_FLAGS_OPEN;
244            goto done;
245        }
246   
247failed:
248    iop = 0;
249   
250done:
251    rtems_semaphore_release(rtems_libio_semaphore);
252    return iop;
253}
254
255static void
256rtems_libio_free(rtems_libio_t *iop)
257{
258    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
259
260    if (iop->sem)
261        rtems_semaphore_delete(iop->sem);
262    (void) memset(iop, 0, sizeof(*iop));
263
264    rtems_semaphore_release(rtems_libio_semaphore);
265}
266
267int
268__rtems_open(
269    const char   *pathname,
270    unsigned32    flag,
271    unsigned32    mode)
272{
273    rtems_status_code rc;
274    rtems_libio_t *iop = 0;
275    rtems_driver_name_t *np;
276    rtems_libio_open_close_args_t args;
277
278    /*
279     * Additional external I/O handlers would be supported by
280     * adding code to pick apart the pathname appropriately.
281     * The networking code does not require changes here since
282     * network file descriptors are obtained using socket(), not
283     * open().
284     */
285
286    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
287        goto done;
288
289    iop = rtems_libio_allocate();
290    if (iop == 0)
291    {
292        rc = RTEMS_TOO_MANY;
293        goto done;
294    }
295   
296    iop->driver = np;
297    iop->pathname = (char *) pathname;
298    iop->flags |= rtems_libio_fcntl_flags(flag);
299
300    args.iop = iop;
301    args.flags = iop->flags;
302    args.mode = mode;
303
304    rc = rtems_io_open(np->major, np->minor, (void *) &args);
305   
306done:
307 
308    if (rc != RTEMS_SUCCESSFUL)
309    {
310        if (iop)
311            rtems_libio_free(iop);
312        return rtems_libio_errno(rc);
313    }
314   
315    return iop - rtems_libio_iops;
316}
317   
318int
319__rtems_close(
320    int  fd
321  )   
322{
323    rtems_status_code rc;
324    rtems_driver_name_t *np;
325    rtems_libio_t *iop;
326    rtems_libio_open_close_args_t args;
327
328    if (rtems_file_descriptor_type(fd)) {
329        int (*fp)(int fd);
330
331        fp = handlers[rtems_file_descriptor_type_index(fd)].close;
332        if (fp == NULL) {
333            errno = EBADF;
334            return -1;
335        }
336        return (*fp)(fd);
337    }
338    iop = rtems_libio_iop(fd);
339    rtems_libio_check_fd(fd);
340
341    np = iop->driver;
342
343    args.iop = iop;
344    args.flags = 0;
345    args.mode = 0;
346   
347    rc = rtems_io_close(np->major, np->minor, (void *) &args);
348
349    if (rc != RTEMS_SUCCESSFUL)
350        return rtems_libio_errno(rc);
351    return 0;
352}
353   
354int
355__rtems_read(
356    int       fd,
357    void *    buffer,
358    unsigned32 count
359  )
360{
361    rtems_status_code rc;
362    rtems_driver_name_t *np;
363    rtems_libio_t *iop;
364    rtems_libio_rw_args_t args;
365
366    if (rtems_file_descriptor_type(fd)) {
367        int (*fp)(int fd, void *buffer, unsigned32 count);
368
369        fp = handlers[rtems_file_descriptor_type_index(fd)].read;
370        if (fp == NULL) {
371            errno = EBADF;
372            return -1;
373        }
374        return (*fp)(fd, buffer, count);
375    }
376    iop = rtems_libio_iop(fd);
377    rtems_libio_check_fd(fd);
378    rtems_libio_check_buffer(buffer);
379    rtems_libio_check_count(count);
380    rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
381
382    np = iop->driver;
383
384    args.iop = iop;
385    args.offset = iop->offset;
386    args.buffer = buffer;
387    args.count = count;
388    args.flags = iop->flags;
389    args.bytes_moved = 0;
390
391    rc = rtems_io_read(np->major, np->minor, (void *) &args);
392
393    iop->offset += args.bytes_moved;
394
395    if (rc != RTEMS_SUCCESSFUL)
396        return rtems_libio_errno(rc);
397
398    return args.bytes_moved;
399}
400
401int
402__rtems_write(
403    int         fd,
404    const void *buffer,
405    unsigned32  count
406  )
407{
408    rtems_status_code rc;
409    rtems_driver_name_t *np;
410    rtems_libio_t *iop;
411    rtems_libio_rw_args_t args;
412
413    if (rtems_file_descriptor_type(fd)) {
414        int (*fp)(int fd, const void *buffer, unsigned32 count);
415
416        fp = handlers[rtems_file_descriptor_type_index(fd)].write;
417        if (fp == NULL) {
418            errno = EBADF;
419            return -1;
420        }
421        return (*fp)(fd, buffer, count);
422    }
423    iop = rtems_libio_iop(fd);
424    rtems_libio_check_fd(fd);
425    rtems_libio_check_buffer(buffer);
426    rtems_libio_check_count(count);
427    rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
428
429    np = iop->driver;
430
431    args.iop = iop;
432    args.offset = iop->offset;
433    args.buffer = (void *) buffer;
434    args.count = count;
435    args.flags = iop->flags;
436    args.bytes_moved = 0;
437
438    rc = rtems_io_write(np->major, np->minor, (void *) &args);
439
440    iop->offset += args.bytes_moved;
441
442    if (rc != RTEMS_SUCCESSFUL)
443        return rtems_libio_errno(rc);
444
445    return args.bytes_moved;
446}
447
448int
449__rtems_ioctl(
450    int         fd,
451    unsigned32  command,
452    void *      buffer)
453{
454    rtems_status_code rc;
455    rtems_driver_name_t *np;
456    rtems_libio_t *iop;
457    rtems_libio_ioctl_args_t args;
458
459    if (rtems_file_descriptor_type(fd)) {
460        int (*fp)(int fd, unsigned32 command, void *buffer);
461
462        fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
463        if (fp == NULL) {
464            errno = EBADF;
465            return -1;
466        }
467        return (*fp)(fd, command, buffer);
468    }
469    iop = rtems_libio_iop(fd);
470    rtems_libio_check_fd(fd);
471
472    np = iop->driver;
473
474    args.iop = iop;
475    args.command = command;
476    args.buffer = buffer;
477
478    rc = rtems_io_control(np->major, np->minor, (void *) &args);
479
480    if (rc != RTEMS_SUCCESSFUL)
481        return rtems_libio_errno(rc);
482
483    return args.ioctl_return;
484}
485   
486/*
487 * internal only??
488 */
489
490
491int
492__rtems_lseek(
493    int                  fd,
494    rtems_libio_offset_t offset,
495    int                  whence
496  )   
497{
498    rtems_libio_t *iop;
499
500    if (rtems_file_descriptor_type(fd)) {
501        int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
502
503        fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
504        if (fp == NULL) {
505            errno = EBADF;
506            return -1;
507        }
508        return (*fp)(fd, offset, whence);
509    }
510    iop = rtems_libio_iop(fd);
511    rtems_libio_check_fd(fd);
512
513    switch (whence)
514    {
515        case SEEK_SET:
516            iop->offset = offset;
517            break;
518
519        case SEEK_CUR:
520            iop->offset += offset;
521            break;
522
523        case SEEK_END:
524            iop->offset = iop->size - offset;
525            break;
526
527        default:
528            errno = EINVAL;
529            return -1;
530    }
531    return 0;
532}
Note: See TracBrowser for help on using the repository browser.