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

4.104.114.84.95
Last change on this file since b06e68ef was b06e68ef, checked in by Joel Sherrill <joel.sherrill@…>, on 08/17/95 at 19:51:51

Numerous miscellaneous features incorporated from Tony Bennett
(tbennett@…) including the following major additions:

+ variable length messages
+ named devices
+ debug monitor
+ association tables/variables

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 *      @(#)libio.c     1.1 - 95/06/02
3 *     
4 *
5 * Provide UNIX/POSIX-like io system calls for RTEMS using the
6 *  RTEMS IO manager
7 *
8 * TODO
9 *
10 *  $Id$
11 */
12
13#include <rtems.h>
14#include <rtems/assoc.h>                /* assoc.h not included by rtems.h */
15
16#include <fcntl.h>                      /* O_RDONLY, et.al. */
17#if defined(solaris2)
18#define O_NDELAY O_NONBLOCK
19#endif
20#include <errno.h>
21#include <string.h>                     /* strcmp */
22#include <unistd.h>
23#include <stdlib.h>                     /* calloc() */
24
25#include "libio.h"                      /* libio.h not pulled in by rtems */
26
27/*
28 * Semaphore to protect the io table
29 */
30
31Objects_Id rtems_libio_semaphore;
32
33#define RTEMS_LIBIO_SEM         rtems_build_name('L', 'B', 'I', 'O')
34#define RTEMS_LIBIO_IOP_SEM(n)  rtems_build_name('L', 'B', 'I', n)
35
36unsigned32     rtems_libio_number_iops;
37rtems_libio_t *rtems_libio_iops;
38rtems_libio_t *rtems_libio_last_iop;
39
40#define rtems_libio_iop(fd)    ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
41                                       &rtems_libio_iops[fd] : 0)
42
43#define rtems_libio_check_fd(fd) \
44    do { \
45        if ((fd) >= rtems_libio_number_iops) \
46        { \
47            errno = EBADF; \
48            return -1; \
49        } \
50    } while (0)
51
52#define rtems_libio_check_buffer(buffer) \
53    do { \
54        if ((buffer) == 0) \
55        { \
56            errno = EINVAL; \
57            return -1; \
58        } \
59    } while (0)
60
61#define rtems_libio_check_count(count) \
62    do { \
63        if ((count) == 0) \
64        { \
65            return 0; \
66        } \
67    } while (0)
68
69#define rtems_libio_check_permissions(iop, flag) \
70    do { \
71        if (((iop)->flags & (flag)) == 0) \
72        { \
73              errno = EINVAL; \
74              return -1; \
75        } \
76    } while (0)
77
78
79void
80rtems_libio_config(
81    rtems_configuration_table *config,
82    unsigned32                 max_fds
83  )
84{
85    rtems_libio_number_iops = max_fds;
86
87    /*
88     * tweak config to reflect # of semaphores we will need
89     */
90
91    config->maximum_semaphores += 1;            /* one for iop table */
92    config->maximum_semaphores += max_fds;
93}
94
95/*
96 * Called by bsp startup code to init the libio area.
97 */
98
99void
100rtems_libio_init(void)
101{
102    rtems_status_code rc;
103
104    if (rtems_libio_number_iops > 0)
105    {
106        rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
107                                                    sizeof(rtems_libio_t));
108        if (rtems_libio_iops == NULL)
109            rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
110
111        rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
112    }
113
114    rc = rtems_semaphore_create(RTEMS_LIBIO_SEM,
115                                1,
116                                RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
117                                &rtems_libio_semaphore);
118    if (rc != RTEMS_SUCCESSFUL)
119        rtems_fatal_error_occurred(rc);
120}
121
122/*
123 * Convert RTEMS status to a UNIX errno
124 */
125
126rtems_assoc_t errno_assoc[] = {
127    { "OK",        RTEMS_SUCCESSFUL,       0 },
128    { "TIMEOUT",   RTEMS_TIMEOUT,          ETIME },
129    { "NO MEMORY", RTEMS_NO_MEMORY,        ENOMEM },
130    { 0, 0, 0 },
131};
132
133static unsigned32
134rtems_libio_errno(rtems_status_code code)
135{
136    int rc;
137   
138    if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
139    {
140        errno = rc;
141        return -1;
142    }
143    return 0;
144}
145
146/*
147 * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
148 */
149
150rtems_assoc_t access_modes_assoc[] = {
151    { "READ",     LIBIO_FLAGS_READ,  O_RDONLY },
152    { "WRITE",    LIBIO_FLAGS_WRITE, O_WRONLY },
153    { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
154    { 0, 0, 0 },
155};
156
157rtems_assoc_t status_flags_assoc[] = {
158    { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
159    { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
160    { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
161    { 0, 0, 0 },
162};
163
164static unsigned32
165rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
166{
167    unsigned32 flags = 0;
168    unsigned32 access_modes;
169
170    /*
171     * Access mode is a small integer
172     */
173   
174    access_modes = fcntl_flags & O_ACCMODE;
175    fcntl_flags &= ~O_ACCMODE;
176    flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
177
178    /*
179     * Everything else is single bits
180     */
181
182    flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
183    return flags;
184}
185
186
187static rtems_libio_t *
188rtems_libio_allocate(void)
189{
190    rtems_libio_t *iop;
191    rtems_status_code rc;
192   
193    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
194
195    for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
196        if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
197        {
198            /*
199             * Got one; create a semaphore for it
200             */
201
202            rc = rtems_semaphore_create(RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
203                                        1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
204                                        &iop->sem);
205            if (rc != RTEMS_SUCCESSFUL)
206                goto failed;
207           
208            iop->flags = LIBIO_FLAGS_OPEN;
209            goto done;
210        }
211   
212failed:
213    iop = 0;
214   
215done:
216    rtems_semaphore_release(rtems_libio_semaphore);
217    return iop;
218}
219
220static void
221rtems_libio_free(rtems_libio_t *iop)
222{
223    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
224
225    if (iop->sem)
226        rtems_semaphore_delete(iop->sem);
227    (void) memset(iop, 0, sizeof(*iop));
228
229    rtems_semaphore_release(rtems_libio_semaphore);
230}
231
232int
233__open(
234    const char   *pathname,
235    unsigned32    flag,
236    unsigned32    mode)
237{
238    rtems_status_code rc;
239    rtems_libio_t *iop = 0;
240    rtems_driver_name_t *np;
241    rtems_libio_open_close_args_t args;
242
243    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
244        goto done;
245
246    iop = rtems_libio_allocate();
247    if (iop == 0)
248    {
249        rc = RTEMS_TOO_MANY;
250        goto done;
251    }
252   
253    iop->driver = np;
254    iop->pathname = (char *) pathname;
255    iop->flags |= rtems_libio_fcntl_flags(flag);
256
257    args.iop = iop;
258    args.flags = iop->flags;
259    args.mode = mode;
260
261    rc = rtems_io_open(np->major, np->minor, (void *) &args);
262   
263done:
264    if (rc != RTEMS_SUCCESSFUL)
265    {
266        if (iop)
267            rtems_libio_free(iop);
268        return rtems_libio_errno(rc);
269    }
270   
271    return iop - rtems_libio_iops;
272}
273   
274int
275__close(
276    int  fd
277  )   
278{
279    rtems_status_code rc;
280    rtems_driver_name_t *np;
281    rtems_libio_t *iop = rtems_libio_iop(fd);
282    rtems_libio_open_close_args_t args;
283
284    rtems_libio_check_fd(fd);
285
286    np = iop->driver;
287
288    args.iop = iop;
289    args.flags = 0;
290    args.mode = 0;
291   
292    rc = rtems_io_close(np->major, np->minor, (void *) &args);
293
294    if (rc != RTEMS_SUCCESSFUL)
295        return rtems_libio_errno(rc);
296    return 0;
297}
298   
299int
300__read(
301    int       fd,
302    void *    buffer,
303    unsigned32 count
304  )
305{
306    rtems_status_code rc;
307    rtems_driver_name_t *np;
308    rtems_libio_t *iop = rtems_libio_iop(fd);
309    rtems_libio_rw_args_t args;
310
311    rtems_libio_check_fd(fd);
312    rtems_libio_check_buffer(buffer);
313    rtems_libio_check_count(count);
314    rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
315
316    np = iop->driver;
317
318    args.iop = iop;
319    args.offset = iop->offset;
320    args.buffer = buffer;
321    args.count = count;
322    args.flags = iop->flags;
323    args.bytes_moved = 0;
324
325    rc = rtems_io_read(np->major, np->minor, (void *) &args);
326
327    iop->offset += args.bytes_moved;
328
329    if (rc != RTEMS_SUCCESSFUL)
330        return rtems_libio_errno(rc);
331
332    return args.bytes_moved;
333}
334
335int
336__write(
337    int         fd,
338    const void *buffer,
339    unsigned32  count
340  )
341{
342    rtems_status_code rc;
343    rtems_driver_name_t *np;
344    rtems_libio_t *iop = rtems_libio_iop(fd);
345    rtems_libio_rw_args_t args;
346
347    rtems_libio_check_fd(fd);
348    rtems_libio_check_buffer(buffer);
349    rtems_libio_check_count(count);
350    rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
351
352    np = iop->driver;
353
354    args.iop = iop;
355    args.offset = iop->offset;
356    args.buffer = (void *) buffer;
357    args.count = count;
358    args.flags = iop->flags;
359    args.bytes_moved = 0;
360
361    rc = rtems_io_write(np->major, np->minor, (void *) &args);
362
363    iop->offset += args.bytes_moved;
364
365    if (rc != RTEMS_SUCCESSFUL)
366        return rtems_libio_errno(rc);
367
368    return args.bytes_moved;
369}
370
371int
372__ioctl(
373    int         fd,
374    unsigned32  command,
375    void *      buffer)
376{
377    rtems_status_code rc;
378    rtems_driver_name_t *np;
379    rtems_libio_t *iop = rtems_libio_iop(fd);
380    rtems_libio_ioctl_args_t args;
381
382    rtems_libio_check_fd(fd);
383
384    np = iop->driver;
385
386    args.iop = iop;
387    args.command = command;
388    args.buffer = buffer;
389
390    rc = rtems_io_control(np->major, np->minor, (void *) &args);
391
392    if (rc != RTEMS_SUCCESSFUL)
393        return rtems_libio_errno(rc);
394
395    return args.ioctl_return;
396}
397   
398/*
399 * internal only??
400 */
401
402
403int
404__lseek(
405    int                  fd,
406    rtems_libio_offset_t offset,
407    int                  whence
408  )   
409{
410    rtems_libio_t *iop = rtems_libio_iop(fd);
411
412    rtems_libio_check_fd(fd);
413
414    switch (whence)
415    {
416        case SEEK_SET:
417            iop->offset = offset;
418            break;
419
420        case SEEK_CUR:
421            iop->offset += offset;
422            break;
423
424        case SEEK_END:
425            iop->offset = iop->size - offset;
426            break;
427
428        default:
429            errno = EINVAL;
430            return -1;
431    }
432    return 0;
433}
Note: See TracBrowser for help on using the repository browser.