TFTP boot working
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Fri, 5 Mar 2010 16:19:34 +0000 (17:19 +0100)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Fri, 5 Mar 2010 16:19:34 +0000 (17:19 +0100)
build_bios.sh
build_demo.sh
software/bios/Makefile
software/bios/boot.c
software/bios/boot.h
software/bios/main.c
software/demo/Makefile
software/demo/main.c
software/include/net/microudp.h
software/libnet/Makefile
software/libnet/microudp.c

index 66cd1ca..5767c1d 100755 (executable)
@@ -35,6 +35,14 @@ if [ "$?" != 0 ] ; then
 else
         echo "OK"
 fi
+echo -n "  Networking library..."
+cd $BASEDIR/software/libnet && make >> $LOGFILE 2>&1
+if [ "$?" != 0 ] ; then
+        echo "FAILED"
+       exit 1
+else
+        echo "OK"
+fi
 echo -n "  BIOS..."
 cd $BASEDIR/software/bios && make >> $LOGFILE 2>&1
 if [ "$?" != 0 ] ; then
index d6d796b..36bf85a 100755 (executable)
@@ -53,14 +53,6 @@ if [ "$?" != 0 ] ; then
 else
         echo "OK"
 fi
-echo -n "  Networking library..."
-cd $BASEDIR/software/libnet && make >> $LOGFILE 2>&1
-if [ "$?" != 0 ] ; then
-        echo "FAILED"
-       exit 1
-else
-        echo "OK"
-fi
 echo -n "  Demonstration firmware..."
 cd $BASEDIR/software/demo && make >> $LOGFILE 2>&1
 if [ "$?" != 0 ] ; then
index 04634ce..20d96d2 100644 (file)
@@ -11,8 +11,8 @@ all: bios_splash.bin
        chmod -x $@
        $(MMDIR)/tools/crc32 $@ write
 
-bios.elf: linker.ld $(OBJECTS)
-       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ $(OBJECTS) -L$(MMDIR)/software/libbase -lbase-light
+bios.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libbase/libbase-light.a $(MMDIR)/software/libnet/libnet.a
+       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ $(OBJECTS) -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libnet -lbase-light -lnet
        chmod -x $@
 
 splash.raw: splash.png
@@ -38,7 +38,8 @@ boot.o: ../../software/include/stdio.h ../../software/include/stdlib.h
 boot.o: ../../software/include/console.h ../../software/include/uart.h
 boot.o: ../../software/include/system.h ../../software/include/board.h
 boot.o: ../../software/include/cffat.h ../../software/include/crc.h
-boot.o: ../../tools/sfl.h ../../software/include/hw/hpdmc.h
+boot.o: ../../tools/sfl.h ../../software/include/net/microudp.h
+boot.o: ../../software/include/net/tftp.h ../../software/include/hw/hpdmc.h
 boot.o: ../../software/include/hw/common.h boot.h
 main.o: ../../software/include/stdio.h ../../software/include/stdlib.h
 main.o: ../../software/include/console.h ../../software/include/string.h
index 7b41b65..927f506 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <cffat.h>
 #include <crc.h>
 #include <sfl.h>
+
+#include <net/microudp.h>
+#include <net/tftp.h>
+
 #include <hw/hpdmc.h>
 
 #include "boot.h"
@@ -47,7 +51,7 @@ static void __attribute__((noinline)) __attribute__((noreturn)) boot(unsigned in
 }
 
 /* Note that we do not use the hw timer so that this function works
- * even if the system controller has been disabled at synthesis.
+ * even if the system controller does not.
  */
 static int check_ack()
 {
@@ -188,6 +192,49 @@ void serialboot()
        }
 }
 
