source: rtems/cpukit/libcsupport/src/libio.c @ 3a4ae6c

4.104.114.84.95
Last change on this file since 3a4ae6c was 3a4ae6c, checked in by Joel Sherrill <joel.sherrill@…>, on 09/11/95 at 19:35:39

The word "RTEMS" almost completely removed from the core.

Configuration Table Template file added and all tests
modified to use this. All gvar.h and conftbl.h files
removed from test directories.

Configuration parameter maximum_devices added.

Core semaphore and mutex handlers added and RTEMS API Semaphore
Manager updated to reflect this.

Initialization sequence changed to invoke API specific initialization
routines. Initialization tasks table now owned by RTEMS Tasks Manager.

Added user extension for post-switch.

Utilized user extensions to implement API specific functionality
like signal dispatching.

Added extensions to the System Initialization Thread so that an
API can register a function to be invoked while the system
is being initialized. These are largely equivalent to the
pre-driver and post-driver hooks.

Added the Modules file oar-go32_p5, modified oar-go32, and modified
the file make/custom/go32.cfg to look at an environment varable which
determines what CPU model is being used.

All BSPs updated to reflect named devices and clock driver's IOCTL
used by the Shared Memory Driver. Also merged clock isr into
main file and removed ckisr.c where possible.

Updated spsize to reflect new and moved variables.

Makefiles for the executive source and include files updated to show
break down of files into Core, RTEMS API, and Neither.

Header and inline files installed into subdirectory based on whether
logically in the Core or a part of the RTEMS API.

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