Numerous miscellaneous features incorporated from Tony Bennett

(tbennett@divnc.com) including the following major additions:

  + variable length messages
  + named devices
  + debug monitor
  + association tables/variables
This commit is contained in:
Joel Sherrill
1995-08-17 19:51:51 +00:00
parent 3b438fa4b0
commit b06e68ef1f
151 changed files with 15476 additions and 1815 deletions

258
c/src/lib/libc/assoc.c Normal file
View File

@@ -0,0 +1,258 @@
/*
* @(#)assoc.c 1.4 - 95/08/02
*
*
* assoc.c
* rtems assoc routines
*
* $Id$
*/
#include <rtems.h>
#include "assoc.h"
#include <stdio.h> /* sprintf */
#include <string.h> /* strcat, strcmp */
#define STREQ(a,b) (strcmp((a), (b)) == 0)
#define rtems_assoc_is_default(ap) ((ap)->name && STREQ(ap->name, RTEMS_ASSOC_DEFAULT_NAME))
rtems_assoc_t *
rtems_assoc_ptr_by_name(
rtems_assoc_t *ap,
char *name
)
{
rtems_assoc_t *default_ap = 0;
if (rtems_assoc_is_default(ap))
default_ap = ap++;
for ( ; ap->name; ap++)
if (strcmp(ap->name, name) == 0)
return ap;
return default_ap;
}
rtems_assoc_t *
rtems_assoc_ptr_by_local(
rtems_assoc_t *ap,
unsigned32 local_value
)
{
rtems_assoc_t *default_ap = 0;
if (rtems_assoc_is_default(ap))
default_ap = ap++;
for ( ; ap->name; ap++)
if (ap->local_value == local_value)
return ap;
return default_ap;
}
rtems_assoc_t *
rtems_assoc_ptr_by_remote(
rtems_assoc_t *ap,
unsigned32 remote_value
)
{
rtems_assoc_t *default_ap = 0;
if (rtems_assoc_is_default(ap))
default_ap = ap++;
for ( ; ap->name; ap++)
if (ap->remote_value == remote_value)
return ap;
return default_ap;
}
/*
* Get values
*/
unsigned32
rtems_assoc_remote_by_local(
rtems_assoc_t *ap,
unsigned32 local_value
)
{
rtems_assoc_t *nap;
nap = rtems_assoc_ptr_by_local(ap, local_value);
if (nap)
return nap->remote_value;
return 0;
}
unsigned32
rtems_assoc_local_by_remote(
rtems_assoc_t *ap,
unsigned32 remote_value
)
{
rtems_assoc_t *nap;
nap = rtems_assoc_ptr_by_remote(ap, remote_value);
if (nap)
return nap->local_value;
return 0;
}
unsigned32
rtems_assoc_remote_by_name(
rtems_assoc_t *ap,
char *name
)
{
rtems_assoc_t *nap;
nap = rtems_assoc_ptr_by_name(ap, name);
if (nap)
return nap->remote_value;
return 0;
}
unsigned32
rtems_assoc_local_by_name(
rtems_assoc_t *ap,
char *name
)
{
rtems_assoc_t *nap;
nap = rtems_assoc_ptr_by_name(ap, name);
if (nap)
return nap->local_value;
return 0;
}
/*
* what to return if a value is not found
* this is not reentrant, but it really shouldn't be invoked anyway
*/
char *
rtems_assoc_name_bad(
unsigned32 bad_value
)
{
static char bad_buffer[32];
sprintf(bad_buffer, "< %d [0x%x] >", bad_value, bad_value);
return bad_buffer;
}
char *
rtems_assoc_name_by_local(
rtems_assoc_t *ap,
unsigned32 local_value
)
{
rtems_assoc_t *nap;
nap = rtems_assoc_ptr_by_local(ap, local_value);
if (nap)
return nap->name;
return rtems_assoc_name_bad(local_value);
}
char *
rtems_assoc_name_by_remote(
rtems_assoc_t *ap,
unsigned32 remote_value
)
{
rtems_assoc_t *nap;
nap = rtems_assoc_ptr_by_remote(ap, remote_value);
if (nap)
return nap->name;
return rtems_assoc_name_bad(remote_value);
}
/*
* Bitfield functions assume just 1 bit set in each of remote and local
* entries; they do not check for this.
*/
unsigned32 rtems_assoc_remote_by_local_bitfield(
rtems_assoc_t *ap,
unsigned32 local_value
)
{
unsigned32 b;
unsigned32 remote_value = 0;
for (b = 1; b; b <<= 1)
if (b & local_value)
remote_value |= rtems_assoc_remote_by_local(ap, b);
return remote_value;
}
unsigned32 rtems_assoc_local_by_remote_bitfield(
rtems_assoc_t *ap,
unsigned32 remote_value
)
{
unsigned32 b;
unsigned32 local_value = 0;
for (b = 1; b; b <<= 1)
if (b & remote_value)
local_value |= rtems_assoc_local_by_remote(ap, b);
return local_value;
}
char *rtems_assoc_name_by_remote_bitfield(
rtems_assoc_t *ap,
unsigned32 value,
char *buffer
)
{
unsigned32 b;
*buffer = 0;
for (b = 1; b; b <<= 1)
if (b & value)
{
if (*buffer)
strcat(buffer, " ");
strcat(buffer, rtems_assoc_name_by_remote(ap, b));
}
return buffer;
}
char *rtems_assoc_name_by_local_bitfield(
rtems_assoc_t *ap,
unsigned32 value,
char *buffer
)
{
unsigned32 b;
*buffer = 0;
for (b = 1; b; b <<= 1)
if (b & value)
{
if (*buffer)
strcat(buffer, " ");
strcat(buffer, rtems_assoc_name_by_local(ap, b));
}
return buffer;
}

