initial commit of lk (little kernel) project
diff --git a/platform/armemu/debug.c b/platform/armemu/debug.c
new file mode 100644
index 0000000..aca3931
--- /dev/null
+++ b/platform/armemu/debug.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/armemu/memmap.h>
+#include <platform/debug.h>
+
+void dputc(char c)
+{
+ *REG8(DEBUG_STDOUT) = c;
+}
+
+int dgetc(char *c)
+{
+ int8_t result = (int8_t)*REG8(DEBUG_STDIN);
+
+ if (result == -1)
+ return -1;
+
+ *c = (char)result;
+ return 0;
+}
+
+void debug_dump_regs(void)
+{
+ *REG32(DEBUG_REGDUMP) = 1;
+}
+
+void debug_halt(void)
+{
+ *REG32(DEBUG_HALT) = 1;
+ for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+ *REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
+ *REG32(DEBUG_MEMDUMPLEN) = len;
+ *REG32(DEBUG_MEMDUMP_BYTE) = 1;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+ len /= 2;
+
+ *REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
+ *REG32(DEBUG_MEMDUMPLEN) = len;
+ *REG32(DEBUG_MEMDUMP_HALFWORD) = 1;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+ len /= 4;
+
+ *REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
+ *REG32(DEBUG_MEMDUMPLEN) = len;
+ *REG32(DEBUG_MEMDUMP_WORD) = 1;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+ if(trace_type < 0 || trace_type >= 4)
+ return;
+
+ *REG32(DEBUG_SET_TRACELEVEL_CPU + trace_type * 4) = level;
+}
+
+uint32_t debug_cycle_count()
+{
+ return *REG32(DEBUG_CYCLE_COUNT);
+}
diff --git a/platform/armemu/include/platform/armemu.h b/platform/armemu/include/platform/armemu.h
new file mode 100644
index 0000000..10b0d60
--- /dev/null
+++ b/platform/armemu/include/platform/armemu.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_ARMEMU_H
+#define __PLATFORM_ARMEMU_H
+
+#include <platform/armemu/memmap.h>
+
+#endif
+
diff --git a/platform/armemu/include/platform/armemu/memmap.h b/platform/armemu/include/platform/armemu/memmap.h
new file mode 100644
index 0000000..9df4e0b
--- /dev/null
+++ b/platform/armemu/include/platform/armemu/memmap.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2005-2006 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __MEMMAP_H
+#define __MEMMAP_H
+
+#define MEMBANK_SIZE (4*1024*1024)
+
+/* some helpful macros */
+#define REG(x) ((volatile unsigned int *)(x))
+#define REG_H(x) ((volatile unsigned short *)(x))
+#define REG_B(x) ((volatile unsigned char *)(x))
+
+/* memory map of our generic arm system */
+// XXX make more dynamic
+#define MAINMEM_BASE 0x0
+#define MAINMEM_SIZE (MEMBANK_SIZE)
+
+/* peripherals are all mapped here */
+#define PERIPHERAL_BASE (0xf0000000)
+
+/* system info */
+#define SYSINFO_REGS_BASE (PERIPHERAL_BASE)
+#define SYSINFO_REGS_SIZE MEMBANK_SIZE
+#define SYSINFO_FEATURES (SYSINFO_REGS_BASE + 0)
+#define SYSINFO_FEATURE_DISPLAY 0x00000001
+#define SYSINFO_FEATURE_CONSOLE 0x00000002
+#define SYSINFO_FEATURE_NETWORK 0x00000004
+
+ /* a write to this register latches the current emulator system time, so the next two regs can be read atomically */
+#define SYSINFO_TIME_LATCH (SYSINFO_REGS_BASE + 4)
+ /* gettimeofday() style time values */
+#define SYSINFO_TIME_SECS (SYSINFO_REGS_BASE + 8)
+#define SYSINFO_TIME_USECS (SYSINFO_REGS_BASE + 12)
+
+/* display */
+#define DISPLAY_BASE (SYSINFO_REGS_BASE + SYSINFO_REGS_SIZE)
+#define DISPLAY_SIZE MEMBANK_SIZE
+#define DISPLAY_FRAMEBUFFER DISPLAY_BASE
+#define DISPLAY_REGS_BASE (DISPLAY_BASE + DISPLAY_SIZE)
+#define DISPLAY_REGS_SIZE MEMBANK_SIZE
+ /* no display regs for now */
+
+/* console (keyboard controller */
+#define CONSOLE_REGS_BASE (DISPLAY_REGS_BASE + DISPLAY_REGS_SIZE)
+#define CONSOLE_REGS_SIZE MEMBANK_SIZE
+#define KYBD_STAT (CONSOLE_REGS_BASE + 0)
+#define KYBD_DATA (CONSOLE_REGS_BASE + 4)
+
+/* programmable timer */
+#define PIT_REGS_BASE (CONSOLE_REGS_BASE + CONSOLE_REGS_SIZE)
+#define PIT_REGS_SIZE MEMBANK_SIZE
+#define PIT_STATUS (PIT_REGS_BASE + 0) // status bit
+#define PIT_CLEAR (PIT_REGS_BASE + 4) // a nonzero write clears any pending timer
+#define PIT_CLEAR_INT (PIT_REGS_BASE + 8) // a nonzero write clears the pending interrupt
+#define PIT_INTERVAL (PIT_REGS_BASE + 12) // set the countdown interval, and what the interval is reset to if periodic
+#define PIT_START_ONESHOT (PIT_REGS_BASE + 16) // a nonzero write starts a oneshot countdown
+#define PIT_START_PERIODIC (PIT_REGS_BASE + 20) // a nonzero write starts a periodic countdown
+
+#define PIT_STATUS_ACTIVE 0x1
+#define PIT_STATUS_INT_PEND 0x2
+
+/* interrupt controller */
+#define PIC_REGS_BASE (PIT_REGS_BASE + PIT_REGS_SIZE)
+#define PIC_REGS_SIZE MEMBANK_SIZE
+
+ /* Current vector mask, read-only */
+#define PIC_MASK (PIC_REGS_BASE + 0)
+ /* Mask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_MASK_LATCH (PIC_REGS_BASE + 4)
+ /* Unmask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_UNMASK_LATCH (PIC_REGS_BASE + 8)
+ /* each bit corresponds to the current status of the interrupt line */
+#define PIC_STAT (PIC_REGS_BASE + 12)
+ /* one bit set for the highest priority non-masked active interrupt */
+#define PIC_CURRENT_BIT (PIC_REGS_BASE + 16)
+ /* holds the current interrupt number of the highest priority non-masked active interrupt,
+ * or 0xffffffff if no interrupt is active
+ */
+#define PIC_CURRENT_NUM (PIC_REGS_BASE + 20)
+
+ /* interrupt map */
+#define INT_PIT 0
+#define INT_KEYBOARD 1
+#define INT_NET 2
+#define PIC_MAX_INT 32
+
+/* debug interface */
+#define DEBUG_REGS_BASE (PIC_REGS_BASE + PIC_REGS_SIZE)
+#define DEBUG_REGS_SIZE MEMBANK_SIZE
+#define DEBUG_STDOUT (DEBUG_REGS_BASE + 0) /* writes to this register are sent through to stdout */
+#define DEBUG_STDIN (DEBUG_REGS_BASE + 0) /* reads from this register return the contents of stdin
+ * or -1 if no data is pending */
+#define DEBUG_REGDUMP (DEBUG_REGS_BASE + 4) /* writes to this register cause the emulator to dump registers */
+#define DEBUG_HALT (DEBUG_REGS_BASE + 8) /* writes to this register will halt the emulator */
+
+#define DEBUG_MEMDUMPADDR (DEBUG_REGS_BASE + 12) /* set the base address of memory to dump */
+#define DEBUG_MEMDUMPLEN (DEBUG_REGS_BASE + 16) /* set the length of memory to dump */
+#define DEBUG_MEMDUMP_BYTE (DEBUG_REGS_BASE + 20) /* trigger a memory dump in byte format */
+#define DEBUG_MEMDUMP_HALFWORD (DEBUG_REGS_BASE + 24) /* trigger a memory dump in halfword format */
+#define DEBUG_MEMDUMP_WORD (DEBUG_REGS_BASE + 28) /* trigger a memory dump in word format */
+
+/* lets you set the trace level of the various subsystems from within the emulator */
+/* only works on emulator builds that support dynamic trace levels */
+#define DEBUG_SET_TRACELEVEL_CPU (DEBUG_REGS_BASE + 32)
+#define DEBUG_SET_TRACELEVEL_UOP (DEBUG_REGS_BASE + 36)
+#define DEBUG_SET_TRACELEVEL_SYS (DEBUG_REGS_BASE + 40)
+#define DEBUG_SET_TRACELEVEL_MMU (DEBUG_REGS_BASE + 44)
+
+#define DEBUG_CYCLE_COUNT (DEBUG_REGS_BASE + 48)
+#define DEBUG_INS_COUNT (DEBUG_REGS_BASE + 52)
+
+/* network interface */
+#define NET_REGS_BASE (DEBUG_REGS_BASE + DEBUG_REGS_SIZE)
+#define NET_REGS_SIZE MEMBANK_SIZE
+
+#define NET_BUF_LEN 2048
+#define NET_IN_BUF_COUNT 32
+
+#define NET_HEAD (NET_REGS_BASE + 0) /* current next buffer the hardware will write to */
+#define NET_TAIL (NET_REGS_BASE + 4) /* currently selected input buffer */
+#define NET_SEND (NET_REGS_BASE + 8) /* writes to this register sends whatever is in the out buf */
+#define NET_SEND_LEN (NET_REGS_BASE + 12) /* length of packet to send */
+#define NET_OUT_BUF (NET_REGS_BASE + NET_BUF_LEN)
+
+#define NET_IN_BUF_LEN (NET_REGS_BASE + 16) /* length of the currently selected in buffer, via tail register */
+#define NET_IN_BUF (NET_REGS_BASE + NET_BUF_LEN*2)
+
+#endif
diff --git a/platform/armemu/interrupts.c b/platform/armemu/interrupts.c
new file mode 100644
index 0000000..604d2dc
--- /dev/null
+++ b/platform/armemu/interrupts.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <sys/types.h>
+#include <debug.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <platform/armemu.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+
+struct int_handler_struct {
+ int_handler handler;
+ void *arg;
+};
+
+static struct int_handler_struct int_handler_table[PIC_MAX_INT];
+
+void platform_init_interrupts(void)
+{
+ // mask all the interrupts
+ *REG32(PIC_MASK_LATCH) = 0xffffffff;
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= PIC_MAX_INT)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = *REG32(PIC_MASK) & (1<<vector);
+ *REG32(PIC_MASK_LATCH) = 1 << vector;
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= PIC_MAX_INT)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = *REG32(PIC_MASK) & (1<<vector);
+ *REG32(PIC_UNMASK_LATCH) = 1 << vector;
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+ // get the current vector
+ unsigned int vector = *REG32(PIC_CURRENT_NUM);
+ if (vector == 0xffffffff)
+ return INT_NO_RESCHEDULE;
+
+// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
+
+ // deliver the interrupt
+ enum handler_return ret;
+
+ ret = INT_NO_RESCHEDULE;
+ if (int_handler_table[vector].handler)
+ ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+
+// dprintf("platform_irq: exit %d\n", ret);
+
+ return ret;
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+ panic("FIQ: unimplemented\n");
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ if (vector >= PIC_MAX_INT)
+ panic("register_int_handler: vector out of range %d\n", vector);
+
+ enter_critical_section();
+
+ int_handler_table[vector].handler = handler;
+ int_handler_table[vector].arg = arg;
+
+ exit_critical_section();
+}
+
diff --git a/platform/armemu/net.c b/platform/armemu/net.c
new file mode 100644
index 0000000..e27d321
--- /dev/null
+++ b/platform/armemu/net.c
@@ -0,0 +1,398 @@
+#if WITH_LWIP
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * This file is a skeleton for developing Ethernet network interface
+ * drivers for lwIP. Add code to the low_level functions and do a
+ * search-and-replace for the word "ethernetif" to replace it with
+ * something that better describes your network interface.
+ */
+/*
+ * ARMEMU bits
+ * Copyright (c) 2006 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <malloc.h>
+#include <dev/ethernet.h>
+#include <err.h>
+#include <reg.h>
+#include <string.h>
+#include <platform/interrupts.h>
+#include <platform/armemu/memmap.h>
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include <lwip/stats.h>
+
+#include "netif/etharp.h"
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 'e'
+#define IFNAME1 'n'
+
+struct ethernetif {
+ struct eth_addr *ethaddr;
+ /* Add whatever per-interface state that is needed here. */
+};
+
+static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+
+/* Forward declarations. */
+static void ethernetif_input(struct netif *netif);
+static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+static void
+low_level_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif = netif->state;
+
+ /* set MAC hardware address length */
+ netif->hwaddr_len = 6;
+
+ /* set MAC hardware address */
+ netif->hwaddr[0] = 0;
+ netif->hwaddr[1] = 0x01;
+ netif->hwaddr[2] = 0x02;
+ netif->hwaddr[3] = 0x03;
+ netif->hwaddr[4] = 0x04;
+ netif->hwaddr[5] = 0x05;
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* broadcast capability */
+ netif->flags = NETIF_FLAG_BROADCAST;
+
+ /* Do whatever else is needed to initialize interface. */
+}
+
+/*
+ * low_level_output():
+ *
+ * Should do the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ */
+
+static err_t
+low_level_output(struct netif *netif, struct pbuf *p)
+{
+ struct ethernetif *ethernetif = netif->state;
+ struct pbuf *q;
+ int i;
+ int j;
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* XXX maybe just a mutex? */
+ enter_critical_section();
+
+ i = 0;
+ for(q = p; q != NULL; q = q->next) {
+ /* Send the data from the pbuf to the interface, one pbuf at a
+ time. The size of the data in each pbuf is kept in the ->len
+ variable. */
+// debug_dump_memory_bytes(q->payload, q->len);
+ for (j = 0; j < q->len; j++)
+ *REG8(NET_OUT_BUF + i + j) = ((unsigned char *)q->payload)[j];
+ i += q->len;
+ }
+
+ *REG(NET_SEND_LEN) = i;
+ *REG(NET_SEND) = 1;
+
+ exit_critical_section();
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+#if LINK_STATS
+ lwip_stats.link.xmit++;
+#endif /* LINK_STATS */
+
+ return ERR_OK;
+}
+
+/*
+ * low_level_input():
+ *
+ * Should allocate a pbuf and transfer the bytes of the incoming
+ * packet from the interface into the pbuf.
+ *
+ */
+
+static struct pbuf *
+low_level_input(struct netif *netif)
+{
+ struct ethernetif *ethernetif = netif->state;
+ struct pbuf *p, *q;
+ u16_t len;
+ int i;
+ int head, tail;
+
+ /* get the head and tail pointers from the ethernet interface */
+ head = *REG(NET_HEAD);
+ tail = *REG(NET_TAIL);
+
+ if (tail == head)
+ return NULL; // false alarm
+
+ /* Obtain the size of the packet and put it into the "len"
+ variable. */
+ len = *REG(NET_IN_BUF_LEN);
+
+#if ETH_PAD_SIZE
+ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p != NULL) {
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* We iterate over the pbuf chain until we have read the entire
+ * packet into the pbuf. */
+ int pos = 0;
+ for(q = p; q != NULL; q = q->next) {
+ /* Read enough bytes to fill this pbuf in the chain. The
+ * available data in the pbuf is given by the q->len
+ * variable. */
+ for (i=0; i < q->len; i++) {
+ ((unsigned char *)q->payload)[i] = *REG8(NET_IN_BUF + pos);
+ pos++;
+ }
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+#if LINK_STATS
+ lwip_stats.link.recv++;
+#endif /* LINK_STATS */
+ } else {
+#if LINK_STATS
+ lwip_stats.link.memerr++;
+ lwip_stats.link.drop++;
+#endif /* LINK_STATS */
+ }
+
+ /* push the tail pointer up by one, giving the buffer back to the hardware */
+ *REG(NET_TAIL) = (tail + 1) % NET_IN_BUF_COUNT;
+
+ return p;
+}
+
+/*
+ * ethernetif_output():
+ *
+ * This function is called by the TCP/IP stack when an IP packet
+ * should be sent. It calls the function called low_level_output() to
+ * do the actual transmission of the packet.
+ *
+ */
+
+static err_t
+ethernetif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+// dprintf("ethernetif_output: netif %p, pbuf %p, ipaddr %p\n", netif, p, ipaddr);
+
+ /* resolve hardware address, then send (or queue) packet */
+ return etharp_output(netif, ipaddr, p);
+
+}
+
+/*
+ * ethernetif_input():
+ *
+ * This function should be called when a packet is ready to be read
+ * from the interface. It uses the function low_level_input() that
+ * should handle the actual reception of bytes from the network
+ * interface.
+ *
+ */
+
+static void
+ethernetif_input(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+ struct eth_hdr *ethhdr;
+ struct pbuf *p;
+
+ ethernetif = netif->state;
+
+ /* move received packet into a new pbuf */
+ p = low_level_input(netif);
+ /* no packet could be read, silently ignore this */
+ if (p == NULL) return;
+ /* points to packet payload, which starts with an Ethernet header */
+ ethhdr = p->payload;
+
+#if LINK_STATS
+ lwip_stats.link.recv++;
+#endif /* LINK_STATS */
+
+ ethhdr = p->payload;
+
+// dprintf("ethernetif_input: type 0x%x\n", htons(ethhdr->type));
+
+ switch (htons(ethhdr->type)) {
+ /* IP packet? */
+ case ETHTYPE_IP:
+ /* update ARP table */
+ etharp_ip_input(netif, p);
+ /* skip Ethernet header */
+ pbuf_header(p, -sizeof(struct eth_hdr));
+ /* pass to network layer */
+ netif->input(p, netif);
+ break;
+
+ case ETHTYPE_ARP:
+ /* pass p to ARP module */
+ etharp_arp_input(netif, ethernetif->ethaddr, p);
+ break;
+ default:
+ pbuf_free(p);
+ p = NULL;
+ break;
+ }
+}
+
+static enum handler_return ethernet_int(void *arg)
+{
+ struct netif *netif = (struct netif *)arg;
+
+ ethernetif_input(netif);
+
+ return INT_RESCHEDULE;
+}
+
+
+
+/*
+ * ethernetif_init():
+ *
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ */
+
+static err_t
+ethernetif_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+
+ ethernetif = mem_malloc(sizeof(struct ethernetif));
+
+ if (ethernetif == NULL)
+ {
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
+ return ERR_MEM;
+ }
+
+ netif->state = ethernetif;
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = ethernetif_output;
+ netif->linkoutput = low_level_output;
+
+ ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
+
+ low_level_init(netif);
+
+ return ERR_OK;
+}
+
+status_t ethernet_init(void)
+{
+ /* check to see if the ethernet feature is turned on */
+ if ((*REG(SYSINFO_FEATURES) & SYSINFO_FEATURE_NETWORK) == 0)
+ return ERR_NOT_FOUND;
+
+ struct netif *netif = calloc(sizeof(struct netif), 1);
+ struct ip_addr *ipaddr = calloc(sizeof(struct ip_addr), 1);
+ struct ip_addr *netmask = calloc(sizeof(struct ip_addr), 1);
+ struct ip_addr *gw = calloc(sizeof(struct ip_addr), 1);
+
+ struct netif *netifret = netif_add(netif, ipaddr, netmask, gw, NULL, ðernetif_init, &ip_input);
+ if (netifret == NULL) {
+ free(netif);
+ free(ipaddr);
+ free(netmask);
+ free(gw);
+ return ERR_NOT_FOUND;
+ }
+
+ /* register for interrupt handlers */
+ register_int_handler(INT_NET, ethernet_int, netif);
+
+ netif_set_default(netif);
+
+ unmask_interrupt(INT_NET, NULL);
+
+ return NO_ERROR;
+}
+
+#endif // WITH_LWIP
diff --git a/platform/armemu/platform.c b/platform/armemu/platform.c
new file mode 100644
index 0000000..1425674
--- /dev/null
+++ b/platform/armemu/platform.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <platform.h>
+#include "platform_p.h"
+
+void platform_init_mmu_mappings(void)
+{
+}
+
+void platform_early_init(void)
+{
+ /* initialize the interrupt controller */
+ platform_init_interrupts();
+
+ /* initialize the timer block */
+ platform_init_timer();
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/armemu/platform_p.h b/platform/armemu/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/armemu/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/armemu/rules.mk b/platform/armemu/rules.mk
new file mode 100644
index 0000000..f51b759
--- /dev/null
+++ b/platform/armemu/rules.mk
@@ -0,0 +1,28 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm926ej-s
+CPU := generic
+
+# emulater doesn't support thumb properly
+ENABLE_THUMB := false
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/net.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/timer.o \
+
+
+# $(LOCAL_DIR)/console.o \
+
+MEMBASE := 0x0
+MEMSIZE := 0x400000 # 4MB
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/armemu/timer.c b/platform/armemu/timer.c
new file mode 100644
index 0000000..770905b
--- /dev/null
+++ b/platform/armemu/timer.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/armemu.h>
+#include "platform_p.h"
+
+static platform_timer_callback t_callback;
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+ enter_critical_section();
+
+ t_callback = callback;
+
+ *REG(PIT_CLEAR) = 1;
+ *REG(PIT_INTERVAL) = interval;
+ *REG(PIT_START_PERIODIC) = 1;
+
+ unmask_interrupt(INT_PIT, NULL);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+ time_t time;
+ *REG(SYSINFO_TIME_LATCH) = 1;
+ time = *REG(SYSINFO_TIME_SECS) * 1000;
+ time += *REG(SYSINFO_TIME_USECS) / 1000;
+
+ return time;
+}
+
+static enum handler_return platform_tick(void *arg)
+{
+ *REG(PIT_CLEAR_INT) = 1;
+ if (t_callback) {
+ return t_callback(arg, current_time());
+ } else {
+ return INT_NO_RESCHEDULE;
+ }
+}
+
+void platform_init_timer(void)
+{
+ register_int_handler(INT_PIT, &platform_tick, NULL);
+}
+