summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libnetworking/rtems
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libnetworking/rtems')
-rw-r--r--c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h16
-rw-r--r--c/src/lib/libnetworking/rtems/rtems_select.c171
-rw-r--r--c/src/lib/libnetworking/rtems/sghostname.c4
3 files changed, 188 insertions, 3 deletions
diff --git a/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h b/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h
index 453fb23c66..5d355f4a36 100644
--- a/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h
+++ b/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h
@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
/*
* Some extra prototypes
*/
-int sethostname (char *name, int namelen);
+int sethostname (char *name, size_t namelen);
void domaininit (void *);
void ifinit (void *);
void ipintr (void);
@@ -174,5 +174,19 @@ void arpintr (void);
void bootpc_init(void);
int socket (int, int, int);
int ioctl (int, unsigned long, ...);
+struct socket *rtems_bsdnet_fdToSocket (int fd);
+int rtems_bsdnet_makeFdForSocket (struct socket *);
+
+/*
+ * Events used by networking routines.
+ * Everything will break if the application
+ * tries to use these events or if the `sleep'
+ * events are equal to any of the NETISR * events.
+ */
+#define SBWAIT_EVENT RTEMS_EVENT_24
+#define SOSLEEP_EVENT RTEMS_EVENT_25
+#define NETISR_IP_EVENT (1 << NETISR_IP)
+#define NETISR_ARP_EVENT (1 << NETISR_ARP)
+#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
diff --git a/c/src/lib/libnetworking/rtems/rtems_select.c b/c/src/lib/libnetworking/rtems/rtems_select.c
new file mode 100644
index 0000000000..2487edf9fc
--- /dev/null
+++ b/c/src/lib/libnetworking/rtems/rtems_select.c
@@ -0,0 +1,171 @@
+/*
+ * $Id$
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/proc.h>
+#include <sys/filio.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+/*
+ *********************************************************************
+ * RTEMS implementation of select() system call *
+ *********************************************************************
+ */
+
+/*
+ * This implementation is quite restricted:
+ * Works on sockets only -- no support for other devices!
+ * A given socket can be in a read-select or a read/recv* by only
+ * one task at a time.
+ * A given socket can be in a write-select or a write/send* by only
+ * one task at a time.
+ *
+ * NOTE - select() is a very expensive system call. It should be avoided
+ * if at all possible. In many cases, rewriting the application
+ * to use multiple tasks (one per socket) is a better solution.
+ */
+
+static __inline int imin(int a, int b) { return (a < b ? a : b); }
+
+static int
+socket_select (struct socket *so, int which, rtems_id tid)
+{
+ switch (which) {
+
+ case FREAD:
+ if (soreadable(so))
+ return (1);
+ so->so_rcv.sb_sel.si_pid = tid;
+ break;
+
+ case FWRITE:
+ if (sowriteable(so))
+ return (1);
+ so->so_snd.sb_sel.si_pid = tid;
+ break;
+
+ case 0:
+ if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
+ return (1);
+ so->so_rcv.sb_sel.si_pid = tid;
+ break;
+ }
+ return (0);
+}
+
+static int
+selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
+{
+ struct socket *so;
+ int msk, i, fd;
+ fd_mask bits, bit;
+ int n = 0;
+ static int flag[3] = { FREAD, FWRITE, 0 };
+
+ for (msk = 0; msk < 3; msk++) {
+ if (ibits[msk] == NULL)
+ continue;
+ for (i = 0; i < nfd; i += NFDBITS) {
+ bits = ibits[msk][i/NFDBITS];
+ for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
+ if ((bits & bit) == 0)
+ continue;
+ bits &= ~bit;
+ so = rtems_bsdnet_fdToSocket (fd);
+ if (so == NULL)
+ return (EBADF);
+ if (socket_select (so, flag[msk], tid)) {
+ obits[msk][fd/NFDBITS] |=
+ (1 << (fd % NFDBITS));
+ n++;
+ }
+ }
+ }
+ }
+ *retval = n;
+ return (0);
+}
+
+int
+select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
+{
+ fd_mask *ibits[3], *obits[3];
+ fd_set ob[3];
+ int error, timo;
+ int retval;
+ rtems_id tid;
+ rtems_interval then, now;
+ rtems_event_set events;
+
+ if (nfds < 0)
+ return (EINVAL);
+ if (tv) {
+ timo = tv->tv_sec * hz + tv->tv_usec / tick;
+ if (timo == 0)
+ timo = 1;
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
+ }
+ else {
+ timo = 0;
+ }
+
+#define getbits(name,i) if (name) { \
+ ibits[i] = &name->fds_bits[0]; \
+ obits[i] = &ob[i].fds_bits[0]; \
+ FD_ZERO(&ob[i]); \
+ } \
+ else ibits[i] = NULL
+ getbits (readfds, 0);
+ getbits (writefds, 1);
+ getbits (exceptfds, 2);
+#undef getbits
+
+ rtems_task_ident (RTEMS_SELF, 0, &tid);
+ rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
+ for (;;) {
+ rtems_bsdnet_semaphore_obtain ();
+ error = selscan(tid, ibits, obits, nfds, &retval);
+ rtems_bsdnet_semaphore_release ();
+ if (error || retval)
+ break;
+ if (timo) {
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ timo -= now - then;
+ if (timo <= 0)
+ break;
+ then = now;
+ }
+ rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
+ }
+
+#define putbits(name,i) if (name) *name = ob[i]
+ putbits (readfds, 0);
+ putbits (writefds, 1);
+ putbits (exceptfds, 2);
+#undef putbits
+ if (error) {
+ errno = error;
+ retval = -1;
+ }
+ return (retval);
+}
diff --git a/c/src/lib/libnetworking/rtems/sghostname.c b/c/src/lib/libnetworking/rtems/sghostname.c
index 36894caa86..307f045fbd 100644
--- a/c/src/lib/libnetworking/rtems/sghostname.c
+++ b/c/src/lib/libnetworking/rtems/sghostname.c
@@ -15,7 +15,7 @@
static char *rtems_hostname;
int
-gethostname (char *name, int namelen)
+gethostname (char *name, size_t namelen)
{
char *cp = rtems_hostname;
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
}
int
-sethostname (char *name, int namelen)
+sethostname (char *name, size_t namelen)
{
char *old, *new;