44
c/src/lib/libc/assoc.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* @(#)assoc.h 1.2 - 95/06/28
*
*
* Rtems associativity routines. Mainly used to convert a value from
* one space to another (eg: our errno's to host errno's and v.v)
*
*
* $Id$
*/
#ifndef _INCLUDE_ASSOC_H
#define _INCLUDE_ASSOC_H
typedef struct {
char *name;
unsigned32 local_value;
unsigned32 remote_value;
} rtems_assoc_t;
/*
* Flag/marker for optional default value in each table
*/
#define RTEMS_ASSOC_DEFAULT_NAME "(default)"
rtems_assoc_t *rtems_assoc_ptr_by_name(rtems_assoc_t *, char *);
rtems_assoc_t *rtems_assoc_ptr_by_value(rtems_assoc_t *, unsigned32);
rtems_assoc_t *rtems_assoc_ptr_by_remote(rtems_assoc_t *, unsigned32);
unsigned32 rtems_assoc_remote_by_local(rtems_assoc_t *, unsigned32);
unsigned32 rtems_assoc_local_by_remote(rtems_assoc_t *, unsigned32);
unsigned32 rtems_assoc_remote_by_name(rtems_assoc_t *, char *);
unsigned32 rtems_assoc_local_by_name(rtems_assoc_t *, char *);
char *rtems_assoc_name_by_local(rtems_assoc_t *, unsigned32);
char *rtems_assoc_name_by_remote(rtems_assoc_t *, unsigned32);
unsigned32 rtems_assoc_remote_by_local_bitfield(rtems_assoc_t *, unsigned32);
char *rtems_assoc_name_by_local_bitfield(rtems_assoc_t *, unsigned32, char *);
char *rtems_assoc_name_by_remote_bitfield(rtems_assoc_t *, unsigned32, char *);
unsigned32 rtems_assoc_local_by_remote_bitfield(rtems_assoc_t *ap, unsigned32);
#endif /* ! _INCLUDE_ASSOC_H */

212
c/src/lib/libc/error.c Normal file
View File

@@ -0,0 +1,212 @@
/*
* @(#)error.c 1.2 - 95/08/02
*
*
* report errors and panics to RTEMS' stderr.
* Currently just used by RTEMS monitor.
*
*
* $Id$
*/
/*
* These routines provide general purpose error reporting.
* rtems_error reports an error to stderr and allows use of
* printf style formatting. A newline is appended to all messages.
*
* error_flag can be specified as any of the following:
*
* RTEMS_ERROR_ERRNO -- include errno text in output
* RTEMS_ERROR_PANIC -- halts local system after output
* RTEMS_ERROR_ABORT -- abort after output
*
* It can also include a rtems_status value which can be OR'd
* with the above flags. *
*
* EXAMPLE
* #include <rtems.h>
* #include <rtems/error.h>
* rtems_error(0, "stray interrupt %d", intr);
*
* EXAMPLE
* if ((status = rtems_task_create(...)) != RTEMS_SUCCCESSFUL)
* {
* rtems_error(status | RTEMS_ERROR_ABORT,
* "could not create task");
* }
*
* EXAMPLE
* if ((fd = open(pathname, O_RDNLY)) < 0)
* {
* rtems_error(FLOSS_ERROR_ERRNO, "open of '%s' failed", pathname);
* goto failed;
* }
*/
#include <rtems.h>
#include "error.h"
#include "assoc.h"
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* _exit() */
/* bug in hpux <errno.h>: no prototypes unless you are C++ */
#ifdef hpux9
char *strerror(int);
#endif
extern char *rtems_progname;
int rtems_panic_in_progress;
rtems_assoc_t rtems_status_assoc[] = {
{ "successful completion", RTEMS_SUCCESSFUL, },
{ "returned from a thread", RTEMS_TASK_EXITTED, },
{ "multiprocessing not configured", RTEMS_MP_NOT_CONFIGURED, },
{ "invalid object name", RTEMS_INVALID_NAME, },
{ "invalid object id", RTEMS_INVALID_ID, },
{ "too many", RTEMS_TOO_MANY, },
{ "timed out waiting", RTEMS_TIMEOUT, },
{ "object deleted while waiting", RTEMS_OBJECT_WAS_DELETED, },
{ "specified size was invalid", RTEMS_INVALID_SIZE, },
{ "address specified is invalid", RTEMS_INVALID_ADDRESS, },
{ "number was invalid", RTEMS_INVALID_NUMBER, },
{ "item has not been initialized", RTEMS_NOT_DEFINED, },
{ "resources still outstanding", RTEMS_RESOURCE_IN_USE, },
{ "request not satisfied", RTEMS_UNSATISFIED, },
{ "thread is in wrong state", RTEMS_INCORRECT_STATE, },
{ "thread already in state", RTEMS_ALREADY_SUSPENDED, },
{ "illegal on calling thread", RTEMS_ILLEGAL_ON_SELF, },
{ "illegal for remote object", RTEMS_ILLEGAL_ON_REMOTE_OBJECT, },
{ "called from wrong environment", RTEMS_CALLED_FROM_ISR, },
{ "invalid thread priority", RTEMS_INVALID_PRIORITY, },
{ "invalid date/time", RTEMS_INVALID_CLOCK, },
{ "invalid node id", RTEMS_INVALID_NODE, },
{ "directive not configured", RTEMS_NOT_CONFIGURED, },
{ "not owner of resource", RTEMS_NOT_OWNER_OF_RESOURCE , },
{ "directive not implemented", RTEMS_NOT_IMPLEMENTED, },
{ "RTEMS inconsistency detected", RTEMS_INTERNAL_ERROR, },
{ "internal multiprocessing only", RTEMS_PROXY_BLOCKING, },
{ "could not get enough memory", RTEMS_NO_MEMORY, },
{ 0, 0, 0 },
};
char *
rtems_status_text(
rtems_status_code status
)
{
return rtems_assoc_name_by_local(rtems_status_assoc, status);
}
static int rtems_verror(
unsigned32 error_flag,
char *printf_format,
va_list arglist
)
{
int local_errno = 0;
int chars_written = 0;
rtems_status_code status;
if (error_flag & RTEMS_ERROR_PANIC)
{
rtems_panic_in_progress++;
/* disable task switches */
_Thread_Disable_dispatch();
/* don't aggravate things */
if (rtems_panic_in_progress > 2)
return 0;
}
(void) fflush(stdout); /* in case stdout/stderr same */
status = error_flag & ~RTEMS_ERROR_MASK;
if (error_flag & RTEMS_ERROR_ERRNO) /* include errno? */
local_errno = errno;
if (_Configuration_Is_multiprocessing())
fprintf(stderr, "[%d] ", _Configuration_MP_table->node);
if (rtems_progname && *rtems_progname)
chars_written += fprintf(stderr, "%s: ", rtems_progname);
chars_written += vfprintf(stderr, printf_format, arglist);
if (status)
chars_written += fprintf(stderr, " (status: %s)", rtems_status_text(status));
if (local_errno)
if ((local_errno > 0) && *strerror(local_errno))
chars_written += fprintf(stderr, " (errno: %s)", strerror(local_errno));
else
chars_written += fprintf(stderr, " (unknown errno=%d)", local_errno);
chars_written += fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (RTEMS_ERROR_PANIC | RTEMS_ERROR_ABORT))
{
if (error_flag & RTEMS_ERROR_PANIC)
{
rtems_error(0, "fatal error, exiting");
_exit(local_errno);
}
else
{
rtems_error(0, "fatal error, aborting");
abort();
}
}
return chars_written;
}
/*
* Report an error.
* error_flag is as above; printf_format is a normal
* printf(3) format string, with its concommitant arguments.
*
* Returns the number of characters written.
*/
int rtems_error(
int error_flag,
char *printf_format,
...
)
{
va_list arglist;
int chars_written;
va_start(arglist, printf_format);
chars_written = rtems_verror(error_flag, printf_format, arglist);
va_end(arglist);
return chars_written;
}
/*
* rtems_panic is shorthand for rtems_error(RTEMS_ERROR_PANIC, ...)
*/
void rtems_panic(
char *printf_format,
...
)
{
va_list arglist;
va_start(arglist, printf_format);
(void) rtems_verror(RTEMS_ERROR_PANIC, printf_format, arglist);
va_end(arglist);
}

