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, &ethernetif_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);
+}
+
diff --git a/platform/at91sam7/README b/platform/at91sam7/README
new file mode 100644
index 0000000..41ce561
--- /dev/null
+++ b/platform/at91sam7/README
@@ -0,0 +1,15 @@
+
+Platform support for the ATMEL AT91SAM7[XS] ARM7 microcontrollers.
+
+This is a base platform -- it needs to be specialized for a particular
+board (see sam7ex256 as an example of this) to be useful.  In particular
+it does not provide the platform/board.h (which must include the 
+correct at91sam7*h file and mux config).
+
+TODO:
+- support clock rates other than (and above) 18MHz
+- compute uart divisor, PIT interval, etc from MCK
+- timer hook should honor the requested interval
+- current_time() should return a meaningful value
+- actually pass argument to interrupt handlers?
+
diff --git a/platform/at91sam7/at91sam7s.pins b/platform/at91sam7/at91sam7s.pins
new file mode 100644
index 0000000..e9c4474
--- /dev/null
+++ b/platform/at91sam7/at91sam7s.pins
@@ -0,0 +1,32 @@
+PA0    PWM0   TIOA0
+PA1    PWM1   TIOB0
+PA2    PWM2   SCK0
+PA3    TWD    NPCS3
+PA4    TWCK   TCLK0
+PA5    RXD0   NPCS3
+PA6    TXD0   PCK0
+PA7    RTS0   PWM3
+PA8    CTS0   ADTRG
+PA9    DRXD   NPCS1
+PA10   DTXD   NPCS2
+PA11   NPCS0  PWM0
+PA12   MISO   PWM1
+PA13   MOSI   PWM2
+PA14   SPCK   PWM3
+PA15   TF     TIOA1
+PA16   TK     TIOB1
+PA17   TD     PCK1
+PA18   RD     PCK2
+PA19   RK     FIQ
+PA20   RF     IRQ0
+PA21   RXD1   PCK1
+PA22   TXD1   NPCS3
+PA23   SCK1   PWM0
+PA24   RTS1   PWM1
+PA25   CTS1   PWM2
+PA26   DCD1   TIOA2
+PA27   DTR1   TIOB2
+PA28   DSR1   TCLK1
+PA29   RI1    TCLK2
+PA30   IRQ1   NPCS2
+PA31   NPCS1  PCK2
\ No newline at end of file
diff --git a/platform/at91sam7/at91sam7x.pins b/platform/at91sam7/at91sam7x.pins
new file mode 100644
index 0000000..f026fb6
--- /dev/null
+++ b/platform/at91sam7/at91sam7x.pins
@@ -0,0 +1,31 @@
+PA0   RXD0        NC
+PA1   TXD0        NC
+PA2   SCK0        SPI1_NPCS1
+PA3   RTS0        SPI1_NPCS2
+PA4   CTS0        SPI1_NPCS3
+PA5   RXD1        NC
+PA6   TXD1        NC
+PA7   SCK1        SPI0_NPCS1
+PA8   RTS1        SPI0_NPCS2
+PA9   CTS1        SPI0_NPCS3
+PA10  TWD         NC
+PA11  TWCK        NC
+PA12  SPI0_NPCS0  NC
+PA13  SPI0_NPCS1  PCK1
+PA14  SPI0_NPCS2  IRQ1
+PA15  SPI0_NPCS3  TCLK2
+PA16  SPI0_MISO   NC
+PA17  SPI0_MOSI   NC
+PA18  SPI0_SPCK   NC
+PA19  CANRX       NC
+PA20  CANTX       NC
+PA21  TF          SPI1_NPCS0
+PA22  TK          SPI1_SPCK
+PA23  TD          SPI1_MOSI
+PA24  RD          SPI1_MISO
+PA25  RK          SPI1_NPCS1
+PA26  RF          SPI1_NPCS2
+PA27  DRXD        PCK3
+PA28  DTXD        NC
+PA29  FIQ         SPI1_NPCS3
+PA30  IRQ0        PCK2
diff --git a/platform/at91sam7/debug.c b/platform/at91sam7/debug.c
new file mode 100644
index 0000000..2cca7b3
--- /dev/null
+++ b/platform/at91sam7/debug.c
@@ -0,0 +1,81 @@
+/*
+ * 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 <debug.h>
+#include <printf.h>
+#include <platform/at91sam7.h>
+#include <kernel/thread.h>
+#include <stdarg.h>
+
+void ser_init(void)
+{
+    AT91DBGU *dbgu = AT91DBGU_ADDR;
+
+//    AT91PIO *pio = AT91PIO_ADDR;
+//    pio->select_a = PIN_DRXD | PIN_DTXD;
+//    pio->pio_disable = PIN_DRXD | PIN_DTXD;
+    
+    dbgu->MR = DBGU_PAR_NONE | DBGU_MODE_NORMAL;
+    // dbgu->BRGR = 10; //MCK_IN_MHZ / 115200 / 16; 
+    dbgu->BRGR = AT91_MCK_MHZ / 115200 / 16;
+    dbgu->CR = DBGU_RXEN | DBGU_TXEN;
+}
+
+void ser_putc(unsigned c)
+{
+    AT91DBGU *dbgu = AT91DBGU_ADDR;
+    if(c == 10) {
+        while(!(dbgu->SR & DBGU_TXRDY));
+        dbgu->THR = 13;
+    }
+    while(!(dbgu->SR & DBGU_TXRDY));
+    dbgu->THR = c;
+}
+
+void ser_puts(const char *s)
+{
+    AT91DBGU *dbgu = AT91DBGU_ADDR;
+    while(*s) {
+        if(*s == 10) {
+            while(!(dbgu->SR & DBGU_TXRDY));
+            dbgu->THR = 13;
+        }
+        while(!(dbgu->SR & DBGU_TXRDY));
+        dbgu->THR = *s++;
+    }
+}
+
+void dputc(char c)
+{
+	ser_putc(c);
+}
+
+void debug_halt()
+{
+	arch_disable_ints();
+    for(;;);
+}
+
+uint32_t debug_cycle_count()
+{
+	PANIC_UNIMPLEMENTED;
+}
diff --git a/platform/at91sam7/emac_dev.c b/platform/at91sam7/emac_dev.c
new file mode 100644
index 0000000..d042ef6
--- /dev/null
+++ b/platform/at91sam7/emac_dev.c
@@ -0,0 +1,249 @@
+/*
+ * 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 <kernel/thread.h>
+#include <kernel/mutex.h>
+#include <platform/at91sam7.h>
+#include <platform/debug.h>
+
+#include <dev/ethernet.h>
+
+#include <malloc.h>
+#include <string.h>
+
+#include <hw/mii.h>
+
+void emac_init_send(void);
+
+#define PHYA 31
+
+static unsigned mi_rd(AT91EMAC *emac, unsigned addr)
+{
+    addr &= 0x1f;
+
+    thread_sleep(20);
+    
+    emac->MAN =
+        (1 << 30) |    /* sof:  01 */
+        (2 << 28) |    /* rw:   10 = read */
+        (PHYA << 23) | /* phya: PHYA */
+        (addr << 18) | /* rega: addr */
+        (2 << 16);     /* code: 10 */
+
+    while(!(emac->NSR & NSR_IDLE)) ;
+
+    thread_sleep(20);
+    return emac->MAN & 0xffff;
+}
+
+static void mi_wr(AT91EMAC *emac, unsigned addr, unsigned val)
+{
+    addr &= 0x1f;
+    val &= 0xffff;
+    
+    emac->MAN =
+        (1 << 30) |    /* sof:  01 */
+        (1 << 28) |    /* rw:   01 = read */
+        (PHYA << 23) | /* phya: PHYA */
+        (addr << 18) | /* rega: addr */
+        (2 << 16) |    /* code: 10 */
+        val;           /* data: val */
+
+    while(!(emac->NSR & NSR_IDLE)) ;
+}
+
+#define PIN_EMAC_ALL   0x3ffff
+#define PIN_PHY_PD     (1 << 18)
+#define PIN_PHY_IRQ    (1 << 26)
+
+#define PIN_PHYAD0     (1 << 26)
+#define PIN_PHYAD1     (1 << 14)
+#define PIN_PHYAD2     (1 << 13)
+#define PIN_PHYAD3     (1 << 6)
+#define PIN_PHYAD4     (1 << 5)
+#define PIN_LPBK       (1 << 15)
+#define PIN_ISOLATE    (1 << 7)
+#define PIN_RMII_MODE  (1 << 16)
+#define PIN_RMII_BTB   (1 << 4)
+
+/* select RMII w/ BTB, 100mbps duplex autonegotiate 
+** disable ISOLATE and LPBK 
+** phya=00001b
+*/
+#define PIN_RESET_LOW  (PIN_LPBK)
+
+int emac_init(void)
+{
+    AT91EMAC *emac = AT91EMAC_ADDR;
+    AT91PIO *piob = AT91PIOB_ADDR;
+    AT91PMC *pmc = AT91PMC_ADDR;
+    AT91RSTC *rstc = AT91RSTC_ADDR;
+
+    dprintf("emac_init()\n");
+    
+        /* enable clock to EMAC */
+    pmc->PCER = (1 << PID_EMAC);
+
+    thread_sleep(10);
+    
+        /* for reset, all lines are gpio inputs and pullups are
+           enabled or disabled per strapping mode defined above */
+    piob->pio_enable = PIN_EMAC_ALL | PIN_PHY_PD | PIN_PHY_IRQ;
+    piob->select_a = PIN_EMAC_ALL;
+    piob->pullup_enable = PIN_EMAC_ALL | PIN_PHY_IRQ;
+    piob->pullup_disable = PIN_LPBK | PIN_ISOLATE | PIN_RMII_MODE;
+    piob->output_disable = PIN_EMAC_ALL;
+
+        /* PHY PD becomes output and high (no powerdown mode */
+    piob->data_set = PIN_PHY_PD;
+    piob->output_enable = PIN_PHY_PD;
+
+    thread_sleep(30);
+    
+    dprintf("emac_init() - reset phy\n");
+
+        /* assert the RST line and wait until the it deasserts */
+    rstc->CR = RSTC_KEY | RSTC_EXTRST;
+    while(rstc->SR & RSTC_NRSTL) ;
+
+    thread_sleep(30);
+    
+        /* after reset all the gpios are assigned to the EMAC,
+           except for PHY_PD (which remains output and high) */
+    piob->pio_disable = PIN_EMAC_ALL;
+
+    emac->USRIO = USRIO_CLKEN;
+    
+    thread_sleep(1000);
+    
+    dprintf("emac_init() - read state\n");
+    
+    emac->NCR = NCR_MPE;
+    emac->NCFG = NCFG_CLK_d64;
+
+    dprintf("bcr = %x\n", mi_rd(emac, MII_REG_BCR));
+    dprintf("id1 = %x\n", mi_rd(emac, MII_REG_PHY_ID1));
+    dprintf("id2 = %x\n", mi_rd(emac, MII_REG_PHY_ID2));
+
+#if 0
+    unsigned state, last;
+    last = 0xff;
+    
+    for(;;) {
+        state = mi_rd(emac, MII_REG_100TX_PHY) & MII_100TX_MODE_MASK;
+        if(last != state) {
+            last = state;
+            char *name;
+            switch(state) {
+            case MII_100TX_MODE_AUTO:
+                name = "auto negotiate";
+                break;
+            case MII_100TX_MODE_10T_H:
+                name = "10-T half duplex";
+                break;
+            case MII_100TX_MODE_10T_F:
+                name = "10-T full duplex";
+                break;
+            case MII_100TX_MODE_100TX_H:
+                name = "100-TX half duplex";
+                break;
+            case MII_100TX_MODE_100TX_F:
+                name = "100-TX full duplex";
+                break;
+            case MII_100TX_MODE_ISOLATE:
+                name = "isolate";
+                break;
+            default:
+                name = "unknown";
+            }
+            dprintf("link state: %s\n", name);
+        }
+        thread_sleep(100);
+    } 
+#endif
+
+    emac_init_send();
+    
+    return 0;
+}
+
+#define XMIT_ENTRY_COUNT 32
+static emac_xmit_entry xmit_list[XMIT_ENTRY_COUNT];
+static unsigned xmit_next = 0;
+static mutex_t xmit_lock;
+
+void emac_init_send(void)
+{
+    AT91EMAC *emac = AT91EMAC_ADDR;
+    int i;
+
+    for(i = 0; i < XMIT_ENTRY_COUNT; i++) {
+        xmit_list[i].info = XMIT_USED;
+        xmit_list[i].addr = 0;
+    }
+    xmit_list[i-1].info |= XMIT_LAST;
+
+    emac->NCFG = NCFG_CLK_d64 | NCFG_SPD | NCFG_FD;
+    emac->NCR = NCR_TE | NCR_MPE;
+    emac->TBQP = (unsigned) xmit_list;
+
+    mutex_init(&xmit_lock);
+}
+
+int ethernet_send(void *data, unsigned len)
+{
+    AT91EMAC *emac = AT91EMAC_ADDR;
+
+    emac_xmit_entry *xe;
+    int waited = 0;
+
+    mutex_acquire(&xmit_lock);
+    
+    xe = xmit_list + xmit_next;
+
+    while(!(xe->info & XMIT_USED)) {
+        thread_yield();
+        waited++;
+    }
+
+    if(waited) dprintf("W%d\n",waited);
+    
+    if(xe->addr != 0) {
+        free((void*) xe->addr);
+    }
+
+    xe->addr = (unsigned) data;
+    if(xmit_next == (XMIT_ENTRY_COUNT - 1)) {
+        xe->info = XMIT_LENGTH(len) | XMIT_LAST | XMIT_WRAP;
+        xmit_next = 0;
+    } else {
+        xe->info = XMIT_LENGTH(len) | XMIT_LAST;
+        xmit_next++;
+    }
+
+    emac->NCR |= NCR_TSTART;
+
+    mutex_release(&xmit_lock);
+
+    return 0;
+}
+
diff --git a/platform/at91sam7/include/platform/at91sam7.h b/platform/at91sam7/include/platform/at91sam7.h
new file mode 100644
index 0000000..cd5a50f
--- /dev/null
+++ b/platform/at91sam7/include/platform/at91sam7.h
@@ -0,0 +1,794 @@
+/* at91sam7s.h -- AT91SAM7S hardware definitions
+**
+** Copyright 2006, Brian Swetland.  All rights reserved.
+** See provided LICENSE file or http://frotz.net/LICENSE for details.
+*/
+
+#ifndef __PLATFORM_AT91SAM7_H__ 
+#define __PLATFORM_AT91SAM7_H__
+
+#if !defined(AT91_SAM7X) && !defined(AT91_SAM7S)
+#error Unspecified Architecture - AT91SAM7S or AT91SAM7X must be defined
+#endif
+
+/* peripheral ids */
+#define PID_AIC_FIQ    0
+#define PID_SYSIRQ     1
+#define PID_PIOA       2
+#define PID_USART0     6
+#define PID_USART1     7
+#define PID_SSC        8
+#define PID_TWI        9
+#define PID_PWMC       10
+#define PID_UDP        11
+#define PID_TC0        12
+#define PID_TC1        13
+#define PID_TC2        14
+#if AT91_SAM7X
+#define PID_PIOB       3
+#define PID_SPI0       4
+#define PID_SPI1       5
+#define PID_CAN        15
+#define PID_EMAC       16
+#define PID_ADC        17
+#define PID_AIC_IRQ0   30
+#define PID_AIC_IRQ1   31
+#else
+#define PID_ADC        4
+#define PID_SPI0       5
+#define PID_AIC_IRQ    30
+#endif
+
+#define BASE_FLASH     0x00100000
+#define BASE_SRAM      0x00200000
+#define BASE_TC        0xFFFA0000
+#define BASE_UDP       0xFFFB0000
+#define BASE_TWI       0xFFFB8000
+#define BASE_USART0    0xFFFC0000
+#define BASE_USART1    0xFFFC4000
+#define BASE_PWMC      0xFFFCC000
+#define BASE_SSC       0xFFFD4000
+#define BASE_ADC       0xFFFD8000
+#define BASE_SPI0      0xFFFE0000
+
+#define BASE_AIC       0xFFFFF000
+#define BASE_DBGU      0xFFFFF200
+#define BASE_PIOA      0xFFFFF400
+#define BASE_PMC       0xFFFFFC00
+#define BASE_RSTC      0xFFFFFD00
+#define BASE_RTT       0xFFFFFD20
+#define BASE_PIT       0xFFFFFD30
+#define BASE_WDT       0xFFFFFD40
+#define BASE_VREG      0xFFFFFD60
+#define BASE_MC        0xFFFFFF00
+
+#if AT91_SAM7X
+#define BASE_CAN       0xFFFD0000
+#define BASE_EMAC      0xFFFDC000
+#define BASE_SPI1      0xFFFE4000
+#define BASE_PIOB      0xFFFFF600
+#endif
+
+
+typedef volatile unsigned int vu4;
+
+typedef struct
+{
+    vu4 MR;
+    vu4 SR;
+    vu4 PIVR;
+    vu4 PIIR;
+} AT91PIT;
+
+/* MR */
+#define PIT_PITEN     (1 << 24)
+#define PIT_PITIEN    (1 << 25)
+
+/* SR */
+#define PIT_PITS      (1)
+
+/* PIxR */
+#define PIT_PICNT(x)   (x >> 20)
+#define PIT_CPIV(x)    (x & 0x000fffff)
+
+#define AT91PIT_ADDR ((AT91PIT*) BASE_PIT)
+
+typedef struct
+{
+    vu4 CR;
+    vu4 MR;
+    vu4 IER;
+    vu4 IDR;
+    vu4 IMR;
+    vu4 SR;
+    vu4 RHR;
+    vu4 THR;
+    vu4 BRGR;
+    vu4 __0[7];
+    vu4 CIDR;
+    vu4 EXID;
+    vu4 FNR;
+} AT91DBGU;
+
+/* CR bits */
+#define DBGU_RSTRX       0x00000004
+#define DBGU_RSTTX       0x00000008
+#define DBGU_RXEN        0x00000010
+#define DBGU_RXDIS       0x00000020
+#define DBGU_TXEN        0x00000040
+#define DBGU_TXDIS       0x00000080
+#define DBGU_RSTSTA      0x00000100
+
+/* MR bits */
+#define DBGU_PAR_EVEN    0x00000000
+#define DBGU_PAR_ODD     0x00000200
+#define DBGU_PAR_SPACE   0x00000400
+#define DBGU_PAR_MARK    0x00000600
+#define DBGU_PAR_NONE    0x00000800
+
+#define DBGU_MODE_NORMAL 0x00000000
+#define DBGU_MODE_ECHO   0x0000C000
+#define DBGU_MODE_LLOOP  0x00008000
+#define DBGU_MODE_RLOOP  0x00004000
+
+/* IER, IDR, IMR, and SR bits */
+#define DBGU_RXRDY       0x00000001
+#define DBGU_TXRDY       0x00000002
+#define DBGU_ENDRX       0x00000008
+#define DBGU_ENDTX       0x00000010
+#define DBGU_OVRE        0x00000020
+#define DBGU_FRAME       0x00000040
+#define DBGU_PARE        0x00000080
+#define DBGU_TXEMPTY     0x00000200
+#define DBGU_TXBUFE      0x00000800
+#define DBGU_RXBUFF      0x00001000
+#define DBGU_COMMTX      0x40000000
+#define DBGU_COMMRX      0x80000000
+
+#define AT91DBGU_ADDR ((AT91DBGU*) BASE_DBGU)
+    
+typedef struct 
+{
+    vu4 pio_enable;
+    vu4 pio_disable;
+    vu4 pio_status;
+    vu4 __0;
+    vu4 output_enable;
+    vu4 output_disable;
+    vu4 output_status;
+    vu4 __1;
+    vu4 filter_enable;
+    vu4 filter_disable;
+    vu4 filter_status;
+    vu4 __2;
+    vu4 data_set;
+    vu4 data_clear;
+    vu4 data_status;
+    vu4 pin_status;
+    vu4 irq_enable;
+    vu4 irq_disable;
+    vu4 irq_mask;
+    vu4 irq_status;
+    vu4 multidriver_enable;
+    vu4 multidriver_disable;
+    vu4 multidriver_status;
+    vu4 __3;
+    vu4 pullup_disable;
+    vu4 pullup_enable;
+    vu4 pullup_status;
+    vu4 __4;
+    vu4 select_a;
+    vu4 select_b;
+    vu4 select_status;
+    vu4 __5[9];
+    vu4 write_enable;
+    vu4 write_disable;
+    vu4 write_status;
+} AT91PIO;    
+
+#define AT91PIOA_ADDR ((AT91PIO*) BASE_PIOA)
+#if AT91_SAM7X
+#define AT91PIOB_ADDR ((AT91PIO*) BASE_PIOB)
+#endif
+
+typedef struct 
+{
+    vu4 SCER;
+    vu4 SCDR;
+    vu4 SCSR;
+    vu4 __0;
+    vu4 PCER;
+    vu4 PCDR;
+    vu4 PCSR;
+    vu4 __1;
+    vu4 MOR;
+    vu4 MCFR;
+    vu4 __2;
+    vu4 PLLR;
+    vu4 MCKR;
+    vu4 __3[2];
+    vu4 PCK0;
+    vu4 PCK1;
+    vu4 PCK2;
+} AT91PMC;
+
+#define AT91PMC_ADDR ((AT91PMC*) BASE_PMC)
+
+/* PMC_SCER/SCDR */
+#define PMC_PCK      0x00000001
+#define PMC_UDP      0x00000080
+#define PMC_PCK0     0x00000100
+#define PMC_PCK1     0x00000200
+#define PMC_PCK2     0x00000400
+
+typedef struct 
+{
+    vu4 CR;
+    vu4 MR;
+    vu4 RDR;
+    vu4 TDR;
+    vu4 SR;
+    vu4 IER;
+    vu4 IDR;
+    vu4 IMR;
+    vu4 __0[4];
+    vu4 CSR0;
+    vu4 CSR1;
+    vu4 CSR2;
+    vu4 CSR3;
+} AT91SPI;
+
+#define AT91SPI0_ADDR ((AT91SPI*) BASE_SPI0)
+#if AT91_SAM7X
+#define AT91SPI1_ADDR ((AT91SPI*) BASE_SPI0)
+#endif
+
+/* CR bits */
+#define SPI_SPIEN         0x00000001
+#define SPI_SPIDIS        0x00000002
+#define SPI_SWRST         0x00000080
+#define SPI_LASTXFER      0x01000000
+
+/* MR bits */
+#define SPI_MSTR          0x00000001
+#define SPI_PS            0x00000002
+#define SPI_PCSDEC        0x00000004
+#define SPI_MODFDIS       0x00000010
+#define SPI_LLB           0x00000080
+#define SPI_DLYBCS(n)     (((n) & 0xff) << 24)
+#define SPI_PCS0          0x000e0000
+#define SPI_PCS1          0x000d0000
+#define SPI_PCS2          0x000b0000
+#define SPI_PCS3          0x00070000
+
+/* SR bits */
+#define SPI_RDRF          0x00000001 /* recv data reg full */
+#define SPI_TDRE          0x00000002 /* xmit data reg empty */
+#define SPI_MODF          0x00000004 /* mode fault error */
+#define SPI_OVRES         0x00000008 /* overrun error */
+#define SPI_ENDRX         0x00000010 /* end of rx buffer */
+#define SPI_ENDTX         0x00000020 /* end of tx buffer */
+#define SPI_RXBUFF        0x00000040 /* rx buffer full */
+#define SPI_TXBUFE        0x00000080 /* tx buffer empty */
+#define SPI_NSSR          0x00000100 /* rising edge on NSS */
+#define SPI_TXEMPTY       0x00000200 /* transmission regs empty */
+#define SPI_SPIENS        0x00010000
+
+typedef struct 
+{
+    vu4 FRM_NUM;
+    vu4 GLB_STAT;
+    vu4 FADDR;
+    vu4 __0;
+    vu4 IER;
+    vu4 IDR;
+    vu4 IMR;
+    vu4 ISR;
+    vu4 ICR;
+    vu4 __1;
+    vu4 RST_EP;
+    vu4 __2;
+    vu4 CSR0;
+    vu4 CSR1;
+    vu4 CSR2;
+    vu4 CSR3;
+    vu4 __3[4];
+    vu4 FDR0;
+    vu4 FDR1;
+    vu4 FDR2;
+    vu4 FDR3;
+    vu4 __4[5];
+    vu4 TXVC;
+} AT91UDP;
+
+#define AT91UDP_ADDR ((AT91UDP*) BASE_UDP)
+
+// GLB_STAT bits
+#define UDP_FADDEN    0x00000001
+#define UDP_CONFG     0x00000002
+#define UDP_ESR       0x00000004
+#define UDP_RSMINPR   0x00000008
+#define UDP_RMWUPE    0x00000010
+
+// FADDR bits
+#define UDP_FEN       0x00000100
+
+// interrupt bits
+#define UDP_EP0INT    0x00000001
+#define UDP_EP1INT    0x00000002
+#define UDP_EP2INT    0x00000004
+#define UDP_EP3INT    0x00000008
+#define UDP_RXSUSP    0x00000100
+#define UDP_RXRSM     0x00000200
+#define UDP_EXTRSM    0x00000400
+#define UDP_SOFINT    0x00000800
+#define UDP_ENDBUSRES 0x00001000
+#define UDP_WAKEUP    0x00002000
+
+// RST_EP bits
+#define UDP_EP0       0x00000001
+#define UDP_EP1       0x00000002
+#define UDP_EP2       0x00000004
+#define UDP_EP3       0x00000008
+
+// CSR bits
+#define UDP_TXCOMP         0x00000001
+#define UDP_RX_DATA_BK0    0x00000002
+#define UDP_RXSETUP        0x00000004
+#define UDP_STALLSENT      0x00000008
+#define UDP_ISOERROR       0x00000008
+#define UDP_TXPKTRDY       0x00000010
+#define UDP_FORCESTALL     0x00000020
+#define UDP_RX_DATA_BK1    0x00000040
+#define UDP_DIR            0x00000080
+
+#define UDP_DTGL           0x00000800
+#define UDP_EPEDS          0x00008000
+
+#define UDP_TYPE_CONTROL     0x00000000
+#define UDP_TYPE_ISOCH_OUT   0x00000100
+#define UDP_TYPE_BULK_OUT    0x00000200
+#define UDP_TYPE_INT_OUT     0x00000300
+#define UDP_TYPE_ISOCH_IN    0x00000500
+#define UDP_TYPE_BULK_IN     0x00000600
+#define UDP_TYPE_INT_IN      0x00000700
+
+typedef struct 
+{
+    vu4 SMR[32];
+    vu4 SVR[32];
+    vu4 IVR;
+    vu4 FVR;
+    vu4 ISR;
+    vu4 IPR;
+    vu4 IMR;
+    vu4 CISR;
+    vu4 __0[2];
+    vu4 IECR;
+    vu4 IDCR;
+    vu4 ICCR;
+    vu4 ISCR;
+    vu4 EOICR;
+    vu4 SPU;
+    vu4 DCR;
+    vu4 __1;
+    vu4 FFER;
+    vu4 FFDR;
+    vu4 FFSR;
+} AT91AIC;
+
+#define AT91AIC_ADDR ((AT91AIC*) BASE_AIC)
+
+
+typedef struct 
+{
+    vu4 CR;
+    vu4 MR;
+    vu4 IER;
+    vu4 IDR;
+    vu4 IMD;
+    vu4 CSR;
+    vu4 RHR;
+    vu4 THR;
+    vu4 BRGR;
+    vu4 RTOR;
+    vu4 TTGR;
+    vu4 __0[5];
+    vu4 FIDI;
+    vu4 NER;
+    vu4 __1;
+    vu4 IF;
+    vu4 MAN;
+} AT91USART;
+
+#define AT91USART0_ADDR ((AT91USART*) 0xFFFC0000)
+#define AT91USART1_ADDR ((AT91USART*) 0xFFFC4000)
+
+/* CR */
+#define USART_RSTRX            0x00000004
+#define USART_RSTTX            0x00000008
+#define USART_RXEN             0x00000010
+#define USART_RXDIS            0x00000020
+#define USART_TXEN             0x00000040
+#define USART_TXDIS            0x00000080
+#define USART_RSTSTA           0x00000100
+#define USART_STTBRK           0x00000200
+#define USART_STPBRK           0x00000400
+#define USART_STTTO            0x00000800
+#define USART_SENDA            0x00001000
+#define USART_RSTIT            0x00002000
+#define USART_RSTNACK          0x00004000
+#define USART_RETTO            0x00008000
+#define USART_DTREN            0x00010000
+#define USART_DTRDIS           0x00020000
+#define USART_RTSEN            0x00040000
+#define USART_RTSDIS           0x00080000
+
+/* MR */
+#define USART_MODE_NORMAL      0x00000000
+#define USART_MODE_RS485       0x00000001
+#define USART_MODE_HWHS        0x00000002
+#define USART_MODE_MODEM       0x00000003
+#define USART_MODE_ISO7816T0   0x00000004
+#define USART_MODE_ISO7816T1   0x00000006
+#define USART_MODE_IRDA        0x00000008
+
+#define USART_CLK_MCK          0x00000000
+#define USART_CLK_MCK_DIV      0x00000010
+#define USART_CLK_SCK          0x00000030
+
+#define USART_CHRL_5BITS       0x00000000
+#define USART_CHRL_6BITS       0x00000040
+#define USART_CHRL_7BITS       0x00000080
+#define USART_CHRL_8BITS       0x000000C0
+
+#define USART_SYNCHRONOUS      0x00000100
+
+#define USART_PARITY_EVEN      0x00000000
+#define USART_PARITY_ODD       0x00000200
+#define USART_PARITY_SPACE     0x00000400
+#define USART_PARITY_MARK      0x00000600
+#define USART_PARITY_NONE      0x00000800
+#define USART_PARITY_MULTIDROP 0x00000C00
+
+#define USART_1STOP            0x00000000
+#define USART_1X5STOP          0x00001000
+#define USART_2STOP            0x00002000
+
+#define USART_CHMODE_NORMAL    0x00000000
+#define USART_CHMODE_ECHO      0x00004000
+#define USART_CHMODE_LLOOP     0x00008000
+#define USART_CHMODE_RLOOP     0x0000C000
+
+#define USART_MSBF             0x00010000
+#define USART_MODE9            0x00020000
+#define USART_CLKO             0x00040000
+#define USART_OVER             0x00080000
+#define USART_INACK            0x00100000
+#define USART_DSNACK           0x00200000
+#define USART_VAR_SYNC         0x00400000
+
+#define USART_FILTER           0x10000000
+#define USART_MAN              0x20000000
+#define USART_ONEBIT           0x80000000
+
+/* CSR */
+#define USART_RXRDY            0x00000001
+#define USART_TXRDY            0x00000002
+#define USART_RXBRK            0x00000004
+#define USART_ENDRX            0x00000008
+#define USART_ENDTX            0x00000010
+#define USART_OVRE             0x00000020
+#define USART_FRAME            0x00000040
+#define USART_PARE             0x00000080
+#define USART_TIMEOUT          0x00000100
+#define USART_TXEMPTY          0x00000200
+#define USART_ITERATION        0x00000400
+#define USART_TXBUFE           0x00000800
+#define USART_RXBUFF           0x00001000
+#define USART_NACK             0x00002000
+
+
+typedef struct 
+{
+    vu4 CR;
+    vu4 SR;
+    vu4 MR;
+} AT91RSTC;
+
+#define RSTC_KEY               0xA5000000
+
+/* cr */
+#define RSTC_PROCRST           0x00000001
+#define RSTC_PERRST            0x00000004
+#define RSTC_EXTRST            0x00000008
+
+/* sr */
+#define RSTC_URSTS             0x00000001
+#define RSTC_BODSTS            0x00000002
+#define RSTC_RSTTYP_MASK       0x00000070
+#define RSTC_RSTTYP_COLD       0x00000000
+#define RSTC_RSTTYP_WATCHDOG   0x00000020
+#define RSTC_RSTTYP_SOFTWARE   0x00000030
+#define RSTC_RSTTYP_NRST_PIN   0x00000040
+#define RSTC_RSTTYP_BROWNOUT   0x00000060
+#define RSTC_NRSTL             0x00010000
+#define RSTC_SRCMP             0x00020000
+
+/* mr */
+#define RSTC_URSTEN            0x00000001
+#define RSTC_URSTIEN           0x00000010
+#define RSTC_ERSTL(n)          (((n) & 0xf) << 8)
+#define RSTC_BODIEN            0x00010000
+
+#define AT91RSTC_ADDR ((AT91RSTC*) BASE_RSTC)
+    
+#if AT91_SAM7X
+
+typedef struct
+{
+    vu4 NCR;
+    vu4 NCFG;
+    vu4 NSR;
+    vu4 __0;
+    
+    vu4 __1;
+    vu4 TSR;
+    vu4 RBQP;
+    vu4 TBQP;
+    
+    vu4 RSR;
+    vu4 ISR;
+    vu4 IER;
+    vu4 IDR;
+    
+    vu4 IMR;
+    vu4 MAN;
+    vu4 PTR;
+    vu4 PFR;
+    
+    vu4 FTO;
+    vu4 SCF;
+    vu4 MCF;
+    vu4 FRO;
+    
+    vu4 FCSE;
+    vu4 ALE;
+    vu4 DTF;
+    vu4 LCOL;
+    
+    vu4 ECOL;
+    vu4 TUND;
+    vu4 CSE;
+    vu4 RRE;
+    
+    vu4 ROV;
+    vu4 RSE;
+    vu4 ELE;
+    vu4 RJA;
+    
+    vu4 USF;
+    vu4 STE;
+    vu4 RLE;
+    vu4 __2;
+    
+    vu4 HRB;
+    vu4 HRT;
+    vu4 SA1B;
+    vu4 SA1T;
+    
+    vu4 SA2B;
+    vu4 SA2T;
+    vu4 SA3B;
+    vu4 SA3T;
+    
+    vu4 SA4B;
+    vu4 SA5T;
+    vu4 TID;
+    vu4 __3;
+    
+    vu4 USRIO;
+} AT91EMAC;
+
+
+#define NCR_LB        0x00000001
+#define NCR_LLB       0x00000002
+#define NCR_RE        0x00000004
+#define NCR_TE        0x00000008
+#define NCR_MPE       0x00000010
+#define NCR_CLRSTAT   0x00000020
+#define NCR_INCSTAT   0x00000040
+#define NCR_WESTAT    0x00000080
+#define NCR_BP        0x00000100
+#define NCR_TSTART    0x00000200
+#define NCR_THALT     0x00000400
+
+#define NCFG_SPD      0x00000001
+#define NCFG_FD       0x00000002
+#define NCFG_JFRAME   0x00000008
+#define NCFG_CAF      0x00000010
+#define NCFG_NBC      0x00000020
+#define NCFG_MTI      0x00000040
+#define NCFG_UNI      0x00000080
+#define NCFG_BIG      0x00000100
+#define NCFG_CLK_d8   0x00000000
+#define NCFG_CLK_d16  0x00000400
+#define NCFG_CLK_d32  0x00000800
+#define NCFG_CLK_d64  0x00000C00
+#define NCFG_RTY      0x00001000
+#define NCFG_PAE      0x00002000
+#define NCFG_RBOF_0   0x00000000
+#define NCFG_RBOF_1   0x00004000
+#define NCFG_RBOF_2   0x00008000
+#define NCFG_RBOF_3   0x0000C000
+#define NCFG_RLCE     0x00010000
+#define NCFG_DRFCS    0x00020000
+#define NCFG_EFRHD    0x00040000
+#define NCFG_IRXFCS   0x00080000
+
+#define NSR_MDIO      0x00000002
+#define NSR_IDLE      0x00000004
+
+#define TSR_UBR       0x00000001
+#define TSR_COL       0x00000002
+#define TSR_RLE       0x00000004
+#define TSR_TGO       0x00000008
+#define TSR_BEX       0x00000010
+#define TSR_COMP      0x00000020
+#define TSR_UND       0x00000040
+
+#define RSR_BNA       0x00000001
+#define RSR_REC       0x00000002
+#define RSR_OVR       0x00000004
+
+#define ISR_MFD       0x00000001
+#define ISR_RCOMP     0x00000002
+#define ISR_RXUBR     0x00000004
+#define ISR_TXUBR     0x00000008
+#define ISR_TUND      0x00000010
+#define ISR_RLE       0x00000020
+#define ISR_TXERR     0x00000040
+#define ISR_TCOMP     0x00000080
+#define ISR_ROVR      0x00000400
+#define ISR_HRESP     0x00000800
+#define ISR_PFR       0x00001000
+#define ISR_PTZ       0x00002000
+
+#define USRIO_RMII    0x00000001
+#define USRIO_CLKEN   0x00000002
+
+#define AT91EMAC_ADDR ((AT91EMAC*) BASE_EMAC)
+
+
+typedef struct 
+{
+    vu4 addr;
+    vu4 info;
+} emac_xmit_entry;
+
+#define XMIT_USED           0x80000000
+#define XMIT_WRAP           0x40000000
+#define XMIT_ERR_RETRY      0x20000000
+#define XMIT_ERR_UNDERRUN   0x10000000
+#define XMIT_ERR_EXHAUSTED  0x08000000
+#define XMIT_NO_CRC         0x00010000
+#define XMIT_LAST           0x00008000
+#define XMIT_LENGTH(n)      ((n) & 0x3FF)
+
+
+/* CAN Registers */
+
+
+typedef struct
+{
+    vu4 MMR;		/* Mailbox Mode Register */
+    vu4 MAM;		/* Mailbox Acceptance Mask Register */
+    vu4 MID;		/* Mailbox ID Register */
+    vu4 MFID;		/* Mailbox Family ID Register */
+    vu4 MSR;		/* Mailbox Status Register */
+    vu4 MDL;		/* Mailbox Data Low Register */
+    vu4 MDH;		/* Mailbox Data High Register */
+    vu4 MCR;		/* Mailbox Control Register */
+}  AT91CAN_MAILBOX;
+
+typedef struct
+{
+    vu4 MR;		/* Mode Register */
+    vu4 IER;		/* Interrupt Enable Register */
+    vu4 IDR;		/* Interrupt Disable Register */
+    vu4 IMR;		/* Interrupt Mask Register */
+    vu4 SR;		/* Status Register */
+    vu4 BR;		/* Baudrate Register */
+    vu4 TIM;		/* Timer Register */
+    vu4 TIMESTP;	/* Timestamp Register */
+    vu4 ECR;		/* Error Counter Register */
+    vu4 TCR;		/* Transfer Command Register */
+    vu4 ACR;		/* Abort Command Register */
+    	
+    vu4 __0[53];	/* 0x002c - 0x0100 is undefined */
+    vu4 __1[63];	/* 0x0200 - 0x01fc is reserved */
+    AT91CAN_MAILBOX Mailbox[8];
+} AT91CAN;
+
+#define CAN_CANEN      0x00000001      /* CAN Controller Enable */
+#define CAN_LPM        0x00000002      /* Enable Low Power Mode */
+#define CAN_ABM        0x00000004      /* Enable Autoband/Listen Mode */
+#define CAN_OVL        0x00000008      /* Enable Overload Frame */
+#define CAN_TEOF       0x00000010      /* Timestamp Messages at each Frame */
+#define CAN_TTM        0x00000020      /* Enable Time Trigger Mode */
+#define CAN_TIMFRZ     0x00000040      /* Enable Timer Freeze */
+#define CAN_DRPT       0x00000080      /* Disable Repeat */
+
+#define CAN_MB(x)    (0x00000001 << x) /* Enable Interrupt Enable */
+#define CAN_ERRA      0x00010000      /* Enable Error Active Mode Interrupt */
+#define CAN_WARN      0x00020000      /* Enable Warning Limit Interrupt */
+#define CAN_ERRP      0x00040000      /* Enable Passive mode interrupt */
+#define CAN_BOFF      0x00080000      /* Enable Bus-off mode interrupt */
+#define CAN_SLEEP     0x00100000      /* Enable Sleep Interrupt */
+#define CAN_WAKEUP    0x00200000      /* Enable Wakeup Interrupt */
+#define CAN_TOVF      0x00400000      /* Enable Timer Overflow Interrupt */
+#define CAN_TSTP      0x00800000      /* Enable TimeStamp Interrupt */
+#define CAN_CERR      0x01000000      /* Enable CRC Error Interrupt */
+#define CAN_SERR      0x02000000      /* Enable Stuffing Error Interrupt */
+#define CAN_AERR      0x04000000      /* Enable Acknowledgement Error Int */
+#define CAN_FERR      0x08000000      /* Enable Form Error Interrupt */
+#define CAN_BERR      0x10000000      /* Enable Bit Error Interrupt */
+
+#define CAN_RBSY      0x20000000      /* Receiver Busy */
+#define CAN_TBSY      0x40000000      /* Transmitter Busy */
+#define CAN_OVLSY     0x80000000      /* Overload Busy */
+
+/* Can Baudrate Regiister */
+
+#define CAN_PHASE2(x)	(x)
+#define CAN_PHASE2_MASK	0x07
+#define CAN_PHASE1(x)	(x<<4)
+#define CAN_PHASE1_MASK	(0x07 << 4)
+#define CAN_PROPAG(x)	(x<<8)
+#define CAN_PROPAG_MASK	(0x07 << 8)
+#define CAN_SJW(x)	(x<<12)
+#define CAN_SJW_MASK(x)	(0x03 << 12)
+#define CAN_BRP(x)	(x<<16)
+#define CAN_BRP_MASK	(0x7f << 16)
+#define CAN_SMP	     0x01000000	     /* Sampling Mode */
+
+/* CAN Transfer Command Register */
+
+#define TCR_TIMRST   0x80000000	     /* Timer Reset */
+
+/* CAN Message Mode Register */
+
+#define CAN_MTIMEMARK(x)   (0x0000001 << x)
+#define CAN_PRIOR(x)	(x << 16)
+#define CAN_MOT(x)	(x << 24)
+
+#define CAN_MIDVB(x)	(x)
+#define CAN_MIDVA(x)	(x << 18)
+#define CAN_MIDE	0x20000000
+
+
+/* CAN MSRx */
+
+/* These are receive, so pass in the value of the register... */
+
+#define CAN_MTIMESTAMP(x)  (x & 0x0000ffff)
+#define CAN_MDLC(x)	   ( (x >> 16) & 0x0f)  /* Mailbox code length */
+#define CAN_MRTR	0x00100000              /* Mailbox Remote Trx Request*/
+#define CAN_MABT	0x00400000              /* Mailbox Message Abort  */
+#define CAN_MRDY	0x00800000              /* Mailbox Ready */
+#define CAN_MMI 	0x01000000              /* Mailbox Message Ignored */
+
+/* Message Control Register */
+
+//#define CAN_MDLC(x)	(x<<16)	        /* Mailbox Data Length Code */
+#define CAN_MACR	(0x01 << 22)	/* Abort Request */
+#define CAN_MTCR	(0x01 << 23)	/* Mailbox Transfer Command */
+
+
+#define AT91CAN_ADDR ((AT91CAN*) BASE_CAN)
+
+
+
+#endif
+
+#endif
diff --git a/platform/at91sam7/init_clock.S b/platform/at91sam7/init_clock.S
new file mode 100644
index 0000000..2de137f
--- /dev/null
+++ b/platform/at91sam7/init_clock.S
@@ -0,0 +1,101 @@
+/* init_clock.S -- AT91SAM7 clock coldstart code
+**
+** Copyright 2006, Brian Swetland.  All rights reserved.     
+** See provided LICENSE file or http://frotz.net/LICENSE for details.
+*/
+
+.globl init_clock
+
+init_clock:
+/* init flash controller timing for 18.432MHz */
+	mov r1, #0xffffff00
+	ldr r0, =0x00340100
+	str r0, [r1, #0x60]
+
+#define PMC_MOR    0x20
+#define PMC_MCFR   0x24
+#define PMC_PLLR   0x2c
+#define PMC_MCKR   0x30
+#define PMC_SR     0x68
+		
+/* PMC_MOR */
+#define PMC_MOSCEN     0x01
+#define PMC_OSCBYPASS  0x02
+
+/* PMC_MCFR */
+#define PMC_MAINRDY	   0x00010000
+
+/* PMC_SR */
+#define PMC_MOSCS      0x01
+#define PMC_LOCK       0x04
+#define PMC_MCKRDY     0x08
+
+/* PMC_MCKR */
+#define PMC_CSS_SLOW   0x00
+#define PMC_CSS_MAIN   0x01
+#define PMC_CSS_PLL    0x03
+#define PMC_PRES_NONE  0x00
+#define PMC_PRES_DIV2  0x04
+#define PMC_PRES_DIV4  0x08
+
+/* Oscillator Init Sequence based on the Atmel sample code
+** in cstartup_boot_SAM7S32_64.s  
+**
+** I cleaned it up a bit -- why they use a temporary register,
+** AND and then CMP instead of just TSTing against an immediate
+** boggles my mind.  I think this could be a bit simpler yet, 
+** but debugging it is a pain, so Good Enough wins for now.
+*/
+	ldr r1, =0xfffffc00
+
+/* bypass main oscillator */
+	mov r0, #PMC_OSCBYPASS
+	str r0, [r1, #PMC_MOR]
+
+/* compensate MAINRDY rising flag (45 SCLK) */
+	mov r0, #45
+1:	subs r0, r0, #1
+	bhi 1b
+
+/* if MAINRDY is set, we have an external oscillator */
+	ldr r0, [r1, #PMC_MCFR]
+	tst r0, #PMC_MAINRDY
+	bne ext_osc_found
+
+/* reset MOSCS flag */
+	mov r0, #0
+	str r0, [r1, #PMC_MOR]
+
+/* enable main oscillator */
+	ldr r0, =((0x40 << 8) | PMC_MOSCEN)
+	str r0, [r1, #PMC_MOR]
+
+/* wait for main oscillator to come online */
+1:	ldr r0, [r1, #PMC_SR]
+	tst r0, #PMC_MOSCS
+	beq 1b
+
+ext_osc_found:
+/* select main oscillator, no prescaler for MCK */
+	mov r0, #(PMC_CSS_MAIN | PMC_PRES_NONE)
+	str r0, [r1, #PMC_MCKR]
+
+/* wait until MCK settles to continue */
+1:	ldr r0, [r1, #PMC_SR]
+	tst r0, #PMC_MCKRDY
+	beq 1b
+
+/* this is a bit of voodoo for selecting a 96.109MHz PLL
+** freq (MUL=72, DIV=14, OUT=0, USBDIV=/1) from the 18.432MHz
+** main clock.
+*/
+	ldr r0, =0x10483f0e
+	str r0, [r1, #PMC_PLLR]
+
+/* let the PLL lock before we continue */
+1:	ldr r0, [r1, #PMC_SR]
+	tst r0, #PMC_LOCK
+	beq 1b
+
+	mov pc, lr
+
diff --git a/platform/at91sam7/init_clock_48mhz.S b/platform/at91sam7/init_clock_48mhz.S
new file mode 100644
index 0000000..a5bf961
--- /dev/null
+++ b/platform/at91sam7/init_clock_48mhz.S
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+.globl init_48mhz_clock
+
+#define PMC_MCKR   0x30
+#define PMC_SR     0x68
+
+#define PMC_MCKRDY     0x08
+#define PMC_PRES_DIV2  0x04
+#define PMC_CSS_PLL    0x03
+
+/* BUG?
+**
+** If I try to exit by bx lr, lr is corrupted somewhere in here.
+** No clue why.  FIQ USB wedge not playing nice?  Am I cheating
+** with my CPSR calls?
+*/
+init_48mhz_clock:
+	ldr r1, =0xfffffc00
+	mov r2, lr
+		
+	// turn on /2 prescaler
+	mov r0, #PMC_PRES_DIV2
+	str r0, [r1, #PMC_MCKR]
+wait_for_clock1:
+	ldr r0, [r1, #PMC_SR]
+	tst r0, #PMC_MCKRDY
+	beq wait_for_clock1
+
+	// switch to pll clock
+	mov r0, #(PMC_PRES_DIV2 | PMC_CSS_PLL)
+	str r0, [r1, #PMC_MCKR]
+wait_for_clock2:
+	ldr r0, [r1, #PMC_SR]
+	tst r0, #PMC_MCKRDY
+	beq wait_for_clock2
+
+	bx r2
diff --git a/platform/at91sam7/interrupts.c b/platform/at91sam7/interrupts.c
new file mode 100644
index 0000000..6c08ef9
--- /dev/null
+++ b/platform/at91sam7/interrupts.c
@@ -0,0 +1,114 @@
+/*
+ * 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 <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/at91sam7.h>
+#include <arch/arm.h>
+
+static int do_nothing()
+{
+    return INT_NO_RESCHEDULE;
+}
+
+void platform_init_interrupts(void)
+{
+    AT91AIC *aic = AT91AIC_ADDR;
+    int n;
+
+    for(n = 0; n < 31; n++) {
+        aic->SVR[n] = (unsigned) do_nothing;
+    }
+    aic->SPU = (unsigned) do_nothing;
+}
+
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+    AT91AIC *aic = AT91AIC_ADDR;
+    
+    if(vector > 31) return ERR_INVALID_ARGS;
+    
+    if(oldstate) {
+        enter_critical_section();
+        *oldstate = aic->IMR & (1 << vector) ? 1 : 0;
+        aic->IDCR = (1 << vector);
+        exit_critical_section();
+    } else {
+        aic->IDCR = (1 << vector);
+    }
+    
+    return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+    AT91AIC *aic = AT91AIC_ADDR;
+    if(vector > 31) return ERR_INVALID_ARGS;
+
+    if(oldstate) {
+        enter_critical_section();
+        *oldstate = aic->IMR & (1 << vector) ? 1 : 0;
+        aic->IECR = (1 << vector);
+        exit_critical_section();
+    } else {
+        aic->IECR = (1 << vector);
+    }
+    
+    return NO_ERROR;
+}
+
+void platform_irq(struct arm_iframe *frame)
+{
+    AT91AIC *aic = AT91AIC_ADDR;
+    int_handler func;
+    enum handler_return ret;
+    
+    inc_critical_section();
+
+    func = (int_handler) aic->IVR;
+//    dprintf("platform_irq() -> %p\n", func);
+
+    ret = func(0);
+    
+    aic->EOICR = (unsigned) aic;
+
+    if(ret == INT_RESCHEDULE) {
+        thread_preempt();
+    }
+
+    dec_critical_section();
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+    AT91AIC *aic = AT91AIC_ADDR;
+    if(vector > 31) return;
+    aic->SVR[vector] = (unsigned) handler;
+}
diff --git a/platform/at91sam7/mkboard.py b/platform/at91sam7/mkboard.py
new file mode 100755
index 0000000..62ce696
--- /dev/null
+++ b/platform/at91sam7/mkboard.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+
+## mkboard.py -- atmel pio mux utility
+##
+## Copyright 2006, Brian Swetland.  All rights reserved.
+## See provided LICENSE file or http://frotz.net/LICENSE for details.
+##
+
+import os, sys, string
+
+# pindef -> num, out, pull, pio, sela, selb
+
+reg_output_disable = 0
+reg_output_enable = 0
+reg_pullup_disable = 0
+reg_pullup_enable = 0
+reg_pio_disable = 0
+reg_pio_enable = 0
+reg_select_a = 0
+reg_select_b = 0
+
+def setup_registers(pindef):
+    global reg_output_disable
+    global reg_output_enable
+    global reg_pullup_disable
+    global reg_pullup_enable
+    global reg_pio_disable
+    global reg_pio_enable
+    global reg_select_a
+    global reg_select_b
+    
+    (num, out, pull, pio, sela, selb) = pindef
+
+    bit = 1 << num
+    
+    if out:
+        reg_output_enable |= bit
+        reg_output_disable &= (~bit)
+    else:
+        reg_output_enable &= (~bit)
+        reg_output_disable |= bit
+
+    if pull:
+        reg_pullup_enable |= bit
+        reg_pullup_disable &= (~bit)
+    else:
+        reg_pullup_enable &= (~bit)
+        reg_pullup_disable |= bit
+
+    if pio:
+        reg_pio_enable |= bit
+        reg_pio_disable &= (~bit)
+    else:
+        reg_pio_enable &= (~bit)
+        reg_pio_disable |= bit
+
+    if sela:
+        reg_select_a |= bit
+    if selb:
+        reg_select_b |= bit
+
+def import_pindef(fn):
+    pass
+
+def read_pins_def(fn, table):
+    output = ""
+    fd = open(fn,'r')
+    for line in fd.xreadlines():
+        line = line.split('#')[0].strip()
+        if not line: continue
+
+        (gpio,pa,pb) = line.split()
+        num = int(gpio[2:])
+
+        table[gpio+"_IN"] = (num, 0, 0, 1, 0, 0)
+        table[gpio+"_IN_PULLUP"] = (num, 0, 1, 1, 0, 0)
+        table[gpio+"_OUT"] = (num, 1, 0, 1, 0, 0)
+        table[gpio+"_"+pa] = (num, 0, 0, 0, 1, 0)
+        table[gpio+"_"+pb] = (num, 0, 0, 0, 0, 1)
+
+    return output
+    
+def read_board_def(fn, table):
+    pins = {}
+    output = ""
+    for n in range(0,32):
+        pins[n] = ''
+        
+    fd = open(fn,'r')
+    for line in fd.xreadlines():
+        line = line.split('#')[0].strip()
+        if not line: continue
+
+        if len(line.split('=')) == 2:
+            (line,func) = line.split('=')
+            line = line.strip()
+            func = func.strip()
+        else:
+            func = ''
+            
+        parts = line.split()
+        if len(parts) < 2:
+            print "ERROR: invalid definition '%s'" % line
+            sys.exit(1)
+
+        if not func:
+            if (parts[1] == 'IN') or (parts[1] == 'OUT'):
+                func = parts[0]
+            else:
+                func = parts[1]
+            
+        pin = string.join(parts,"_")
+        
+        if not table.has_key(pin):
+            print "ERROR: pin '%s' does not exist" % pin
+            sys.exit(1)
+
+        pindef = table[pin]
+        num = pindef[0]
+        if pins[num]:
+            print "ERROR: pin '%s' conflicts with pin '%s'" % (pin, pins[num])
+            sys.exit(1)
+        pins[num] = pin
+
+        setup_registers(pindef)
+        output += "#define PIN_%-12s (1 << %d)\n" % (func, num)
+
+    return output
+
+table = {}
+output = ""
+    
+for fn in sys.argv[1:]:
+    if fn.endswith('.pins'):
+        if table:
+            print "ERROR: only one pin definition file allowed"
+            sys.exit(1)
+        output = read_pins_def(fn, table)
+        continue
+    
+    if fn.endswith('.def'):
+        if not table:
+            print "ERROR: must specify a pin definition file first"
+            sys.exit(1)
+
+        reg_output_disable = 0xffffffffL
+        reg_output_enable =  0L
+        reg_pullup_disable = 0L
+        reg_pullup_enable =  0xffffffffL
+        reg_pio_disable =    0L
+        reg_pio_enable =     0xffffffffL
+        reg_select_a =       0L
+        reg_select_b =       0L
+            
+        output = read_board_def(fn, table)
+        fd = open(fn[:-4] + ".h", 'w')
+        fd.write("/* DO NOT EDIT -- AUTOGENERATED FROM '%s' */\n\n" % fn)
+        fd.write("#ifndef __BOARD_DEFINITION_FILE__\n")
+        fd.write("#define __BOARD_DEFINITION_FILE__\n\n")
+        fd.write(output)
+        fd.write("\n")
+        fd.write("#define BOARD_OUTPUT_DISABLE 0x%08x\n" % reg_output_disable)
+        fd.write("#define BOARD_OUTPUT_ENABLE  0x%08x\n" % reg_output_enable)
+        fd.write("#define BOARD_PULLUP_DISABLE 0x%08x\n" % reg_pullup_disable)
+        fd.write("#define BOARD_PULLUP_ENABLE  0x%08x\n" % reg_pullup_enable)
+        fd.write("#define BOARD_PIO_DISABLE    0x%08x\n" % reg_pio_disable)
+        fd.write("#define BOARD_PIO_ENABLE     0x%08x\n" % reg_pio_enable)
+        fd.write("#define BOARD_SELECT_A       0x%08x\n" % reg_select_a)
+        fd.write("#define BOARD_SELECT_B       0x%08x\n" % reg_select_b)
+        fd.write("\n#endif\n")
+        fd.close()
+        continue
+
+    print "ERROR: what is '%s'?" % fn
+    sys.exit(1)
+    
+    
+
diff --git a/platform/at91sam7/mux.c b/platform/at91sam7/mux.c
new file mode 100644
index 0000000..7c9d9a6
--- /dev/null
+++ b/platform/at91sam7/mux.c
@@ -0,0 +1,39 @@
+/*
+ * 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 <platform/at91sam7.h>
+#include <platform/mux.h>
+
+void mux_init(void)
+{
+	AT91PIO *pio = AT91PIOA_ADDR;
+
+	pio->output_disable = BOARD_OUTPUT_DISABLE;
+	pio->output_enable = BOARD_OUTPUT_ENABLE;
+	pio->pullup_disable = BOARD_PULLUP_DISABLE;
+	pio->pullup_enable = BOARD_PULLUP_ENABLE;
+	pio->pio_disable = BOARD_PIO_DISABLE;
+	pio->pio_enable = BOARD_PIO_ENABLE;
+	pio->select_a = BOARD_SELECT_A;
+	pio->select_b = BOARD_SELECT_B;
+}
+
diff --git a/platform/at91sam7/platform.c b/platform/at91sam7/platform.c
new file mode 100644
index 0000000..378c06d
--- /dev/null
+++ b/platform/at91sam7/platform.c
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+void emac_init();
+
+void platform_init(void)
+{
+#if AT91_SAM7X
+    emac_init();
+#endif
+}
diff --git a/platform/at91sam7/platform_early.S b/platform/at91sam7/platform_early.S
new file mode 100644
index 0000000..e78e271
--- /dev/null
+++ b/platform/at91sam7/platform_early.S
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+.globl platform_early_init
+platform_early_init:
+	stmdb sp!, {lr}
+		
+/* enable the NRST reset pin */
+	ldr r1, =0xfffffd08
+	ldr r0, =0xa5000401
+	str r0, [r1]
+		
+/* disable watchdog */
+	ldr r1, =0xfffffd44
+	ldr r0, =0x3fff8fff
+	str r0, [r1]
+
+	bl init_clock
+	bl init_48mhz_clock
+
+/* copy the .data section from ROM to RAM */
+	ldr     r0, =__rodata_end
+	ldr     r1, =__data_start
+	ldr     r2, =__bss_start
+__data_loop:
+	cmp     r1, r2
+	ldrlt   r3, [r0], #4
+	strlt   r3, [r1], #4
+	blt     __data_loop
+
+	bl mux_init		
+	bl ser_init
+	bl platform_init_interrupts
+		
+	ldmia sp!, {lr}
+	bx lr
diff --git a/platform/at91sam7/rules.mk b/platform/at91sam7/rules.mk
new file mode 100644
index 0000000..9186ef8
--- /dev/null
+++ b/platform/at91sam7/rules.mk
@@ -0,0 +1,70 @@
+#
+# The TARGET is expected to indicate which *specific* AT91SAM7 chip
+# is being used, since features and memory vary from chip to chip
+#
+#             chip       ram   rom    EMAC  CAN  
+# AT91CHIP := sam7s64    16k   64k    N     N    
+# AT91CHIP := sam7s256   64k   256k   N     N
+# AT91CHIP := sam7x256   64k   256k   Y     Y
+#
+
+# ROMBASE, MEMBASE, and MEMSIZE are required for the linker script
+ROMBASE := 0x0
+MEMBASE := 0x200000
+
+TMP_CFG := bad
+ifeq ($(AT91CHIP), sam7x256)
+DEFINES += AT91_SAM7X=1 
+DEFINES += AT91_RAMSIZE=65536
+DEFINES += AT91_ROMSIZE=262144
+MEMSIZE := 65536
+TMP_CFG := ok
+endif
+ifeq ($(AT91CHIP), sam7s256)
+DEFINES += AT91_SAM7S=1 
+DEFINES += AT91_RAMSIZE=65536
+DEFINES += AT91_ROMSIZE=262144
+MEMSIZE := 65536
+TMP_CFG := ok
+endif
+ifeq ($(AT91CHIP), sam7s64)
+DEFINES += AT91_SAM7S=1 
+DEFINES += AT91_RAMSIZE=16384
+DEFINES += AT91_ROMSIZE=65536
+MEMSIZE := 16384
+TMP_CFG := ok
+endif
+
+ifeq ($(TMP_CFG), bad)
+$(error The AT91SAM7 platform requires AT91CHIP be set by the target)
+endif
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm7tdmi
+
+DEFINES += AT91_MCK_MHZ=48000000
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+OBJS += \
+	$(LOCAL_DIR)/debug.o \
+	$(LOCAL_DIR)/interrupts.o \
+	$(LOCAL_DIR)/platform_early.o \
+	$(LOCAL_DIR)/platform.o \
+	$(LOCAL_DIR)/timer.o \
+	$(LOCAL_DIR)/init_clock.o \
+	$(LOCAL_DIR)/init_clock_48mhz.o \
+	$(LOCAL_DIR)/mux.o \
+	$(LOCAL_DIR)/emac_dev.o
+
+# use a two segment memory layout, where all of the read-only sections 
+# of the binary reside in rom, and the read/write are in memory. The 
+# ROMBASE, MEMBASE, and MEMSIZE make variables are required to be set 
+# for the linker script to be generated properly.
+#
+LINKER_SCRIPT += \
+	$(BUILDDIR)/system-twosegment.ld
+
diff --git a/platform/at91sam7/timer.c b/platform/at91sam7/timer.c
new file mode 100644
index 0000000..e4b6596
--- /dev/null
+++ b/platform/at91sam7/timer.c
@@ -0,0 +1,102 @@
+/*
+ * 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 <kernel/thread.h>
+#include <platform/timer.h>
+#include <platform/interrupts.h>
+#include <platform/debug.h>
+#include <platform/at91sam7.h>
+
+#define FIXED_1KHZ_TIMER 0
+
+static platform_timer_callback timer_func;
+
+static volatile time_t ticks = 0;
+
+#if FIXED_1KHZ_TIMER
+static volatile int timer_interval;
+static volatile int timer_downcount;
+#else
+static int timer_ms_per_tick;
+#endif
+
+time_t current_time(void)
+{
+	return ticks;
+}
+
+static enum handler_return pit_irq_handler(void *arg)
+{
+    AT91PIT *pit = AT91PIT_ADDR;
+    unsigned n = PIT_PICNT(pit->PIVR);
+
+#if FIXED_1KHZ_TIMER
+    ticks += n;
+    timer_downcount -= n;
+
+    if(timer_downcount <= 0) {
+        timer_downcount = timer_interval;
+        return timer_func(0, ticks);
+    } else {
+        return INT_NO_RESCHEDULE;
+    }
+#else
+    ticks += (n * timer_ms_per_tick);
+    return timer_func(0, ticks);
+#endif
+}
+
+status_t platform_set_periodic_timer(platform_timer_callback callback,
+                                     void *arg, time_t interval)
+{
+    unsigned n;
+    
+    AT91PIT *pit = AT91PIT_ADDR;
+
+    n = AT91_MCK_MHZ / 16 / 1000;
+    dprintf("timer: MCK=%dKHz, n=%d\n", AT91_MCK_MHZ / 1000, n);
+
+    enter_critical_section();
+    
+    timer_func = callback;
+
+#if FIXED_1KHZ_TIMER
+    timer_interval = interval;
+    timer_downcount = interval;
+#else
+    timer_ms_per_tick = interval;
+    n *= interval;
+#endif
+    
+    pit->MR = PIT_PITEN | PIT_PITIEN | (n & 0xfffff);
+    
+    register_int_handler(PID_SYSIRQ, pit_irq_handler, 0);
+    unmask_interrupt(PID_SYSIRQ, 0);
+
+    exit_critical_section();
+    
+    return NO_ERROR;
+}
+
diff --git a/platform/debug.c b/platform/debug.c
new file mode 100644
index 0000000..a38ccbc
--- /dev/null
+++ b/platform/debug.c
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+ 
diff --git a/platform/init.c b/platform/init.c
new file mode 100644
index 0000000..c397b50
--- /dev/null
+++ b/platform/init.c
@@ -0,0 +1,43 @@
+/*
+ * 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>
+
+/* 
+ * default implementations of these routines, if the platform code
+ * chooses not to implement.
+ */
+
+__WEAK void platform_init_mmu_mappings(void)
+{
+}
+
+__WEAK void platform_early_init(void)
+{
+}
+
+__WEAK void platform_init(void)
+{
+}
+
diff --git a/platform/integrator/debug.c b/platform/integrator/debug.c
new file mode 100644
index 0000000..ab9f901
--- /dev/null
+++ b/platform/integrator/debug.c
@@ -0,0 +1,146 @@
+/*
+ * 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 <debug.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <platform/integrator.h>
+
+static void write_uart_reg(int uart, int reg, unsigned char data)
+{
+	unsigned long base;
+	int mul = 4;
+
+	switch(uart) {
+		case 0: base = INTEGRATOR_UART0_REG_BASE; break;
+		case 1: base = INTEGRATOR_UART1_REG_BASE; break;
+		default: return;
+	}
+
+	*(volatile unsigned char *)(base + reg * mul) = data;
+}
+
+static unsigned char read_uart_reg(int uart, int reg)
+{
+	unsigned long base;
+	int mul = 4;
+
+	switch(uart) {
+		case 0: base = INTEGRATOR_UART0_REG_BASE; break;
+		case 1: base = INTEGRATOR_UART1_REG_BASE; break;
+		default: return 0;
+	}
+
+	return *(volatile unsigned char *)(base + reg * mul);
+}
+
+static int uart_init(void)
+{
+#if 0
+	/* clear the tx & rx fifo and disable */
+	write_uart_reg(0, UART_FCR, 0x6);
+#endif
+
+	return 0;
+}
+
+static int uart_putc(int port, char c )
+{
+	write_uart_reg(0, PL011_UARTDR, c);
+#if 0
+	while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the shift register to empty
+		;
+  	write_uart_reg(port, UART_THR, c);
+#endif
+	return 0;
+}
+
+static int uart_getc(int port, bool wait)  /* returns -1 if no data available */
+{
+#if 0
+	if (wait) {
+		while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
+			;
+	} else {
+		if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
+			return -1;
+	}
+	return read_uart_reg(port, UART_RHR);
+#endif
+	return -1;
+}
+
+void dputc(char c)
+{
+	uart_putc(0, c);
+}
+
+int dgetc(char *c)
+{
+	int result = uart_getc(0, false);
+
+	if (result < 0)
+		return -1;
+
+	*c = result;
+	return 0;
+}
+
+void debug_dump_regs(void)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_halt(void)
+{
+	dprintf("HALT: spinning forever...\n");
+	for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+uint32_t debug_cycle_count()
+{
+	PANIC_UNIMPLEMENTED;
+}
diff --git a/platform/integrator/include/platform/integrator.h b/platform/integrator/include/platform/integrator.h
new file mode 100644
index 0000000..47eaacb
--- /dev/null
+++ b/platform/integrator/include/platform/integrator.h
@@ -0,0 +1,59 @@
+/*
+ * 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 __INTEGRATOR_H
+#define __INTEGRATOR_H
+
+/* memory map */
+#define SDRAM_BASE	0x00000000
+
+#define INTEGRATOR_CORE_REG_BASE  0x10000000
+#define INTEGRATOR_SYS_REG_BASE   0x11000000
+#define INTEGRATOR_EBI_REG_BASE   0x12000000
+#define INTEGRATOR_TIMER_REG_BASE 0x13000000
+#define INTEGRATOR_INT_REG_BASE   0x14000000
+#define INTEGRATOR_UART0_REG_BASE 0x16000000
+#define INTEGRATOR_UART1_REG_BASE 0x17000000
+#define INTEGRATOR_LEDS_REG_BASE  0x1a000000
+#define INTEGRATOR_GPIO_REG_BASE  0x1b000000
+
+/* uart stuff */
+#define PL011_UARTDR (0)
+#define PL011_UARTRSR (1)
+#define PL011_UARTECR (1)
+#define PL011_UARTFR (6)
+#define PL011_UARTILPR (8)
+#define PL011_UARTIBRD (9)
+#define PL011_UARTFBRD (10)
+#define PL011_UARTLCR_H (11)
+#define PL011_UARTCR (12)
+#define PL011_UARTIFLS (13)
+#define PL011_UARTIMSC (14)
+#define PL011_UARTTRIS (15)
+#define PL011_UARTTMIS (16)
+#define PL011_UARTICR (17)
+#define PL011_UARTMACR (18)
+
+#define INT_VECTORS 32 // XXX just made this up
+
+#endif
+
diff --git a/platform/integrator/interrupts.c b/platform/integrator/interrupts.c
new file mode 100644
index 0000000..ef5f221
--- /dev/null
+++ b/platform/integrator/interrupts.c
@@ -0,0 +1,238 @@
+/*
+ * 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 <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+#include <platform/integrator.h>
+
+struct int_handler_struct {
+	int_handler handler;
+	void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+#if 0
+static const uint32_t icBase[5] = {
+	INTCON0_BASE, INTCON1_BASE, INTCON2_BASE, INTCON3_BASE, INTCON4_BASE };
+
+/* a bitmap of the level triggered interrupt vectors */
+static uint32_t level_trigger[5] = {
+	0xb3fefe8f,	// level 1 0-31
+	0xfdb3c1fd,	// level 2 0-31
+	0xfffff7ff, // level 2 32-63
+	0xbfffffff, // level 2 64-95
+	0xffffffff // level 2 96-128
+};
+
+inline volatile uint32_t *ICReg(uint controller, uint reg)
+{
+	return (volatile uint32_t *)(icBase[controller] + reg);
+}
+
+inline uint32_t readICReg(uint controller, uint reg)
+{
+	return *ICReg(controller, reg);
+}
+inline void writeICReg(uint controller, uint reg, uint val)
+{
+	*ICReg(controller, reg) = val;
+}
+
+inline uint vectorToController(uint vector)
+{
+	return vector / 32;
+}
+#endif
+
+void platform_init_interrupts(void)
+{
+#if 0
+	unsigned int i;
+
+	// mask all interrupts
+	*ICReg(0, INTCON_MIR) = 0xfffffffa;
+	*ICReg(1, INTCON_MIR) = 0xffffffff;
+	*ICReg(2, INTCON_MIR) = 0xffffffff;
+	*ICReg(3, INTCON_MIR) = 0xffffffff;
+	*ICReg(4, INTCON_MIR) = 0xffffffff;
+
+	// set up each of the interrupts
+	for (i = 0; i < INT_VECTORS; i++) {
+		// set each vector up as high priority, IRQ, and default edge/level sensitivity
+		*ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
+	}
+
+	// clear any pending interrupts
+	*ICReg(0, INTCON_ITR) = 0;
+	*ICReg(1, INTCON_ITR) = 0;
+	*ICReg(2, INTCON_ITR) = 0;
+	*ICReg(3, INTCON_ITR) = 0;
+	*ICReg(4, INTCON_ITR) = 0;
+
+	// globally unmask interrupts
+	*ICReg(1, INTCON_CONTROL) = 3;
+	*ICReg(0, INTCON_CONTROL) = 3;
+	*ICReg(0, INTCON_GMR) = 0;
+
+	dprintf("end of platform_init_interrupts\n");
+
+#if 0
+	arch_enable_ints();
+
+	dprintf("&ITR0 0x%x\n", (uint32_t)ICReg(0, INTCON_ITR));
+
+	dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
+	dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
+	dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
+
+	*ICReg(0, INTCON_ILR_BASE + 4*7) = 0;
+	*ICReg(0, INTCON_MIR) &= ~0x80;
+
+	dprintf("triggering int\n");
+	
+	*ICReg(0, INTCON_SISR) = 0x80;
+
+	dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
+	dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
+	dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
+
+	for(;;);
+#endif
+#endif
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+#if 0
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	if (oldstate)
+		*oldstate = false;
+
+	volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+	*mir = *mir | (1<<(vector % 32));
+
+	exit_critical_section();
+#endif
+
+	return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+#if 0
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	if (oldstate)
+		*oldstate = false;
+
+	volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+	*mir = *mir & ~(1<<(vector % 32));
+
+	exit_critical_section();
+#endif
+
+	return NO_ERROR;
+}
+
+void platform_irq(struct arm_iframe *frame)
+{
+	PANIC_UNIMPLEMENTED;
+#if 0
+	// get the current vector
+	unsigned int vector;
+   
+	inc_critical_section();
+
+	// read from the first level int handler
+	vector = *ICReg(0, INTCON_SIR_IRQ);
+	
+	// see if it's coming from the second level handler
+	if (vector == 0) {
+		vector = *ICReg(1, INTCON_SIR_IRQ) + 32;
+	}
+
+//	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);
+
+	// ack the interrupt
+	if (vector >= 32) {
+		// interrupt is chained, so ack the second level first, and then the first
+		*ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32));
+		*ICReg(1, INTCON_CONTROL) |= 1;
+		vector = 0; // force the following code to ack the chained first level vector
+	} 
+
+	*ICReg(0, INTCON_ITR) = ~(1 << vector);
+	*ICReg(0, INTCON_CONTROL) = 1;
+
+	if (ret == INT_RESCHEDULE)
+		thread_preempt();
+
+	dec_critical_section();
+
+//	dprintf("platform_irq: exit\n");
+#endif
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+	if (vector >= INT_VECTORS)
+		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/integrator/platform.c b/platform/integrator/platform.c
new file mode 100644
index 0000000..5b31242
--- /dev/null
+++ b/platform/integrator/platform.c
@@ -0,0 +1,55 @@
+/*
+ * 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"
+#include <platform/integrator.h>
+#include <arch/arm/mmu.h>
+
+void platform_init_mmu_mappings(void)
+{
+}
+
+void platform_early_init(void)
+{
+#if 0
+	/* do some memory map initialization */
+	addr_t addr;
+	arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
+	for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
+		arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
+	}
+
+	/* initialize the interrupt controller */
+	platform_init_interrupts();
+
+	/* initialize the timer block */
+	platform_init_timer();
+#endif
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/integrator/platform_p.h b/platform/integrator/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/integrator/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/integrator/rules.mk b/platform/integrator/rules.mk
new file mode 100644
index 0000000..a189153
--- /dev/null
+++ b/platform/integrator/rules.mk
@@ -0,0 +1,26 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm926ej-s
+CPU := generic
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+OBJS += \
+	$(LOCAL_DIR)/debug.o \
+	$(LOCAL_DIR)/platform.o \
+	$(LOCAL_DIR)/interrupts.o \
+	$(LOCAL_DIR)/timer.o \
+
+#	$(LOCAL_DIR)/net.o \
+
+
+#	$(LOCAL_DIR)/console.o \
+
+MEMBASE ?= 0x0
+MEMSIZE ?= 0x08000000	# 128MB
+
+LINKER_SCRIPT += \
+	$(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/integrator/timer.c b/platform/integrator/timer.c
new file mode 100644
index 0000000..55d14de
--- /dev/null
+++ b/platform/integrator/timer.c
@@ -0,0 +1,101 @@
+/*
+ * 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 <debug.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/integrator.h>
+#include "platform_p.h"
+
+static time_t system_time = 0;
+
+static time_t tick_interval;
+static uint32_t ticks_per_interval;
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+#if 0
+	enter_critical_section();
+
+	t_callback = callback;
+	callback_arg = arg;
+	tick_interval = interval;
+	ticks_per_interval = interval * 32768 / 1000; // interval is in ms
+
+	OS_TIMER_CTRL_REG = 0; // stop it
+	OS_TIMER_TICK_VALUE_REG = ticks_per_interval;
+	OS_TIMER_CTRL_REG = (1<<3) | (1<<2) | (1<<1) | (1<<0);
+
+	exit_critical_section();
+#endif
+
+	return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+#if 0
+	time_t t;
+	uint32_t delta_ticks;
+	uint32_t delta_ticks2;
+	
+retry:
+	delta_ticks = OS_TIMER_TICK_COUNTER_REG;
+	t = system_time;
+	delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
+	if (delta_ticks2 > delta_ticks)
+		goto retry;
+
+	t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
+
+	return t;
+#else
+	static time_t time = 0;
+	return time++;
+#endif
+
+}
+
+static enum handler_return os_timer_tick(void *arg)
+{
+	system_time += tick_interval;
+//	dprintf("os_timer_tick %d\n", system_time);
+
+	return t_callback(callback_arg, system_time);
+}
+
+void platform_init_timer(void)
+{
+#if 0
+	OS_TIMER_CTRL_REG = 0; // stop the timer if it's already running
+
+	register_int_handler(IRQ_OS_TIMER, &os_timer_tick, NULL);
+	unmask_interrupt(IRQ_OS_TIMER, NULL);
+#endif
+}
+
diff --git a/platform/omap3/debug.c b/platform/omap3/debug.c
new file mode 100644
index 0000000..973287b
--- /dev/null
+++ b/platform/omap3/debug.c
@@ -0,0 +1,86 @@
+/*
+ * 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 <debug.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <dev/uart.h>
+#include <target/debugconfig.h>
+
+void dputc(char c)
+{
+	if (c == '\n')
+		uart_putc(DEBUG_UART, '\r');
+	uart_putc(DEBUG_UART, c);
+}
+
+int dgetc(char *c)
+{
+	int _c;
+
+	if ((_c = uart_getc(DEBUG_UART, false)) < 0)
+		return -1;
+
+	*c = _c;
+	return 0;
+}
+
+void debug_dump_regs(void)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_halt(void)
+{
+	dprintf("HALT: spinning forever...\n");
+	for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+uint32_t debug_cycle_count(void)
+{
+//	PANIC_UNIMPLEMENTED;
+	return 0;
+}
diff --git a/platform/omap3/include/platform/omap3.h b/platform/omap3/include/platform/omap3.h
new file mode 100644
index 0000000..c7d9405
--- /dev/null
+++ b/platform/omap3/include/platform/omap3.h
@@ -0,0 +1,175 @@
+/*
+ * 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_OMAP3_H
+#define __PLATFORM_OMAP3_H
+
+#define SDRAM_BASE 0x80000000
+
+#define L4_BASE     0x48000000
+#define L4_WKUP_BASE    0x48300000
+#define L4_PER_BASE 0x49000000
+#define L4_EMU_BASE 0x54000000
+#define GFX_BASE    0x50000000
+#define L3_BASE     0x68000000
+#define SMS_BASE    0x6C000000
+#define SDRC_BASE   0x6D000000
+#define GPMC_BASE   0x6E000000
+#define SCM_BASE    0x48002000
+
+/* clocks */
+#define CM_CLKSEL_PER		(L4_BASE + 0x5040)
+
+/* General Purpose Timers */
+#define OMAP34XX_GPT1           (L4_BASE + 0x318000)
+#define OMAP34XX_GPT2           (L4_BASE + 0x1032000)
+#define OMAP34XX_GPT3           (L4_BASE + 0x1034000)
+#define OMAP34XX_GPT4           (L4_BASE + 0x1036000)
+#define OMAP34XX_GPT5           (L4_BASE + 0x1038000)
+#define OMAP34XX_GPT6           (L4_BASE + 0x103A000)
+#define OMAP34XX_GPT7           (L4_BASE + 0x103C000)
+#define OMAP34XX_GPT8           (L4_BASE + 0x103E000)
+#define OMAP34XX_GPT9           (L4_BASE + 0x1040000)
+#define OMAP34XX_GPT10          (L4_BASE + 0x86000)
+#define OMAP34XX_GPT11          (L4_BASE + 0x88000)
+#define OMAP34XX_GPT12          (L4_BASE + 0x304000)
+
+#define TIDR				0x00
+#define TIOCP_CFG			0x10
+#define TISTAT				0x14
+#define TISR				0x18
+#define TIER				0x1C
+#define TWER				0x20
+#define TCLR				0x24
+#define TCRR				0x28
+#define TLDR				0x2C
+#define TTGR				0x30
+#define TWPS				0x34
+#define TMAR				0x38
+#define TCAR1				0x3C
+#define TSICR				0x40
+#define TCAR2				0x44
+#define TPIR				0x48
+#define TNIR				0x4C
+#define TCVR				0x50
+#define TOCR				0x54
+#define TOWR				0x58
+
+/* WatchDog Timers (1 secure, 3 GP) */
+#define WD1_BASE            (0x4830C000)
+#define WD2_BASE            (0x48314000)
+#define WD3_BASE            (0x49030000)
+
+#define WIDR		0x00
+#define WD_SYSCONFIG	0x10
+#define WD_SYSSTATUS	0x14
+#define WISR		0x18
+#define WIER		0x1C
+#define WCLR		0x24
+#define WCRR		0x28
+#define WLDR		0x2C
+#define WTGR		0x30
+#define WWPS		0x34
+#define WSPR		0x48
+
+#define W_PEND_WCLR	(1<<0)
+#define W_PEND_WCRR	(1<<1)
+#define W_PEND_WLDR	(1<<2)
+#define W_PEND_WTGR	(1<<3)
+#define W_PEND_WSPR	(1<<4)
+
+#define WD_UNLOCK1      0xAAAA
+#define WD_UNLOCK2      0x5555
+
+/* 32KTIMER */
+#define TIMER32K_BASE		(L4_BASE + 0x320000)
+#define TIMER32K_REV		(TIMER32K_BASE + 0x00)
+#define TIMER32K_CR			(TIMER32K_BASE + 0x10)
+
+/* UART */
+#define OMAP_UART1_BASE     (L4_BASE + 0x6a000)
+#define OMAP_UART2_BASE     (L4_BASE + 0x6c000)
+#define OMAP_UART3_BASE     (L4_BASE + 0x01020000)
+
+#define UART_RHR    0
+#define UART_THR    0
+#define UART_DLL    0
+#define UART_IER    1
+#define UART_DLH    1
+#define UART_IIR    2
+#define UART_FCR    2
+#define UART_EFR    2
+#define UART_LCR    3
+#define UART_MCR    4
+#define UART_LSR    5
+#define UART_MSR    6
+#define UART_TCR    6
+#define UART_SPR    7
+#define UART_TLR    7
+#define UART_MDR1   8
+#define UART_MDR2   9
+#define UART_SFLSR  10
+#define UART_RESUME 11
+#define UART_TXFLL  10
+#define UART_TXFLH  11
+#define UART_SFREGL 12
+#define UART_SFREGH 13
+#define UART_RXFLL  12
+#define UART_RXFLH  13
+#define UART_BLR    14
+#define UART_UASR   14
+#define UART_ACREG  15
+#define UART_SCR    16
+#define UART_SSR    17
+#define UART_EBLR   18
+#define UART_MVR    19
+#define UART_SYSC   20
+
+/* MPU INTC */
+#define INTC_BASE			(L4_BASE + 0x200000)
+#define INTC_REVISION		(INTC_BASE + 0x000)
+#define INTC_SYSCONFIG		(INTC_BASE + 0x010)
+#define INTC_SYSSTATUS		(INTC_BASE + 0x014)
+#define INTC_SIR_IRQ		(INTC_BASE + 0x040)
+#define INTC_SIR_FIQ		(INTC_BASE + 0x044)
+#define INTC_CONTROL		(INTC_BASE + 0x048)
+#define INTC_PROTECTION		(INTC_BASE + 0x04C)
+#define INTC_IDLE			(INTC_BASE + 0x050)
+#define INTC_IRQ_PRIORITY	(INTC_BASE + 0x060)
+#define INTC_FIQ_PRIORITY	(INTC_BASE + 0x064)
+#define INTC_THRESHOLD		(INTC_BASE + 0x068)
+#define INTC_ITR(n)			(INTC_BASE + 0x080 + (n) * 0x20)
+#define INTC_MIR(n)			(INTC_BASE + 0x084 + (n) * 0x20)
+#define INTC_MIR_CLEAR(n)	(INTC_BASE + 0x088 + (n) * 0x20)
+#define INTC_MIR_SET(n)		(INTC_BASE + 0x08C + (n) * 0x20)
+#define INTC_ISR_SET(n)		(INTC_BASE + 0x090 + (n) * 0x20)
+#define INTC_ISR_CLEAR(n)	(INTC_BASE + 0x094 + (n) * 0x20)
+#define INTC_PENDING_IRQ(n)	(INTC_BASE + 0x098 + (n) * 0x20)
+#define INTC_PENDING_FIQ(n)	(INTC_BASE + 0x09C + (n) * 0x20)
+#define INTC_ILR(n)			(INTC_BASE + 0x100 + (n) * 4)
+
+/* interrupts */
+#define INT_VECTORS 		96
+#define GPT2_IRQ			38
+
+#endif
+
diff --git a/platform/omap3/interrupts.c b/platform/omap3/interrupts.c
new file mode 100644
index 0000000..225d810
--- /dev/null
+++ b/platform/omap3/interrupts.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <debug.h>
+#include <err.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+#include <platform/omap3.h>
+
+struct int_handler_struct {
+	int_handler handler;
+	void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+#define vectorToController(vector) ((vector) / 32)
+
+void platform_init_interrupts(void)
+{
+	unsigned int i;
+
+	// reset the controller
+	*REG32(INTC_SYSCONFIG) = 0x2; // start a reset
+	while ((*REG32(INTC_SYSSTATUS) & 0x1) == 0)
+		;
+
+	// mask all interrupts
+	*REG32(INTC_MIR(0)) = 0xffffffff;
+	*REG32(INTC_MIR(1)) = 0xffffffff;
+	*REG32(INTC_MIR(2)) = 0xffffffff;
+
+	// set up each of the interrupts
+	for (i = 0; i < INT_VECTORS; i++) {
+		// set each vector up as high priority IRQ
+		*REG32(INTC_ILR(i)) = 0;
+		//*ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
+	}
+
+	// disable the priority threshold
+	*REG32(INTC_THRESHOLD) = 0xff;
+
+	// clear any pending sw interrupts
+	*REG32(INTC_ISR_CLEAR(0)) = 0xffffffff;
+	*REG32(INTC_ISR_CLEAR(1)) = 0xffffffff;
+	*REG32(INTC_ISR_CLEAR(2)) = 0xffffffff;
+
+	// globally unmask interrupts
+	*REG32(INTC_CONTROL) = 3; // reset and enable the controller
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	if (oldstate)
+		*oldstate = false;
+
+	*REG32(INTC_MIR_SET(vectorToController(vector))) = 1 << (vector % 32);
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+
+void platform_mask_irqs(void)
+{
+	int i;
+	for (i=0; i<INT_VECTORS; i++)
+		mask_interrupt(i, NULL);
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	if (oldstate)
+		*oldstate = false;
+
+	*REG32(INTC_MIR_CLEAR(vectorToController(vector))) = 1 << (vector % 32);
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+	// get the current vector
+	unsigned int vector;
+   
+	// read the currently active IRQ
+	vector = *REG32(INTC_SIR_IRQ) & 0x7f;
+
+//	TRACEF("spsr 0x%x, pc 0x%x, currthread %p, vector %d, handler %p\n", frame->spsr, frame->pc, current_thread, vector, int_handler_table[vector].handler);
+
+#if THREAD_STATS
+	thread_stats.interrupts++;
+#endif
+
+	// 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);
+
+	// ack the interrupt
+	*REG32(INTC_CONTROL) = 0x1;
+
+	return ret;
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+	if (vector >= INT_VECTORS)
+		panic("register_int_handler: vector out of range %d\n", vector);
+
+	enter_critical_section();
+
+	int_handler_table[vector].arg = arg;
+	int_handler_table[vector].handler = handler;
+
+	exit_critical_section();
+}
+
+
diff --git a/platform/omap3/platform.c b/platform/omap3/platform.c
new file mode 100644
index 0000000..0df0469
--- /dev/null
+++ b/platform/omap3/platform.c
@@ -0,0 +1,56 @@
+/*
+ * 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 <arch/arm/mmu.h>
+#include <platform.h>
+#include "platform_p.h"
+#include <platform/omap3.h>
+#include <dev/uart.h>
+
+void platform_init_mmu_mappings(void)
+{
+	/* do some memory map initialization */
+	addr_t addr;
+	arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
+	for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
+		arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
+	}
+}
+
+void platform_early_init(void)
+{
+	/* initialize the interrupt controller */
+	platform_init_interrupts();
+
+	/* initialize the timer block */
+	platform_init_timer();
+
+	/* initialize the uart */
+	uart_init_early();
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/omap3/platform_p.h b/platform/omap3/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/omap3/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/omap3/rules.mk b/platform/omap3/rules.mk
new file mode 100644
index 0000000..41da8e6
--- /dev/null
+++ b/platform/omap3/rules.mk
@@ -0,0 +1,23 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := cortex-a8
+CPU := generic
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+OBJS += \
+	$(LOCAL_DIR)/debug.o \
+	$(LOCAL_DIR)/interrupts.o \
+	$(LOCAL_DIR)/platform.o \
+	$(LOCAL_DIR)/timer.o \
+	$(LOCAL_DIR)/uart.o
+
+MEMBASE := 0x80000000
+
+DEFINES += MEMBASE=$(MEMBASE)
+
+LINKER_SCRIPT += \
+	$(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/omap3/timer.c b/platform/omap3/timer.c
new file mode 100644
index 0000000..7c2b1f3
--- /dev/null
+++ b/platform/omap3/timer.c
@@ -0,0 +1,128 @@
+/*
+ * 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 <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/omap3.h>
+#include "platform_p.h"
+
+static time_t tick_interval;
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+/* timer 2 */
+static const ulong timer_base = OMAP34XX_GPT2;
+
+#define TIMER_TICK_RATE 32768
+
+#define TIMER_REG(reg) *REG32(timer_base + (reg))
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+	enter_critical_section();
+
+	t_callback = callback;
+	callback_arg = arg;
+	tick_interval = interval;
+	uint32_t ticks_per_interval = (uint64_t)interval * TIMER_TICK_RATE / 1000; // interval is in ms
+
+	TIMER_REG(TCLR) = 0; // stop the timer
+	TIMER_REG(TLDR) = -ticks_per_interval;
+	TIMER_REG(TTGR) = 1;
+	TIMER_REG(TIER) = 0x2;
+	TIMER_REG(TCLR) = 0x3; // autoreload, start
+
+	unmask_interrupt(GPT2_IRQ, NULL);
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+	uint32_t delta_ticks;
+	uint32_t delta_ticks2;
+	
+retry:
+	delta_ticks = *REG32(TIMER32K_CR);
+	delta_ticks2 = *REG32(TIMER32K_CR);
+	if (delta_ticks2 != delta_ticks)
+		goto retry;
+
+	uint64_t longtime = delta_ticks * 1000ULL / 32768ULL;
+
+	return (time_t)longtime;
+}
+
+bigtime_t current_time_hires(void)
+{
+	uint32_t delta_ticks;
+	uint32_t delta_ticks2;
+	
+retry:
+	delta_ticks = *REG32(TIMER32K_CR);
+	delta_ticks2 = *REG32(TIMER32K_CR);
+	if (delta_ticks2 != delta_ticks)
+		goto retry;
+
+	uint64_t longtime = delta_ticks * 1000000ULL / 32768ULL;
+
+	return (bigtime_t)longtime;
+}
+static enum handler_return os_timer_tick(void *arg)
+{
+	TIMER_REG(TISR) = TIMER_REG(TISR);
+
+	return t_callback(callback_arg, current_time());
+}
+
+void platform_init_timer(void)
+{
+	// reset the GP timer 
+	TIMER_REG(TIOCP_CFG) = 0x2;
+	while ((TIMER_REG(TISTAT) & 1) == 0)
+		;
+
+	// set GPT2-9 clock inputs over to 32k
+	*REG32(CM_CLKSEL_PER) = 0;
+
+	// disable ints
+	TIMER_REG(TIER) = 0;
+	TIMER_REG(TISR) = 0x7; // clear any pending bits
+
+	// XXX make sure 32K timer is running
+
+	register_int_handler(GPT2_IRQ, &os_timer_tick, NULL);
+}
+
+void platform_halt_timers(void)
+{
+	TIMER_REG(TCLR) = 0;
+}
+
diff --git a/platform/omap3/uart.c b/platform/omap3/uart.c
new file mode 100644
index 0000000..e4c5102
--- /dev/null
+++ b/platform/omap3/uart.c
@@ -0,0 +1,150 @@
+/*
+ * 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 <debug.h>
+#include <dev/uart.h>
+#include <platform/omap3.h>
+#include <target/debugconfig.h>
+
+struct uart_stat {
+	addr_t base;
+	uint shift;
+};
+
+static struct uart_stat uart[3] = {
+	{ OMAP_UART1_BASE, 2 },
+	{ OMAP_UART2_BASE, 2 },
+	{ OMAP_UART3_BASE, 2 },
+};
+
+static inline void write_uart_reg(int port, uint reg, unsigned char data)
+{
+	*(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift)) = data;
+}
+
+static inline unsigned char read_uart_reg(int port, uint reg)
+{
+	return *(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift));
+}
+
+#define LCR_8N1		0x03
+
+#define FCR_FIFO_EN     0x01		/* Fifo enable */
+#define FCR_RXSR        0x02		/* Receiver soft reset */
+#define FCR_TXSR        0x04		/* Transmitter soft reset */
+
+#define MCR_DTR         0x01
+#define MCR_RTS         0x02
+#define MCR_DMA_EN      0x04
+#define MCR_TX_DFR      0x08
+
+#define LCR_WLS_MSK	0x03		/* character length select mask */
+#define LCR_WLS_5	0x00		/* 5 bit character length */
+#define LCR_WLS_6	0x01		/* 6 bit character length */
+#define LCR_WLS_7	0x02		/* 7 bit character length */
+#define LCR_WLS_8	0x03		/* 8 bit character length */
+#define LCR_STB		0x04		/* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define LCR_PEN		0x08		/* Parity eneble */
+#define LCR_EPS		0x10		/* Even Parity Select */
+#define LCR_STKP	0x20		/* Stick Parity */
+#define LCR_SBRK	0x40		/* Set Break */
+#define LCR_BKSE	0x80		/* Bank select enable */
+
+#define LSR_DR		0x01		/* Data ready */
+#define LSR_OE		0x02		/* Overrun */
+#define LSR_PE		0x04		/* Parity error */
+#define LSR_FE		0x08		/* Framing error */
+#define LSR_BI		0x10		/* Break */
+#define LSR_THRE	0x20		/* Xmit holding register empty */
+#define LSR_TEMT	0x40		/* Xmitter empty */
+#define LSR_ERR		0x80		/* Error */
+
+#define LCRVAL LCR_8N1					/* 8 data, 1 stop, no parity */
+#define MCRVAL (MCR_DTR | MCR_RTS)			/* RTS/DTR */
+#define FCRVAL (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR)	/* Clear & enable FIFOs */
+
+#define V_NS16550_CLK            (48000000)  /* 48MHz (APLL96/2) */
+
+void uart_init_port(int port, uint baud)
+{
+	/* clear the tx & rx fifo and disable */
+	uint16_t baud_divisor = (V_NS16550_CLK / 16 / baud);
+
+	write_uart_reg(port, UART_IER, 0);
+	write_uart_reg(port, UART_LCR, LCR_BKSE | LCRVAL); // config mode A
+	write_uart_reg(port, UART_DLL, baud_divisor & 0xff);
+	write_uart_reg(port, UART_DLH, (baud_divisor >> 8) & 0xff);
+	write_uart_reg(port, UART_LCR, LCRVAL); // operational mode
+	write_uart_reg(port, UART_MCR, MCRVAL);
+	write_uart_reg(port, UART_FCR, FCRVAL);
+	write_uart_reg(port, UART_MDR1, 0); // UART 16x mode
+
+//	write_uart_reg(port, UART_LCR, 0xBF); // config mode B
+//	write_uart_reg(port, UART_EFR, (1<<7)|(1<<6)); // hw flow control
+//	write_uart_reg(port, UART_LCR, LCRVAL); // operational mode
+}
+
+void uart_init_early(void)
+{
+	uart_init_port(DEBUG_UART, 115200);
+}
+
+void uart_init(void)
+{
+}
+
+int uart_putc(int port, char c )
+{
+	while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the last char to get out
+		;
+  	write_uart_reg(port, UART_THR, c);
+	return 0;
+}
+
+int uart_getc(int port, bool wait)  /* returns -1 if no data available */
+{
+	if (wait) {
+		while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
+			;
+	} else {
+		if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
+			return -1;
+	}
+	return read_uart_reg(port, UART_RHR);
+}
+
+void uart_flush_tx(int port)
+{
+	while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the last char to get out
+		;
+}
+
+void uart_flush_rx(int port)
+{
+	// empty the rx fifo
+	while (read_uart_reg(port, UART_LSR) & (1<<0)) {
+		volatile char c = read_uart_reg(port, UART_RHR);
+		(void)c;
+	}
+}
+
+
diff --git a/platform/omap5912/debug.c b/platform/omap5912/debug.c
new file mode 100644
index 0000000..cb3ea29
--- /dev/null
+++ b/platform/omap5912/debug.c
@@ -0,0 +1,143 @@
+/*
+ * 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 <debug.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <platform/omap5912.h>
+
+static void write_uart_reg(int uart, int reg, unsigned char data)
+{
+	unsigned long base;
+	int mul = 4;
+
+	switch(uart) {
+		case 0: base = UART0_BASE; break;
+		case 1: base = UART1_BASE; break;
+		case 2: base = UART2_BASE; break;
+		default: return;
+	}
+
+	*(volatile unsigned char *)(base + reg * mul) = data;
+}
+
+static unsigned char read_uart_reg(int uart, int reg)
+{
+	unsigned long base;
+	int mul = 4;
+
+	switch(uart) {
+		case 0: base = UART0_BASE; break;
+		case 1: base = UART1_BASE; break;
+		case 2: base = UART2_BASE; break;
+		default: return 0;
+	}
+
+	return *(volatile unsigned char *)(base + reg * mul);
+}
+
+static int uart_init(void)
+{
+	/* clear the tx & rx fifo and disable */
+	write_uart_reg(0, UART_FCR, 0x6);
+
+	return 0;
+}
+
+static int uart_putc(int port, char c )
+{
+	while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the shift register to empty
+		;
+  	write_uart_reg(port, UART_THR, c);
+	return 0;
+}
+
+static int uart_getc(int port, bool wait)  /* returns -1 if no data available */
+{
+	if (wait) {
+		while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
+			;
+	} else {
+		if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
+			return -1;
+	}
+	return read_uart_reg(port, UART_RHR);
+}
+
+void dputc(char c)
+{
+	if (c == '\n')
+		uart_putc(0, '\r');
+	uart_putc(0, c);
+}
+
+int dgetc(char *c)
+{
+	int _c;
+
+	if ((_c = uart_getc(0, false)) < 0)
+		return -1;
+
+	*c = _c;
+	return 0;
+}
+
+void debug_dump_regs(void)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_halt(void)
+{
+	dprintf("HALT: spinning forever...\n");
+	for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+uint32_t debug_cycle_count(void)
+{
+//	PANIC_UNIMPLEMENTED;
+	return 0;
+}
diff --git a/platform/omap5912/include/platform/omap5912.h b/platform/omap5912/include/platform/omap5912.h
new file mode 100644
index 0000000..0255b82
--- /dev/null
+++ b/platform/omap5912/include/platform/omap5912.h
@@ -0,0 +1,139 @@
+/*
+ * 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 __OMAP5912_H
+#define __OMAP5912_H
+
+/* memory map */
+#define SDRAM_BASE	0x10000000
+
+/* clocks */
+#define DPLL_CTRL	(*(volatile unsigned short *)0xfffecf00)
+#define ARM_CKCTL	(*(volatile unsigned int *)0xfffece00)
+#define ARM_SYSST	(*(volatile unsigned int *)0xfffece18)
+
+/* uart */
+#define UART0_BASE 0xfffb0000
+#define UART1_BASE 0xfffb0800
+#define UART2_BASE 0xfffb9800
+
+#define UART_RHR	0
+#define UART_THR	0
+#define UART_DLL	0
+#define UART_IER	1
+#define UART_DLH	1
+#define UART_IIR	2
+#define UART_FCR	2
+#define UART_EFR	2
+#define UART_LCR	3
+#define UART_MCR	4
+#define UART_LSR	5
+#define UART_MSR	6
+#define UART_TCR	6
+#define UART_SPR	7
+#define UART_TLR	7
+#define UART_MDR1	8
+#define UART_MDR2	9
+#define UART_SFLSR	10
+#define UART_RESUME	11
+#define UART_TXFLL	10
+#define UART_TXFLH	11
+#define UART_SFREGL	12
+#define UART_SFREGH	13
+#define UART_RXFLL	12
+#define UART_RXFLH	13
+#define UART_BLR	14
+#define UART_UASR	14
+#define UART_ACREG	15
+#define UART_SCR	16
+#define UART_SSR	17
+#define UART_EBLR	18
+#define UART_MVR	19
+#define UART_SYSC	20
+
+/* timers */
+#define MPU_TIMER0_BASE      0xfffec500
+#define MPU_TIMER1_BASE      0xfffec600
+#define MPU_TIMER2_BASE      0xfffec700
+#define WATCHDOG_TIMER_BASE  0xfffec800
+#define OS_TIMER_BASE        0xfffb9000
+#define GP_TIMER1_BASE       0xfffb1400
+#define GP_TIMER2_BASE       0xfffb1c00
+#define GP_TIMER3_BASE       0xfffb2400
+#define GP_TIMER4_BASE       0xfffb2c00
+#define GP_TIMER5_BASE       0xfffb3400
+#define GP_TIMER6_BASE       0xfffb3c00
+#define GP_TIMER7_BASE       0xfffb4400
+#define GP_TIMER8_BASE       0xfffb5c00
+
+#define MPU_CNTL_TIMER1		(*(volatile unsigned int *)(MPU_TIMER1_BASE + 0x00))
+#define MPU_LOAD_TIMER1		(*(volatile unsigned int *)(MPU_TIMER1_BASE + 0x04))
+#define MPU_READ_TIMER1		(*(volatile unsigned int *)(MPU_TIMER1_BASE + 0x08))
+#define MPU_CNTL_TIMER2		(*(volatile unsigned int *)(MPU_TIMER2_BASE + 0x00))
+#define MPU_LOAD_TIMER2		(*(volatile unsigned int *)(MPU_TIMER2_BASE + 0x04))
+#define MPU_READ_TIMER2		(*(volatile unsigned int *)(MPU_TIMER2_BASE + 0x08))
+#define MPU_CNTL_TIMER3		(*(volatile unsigned int *)(MPU_TIMER3_BASE + 0x00))
+#define MPU_LOAD_TIMER3		(*(volatile unsigned int *)(MPU_TIMER3_BASE + 0x04))
+#define MPU_READ_TIMER3		(*(volatile unsigned int *)(MPU_TIMER3_BASE + 0x08))
+
+#define OS_TIMER_TICK_VALUE_REG 	(*(volatile unsigned int *)(OS_TIMER_BASE + 0x00))
+#define OS_TIMER_TICK_COUNTER_REG 	(*(volatile unsigned int *)(OS_TIMER_BASE + 0x04))
+#define OS_TIMER_CTRL_REG		(*(volatile unsigned int *)(OS_TIMER_BASE + 0x08))
+
+
+/* interrupt controller */
+#define INT_VECTORS			(32 + 128)
+#define INTCON0_BASE		0xfffecb00	
+#define INTCON1_BASE		0xfffe0000
+#define INTCON2_BASE		0xfffe0100
+#define INTCON3_BASE		0xfffe0200
+#define INTCON4_BASE		0xfffe0300
+
+#define INTCON_ITR			0x00
+#define INTCON_MIR			0x04
+#define INTCON_SIR_IRQ		0x10
+#define INTCON_SIR_FIQ		0x14
+#define INTCON_CONTROL		0x18
+#define INTCON_ILR_BASE		0x1c
+#define INTCON_SISR			0x9c
+#define INTCON_GMR			0xa0	/* only on first level controller */
+#define INTCON_STATUS		0xa0	/* only on second level controllers */
+#define INTCON_OCP_CFG		0xa4
+#define INTCON_INTH_REV		0xa8
+
+/* interrupts */
+#define IRQ_TIMER3			16
+#define IRQ_GPTIMER1		17
+#define IRQ_GPTIMER2		18
+#define IRQ_TIMER1			26
+#define IRQ_WD_TIMER		27
+#define IRQ_TIMER2			30
+#define IRQ_OS_TIMER		(32 + 22)
+#define IRQ_GPTIMER3		(32 + 34)
+#define IRQ_GPTIMER4		(32 + 35)
+#define IRQ_GPTIMER5		(32 + 36)
+#define IRQ_GPTIMER6		(32 + 37)
+#define IRQ_GPTIMER7		(32 + 38)
+#define IRQ_GPTIMER8		(32 + 39)
+
+#endif
+
diff --git a/platform/omap5912/interrupts.c b/platform/omap5912/interrupts.c
new file mode 100644
index 0000000..5621561
--- /dev/null
+++ b/platform/omap5912/interrupts.c
@@ -0,0 +1,199 @@
+/*
+ * 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 <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+#include <platform/omap5912.h>
+
+struct int_handler_struct {
+	int_handler handler;
+	void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+static const uint32_t icBase[5] = {
+	INTCON0_BASE, INTCON1_BASE, INTCON2_BASE, INTCON3_BASE, INTCON4_BASE };
+
+/* a bitmap of the level triggered interrupt vectors */
+static uint32_t level_trigger[5] = {
+	0xb3fefe8f,	// level 1 0-31
+	0xfdb3c1fd,	// level 2 0-31
+	0xfffff7ff, // level 2 32-63
+	0xbfffffff, // level 2 64-95
+	0xffffffff // level 2 96-128
+};
+
+static inline volatile uint32_t *ICReg(uint controller, uint reg)
+{
+	return (volatile uint32_t *)(icBase[controller] + reg);
+}
+
+static inline uint32_t readICReg(uint controller, uint reg)
+{
+	return *ICReg(controller, reg);
+}
+static inline void writeICReg(uint controller, uint reg, uint val)
+{
+	*ICReg(controller, reg) = val;
+}
+
+static inline uint vectorToController(uint vector)
+{
+	return vector / 32;
+}
+
+void platform_init_interrupts(void)
+{
+	unsigned int i;
+
+	// mask all interrupts
+	*ICReg(0, INTCON_MIR) = 0xfffffffa;
+	*ICReg(1, INTCON_MIR) = 0xffffffff;
+	*ICReg(2, INTCON_MIR) = 0xffffffff;
+	*ICReg(3, INTCON_MIR) = 0xffffffff;
+	*ICReg(4, INTCON_MIR) = 0xffffffff;
+
+	// set up each of the interrupts
+	for (i = 0; i < INT_VECTORS; i++) {
+		// set each vector up as high priority, IRQ, and default edge/level sensitivity
+		*ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
+	}
+
+	// clear any pending interrupts
+	*ICReg(0, INTCON_ITR) = 0;
+	*ICReg(1, INTCON_ITR) = 0;
+	*ICReg(2, INTCON_ITR) = 0;
+	*ICReg(3, INTCON_ITR) = 0;
+	*ICReg(4, INTCON_ITR) = 0;
+
+	// globally unmask interrupts
+	*ICReg(1, INTCON_CONTROL) = 3;
+	*ICReg(0, INTCON_CONTROL) = 3;
+	*ICReg(0, INTCON_GMR) = 0;
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	if (oldstate)
+		*oldstate = false;
+
+	volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+	*mir = *mir | (1<<(vector % 32));
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	if (oldstate)
+		*oldstate = false;
+
+	volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+	*mir = *mir & ~(1<<(vector % 32));
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+	// get the current vector
+	unsigned int vector;
+   
+#if THREAD_STATS
+	thread_stats.interrupts++;
+#endif
+
+	// read from the first level int handler
+	vector = *ICReg(0, INTCON_SIR_IRQ);
+	
+	// see if it's coming from the second level handler
+	if (vector == 0) {
+		vector = *ICReg(1, INTCON_SIR_IRQ) + 32;
+	}
+
+//	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);
+
+	// ack the interrupt
+	if (vector >= 32) {
+		// interrupt is chained, so ack the second level first, and then the first
+		*ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32));
+		*ICReg(1, INTCON_CONTROL) |= 1;
+		vector = 0; // force the following code to ack the chained first level vector
+	} 
+
+	*ICReg(0, INTCON_ITR) = ~(1 << vector);
+	*ICReg(0, INTCON_CONTROL) = 1;
+
+	return ret;
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+	PANIC_UNIMPLEMENTED;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+	if (vector >= INT_VECTORS)
+		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/omap5912/platform.c b/platform/omap5912/platform.c
new file mode 100644
index 0000000..1dd703d
--- /dev/null
+++ b/platform/omap5912/platform.c
@@ -0,0 +1,52 @@
+/*
+ * 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"
+#include <platform/omap5912.h>
+#include <arch/arm/mmu.h>
+
+void platform_init_mmu_mappings(void)
+{
+	/* do some memory map initialization */
+	addr_t addr;
+	arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
+	for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
+		arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
+	}
+}
+
+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/omap5912/platform_p.h b/platform/omap5912/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/omap5912/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/omap5912/rules.mk b/platform/omap5912/rules.mk
new file mode 100644
index 0000000..e1bddc1
--- /dev/null
+++ b/platform/omap5912/rules.mk
@@ -0,0 +1,24 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm926ej-s
+CPU := generic
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+OBJS += \
+	$(LOCAL_DIR)/debug.o \
+	$(LOCAL_DIR)/interrupts.o \
+	$(LOCAL_DIR)/platform.o \
+	$(LOCAL_DIR)/timer.o
+
+
+#	$(LOCAL_DIR)/console.o \
+
+MEMBASE := 0x10000000
+#MEMSIZE := 0x02000000	# 32MB
+
+LINKER_SCRIPT += \
+	$(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/omap5912/timer.c b/platform/omap5912/timer.c
new file mode 100644
index 0000000..72659f1
--- /dev/null
+++ b/platform/omap5912/timer.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <debug.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/omap5912.h>
+#include "platform_p.h"
+
+static time_t system_time = 0;
+
+static time_t tick_interval;
+static uint32_t ticks_per_interval;
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+	enter_critical_section();
+
+	t_callback = callback;
+	callback_arg = arg;
+	tick_interval = interval;
+	ticks_per_interval = interval * 32768 / 1000; // interval is in ms
+
+	OS_TIMER_CTRL_REG = 0; // stop it
+	OS_TIMER_TICK_VALUE_REG = ticks_per_interval;
+	OS_TIMER_CTRL_REG = (1<<3) | (1<<2) | (1<<1) | (1<<0);
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+	time_t t;
+	uint32_t delta_ticks;
+	uint32_t delta_ticks2;
+
+retry:
+	delta_ticks = OS_TIMER_TICK_COUNTER_REG;
+	t = system_time;
+	delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
+	if (delta_ticks2 > delta_ticks)
+		goto retry;
+
+	t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
+
+	return t;
+}
+
+bigtime_t current_time_hires(void)
+{
+	time_t t;
+	uint32_t delta_ticks;
+	uint32_t delta_ticks2;
+
+retry:
+	delta_ticks = OS_TIMER_TICK_COUNTER_REG;
+	t = system_time;
+	delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
+	if (delta_ticks2 > delta_ticks)
+		goto retry;
+
+	t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
+
+	return t * 1000ULL;
+}
+
+
+static enum handler_return os_timer_tick(void *arg)
+{
+	system_time += tick_interval;
+//	dprintf("os_timer_tick %d\n", system_time);
+
+	return t_callback(callback_arg, system_time);
+}
+
+void platform_init_timer(void)
+{
+	OS_TIMER_CTRL_REG = 0; // stop the timer if it's already running
+
+	register_int_handler(IRQ_OS_TIMER, &os_timer_tick, NULL);
+	unmask_interrupt(IRQ_OS_TIMER, NULL);
+}
+
diff --git a/platform/rules.mk b/platform/rules.mk
new file mode 100644
index 0000000..c1acc50
--- /dev/null
+++ b/platform/rules.mk
@@ -0,0 +1,7 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+# shared platform code
+OBJS += \
+	$(LOCAL_DIR)/debug.o \
+	$(LOCAL_DIR)/init.o
+