+static unsigned char macadr[] = {0xf8, 0x71, 0xfe, 0x01, 0x02, 0x03};
+
+void netboot()
+{
+       int size;
+       unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
+       unsigned int ip;
+
+       printf("I: Booting from network...\n");
+       printf("I: MAC      : %02x:%02x:%02x:%02x:%02x:%02x\n", macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]);
+       printf("I: Local IP : 192.168.0.42\n");
+       printf("I: Remote IP: 192.168.0.14\n");
+
+       ip = IPTOINT(192,168,0,14);
+       
+       microudp_start(macadr, IPTOINT(192,168,0,42), (void *)(SDRAM_BASE+1024*1024*(brd_desc->sdram_size-2)));
+       
+       if(tftp_get(ip, "boot.bin", (void *)SDRAM_BASE) <= 0) {
+               printf("E: Unable to download boot.bin\n");
+               return;
+       }
+       
+       cmdline_adr = SDRAM_BASE+0x1000000;
+       if(tftp_get(ip, "cmdline.txt", (void *)cmdline_adr) <= 0) {
+               printf("I: No command line parameters found\n");
+               cmdline_adr = 0;
+       }
+
+       initrdstart_adr = SDRAM_BASE+0x1002000;
+       size = tftp_get(ip, "initrd.bin", (void *)initrdstart_adr);
+       if(size <= 0) {
+               printf("I: No initial ramdisk found\n");
+               initrdstart_adr = 0;
+               initrdend_adr = 0;
+       } else
+               initrdend_adr = initrdstart_adr + size - 1;
+
+       microudp_shutdown();
+
+       printf("I: Booting...\n");
+       boot(cmdline_adr, initrdstart_adr, initrdend_adr, SDRAM_BASE);
+}
+
 static int tryload(char *filename, unsigned int address)
 {
        int devsize, realsize;
@@ -200,11 +247,12 @@ static int tryload(char *filename, unsigned int address)
                cffat_done();
                return -1;
        }
-       printf("I: Read a %d byte image from %s, CRC32 %08x\n", realsize, filename, crc32((unsigned char *)SDRAM_BASE, realsize));
+       printf("I: Read a %d byte image from %s\n", realsize, filename);
        
        return realsize;
 }
 
+
 void cardboot(int alt)
 {
        int size;
index a15f86c..a0b9e38 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
@@ -18,7 +18,9 @@
 #ifndef __BOOT_H
 #define __BOOT_H
 
-void cardboot(int alt);
 void serialboot();
+void netboot();
+void cardboot(int alt);
+
 
 #endif /* __BOOT_H */
index f39af84..37bef60 100644 (file)
@@ -423,6 +423,7 @@ static void help()
        puts("ls         - list files on the memory card");
        puts("load       - load a file from the memory card");
        puts("serialboot - attempt SFL boot");
+       puts("netboot    - boot via TFTP");
        puts("cardboot   - attempt booting from memory card");
        puts("reboot     - system reset");
 }
@@ -463,6 +464,7 @@ static void do_command(char *c)
        else if(strcmp(token, "load") == 0) load(get_token(&c), get_token(&c));
        
        else if(strcmp(token, "serialboot") == 0) serialboot();
+       else if(strcmp(token, "netboot") == 0) netboot();
        else if(strcmp(token, "cardboot") == 0) cardboot(0);
 
        else if(strcmp(token, "reboot") == 0) reboot();
