ia64/xen-unstable

changeset 16821:3c49ae5641b0

minios: add lwIP 1.3.0 support

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jan 21 11:20:52 2008 +0000 (2008-01-21)
parents aca8d453da59
children 60ee6f97cb19
files extras/mini-os/Makefile extras/mini-os/daytime.c extras/mini-os/include/arch/cc.h extras/mini-os/include/arch/perf.h extras/mini-os/include/arch/sys_arch.h extras/mini-os/include/console.h extras/mini-os/include/lwipopts.h extras/mini-os/include/netfront.h extras/mini-os/lwip-arch.c extras/mini-os/lwip-net.c extras/mini-os/minios.mk
line diff
     1.1 --- a/extras/mini-os/Makefile	Mon Jan 21 11:20:27 2008 +0000
     1.2 +++ b/extras/mini-os/Makefile	Mon Jan 21 11:20:52 2008 +0000
     1.3 @@ -47,6 +47,13 @@ EXTRA_INC =
     1.4  # This must be before include minios.mk!
     1.5  include $(TARGET_ARCH_DIR)/arch.mk
     1.6  
     1.7 +ifneq ($(LWIPDIR),)
     1.8 +lwip=y
     1.9 +DEF_CFLAGS += -DHAVE_LWIP
    1.10 +DEF_CFLAGS += -I$(LWIPDIR)/src/include
    1.11 +DEF_CFLAGS += -I$(LWIPDIR)/src/include/ipv4
    1.12 +endif
    1.13 +
    1.14  # Include common mini-os makerules.
    1.15  include minios.mk
    1.16  
    1.17 @@ -90,6 +97,24 @@ links:	$(ARCH_LINKS)
    1.18  arch_lib:
    1.19  	$(MAKE) --directory=$(TARGET_ARCH_DIR) || exit 1;
    1.20  
    1.21 +ifeq ($(lwip),y)
    1.22 +# lwIP library
    1.23 +LWC	:= $(shell find $(LWIPDIR)/ -type f -name '*.c')
    1.24 +LWC	:= $(filter-out %6.c %ip6_addr.c %ethernetif.c, $(LWC))
    1.25 +LWC	+= lwip-arch.c lwip-net.c
    1.26 +LWO	:= $(patsubst %.c,%.o,$(LWC))
    1.27 +
    1.28 +lwip.a: $(LWO)
    1.29 +	$(RM) $@
    1.30 +	$(AR) cqs $@ $^
    1.31 +
    1.32 +OBJS += lwip.a
    1.33 +
    1.34 +OBJS := $(filter-out $(LWO), $(OBJS))
    1.35 +else
    1.36 +OBJS := $(filter-out daytime.o lwip%.o, $(OBJS))
    1.37 +endif
    1.38 +
    1.39  $(TARGET): links $(OBJS) arch_lib
    1.40  	$(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o
    1.41  	$(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
    1.42 @@ -107,6 +132,7 @@ clean:	arch_clean
    1.43  	done
    1.44  	rm -f *.o *~ core $(TARGET).elf $(TARGET).raw $(TARGET) $(TARGET).gz
    1.45  	find . -type l | xargs rm -f
    1.46 +	$(RM) lwip.a $(LWO)
    1.47  	rm -f tags TAGS
    1.48  
    1.49  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/extras/mini-os/daytime.c	Mon Jan 21 11:20:52 2008 +0000
     2.3 @@ -0,0 +1,64 @@
     2.4 +/* 
     2.5 + * daytime.c: a simple network service based on lwIP and mini-os
     2.6 + * 
     2.7 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
     2.8 + */
     2.9 +
    2.10 +#include <os.h>
    2.11 +#include <xmalloc.h>
    2.12 +#include <console.h>
    2.13 +#include <netfront.h>
    2.14 +#include <lwip/api.h>
    2.15 +
    2.16 +static char message[29];
    2.17 +
    2.18 +void run_server(void *p)
    2.19 +{
    2.20 +    struct ip_addr listenaddr = { 0 };
    2.21 +    struct ip_addr ipaddr = { htonl(0x0a000001) };
    2.22 +    struct ip_addr netmask = { htonl(0xff000000) };
    2.23 +    struct ip_addr gw = { 0 };
    2.24 +    struct netconn *listener;
    2.25 +    struct netconn *session;
    2.26 +    struct timeval tv;
    2.27 +    err_t rc;
    2.28 +
    2.29 +    start_networking();
    2.30 +    networking_set_addr(&ipaddr, &netmask, &gw);
    2.31 +
    2.32 +    tprintk("Opening connection\n");
    2.33 +
    2.34 +    listener = netconn_new(NETCONN_TCP);
    2.35 +    tprintk("Connection at %p\n", listener);
    2.36 +
    2.37 +    rc = netconn_bind(listener, &listenaddr, 13);
    2.38 +    if (rc != ERR_OK) {
    2.39 +        tprintk("Failed to bind connection: %i\n", rc);
    2.40 +        return;
    2.41 +    }
    2.42 +
    2.43 +    rc = netconn_listen(listener);
    2.44 +    if (rc != ERR_OK) {
    2.45 +        tprintk("Failed to listen on connection: %i\n", rc);
    2.46 +        return;
    2.47 +    }
    2.48 +
    2.49 +    while (1) {
    2.50 +        session = netconn_accept(listener);
    2.51 +        if (session == NULL) 
    2.52 +            continue;
    2.53 +
    2.54 +        gettimeofday(&tv, NULL);
    2.55 +        sprintf(message, "%20lu.%6.6lu\n", tv.tv_sec, tv.tv_usec);
    2.56 +        (void) netconn_write(session, message, strlen(message), NETCONN_COPY);
    2.57 +        (void) netconn_disconnect(session);
    2.58 +        (void) netconn_delete(session);
    2.59 +    }
    2.60 +}
    2.61 +
    2.62 +
    2.63 +int app_main(start_info_t *si)
    2.64 +{
    2.65 +    create_thread("server", run_server, NULL);
    2.66 +    return 0;
    2.67 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/extras/mini-os/include/arch/cc.h	Mon Jan 21 11:20:52 2008 +0000
     3.3 @@ -0,0 +1,83 @@
     3.4 +/* 
     3.5 + * lwip/arch/cc.h
     3.6 + *
     3.7 + * Compiler-specific types and macros for lwIP running on mini-os 
     3.8 + *
     3.9 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
    3.10 + */
    3.11 +
    3.12 +#ifndef __LWIP_ARCH_CC_H__
    3.13 +#define __LWIP_ARCH_CC_H__
    3.14 +
    3.15 +/*   Typedefs for the types used by lwip - */
    3.16 +#include <os.h>
    3.17 +#include <types.h>
    3.18 +#include <time.h>
    3.19 +typedef  u8  u8_t;
    3.20 +typedef  s8  s8_t;
    3.21 +typedef u16 u16_t;
    3.22 +typedef s16 s16_t;
    3.23 +typedef u32 u32_t;
    3.24 +typedef s32 s32_t;
    3.25 +typedef u64 u64_t;
    3.26 +typedef s64 s64_t;
    3.27 +typedef uintptr_t mem_ptr_t;
    3.28 +
    3.29 +typedef u16 u_short;
    3.30 +
    3.31 +/*   Compiler hints for packing lwip's structures - */
    3.32 +#define PACK_STRUCT_FIELD(_x)  _x
    3.33 +#define PACK_STRUCT_STRUCT     __attribute__ ((packed))
    3.34 +#define PACK_STRUCT_BEGIN 
    3.35 +#define PACK_STRUCT_END
    3.36 +
    3.37 +/*   Platform specific diagnostic output - */
    3.38 +
    3.39 +extern void lwip_printk(char *fmt, ...);
    3.40 +#define LWIP_PLATFORM_DIAG(_x) do { lwip_printk _x ; } while (0)
    3.41 +
    3.42 +extern void lwip_die(char *fmt, ...);
    3.43 +#define LWIP_PLATFORM_ASSERT(_x) do { lwip_die(_x); } while(0)
    3.44 +
    3.45 +/*   "lightweight" synchronization mechanisms - */
    3.46 +/*     SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. */
    3.47 +/*     SYS_ARCH_PROTECT(x)      - enter protection mode. */
    3.48 +/*     SYS_ARCH_UNPROTECT(x)    - leave protection mode. */
    3.49 +
    3.50 +/*   If the compiler does not provide memset() this file must include a */
    3.51 +/*   definition of it, or include a file which defines it. */
    3.52 +#include <lib.h>
    3.53 +
    3.54 +/*   This file must either include a system-local <errno.h> which defines */
    3.55 +/*   the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO */
    3.56 +/*   to make lwip/arch.h define the codes which are used throughout. */
    3.57 +#include <errno.h>
    3.58 +
    3.59 +/*   Not required by the docs, but needed for network-order calculations */
    3.60 +#include <endian.h>
    3.61 +
    3.62 +#include <inttypes.h>
    3.63 +#define S16_F PRIi16
    3.64 +#define U16_F PRIu16
    3.65 +#define X16_F PRIx16
    3.66 +#define S32_F PRIi32
    3.67 +#define U32_F PRIu32
    3.68 +#define X32_F PRIx32
    3.69 +
    3.70 +#if 0
    3.71 +#ifndef DBG_ON
    3.72 +#define DBG_ON	LWIP_DBG_ON
    3.73 +#endif
    3.74 +#define LWIP_DEBUG	DBG_ON
    3.75 +//#define IP_DEBUG	DBG_ON
    3.76 +#define TCP_DEBUG	DBG_ON
    3.77 +#define TCP_INPUT_DEBUG	DBG_ON
    3.78 +#define TCP_QLEN_DEBUG	DBG_ON
    3.79 +#define TCPIP_DEBUG	DBG_ON
    3.80 +#define DBG_TYPES_ON	DBG_ON
    3.81 +#endif
    3.82 +
    3.83 +/* TODO: checksum doesn't work fine?! */
    3.84 +#define CHECKSUM_CHECK_TCP	0
    3.85 +
    3.86 +#endif /* __LWIP_ARCH_CC_H__ */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/extras/mini-os/include/arch/perf.h	Mon Jan 21 11:20:52 2008 +0000
     4.3 @@ -0,0 +1,15 @@
     4.4 +/* 
     4.5 + * lwip/arch/perf.h
     4.6 + *
     4.7 + * Arch-specific performance measurement for lwIP running on mini-os 
     4.8 + *
     4.9 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
    4.10 + */
    4.11 +
    4.12 +#ifndef __LWIP_ARCH_PERF_H__
    4.13 +#define __LWIP_ARCH_PERF_H__
    4.14 +
    4.15 +#define PERF_START    do { } while(0)
    4.16 +#define PERF_STOP(_x) do { (void)(_x); } while (0)
    4.17 +
    4.18 +#endif /* __LWIP_ARCH_PERF_H__ */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/extras/mini-os/include/arch/sys_arch.h	Mon Jan 21 11:20:52 2008 +0000
     5.3 @@ -0,0 +1,35 @@
     5.4 +/* 
     5.5 + * lwip/arch/sys_arch.h
     5.6 + *
     5.7 + * Arch-specific semaphores and mailboxes for lwIP running on mini-os 
     5.8 + *
     5.9 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
    5.10 + */
    5.11 +
    5.12 +#ifndef __LWIP_ARCH_SYS_ARCH_H__
    5.13 +#define __LWIP_ARCH_SYS_ARCH_H__
    5.14 +
    5.15 +#include <os.h>
    5.16 +#include <xmalloc.h>
    5.17 +#include <semaphore.h>
    5.18 +
    5.19 +typedef struct semaphore *sys_sem_t;
    5.20 +#define SYS_SEM_NULL ((sys_sem_t) NULL)
    5.21 +
    5.22 +struct mbox {
    5.23 +    int count;
    5.24 +    void **messages;
    5.25 +    struct semaphore read_sem;
    5.26 +    struct semaphore write_sem;
    5.27 +    int writer;
    5.28 +    int reader;
    5.29 +};
    5.30 +
    5.31 +typedef struct mbox *sys_mbox_t;
    5.32 +#define SYS_MBOX_NULL ((sys_mbox_t) 0)
    5.33 +
    5.34 +typedef struct thread *sys_thread_t;
    5.35 +
    5.36 +typedef unsigned long sys_prot_t;
    5.37 +
    5.38 +#endif /*__LWIP_ARCH_SYS_ARCH_H__ */
     6.1 --- a/extras/mini-os/include/console.h	Mon Jan 21 11:20:27 2008 +0000
     6.2 +++ b/extras/mini-os/include/console.h	Mon Jan 21 11:20:52 2008 +0000
     6.3 @@ -38,9 +38,12 @@
     6.4  
     6.5  #include<traps.h>
     6.6  
     6.7 +void print(int direct, const char *fmt, va_list args);
     6.8  void printk(const char *fmt, ...);
     6.9  void xprintk(const char *fmt, ...);
    6.10  
    6.11 +#define tprintk(_fmt, _args...) printk("[%s] " _fmt, current->name, ##_args) 
    6.12 +
    6.13  void xencons_rx(char *buf, unsigned len, struct pt_regs *regs);
    6.14  void xencons_tx(void);
    6.15  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/extras/mini-os/include/lwipopts.h	Mon Jan 21 11:20:52 2008 +0000
     7.3 @@ -0,0 +1,22 @@
     7.4 +/*
     7.5 + * lwipopts.h
     7.6 + *
     7.7 + * Configuration for lwIP running on mini-os 
     7.8 + *
     7.9 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
    7.10 + */
    7.11 +
    7.12 +#ifndef __LWIP_LWIPOPTS_H__
    7.13 +#define __LWIP_LWIPOPTS_H__
    7.14 +
    7.15 +#define SYS_LIGHTWEIGHT_PROT 1
    7.16 +#define MEM_LIBC_MALLOC 1
    7.17 +#define LWIP_TIMEVAL_PRIVATE 0
    7.18 +#define LWIP_DHCP 1
    7.19 +#define LWIP_COMPAT_SOCKETS 0
    7.20 +#define LWIP_IGMP 1
    7.21 +#define MEMP_NUM_SYS_TIMEOUT 10
    7.22 +#define TCP_SND_BUF 3000
    7.23 +#define TCP_MSS 1500
    7.24 +
    7.25 +#endif /* __LWIP_LWIPOPTS_H__ */
     8.1 --- a/extras/mini-os/include/netfront.h	Mon Jan 21 11:20:27 2008 +0000
     8.2 +++ b/extras/mini-os/include/netfront.h	Mon Jan 21 11:20:52 2008 +0000
     8.3 @@ -1,7 +1,19 @@
     8.4  #include <wait.h>
     8.5 +#ifdef HAVE_LWIP
     8.6 +#include <lwip/netif.h>
     8.7 +#endif
     8.8  struct netfront_dev;
     8.9  struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned char *data, int len), unsigned char rawmac[6]);
    8.10  void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
    8.11  void shutdown_netfront(struct netfront_dev *dev);
    8.12  
    8.13  extern struct wait_queue_head netfront_queue;
    8.14 +
    8.15 +#ifdef HAVE_LWIP
    8.16 +/* Call this to bring up the netfront interface and the lwIP stack.
    8.17 + * N.B. _must_ be called from a thread; it's not safe to call this from 
    8.18 + * app_main(). */
    8.19 +void start_networking(void);
    8.20 +
    8.21 +void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw);
    8.22 +#endif
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/extras/mini-os/lwip-arch.c	Mon Jan 21 11:20:52 2008 +0000
     9.3 @@ -0,0 +1,293 @@
     9.4 +/* 
     9.5 + * lwip-arch.c
     9.6 + *
     9.7 + * Arch-specific semaphores and mailboxes for lwIP running on mini-os 
     9.8 + *
     9.9 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
    9.10 + */
    9.11 +
    9.12 +#include <os.h>
    9.13 +#include <time.h>
    9.14 +#include <console.h>
    9.15 +#include <xmalloc.h>
    9.16 +#include <lwip/sys.h>
    9.17 +#include <stdarg.h>
    9.18 +
    9.19 +/* Is called to initialize the sys_arch layer */
    9.20 +void sys_init(void)
    9.21 +{
    9.22 +}
    9.23 +
    9.24 +/* Creates and returns a new semaphore. The "count" argument specifies
    9.25 + * the initial state of the semaphore. */
    9.26 +sys_sem_t sys_sem_new(u8_t count)
    9.27 +{
    9.28 +    struct semaphore *sem = xmalloc(struct semaphore);
    9.29 +    sem->count = count;
    9.30 +    init_waitqueue_head(&sem->wait);
    9.31 +    return sem;
    9.32 +}
    9.33 +
    9.34 +/* Deallocates a semaphore. */
    9.35 +void sys_sem_free(sys_sem_t sem)
    9.36 +{
    9.37 +    xfree(sem);
    9.38 +}
    9.39 +
    9.40 +/* Signals a semaphore. */
    9.41 +void sys_sem_signal(sys_sem_t sem)
    9.42 +{
    9.43 +    up(sem);
    9.44 +}
    9.45 +
    9.46 +/* Blocks the thread while waiting for the semaphore to be
    9.47 + * signaled. If the "timeout" argument is non-zero, the thread should
    9.48 + * only be blocked for the specified time (measured in
    9.49 + * milliseconds).
    9.50 + * 
    9.51 + * If the timeout argument is non-zero, the return value is the number of
    9.52 + * milliseconds spent waiting for the semaphore to be signaled. If the
    9.53 + * semaphore wasn't signaled within the specified time, the return value is
    9.54 + * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
    9.55 + * (i.e., it was already signaled), the function may return zero. */
    9.56 +u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
    9.57 +{
    9.58 +    /* Slightly more complicated than the normal minios semaphore:
    9.59 +     * need to wake on timeout *or* signal */
    9.60 +    sys_prot_t prot;
    9.61 +    s64_t then = NOW();
    9.62 +    s64_t deadline;
    9.63 +
    9.64 +    if (timeout == 0)
    9.65 +	deadline = 0;
    9.66 +    else
    9.67 +	deadline = then + MILLISECS(timeout);
    9.68 +
    9.69 +    while(1) {
    9.70 +        wait_event_deadline(sem->wait, (sem->count > 0), deadline);
    9.71 +
    9.72 +        prot = sys_arch_protect();
    9.73 +	/* Atomically check that we can proceed */
    9.74 +	if (sem->count > 0 || (deadline && NOW() >= deadline))
    9.75 +	    break;
    9.76 +        sys_arch_unprotect(prot);
    9.77 +    }
    9.78 +
    9.79 +    if (sem->count > 0) {
    9.80 +        sem->count--;
    9.81 +        sys_arch_unprotect(prot);
    9.82 +        return NSEC_TO_MSEC(NOW() - then); 
    9.83 +    }
    9.84 +    
    9.85 +    sys_arch_unprotect(prot);
    9.86 +    return SYS_ARCH_TIMEOUT;
    9.87 +}
    9.88 +
    9.89 +/* Creates an empty mailbox. */
    9.90 +sys_mbox_t sys_mbox_new(int size)
    9.91 +{
    9.92 +    struct mbox *mbox = xmalloc(struct mbox);
    9.93 +    if (!size)
    9.94 +        size = 32;
    9.95 +    else if (size == 1)
    9.96 +        size = 2;
    9.97 +    mbox->count = size;
    9.98 +    mbox->messages = xmalloc_array(void*, size);
    9.99 +    init_SEMAPHORE(&mbox->read_sem, 0);
   9.100 +    mbox->reader = 0;
   9.101 +    init_SEMAPHORE(&mbox->write_sem, size);
   9.102 +    mbox->writer = 0;
   9.103 +    return mbox;
   9.104 +}
   9.105 +
   9.106 +/* Deallocates a mailbox. If there are messages still present in the
   9.107 + * mailbox when the mailbox is deallocated, it is an indication of a
   9.108 + * programming error in lwIP and the developer should be notified. */
   9.109 +void sys_mbox_free(sys_mbox_t mbox)
   9.110 +{
   9.111 +    ASSERT(mbox->reader == mbox->writer);
   9.112 +    xfree(mbox->messages);
   9.113 +    xfree(mbox);
   9.114 +}
   9.115 +
   9.116 +/* Posts the "msg" to the mailbox, internal version that actually does the
   9.117 + * post. */
   9.118 +static void do_mbox_post(sys_mbox_t mbox, void *msg)
   9.119 +{
   9.120 +    /* The caller got a semaphore token, so we are now allowed to increment
   9.121 +     * writer, but we still need to prevent concurrency between writers
   9.122 +     * (interrupt handler vs main) */
   9.123 +    sys_prot_t prot = sys_arch_protect();
   9.124 +    mbox->messages[mbox->writer] = msg;
   9.125 +    mbox->writer = (mbox->writer + 1) % mbox->count;
   9.126 +    ASSERT(mbox->reader != mbox->writer);
   9.127 +    sys_arch_unprotect(prot);
   9.128 +    up(&mbox->read_sem);
   9.129 +}
   9.130 +
   9.131 +/* Posts the "msg" to the mailbox. */
   9.132 +void sys_mbox_post(sys_mbox_t mbox, void *msg)
   9.133 +{
   9.134 +    if (mbox == SYS_MBOX_NULL)
   9.135 +        return;
   9.136 +    down(&mbox->write_sem);
   9.137 +    do_mbox_post(mbox, msg);
   9.138 +}
   9.139 +
   9.140 +/* Try to post the "msg" to the mailbox. */
   9.141 +err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
   9.142 +{
   9.143 +    if (mbox == SYS_MBOX_NULL)
   9.144 +        return ERR_BUF;
   9.145 +    if (!trydown(&mbox->write_sem))
   9.146 +        return ERR_MEM;
   9.147 +    do_mbox_post(mbox, msg);
   9.148 +    return ERR_OK;
   9.149 +}
   9.150 +
   9.151 +/*
   9.152 + * Fetch a message from a mailbox. Internal version that actually does the
   9.153 + * fetch.
   9.154 + */
   9.155 +static void do_mbox_fetch(sys_mbox_t mbox, void **msg)
   9.156 +{
   9.157 +    sys_prot_t prot;
   9.158 +    /* The caller got a semaphore token, so we are now allowed to increment
   9.159 +     * reader, but we may still need to prevent concurrency between readers.
   9.160 +     * FIXME: can there be concurrent readers? */
   9.161 +    prot = sys_arch_protect();
   9.162 +    ASSERT(mbox->reader != mbox->writer);
   9.163 +    if (msg != NULL)
   9.164 +        *msg = mbox->messages[mbox->reader];
   9.165 +    mbox->reader = (mbox->reader + 1) % mbox->count;
   9.166 +    sys_arch_unprotect(prot);
   9.167 +    up(&mbox->write_sem);
   9.168 +}
   9.169 +
   9.170 +/* Blocks the thread until a message arrives in the mailbox, but does
   9.171 + * not block the thread longer than "timeout" milliseconds (similar to
   9.172 + * the sys_arch_sem_wait() function). The "msg" argument is a result
   9.173 + * parameter that is set by the function (i.e., by doing "*msg =
   9.174 + * ptr"). The "msg" parameter maybe NULL to indicate that the message
   9.175 + * should be dropped.
   9.176 + *
   9.177 + * The return values are the same as for the sys_arch_sem_wait() function:
   9.178 + * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
   9.179 + * timeout. */
   9.180 +u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
   9.181 +{
   9.182 +    u32 rv;
   9.183 +    if (mbox == SYS_MBOX_NULL)
   9.184 +        return SYS_ARCH_TIMEOUT;
   9.185 +
   9.186 +    rv = sys_arch_sem_wait(&mbox->read_sem, timeout);
   9.187 +    if ( rv == SYS_ARCH_TIMEOUT )
   9.188 +        return rv;
   9.189 +
   9.190 +    do_mbox_fetch(mbox, msg);
   9.191 +    return 0;
   9.192 +}
   9.193 +
   9.194 +/* This is similar to sys_arch_mbox_fetch, however if a message is not
   9.195 + * present in the mailbox, it immediately returns with the code
   9.196 + * SYS_MBOX_EMPTY. On success 0 is returned.
   9.197 + *
   9.198 + * To allow for efficient implementations, this can be defined as a
   9.199 + * function-like macro in sys_arch.h instead of a normal function. For
   9.200 + * example, a naive implementation could be:
   9.201 + *   #define sys_arch_mbox_tryfetch(mbox,msg) \
   9.202 + *     sys_arch_mbox_fetch(mbox,msg,1)
   9.203 + * although this would introduce unnecessary delays. */
   9.204 +
   9.205 +u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) {
   9.206 +    if (mbox == SYS_MBOX_NULL)
   9.207 +        return SYS_ARCH_TIMEOUT;
   9.208 +
   9.209 +    if (!trydown(&mbox->read_sem))
   9.210 +	return SYS_MBOX_EMPTY;
   9.211 +
   9.212 +    do_mbox_fetch(mbox, msg);
   9.213 +    return 0;
   9.214 +}
   9.215 +
   9.216 +
   9.217 +/* Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
   9.218 + * each thread has a list of timeouts which is repressented as a linked
   9.219 + * list of sys_timeout structures. The sys_timeouts structure holds a
   9.220 + * pointer to a linked list of timeouts. This function is called by
   9.221 + * the lwIP timeout scheduler and must not return a NULL value. 
   9.222 + *
   9.223 + * In a single threadd sys_arch implementation, this function will
   9.224 + * simply return a pointer to a global sys_timeouts variable stored in
   9.225 + * the sys_arch module. */
   9.226 +struct sys_timeouts *sys_arch_timeouts(void) 
   9.227 +{
   9.228 +    static struct sys_timeouts timeout;
   9.229 +    return &timeout;
   9.230 +}
   9.231 +
   9.232 +
   9.233 +/* Starts a new thread with priority "prio" that will begin its execution in the
   9.234 + * function "thread()". The "arg" argument will be passed as an argument to the
   9.235 + * thread() function. The id of the new thread is returned. Both the id and
   9.236 + * the priority are system dependent. */
   9.237 +static struct thread *lwip_thread;
   9.238 +sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
   9.239 +{
   9.240 +    struct thread *t;
   9.241 +    if (stacksize > STACK_SIZE) {
   9.242 +	printk("Can't start lwIP thread: stack size %d is too large for our %d\n", stacksize, STACK_SIZE);
   9.243 +	do_exit();
   9.244 +    }
   9.245 +    lwip_thread = t = create_thread(name, thread, arg);
   9.246 +    return t;
   9.247 +}
   9.248 +
   9.249 +/* This optional function does a "fast" critical region protection and returns
   9.250 + * the previous protection level. This function is only called during very short
   9.251 + * critical regions. An embedded system which supports ISR-based drivers might
   9.252 + * want to implement this function by disabling interrupts. Task-based systems
   9.253 + * might want to implement this by using a mutex or disabling tasking. This
   9.254 + * function should support recursive calls from the same task or interrupt. In
   9.255 + * other words, sys_arch_protect() could be called while already protected. In
   9.256 + * that case the return value indicates that it is already protected.
   9.257 + *
   9.258 + * sys_arch_protect() is only required if your port is supporting an operating
   9.259 + * system. */
   9.260 +sys_prot_t sys_arch_protect(void)
   9.261 +{
   9.262 +    unsigned long flags;
   9.263 +    local_irq_save(flags);
   9.264 +    return flags;
   9.265 +}
   9.266 +
   9.267 +/* This optional function does a "fast" set of critical region protection to the
   9.268 + * value specified by pval. See the documentation for sys_arch_protect() for
   9.269 + * more information. This function is only required if your port is supporting
   9.270 + * an operating system. */
   9.271 +void sys_arch_unprotect(sys_prot_t pval)
   9.272 +{
   9.273 +    local_irq_restore(pval);
   9.274 +}
   9.275 +
   9.276 +/* non-fatal, print a message. */
   9.277 +void lwip_printk(char *fmt, ...)
   9.278 +{
   9.279 +    va_list args;
   9.280 +    va_start(args, fmt);
   9.281 +    printk("lwIP: ");
   9.282 +    print(0, fmt, args);
   9.283 +    va_end(args);
   9.284 +}
   9.285 +
   9.286 +/* fatal, print message and abandon execution. */
   9.287 +void lwip_die(char *fmt, ...)
   9.288 +{
   9.289 +    va_list args;
   9.290 +    va_start(args, fmt);
   9.291 +    printk("lwIP assertion failed: ");
   9.292 +    print(0, fmt, args);
   9.293 +    va_end(args);
   9.294 +    printk("\n");
   9.295 +    BUG();
   9.296 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/extras/mini-os/lwip-net.c	Mon Jan 21 11:20:52 2008 +0000
    10.3 @@ -0,0 +1,360 @@
    10.4 +/* 
    10.5 + * lwip-net.c
    10.6 + *
    10.7 + * interface between lwIP's ethernet and Mini-os's netfront.
    10.8 + * For now, support only one network interface, as mini-os does.
    10.9 + *
   10.10 + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
   10.11 + * based on lwIP's ethernetif.c skeleton file, copyrights as below.
   10.12 + */
   10.13 +
   10.14 +
   10.15 +/*
   10.16 + * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
   10.17 + * All rights reserved. 
   10.18 + * 
   10.19 + * Redistribution and use in source and binary forms, with or without modification, 
   10.20 + * are permitted provided that the following conditions are met:
   10.21 + *
   10.22 + * 1. Redistributions of source code must retain the above copyright notice,
   10.23 + *    this list of conditions and the following disclaimer.
   10.24 + * 2. Redistributions in binary form must reproduce the above copyright notice,
   10.25 + *    this list of conditions and the following disclaimer in the documentation
   10.26 + *    and/or other materials provided with the distribution.
   10.27 + * 3. The name of the author may not be used to endorse or promote products
   10.28 + *    derived from this software without specific prior written permission. 
   10.29 + *
   10.30 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
   10.31 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
   10.32 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
   10.33 + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
   10.34 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
   10.35 + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   10.36 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   10.37 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
   10.38 + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
   10.39 + * OF SUCH DAMAGE.
   10.40 + *
   10.41 + * This file is part of the lwIP TCP/IP stack.
   10.42 + * 
   10.43 + * Author: Adam Dunkels <adam@sics.se>
   10.44 + *
   10.45 + */
   10.46 +
   10.47 +#include <os.h>
   10.48 +
   10.49 +#include "lwip/opt.h"
   10.50 +#include "lwip/def.h"
   10.51 +#include "lwip/mem.h"
   10.52 +#include "lwip/pbuf.h"
   10.53 +#include "lwip/sys.h"
   10.54 +
   10.55 +#include <lwip/stats.h>
   10.56 +#include <lwip/sys.h>
   10.57 +#include <lwip/mem.h>
   10.58 +#include <lwip/memp.h>
   10.59 +#include <lwip/pbuf.h>
   10.60 +#include <netif/etharp.h>
   10.61 +#include <lwip/tcpip.h>
   10.62 +#include <lwip/tcp.h>
   10.63 +#include <lwip/netif.h>
   10.64 +#include <lwip/dhcp.h>
   10.65 +
   10.66 +#include "netif/etharp.h"
   10.67 +
   10.68 +#include <netfront.h>
   10.69 +
   10.70 +/* Define those to better describe your network interface. */
   10.71 +#define IFNAME0 'e'
   10.72 +#define IFNAME1 'n'
   10.73 +
   10.74 +#define IF_IPADDR	0x00000000
   10.75 +#define IF_NETMASK	0x00000000
   10.76 +
   10.77 +/* Only have one network interface at a time. */
   10.78 +static struct netif *the_interface = NULL;
   10.79 +
   10.80 +static unsigned char rawmac[6];
   10.81 +static struct netfront_dev *dev;
   10.82 +
   10.83 +/* Forward declarations. */
   10.84 +static err_t netfront_output(struct netif *netif, struct pbuf *p,
   10.85 +             struct ip_addr *ipaddr);
   10.86 +
   10.87 +/*
   10.88 + * low_level_output():
   10.89 + *
   10.90 + * Should do the actual transmission of the packet. The packet is
   10.91 + * contained in the pbuf that is passed to the function. This pbuf
   10.92 + * might be chained.
   10.93 + *
   10.94 + */
   10.95 +
   10.96 +static err_t
   10.97 +low_level_output(struct netif *netif, struct pbuf *p)
   10.98 +{
   10.99 +#ifdef ETH_PAD_SIZE
  10.100 +  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
  10.101 +#endif
  10.102 +
  10.103 +  /* Send the data from the pbuf to the interface, one pbuf at a
  10.104 +     time. The size of the data in each pbuf is kept in the ->len
  10.105 +     variable. */
  10.106 +  if (!p->next) {
  10.107 +    /* Only one fragment, can send it directly */
  10.108 +      netfront_xmit(dev, p->payload, p->len);
  10.109 +  } else {
  10.110 +    unsigned char data[p->tot_len], *cur;
  10.111 +    struct pbuf *q;
  10.112 +
  10.113 +    for(q = p, cur = data; q != NULL; cur += q->len, q = q->next)
  10.114 +      memcpy(cur, q->payload, q->len);
  10.115 +    netfront_xmit(dev, data, p->tot_len);
  10.116 +  }
  10.117 +
  10.118 +#if ETH_PAD_SIZE
  10.119 +  pbuf_header(p, ETH_PAD_SIZE);			/* reclaim the padding word */
  10.120 +#endif
  10.121 +  
  10.122 +  LINK_STATS_INC(link.xmit);
  10.123 +
  10.124 +  return ERR_OK;
  10.125 +}
  10.126 +
  10.127 +
  10.128 +
  10.129 +/*
  10.130 + * netfront_output():
  10.131 + *
  10.132 + * This function is called by the TCP/IP stack when an IP packet
  10.133 + * should be sent. It calls the function called low_level_output() to
  10.134 + * do the actual transmission of the packet.
  10.135 + *
  10.136 + */
  10.137 +
  10.138 +static err_t
  10.139 +netfront_output(struct netif *netif, struct pbuf *p,
  10.140 +      struct ip_addr *ipaddr)
  10.141 +{
  10.142 +  
  10.143 + /* resolve hardware address, then send (or queue) packet */
  10.144 +  return etharp_output(netif, p, ipaddr);
  10.145 + 
  10.146 +}
  10.147 +
  10.148 +/*
  10.149 + * netfront_input():
  10.150 + *
  10.151 + * This function should be called when a packet is ready to be read
  10.152 + * from the interface. 
  10.153 + *
  10.154 + */
  10.155 +
  10.156 +static void
  10.157 +netfront_input(struct netif *netif, unsigned char* data, int len)
  10.158 +{
  10.159 +  struct eth_hdr *ethhdr;
  10.160 +  struct pbuf *p, *q;
  10.161 +
  10.162 +#if ETH_PAD_SIZE
  10.163 +  len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
  10.164 +#endif
  10.165 +  
  10.166 +  /* move received packet into a new pbuf */
  10.167 +  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  10.168 +  if (p == NULL) {
  10.169 +    LINK_STATS_INC(link.memerr);
  10.170 +    LINK_STATS_INC(link.drop);
  10.171 +    return;
  10.172 +  }
  10.173 +
  10.174 +#if ETH_PAD_SIZE
  10.175 +  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
  10.176 +#endif
  10.177 +  
  10.178 +  /* We iterate over the pbuf chain until we have read the entire
  10.179 +   * packet into the pbuf. */
  10.180 +  for(q = p; q != NULL && len > 0; q = q->next) {
  10.181 +    /* Read enough bytes to fill this pbuf in the chain. The
  10.182 +     * available data in the pbuf is given by the q->len
  10.183 +     * variable. */
  10.184 +    memcpy(q->payload, data, len < q->len ? len : q->len);
  10.185 +    data += q->len;
  10.186 +    len -= q->len;
  10.187 +  }
  10.188 +
  10.189 +#if ETH_PAD_SIZE
  10.190 +  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
  10.191 +#endif
  10.192 +
  10.193 +  LINK_STATS_INC(link.recv);
  10.194 +
  10.195 +  /* points to packet payload, which starts with an Ethernet header */
  10.196 +  ethhdr = p->payload;
  10.197 +
  10.198 +  ethhdr = p->payload;
  10.199 +    
  10.200 +  switch (htons(ethhdr->type)) {
  10.201 +  /* IP packet? */
  10.202 +  case ETHTYPE_IP:
  10.203 +#if 0
  10.204 +/* CSi disabled ARP table update on ingress IP packets.
  10.205 +   This seems to work but needs thorough testing. */
  10.206 +    /* update ARP table */
  10.207 +    etharp_ip_input(netif, p);
  10.208 +#endif
  10.209 +    /* skip Ethernet header */
  10.210 +    pbuf_header(p, -(s16)sizeof(struct eth_hdr));
  10.211 +    /* pass to network layer */
  10.212 +    tcpip_input(p, netif);
  10.213 +    break;
  10.214 +      
  10.215 +  case ETHTYPE_ARP:
  10.216 +    /* pass p to ARP module  */
  10.217 +    etharp_arp_input(netif, (struct eth_addr *) netif->hwaddr, p);
  10.218 +    break;
  10.219 +  default:
  10.220 +    pbuf_free(p);
  10.221 +    p = NULL;
  10.222 +    break;
  10.223 +  }
  10.224 +}
  10.225 +
  10.226 +
  10.227 +/* 
  10.228 + * netif_rx(): overrides the default netif_rx behaviour in the netfront driver.
  10.229 + * 
  10.230 + * Pull received packets into a pbuf queue for the low_level_input() 
  10.231 + * function to pass up to lwIP.
  10.232 + */
  10.233 +
  10.234 +void netif_rx(unsigned char* data, int len)
  10.235 +{
  10.236 +  if (the_interface != NULL) {
  10.237 +    netfront_input(the_interface, data, len);
  10.238 +    wake_up(&netfront_queue);
  10.239 +  }
  10.240 +  /* By returning, we ack the packet and relinquish the RX ring slot */
  10.241 +}
  10.242 +
  10.243 +/*
  10.244 + * Set the IP, mask and gateway of the IF
  10.245 + */
  10.246 +void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw)
  10.247 +{
  10.248 +  netif_set_ipaddr(the_interface, ipaddr);
  10.249 +  netif_set_netmask(the_interface, netmask);
  10.250 +  netif_set_gw(the_interface, gw);
  10.251 +}
  10.252 +
  10.253 +
  10.254 +static void
  10.255 +arp_timer(void *arg)
  10.256 +{
  10.257 +  etharp_tmr();
  10.258 +  sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
  10.259 +}
  10.260 +
  10.261 +/*
  10.262 + * netif_netfront_init():
  10.263 + *
  10.264 + * Should be called at the beginning of the program to set up the
  10.265 + * network interface. It calls the function low_level_init() to do the
  10.266 + * actual setup of the hardware.
  10.267 + *
  10.268 + */
  10.269 +
  10.270 +err_t
  10.271 +netif_netfront_init(struct netif *netif)
  10.272 +{
  10.273 +  unsigned char *mac = netif->state;
  10.274 +
  10.275 +#if LWIP_SNMP
  10.276 +  /* ifType ethernetCsmacd(6) @see RFC1213 */
  10.277 +  netif->link_type = 6;
  10.278 +  /* your link speed here */
  10.279 +  netif->link_speed = ;
  10.280 +  netif->ts = 0;
  10.281 +  netif->ifinoctets = 0;
  10.282 +  netif->ifinucastpkts = 0;
  10.283 +  netif->ifinnucastpkts = 0;
  10.284 +  netif->ifindiscards = 0;
  10.285 +  netif->ifoutoctets = 0;
  10.286 +  netif->ifoutucastpkts = 0;
  10.287 +  netif->ifoutnucastpkts = 0;
  10.288 +  netif->ifoutdiscards = 0;
  10.289 +#endif
  10.290 +  
  10.291 +  netif->name[0] = IFNAME0;
  10.292 +  netif->name[1] = IFNAME1;
  10.293 +  netif->output = netfront_output;
  10.294 +  netif->linkoutput = low_level_output;
  10.295 +  
  10.296 +  the_interface = netif;
  10.297 +  
  10.298 +  /* set MAC hardware address */
  10.299 +  netif->hwaddr_len = 6;
  10.300 +  netif->hwaddr[0] = mac[0];
  10.301 +  netif->hwaddr[1] = mac[1];
  10.302 +  netif->hwaddr[2] = mac[2];
  10.303 +  netif->hwaddr[3] = mac[3];
  10.304 +  netif->hwaddr[4] = mac[4];
  10.305 +  netif->hwaddr[5] = mac[5];
  10.306 +
  10.307 +  /* No interesting per-interface state */
  10.308 +  netif->state = NULL;
  10.309 +
  10.310 +  /* maximum transfer unit */
  10.311 +  netif->mtu = 1500;
  10.312 +  
  10.313 +  /* broadcast capability */
  10.314 +  netif->flags = NETIF_FLAG_BROADCAST;
  10.315 +
  10.316 +  etharp_init();
  10.317 +
  10.318 +  sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
  10.319 +
  10.320 +  return ERR_OK;
  10.321 +}
  10.322 +
  10.323 +/*
  10.324 + * Thread run by netfront: bring up the IP address and fire lwIP timers.
  10.325 + */
  10.326 +static __DECLARE_SEMAPHORE_GENERIC(tcpip_is_up, 0);
  10.327 +static void tcpip_bringup_finished(void *p)
  10.328 +{
  10.329 +  tprintk("TCP/IP bringup ends.\n");
  10.330 +  up(&tcpip_is_up);
  10.331 +}
  10.332 +
  10.333 +/* 
  10.334 + * Utility function to bring the whole lot up.  Call this from app_main() 
  10.335 + * or similar -- it starts netfront and have lwIP start its thread,
  10.336 + * which calls back to tcpip_bringup_finished(), which 
  10.337 + * lets us know it's OK to continue.
  10.338 + */
  10.339 +void start_networking(void)
  10.340 +{
  10.341 +  struct netif *netif;
  10.342 +  struct ip_addr ipaddr = { htonl(IF_IPADDR) };
  10.343 +  struct ip_addr netmask = { htonl(IF_NETMASK) };
  10.344 +  struct ip_addr gw = { 0 };
  10.345 +
  10.346 +  tprintk("Waiting for network.\n");
  10.347 +
  10.348 +  dev = init_netfront(NULL, NULL, rawmac);
  10.349 +  
  10.350 +  tprintk("TCP/IP bringup begins.\n");
  10.351 +  
  10.352 +  netif = xmalloc(struct netif);
  10.353 +  tcpip_init(tcpip_bringup_finished, netif);
  10.354 +    
  10.355 +  netif_add(netif, &ipaddr, &netmask, &gw, rawmac, 
  10.356 +            netif_netfront_init, ip_input);
  10.357 +  netif_set_default(netif);
  10.358 +  netif_set_up(netif);
  10.359 +
  10.360 +  down(&tcpip_is_up);
  10.361 +
  10.362 +  tprintk("Network is ready.\n");
  10.363 +}
    11.1 --- a/extras/mini-os/minios.mk	Mon Jan 21 11:20:27 2008 +0000
    11.2 +++ b/extras/mini-os/minios.mk	Mon Jan 21 11:20:52 2008 +0000
    11.3 @@ -6,7 +6,7 @@ debug = y
    11.4  
    11.5  # Define some default flags.
    11.6  # NB. '-Wcast-qual' is nasty, so I omitted it.
    11.7 -DEF_CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
    11.8 +DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
    11.9  DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
   11.10  DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
   11.11  DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)