26
c/src/lib/libc/error.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* @(#)error.h 1.1 - 95/08/02
*
*
* Defines and externs for rtems error reporting
*
* $Id$
*/
/*
* rtems_error() and rtems_panic() support
*/
#define RTEMS_ERROR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define RTEMS_ERROR_PANIC (RTEMS_ERROR_ERRNO / 2) /* err fatal; no return */
#define RTEMS_ERROR_ABORT (RTEMS_ERROR_ERRNO / 4) /* err is fatal; panic */
#define RTEMS_ERROR_MASK (RTEMS_ERROR_ERRNO | RTEMS_ERROR_ABORT | \
RTEMS_ERROR_PANIC) /* all */
char *rtems_status_text(rtems_status_code);
int rtems_error(int error_code, char *printf_format, ...);
void rtems_panic(char *printf_format, ...);
extern int rtems_panic_in_progress;

433
c/src/lib/libc/libio.c Normal file
View File

@@ -0,0 +1,433 @@
/*
* @(#)libio.c 1.1 - 95/06/02
*
*
* Provide UNIX/POSIX-like io system calls for RTEMS using the
* RTEMS IO manager
*
* TODO
*
* $Id$
*/
#include <rtems.h>
#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
#include <fcntl.h> /* O_RDONLY, et.al. */
#if defined(solaris2)
#define O_NDELAY O_NONBLOCK
#endif
#include <errno.h>
#include <string.h> /* strcmp */
#include <unistd.h>
#include <stdlib.h> /* calloc() */
#include "libio.h" /* libio.h not pulled in by rtems */
/*
* Semaphore to protect the io table
*/
Objects_Id rtems_libio_semaphore;
#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
unsigned32 rtems_libio_number_iops;
rtems_libio_t *rtems_libio_iops;
rtems_libio_t *rtems_libio_last_iop;
#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
&rtems_libio_iops[fd] : 0)
#define rtems_libio_check_fd(fd) \
do { \
if ((fd) >= rtems_libio_number_iops) \
{ \
errno = EBADF; \
return -1; \
} \
} while (0)
#define rtems_libio_check_buffer(buffer) \
do { \
if ((buffer) == 0) \
{ \
errno = EINVAL; \
return -1; \
} \
} while (0)
#define rtems_libio_check_count(count) \
do { \
if ((count) == 0) \
{ \
return 0; \
} \
} while (0)
#define rtems_libio_check_permissions(iop, flag) \
do { \
if (((iop)->flags & (flag)) == 0) \
{ \
errno = EINVAL; \
return -1; \
} \
} while (0)
void
rtems_libio_config(
rtems_configuration_table *config,
unsigned32 max_fds
)
{
rtems_libio_number_iops = max_fds;
/*
* tweak config to reflect # of semaphores we will need
*/
config->maximum_semaphores += 1; /* one for iop table */
config->maximum_semaphores += max_fds;
}
/*
* Called by bsp startup code to init the libio area.
*/
void
rtems_libio_init(void)
{
rtems_status_code rc;
if (rtems_libio_number_iops > 0)
{
rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
sizeof(rtems_libio_t));
if (rtems_libio_iops == NULL)
rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
}
rc = rtems_semaphore_create(RTEMS_LIBIO_SEM,
1,
RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
&rtems_libio_semaphore);
if (rc != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred(rc);
}
/*
* Convert RTEMS status to a UNIX errno
*/
rtems_assoc_t errno_assoc[] = {
{ "OK", RTEMS_SUCCESSFUL, 0 },
{ "TIMEOUT", RTEMS_TIMEOUT, ETIME },
{ "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM },
{ 0, 0, 0 },
};
static unsigned32
rtems_libio_errno(rtems_status_code code)
{
int rc;
if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
{
errno = rc;
return -1;
}
return 0;
}
/*
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
rtems_assoc_t access_modes_assoc[] = {
{ "READ", LIBIO_FLAGS_READ, O_RDONLY },
{ "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
{ "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
{ 0, 0, 0 },
};
rtems_assoc_t status_flags_assoc[] = {
{ "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
{ "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
{ "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
{ 0, 0, 0 },
};
static unsigned32
rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
{
unsigned32 flags = 0;
unsigned32 access_modes;
/*
* Access mode is a small integer
*/
access_modes = fcntl_flags & O_ACCMODE;
fcntl_flags &= ~O_ACCMODE;
flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
/*
* Everything else is single bits
*/
flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
return flags;
}
static rtems_libio_t *
rtems_libio_allocate(void)
{
rtems_libio_t *iop;
rtems_status_code rc;
rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
{
/*
* Got one; create a semaphore for it
*/
rc = rtems_semaphore_create(RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
&iop->sem);
if (rc != RTEMS_SUCCESSFUL)
goto failed;
iop->flags = LIBIO_FLAGS_OPEN;
goto done;
}
failed:
iop = 0;
done:
rtems_semaphore_release(rtems_libio_semaphore);
return iop;
}
static void
rtems_libio_free(rtems_libio_t *iop)
{
rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
if (iop->sem)
rtems_semaphore_delete(iop->sem);
(void) memset(iop, 0, sizeof(*iop));
rtems_semaphore_release(rtems_libio_semaphore);
}
int
__open(
const char *pathname,
unsigned32 flag,
unsigned32 mode)
{
rtems_status_code rc;
rtems_libio_t *iop = 0;
rtems_driver_name_t *np;
rtems_libio_open_close_args_t args;
if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
goto done;
iop = rtems_libio_allocate();
if (iop == 0)
{
rc = RTEMS_TOO_MANY;
goto done;
}
iop->driver = np;
iop->pathname = (char *) pathname;
iop->flags |= rtems_libio_fcntl_flags(flag);
args.iop = iop;
args.flags = iop->flags;
args.mode = mode;
rc = rtems_io_open(np->major, np->minor, (void *) &args);
done:
if (rc != RTEMS_SUCCESSFUL)
{
if (iop)
rtems_libio_free(iop);
return rtems_libio_errno(rc);
}
return iop - rtems_libio_iops;
}
int
__close(
int fd
)
{
rtems_status_code rc;
rtems_driver_name_t *np;
rtems_libio_t *iop = rtems_libio_iop(fd);
rtems_libio_open_close_args_t args;
rtems_libio_check_fd(fd);
np = iop->driver;
args.iop = iop;
args.flags = 0;
args.mode = 0;
rc = rtems_io_close(np->major, np->minor, (void *) &args);
if (rc != RTEMS_SUCCESSFUL)
return rtems_libio_errno(rc);
return 0;
}
int
__read(
int fd,
void * buffer,
unsigned32 count
)
{
rtems_status_code rc;
rtems_driver_name_t *np;
rtems_libio_t *iop = rtems_libio_iop(fd);
rtems_libio_rw_args_t args;
rtems_libio_check_fd(fd);
rtems_libio_check_buffer(buffer);
rtems_libio_check_count(count);
rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
np = iop->driver;
args.iop = iop;
args.offset = iop->offset;
args.buffer = buffer;
args.count = count;
args.flags = iop->flags;
args.bytes_moved = 0;
rc = rtems_io_read(np->major, np->minor, (void *) &args);
iop->offset += args.bytes_moved;
if (rc != RTEMS_SUCCESSFUL)
return rtems_libio_errno(rc);
return args.bytes_moved;
}
int
__write(
int fd,
const void *buffer,
unsigned32 count
)
{
rtems_status_code rc;
rtems_driver_name_t *np;
rtems_libio_t *iop = rtems_libio_iop(fd);
rtems_libio_rw_args_t args;
rtems_libio_check_fd(fd);
rtems_libio_check_buffer(buffer);
rtems_libio_check_count(count);
rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
np = iop->driver;
args.iop = iop;
args.offset = iop->offset;
args.buffer = (void *) buffer;
args.count = count;
args.flags = iop->flags;
args.bytes_moved = 0;
rc = rtems_io_write(np->major, np->minor, (void *) &args);
iop->offset += args.bytes_moved;
if (rc != RTEMS_SUCCESSFUL)
return rtems_libio_errno(rc);
return args.bytes_moved;
}
int
__ioctl(
int fd,
unsigned32 command,
void * buffer)
{
rtems_status_code rc;
rtems_driver_name_t *np;
rtems_libio_t *iop = rtems_libio_iop(fd);
rtems_libio_ioctl_args_t args;
rtems_libio_check_fd(fd);
np = iop->driver;
args.iop = iop;
args.command = command;
args.buffer = buffer;
rc = rtems_io_control(np->major, np->minor, (void *) &args);
if (rc != RTEMS_SUCCESSFUL)
return rtems_libio_errno(rc);
return args.ioctl_return;
}
/*
* internal only??
*/
int
__lseek(
int fd,
rtems_libio_offset_t offset,
int whence
)
{
rtems_libio_t *iop = rtems_libio_iop(fd);
rtems_libio_check_fd(fd);
switch (whence)
{
case SEEK_SET:
iop->offset = offset;
break;
case SEEK_CUR:
iop->offset += offset;
break;
case SEEK_END:
iop->offset = iop->size - offset;
break;
default:
errno = EINVAL;
return -1;
}
return 0;
}

