software/bios: rename libnet to libliteeth and move all ethernet files to it.
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 18 May 2020 19:04:54 +0000 (21:04 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 18 May 2020 19:04:54 +0000 (21:04 +0200)
15 files changed:
litex/soc/integration/builder.py
litex/soc/software/bios/Makefile
litex/soc/software/bios/boot.c
litex/soc/software/bios/main.c
litex/soc/software/common.mak
litex/soc/software/include/net/microudp.h [deleted file]
litex/soc/software/include/net/tftp.h [deleted file]
litex/soc/software/libliteeth/Makefile [new file with mode: 0644]
litex/soc/software/libliteeth/tftp.c [new file with mode: 0644]
litex/soc/software/libliteeth/tftp.h [new file with mode: 0644]
litex/soc/software/libliteeth/udp.c [new file with mode: 0644]
litex/soc/software/libliteeth/udp.h [new file with mode: 0644]
litex/soc/software/libnet/Makefile [deleted file]
litex/soc/software/libnet/microudp.c [deleted file]
litex/soc/software/libnet/tftp.c [deleted file]

index 4fd1b2330347d3044acf14e50a71368c4267f618..79c6b95d39e1a1b2486e29060ccad6da988d2a55 100644 (file)
@@ -25,7 +25,7 @@ __all__ = ["soc_software_packages", "soc_directory",
 soc_software_packages = [
     "libcompiler_rt",
     "libbase",
-    "libnet",
+    "libliteeth",
     "bios"
 ]
 
index ac7725e6037e81cef9d74b47aa3cf70ff49e364c..8d4090b7bf8822a849f6bb1d5d28660cc9d77f65 100755 (executable)
@@ -59,15 +59,15 @@ endif
 bios.elf: $(BIOS_DIRECTORY)/linker.ld $(OBJECTS)
 
 
-%.elf: ../libbase/crt0-ctr.o ../libnet/libnet.a ../libbase/libbase-nofloat.a ../libcompiler_rt/libcompiler_rt.a
+%.elf: ../libbase/crt0-ctr.o ../libliteeth/libliteeth.a ../libbase/libbase-nofloat.a ../libcompiler_rt/libcompiler_rt.a
        $(LD) $(LDFLAGS) -T $(BIOS_DIRECTORY)/linker.ld -N -o $@ \
                ../libbase/crt0-ctr.o \
                $(OBJECTS) \
-               -L../libnet \
+               -L../libliteeth \
                -L../libbase \
                -L../libcompiler_rt \
                $(BP_LIBS) \
-               -lnet -lbase-nofloat -lcompiler_rt \
+               -lliteeth -lbase-nofloat -lcompiler_rt \
                $(BP_FLAGS)
 
 ifneq ($(OS),Windows_NT)
index c12cfe25142e006b8fbe4dc7f21cbc5ec04a89fc..36993a6fe888c44de21d1c5cb47c232a8ceeeb50 100644 (file)
@@ -21,8 +21,8 @@
 #include <generated/soc.h>
 
 #ifdef CSR_ETHMAC_BASE
-#include <net/microudp.h>
-#include <net/tftp.h>
+#include <udp.h>
+#include <tftp.h>
 #endif
 
 #ifdef CSR_SPIFLASH_BASE
@@ -340,7 +340,7 @@ void netboot(void)
 
        ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
 
-       microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
+       udp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
 
        tftp_port = TFTP_SERVER_PORT;
        printf("Fetching from: UDP/%d\n", tftp_port);
index 7864260aa375fae11cddaf3c28894298177c289b..a9857c88d8c56360fc9683c86b1b4249ffd1b7b4 100644 (file)
@@ -30,7 +30,7 @@
 #include <generated/git.h>
 
 #ifdef CSR_ETHMAC_BASE
-#include <net/microudp.h>
+#include "udp.h"
 #endif
 
 #ifdef CSR_SPIFLASH_BASE
index 83f1aba42568f658f47c446de7c132ff1545b7d3..fb97fc4803e775bf224e5b0fd6364500a46c0e74 100644 (file)
@@ -45,7 +45,12 @@ DEPFLAGS += -MD -MP
 
 # Toolchain options
 #
-INCLUDES = -I$(SOC_DIRECTORY)/software/include/base -I$(SOC_DIRECTORY)/software/include -I$(SOC_DIRECTORY)/common -I$(BUILDINC_DIRECTORY) -I$(CPU_DIRECTORY)
+INCLUDES = -I$(SOC_DIRECTORY)/software/include/base \
+           -I$(SOC_DIRECTORY)/software/include \
+           -I$(SOC_DIRECTORY)/common \
+           -I$(BUILDINC_DIRECTORY) \
+           -I$(CPU_DIRECTORY) \
+           -I$(SOC_DIRECTORY)/software/libliteeth
 COMMONFLAGS = $(DEPFLAGS) -Os $(CPUFLAGS) -g3 -fomit-frame-pointer -Wall -fno-builtin -nostdinc $(INCLUDES)
 CFLAGS = $(COMMONFLAGS) -fexceptions -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes
 CXXFLAGS = $(COMMONFLAGS) -std=c++11 -I$(SOC_DIRECTORY)/software/include/basec++ -fexceptions -fno-rtti -ffreestanding
diff --git a/litex/soc/software/include/net/microudp.h b/litex/soc/software/include/net/microudp.h
deleted file mode 100644 (file)
index f148a34..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __MICROUDP_H
-#define __MICROUDP_H
-
-#define IPTOINT(a, b, c, d) ((a << 24)|(b << 16)|(c << 8)|d)
-
-#define MICROUDP_BUFSIZE (5*1532)
-
-typedef void (*udp_callback)(unsigned int src_ip, unsigned short src_port, unsigned short dst_port, void *data, unsigned int length);
-
-void microudp_start(const unsigned char *macaddr, unsigned int ip);
-int microudp_arp_resolve(unsigned int ip);
-void *microudp_get_tx_buffer(void);
-int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int length);
-void microudp_set_callback(udp_callback callback);
-void microudp_service(void);
-
-void eth_init(void);
-void eth_mode(void);
-
-#endif /* __MICROUDP_H */
diff --git a/litex/soc/software/include/net/tftp.h b/litex/soc/software/include/net/tftp.h
deleted file mode 100644 (file)
index 788731b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __TFTP_H
-#define __TFTP_H
-
-#include <stdint.h>
-
-int tftp_get(uint32_t ip, uint16_t server_port, const char *filename,
-    void *buffer);
-int tftp_put(uint32_t ip, uint16_t server_port, const char *filename,
-    const void *buffer, int size);
-
-#endif /* __TFTP_H */
-
diff --git a/litex/soc/software/libliteeth/Makefile b/litex/soc/software/libliteeth/Makefile
new file mode 100644 (file)
index 0000000..593acc2
--- /dev/null
@@ -0,0 +1,23 @@
+include ../include/generated/variables.mak
+include $(SOC_DIRECTORY)/software/common.mak
+
+OBJECTS=udp.o tftp.o
+
+all: libliteeth.a
+
+libliteeth.a: $(OBJECTS)
+       $(AR) crs libliteeth.a $(OBJECTS)
+
+# pull in dependency info for *existing* .o files
+-include $(OBJECTS:.o=.d)
+
+%.o: $(LIBLITEETH_DIRECTORY)/%.c
+       $(compile)
+
+%.o: %.S
+       $(assemble)
+
+.PHONY: all clean
+
+clean:
+       $(RM) $(OBJECTS) libliteeth.a .*~ *~
diff --git a/litex/soc/software/libliteeth/tftp.c b/litex/soc/software/libliteeth/tftp.c
new file mode 100644 (file)
index 0000000..c5ac5f3
--- /dev/null
@@ -0,0 +1,236 @@
+// This file is Copyright (c) 2013 Werner Almesberger <werner@almesberger.net>
+// This file is Copyright (c) 2013-2015 Sebastien Bourdeauducq <sb@m-labs.hk>
+// This file is Copyright (c) 2014-2015 Florent Kermarec <florent@enjoy-digital.fr>
+// This file is Copyright (c) 2017 Greg Darke <greg@tsukasa.net.au>
+// This file is Copyright (c) 2018 Ewen McNeill <ewen@naos.co.nz>
+
+// License: BSD
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "udp.h"
+#include "tftp.h"
+
+/* Local TFTP client port (arbitrary) */
+#define PORT_IN                7642
+
+enum {
+       TFTP_RRQ        = 1,    /* Read request */
+       TFTP_WRQ        = 2,    /* Write request */
+       TFTP_DATA       = 3,    /* Data */
+       TFTP_ACK        = 4,    /* Acknowledgment */
+       TFTP_ERROR      = 5,    /* Error */
+};
+
+#define        BLOCK_SIZE      512     /* block size in bytes */
+
+
+static int format_request(uint8_t *buf, uint16_t op, const char *filename)
+{
+       int len = strlen(filename);
+
+       *buf++ = op >> 8; /* Opcode */
+       *buf++ = op;
+       memcpy(buf, filename, len);
+       buf += len;
+       *buf++ = 0x00;
+       *buf++ = 'o';
+       *buf++ = 'c';
+       *buf++ = 't';
+       *buf++ = 'e';
+       *buf++ = 't';
+       *buf++ = 0x00;
+       return 9+strlen(filename);
+}
+
+static int format_ack(uint8_t *buf, uint16_t block)
+{
+       *buf++ = 0x00; /* Opcode: Ack */
+       *buf++ = TFTP_ACK;
+       *buf++ = (block & 0xff00) >> 8;
+       *buf++ = (block & 0x00ff);
+       return 4;
+}
+
+static int format_data(uint8_t *buf, uint16_t block, const void *data, int len)
+{
+       *buf++ = 0x00; /* Opcode: Data*/
+       *buf++ = TFTP_DATA;
+       *buf++ = (block & 0xff00) >> 8;
+       *buf++ = (block & 0x00ff);
+       memcpy(buf, data, len);
+       return len+4;
+}
+
+static uint8_t *packet_data;
+static int total_length;
+static int transfer_finished;
+static uint8_t *dst_buffer;
+static int last_ack; /* signed, so we can use -1 */
+static uint16_t data_port;
+
+static void rx_callback(uint32_t src_ip, uint16_t src_port,
+    uint16_t dst_port, void *_data, unsigned int length)
+{
+       uint8_t *data = _data;
+       uint16_t opcode;
+       uint16_t block;
+       int i;
+       int offset;
+
+       if(length < 4) return;
+       if(dst_port != PORT_IN) return;
+       opcode = data[0] << 8 | data[1];
+       block = data[2] << 8 | data[3];
+       if(opcode == TFTP_ACK) { /* Acknowledgement */
+               data_port = src_port;
+               last_ack = block;
+               return;
+       }
+       if(block < 1) return;
+       if(opcode == TFTP_DATA) { /* Data */
+               length -= 4;
+               offset = (block-1)*BLOCK_SIZE;
+               for(i=0;i<length;i++)
+                       dst_buffer[offset+i] = data[i+4];
+               total_length += length;
+               if(length < BLOCK_SIZE)
+                       transfer_finished = 1;
+
+               packet_data = udp_get_tx_buffer();
+               length = format_ack(packet_data, block);
+               udp_send(PORT_IN, src_port, length);
+       }
+       if(opcode == TFTP_ERROR) { /* Error */
+               total_length = -1;
+               transfer_finished = 1;
+       }
+}
+
+int tftp_get(uint32_t ip, uint16_t server_port, const char *filename,
+    void *buffer)
+{
+       int len;
+       int tries;
+       int i;
+       int length_before;
+       int spin = 0;
+
+       if(!udp_arp_resolve(ip))
+               return -1;
+
+       udp_set_callback(rx_callback);
+
+       dst_buffer = buffer;
+
+       total_length = 0;
+       transfer_finished = 0;
+       tries = 5;
+       while(1) {
+               packet_data = udp_get_tx_buffer();
+               len = format_request(packet_data, TFTP_RRQ, filename);
+               udp_send(PORT_IN, server_port, len);
+               for(i=0;i<2000000;i++) {
+                       udp_service();
+                       if((total_length > 0) || transfer_finished) break;
+               }
+               if((total_length > 0) || transfer_finished) break;
+               tries--;
+               if(tries == 0) {
+                       udp_set_callback(NULL);
+                       return -1;
+               }
+       }
+
+       i = 12000000;
+       length_before = total_length;
+       while(!transfer_finished) {
+               if(length_before != total_length) {
+                       i = 12000000;
+                       length_before = total_length;
+                       if ((total_length & 0x7fff) == 0) { // every 32K
+                               putchar("|/-\\"[spin++ % 4]);
+                               putchar('\b');
+                       }
+               }
+               if(i-- == 0) {
+                       udp_set_callback(NULL);
+                       return -1;
+               }
+               udp_service();
+       }
+
+       udp_set_callback(NULL);
+
+       return total_length;
+}
+
+int tftp_put(uint32_t ip, uint16_t server_port, const char *filename,
+    const void *buffer, int size)
+{
+       int len, send;
+       int tries;
+       int i;
+       int block = 0, sent = 0;
+
+       if(!udp_arp_resolve(ip))
+               return -1;
+
+       udp_set_callback(rx_callback);
+
+       packet_data = udp_get_tx_buffer();
+
+       total_length = 0;
+       transfer_finished = 0;
+       tries = 5;
+       while(1) {
+               packet_data = udp_get_tx_buffer();
+               len = format_request(packet_data, TFTP_WRQ, filename);
+               udp_send(PORT_IN, server_port, len);
+               for(i=0;i<2000000;i++) {
+                       last_ack = -1;
+                       udp_service();
+                       if(last_ack == block)
+                               goto send_data;
+                       if(transfer_finished)
+                               goto fail;
+               }
+               tries--;
+               if(tries == 0)
+                       goto fail;
+       }
+
+send_data:
+       do {
+               block++;
+               send = sent+BLOCK_SIZE > size ? size-sent : BLOCK_SIZE;
+               tries = 5;
+               while(1) {
+                       packet_data = udp_get_tx_buffer();
+                       len = format_data(packet_data, block, buffer, send);
+                       udp_send(PORT_IN, data_port, len);
+                       for(i=0;i<12000000;i++) {
+                               udp_service();
+                               if(transfer_finished)
+                                       goto fail;
+                               if(last_ack == block)
+                                       goto next;
+                       }
+                       if (!--tries)
+                               goto fail;
+               }
+next:
+               sent += send;
+               buffer += send;
+       } while (send == BLOCK_SIZE);
+
+       udp_set_callback(NULL);
+
+       return sent;
+
+fail:
+       udp_set_callback(NULL);
+       return -1;
+}
diff --git a/litex/soc/software/libliteeth/tftp.h b/litex/soc/software/libliteeth/tftp.h
new file mode 100644 (file)
index 0000000..788731b
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __TFTP_H
+#define __TFTP_H
+
+#include <stdint.h>
+
+int tftp_get(uint32_t ip, uint16_t server_port, const char *filename,
+    void *buffer);
+int tftp_put(uint32_t ip, uint16_t server_port, const char *filename,
+    const void *buffer, int size);
+
+#endif /* __TFTP_H */
+
diff --git a/litex/soc/software/libliteeth/udp.c b/litex/soc/software/libliteeth/udp.c
new file mode 100644 (file)
index 0000000..d869621
--- /dev/null
@@ -0,0 +1,474 @@
+// This file is Copyright (c) 2013 Werner Almesberger <werner@almesberger.net>
+// This file is Copyright (c) 2014-2015 Sebastien Bourdeauducq <sb@m-labs.hk>
+// This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
+// This file is Copyright (c) 2018 Jean-François Nguyen <jf@lse.epita.fr>
+// This file is Copyright (c) 2013 Robert Jordens <jordens@gmail.com>
+// License: BSD
+
+#include <generated/csr.h>
+#include <generated/mem.h>
+
+#ifdef CSR_ETHMAC_BASE
+
+#include <stdio.h>
+#include <inet.h>
+#include <system.h>
+#include <crc.h>
+#include <hw/flags.h>
+
+#include "udp.h"
+
+//#define DEBUG_UDP_TX
+//#define DEBUG_UDP_RX
+
+#define ETHERTYPE_ARP 0x0806
+#define ETHERTYPE_IP  0x0800
+
+#ifdef CSR_ETHMAC_PREAMBLE_CRC_ADDR
+#define HW_PREAMBLE_CRC
+#endif
+
+struct ethernet_header {
+#ifndef HW_PREAMBLE_CRC
+       unsigned char preamble[8];
+#endif
+       unsigned char destmac[6];
+       unsigned char srcmac[6];
+       unsigned short ethertype;
+} __attribute__((packed));
+
+static void fill_eth_header(struct ethernet_header *h, const unsigned char *destmac, const unsigned char *srcmac, unsigned short ethertype)
+{
+       int i;
+
+#ifndef HW_PREAMBLE_CRC
+       for(i=0;i<7;i++)
+               h->preamble[i] = 0x55;
+       h->preamble[7] = 0xd5;
+#endif
+       for(i=0;i<6;i++)
+               h->destmac[i] = destmac[i];
+       for(i=0;i<6;i++)
+               h->srcmac[i] = srcmac[i];
+       h->ethertype = htons(ethertype);
+}
+
+#define ARP_HWTYPE_ETHERNET 0x0001
+#define ARP_PROTO_IP        0x0800
+#ifndef HW_PREAMBLE_CRC
+#define ARP_PACKET_LENGTH 68
+#else
+#define ARP_PACKET_LENGTH 60
+#endif
+
+#define ARP_OPCODE_REQUEST  0x0001
+#define ARP_OPCODE_REPLY    0x0002
+
+struct arp_frame {
+       unsigned short hwtype;
+       unsigned short proto;
+       unsigned char hwsize;
+       unsigned char protosize;
+       unsigned short opcode;
+       unsigned char sender_mac[6];
+       unsigned int sender_ip;
+       unsigned char target_mac[6];
+       unsigned int target_ip;
+       unsigned char padding[18];
+} __attribute__((packed));
+
+#define IP_IPV4                        0x45
+#define IP_DONT_FRAGMENT       0x4000
+#define IP_TTL                 64
+#define IP_PROTO_UDP           0x11
+
+struct ip_header {
+       unsigned char version;
+       unsigned char diff_services;
+       unsigned short total_length;
+       unsigned short identification;
+       unsigned short fragment_offset;
+       unsigned char ttl;
+       unsigned char proto;
+       unsigned short checksum;
+       unsigned int src_ip;
+       unsigned int dst_ip;
+} __attribute__((packed));
+
+struct udp_header {
+       unsigned short src_port;
+       unsigned short dst_port;
+       unsigned short length;
+       unsigned short checksum;
+} __attribute__((packed));
+
+struct udp_frame {
+       struct ip_header ip;
+       struct udp_header udp;
+       char payload[];
+} __attribute__((packed));
+
+struct ethernet_frame {
+       struct ethernet_header eth_header;
+       union {
+               struct arp_frame arp;
+               struct udp_frame udp;
+       } contents;
+} __attribute__((packed));
+
+typedef union {
+       struct ethernet_frame frame;
+       unsigned char raw[ETHMAC_SLOT_SIZE];
+} ethernet_buffer;
+
+static unsigned int rxslot;
+static unsigned int rxlen;
+static ethernet_buffer *rxbuffer;
+
+static unsigned int txslot;
+static unsigned int txlen;
+static ethernet_buffer *txbuffer;
+
+static void send_packet(void)
+{
+       /* wait buffer to be available */
+       while(!(ethmac_sram_reader_ready_read()));
+
+       /* fill txbuffer */
+#ifndef HW_PREAMBLE_CRC
+       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;
+       txlen += 4;
+#endif
+
+#ifdef DEBUG_LITEETH_UDP_TX
+       int j;
+       printf(">>>> txlen : %d\n", txlen);
+       for(j=0;j<txlen;j++)
+               printf("%02x",txbuffer->raw[j]);
+       printf("\n");
+#endif
+
+       /* fill slot, length and send */
+       ethmac_sram_reader_slot_write(txslot);
+       ethmac_sram_reader_length_write(txlen);
+       ethmac_sram_reader_start_write(1);
+
+       /* update txslot / txbuffer */
+       txslot = (txslot+1)%ETHMAC_TX_SLOTS;
+       txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot));
+}
+
+static unsigned char my_mac[6];
+static unsigned int my_ip;
+
+/* ARP cache - one entry only */
+static unsigned char cached_mac[6];
+static unsigned int cached_ip;
+
+static void process_arp(void)
+{
+       const struct arp_frame *rx_arp = &rxbuffer->frame.contents.arp;
+       struct arp_frame *tx_arp = &txbuffer->frame.contents.arp;
+
+       if(rxlen < ARP_PACKET_LENGTH) return;
+       if(ntohs(rx_arp->hwtype) != ARP_HWTYPE_ETHERNET) return;
+       if(ntohs(rx_arp->proto) != ARP_PROTO_IP) return;
+       if(rx_arp->hwsize != 6) return;
+       if(rx_arp->protosize != 4) return;
+
+       if(ntohs(rx_arp->opcode) == ARP_OPCODE_REPLY) {
+               if(ntohl(rx_arp->sender_ip) == cached_ip) {
+                       int i;
+                       for(i=0;i<6;i++)
+                               cached_mac[i] = rx_arp->sender_mac[i];
+               }
+               return;
+       }
+       if(ntohs(rx_arp->opcode) == ARP_OPCODE_REQUEST) {
+               if(ntohl(rx_arp->target_ip) == my_ip) {
+                       int i;
+
+                       fill_eth_header(&txbuffer->frame.eth_header,
+                               rx_arp->sender_mac,
+                               my_mac,
+                               ETHERTYPE_ARP);
+                       txlen = ARP_PACKET_LENGTH;
+                       tx_arp->hwtype = htons(ARP_HWTYPE_ETHERNET);
+                       tx_arp->proto = htons(ARP_PROTO_IP);
+                       tx_arp->hwsize = 6;
+                       tx_arp->protosize = 4;
+                       tx_arp->opcode = htons(ARP_OPCODE_REPLY);
+                       tx_arp->sender_ip = htonl(my_ip);
+                       for(i=0;i<6;i++)
+                               tx_arp->sender_mac[i] = my_mac[i];
+                       tx_arp->target_ip = htonl(ntohl(rx_arp->sender_ip));
+                       for(i=0;i<6;i++)
+                               tx_arp->target_mac[i] = rx_arp->sender_mac[i];
+                       send_packet();
+               }
+               return;
+       }
+}
+
+static const unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+int udp_arp_resolve(unsigned int ip)
+{
+       struct arp_frame *arp;
+       int i;
+       int tries;
+       int timeout;
+
+       if(cached_ip == ip) {
+               for(i=0;i<6;i++)
+                       if(cached_mac[i]) return 1;
+       }
+       cached_ip = ip;
+       for(i=0;i<6;i++)
+               cached_mac[i] = 0;
+
+       for(tries=0;tries<100;tries++) {
+               /* Send an ARP request */
+               fill_eth_header(&txbuffer->frame.eth_header,
+                               broadcast,
+                               my_mac,
+                               ETHERTYPE_ARP);
+               txlen = ARP_PACKET_LENGTH;
+               arp = &txbuffer->frame.contents.arp;
+               arp->hwtype = htons(ARP_HWTYPE_ETHERNET);
+               arp->proto = htons(ARP_PROTO_IP);
+               arp->hwsize = 6;
+               arp->protosize = 4;
+               arp->opcode = htons(ARP_OPCODE_REQUEST);
+               arp->sender_ip = htonl(my_ip);
+               for(i=0;i<6;i++)
+                       arp->sender_mac[i] = my_mac[i];
+               arp->target_ip = htonl(ip);
+               for(i=0;i<6;i++)
+                       arp->target_mac[i] = 0;
+
+               send_packet();
+
+               /* Do we get a reply ? */
+               for(timeout=0;timeout<100000;timeout++) {
+                       udp_service();
+                       for(i=0;i<6;i++)
+                               if(cached_mac[i]) return 1;
+               }
+       }
+
+       return 0;
+}
+
+static unsigned short ip_checksum(unsigned int r, void *buffer, unsigned int length, int complete)
+{
+       unsigned char *ptr;
+       unsigned int i;
+
+       ptr = (unsigned char *)buffer;
+       length >>= 1;
+
+       for(i=0;i<length;i++)
+               r += ((unsigned int)(ptr[2*i]) << 8)|(unsigned int)(ptr[2*i+1]) ;
+
+       /* Add overflows */
+       while(r >> 16)
+               r = (r & 0xffff) + (r >> 16);
+
+       if(complete) {
+               r = ~r;
+               r &= 0xffff;
+               if(r == 0) r = 0xffff;
+       }
+       return r;
+}
+
+void *udp_get_tx_buffer(void)
+{
+       return txbuffer->frame.contents.udp.payload;
+}
+
+struct pseudo_header {
+       unsigned int src_ip;
+       unsigned int dst_ip;
+       unsigned char zero;
+       unsigned char proto;
+       unsigned short length;
+} __attribute__((packed));
+
+int udp_send(unsigned short src_port, unsigned short dst_port, unsigned int length)
+{
+       struct pseudo_header h;
+       unsigned int r;
+
+       if((cached_mac[0] == 0) && (cached_mac[1] == 0) && (cached_mac[2] == 0)
+               && (cached_mac[3] == 0) && (cached_mac[4] == 0) && (cached_mac[5] == 0))
+               return 0;
+
+       txlen = length + sizeof(struct ethernet_header) + sizeof(struct udp_frame);
+       if(txlen < ARP_PACKET_LENGTH) txlen = ARP_PACKET_LENGTH;
+
+       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 = htons(length + sizeof(struct udp_frame));
+       txbuffer->frame.contents.udp.ip.identification = htons(0);
+       txbuffer->frame.contents.udp.ip.fragment_offset = htons(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 = htonl(my_ip);
+       h.dst_ip = txbuffer->frame.contents.udp.ip.dst_ip = htonl(cached_ip);
+       txbuffer->frame.contents.udp.ip.checksum = htons(ip_checksum(0, &txbuffer->frame.contents.udp.ip,
+               sizeof(struct ip_header), 1));
+
+       txbuffer->frame.contents.udp.udp.src_port = htons(src_port);
+       txbuffer->frame.contents.udp.udp.dst_port = htons(dst_port);
+       h.length = txbuffer->frame.contents.udp.udp.length = htons(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;
+               length++;
+       }
+       r = ip_checksum(r, &txbuffer->frame.contents.udp.udp,
+               sizeof(struct udp_header)+length, 1);
+       txbuffer->frame.contents.udp.udp.checksum = htons(r);
+
+       send_packet();
+
+       return 1;
+}
+
+static udp_callback rx_callback;
+
+static void process_ip(void)
+{
+       if(rxlen < (sizeof(struct ethernet_header)+sizeof(struct udp_frame))) return;
+       struct udp_frame *udp_ip = &rxbuffer->frame.contents.udp;
+       /* We don't verify UDP and IP checksums and rely on the Ethernet checksum solely */
+       if(udp_ip->ip.version != IP_IPV4) return;
+       // check disabled for QEMU compatibility
+       //if(rxbuffer->frame.contents.udp.ip.diff_services != 0) return;
+       if(ntohs(udp_ip->ip.total_length) < sizeof(struct udp_frame)) return;
+       // check disabled for QEMU compatibility
+       //if(ntohs(rxbuffer->frame.contents.udp.ip.fragment_offset) != IP_DONT_FRAGMENT) return;
+       if(udp_ip->ip.proto != IP_PROTO_UDP) return;
+       if(ntohl(udp_ip->ip.dst_ip) != my_ip) return;
+       if(ntohs(udp_ip->udp.length) < sizeof(struct udp_header)) return;
+
+       if(rx_callback)
+               rx_callback(ntohl(udp_ip->ip.src_ip), ntohs(udp_ip->udp.src_port), ntohs(udp_ip->udp.dst_port),
+                           udp_ip->payload, ntohs(udp_ip->udp.length)-sizeof(struct udp_header));
+}
+
+void udp_set_callback(udp_callback callback)
+{
+       rx_callback = callback;
+}
+
+static void process_frame(void)
+{
+       flush_cpu_dcache();
+
+#ifdef DEBUG_LITEETH_UDP_RX
+       int j;
+       printf("<<< rxlen : %d\n", rxlen);
+       for(j=0;j<rxlen;j++)
+               printf("%02x", rxbuffer->raw[j]);
+       printf("\n");
+#endif
+
+#ifndef HW_PREAMBLE_CRC
+       int i;
+       for(i=0;i<7;i++)
+               if(rxbuffer->frame.eth_header.preamble[i] != 0x55) return;
+       if(rxbuffer->frame.eth_header.preamble[7] != 0xd5) return;
+#endif
+
+#ifndef HW_PREAMBLE_CRC
+       unsigned int received_crc;
+       unsigned int computed_crc;
+       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 */
+#endif
+
+       if(ntohs(rxbuffer->frame.eth_header.ethertype) == ETHERTYPE_ARP) process_arp();
+       else if(ntohs(rxbuffer->frame.eth_header.ethertype) == ETHERTYPE_IP) process_ip();
+}
+
+void udp_start(const unsigned char *macaddr, unsigned int ip)
+{
+       int i;
+       ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER);
+       ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
+
+       for(i=0;i<6;i++)
+               my_mac[i] = macaddr[i];
+       my_ip = ip;
+
+       cached_ip = 0;
+       for(i=0;i<6;i++)
+               cached_mac[i] = 0;
+
+       txslot = 0;
+       ethmac_sram_reader_slot_write(txslot);
+       txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot));
+
+       rxslot = 0;
+       rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot);
+       rx_callback = (udp_callback)0;
+}
+
+void udp_service(void)
+{
+       if(ethmac_sram_writer_ev_pending_read() & ETHMAC_EV_SRAM_WRITER) {
+               rxslot = ethmac_sram_writer_slot_read();
+               rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot);
+               rxlen = ethmac_sram_writer_length_read();
+               process_frame();
+               ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
+       }
+}
+
+void eth_init(void)
+{
+       printf("Ethernet init...\n");
+#ifdef CSR_ETHPHY_CRG_RESET_ADDR
+       ethphy_crg_reset_write(1);
+       busy_wait(200);
+       ethphy_crg_reset_write(0);
+       busy_wait(200);
+#endif
+}
+
+#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
+void eth_mode(void)
+{
+       printf("Ethernet phy mode: ");
+       if (ethphy_mode_detection_mode_read())
+               printf("MII");
+       else
+               printf("GMII");
+       printf("\n");
+}
+#endif
+
+#endif
diff --git a/litex/soc/software/libliteeth/udp.h b/litex/soc/software/libliteeth/udp.h
new file mode 100644 (file)
index 0000000..132ef76
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __UDP_H
+#define __UDP_H
+
+#define IPTOINT(a, b, c, d) ((a << 24)|(b << 16)|(c << 8)|d)
+
+#define UDP_BUFSIZE (5*1532)
+
+typedef void (*udp_callback)(unsigned int src_ip, unsigned short src_port, unsigned short dst_port, void *data, unsigned int length);
+
+void udp_start(const unsigned char *macaddr, unsigned int ip);
+int udp_arp_resolve(unsigned int ip);
+void *udp_get_tx_buffer(void);
+int udp_send(unsigned short src_port, unsigned short dst_port, unsigned int length);
+void udp_set_callback(udp_callback callback);
+void udp_service(void);
+
+void eth_init(void);
+void eth_mode(void);
+
+#endif /* __UDP_H */
diff --git a/litex/soc/software/libnet/Makefile b/litex/soc/software/libnet/Makefile
deleted file mode 100644 (file)
index 188e48d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-include ../include/generated/variables.mak
-include $(SOC_DIRECTORY)/software/common.mak
-
-OBJECTS=microudp.o tftp.o
-
-all: libnet.a
-
-libnet.a: $(OBJECTS)
-       $(AR) crs libnet.a $(OBJECTS)
-
-# pull in dependency info for *existing* .o files
--include $(OBJECTS:.o=.d)
-
-%.o: $(LIBNET_DIRECTORY)/%.c
-       $(compile)
-
-%.o: %.S
-       $(assemble)
-
-.PHONY: all clean
-
-clean:
-       $(RM) $(OBJECTS) libnet.a .*~ *~
diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c
deleted file mode 100644 (file)
index 3199456..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-// This file is Copyright (c) 2013 Werner Almesberger <werner@almesberger.net>
-// This file is Copyright (c) 2014-2015 Sebastien Bourdeauducq <sb@m-labs.hk>
-// This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-// This file is Copyright (c) 2018 Jean-François Nguyen <jf@lse.epita.fr>
-// This file is Copyright (c) 2013 Robert Jordens <jordens@gmail.com>
-// License: BSD
-
-#include <generated/csr.h>
-#include <generated/mem.h>
-
-#ifdef CSR_ETHMAC_BASE
-
-#include <stdio.h>
-#include <inet.h>
-#include <system.h>
-#include <crc.h>
-#include <hw/flags.h>
-
-#include <net/microudp.h>
-
-//#define DEBUG_MICROUDP_TX
-//#define DEBUG_MICROUDP_RX
-
-#define ETHERTYPE_ARP 0x0806
-#define ETHERTYPE_IP  0x0800
-
-#ifdef CSR_ETHMAC_PREAMBLE_CRC_ADDR
-#define HW_PREAMBLE_CRC
-#endif
-
-struct ethernet_header {
-#ifndef HW_PREAMBLE_CRC
-       unsigned char preamble[8];
-#endif
-       unsigned char destmac[6];
-       unsigned char srcmac[6];
-       unsigned short ethertype;
-} __attribute__((packed));
-
-static void fill_eth_header(struct ethernet_header *h, const unsigned char *destmac, const unsigned char *srcmac, unsigned short ethertype)
-{
-       int i;
-
-#ifndef HW_PREAMBLE_CRC
-       for(i=0;i<7;i++)
-               h->preamble[i] = 0x55;
-       h->preamble[7] = 0xd5;
-#endif
-       for(i=0;i<6;i++)
-               h->destmac[i] = destmac[i];
-       for(i=0;i<6;i++)
-               h->srcmac[i] = srcmac[i];
-       h->ethertype = htons(ethertype);
-}
-
-#define ARP_HWTYPE_ETHERNET 0x0001
-#define ARP_PROTO_IP        0x0800
-#ifndef HW_PREAMBLE_CRC
-#define ARP_PACKET_LENGTH 68
-#else
-#define ARP_PACKET_LENGTH 60
-#endif
-
-#define ARP_OPCODE_REQUEST  0x0001
-#define ARP_OPCODE_REPLY    0x0002
-
-struct arp_frame {
-       unsigned short hwtype;
-       unsigned short proto;
-       unsigned char hwsize;
-       unsigned char protosize;
-       unsigned short opcode;
-       unsigned char sender_mac[6];
-       unsigned int sender_ip;
-       unsigned char target_mac[6];
-       unsigned int target_ip;
-       unsigned char padding[18];
-} __attribute__((packed));
-
-#define IP_IPV4                        0x45
-#define IP_DONT_FRAGMENT       0x4000
-#define IP_TTL                 64
-#define IP_PROTO_UDP           0x11
-
-struct ip_header {
-       unsigned char version;
-       unsigned char diff_services;
-       unsigned short total_length;
-       unsigned short identification;
-       unsigned short fragment_offset;
-       unsigned char ttl;
-       unsigned char proto;
-       unsigned short checksum;
-       unsigned int src_ip;
-       unsigned int dst_ip;
-} __attribute__((packed));
-
-struct udp_header {
-       unsigned short src_port;
-       unsigned short dst_port;
-       unsigned short length;
-       unsigned short checksum;
-} __attribute__((packed));
-
-struct udp_frame {
-       struct ip_header ip;
-       struct udp_header udp;
-       char payload[];
-} __attribute__((packed));
-
-struct ethernet_frame {
-       struct ethernet_header eth_header;
-       union {
-               struct arp_frame arp;
-               struct udp_frame udp;
-       } contents;
-} __attribute__((packed));
-
-typedef union {
-       struct ethernet_frame frame;
-       unsigned char raw[ETHMAC_SLOT_SIZE];
-} ethernet_buffer;
-
-static unsigned int rxslot;
-static unsigned int rxlen;
-static ethernet_buffer *rxbuffer;
-
-static unsigned int txslot;
-static unsigned int txlen;
-static ethernet_buffer *txbuffer;
-
-static void send_packet(void)
-{
-       /* wait buffer to be available */
-       while(!(ethmac_sram_reader_ready_read()));
-
-       /* fill txbuffer */
-#ifndef HW_PREAMBLE_CRC
-       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;
-       txlen += 4;
-#endif
-
-#ifdef DEBUG_MICROUDP_TX
-       int j;
-       printf(">>>> txlen : %d\n", txlen);
-       for(j=0;j<txlen;j++)
-               printf("%02x",txbuffer->raw[j]);
-       printf("\n");
-#endif
-
-       /* fill slot, length and send */
-       ethmac_sram_reader_slot_write(txslot);
-       ethmac_sram_reader_length_write(txlen);
-       ethmac_sram_reader_start_write(1);
-
-       /* update txslot / txbuffer */
-       txslot = (txslot+1)%ETHMAC_TX_SLOTS;
-       txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot));
-}
-
-static unsigned char my_mac[6];
-static unsigned int my_ip;
-
-/* ARP cache - one entry only */
-static unsigned char cached_mac[6];
-static unsigned int cached_ip;
-
-static void process_arp(void)
-{
-       const struct arp_frame *rx_arp = &rxbuffer->frame.contents.arp;
-       struct arp_frame *tx_arp = &txbuffer->frame.contents.arp;
-
-       if(rxlen < ARP_PACKET_LENGTH) return;
-       if(ntohs(rx_arp->hwtype) != ARP_HWTYPE_ETHERNET) return;
-       if(ntohs(rx_arp->proto) != ARP_PROTO_IP) return;
-       if(rx_arp->hwsize != 6) return;
-       if(rx_arp->protosize != 4) return;
-
-       if(ntohs(rx_arp->opcode) == ARP_OPCODE_REPLY) {
-               if(ntohl(rx_arp->sender_ip) == cached_ip) {
-                       int i;
-                       for(i=0;i<6;i++)
-                               cached_mac[i] = rx_arp->sender_mac[i];
-               }
-               return;
-       }
-       if(ntohs(rx_arp->opcode) == ARP_OPCODE_REQUEST) {
-               if(ntohl(rx_arp->target_ip) == my_ip) {
-                       int i;
-
-                       fill_eth_header(&txbuffer->frame.eth_header,
-                               rx_arp->sender_mac,
-                               my_mac,
-                               ETHERTYPE_ARP);
-                       txlen = ARP_PACKET_LENGTH;
-                       tx_arp->hwtype = htons(ARP_HWTYPE_ETHERNET);
-                       tx_arp->proto = htons(ARP_PROTO_IP);
-                       tx_arp->hwsize = 6;
-                       tx_arp->protosize = 4;
-                       tx_arp->opcode = htons(ARP_OPCODE_REPLY);
-                       tx_arp->sender_ip = htonl(my_ip);
-                       for(i=0;i<6;i++)
-                               tx_arp->sender_mac[i] = my_mac[i];
-                       tx_arp->target_ip = htonl(ntohl(rx_arp->sender_ip));
-                       for(i=0;i<6;i++)
-                               tx_arp->target_mac[i] = rx_arp->sender_mac[i];
-                       send_packet();
-               }
-               return;
-       }
-}
-
-static const unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-int microudp_arp_resolve(unsigned int ip)
-{
-       struct arp_frame *arp;
-       int i;
-       int tries;
-       int timeout;
-
-       if(cached_ip == ip) {
-               for(i=0;i<6;i++)
-                       if(cached_mac[i]) return 1;
-       }
-       cached_ip = ip;
-       for(i=0;i<6;i++)
-               cached_mac[i] = 0;
-
-       for(tries=0;tries<100;tries++) {
-               /* Send an ARP request */
-               fill_eth_header(&txbuffer->frame.eth_header,
-                               broadcast,
-                               my_mac,
-                               ETHERTYPE_ARP);
-               txlen = ARP_PACKET_LENGTH;
-               arp = &txbuffer->frame.contents.arp;
-               arp->hwtype = htons(ARP_HWTYPE_ETHERNET);
-               arp->proto = htons(ARP_PROTO_IP);
-               arp->hwsize = 6;
-               arp->protosize = 4;
-               arp->opcode = htons(ARP_OPCODE_REQUEST);
-               arp->sender_ip = htonl(my_ip);
-               for(i=0;i<6;i++)
-                       arp->sender_mac[i] = my_mac[i];
-               arp->target_ip = htonl(ip);
-               for(i=0;i<6;i++)
-                       arp->target_mac[i] = 0;
-
-               send_packet();
-
-               /* Do we get a reply ? */
-               for(timeout=0;timeout<100000;timeout++) {
-                       microudp_service();
-                       for(i=0;i<6;i++)
-                               if(cached_mac[i]) return 1;
-               }
-       }
-
-       return 0;
-}
-
-static unsigned short ip_checksum(unsigned int r, void *buffer, unsigned int length, int complete)
-{
-       unsigned char *ptr;
-       unsigned int i;
-
-       ptr = (unsigned char *)buffer;
-       length >>= 1;
-
-       for(i=0;i<length;i++)
-               r += ((unsigned int)(ptr[2*i]) << 8)|(unsigned int)(ptr[2*i+1]) ;
-
-       /* Add overflows */
-       while(r >> 16)
-               r = (r & 0xffff) + (r >> 16);
-
-       if(complete) {
-               r = ~r;
-               r &= 0xffff;
-               if(r == 0) r = 0xffff;
-       }
-       return r;
-}
-
-void *microudp_get_tx_buffer(void)
-{
-       return txbuffer->frame.contents.udp.payload;
-}
-
-struct pseudo_header {
-       unsigned int src_ip;
-       unsigned int dst_ip;
-       unsigned char zero;
-       unsigned char proto;
-       unsigned short length;
-} __attribute__((packed));
-
-int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int length)
-{
-       struct pseudo_header h;
-       unsigned int r;
-
-       if((cached_mac[0] == 0) && (cached_mac[1] == 0) && (cached_mac[2] == 0)
-               && (cached_mac[3] == 0) && (cached_mac[4] == 0) && (cached_mac[5] == 0))
-               return 0;
-
-       txlen = length + sizeof(struct ethernet_header) + sizeof(struct udp_frame);
-       if(txlen < ARP_PACKET_LENGTH) txlen = ARP_PACKET_LENGTH;
-
-       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 = htons(length + sizeof(struct udp_frame));
-       txbuffer->frame.contents.udp.ip.identification = htons(0);
-       txbuffer->frame.contents.udp.ip.fragment_offset = htons(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 = htonl(my_ip);
-       h.dst_ip = txbuffer->frame.contents.udp.ip.dst_ip = htonl(cached_ip);
-       txbuffer->frame.contents.udp.ip.checksum = htons(ip_checksum(0, &txbuffer->frame.contents.udp.ip,
-               sizeof(struct ip_header), 1));
-
-       txbuffer->frame.contents.udp.udp.src_port = htons(src_port);
-       txbuffer->frame.contents.udp.udp.dst_port = htons(dst_port);
-       h.length = txbuffer->frame.contents.udp.udp.length = htons(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;
-               length++;
-       }
-       r = ip_checksum(r, &txbuffer->frame.contents.udp.udp,
-               sizeof(struct udp_header)+length, 1);
-       txbuffer->frame.contents.udp.udp.checksum = htons(r);
-
-       send_packet();
-
-       return 1;
-}
-
-static udp_callback rx_callback;
-
-static void process_ip(void)
-{
-       if(rxlen < (sizeof(struct ethernet_header)+sizeof(struct udp_frame))) return;
-       struct udp_frame *udp_ip = &rxbuffer->frame.contents.udp;
-       /* We don't verify UDP and IP checksums and rely on the Ethernet checksum solely */
-       if(udp_ip->ip.version != IP_IPV4) return;
-       // check disabled for QEMU compatibility
-       //if(rxbuffer->frame.contents.udp.ip.diff_services != 0) return;
-       if(ntohs(udp_ip->ip.total_length) < sizeof(struct udp_frame)) return;
-       // check disabled for QEMU compatibility
-       //if(ntohs(rxbuffer->frame.contents.udp.ip.fragment_offset) != IP_DONT_FRAGMENT) return;
-       if(udp_ip->ip.proto != IP_PROTO_UDP) return;
-       if(ntohl(udp_ip->ip.dst_ip) != my_ip) return;
-       if(ntohs(udp_ip->udp.length) < sizeof(struct udp_header)) return;
-
-       if(rx_callback)
-               rx_callback(ntohl(udp_ip->ip.src_ip), ntohs(udp_ip->udp.src_port), ntohs(udp_ip->udp.dst_port),
-                           udp_ip->payload, ntohs(udp_ip->udp.length)-sizeof(struct udp_header));
-}
-
-void microudp_set_callback(udp_callback callback)
-{
-       rx_callback = callback;
-}
-
-static void process_frame(void)
-{
-       flush_cpu_dcache();
-
-#ifdef DEBUG_MICROUDP_RX
-       int j;
-       printf("<<< rxlen : %d\n", rxlen);
-       for(j=0;j<rxlen;j++)
-               printf("%02x", rxbuffer->raw[j]);
-       printf("\n");
-#endif
-
-#ifndef HW_PREAMBLE_CRC
-       int i;
-       for(i=0;i<7;i++)
-               if(rxbuffer->frame.eth_header.preamble[i] != 0x55) return;
-       if(rxbuffer->frame.eth_header.preamble[7] != 0xd5) return;
-#endif
-
-#ifndef HW_PREAMBLE_CRC
-       unsigned int received_crc;
-       unsigned int computed_crc;
-       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 */
-#endif
-
-       if(ntohs(rxbuffer->frame.eth_header.ethertype) == ETHERTYPE_ARP) process_arp();
-       else if(ntohs(rxbuffer->frame.eth_header.ethertype) == ETHERTYPE_IP) process_ip();
-}
-
-void microudp_start(const unsigned char *macaddr, unsigned int ip)
-{
-       int i;
-       ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER);
-       ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
-
-       for(i=0;i<6;i++)
-               my_mac[i] = macaddr[i];
-       my_ip = ip;
-
-       cached_ip = 0;
-       for(i=0;i<6;i++)
-               cached_mac[i] = 0;
-
-       txslot = 0;
-       ethmac_sram_reader_slot_write(txslot);
-       txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot));
-
-       rxslot = 0;
-       rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot);
-       rx_callback = (udp_callback)0;
-}
-
-void microudp_service(void)
-{
-       if(ethmac_sram_writer_ev_pending_read() & ETHMAC_EV_SRAM_WRITER) {
-               rxslot = ethmac_sram_writer_slot_read();
-               rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot);
-               rxlen = ethmac_sram_writer_length_read();
-               process_frame();
-               ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
-       }
-}
-
-void eth_init(void)
-{
-       printf("Ethernet init...\n");
-#ifdef CSR_ETHPHY_CRG_RESET_ADDR
-       ethphy_crg_reset_write(1);
-       busy_wait(200);
-       ethphy_crg_reset_write(0);
-       busy_wait(200);
-#endif
-}
-
-#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
-void eth_mode(void)
-{
-       printf("Ethernet phy mode: ");
-       if (ethphy_mode_detection_mode_read())
-               printf("MII");
-       else
-               printf("GMII");
-       printf("\n");
-}
-#endif
-
-#endif
diff --git a/litex/soc/software/libnet/tftp.c b/litex/soc/software/libnet/tftp.c
deleted file mode 100644 (file)
index 439b3e0..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-// This file is Copyright (c) 2013 Werner Almesberger <werner@almesberger.net>
-// This file is Copyright (c) 2013-2015 Sebastien Bourdeauducq <sb@m-labs.hk>
-// This file is Copyright (c) 2014-2015 Florent Kermarec <florent@enjoy-digital.fr>
-// This file is Copyright (c) 2017 Greg Darke <greg@tsukasa.net.au>
-// This file is Copyright (c) 2018 Ewen McNeill <ewen@naos.co.nz>
-
-// License: BSD
-
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <net/microudp.h>
-#include <net/tftp.h>
-
-/* Local TFTP client port (arbitrary) */
-#define PORT_IN                7642
-
-enum {
-       TFTP_RRQ        = 1,    /* Read request */
-       TFTP_WRQ        = 2,    /* Write request */
-       TFTP_DATA       = 3,    /* Data */
-       TFTP_ACK        = 4,    /* Acknowledgment */
-       TFTP_ERROR      = 5,    /* Error */
-};
-
-#define        BLOCK_SIZE      512     /* block size in bytes */
-
-
-static int format_request(uint8_t *buf, uint16_t op, const char *filename)
-{
-       int len = strlen(filename);
-
-       *buf++ = op >> 8; /* Opcode */
-       *buf++ = op;
-       memcpy(buf, filename, len);
-       buf += len;
-       *buf++ = 0x00;
-       *buf++ = 'o';
-       *buf++ = 'c';
-       *buf++ = 't';
-       *buf++ = 'e';
-       *buf++ = 't';
-       *buf++ = 0x00;
-       return 9+strlen(filename);
-}
-
-static int format_ack(uint8_t *buf, uint16_t block)
-{
-       *buf++ = 0x00; /* Opcode: Ack */
-       *buf++ = TFTP_ACK;
-       *buf++ = (block & 0xff00) >> 8;
-       *buf++ = (block & 0x00ff);
-       return 4;
-}
-
-static int format_data(uint8_t *buf, uint16_t block, const void *data, int len)
-{
-       *buf++ = 0x00; /* Opcode: Data*/
-       *buf++ = TFTP_DATA;
-       *buf++ = (block & 0xff00) >> 8;
-       *buf++ = (block & 0x00ff);
-       memcpy(buf, data, len);
-       return len+4;
-}
-
-static uint8_t *packet_data;
-static int total_length;
-static int transfer_finished;
-static uint8_t *dst_buffer;
-static int last_ack; /* signed, so we can use -1 */
-static uint16_t data_port;
-
-static void rx_callback(uint32_t src_ip, uint16_t src_port,
-    uint16_t dst_port, void *_data, unsigned int length)
-{
-       uint8_t *data = _data;
-       uint16_t opcode;
-       uint16_t block;
-       int i;
-       int offset;
-
-       if(length < 4) return;
-       if(dst_port != PORT_IN) return;
-       opcode = data[0] << 8 | data[1];
-       block = data[2] << 8 | data[3];
-       if(opcode == TFTP_ACK) { /* Acknowledgement */
-               data_port = src_port;
-               last_ack = block;
-               return;
-       }
-       if(block < 1) return;
-       if(opcode == TFTP_DATA) { /* Data */
-               length -= 4;
-               offset = (block-1)*BLOCK_SIZE;
-               for(i=0;i<length;i++)
-                       dst_buffer[offset+i] = data[i+4];
-               total_length += length;
-               if(length < BLOCK_SIZE)
-                       transfer_finished = 1;
-
-               packet_data = microudp_get_tx_buffer();
-               length = format_ack(packet_data, block);
-               microudp_send(PORT_IN, src_port, length);
-       }
-       if(opcode == TFTP_ERROR) { /* Error */
-               total_length = -1;
-               transfer_finished = 1;
-       }
-}
-
-int tftp_get(uint32_t ip, uint16_t server_port, const char *filename,
-    void *buffer)
-{
-       int len;
-       int tries;
-       int i;
-       int length_before;
-       int spin = 0;
-
-       if(!microudp_arp_resolve(ip))
-               return -1;
-
-       microudp_set_callback(rx_callback);
-
-       dst_buffer = buffer;
-
-       total_length = 0;
-       transfer_finished = 0;
-       tries = 5;
-       while(1) {
-               packet_data = microudp_get_tx_buffer();
-               len = format_request(packet_data, TFTP_RRQ, filename);
-               microudp_send(PORT_IN, server_port, len);
-               for(i=0;i<2000000;i++) {
-                       microudp_service();
-                       if((total_length > 0) || transfer_finished) break;
-               }
-               if((total_length > 0) || transfer_finished) break;
-               tries--;
-               if(tries == 0) {
-                       microudp_set_callback(NULL);
-                       return -1;
-               }
-       }
-
-       i = 12000000;
-       length_before = total_length;
-       while(!transfer_finished) {
-               if(length_before != total_length) {
-                       i = 12000000;
-                       length_before = total_length;
-                       if ((total_length & 0x7fff) == 0) { // every 32K
-                               putchar("|/-\\"[spin++ % 4]);
-                               putchar('\b');
-                       }
-               }
-               if(i-- == 0) {
-                       microudp_set_callback(NULL);
-                       return -1;
-               }
-               microudp_service();
-       }
-
-       microudp_set_callback(NULL);
-
-       return total_length;
-}
-
-int tftp_put(uint32_t ip, uint16_t server_port, const char *filename,
-    const void *buffer, int size)
-{
-       int len, send;
-       int tries;
-       int i;
-       int block = 0, sent = 0;
-
-       if(!microudp_arp_resolve(ip))
-               return -1;
-
-       microudp_set_callback(rx_callback);
-
-       packet_data = microudp_get_tx_buffer();
-
-       total_length = 0;
-       transfer_finished = 0;
-       tries = 5;
-       while(1) {
-               packet_data = microudp_get_tx_buffer();
-               len = format_request(packet_data, TFTP_WRQ, filename);
-               microudp_send(PORT_IN, server_port, len);
-               for(i=0;i<2000000;i++) {
-                       last_ack = -1;
-                       microudp_service();
-                       if(last_ack == block)
-                               goto send_data;
-                       if(transfer_finished)
-                               goto fail;
-               }
-               tries--;
-               if(tries == 0)
-                       goto fail;
-       }
-
-send_data:
-       do {
-               block++;
-               send = sent+BLOCK_SIZE > size ? size-sent : BLOCK_SIZE;
-               tries = 5;
-               while(1) {
-                       packet_data = microudp_get_tx_buffer();
-                       len = format_data(packet_data, block, buffer, send);
-                       microudp_send(PORT_IN, data_port, len);
-                       for(i=0;i<12000000;i++) {
-                               microudp_service();
-                               if(transfer_finished)
-                                       goto fail;
-                               if(last_ack == block)
-                                       goto next;
-                       }
-                       if (!--tries)
-                               goto fail;
-               }
-next:
-               sent += send;
-               buffer += send;
-       } while (send == BLOCK_SIZE);
-
-       microudp_set_callback(NULL);
-
-       return sent;
-
-fail:
-       microudp_set_callback(NULL);
-       return -1;
-}