@@ -534,9 +536,10 @@ static const char banner[] =
 
 static void boot_sequence()
 {
-       splash_display((void *)(SDRAM_BASE+1024*1024*(brd_desc->sdram_size-4)));
+       splash_display((void *)(SDRAM_BASE+1024*1024*(brd_desc->sdram_size-1)));
        if(test_user_abort()) {
                serialboot(1);
+               netboot();
                if(brd_desc->memory_card != MEMCARD_NONE) {
                        if(CSR_GPIO_IN & GPIO_DIP1)
                                cardboot(1);
index 86c8cd4..47cfe89 100644 (file)
@@ -30,8 +30,8 @@ spam.h: spam.raw
        chmod -x $@
        $(MMDIR)/tools/crc32 $@
 
-boot.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libbase/libbase.a $(MMDIR)/software/libmath/libmath.a $(MMDIR)/software/libhal/libhal.a $(MMDIR)/software/libnet/libnet.a
-       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libmath -L$(MMDIR)/software/libhal -L$(MMDIR)/software/libnet --start-group $(OBJECTS) -lbase -lmath -lhal -lnet --end-group
+boot.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libbase/libbase.a $(MMDIR)/software/libmath/libmath.a $(MMDIR)/software/libhal/libhal.a
+       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libmath -L$(MMDIR)/software/libhal --start-group $(OBJECTS) -lbase -lmath -lhal --end-group
        chmod -x $@
 
 .PHONY: clean depend
index ae8a024..c48d493 100644 (file)
@@ -33,9 +33,6 @@
 #include <hal/slowout.h>
 #include <hal/hdlcd.h>
 
-#include <net/microudp.h>
-#include <net/tftp.h>
-
 #include "apipe.h"
 #include "rpipe.h"
 #include "renderer.h"
@@ -52,48 +49,33 @@ static void banner()
                          "\e[0m           SoC demo program\n\n\n");
 }
 
-static unsigned char macadr[] = {0xf8, 0x71, 0xfe, 0x01, 0x02, 0x03};
-
-static char tftp_buffer[128*1024];
-
 int main()
 {
-       int len, i;
-       
        irq_setmask(0);
        irq_enable(1);
        uart_async_init();
        banner();
-       
-       microudp_start(macadr, IPTOINT(192,168,0,42));
-       len = tftp_get(IPTOINT(192,168,0,14), "programme.txt", tftp_buffer);
-       microudp_shutdown();
-       printf("Got %d bytes\n", len);
-       for(i=0;i<len;i++)
-               writechar(tftp_buffer[i]);
-       
        brd_init();
        cpustats_init();
        time_init();
        mem_init();
-       //vga_init();
-       //snd_init();
-       //pfpu_init();
-       //tmu_init();
-       //renderer_init();
-       //apipe_init();
-       //rpipe_init();
-       //slowout_init();
-       //hdlcd_init();
-       //ui_init();
+       vga_init();
+       snd_init();
+       pfpu_init();
+       tmu_init();
+       renderer_init();
+       apipe_init();
+       rpipe_init();
+       slowout_init();
+       hdlcd_init();
+       ui_init();
        shell_init();
        
        while(1) {
                if(readchar_nonblock())
                        shell_input(readchar());
-               microudp_service();
-               //apipe_service();
-               //rpipe_service();
+               apipe_service();
+               rpipe_service();
        }
        
        return 0;
index 0fbd1be..f75fb0b 100644 (file)
@@ -22,7 +22,7 @@
 
 typedef void (*udp_callback)(unsigned int src_ip, unsigned short src_port, unsigned short dst_port, void *data, unsigned int length);
 
-void microudp_start(unsigned char *macaddr, unsigned int ip);
+void microudp_start(unsigned char *macaddr, unsigned int ip, void *buffers);
 int microudp_arp_resolve(unsigned int ip);
 void *microudp_get_tx_buffer();
 int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int length);
index 57f1c32..7b60430 100644 (file)
@@ -21,3 +21,11 @@ clean:
 
 mdio.o: ../../software/include/hw/minimac.h
 mdio.o: ../../software/include/hw/common.h ../../software/include/net/mdio.h
+microudp.o: ../../software/include/stdio.h ../../software/include/stdlib.h
+microudp.o: ../../software/include/crc.h ../../software/include/hw/minimac.h
+microudp.o: ../../software/include/hw/common.h
+microudp.o: ../../software/include/hw/sysctl.h
+microudp.o: ../../software/include/net/microudp.h
+tftp.o: ../../software/include/stdio.h ../../software/include/stdlib.h
+tftp.o: ../../software/include/string.h ../../software/include/net/microudp.h
+tftp.o: ../../software/include/net/tftp.h
index f5509b7..5de7d88 100644 (file)
@@ -106,26 +106,26 @@ struct ethernet_frame {
 
 typedef union {
        struct ethernet_frame frame;
-       unsigned char raw[1530];
+       unsigned char raw[1532];
 } ethernet_buffer;
 
 
 static int rxlen;
-static ethernet_buffer rxbuffer __attribute__((aligned(4)));
+static ethernet_buffer *rxbuffer;
 static int txlen;
-static ethernet_buffer txbuffer __attribute__((aligned(4)));
+static ethernet_buffer *txbuffer;
 
 static void send_packet()
 {
        unsigned int crc;
        
-       crc = crc32(&txbuffer.raw[8], txlen-8);
-       txbuffer.raw[txlen  ] = (crc & 0xff);
-       txbuffer.raw[txlen+1] = (crc & 0xff00) >> 8;
-       txbuffer.raw[txlen+2] = (crc & 0xff0000) >> 16;
-       txbuffer.raw[txlen+3] = (crc & 0xff000000) >> 24;
+       crc = crc32(&txbuffer->raw[8], txlen-8);
+       txbuffer->raw[txlen  ] = (crc & 0xff);
+       txbuffer->raw[txlen+1] = (crc & 0xff00) >> 8;
+       txbuffer->raw[txlen+2] = (crc & 0xff0000) >> 16;
+       txbuffer->raw[txlen+3] = (crc & 0xff000000) >> 24;
        txlen += 4;
-       CSR_MINIMAC_TXADR = (unsigned int)&txbuffer;
+       CSR_MINIMAC_TXADR = (unsigned int)txbuffer;
        CSR_MINIMAC_TXREMAINING = txlen;
        while(CSR_MINIMAC_TXREMAINING != 0);
 }
@@ -140,38 +140,38 @@ static unsigned int cached_ip;
 static void process_arp()
 {
        if(rxlen < 68) return;
-       if(rxbuffer.frame.contents.arp.hwtype != ARP_HWTYPE_ETHERNET) return;
-       if(rxbuffer.frame.contents.arp.proto != ARP_PROTO_IP) return;
-       if(rxbuffer.frame.contents.arp.hwsize != 6) return;
-       if(rxbuffer.frame.contents.arp.protosize != 4) return;
-       if(rxbuffer.frame.contents.arp.opcode == ARP_OPCODE_REPLY) {
-               if(rxbuffer.frame.contents.arp.sender_ip == cached_ip) {
+       if(rxbuffer->frame.contents.arp.hwtype != ARP_HWTYPE_ETHERNET) return;
+       if(rxbuffer->frame.contents.arp.proto != ARP_PROTO_IP) return;
+       if(rxbuffer->frame.contents.arp.hwsize != 6) return;
+       if(rxbuffer->frame.contents.arp.protosize != 4) return;
+       if(rxbuffer->frame.contents.arp.opcode == ARP_OPCODE_REPLY) {
+               if(rxbuffer->frame.contents.arp.sender_ip == cached_ip) {
                        int i;
                        for(i=0;i<6;i++)
-                               cached_mac[i] = rxbuffer.frame.contents.arp.sender_mac[i];
+                               cached_mac[i] = rxbuffer->frame.contents.arp.sender_mac[i];
                }
                return;
        }
-       if(rxbuffer.frame.contents.arp.opcode == ARP_OPCODE_REQUEST) {
-               if(rxbuffer.frame.contents.arp.target_ip == my_ip) {
+       if(rxbuffer->frame.contents.arp.opcode == ARP_OPCODE_REQUEST) {
+               if(rxbuffer->frame.contents.arp.target_ip == my_ip) {
                        int i;
                        
-                       fill_eth_header(&txbuffer.frame.eth_header,
-                               rxbuffer.frame.contents.arp.sender_mac,
+                       fill_eth_header(&txbuffer->frame.eth_header,
+                               rxbuffer->frame.contents.arp.sender_mac,
                                my_mac,
                                ETHERTYPE_ARP);
                        txlen = 68;
-                       txbuffer.frame.contents.arp.hwtype = ARP_HWTYPE_ETHERNET;
-                       txbuffer.frame.contents.arp.proto = ARP_PROTO_IP;
-                       txbuffer.frame.contents.arp.hwsize = 6;
-                       txbuffer.frame.contents.arp.protosize = 4;
-                       txbuffer.frame.contents.arp.opcode = ARP_OPCODE_REPLY;
-                       txbuffer.frame.contents.arp.sender_ip = my_ip;
+                       txbuffer->frame.contents.arp.hwtype = ARP_HWTYPE_ETHERNET;
+                       txbuffer->frame.contents.arp.proto = ARP_PROTO_IP;
+                       txbuffer->frame.contents.arp.hwsize = 6;
+                       txbuffer->frame.contents.arp.protosize = 4;
+                       txbuffer->frame.contents.arp.opcode = ARP_OPCODE_REPLY;
+                       txbuffer->frame.contents.arp.sender_ip = my_ip;
                        for(i=0;i<6;i++)
-                               txbuffer.frame.contents.arp.sender_mac[i] = my_mac[i];
-                       txbuffer.frame.contents.arp.target_ip = rxbuffer.frame.contents.arp.sender_ip;
+                               txbuffer->frame.contents.arp.sender_mac[i] = my_mac[i];
+                       txbuffer->frame.contents.arp.target_ip = rxbuffer->frame.contents.arp.sender_ip;
                        for(i=0;i<6;i++)
-                               txbuffer.frame.contents.arp.target_mac[i] = rxbuffer.frame.contents.arp.sender_mac[i];
+                               txbuffer->frame.contents.arp.target_mac[i] = rxbuffer->frame.contents.arp.sender_mac[i];
                        send_packet();
                }
                return;
@@ -196,22 +196,22 @@ int microudp_arp_resolve(unsigned int ip)
 
        for(tries=0;tries<5;tries++) {
                /* Send an ARP request */
-               fill_eth_header(&txbuffer.frame.eth_header,
+               fill_eth_header(&txbuffer->frame.eth_header,
                                broadcast,
                                my_mac,
                                ETHERTYPE_ARP);
                txlen = 68;
-               txbuffer.frame.contents.arp.hwtype = ARP_HWTYPE_ETHERNET;
-               txbuffer.frame.contents.arp.proto = ARP_PROTO_IP;
-               txbuffer.frame.contents.arp.hwsize = 6;
-               txbuffer.frame.contents.arp.protosize = 4;
-               txbuffer.frame.contents.arp.opcode = ARP_OPCODE_REQUEST;
-               txbuffer.frame.contents.arp.sender_ip = my_ip;
+               txbuffer->frame.contents.arp.hwtype = ARP_HWTYPE_ETHERNET;
+               txbuffer->frame.contents.arp.proto = ARP_PROTO_IP;
+               txbuffer->frame.contents.arp.hwsize = 6;
+               txbuffer->frame.contents.arp.protosize = 4;
+               txbuffer->frame.contents.arp.opcode = ARP_OPCODE_REQUEST;
+               txbuffer->frame.contents.arp.sender_ip = my_ip;
                for(i=0;i<6;i++)
-                       txbuffer.frame.contents.arp.sender_mac[i] = my_mac[i];
-               txbuffer.frame.contents.arp.target_ip = ip;
+                       txbuffer->frame.contents.arp.sender_mac[i] = my_mac[i];
+               txbuffer->frame.contents.arp.target_ip = ip;
                for(i=0;i<6;i++)
-                       txbuffer.frame.contents.arp.target_mac[i] = 0;
+                       txbuffer->frame.contents.arp.target_mac[i] = 0;
                send_packet();
 
                /* Do we get a reply ? */
@@ -250,7 +250,7 @@ static unsigned short ip_checksum(unsigned int r, void *buffer, unsigned int len
 
 void *microudp_get_tx_buffer()
 {
-       return txbuffer.frame.contents.udp.payload;
+       return txbuffer->frame.contents.udp.payload;
 }
 
 struct pseudo_header {
@@ -273,38 +273,38 @@ int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int
        txlen = length + sizeof(struct ethernet_header) + sizeof(struct udp_frame) + 8;
        if(txlen < 72) txlen = 72;
        
-       fill_eth_header(&txbuffer.frame.eth_header,
+       fill_eth_header(&txbuffer->frame.eth_header,
                cached_mac,
                my_mac,
                ETHERTYPE_IP);
        
-       txbuffer.frame.contents.udp.ip.version = IP_IPV4;
-       txbuffer.frame.contents.udp.ip.diff_services = 0;
-       txbuffer.frame.contents.udp.ip.total_length = length + sizeof(struct udp_frame);
-       txbuffer.frame.contents.udp.ip.identification = 0;
-       txbuffer.frame.contents.udp.ip.fragment_offset = IP_DONT_FRAGMENT;
-       txbuffer.frame.contents.udp.ip.ttl = IP_TTL;
-       h.proto = txbuffer.frame.contents.udp.ip.proto = IP_PROTO_UDP;
-       txbuffer.frame.contents.udp.ip.checksum = 0;
-       h.src_ip = txbuffer.frame.contents.udp.ip.src_ip = my_ip;
-       h.dst_ip = txbuffer.frame.contents.udp.ip.dst_ip = cached_ip;
-       txbuffer.frame.contents.udp.ip.checksum = ip_checksum(0, &txbuffer.frame.contents.udp.ip,
+       txbuffer->frame.contents.udp.ip.version = IP_IPV4;
+       txbuffer->frame.contents.udp.ip.diff_services = 0;
+       txbuffer->frame.contents.udp.ip.total_length = length + sizeof(struct udp_frame);
+       txbuffer->frame.contents.udp.ip.identification = 0;
+       txbuffer->frame.contents.udp.ip.fragment_offset = IP_DONT_FRAGMENT;
+       txbuffer->frame.contents.udp.ip.ttl = IP_TTL;
+       h.proto = txbuffer->frame.contents.udp.ip.proto = IP_PROTO_UDP;
+       txbuffer->frame.contents.udp.ip.checksum = 0;
+       h.src_ip = txbuffer->frame.contents.udp.ip.src_ip = my_ip;
+       h.dst_ip = txbuffer->frame.contents.udp.ip.dst_ip = cached_ip;
+       txbuffer->frame.contents.udp.ip.checksum = ip_checksum(0, &txbuffer->frame.contents.udp.ip,
                sizeof(struct ip_header), 1);
 
-       txbuffer.frame.contents.udp.udp.src_port = src_port;
-       txbuffer.frame.contents.udp.udp.dst_port = dst_port;
-       h.length = txbuffer.frame.contents.udp.udp.length = length + sizeof(struct udp_header);
-       txbuffer.frame.contents.udp.udp.checksum = 0;
+       txbuffer->frame.contents.udp.udp.src_port = src_port;
+       txbuffer->frame.contents.udp.udp.dst_port = dst_port;
+       h.length = txbuffer->frame.contents.udp.udp.length = length + sizeof(struct udp_header);
+       txbuffer->frame.contents.udp.udp.checksum = 0;
 
        h.zero = 0;
        r = ip_checksum(0, &h, sizeof(struct pseudo_header), 0);
        if(length & 1) {
-               txbuffer.frame.contents.udp.payload[length] = 0;
+               txbuffer->frame.contents.udp.payload[length] = 0;
                length++;
        }
-       r = ip_checksum(r, &txbuffer.frame.contents.udp.udp,
+       r = ip_checksum(r, &txbuffer->frame.contents.udp.udp,
                sizeof(struct udp_header)+length, 1);
-       txbuffer.frame.contents.udp.udp.checksum = r;
+       txbuffer->frame.contents.udp.udp.checksum = r;
        
        send_packet();
 
@@ -317,16 +317,16 @@ static void process_ip()
 {
        if(rxlen < (sizeof(struct ethernet_header)+sizeof(struct udp_frame))) return;
        /* We don't verify UDP and IP checksums and rely on the Ethernet checksum solely */
-       if(rxbuffer.frame.contents.udp.ip.version != IP_IPV4) return;
-       if(rxbuffer.frame.contents.udp.ip.diff_services != 0) return;
-       if(rxbuffer.frame.contents.udp.ip.total_length < sizeof(struct udp_frame)) return;
-       if(rxbuffer.frame.contents.udp.ip.fragment_offset != IP_DONT_FRAGMENT) return;
-       if(rxbuffer.frame.contents.udp.ip.proto != IP_PROTO_UDP) return;
-       if(rxbuffer.frame.contents.udp.ip.dst_ip != my_ip) return;
-       if(rxbuffer.frame.contents.udp.udp.length < sizeof(struct udp_header)) return;
+       if(rxbuffer->frame.contents.udp.ip.version != IP_IPV4) return;
+       if(rxbuffer->frame.contents.udp.ip.diff_services != 0) return;
+       if(rxbuffer->frame.contents.udp.ip.total_length < sizeof(struct udp_frame)) return;
+       if(rxbuffer->frame.contents.udp.ip.fragment_offset != IP_DONT_FRAGMENT) return;
+       if(rxbuffer->frame.contents.udp.ip.proto != IP_PROTO_UDP) return;
+       if(rxbuffer->frame.contents.udp.ip.dst_ip != my_ip) return;
+       if(rxbuffer->frame.contents.udp.udp.length < sizeof(struct udp_header)) return;
 
        if(rx_callback)
-               rx_callback(rxbuffer.frame.contents.udp.ip.src_ip, rxbuffer.frame.contents.udp.udp.src_port, rxbuffer.frame.contents.udp.udp.dst_port, rxbuffer.frame.contents.udp.payload, rxbuffer.frame.contents.udp.udp.length-sizeof(struct udp_header));
+               rx_callback(rxbuffer->frame.contents.udp.ip.src_ip, rxbuffer->frame.contents.udp.udp.src_port, rxbuffer->frame.contents.udp.udp.dst_port, rxbuffer->frame.contents.udp.payload, rxbuffer->frame.contents.udp.udp.length-sizeof(struct udp_header));
 }
 
 void microudp_set_callback(udp_callback callback)
@@ -341,23 +341,27 @@ static void process_frame()
        unsigned int computed_crc;
 
        for(i=0;i<7;i++)
-               if(rxbuffer.frame.eth_header.preamble[i] != 0x55) return;
-       if(rxbuffer.frame.eth_header.preamble[7] != 0xd5) return;
-       received_crc = ((unsigned int)rxbuffer.raw[rxlen-1] << 24)
-               |((unsigned int)rxbuffer.raw[rxlen-2] << 16)
-               |((unsigned int)rxbuffer.raw[rxlen-3] <<  8)
-               |((unsigned int)rxbuffer.raw[rxlen-4]);
-       computed_crc = crc32(&rxbuffer.raw[8], rxlen-12);
+               if(rxbuffer->frame.eth_header.preamble[i] != 0x55) return;
+       if(rxbuffer->frame.eth_header.preamble[7] != 0xd5) return;
+       received_crc = ((unsigned int)rxbuffer->raw[rxlen-1] << 24)
+               |((unsigned int)rxbuffer->raw[rxlen-2] << 16)
+               |((unsigned int)rxbuffer->raw[rxlen-3] <<  8)
+               |((unsigned int)rxbuffer->raw[rxlen-4]);
+       computed_crc = crc32(&rxbuffer->raw[8], rxlen-12);
        if(received_crc != computed_crc) return;
 
        rxlen -= 4; /* strip CRC here to be consistent with TX */
-       if(rxbuffer.frame.eth_header.ethertype == ETHERTYPE_ARP) process_arp();
-       else if(rxbuffer.frame.eth_header.ethertype == ETHERTYPE_IP) process_ip();
+       if(rxbuffer->frame.eth_header.ethertype == ETHERTYPE_ARP) process_arp();
+       else if(rxbuffer->frame.eth_header.ethertype == ETHERTYPE_IP) process_ip();
 }
 
-void microudp_start(unsigned char *macaddr, unsigned int ip)
+void microudp_start(unsigned char *macaddr, unsigned int ip, void *buffers)
 {
        int i;
+       char *_buffers = (char *)buffers;
+
+       rxbuffer = (ethernet_buffer *)_buffers;
+       txbuffer = (ethernet_buffer *)(_buffers + sizeof(ethernet_buffer));
 
        for(i=0;i<6;i++)
                my_mac[i] = macaddr[i];
@@ -369,7 +373,7 @@ void microudp_start(unsigned char *macaddr, unsigned int ip)
 
        rx_callback = (udp_callback)0;
        
-       CSR_MINIMAC_ADDR0 = (unsigned int)&rxbuffer;
+       CSR_MINIMAC_ADDR0 = (unsigned int)rxbuffer;
        CSR_MINIMAC_STATE0 = MINIMAC_STATE_LOADED;
        CSR_MINIMAC_SETUP = 0;
 }