101
c/src/lib/libc/libio.h Normal file
View File

@@ -0,0 +1,101 @@
/*
* @(#)libio.h 1.1 - 95/06/02
*
*
* General purpose communication channel for RTEMS to allow UNIX/POSIX
* system call behavior on top of RTEMS IO devices.
*
* TODO
* stat(2)
* unlink(2)
* rename(2)
*
* $Id$
*/
#ifndef _RTEMS_LIBIO_H
#define _RTEMS_LIBIO_H
typedef unsigned32 rtems_libio_offset_t;
/*
* An open file data structure, indexed by 'fd'
* TODO:
* should really have a separate per/file data structure that this
* points to (eg: size, offset, driver, pathname should be in that)
*/
typedef struct {
rtems_driver_name_t *driver;
rtems_libio_offset_t size; /* size of file */
rtems_libio_offset_t offset; /* current offset into the file */
unsigned32 flags;
char *pathname; /* opened pathname */
Objects_Id sem;
unsigned32 data0; /* private to "driver" */
unsigned32 data1; /* ... */
} rtems_libio_t;
/*
* param block for read/write
* Note: it must include 'offset' instead of using iop's offset since
* we can have multiple outstanding i/o's on a device.
*/
typedef struct {
rtems_libio_t *iop;
rtems_libio_offset_t offset;
unsigned8 *buffer;
unsigned32 count;
unsigned32 flags;
unsigned32 bytes_moved;
} rtems_libio_rw_args_t;
/*
* param block for open/close
*/
typedef struct {
rtems_libio_t *iop;
unsigned32 flags;
unsigned32 mode;
} rtems_libio_open_close_args_t;
/*
* param block for ioctl
*/
typedef struct {
rtems_libio_t *iop;
unsigned32 command;
void *buffer;
unsigned32 ioctl_return;
} rtems_libio_ioctl_args_t;
/*
* Values for 'flag'
*/
#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
#define LIBIO_FLAGS_READ 0x0002 /* reading */
#define LIBIO_FLAGS_WRITE 0x0004 /* writing */
#define LIBIO_FLAGS_LINE_BUFFERED 0x0008 /* line buffered io (^h, ^u, etc) */
#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
void rtems_libio_config(rtems_configuration_table *config, unsigned32 max_fds);
void rtems_libio_init(void);
int __open(const char *pathname, unsigned32 flag, unsigned32 mode);
int __close(int fd);
int __read(int fd, void *buffer, unsigned32 count);
int __write(int fd, const void *buffer, unsigned32 count);
int __ioctl(int fd, unsigned32 command, void *buffer);
int __lseek(int fd, rtems_libio_offset_t offset, int whence);
#endif /* _RTEMS_LIBIO_H */

View File

@@ -35,27 +35,6 @@ __isatty(int _fd)
return 1;
}
int
__close(int _fd)
{
/* return value usually ignored anyhow */
return 0;
}
int
__open(const char *filename)
{
/* always fail */
return -1;
}
int
__lseek(int _fd, off_t offset, int whence)
{
/* nothing is ever seekable */
return -1;
}
int stat( const char *path, struct stat *buf )
{
/* always fail */