diff options
-rw-r--r-- | firmware/zpu/apps/txrx_uhd.c | 150 | ||||
-rw-r--r-- | firmware/zpu/lib/memory_map.h | 125 | ||||
-rw-r--r-- | firmware/zpu/lib/net_common.c | 99 | ||||
-rw-r--r-- | firmware/zpu/lib/net_common.h | 21 |
4 files changed, 162 insertions, 233 deletions
diff --git a/firmware/zpu/apps/txrx_uhd.c b/firmware/zpu/apps/txrx_uhd.c index 68c24e872..12f173f5c 100644 --- a/firmware/zpu/apps/txrx_uhd.c +++ b/firmware/zpu/apps/txrx_uhd.c @@ -1,8 +1,5 @@ -// -// Copyright 2010-2011 Ettus Research LLC -// /* - * Copyright 2007,2008 Free Software Foundation, Inc. + * Copyright 2010-2011 Ettus Research LLC * * 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 @@ -18,94 +15,58 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <lwip/ip.h> -#include <lwip/udp.h> +//peripheral headers #include "u2_init.h" -#include "memory_map.h" #include "spi.h" +#include "i2c.h" #include "hal_io.h" #include "pic.h" -#include <stdbool.h> -#include "ethernet.h" + +//printf headers #include "nonstdio.h" -#include <net/padded_eth_hdr.h> -#include <net_common.h> -#include "memcpy_wa.h" -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include "clocks.h" + +//network headers +#include "arp_cache.h" +#include "ethernet.h" +#include "net_common.h" #include "usrp2/fw_common.h" -#include <i2c.h> -#include <ethertype.h> -#include <arp_cache.h> #include "udp_fw_update.h" #include "pkt_ctrl.h" -#include "banal.h" -static void setup_network(void); +//standard headers +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> -// ---------------------------------------------------------------- -// the fast-path setup global variables -// ---------------------------------------------------------------- -static eth_mac_addr_t fp_mac_addr_src, fp_mac_addr_dst; -struct socket_address fp_socket_src, fp_socket_dst; extern uint16_t dsp0_dst_port, err0_dst_port, dsp1_dst_port; -static void handle_udp_err0_packet( +static void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - sr_udp_sm->err0_port = (((uint32_t)dst.port) << 16) | src.port; - err0_dst_port = src.port; - printf("Storing for async error path:\n"); - printf(" source udp port: %d\n", dst.port); - printf(" destination udp port: %d\n", src.port); - newline(); -} + size_t which; + switch(dst.port){ + case USRP2_UDP_DSP0_PORT: + which = 0; + dsp0_dst_port = src.port; + break; -static void handle_udp_dsp1_packet( - struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len -){ - sr_udp_sm->dsp1_port = (((uint32_t)dst.port) << 16) | src.port; - dsp1_dst_port = src.port; - printf("Storing for dsp1 path:\n"); - printf(" source udp port: %d\n", dst.port); - printf(" destination udp port: %d\n", src.port); - newline(); -} + case USRP2_UDP_DSP1_PORT: + which = 2; + dsp1_dst_port = src.port; + break; -static void handle_udp_dsp0_packet( - struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len -){ - fp_mac_addr_src = *ethernet_mac_addr(); - arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); - fp_socket_src = dst; - fp_socket_dst = src; - sr_udp_sm->dsp0_port = (((uint32_t)dst.port) << 16) | src.port; - dsp0_dst_port = src.port; - printf("Storing for dsp0 path:\n"); - printf(" source mac addr: "); - print_mac_addr(&fp_mac_addr_src); newline(); - printf(" source ip addr: "); - print_ip_addr(&fp_socket_src.addr); newline(); - printf(" source udp port: %d\n", fp_socket_src.port); - printf(" destination mac addr: "); - print_mac_addr(&fp_mac_addr_dst); newline(); - printf(" destination ip addr: "); - print_ip_addr(&fp_socket_dst.addr); newline(); - printf(" destination udp port: %d\n", fp_socket_dst.port); - newline(); - - //setup network - setup_network(); + case USRP2_UDP_ERR0_PORT: + which = 1; + err0_dst_port = src.port; + break; + + default: return; + } + eth_mac_addr_t eth_mac_host; arp_cache_lookup_mac(&src.addr, ð_mac_host); + setup_framer(eth_mac_host, *ethernet_mac_addr(), src, dst, which); } #define OTW_GPIO_BANK_TO_NUM(bank) \ @@ -278,6 +239,7 @@ static void handle_udp_ctrl_packet( send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); } +#include <net/padded_eth_hdr.h> static void handle_inp_packet(uint32_t *buff, size_t num_lines){ //test if its an ip recovery packet @@ -318,40 +280,6 @@ void link_changed_callback(int speed){ } } -static void setup_network(void){ - - //setup ethernet header machine - sr_udp_sm->eth_hdr.mac_dst_0_1 = (fp_mac_addr_dst.addr[0] << 8) | fp_mac_addr_dst.addr[1]; - sr_udp_sm->eth_hdr.mac_dst_2_3 = (fp_mac_addr_dst.addr[2] << 8) | fp_mac_addr_dst.addr[3]; - sr_udp_sm->eth_hdr.mac_dst_4_5 = (fp_mac_addr_dst.addr[4] << 8) | fp_mac_addr_dst.addr[5]; - sr_udp_sm->eth_hdr.mac_src_0_1 = (fp_mac_addr_src.addr[0] << 8) | fp_mac_addr_src.addr[1]; - sr_udp_sm->eth_hdr.mac_src_2_3 = (fp_mac_addr_src.addr[2] << 8) | fp_mac_addr_src.addr[3]; - sr_udp_sm->eth_hdr.mac_src_4_5 = (fp_mac_addr_src.addr[4] << 8) | fp_mac_addr_src.addr[5]; - sr_udp_sm->eth_hdr.ether_type = ETHERTYPE_IPV4; - - //setup ip header machine - unsigned int chksum = 0; - sr_udp_sm->ip_hdr.ver_ihl_tos = CHKSUM(0x4500, &chksum); // IPV4, 5 words of header (20 bytes), TOS=0 - sr_udp_sm->ip_hdr.total_length = UDP_SM_INS_IP_LEN; // Don't checksum this line in SW - sr_udp_sm->ip_hdr.identification = CHKSUM(0x0000, &chksum); // ID - sr_udp_sm->ip_hdr.flags_frag_off = CHKSUM(0x4000, &chksum); // don't fragment - sr_udp_sm->ip_hdr.ttl_proto = CHKSUM(0x2011, &chksum); // TTL=32, protocol = UDP (17 decimal) - //sr_udp_sm->ip_hdr.checksum .... filled in below - uint32_t src_ip_addr = fp_socket_src.addr.addr; - uint32_t dst_ip_addr = fp_socket_dst.addr.addr; - sr_udp_sm->ip_hdr.src_addr_high = CHKSUM(src_ip_addr >> 16, &chksum); // IP src high - sr_udp_sm->ip_hdr.src_addr_low = CHKSUM(src_ip_addr & 0xffff, &chksum); // IP src low - sr_udp_sm->ip_hdr.dst_addr_high = CHKSUM(dst_ip_addr >> 16, &chksum); // IP dst high - sr_udp_sm->ip_hdr.dst_addr_low = CHKSUM(dst_ip_addr & 0xffff, &chksum); // IP dst low - sr_udp_sm->ip_hdr.checksum = UDP_SM_INS_IP_HDR_CHKSUM | (chksum & 0xffff); - - //setup the udp header machine - sr_udp_sm->udp_hdr.src_port = UDP_SM_INS_UDP_SRC_PORT; - sr_udp_sm->udp_hdr.dst_port = UDP_SM_INS_UDP_DST_PORT; - sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN; - sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum -} - int main(void) { @@ -370,9 +298,9 @@ main(void) //2) register callbacks for udp ports we service init_udp_listeners(); register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet); - register_udp_listener(USRP2_UDP_DSP0_PORT, handle_udp_dsp0_packet); - register_udp_listener(USRP2_UDP_ERR0_PORT, handle_udp_err0_packet); - register_udp_listener(USRP2_UDP_DSP1_PORT, handle_udp_dsp1_packet); + register_udp_listener(USRP2_UDP_DSP0_PORT, handle_udp_data_packet); + register_udp_listener(USRP2_UDP_ERR0_PORT, handle_udp_data_packet); + register_udp_listener(USRP2_UDP_DSP1_PORT, handle_udp_data_packet); #ifdef USRP2P register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); #endif diff --git a/firmware/zpu/lib/memory_map.h b/firmware/zpu/lib/memory_map.h index e08136053..132fdb6f6 100644 --- a/firmware/zpu/lib/memory_map.h +++ b/firmware/zpu/lib/memory_map.h @@ -187,22 +187,24 @@ typedef struct { // 1KB of address space (== 256 32-bit write-only regs) //////////////////////////////////////////////////// -#define SR_MISC 0 -#define SR_TX_PROT_ENG 32 -#define SR_RX_PROT_ENG 48 -#define SR_ROUTER_CTRL 64 -#define SR_UDP_SM 96 -#define SR_TX_DSP 208 -#define SR_TX_CTRL 224 -#define SR_RX_DSP0 160 -#define SR_RX_DSP1 240 -#define SR_RX_CTRL0 176 -#define SR_RX_CTRL1 32 -#define SR_TIME64 192 -#define SR_SIMTIMER 198 -#define SR_LAST 255 - -#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) +#define SR_MISC 0 // 7 regs +#define SR_SIMTIMER 8 // 2 +#define SR_TIME64 10 // 6 +#define SR_BUF_POOL 16 // 4 + +#define SR_RX_FRONT 24 // 5 +#define SR_RX_CTRL0 32 // 9 +#define SR_RX_DSP0 48 // 7 +#define SR_RX_CTRL1 80 // 9 +#define SR_RX_DSP1 96 // 7 + +#define SR_TX_FRONT 128 // ? +#define SR_TX_CTRL 144 // 6 +#define SR_TX_DSP 160 // 5 + +#define SR_UDP_SM 192 // 64 + +#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) #define SR_ADDR_BLDRDONE _SR_ADDR(5) @@ -215,20 +217,19 @@ typedef struct { volatile uint32_t iface_ctrl; } router_ctrl_t; -#define router_ctrl ((router_ctrl_t *) _SR_ADDR(SR_ROUTER_CTRL)) +#define router_ctrl ((router_ctrl_t *) _SR_ADDR(SR_BUF_POOL)) // --- misc outputs --- typedef struct { - volatile uint32_t clk_ctrl; - volatile uint32_t serdes_ctrl; - volatile uint32_t adc_ctrl; - volatile uint32_t leds; - volatile uint32_t phy_ctrl; // LSB is reset line to eth phy - volatile uint32_t debug_mux_ctrl; - volatile uint32_t ram_page; // FIXME should go somewhere else... - volatile uint32_t flush_icache; // Flush the icache - volatile uint32_t led_src; // HW or SW control for LEDs + volatile uint32_t clk_ctrl; + volatile uint32_t serdes_ctrl; + volatile uint32_t adc_ctrl; + volatile uint32_t leds; + volatile uint32_t phy_ctrl; // LSB is reset line to eth phy + volatile uint32_t debug_mux_ctrl; + volatile uint32_t led_src; // HW or SW control for LEDs + volatile uint32_t flush_icache; // Flush the icache } output_regs_t; #define CLK_RESET (1<<4) @@ -255,71 +256,15 @@ typedef struct { #define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) -// --- udp tx regs --- +// --- protocol framer regs --- -typedef struct { - // Bits 19:16 are control info; bits 15:0 are data (see below) - // First two words are unused. - volatile uint32_t _nope[2]; - //--- ethernet header - 14 bytes--- - volatile struct{ - uint32_t mac_dst_0_1; //word 2 - uint32_t mac_dst_2_3; - uint32_t mac_dst_4_5; - uint32_t mac_src_0_1; - uint32_t mac_src_2_3; - uint32_t mac_src_4_5; - uint32_t ether_type; //word 8 - } eth_hdr; - //--- ip header - 20 bytes --- - volatile struct{ - uint32_t ver_ihl_tos; //word 9 - uint32_t total_length; - uint32_t identification; - uint32_t flags_frag_off; - uint32_t ttl_proto; - uint32_t checksum; - uint32_t src_addr_high; - uint32_t src_addr_low; - uint32_t dst_addr_high; - uint32_t dst_addr_low; //word 18 - } ip_hdr; - //--- udp header - 8 bytes --- - volatile struct{ - uint32_t src_port; //word 19 - uint32_t dst_port; - uint32_t length; - uint32_t checksum; //word 22 - } udp_hdr; - volatile uint32_t _pad[1]; - volatile uint32_t dsp0_port; - volatile uint32_t err0_port; - volatile uint32_t dsp1_port; - volatile uint32_t err1_port; -} sr_udp_sm_t; - -// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) - -// Insert a UDP source port from the table -#define UDP_SM_INS_UDP_SRC_PORT (1 << 21) - -// Insert a UDP dest port from the table -#define UDP_SM_INS_UDP_DST_PORT (1 << 20) - -// This is the last word of the header -#define UDP_SM_LAST_WORD (1 << 19) - -// Insert IP header checksum here. Data is the xor of 16'hFFFF and -// the values written into regs 9-13 and 15-18. -#define UDP_SM_INS_IP_HDR_CHKSUM (1 << 18) - -// Insert IP Length here (data ignored) -#define UDP_SM_INS_IP_LEN (1 << 17) - -// Insert UDP Length here (data ignore) -#define UDP_SM_INS_UDP_LEN (1 << 16) - -#define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM)) +typedef struct{ + struct{ + volatile uint32_t entry[16]; + } table[4]; +} sr_proto_framer_t; + +#define sr_proto_framer_regs ((sr_proto_framer_t *) _SR_ADDR(SR_UDP_SM)) // --- VITA TX CTRL regs --- diff --git a/firmware/zpu/lib/net_common.c b/firmware/zpu/lib/net_common.c index f70f279ac..895b7b942 100644 --- a/firmware/zpu/lib/net_common.c +++ b/firmware/zpu/lib/net_common.c @@ -36,17 +36,40 @@ #include <string.h> #include "pkt_ctrl.h" +/*********************************************************************** + * Constants + Globals + **********************************************************************/ static const bool debug = false; - static const size_t out_buff_size = 2048; - static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +#define MAX_UDP_LISTENERS 6 //used in the top level application... uint16_t dsp0_dst_port, err0_dst_port, dsp1_dst_port; -// ------------------------------------------------------------------------ +/*********************************************************************** + * Checksum routines + **********************************************************************/ +static unsigned int CHKSUM(unsigned int x, unsigned int *chksum){ + *chksum += x; + *chksum = (*chksum & 0xffff) + (*chksum>>16); + *chksum = (*chksum & 0xffff) + (*chksum>>16); + return x; +} + +static unsigned int chksum_buffer( + unsigned short *buf, int nshorts, + unsigned int initial_chksum +){ + unsigned int chksum = initial_chksum; + for (int i = 0; i < nshorts; i++) CHKSUM(buf[i], &chksum); + + return chksum; +} +/*********************************************************************** + * Listener registry + **********************************************************************/ static eth_mac_addr_t _local_mac_addr; static struct ip_addr _local_ip_addr; void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr){ @@ -54,10 +77,6 @@ void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_add _local_ip_addr = *ip_addr; } -//------------------------------------------------------------------------- - -#define MAX_UDP_LISTENERS 6 - struct listener_entry { unsigned short port; udp_receiver_t rcvr; @@ -104,9 +123,55 @@ register_udp_listener(int port, udp_receiver_t rcvr) } } -// ------------------------------------------------------------------------ +/*********************************************************************** + * Protocol framer + **********************************************************************/ +void setup_framer( + eth_mac_addr_t eth_dst, + eth_mac_addr_t eth_src, + struct socket_address sock_dst, + struct socket_address sock_src, + size_t which +){ + struct { + padded_eth_hdr_t eth; + struct ip_hdr ip; + struct udp_hdr udp; + } frame; + + //-- load Ethernet header --// + frame.eth.dst = eth_dst; + frame.eth.src = eth_src; + frame.eth.ethertype = ETHERTYPE_IPV4; + + //-- load IPv4 header --// + IPH_VHLTOS_SET(&frame.ip, 4, 5, 0); + IPH_LEN_SET(&frame.ip, 0); + IPH_ID_SET(&frame.ip, 0); + IPH_OFFSET_SET(&frame.ip, IP_DF); // don't fragment + const int ttl = 32; + frame.ip._ttl_proto = (ttl << 8) | (IP_PROTO_UDP & 0xff); + frame.ip._chksum = 0; + frame.ip.src = sock_src.addr; + frame.ip.dest = sock_dst.addr; + frame.ip._chksum = ~chksum_buffer( + (unsigned short *) &frame.ip, + sizeof(frame.ip)/sizeof(short), 0 + ); + + //-- load UDP header --// + frame.udp.src = sock_src.port; + frame.udp.dest = sock_dst.port; + frame.udp.len = 0; + frame.udp.chksum = 0; + //copy into the framer table registers + memcpy_wa((void *)(sr_proto_framer_regs->table[which].entry + 1), &frame, sizeof(frame)); +} +/*********************************************************************** + * Slow-path packet framing and transmission + **********************************************************************/ /*! * low level routine to assembly an ethernet frame and send it. * @@ -164,24 +229,6 @@ send_pkt( if (debug) printf("sent %d bytes\n", (int)total_len); } -unsigned int CHKSUM(unsigned int x, unsigned int *chksum) -{ - *chksum += x; - *chksum = (*chksum & 0xffff) + (*chksum>>16); - *chksum = (*chksum & 0xffff) + (*chksum>>16); - return x; -} - -static unsigned int -chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum) -{ - unsigned int chksum = initial_chksum; - for (int i = 0; i < nshorts; i++) - CHKSUM(buf[i], &chksum); - - return chksum; -} - void send_ip_pkt(struct ip_addr dst, int protocol, const void *buf0, size_t len0, diff --git a/firmware/zpu/lib/net_common.h b/firmware/zpu/lib/net_common.h index 409022352..3cbc5c514 100644 --- a/firmware/zpu/lib/net_common.h +++ b/firmware/zpu/lib/net_common.h @@ -1,6 +1,5 @@ -/* -*- c++ -*- */ /* - * Copyright 2009,2010 Ettus Research LLC + * Copyright 2009-2011 Ettus Research LLC * * 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 @@ -23,12 +22,22 @@ #include <net/socket_address.h> #include <net/eth_mac_addr.h> -/* - * 1's complement sum for IP and UDP headers +/*! + * Setup an entry in the protocol framer for a UDP socket. * - * init chksum to zero to start. + * \param eth_dst ethernet destination mac addr + * \param eth_src ethernet source mac addr + * \param sock_dst udp/ip socket destination + * \param sock_src udp/ip socket source + * \param which the index into the table */ -unsigned int CHKSUM(unsigned int x, unsigned int *chksum); +void setup_framer( + eth_mac_addr_t eth_dst, + eth_mac_addr_t eth_src, + struct socket_address sock_dst, + struct socket_address sock_src, + size_t which +); typedef void (*udp_receiver_t)(struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len); |