diff options
38 files changed, 457 insertions, 1808 deletions
| diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 9c1873e1c..e9c98c26e 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -28,12 +28,10 @@  #include "memory_map.h"  #include "spi.h"  #include "hal_io.h" -#include "buffer_pool.h"  #include "pic.h"  #include <stdbool.h>  #include "ethernet.h"  #include "nonstdio.h" -#include "dbsm.h"  #include <net/padded_eth_hdr.h>  #include <net_common.h>  #include "memcpy_wa.h" @@ -42,87 +40,12 @@  #include <string.h>  #include "clocks.h"  #include "usrp2/fw_common.h" -#include <i2c_async.h>  #include <i2c.h>  #include <ethertype.h>  #include <arp_cache.h>  #include "udp_fw_update.h" - -/* - * Full duplex Tx and Rx between ethernet and DSP pipelines - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow - * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow - */ -//#define CPU_RX_BUF	0	// eth -> cpu - -#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer) -#define	DSP_RX_BUF_1	3	// dsp rx -> eth -#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer) -#define	DSP_TX_BUF_1	5	// eth -> dsp tx - -/* - * ================================================================ - *   configure DSP TX double buffering state machine (eth -> dsp) - * ================================================================ - */ - -// DSP Tx reads ethernet header words -#define DSP_TX_FIRST_LINE ((sizeof(padded_eth_hdr_t) + sizeof(struct ip_hdr) + sizeof(struct udp_hdr))/sizeof(uint32_t)) - -// Receive from ethernet -buf_cmd_args_t dsp_tx_recv_args = { -  PORT_ETH, -  0, -  BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { -  PORT_DSP, -  DSP_TX_FIRST_LINE,	// starts just past transport header -  0			// filled in from last_line register -}; - -dbsm_t dsp_tx_sm;	// the state machine - -/* - * ================================================================ - *   configure DSP RX double buffering state machine (dsp -> eth) - * ================================================================ - */ - -static const uint32_t rx_ctrl_word = 1 << 16; - -// DSP Rx writes ethernet header words -#define DSP_RX_FIRST_LINE sizeof(rx_ctrl_word)/sizeof(uint32_t) - -static bool dbsm_rx_inspector(dbsm_t *sm, int buf_this){ -    size_t num_lines = buffer_pool_status->last_line[buf_this]-DSP_RX_FIRST_LINE; -    ((uint32_t*)buffer_ram(buf_this))[0] = (num_lines*sizeof(uint32_t)) | (1 << 16); -    return false; -} - -// receive from DSP -buf_cmd_args_t dsp_rx_recv_args = { -  PORT_DSP, -  DSP_RX_FIRST_LINE, -  BP_LAST_LINE -}; - -// send to ETH -buf_cmd_args_t dsp_rx_send_args = { -  PORT_ETH, -  0,		// starts with ethernet header in line 0 -  0,		// filled in from list_line register -}; - -dbsm_t dsp_rx_sm;	// the state machine - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; +#include "pkt_ctrl.h" +#include "banal.h"  static void setup_network(void); @@ -130,16 +53,7 @@ static void setup_network(void);  // the fast-path setup global variables  // ----------------------------------------------------------------  static eth_mac_addr_t fp_mac_addr_src, fp_mac_addr_dst; -static struct socket_address fp_socket_src, fp_socket_dst; - -// ---------------------------------------------------------------- -void start_rx_streaming_cmd(void); -void stop_rx_cmd(void); - -static void print_ip_addr(const void *t){ -    uint8_t *p = (uint8_t *)t; -    printf("%d.%d.%d.%d", p[0], p[1], p[2], p[3]); -} +extern struct socket_address fp_socket_src, fp_socket_dst;  void handle_udp_data_packet(      struct socket_address src, struct socket_address dst, @@ -166,41 +80,11 @@ void handle_udp_data_packet(      //setup network and vrt      setup_network(); -    // kick off the state machine -    dbsm_start(&dsp_rx_sm); -  }  #define OTW_GPIO_BANK_TO_NUM(bank) \      (((bank) == USRP2_DIR_RX)? (GPIO_RX_BANK) : (GPIO_TX_BANK)) -//setup the output data -static usrp2_ctrl_data_t ctrl_data_out; -static struct socket_address i2c_src; -static struct socket_address spi_src; - -static volatile bool i2c_done = false; -void i2c_read_done_callback(void) { -  //printf("I2C read done callback\n"); -  i2c_async_data_ready(ctrl_data_out.data.i2c_args.data); -  i2c_done = true; -  i2c_register_callback(0); -} - -void i2c_write_done_callback(void) { -  //printf("I2C write done callback\n"); -  i2c_done = true; -  i2c_register_callback(0); -} - -static volatile bool spi_done = false; -static volatile uint32_t spi_readback_data; -void get_spi_readback_data(void) { -  ctrl_data_out.data.spi_args.data = spi_get_data(); -  spi_done = true; -  spi_register_callback(0); -} -  void handle_udp_ctrl_packet(      struct socket_address src, struct socket_address dst,      unsigned char *payload, int payload_len @@ -226,6 +110,7 @@ void handle_udp_ctrl_packet(      }      //setup the output data +    usrp2_ctrl_data_t ctrl_data_out;      ctrl_data_out.proto_ver = USRP2_FW_COMPAT_NUM;      ctrl_data_out.id=USRP2_CTRL_ID_HUH_WHAT;      ctrl_data_out.seq=ctrl_data_in->seq; @@ -239,7 +124,6 @@ void handle_udp_ctrl_packet(      case USRP2_CTRL_ID_WAZZUP_BRO:          ctrl_data_out.id = USRP2_CTRL_ID_WAZZUP_DUDE;          memcpy(&ctrl_data_out.data.ip_addr, get_ip_addr(), sizeof(struct ip_addr)); -        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      /******************************************************************* @@ -247,21 +131,19 @@ void handle_udp_ctrl_packet(       ******************************************************************/      case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{              //transact -            bool success = spi_async_transact( -                //(ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, +            uint32_t result = spi_transact( +                (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX,                  ctrl_data_in->data.spi_args.dev,      //which device                  ctrl_data_in->data.spi_args.data,     //32 bit data                  ctrl_data_in->data.spi_args.num_bits, //length in bits -                (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | //flags -                (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL, -                get_spi_readback_data //callback +                (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | +                (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL              );              //load output +            ctrl_data_out.data.spi_args.data = result;              ctrl_data_out.id = USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE; -            spi_src = src;          } -//        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      /******************************************************************* @@ -269,13 +151,11 @@ void handle_udp_ctrl_packet(       ******************************************************************/      case USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO:{              uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes; -            i2c_register_callback(i2c_read_done_callback); -            i2c_async_read( +            i2c_read(                  ctrl_data_in->data.i2c_args.addr, +                ctrl_data_out.data.i2c_args.data,                  num_bytes              ); -            i2c_src = src; -//            i2c_dst = dst;              ctrl_data_out.id = USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE;              ctrl_data_out.data.i2c_args.bytes = num_bytes;          } @@ -283,14 +163,11 @@ void handle_udp_ctrl_packet(      case USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO:{              uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes; -            i2c_register_callback(i2c_read_done_callback); -            i2c_async_write( +            i2c_write(                  ctrl_data_in->data.i2c_args.addr,                  ctrl_data_in->data.i2c_args.data,                  num_bytes              ); -            i2c_src = src; -//            i2c_dst = dst;              ctrl_data_out.id = USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE;              ctrl_data_out.data.i2c_args.bytes = num_bytes;          } @@ -322,7 +199,6 @@ void handle_udp_ctrl_packet(          }          ctrl_data_out.id = USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE; -        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      case USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO: @@ -345,7 +221,6 @@ void handle_udp_ctrl_packet(          }          ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE; -        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      case USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO:{ @@ -372,32 +247,11 @@ void handle_udp_ctrl_packet(      default:          ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; -        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));      } -     +    send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));  } -/* - * Called when an ethernet packet is received. - * Return true if we handled it here, otherwise - * it'll be passed on to the DSP Tx pipe - */ -static bool -eth_pkt_inspector(dbsm_t *sm, int bufno) -{ -  //point me to the ethernet frame -  uint32_t *buff = (uint32_t *)buffer_ram(bufno); - -  //treat this as fast-path data? -  // We have to do this operation as fast as possible. -  // Therefore, we do not check all the headers, -  // just check that the udp port matches -  // and that the vrt header is non zero. -  // In the future, a hardware state machine will do this... -  if ( //warning! magic numbers approaching.... -      (((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) && -      ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[1] != USRP2_INVALID_VRT_HEADER) -  ) return false; +static void handle_inp_packet(uint32_t *buff, size_t num_lines){    //test if its an ip recovery packet    typedef struct{ @@ -411,42 +265,30 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)    if (recovery_packet->eth_hdr.ethertype == 0xbeee && strncmp(recovery_packet->code, "addr", 4) == 0){        printf("Got ip recovery packet: "); print_ip_addr(&recovery_packet->data.ip_addr); newline();        set_ip_addr(&recovery_packet->data.ip_addr); -      return true; +      return;    }    //pass it to the slow-path handler -  size_t len = buffer_pool_status->last_line[bufno] - 3; -  handle_eth_packet(buff, len); -  return true; +  handle_eth_packet(buff, num_lines);  } -//------------------------------------------------------------------ -/* - * 1's complement sum for IP and UDP headers - * - * init chksum to zero to start. - */ -static unsigned int -CHKSUM(unsigned int x, unsigned int *chksum) -{ -  *chksum += x; -  *chksum = (*chksum & 0xffff) + (*chksum>>16); -  *chksum = (*chksum & 0xffff) + (*chksum>>16); -  return x; -} +//------------------------------------------------------------------  /*   * Called when eth phy state changes (w/ interrupts disabled)   */ -volatile bool link_is_up = false;	// eth handler sets this -void -link_changed_callback(int speed) -{ -  link_is_up = speed != 0; -  hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45); -  printf("\neth link changed: speed = %d\n", speed); -  if (link_is_up) send_gratuitous_arp(); +void link_changed_callback(int speed){ +    printf("\neth link changed: speed = %d\n", speed); +    if (speed != 0){ +        hal_set_leds(LED_RJ45, LED_RJ45); +        pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_MASTER); +        send_gratuitous_arp(); +    } +    else{ +        hal_set_leds(0x0, LED_RJ45); +        pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_SLAVE); +    }  }  static void setup_network(void){ @@ -483,15 +325,6 @@ static void setup_network(void){    sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD;		// zero UDP checksum  } -inline static void -buffer_irq_handler(unsigned irq) -{ -  uint32_t  status = buffer_pool_status->status; - -  dbsm_process_status(&dsp_tx_sm, status); -  dbsm_process_status(&dsp_rx_sm, status); -} -  int  main(void)  { @@ -515,72 +348,40 @@ main(void)    printf("Firmware compatibility number: %d\n", USRP2_FW_COMPAT_NUM);    //1) register the addresses into the network stack -  register_mac_addr(ethernet_mac_addr()); -  register_ip_addr(get_ip_addr()); -   +  register_addrs(ethernet_mac_addr(), get_ip_addr()); +  pkt_ctrl_program_inspector(get_ip_addr(), USRP2_UDP_CTRL_PORT, USRP2_UDP_DATA_PORT); +    //2) register callbacks for udp ports we service    register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet);    register_udp_listener(USRP2_UDP_DATA_PORT, handle_udp_data_packet);    register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); -  //3) setup ethernet hardware to bring the link up +  //3) set the routing mode to slave and send a garp +  pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_SLAVE); +  send_gratuitous_arp(); + +  //4) setup ethernet hardware to bring the link up    ethernet_register_link_changed_callback(link_changed_callback);    ethernet_init(); -  // initialize double buffering state machine for ethernet -> DSP Tx - -  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, -	    &dsp_tx_recv_args, &dsp_tx_send_args, -	    eth_pkt_inspector); - - -  // initialize double buffering state machine for DSP RX -> Ethernet - -    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, -	      &dsp_rx_recv_args, &dsp_rx_send_args, -	      dbsm_rx_inspector); - -  sr_tx_ctrl->clear_state = 1; -  bp_clear_buf(DSP_TX_BUF_0); -  bp_clear_buf(DSP_TX_BUF_1); +  while(true){ -  // kick off the state machine -  dbsm_start(&dsp_tx_sm); - -  //int which = 0; - -  while(1){ -    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); -    // which ^= 0x8000; - -    buffer_irq_handler(0); - -    if(i2c_done) { -      i2c_done = false; -      send_udp_pkt(USRP2_UDP_CTRL_PORT, i2c_src, &ctrl_data_out, sizeof(ctrl_data_out)); -      //printf("Sending UDP packet from main loop for I2C...\n"); -    } - -    if(spi_done) { -      spi_done = false; -      send_udp_pkt(USRP2_UDP_CTRL_PORT, spi_src, &ctrl_data_out, sizeof(ctrl_data_out)); +    size_t num_lines; +    void *buff = pkt_ctrl_claim_incoming_buffer(&num_lines); +    if (buff != NULL){ +        handle_inp_packet((uint32_t *)buff, num_lines); +        pkt_ctrl_release_incoming_buffer();      }      int pending = pic_regs->pending;		// poll for under or overrun      if (pending & PIC_UNDERRUN_INT){ -      //dbsm_handle_tx_underrun(&dsp_tx_sm);        pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt        putchar('U');      }      if (pending & PIC_OVERRUN_INT){ -      //dbsm_handle_rx_overrun(&dsp_rx_sm);        pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt - -      // FIXME Figure out how to handle this robustly. -      // Any buffers that are emptying should be allowed to drain... -        putchar('O');      }    } diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc index 38c630df4..d99fc4d98 100644 --- a/firmware/microblaze/lib/Makefile.inc +++ b/firmware/microblaze/lib/Makefile.inc @@ -21,10 +21,7 @@ COMMON_SRCS = \  	$(top_srcdir)/lib/u2_init.c \  	$(top_srcdir)/lib/abort.c \  	$(top_srcdir)/lib/ad9510.c \ -	$(top_srcdir)/lib/bsm12.c \ -	$(top_srcdir)/lib/buffer_pool.c \  	$(top_srcdir)/lib/clocks.c \ -	$(top_srcdir)/lib/dbsm.c \  	$(top_srcdir)/lib/eeprom.c \  	$(top_srcdir)/lib/eth_addrs.c \  	$(top_srcdir)/lib/eth_mac.c \ @@ -33,13 +30,13 @@ COMMON_SRCS = \  	$(top_srcdir)/lib/hal_io.c \  	$(top_srcdir)/lib/hal_uart.c \  	$(top_srcdir)/lib/i2c.c \ -	$(top_srcdir)/lib/i2c_async.c \  	$(top_srcdir)/lib/mdelay.c \  	$(top_srcdir)/lib/memcpy_wa.c \  	$(top_srcdir)/lib/memset_wa.c \  	$(top_srcdir)/lib/nonstdio.c \  	$(top_srcdir)/lib/pic.c \ -	$(top_srcdir)/lib/print_mac_addr.c \ +	$(top_srcdir)/lib/pkt_ctrl.c \ +	$(top_srcdir)/lib/print_addrs.c \  	$(top_srcdir)/lib/print_rmon_regs.c \  	$(top_srcdir)/lib/print_buffer.c \  	$(top_srcdir)/lib/printf.c \ diff --git a/firmware/microblaze/lib/banal.h b/firmware/microblaze/lib/banal.h index 7b3c71a20..eb7ed509a 100644 --- a/firmware/microblaze/lib/banal.h +++ b/firmware/microblaze/lib/banal.h @@ -19,24 +19,8 @@  #define INCLUDED_BANAL_H  #include <stdint.h> -#include <lwip/ip_addr.h> -/* - * 1's complement sum for IP and UDP headers - * - * init chksum to zero to start. - */ -static inline unsigned int -CHKSUM(unsigned int x, unsigned int *chksum) -{ -  *chksum += x; -  *chksum = (*chksum & 0xffff) + (*chksum>>16); -  *chksum = (*chksum & 0xffff) + (*chksum>>16); -  return x; -} - -unsigned int  -chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum); +#define dimof(x) (sizeof(x)/sizeof(x[0]))  //-------------- unsigned get_int 8, 16, 32, 64 --------------// @@ -84,7 +68,4 @@ get_int64(const unsigned char *s)    return get_uint64(s);  } -void -print_ip(struct ip_addr ip); -  #endif /* INCLUDED_BANAL_H */ diff --git a/firmware/microblaze/lib/bsm12.c b/firmware/microblaze/lib/bsm12.c deleted file mode 100644 index 3f17fe42d..000000000 --- a/firmware/microblaze/lib/bsm12.c +++ /dev/null @@ -1,319 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ - -/* - * buffer state machine: 1 input to two outputs - * - * Typically used to read packets from the ethernet and then after inspecting, - * handle the packet in firmware or pass it on to 1 of the 2 buffer destinations. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "bsm12.h" -#include "memory_map.h" -#include "buffer_pool.h" -#include <stdbool.h> -#include "nonstdio.h" -#include <stdlib.h> - -typedef enum { -  BS_EMPTY, -  BS_FILLING, -  BS_FULL, -  BS_EMPTYING, -} buffer_state_t; - -static buffer_state_t buffer_state[NBUFFERS]; -static uint32_t last_send_ctrl[NBUFFERS]; -static int8_t  buffer_target[NBUFFERS];	    // -1, 0 or 1. -static uint8_t buffer_dst[NBUFFERS];	    // 0 or 1. Valid only when BF_EMPTYING - -#define ST_IDLE (-1) - -void -bsm12_init(bsm12_t *sm, int buf0, -	   const buf_cmd_args_t *recv, -	   const buf_cmd_args_t *send0, -	   const buf_cmd_args_t *send1, -	   bsm12_inspector_t inspect) -{ -  if (buf0 & 0x3)	// precondition: buf0 % 4 == 0 -    abort(); - -  sm->buf0 = buf0; -  sm->running = false; -  sm->recv_args = *recv; -  sm->send_args[0] = *send0; -  sm->send_args[1] = *send1; - -  sm->rx_state = ST_IDLE; -  sm->tx_state[0] = ST_IDLE; -  sm->tx_state[1] = ST_IDLE; - -  sm->inspect = inspect; - -  sm->bps_error = BPS_ERROR(buf0 + 0) | BPS_ERROR(buf0 + 1) | BPS_ERROR(buf0 + 2); -  sm->bps_done  = BPS_DONE(buf0 + 0)  | BPS_DONE(buf0 + 1)  | BPS_DONE(buf0 + 2); -  sm->bps_error_or_done = sm->bps_error | sm->bps_done; - -  // How much to adjust the last_line register. -  // It's 1 for everything but the ethernet. -  sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1; - -  buffer_state[sm->buf0 + 0] = BS_EMPTY; -  buffer_state[sm->buf0 + 1] = BS_EMPTY; -  buffer_state[sm->buf0 + 2] = BS_EMPTY; - -  buffer_target[sm->buf0 + 0] = -1; -  buffer_target[sm->buf0 + 1] = -1; -  buffer_target[sm->buf0 + 2] = -1; - -  for (int i = 0; i < NBUFFERS; i++) -    sm->next_buf[i] = buf0; - -  sm->next_buf[buf0 + 0] = buf0 + 1; -  sm->next_buf[buf0 + 1] = buf0 + 2; -  sm->next_buf[buf0 + 2] = buf0 + 0; - -  for (int i = 0; i < 3; i++){ -    sm->precomputed_receive_to_buf_ctrl_word[i] = -      (BPC_READ -       | BPC_BUFFER(sm->buf0 + i) -       | BPC_PORT(sm->recv_args.port) -       | BPC_STEP(1) -       | BPC_FIRST_LINE(sm->recv_args.first_line) -       | BPC_LAST_LINE(sm->recv_args.last_line)); -     -    for (int j = 0; j < 2; j++){ -      sm->precomputed_send_from_buf_ctrl_word[i][j] = -	(BPC_WRITE -	 | BPC_BUFFER(sm->buf0 + i) -	 | BPC_PORT(sm->send_args[j].port) -	 | BPC_STEP(1) -	 | BPC_FIRST_LINE(sm->send_args[j].first_line) -	 | BPC_LAST_LINE(0));		// last line filled in at runtime -    } -  } -} - -static inline void -bsm12_receive_to_buf(bsm12_t *sm, int bufno) -{ -  buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 0x3]; -} - -static inline void -bsm12_send_from_buf(bsm12_t *sm, int bufno, int dst_idx) -{ -  dst_idx &= 0x1; - -  uint32_t t =  -    (sm->precomputed_send_from_buf_ctrl_word[bufno & 0x3][dst_idx] -     | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj)); - -  buffer_pool_ctrl->ctrl = t; -  last_send_ctrl[bufno] = t; -  buffer_dst[bufno] = dst_idx; -} - -static inline void -bsm12_resend_from_buf(bsm12_t *sm, int bufno) -{ -  buffer_pool_ctrl->ctrl = last_send_ctrl[bufno]; -} - -void -bsm12_start(bsm12_t *sm) -{ -  sm->running = true; - -  buffer_state[sm->buf0 + 0] = BS_EMPTY; -  buffer_state[sm->buf0 + 1] = BS_EMPTY; -  buffer_state[sm->buf0 + 2] = BS_EMPTY; - -  buffer_target[sm->buf0 + 0] = -1; -  buffer_target[sm->buf0 + 1] = -1; -  buffer_target[sm->buf0 + 2] = -1; - -  bp_clear_buf(sm->buf0 + 0); -  bp_clear_buf(sm->buf0 + 1); -  bp_clear_buf(sm->buf0 + 2); - -  sm->rx_state = 0; -  sm->tx_state[0] = ST_IDLE; -  sm->tx_state[1] = ST_IDLE; -  bsm12_receive_to_buf(sm, sm->buf0); -  buffer_state[sm->buf0] = BS_FILLING; -} - -void -bsm12_stop(bsm12_t *sm) -{ -  sm->running = false; -  bp_clear_buf(sm->buf0 + 0); -  bp_clear_buf(sm->buf0 + 1); -  bp_clear_buf(sm->buf0 + 2); -  buffer_state[sm->buf0 + 0] = BS_EMPTY; -  buffer_state[sm->buf0 + 1] = BS_EMPTY; -  buffer_state[sm->buf0 + 2] = BS_EMPTY; -} - -static void bsm12_process_helper(bsm12_t *sm, int buf_this); -static void bsm12_error_helper(bsm12_t *sm, int buf_this); - -void -bsm12_process_status(bsm12_t *sm, uint32_t status) -{ -  // anything for us? -  if ((status & sm->bps_error_or_done) == 0 || !sm->running) -    return; - -  if (status & sm->bps_error){ -    // Most likely an ethernet Rx error.  We just restart the transfer. -    if (status & (BPS_ERROR(sm->buf0 + 0))) -      bsm12_error_helper(sm, sm->buf0 + 0); - -    if (status & (BPS_ERROR(sm->buf0 + 1))) -      bsm12_error_helper(sm, sm->buf0 + 1); - -    if (status & (BPS_ERROR(sm->buf0 + 2))) -      bsm12_error_helper(sm, sm->buf0 + 2); -  } - -  if (status & BPS_DONE(sm->buf0 + 0)) -    bsm12_process_helper(sm, sm->buf0 + 0); - -  if (status & BPS_DONE(sm->buf0 + 1)) -    bsm12_process_helper(sm, sm->buf0 + 1); - -  if (status & BPS_DONE(sm->buf0 + 2)) -    bsm12_process_helper(sm, sm->buf0 + 2); -} - -static void  -bsm12_process_helper(bsm12_t *sm, int buf_this) -{ -  bp_clear_buf(buf_this); - -  if (buffer_state[buf_this] == BS_FILLING){ - -    buffer_state[buf_this] = BS_FULL; -    buffer_target[buf_this] = -1; - -    // -    // where does this packet go? -    // -    int dst = sm->inspect(sm, buf_this); -    if (dst == -1){ -      // -      // f/w handled the packet; refill the buffer -      // -      bsm12_receive_to_buf(sm, buf_this); -      buffer_state[buf_this] = BS_FILLING; -      buffer_target[buf_this] = -1; -      sm->rx_state = buf_this & 0x3; -    } -    else {	// goes to dst 0 or 1 -      // -      // If the next buffer is empty, start a receive on it -      // -      int t = sm->next_buf[buf_this]; -      if (buffer_state[t] == BS_EMPTY){ -	bsm12_receive_to_buf(sm, t); -	buffer_state[t] = BS_FILLING; -	buffer_target[t] = -1; -	sm->rx_state = t & 0x3; -      } -      else -	sm->rx_state = ST_IDLE; - -      // -      // If the destination is idle, start the xfer, othewise remember it -      // -      if (sm->tx_state[dst] == ST_IDLE){ -	bsm12_send_from_buf(sm, buf_this, dst); -	sm->tx_state[dst] = buf_this & 0x3; -	buffer_state[buf_this] = BS_EMPTYING; -	buffer_target[buf_this] = -1; -      } -      else { -	buffer_target[buf_this] = dst; -      } -    } -  } - -  else {    // BS_EMPTYING - -    buffer_state[buf_this] = BS_EMPTY; -    buffer_target[buf_this] = -1; - -    if (sm->rx_state == ST_IDLE){	// fire off another receive -      sm->rx_state = buf_this & 0x3; -      bsm12_receive_to_buf(sm, buf_this); -      buffer_state[buf_this] = BS_FILLING; -      buffer_target[buf_this] = -1; -    } - -    int dst = buffer_dst[buf_this];	// the dst we were emptying into -    // is the next buffer full and for us? -    int t = sm->next_buf[buf_this]; -    if (buffer_target[t] == dst){		// yes, -      bsm12_send_from_buf(sm, t, dst);		// send it -      buffer_state[t] = BS_EMPTYING; -      buffer_target[t] = -1; -      sm->tx_state[dst] = t & 0x3; -    } -    // how about the one after that? -    else if (buffer_target[t=sm->next_buf[t]] == dst){	// yes, -      bsm12_send_from_buf(sm, t, dst);			// send it -      buffer_state[t] = BS_EMPTYING; -      buffer_target[t] = -1; -      sm->tx_state[dst] = t & 0x3; -    } -    else { -      sm->tx_state[dst] = ST_IDLE; -    } -  } -} - -static void -bsm12_error_helper(bsm12_t *sm, int buf_this) -{ -  bp_clear_buf(buf_this);		  // clears ERROR flag - -  if (buffer_state[buf_this] == BS_FILLING){ -    bsm12_receive_to_buf(sm, buf_this);	  // restart the xfer -  } -  else { // buffer was emptying -    bsm12_resend_from_buf(sm, buf_this);  // restart the xfer -  } -} - - -void -bsm12_handle_tx_underrun(bsm12_t *sm) -{ -} - -void -bsm12_handle_rx_overrun(bsm12_t *sm) -{ -} diff --git a/firmware/microblaze/lib/bsm12.h b/firmware/microblaze/lib/bsm12.h deleted file mode 100644 index b8e576b79..000000000 --- a/firmware/microblaze/lib/bsm12.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ - -#ifndef INCLUDED_BSM12_H -#define INCLUDED_BSM12_H - -#include "dbsm.h" -#include "memory_map.h" - -/*! - * buffer state machine: 1 input to two outputs - * - * Typically used to read packets from the ethernet and then after inspecting, - * handle the packet in firmware or pass it on to 1 of the 2 buffer destinations. - */ - -struct _bsm12; -typedef struct _bsm12 bsm12_t; - -/*! - * Pointer to function that does packet inspection. - * - * \param sm		the state machine - * \param buf_this	the index of the buffer to inspect and/or pass on - * - * Returns -1, 0 or 1.  If it returns -1, it means that the s/w - * handled that packet, and that it should NOT be passed on to one of - * the buffer endpoints.  0 indicates the first endpoint, 1 the second endpoint. - */ -typedef int (*bsm12_inspector_t)(bsm12_t *sm, int buf_this); - - -/*! - * buffer state machine: 1 input to two outputs - */ -struct _bsm12 -{ -  uint8_t	  buf0;	 // This machine uses buf0, buf0+1 and buf0+2.  buf0 % 4 == 0. -  uint8_t	  running; -  int8_t	  rx_state;	// -1, 0, 1, 2  which buffer we're receiving into -  int8_t	  tx_state[2];	// -1, 0, 1, 2  which buffer we're sending from -  buf_cmd_args_t  recv_args; -  buf_cmd_args_t  send_args[2]; -  bsm12_inspector_t inspect; -  int		  last_line_adj; -  uint32_t	  bps_error; -  uint32_t	  bps_done; -  uint32_t	  bps_error_or_done; -  uint8_t	  next_buf[NBUFFERS]; -  uint32_t	  precomputed_receive_to_buf_ctrl_word[3]; -  uint32_t	  precomputed_send_from_buf_ctrl_word[4][2];  // really only 3, not 4  -                                                              //   (easier addr comp) -}; - -void bsm12_init(bsm12_t *sm, int buf0, -		const buf_cmd_args_t *recv, -		const buf_cmd_args_t *send0, -		const buf_cmd_args_t *send1, -		bsm12_inspector_t inspect); - -void bsm12_start(bsm12_t *sm); -void bsm12_stop(bsm12_t *sm); -void bsm12_process_status(bsm12_t *sm, uint32_t status); -void bsm12_handle_tx_underrun(bsm12_t *sm); -void bsm12_handle_rx_overrun(bsm12_t *sm); - - -#endif /* INCLUDED_BSM12_H */ diff --git a/firmware/microblaze/lib/buffer_pool.c b/firmware/microblaze/lib/buffer_pool.c deleted file mode 100644 index 77e7c5213..000000000 --- a/firmware/microblaze/lib/buffer_pool.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ - -#include "memory_map.h" -#include "buffer_pool.h" -#include "hal_io.h"  - -void -bp_init(void) -{ -  int i; -  bp_disable_port(PORT_SERDES); -  bp_disable_port(PORT_DSP); -  bp_disable_port(PORT_ETH); -  bp_disable_port(PORT_RAM); - -  for (i = 0; i < NBUFFERS; i++) -    bp_clear_buf(i); -} - -#ifndef INLINE_BUFFER_POOL - -void -bp_clear_buf(int bufnum) -{ -  buffer_pool_ctrl->ctrl = BPC_BUFFER(bufnum) | BPC_PORT_NIL | BPC_CLR; -} - -void -bp_disable_port(int portnum)  -{ -  // disable buffer connections to this port -  buffer_pool_ctrl->ctrl = BPC_BUFFER_NIL | BPC_PORT(portnum); -} - -void -bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll) -{ -  buffer_pool_ctrl->ctrl = (BPC_READ -			    | BPC_BUFFER(bufnum) -			    | BPC_PORT(port) -			    | BPC_STEP(step) -			    | BPC_FIRST_LINE(fl) -			    | BPC_LAST_LINE(ll)); -} - -void -bp_send_from_buf(int bufnum, int port, int step, int fl, int ll) -{ -  buffer_pool_ctrl->ctrl = (BPC_WRITE -			    | BPC_BUFFER(bufnum) -			    | BPC_PORT(port) -			    | BPC_STEP(step) -			    | BPC_FIRST_LINE(fl) -			    | BPC_LAST_LINE(ll)); -} - -#endif diff --git a/firmware/microblaze/lib/buffer_pool.h b/firmware/microblaze/lib/buffer_pool.h deleted file mode 100644 index 145b20f8d..000000000 --- a/firmware/microblaze/lib/buffer_pool.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ - -#ifndef INCLUDED_BUFFER_POOL_H -#define INCLUDED_BUFFER_POOL_H - -#include "memory_map.h" - -// Buffer Pool Management - - -// define to have common buffer operations inlined -#define INLINE_BUFFER_POOL 1 - -void bp_init(void); - -#ifndef INLINE_BUFFER_POOL - -void bp_clear_buf(int bufnum); -void bp_disable_port(int portnum); -void bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll); -void bp_send_from_buf(int bufnum, int port, int step, int fl, int ll); - -#else - -static inline void -bp_clear_buf(int bufnum) -{ -  buffer_pool_ctrl->ctrl = BPC_BUFFER(bufnum) | BPC_PORT_NIL | BPC_CLR; -} - -static inline void -bp_disable_port(int portnum)  -{ -  // disable buffer connections to this port -  buffer_pool_ctrl->ctrl = BPC_BUFFER_NIL | BPC_PORT(portnum); -} - -static inline void -bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll) -{ -  buffer_pool_ctrl->ctrl = (BPC_READ -			    | BPC_BUFFER(bufnum) -			    | BPC_PORT(port) -			    | BPC_STEP(step) -			    | BPC_FIRST_LINE(fl) -			    | BPC_LAST_LINE(ll)); -} - -static inline void -bp_send_from_buf(int bufnum, int port, int step, int fl, int ll) -{ -  buffer_pool_ctrl->ctrl = (BPC_WRITE -			    | BPC_BUFFER(bufnum) -			    | BPC_PORT(port) -			    | BPC_STEP(step) -			    | BPC_FIRST_LINE(fl) -			    | BPC_LAST_LINE(ll)); -} -#endif -#endif diff --git a/firmware/microblaze/lib/compiler.h b/firmware/microblaze/lib/compiler.h index 4fa9b49f8..f677bdc3b 100644 --- a/firmware/microblaze/lib/compiler.h +++ b/firmware/microblaze/lib/compiler.h @@ -1,6 +1,6 @@  /* -*- c++ -*- */  /* - * Copyright 2009 Ettus Research LLC + * Copyright 2009, 2010 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 @@ -21,5 +21,6 @@  // FIXME gcc specific.  #define _AL4   __attribute__((aligned (4))) +#define FORCE_INLINE inline __attribute__((always_inline))  #endif /* INCLUDED_COMPILER_H */ diff --git a/firmware/microblaze/lib/dbsm.c b/firmware/microblaze/lib/dbsm.c deleted file mode 100644 index cee343eaa..000000000 --- a/firmware/microblaze/lib/dbsm.c +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ - -/* - * Double Buffering State Machine - */ - -#include "dbsm.h" -#include "memory_map.h" -#include "buffer_pool.h" -#include <stdbool.h> -#include "nonstdio.h" -#include <stdlib.h> - -typedef enum { -  BS_EMPTY, -  BS_FILLING, -  BS_FULL, -  BS_EMPTYING, -} buffer_state_t; - -static buffer_state_t buffer_state[NBUFFERS]; - -bool -dbsm_nop_inspector(dbsm_t *sm, int buf_this) -{ -  return false; -} - -void -dbsm_init(dbsm_t *sm, int buf0, -	  const buf_cmd_args_t *recv, const buf_cmd_args_t *send, -	  inspector_t inspect) -{ -  if (buf0 & 0x1)	// must be even -    abort(); - -  sm->buf0 = buf0; -  sm->running = false; -  sm->recv_args = *recv; -  sm->send_args = *send; - -  sm->rx_idle = true; -  sm->tx_idle = true; - -  sm->inspect = inspect; - -  // How much to adjust the last_line register. -  // It's 1 for everything but the ethernet. -  //sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1; -  sm->last_line_adj = 1; - -  buffer_state[sm->buf0] = BS_EMPTY; -  buffer_state[sm->buf0 ^ 1] = BS_EMPTY; - -  sm->precomputed_receive_to_buf_ctrl_word[0] = -    (BPC_READ -     | BPC_BUFFER(sm->buf0) -     | BPC_PORT(sm->recv_args.port) -     | BPC_STEP(1) -     | BPC_FIRST_LINE(sm->recv_args.first_line) -     | BPC_LAST_LINE(sm->recv_args.last_line)); -     -  sm->precomputed_receive_to_buf_ctrl_word[1] = -    (BPC_READ -     | BPC_BUFFER(sm->buf0 ^ 1) -     | BPC_PORT(sm->recv_args.port) -     | BPC_STEP(1) -     | BPC_FIRST_LINE(sm->recv_args.first_line) -     | BPC_LAST_LINE(sm->recv_args.last_line)); -     -  sm->precomputed_send_from_buf_ctrl_word[0] = -    (BPC_WRITE -     | BPC_BUFFER(sm->buf0) -     | BPC_PORT(sm->send_args.port) -     | BPC_STEP(1) -     | BPC_FIRST_LINE(sm->send_args.first_line) -     | BPC_LAST_LINE(0));		// last line filled in at runtime -     -  sm->precomputed_send_from_buf_ctrl_word[1] = -    (BPC_WRITE -     | BPC_BUFFER(sm->buf0 ^ 1) -     | BPC_PORT(sm->send_args.port) -     | BPC_STEP(1) -     | BPC_FIRST_LINE(sm->send_args.first_line) -     | BPC_LAST_LINE(0));		// last line filled in at runtime -     -} - -static inline void -dbsm_receive_to_buf(dbsm_t *sm, int bufno) -{ -  buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 1]; -} - -static inline void -dbsm_send_from_buf(dbsm_t *sm, int bufno) -{ -  buffer_pool_ctrl->ctrl = -    (sm->precomputed_send_from_buf_ctrl_word[bufno & 1] -     | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj)); -} - -void -dbsm_start(dbsm_t *sm) -{ -  // printf("dbsm_start: buf0 = %d, recv_port = %d\n", sm->buf0, sm->recv_args.port); - -  sm->running = true; - -  buffer_state[sm->buf0] = BS_EMPTY; -  buffer_state[sm->buf0 ^ 1] = BS_EMPTY; - -  bp_clear_buf(sm->buf0); -  bp_clear_buf(sm->buf0 ^ 1); - -  sm->tx_idle = true; -  sm->rx_idle = false; -  dbsm_receive_to_buf(sm, sm->buf0); -  buffer_state[sm->buf0] = BS_FILLING; - -} - - -void -dbsm_stop(dbsm_t *sm) -{ -  sm->running = false; -  bp_clear_buf(sm->buf0); -  bp_clear_buf(sm->buf0 ^ 1); -  buffer_state[sm->buf0] = BS_EMPTY; -  buffer_state[sm->buf0 ^ 1] = BS_EMPTY; -} - -static void dbsm_process_helper(dbsm_t *sm, int buf_this); -static void dbsm_error_helper(dbsm_t *sm, int buf_this); - -void -dbsm_process_status(dbsm_t *sm, uint32_t status) -{ -  if (!sm->running) -    return; - -  if (status & (BPS_ERROR(sm->buf0) | BPS_ERROR(sm->buf0 ^ 1))){ -    putchar('E'); -    // Most likely an ethernet Rx error.  We just restart the transfer. -    if (status & (BPS_ERROR(sm->buf0))) -      dbsm_error_helper(sm, sm->buf0); -      //dbsm_process_helper(sm, sm->buf0); //forward errors - -    if (status & (BPS_ERROR(sm->buf0 ^ 1))) -      dbsm_error_helper(sm, sm->buf0 ^ 1); -      //dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors -  } - -  if (status & BPS_DONE(sm->buf0)) -    dbsm_process_helper(sm, sm->buf0); - -  if (status & BPS_DONE(sm->buf0 ^ 1)) -    dbsm_process_helper(sm, sm->buf0 ^ 1); -} - -static void -dbsm_process_helper(dbsm_t *sm, int buf_this) -{ -  int buf_other = buf_this ^ 1; - -  bp_clear_buf(buf_this); - -  if (buffer_state[buf_this] == BS_FILLING){ -    buffer_state[buf_this] = BS_FULL; -    // -    // does s/w handle this packet? -    // -    if (sm->inspect(sm, buf_this)){ -      // s/w handled the packet; refill the buffer -      dbsm_receive_to_buf(sm, buf_this); -      buffer_state[buf_this] = BS_FILLING; -    } - -    else {	// s/w didn't handle this; pass it on - -      if(buffer_state[buf_other] == BS_EMPTY){ -	dbsm_receive_to_buf(sm, buf_other); -	buffer_state[buf_other] = BS_FILLING; -      } -      else -	sm->rx_idle = true; - -      if (sm->tx_idle){ -	sm->tx_idle = false; -	dbsm_send_from_buf(sm, buf_this); -	buffer_state[buf_this] = BS_EMPTYING; -      } -    } -  } -  else {  // buffer was emptying -    buffer_state[buf_this] = BS_EMPTY; -    if (sm->rx_idle){ -      sm->rx_idle = false; -      dbsm_receive_to_buf(sm, buf_this); -      buffer_state[buf_this] = BS_FILLING; -    } -    if (buffer_state[buf_other] == BS_FULL){ -      dbsm_send_from_buf(sm, buf_other); -      buffer_state[buf_other] = BS_EMPTYING; -    } -    else -      sm->tx_idle = true; -  } -} - -static void -dbsm_error_helper(dbsm_t *sm, int buf_this) -{ -  bp_clear_buf(buf_this);		// clears ERROR flag - -  if (buffer_state[buf_this] == BS_FILLING){ -    dbsm_receive_to_buf(sm, buf_this);	  // restart the xfer -  } -  else { // buffer was emptying -    dbsm_send_from_buf(sm, buf_this);	  // restart the xfer -  } -} - -/* - * Handle DSP Tx underrun - */ -void -dbsm_handle_tx_underrun(dbsm_t *sm) -{ -  // clear the DSP Tx state machine -  sr_tx_ctrl->clear_state = 1; - -  // If there's a buffer that's empyting, clear it & flush xfer - -  if (buffer_state[sm->buf0] == BS_EMPTYING){ -    bp_clear_buf(sm->buf0); -    sr_tx_ctrl->clear_state = 1;	// flush partial packet -    // drop frame in progress on ground.  Pretend it finished -    dbsm_process_helper(sm, sm->buf0); -  } -  else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){ -    bp_clear_buf(sm->buf0 ^ 1); -    sr_tx_ctrl->clear_state = 1;	// flush partial packet -    // drop frame in progress on ground.  Pretend it finished -    dbsm_process_helper(sm, sm->buf0 ^ 1); -  } -} - -/* - * Handle DSP Rx overrun - */ -void -dbsm_handle_rx_overrun(dbsm_t *sm) -{ -  sr_rx_ctrl->clear_overrun = 1; - -  // If there's a buffer that's filling, clear it. -  // Any restart will be the job of the caller. -   -  if (buffer_state[sm->buf0] == BS_FILLING) -    bp_clear_buf(sm->buf0); - -  if (buffer_state[sm->buf0 ^1] == BS_FILLING) -    bp_clear_buf(sm->buf0 ^ 1); -} - -void  -dbsm_wait_for_opening(dbsm_t *sm) -{ -  if (buffer_state[sm->buf0] == BS_EMPTYING){ -    // wait for xfer to complete -    int mask = BPS_DONE(sm->buf0) | BPS_ERROR(sm->buf0) | BPS_IDLE(sm->buf0); -    while ((buffer_pool_status->status & mask) == 0) -      ; -  } -  else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){ -    // wait for xfer to complete -    int mask = BPS_DONE(sm->buf0 ^ 1) | BPS_ERROR(sm->buf0 ^ 1) | BPS_IDLE(sm->buf0 ^ 1); -    while ((buffer_pool_status->status & mask) == 0) -      ; -  } -} diff --git a/firmware/microblaze/lib/dbsm.h b/firmware/microblaze/lib/dbsm.h deleted file mode 100644 index cb7e12fc3..000000000 --- a/firmware/microblaze/lib/dbsm.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ -#ifndef INCLUDED_DBSM_H -#define INCLUDED_DBSM_H - -/* - * Double Buffering State Machine - */ - -#include <stdint.h> -#include <stdbool.h> - -struct _dbsm; -typedef struct _dbsm dbsm_t; - -/* - * pointer to function that does packet inspection. - * - * If one of these returns true, it means that the s/w - * handled that packet, and that it should NOT be passed - * on to the normal destination port. - */ -typedef bool (*inspector_t)(dbsm_t *sm, int buf_this); - -bool dbsm_nop_inspector(dbsm_t *sm, int buf_this);	// returns false - - -typedef struct -{ -  uint16_t	port; -  uint16_t	first_line; -  uint16_t	last_line; -} buf_cmd_args_t; - -/*! - * double buffer state machine - */ -struct _dbsm -{ -  uint8_t	  buf0;	     // Must be even. This machine uses buf0 and buf0+1 -  uint8_t	  running; -  uint8_t	  rx_idle; -  uint8_t	  tx_idle; -  buf_cmd_args_t  recv_args; -  buf_cmd_args_t  send_args; -  inspector_t	  inspect; -  uint32_t	  precomputed_receive_to_buf_ctrl_word[2]; -  uint32_t	  precomputed_send_from_buf_ctrl_word[2]; -  int		  last_line_adj; -}; - -void dbsm_init(dbsm_t *sm, int buf0, -	       const buf_cmd_args_t *recv, const buf_cmd_args_t *send, -	       inspector_t inspect); - -void dbsm_start(dbsm_t *sm); -void dbsm_stop(dbsm_t *sm); -void dbsm_process_status(dbsm_t *sm, uint32_t status); -void dbsm_handle_tx_underrun(dbsm_t *sm); -void dbsm_handle_rx_overrun(dbsm_t *sm); - -/* - * The cpu calls this when it want to ensure that it can send a buffer - * to the same destination being used by this state machine. - * - * If neither buffer is EMPTYING it returns immediately.  If a buffer - * is EMPYTING, it waits for the h/w to transition to the DONE or - * ERROR state. - * - * When this function returns, the caller queues it's buffer and busy - * waits for it to complete. - */ -void dbsm_wait_for_opening(dbsm_t *sm); - -#endif /* INCLUDED_DBSM_H */ diff --git a/firmware/microblaze/lib/eth_mac.c b/firmware/microblaze/lib/eth_mac.c index 034a4d494..581a5c69f 100644 --- a/firmware/microblaze/lib/eth_mac.c +++ b/firmware/microblaze/lib/eth_mac.c @@ -28,6 +28,7 @@  void  eth_mac_set_addr(const eth_mac_addr_t *src)  { +  /* disable because MAC_SET_PASS_ALL is set below    eth_mac->ucast_hi =       (((unsigned int)src->addr[0])<<8) +       ((unsigned int)src->addr[1]); @@ -36,6 +37,7 @@ eth_mac_set_addr(const eth_mac_addr_t *src)      (((unsigned int)src->addr[3])<<16) +      (((unsigned int)src->addr[4])<<8) +      (((unsigned int)src->addr[5])); +*/  } @@ -45,7 +47,7 @@ eth_mac_init(const eth_mac_addr_t *src)    eth_mac->miimoder = 25;	// divider from CPU clock (50MHz/25 = 2MHz)    eth_mac_set_addr(src); -  eth_mac->settings = MAC_SET_PAUSE_EN | MAC_SET_PASS_BCAST | MAC_SET_PASS_UCAST | MAC_SET_PAUSE_SEND_EN;  +  eth_mac->settings = MAC_SET_PAUSE_EN | MAC_SET_PASS_BCAST | MAC_SET_PASS_UCAST | MAC_SET_PAUSE_SEND_EN | MAC_SET_PASS_ALL;    eth_mac->pause_time = 38;    eth_mac->pause_thresh = 1200; diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c index 6305408d6..a34ca615b 100644 --- a/firmware/microblaze/lib/net_common.c +++ b/firmware/microblaze/lib/net_common.c @@ -22,7 +22,6 @@  #include "net_common.h"  #include "banal.h"  #include <hal_io.h> -#include <buffer_pool.h>  #include <memory_map.h>  #include <memcpy_wa.h>  #include <ethernet.h> @@ -36,28 +35,21 @@  #include "if_arp.h"  #include <ethertype.h>  #include <string.h> +#include "pkt_ctrl.h" +static const bool debug = false; -int cpu_tx_buf_dest_port = PORT_ETH; +static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; -// If this is non-zero, this dbsm could be writing to the ethernet -dbsm_t *ac_could_be_sending_to_eth; - -static inline bool -ip_addr_eq(const struct ip_addr a, const struct ip_addr b) -{ -  return a.addr == b.addr; -} +//used in the top level application... +struct socket_address fp_socket_src, fp_socket_dst;  // ------------------------------------------------------------------------  static eth_mac_addr_t _local_mac_addr; -void register_mac_addr(const eth_mac_addr_t *mac_addr){ -    _local_mac_addr = *mac_addr; -} -  static struct ip_addr _local_ip_addr; -void register_ip_addr(const struct ip_addr *ip_addr){ +void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr){ +    _local_mac_addr = *mac_addr;      _local_ip_addr = *ip_addr;  } @@ -126,13 +118,6 @@ send_pkt(eth_mac_addr_t dst, int ethertype,  	 const void *buf1, size_t len1,  	 const void *buf2, size_t len2)  { -  // Wait for buffer to become idle -  // FIXME can this ever not be ready? - -  //hal_set_leds(LED_BUF_BUSY, LED_BUF_BUSY); -  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0) -    ; -  //hal_set_leds(0, LED_BUF_BUSY);    // Assemble the header    padded_eth_hdr_t	ehdr; @@ -141,9 +126,10 @@ send_pkt(eth_mac_addr_t dst, int ethertype,    ehdr.src = _local_mac_addr;    ehdr.ethertype = ethertype; -  uint32_t *p = buffer_ram(CPU_TX_BUF); +  uint32_t *buff = (uint32_t *)pkt_ctrl_claim_outgoing_buffer();    // Copy the pieces into the buffer +  uint32_t *p = buff;    *p++ = 0x0;  				  // slow path    memcpy_wa(p, &ehdr, sizeof(ehdr));      // 4 lines    p += sizeof(ehdr)/sizeof(uint32_t); @@ -173,34 +159,23 @@ send_pkt(eth_mac_addr_t dst, int ethertype,      p += len2/sizeof(uint32_t);    } -  size_t total_len = (p - buffer_ram(CPU_TX_BUF)) * sizeof(uint32_t); +  size_t total_len = (p - buff) * sizeof(uint32_t);    if (total_len < 60)		// ensure that we don't try to send a short packet      total_len = 60; -   -  // wait until nobody else is sending to the ethernet -  if (ac_could_be_sending_to_eth){ -    //hal_set_leds(LED_ETH_BUSY, LED_ETH_BUSY); -    dbsm_wait_for_opening(ac_could_be_sending_to_eth); -    //hal_set_leds(0x0, LED_ETH_BUSY); -  } - -  if (0){ -    printf("send_pkt to port %d, len = %d\n", -	   cpu_tx_buf_dest_port, (int) total_len); -    print_buffer(buffer_ram(CPU_TX_BUF), total_len/4); -  } - -  // fire it off -  bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, total_len/4); -  // wait for it to complete (not long, it's a small pkt) -  while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0) -    ; +  pkt_ctrl_commit_outgoing_buffer(total_len/4); +  if (debug) printf("sent %d bytes\n", (int)total_len); +} -  bp_clear_buf(CPU_TX_BUF); +unsigned int CHKSUM(unsigned int x, unsigned int *chksum) +{ +  *chksum += x; +  *chksum = (*chksum & 0xffff) + (*chksum>>16); +  *chksum = (*chksum & 0xffff) + (*chksum>>16); +  return x;  } -unsigned int  +static unsigned int  chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum)  {    unsigned int chksum = initial_chksum; @@ -210,7 +185,6 @@ chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum)    return chksum;  } -  void  send_ip_pkt(struct ip_addr dst, int protocol,  	    const void *buf0, size_t len0, @@ -235,7 +209,7 @@ send_ip_pkt(struct ip_addr dst, int protocol,    bool found = arp_cache_lookup_mac(&ip.dest, &dst_mac);    if (!found){      printf("net_common: failed to hit cache looking for "); -    print_ip(ip.dest); +    print_ip_addr(&ip.dest);      newline();      return;    } @@ -294,6 +268,11 @@ handle_icmp_packet(struct ip_addr src, struct ip_addr dst,      if (icmp->code == ICMP_DUR_PORT){	// port unreachable        //handle destination port unreachable (the host ctrl+c'd the app): +      //filter out non udp data response +      struct ip_hdr *ip = (struct ip_hdr *)(((uint8_t*)icmp) + sizeof(struct icmp_echo_hdr)); +      struct udp_hdr *udp = (struct udp_hdr *)(((char *)ip) + IP_HLEN); +      if (IPH_PROTO(ip) != IP_PROTO_UDP || udp->dest != fp_socket_dst.port) return; +        //end async update packets per second        sr_tx_ctrl->cyc_per_up = 0; @@ -373,8 +352,7 @@ void send_gratuitous_arp(void){    memcpy(req.ar_tip, get_ip_addr(),       sizeof(struct ip_addr));    //send the request with a broadcast ethernet mac address -  eth_mac_addr_t t; memset(&t, 0xff, sizeof(t)); -  send_pkt(t, ETHERTYPE_ARP, &req, sizeof(req), 0, 0, 0, 0); +  send_pkt(BCAST_MAC_ADDR, ETHERTYPE_ARP, &req, sizeof(req), 0, 0, 0, 0);  }  static void @@ -412,7 +390,7 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size)    sip.addr = get_int32(p->ar_sip);    tip.addr = get_int32(p->ar_tip); -  if (ip_addr_eq(tip, _local_ip_addr)){	// They're looking for us... +  if (memcmp(&tip, &_local_ip_addr, sizeof(_local_ip_addr)) == 0){	// They're looking for us...      send_arp_reply(p, _local_mac_addr);    }  } @@ -420,15 +398,17 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size)  void  handle_eth_packet(uint32_t *p, size_t nlines)  { -  //print_buffer(p, nlines); +  static size_t bcount = 0; +  if (debug) printf("===> %d\n", (int)bcount++); +  if (debug) print_buffer(p, nlines); -  int ethertype = p[3] & 0xffff; +  padded_eth_hdr_t *eth_hdr = (padded_eth_hdr_t *)p; -  if (ethertype == ETHERTYPE_ARP){ +  if (eth_hdr->ethertype == ETHERTYPE_ARP){      struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(p + 4);      handle_arp_packet(arp, nlines*sizeof(uint32_t) - 14);    } -  else if (ethertype == ETHERTYPE_IPV4){ +  else if (eth_hdr->ethertype == ETHERTYPE_IPV4){      struct ip_hdr *ip = (struct ip_hdr *)(p + 4);      if (IPH_V(ip) != 4 || IPH_HL(ip) != 5)	// ignore pkts w/ bad version or options        return; @@ -436,7 +416,10 @@ handle_eth_packet(uint32_t *p, size_t nlines)      if (IPH_OFFSET(ip) & (IP_MF | IP_OFFMASK))	// ignore fragmented packets        return; -    // FIXME filter on dest ip addr (should be broadcast or for us) +    // filter on dest ip addr (should be broadcast or for us) +    bool is_bcast = memcmp(ð_hdr->dst, &BCAST_MAC_ADDR, sizeof(BCAST_MAC_ADDR)) == 0; +    bool is_my_ip = memcmp(&ip->dest, &_local_ip_addr, sizeof(_local_ip_addr)) == 0; +    if (!is_bcast && !is_my_ip) return;      arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)p)+8)); diff --git a/firmware/microblaze/lib/net_common.h b/firmware/microblaze/lib/net_common.h index 3040e5ef3..4004ca6e6 100644 --- a/firmware/microblaze/lib/net_common.h +++ b/firmware/microblaze/lib/net_common.h @@ -20,25 +20,20 @@  #include <stdint.h>  #include <stddef.h> -#include <dbsm.h>  #include <net/socket_address.h>  #include <net/eth_mac_addr.h> -#define CPU_TX_BUF 	7	// cpu -> eth - -extern int cpu_tx_buf_dest_port; - -// If this is non-zero, this dbsm could be writing to the ethernet -extern dbsm_t *ac_could_be_sending_to_eth; - -void stop_streaming(void); +/* + * 1's complement sum for IP and UDP headers + * + * init chksum to zero to start. + */ +unsigned int CHKSUM(unsigned int x, unsigned int *chksum);  typedef void (*udp_receiver_t)(struct socket_address src, struct socket_address dst,  			       unsigned char *payload, int payload_len); -void register_mac_addr(const eth_mac_addr_t *mac_addr); - -void register_ip_addr(const struct ip_addr *ip_addr); +void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr);  void register_udp_listener(int port, udp_receiver_t rcvr); diff --git a/firmware/microblaze/lib/nonstdio.h b/firmware/microblaze/lib/nonstdio.h index 62ebfa46d..6aca7ed9a 100644 --- a/firmware/microblaze/lib/nonstdio.h +++ b/firmware/microblaze/lib/nonstdio.h @@ -45,4 +45,6 @@ void print_buffer(uint32_t *buf, size_t n);  //char *itoa(signed long value, char *result, int base);  //void reverse(char s[]); +void print_ip_addr(const void *t); +  #endif /* INCLUDED_NONSTDIO_H */ diff --git a/firmware/microblaze/lib/pkt_ctrl.c b/firmware/microblaze/lib/pkt_ctrl.c new file mode 100644 index 000000000..7e095ec00 --- /dev/null +++ b/firmware/microblaze/lib/pkt_ctrl.c @@ -0,0 +1,69 @@ +/* + * Copyright 2010 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#include "pkt_ctrl.h" +#include "memory_map.h" +#include <nonstdio.h> + +void pkt_ctrl_program_inspector( +    const struct ip_addr *ip_addr, uint16_t ctrl_port, uint16_t data_port +){ +    buffer_pool_ctrl->ip_addr = ip_addr->addr; +    buffer_pool_ctrl->ctrl_ports = ctrl_port; +    buffer_pool_ctrl->data_ports = data_port; +} + +void pkt_ctrl_set_routing_mode(pkt_ctrl_routing_mode_t mode){ +    switch(mode){ +    case PKT_CTRL_ROUTING_MODE_SLAVE: +        buffer_pool_ctrl->misc_ctrl = 0; +        break; +    case PKT_CTRL_ROUTING_MODE_MASTER: +        buffer_pool_ctrl->misc_ctrl = 1; +        break; +    } +} + +static inline bool is_status_bit_set(int bit){ +    return buffer_pool_status->status & (1 << bit); +} + +#define CPU_OUT_HS_BIT 0 //from packet router to CPU +#define CPU_INP_HS_BIT 1 //from CPU to packet router + +void *pkt_ctrl_claim_incoming_buffer(size_t *num_lines){ +    if (!is_status_bit_set(CPU_OUT_HS_BIT)) return NULL; +    *num_lines = (buffer_pool_status->status >> 16) & 0xffff; +    return buffer_ram(0); +} + +void pkt_ctrl_release_incoming_buffer(void){ +    buffer_pool_ctrl->cpu_out_ctrl = 1; +    while (is_status_bit_set(CPU_OUT_HS_BIT)){} +    buffer_pool_ctrl->cpu_out_ctrl = 0; +} + +void *pkt_ctrl_claim_outgoing_buffer(void){ +    while (!is_status_bit_set(CPU_INP_HS_BIT)){} +    return buffer_ram(1); +} + +void pkt_ctrl_commit_outgoing_buffer(size_t num_lines){ +    buffer_pool_ctrl->cpu_inp_ctrl = ((num_lines & 0xffff) << 16) | 1; +    while (is_status_bit_set(CPU_INP_HS_BIT)){} +    buffer_pool_ctrl->cpu_inp_ctrl = 0; +} diff --git a/firmware/microblaze/lib/pkt_ctrl.h b/firmware/microblaze/lib/pkt_ctrl.h new file mode 100644 index 000000000..346e22094 --- /dev/null +++ b/firmware/microblaze/lib/pkt_ctrl.h @@ -0,0 +1,63 @@ +/* + * Copyright 2010 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#ifndef INCLUDED_PKT_CTRL_H +#define INCLUDED_PKT_CTRL_H + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> +#include <lwip/ip_addr.h> + +typedef enum { +    PKT_CTRL_ROUTING_MODE_SLAVE, +    PKT_CTRL_ROUTING_MODE_MASTER, +} pkt_ctrl_routing_mode_t; + +//! Program the decision values into the packet inspector +void pkt_ctrl_program_inspector( +    const struct ip_addr *ip_addr, uint16_t ctrl_port, uint16_t data_port +); + +//! Set the routing mode for this device +void pkt_ctrl_set_routing_mode(pkt_ctrl_routing_mode_t mode); + +/*! + * Try to claim an incomming buffer. + * \param num_lines filled with the buffer size + * \return a pointer to the buffer memory or NULL + */ +void *pkt_ctrl_claim_incoming_buffer(size_t *num_lines); + +/*! + * Release the incoming buffer. Call when done. + */ +void pkt_ctrl_release_incoming_buffer(void); + +/*! + * Claim an outgoing buffer. + * \return a pointer to the buffer + */ +void *pkt_ctrl_claim_outgoing_buffer(void); + +/*! + * Commit the outgoing buffer. + * \param num_lines how many lines written. + */ +void pkt_ctrl_commit_outgoing_buffer(size_t num_lines); + +#endif /* INCLUDED_PKT_CTRL_H */ diff --git a/firmware/microblaze/lib/print_mac_addr.c b/firmware/microblaze/lib/print_addrs.c index 475082325..29601c47c 100644 --- a/firmware/microblaze/lib/print_mac_addr.c +++ b/firmware/microblaze/lib/print_addrs.c @@ -26,3 +26,7 @@ print_mac_addr(const unsigned char addr[6])    }  } +void print_ip_addr(const void *t){ +    uint8_t *p = (uint8_t *)t; +    printf("%d.%d.%d.%d", p[0], p[1], p[2], p[3]); +} diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c index 2a41a1bfa..af0d8a68f 100644 --- a/firmware/microblaze/lib/spi.c +++ b/firmware/microblaze/lib/spi.c @@ -20,9 +20,9 @@  #include "pic.h"  #include "nonstdio.h" -void (*volatile spi_callback)(void); //SPI callback when xfer complete. +//void (*volatile spi_callback)(void); //SPI callback when xfer complete. -static void spi_irq_handler(unsigned irq); +//static void spi_irq_handler(unsigned irq);  void  spi_init(void)  @@ -66,6 +66,7 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags      return 0;  } +/*  void spi_register_callback(void (*volatile callback)(void)) {    spi_callback = callback;  } @@ -106,3 +107,4 @@ spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*    return true;  } +*/ diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h index 54618cedd..71245150a 100644 --- a/firmware/microblaze/lib/spi.h +++ b/firmware/microblaze/lib/spi.h @@ -48,12 +48,12 @@ void spi_wait(void);  uint32_t  spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags); -uint32_t spi_get_data(void); +//uint32_t spi_get_data(void);  //static void spi_irq_handler(unsigned irq); -void spi_register_callback(void (*volatile callback)(void)); +//void spi_register_callback(void (*volatile callback)(void)); -bool  -spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)); +//bool  +//spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void));  // ----------------------------------------------------------------  // Routines that manipulate the FLASH SPI BUS diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 4a553a713..191a0e816 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -20,25 +20,13 @@  #include "spi.h"  #include "pic.h"  #include "hal_io.h" -#include "buffer_pool.h"  #include "hal_uart.h"  #include "i2c.h" -#include "i2c_async.h"  #include "mdelay.h"  #include "clocks.h"  #include "usrp2/fw_common.h"  #include "nonstdio.h" -unsigned char u2_hw_rev_major; -unsigned char u2_hw_rev_minor; - -static inline void -get_hw_rev(void) -{ -  bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, &u2_hw_rev_minor, 1); -  ok &= eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV+1, &u2_hw_rev_major, 1); -} -  /*   * We ought to arrange for this to be called before main, but for now,   * we require that the user's main call u2_init as the first thing... @@ -60,13 +48,8 @@ u2_init(void)    // init i2c so we can read our rev    pic_init();	// progammable interrupt controller    i2c_init(); -  i2c_register_handler(); //for using async I2C    hal_enable_ints(); -  bp_init();	// buffer pool -   - -    // flash all leds to let us know board is alive    hal_set_leds(0x0, 0x1f);    mdelay(100); @@ -85,6 +68,8 @@ u2_init(void)      printf("ad9510 reg[0x%x] = 0x%x\n", rr, vv);    }  #endif -   + +  output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN); +    return true;  } diff --git a/firmware/microblaze/lib/usrp2_bytesex.h b/firmware/microblaze/lib/usrp2_bytesex.h deleted file mode 100644 index 2b74f2a0b..000000000 --- a/firmware/microblaze/lib/usrp2_bytesex.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ -#ifndef INCLUDED_USRP2_BYTESEX_H -#define INCLUDED_USRP2_BYTESEX_H - -// The USRP2 speaks big-endian... -// Use the standard include files or provide substitutions for -// htons and friends - -#if defined(HAVE_ARPA_INET_H) -#include <arpa/inet.h> -#elif defined(HAVE_NETINET_IN_H) -#include <netinet/in.h> -#else -#include <stdint.h> - -#ifdef WORDS_BIGENDIAN  // nothing to do... - -static inline uint32_t htonl(uint32_t x){ return x; } -static inline uint16_t htons(uint16_t x){ return x; } -static inline uint32_t ntohl(uint32_t x){ return x; } -static inline uint16_t ntohs(uint16_t x){ return x; } - -#else - -#ifdef HAVE_BYTESWAP_H -#include <byteswap.h> -#else - -static inline uint16_t -bswap_16 (uint16_t x) -{ -  return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)); -} - -static inline uint32_t -bswap_32 (uint32_t x) -{ -  return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) \ -        | (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24)); -} -#endif - -static inline uint32_t htonl(uint32_t x){ return bswap_32(x); } -static inline uint16_t htons(uint16_t x){ return bswap_16(x); } -static inline uint32_t ntohl(uint32_t x){ return bswap_32(x); } -static inline uint16_t ntohs(uint16_t x){ return bswap_16(x); } - -#endif -#endif -#endif /* INCLUDED_USRP2_BYTESEX_H */ diff --git a/firmware/microblaze/lib/wb16550.h b/firmware/microblaze/lib/wb16550.h deleted file mode 100644 index 7522f4438..000000000 --- a/firmware/microblaze/lib/wb16550.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * 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, either version 3 of the License, or - * (at your option) any later version. - * - * 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/>. - */ - - -// Wishbone National Semiconductor 16550A compatible UART  - -#ifndef INCLUDED_WB16550_H -#define INCLUDED_WB16550_H - -#include <stdint.h> - -typedef struct { -  volatile uint8_t data;     // 0 r/w: r: rx fifo, w: tx fifo (if DLAB: LSB of divisor) -  volatile uint8_t ier;      // 1 r/w: Interrupt Enable Register (if DLAB: MSB of divisor) -  volatile uint8_t iir_fcr;  // 2 r/w: r: Interrupt ID Register, -                             //        w: Fifo Control Register -  volatile uint8_t lcr;      // 3 r/w: Line Control Register -  volatile uint8_t mcr;      // 4 w:   Modem Control Register -  volatile uint8_t lsr;      // 5 r:   Line Status Register -  volatile uint8_t msr;      // 6 r:   Modem Status Register - -} wb16550_reg_t; - -#define UART_IER_RDI		0x01  // Enable received data interrupt -#define UART_IER_THRI		0x02  // Enable transmitter holding reg empty int. -#define	UART_IER_RLSI		0x04  // Enable receiver line status interrupt -#define UART_IER_MSI		0x08  // Enable modem status interrupt - -#define	UART_IIR_NO_INT		0x01  // No interrupts pending -#define UART_IIR_ID_MASK	0x06  // Mask for interrupt ID -#define	UART_IIR_MSI		0x00  // Modem status interrupt -#define	UART_IIR_THRI		0x02  // Tx holding register empty int -#define	UART_IIR_RDI		0x04  // Rx data available int -#define UART_IIR_RLSI		0x06  // Receiver line status int - -#define	UART_FCR_ENABLE_FIFO	0x01  // ignore, always enabled -#define UART_FCR_CLEAR_RCVR	0x02  // Clear the RCVR FIFO -#define UART_FCR_CLEAR_XMIT	0x04  // Clear the XMIT FIFO -#define UART_FCR_TRIGGER_MASK	0xC0  // Mask for FIFO trigger range -#define	UART_FCR_TRIGGER_1	0x00  // Rx fifo trigger level:  1 byte -#define	UART_FCR_TRIGGER_4	0x40  // Rx fifo trigger level:  4 bytes -#define	UART_FCR_TRIGGER_8	0x80  // Rx fifo trigger level:  8 bytes -#define	UART_FCR_TRIGGER_14	0xC0  // Rx fifo trigger level: 14 bytes - -#define UART_LCR_DLAB		0x80  // Divisor latch access bit  -#define UART_LCR_SBC		0x40  // Set break control  -#define UART_LCR_SPAR		0x20  // Stick parity -#define UART_LCR_EPAR		0x10  // Even parity select  -#define UART_LCR_PARITY		0x08  // Parity Enable  -#define UART_LCR_STOP		0x04  // Stop bits: 0=1 bit, 1=2 bits  -#define UART_LCR_WLEN5		0x00  // Wordlength: 5 bits  -#define UART_LCR_WLEN6		0x01  // Wordlength: 6 bits  -#define UART_LCR_WLEN7		0x02  // Wordlength: 7 bits  -#define UART_LCR_WLEN8		0x03  // Wordlength: 8 bits  - -#define UART_MCR_LOOP		0x10  // Enable loopback test mode  -#define UART_MCR_OUT2n		0x08  // Out2 complement (loopback mode) -#define UART_MCR_OUT1n		0x04  // Out1 complement (loopback mode) -#define UART_MCR_RTSn		0x02  // RTS complement  -#define UART_MCR_DTRn		0x01  // DTR complement  - -#define UART_LSR_TEMT		0x40  // Transmitter empty  -#define UART_LSR_THRE		0x20  // Transmit-hold-register empty  -#define UART_LSR_BI		0x10  // Break interrupt indicator  -#define UART_LSR_FE		0x08  // Frame error indicator  -#define UART_LSR_PE		0x04  // Parity error indicator  -#define UART_LSR_OE		0x02  // Overrun error indicator  -#define UART_LSR_DR		0x01  // Receiver data ready  -#define UART_LSR_BRK_ERROR_BITS	0x1E  // BI, FE, PE, OE bits  -#define UART_LSR_ERROR		0x80  // At least 1 PE, FE or BI are in the fifo - -#define UART_MSR_DCD		0x80  // Data Carrier Detect  -#define UART_MSR_RI		0x40  // Ring Indicator  -#define UART_MSR_DSR		0x20  // Data Set Ready  -#define UART_MSR_CTS		0x10  // Clear to Send  -#define UART_MSR_DDCD		0x08  // Delta DCD  -#define UART_MSR_TERI		0x04  // Trailing edge ring indicator  -#define UART_MSR_DDSR		0x02  // Delta DSR  -#define UART_MSR_DCTS		0x01  // Delta CTS  -#define UART_MSR_ANY_DELTA	0x0F  // Any of the delta bits!  - - -#endif  // INCLUDED_WB16550_H  diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index 7a58e7253..7fd353204 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -24,8 +24,6 @@ AM_LDFLAGS = \  	$(COMMON_LFLAGS) \  	-Wl,-defsym -Wl,_TEXT_START_ADDR=0x0050 \  	-Wl,-defsym -Wl,_STACK_SIZE=3072 -	 -LDADD = libusrp2.a  LDADD = libusrp2.a @@ -38,7 +36,7 @@ libusrp2_a_SOURCES = \  	$(COMMON_SRCS) \  	sd.c \  	ethernet.c \ -  udp_fw_update.c +	udp_fw_update.c  noinst_PROGRAMS = \  	usrp2_txrx_uhd.elf diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h index eac0c217f..23d96389f 100644 --- a/firmware/microblaze/usrp2/memory_map.h +++ b/firmware/microblaze/usrp2/memory_map.h @@ -53,9 +53,7 @@  #define BUFFER_POOL_RAM_BASE 0x8000 -#define	NBUFFERS                8  #define BP_NLINES	   0x0200	// number of 32-bit lines in a buffer -#define BP_LAST_LINE	(BP_NLINES - 1)	// last line in a buffer  #define buffer_pool_ram \    ((uint32_t *) BUFFER_POOL_RAM_BASE) @@ -173,8 +171,8 @@ typedef struct {  #define BUFFER_POOL_STATUS_BASE 0xCC00  typedef struct { -  volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer -  volatile uint32_t status;	         // error and done flags +  volatile uint32_t _padding[8]; +  volatile uint32_t status;    volatile uint32_t hw_config;	         // see below    volatile uint32_t dummy[3];    volatile uint32_t irqs; @@ -184,74 +182,6 @@ typedef struct {  #define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE) -/* - * Buffer n's xfer is done. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_DONE(n)     (0x00000001 << (n)) -#define BPS_DONE_0	BPS_DONE(0) -#define BPS_DONE_1	BPS_DONE(1) -#define BPS_DONE_2	BPS_DONE(2) -#define BPS_DONE_3	BPS_DONE(3) -#define BPS_DONE_4	BPS_DONE(4) -#define BPS_DONE_5	BPS_DONE(5) -#define BPS_DONE_6	BPS_DONE(6) -#define BPS_DONE_7	BPS_DONE(7) - -/* - * Buffer n's xfer had an error. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_ERROR(n)	(0x00000100 << (n)) -#define BPS_ERROR_0	BPS_ERROR(0) -#define BPS_ERROR_1	BPS_ERROR(1) -#define BPS_ERROR_2	BPS_ERROR(2) -#define BPS_ERROR_3	BPS_ERROR(3) -#define BPS_ERROR_4	BPS_ERROR(4) -#define BPS_ERROR_5	BPS_ERROR(5) -#define BPS_ERROR_6	BPS_ERROR(6) -#define BPS_ERROR_7	BPS_ERROR(7) - -/* - * Buffer n is idle.  A buffer is idle if it's not - * DONE, ERROR, or processing a transaction.  If it's - * IDLE, it's safe to start a new transaction. - * - * Clear this bit by starting a xfer with - * bp_send_from_buf or bp_receive_to_buf. - */ -#define BPS_IDLE(n)     (0x00010000 << (n)) -#define BPS_IDLE_0	BPS_IDLE(0) -#define BPS_IDLE_1	BPS_IDLE(1) -#define BPS_IDLE_2	BPS_IDLE(2) -#define BPS_IDLE_3	BPS_IDLE(3) -#define BPS_IDLE_4	BPS_IDLE(4) -#define BPS_IDLE_5	BPS_IDLE(5) -#define BPS_IDLE_6	BPS_IDLE(6) -#define BPS_IDLE_7	BPS_IDLE(7) - -/* - * Buffer n has a "slow path" packet in it. - * This bit is orthogonal to the bits above and indicates that - * the FPGA ethernet rx protocol engine has identified this packet - * as one requiring firmware intervention. - */ -#define BPS_SLOWPATH(n) (0x01000000 << (n)) -#define BPS_SLOWPATH_0	BPS_SLOWPATH(0) -#define BPS_SLOWPATH_1	BPS_SLOWPATH(1) -#define BPS_SLOWPATH_2	BPS_SLOWPATH(2) -#define BPS_SLOWPATH_3	BPS_SLOWPATH(3) -#define BPS_SLOWPATH_4	BPS_SLOWPATH(4) -#define BPS_SLOWPATH_5	BPS_SLOWPATH(5) -#define BPS_SLOWPATH_6	BPS_SLOWPATH(6) -#define BPS_SLOWPATH_7	BPS_SLOWPATH(7) - - -#define BPS_DONE_ALL	  0x000000ff	// mask of all dones -#define BPS_ERROR_ALL	  0x0000ff00	// mask of all errors -#define BPS_IDLE_ALL      0x00ff0000	// mask of all idles -#define BPS_SLOWPATH_ALL  0xff000000	// mask of all slowpaths -  // The hw_config register  #define	HWC_SIMULATION		0x80000000 @@ -316,49 +246,14 @@ hwconfig_wishbone_divisor(void)  // --- buffer pool control regs ---  typedef struct { -  volatile uint32_t ctrl; +  volatile uint32_t misc_ctrl; +  volatile uint32_t ip_addr; +  volatile uint32_t ctrl_ports; //ctrl (low 16) other (high 16) +  volatile uint32_t data_ports; //dsp0 (low 16) dsp1 (high 16) +  volatile uint32_t cpu_out_ctrl; +  volatile uint32_t cpu_inp_ctrl;  } buffer_pool_ctrl_t; -// buffer pool ports - -#define	PORT_SERDES	0	// serial/deserializer -#define	PORT_DSP	1	// DSP tx or rx pipeline -#define	PORT_ETH	2	// ethernet tx or rx -#define	PORT_RAM	3	// RAM tx or rx - -// the buffer pool ctrl register fields - -#define BPC_BUFFER(n) (((n) & 0xf) << 28) -#define   BPC_BUFFER_MASK      BPC_BUFFER(~0) -#define   BPC_BUFFER_0	       BPC_BUFFER(0) -#define   BPC_BUFFER_1	       BPC_BUFFER(1) -#define   BPC_BUFFER_2	       BPC_BUFFER(2) -#define   BPC_BUFFER_3	       BPC_BUFFER(3) -#define   BPC_BUFFER_4	       BPC_BUFFER(4) -#define   BPC_BUFFER_5	       BPC_BUFFER(5) -#define   BPC_BUFFER_6	       BPC_BUFFER(6) -#define   BPC_BUFFER_7	       BPC_BUFFER(7) -#define	  BPC_BUFFER_NIL       BPC_BUFFER(0x8)	// disable - -#define BPC_PORT(n) (((n) & 0x7) << 25) -#define   BPC_PORT_MASK        BPC_PORT(~0) -#define   BPC_PORT_SERDES      BPC_PORT(PORT_SERDES) -#define   BPC_PORT_DSP	       BPC_PORT(PORT_DSP) -#define   BPC_PORT_ETH         BPC_PORT(PORT_ETH) -#define   BPC_PORT_RAM         BPC_PORT(PORT_RAM) -#define   BPC_PORT_NIL	       BPC_PORT(0x4)   	// disable - -#define	BPC_CLR	       	       (1 << 24)  // mutually excl commands -#define	BPC_READ	       (1 << 23) -#define BPC_WRITE              (1 << 22) - -#define BPC_STEP(step) (((step) & 0xf) << 18) -#define   BPC_STEP_MASK	       BPC_STEP(~0) -#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) -#define   BPC_LAST_LINE_MASK   BPC_LAST_LINE(~0) -#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) -#define   BPC_FIRST_LINE_MASK  BPC_FIRST_LINE(~0) -  #define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE)  // --- misc outputs --- diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index 3b2dc0057..5edb3b313 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -78,9 +78,7 @@ wb_1master #(.decode_w(8),  #define BUFFER_POOL_RAM_BASE 0x4000 -#define	NBUFFERS                8  #define BP_NLINES	   0x0200	// number of 32-bit lines in a buffer -#define BP_LAST_LINE	(BP_NLINES - 1)	// last line in a buffer  #define buffer_pool_ram \    ((uint32_t *) BUFFER_POOL_RAM_BASE) @@ -198,8 +196,8 @@ typedef struct {  #define BUFFER_POOL_STATUS_BASE 0x3300  typedef struct { -  volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer -  volatile uint32_t status;	         // error and done flags +  volatile uint32_t _padding[8]; +  volatile uint32_t status;    volatile uint32_t hw_config;	         // see below    volatile uint32_t dummy[3];    volatile uint32_t irqs; @@ -211,74 +209,6 @@ typedef struct {  #define BUTTON_PUSHED ((buffer_pool_status->irqs & PIC_BUTTON) ? 0 : 1) -/* - * Buffer n's xfer is done. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_DONE(n)     (0x00000001 << (n)) -#define BPS_DONE_0	BPS_DONE(0) -#define BPS_DONE_1	BPS_DONE(1) -#define BPS_DONE_2	BPS_DONE(2) -#define BPS_DONE_3	BPS_DONE(3) -#define BPS_DONE_4	BPS_DONE(4) -#define BPS_DONE_5	BPS_DONE(5) -#define BPS_DONE_6	BPS_DONE(6) -#define BPS_DONE_7	BPS_DONE(7) - -/* - * Buffer n's xfer had an error. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_ERROR(n)	(0x00000100 << (n)) -#define BPS_ERROR_0	BPS_ERROR(0) -#define BPS_ERROR_1	BPS_ERROR(1) -#define BPS_ERROR_2	BPS_ERROR(2) -#define BPS_ERROR_3	BPS_ERROR(3) -#define BPS_ERROR_4	BPS_ERROR(4) -#define BPS_ERROR_5	BPS_ERROR(5) -#define BPS_ERROR_6	BPS_ERROR(6) -#define BPS_ERROR_7	BPS_ERROR(7) - -/* - * Buffer n is idle.  A buffer is idle if it's not - * DONE, ERROR, or processing a transaction.  If it's - * IDLE, it's safe to start a new transaction. - * - * Clear this bit by starting a xfer with - * bp_send_from_buf or bp_receive_to_buf. - */ -#define BPS_IDLE(n)     (0x00010000 << (n)) -#define BPS_IDLE_0	BPS_IDLE(0) -#define BPS_IDLE_1	BPS_IDLE(1) -#define BPS_IDLE_2	BPS_IDLE(2) -#define BPS_IDLE_3	BPS_IDLE(3) -#define BPS_IDLE_4	BPS_IDLE(4) -#define BPS_IDLE_5	BPS_IDLE(5) -#define BPS_IDLE_6	BPS_IDLE(6) -#define BPS_IDLE_7	BPS_IDLE(7) - -/* - * Buffer n has a "slow path" packet in it. - * This bit is orthogonal to the bits above and indicates that - * the FPGA ethernet rx protocol engine has identified this packet - * as one requiring firmware intervention. - */ -#define BPS_SLOWPATH(n) (0x01000000 << (n)) -#define BPS_SLOWPATH_0	BPS_SLOWPATH(0) -#define BPS_SLOWPATH_1	BPS_SLOWPATH(1) -#define BPS_SLOWPATH_2	BPS_SLOWPATH(2) -#define BPS_SLOWPATH_3	BPS_SLOWPATH(3) -#define BPS_SLOWPATH_4	BPS_SLOWPATH(4) -#define BPS_SLOWPATH_5	BPS_SLOWPATH(5) -#define BPS_SLOWPATH_6	BPS_SLOWPATH(6) -#define BPS_SLOWPATH_7	BPS_SLOWPATH(7) - - -#define BPS_DONE_ALL	  0x000000ff	// mask of all dones -#define BPS_ERROR_ALL	  0x0000ff00	// mask of all errors -#define BPS_IDLE_ALL      0x00ff0000	// mask of all idles -#define BPS_SLOWPATH_ALL  0xff000000	// mask of all slowpaths -  // The hw_config register  #define	HWC_SIMULATION		0x80000000 @@ -343,49 +273,14 @@ hwconfig_wishbone_divisor(void)  // --- buffer pool control regs ---  typedef struct { -  volatile uint32_t ctrl; +  volatile uint32_t misc_ctrl; +  volatile uint32_t ip_addr; +  volatile uint32_t ctrl_ports; //ctrl (low 16) other (high 16) +  volatile uint32_t data_ports; //dsp0 (low 16) dsp1 (high 16) +  volatile uint32_t cpu_out_ctrl; +  volatile uint32_t cpu_inp_ctrl;  } buffer_pool_ctrl_t; -// buffer pool ports - -#define	PORT_SERDES	0	// serial/deserializer -#define	PORT_DSP	1	// DSP tx or rx pipeline -#define	PORT_ETH	2	// ethernet tx or rx -#define	PORT_RAM	3	// RAM tx or rx - -// the buffer pool ctrl register fields - -#define BPC_BUFFER(n) (((n) & 0xf) << 28) -#define   BPC_BUFFER_MASK      BPC_BUFFER(~0) -#define   BPC_BUFFER_0	       BPC_BUFFER(0) -#define   BPC_BUFFER_1	       BPC_BUFFER(1) -#define   BPC_BUFFER_2	       BPC_BUFFER(2) -#define   BPC_BUFFER_3	       BPC_BUFFER(3) -#define   BPC_BUFFER_4	       BPC_BUFFER(4) -#define   BPC_BUFFER_5	       BPC_BUFFER(5) -#define   BPC_BUFFER_6	       BPC_BUFFER(6) -#define   BPC_BUFFER_7	       BPC_BUFFER(7) -#define	  BPC_BUFFER_NIL       BPC_BUFFER(0x8)	// disable - -#define BPC_PORT(n) (((n) & 0x7) << 25) -#define   BPC_PORT_MASK        BPC_PORT(~0) -#define   BPC_PORT_SERDES      BPC_PORT(PORT_SERDES) -#define   BPC_PORT_DSP	       BPC_PORT(PORT_DSP) -#define   BPC_PORT_ETH         BPC_PORT(PORT_ETH) -#define   BPC_PORT_RAM         BPC_PORT(PORT_RAM) -#define   BPC_PORT_NIL	       BPC_PORT(0x4)   	// disable - -#define	BPC_CLR	       	       (1 << 24)  // mutually excl commands -#define	BPC_READ	       (1 << 23) -#define BPC_WRITE              (1 << 22) - -#define BPC_STEP(step) (((step) & 0xf) << 18) -#define   BPC_STEP_MASK	       BPC_STEP(~0) -#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) -#define   BPC_LAST_LINE_MASK   BPC_LAST_LINE(~0) -#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) -#define   BPC_FIRST_LINE_MASK  BPC_FIRST_LINE(~0) -  #define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE)  // --- misc outputs --- diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 8e5743102..3031a0075 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -101,7 +101,7 @@ On some systems, the firewall will block UDP broadcast packets.  It is recommended that you change or disable your firewall settings.  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Multiple device configuration +Multiple devices per host  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  For maximum throughput, one ethernet interface per USRP2 is recommended,  although multiple devices may be connected via a gigabit ethernet switch. @@ -210,6 +210,66 @@ Example device address string representation for 2 USRP2s with IPv4 addresses 19      addr0=192.168.10.2, addr1=192.168.20.2  ------------------------------------------------------------------------ +Using the MIMO Cable +------------------------------------------------------------------------ +The MIMO cable allows two USRP devices to share reference clocks, +time synchronization, and the ethernet interface. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Shared ethernet mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In shared ethernet mode, +only one device in the configuration can be attached to the ethernet. +This device will be referred to as the master, and the other device, the slave. + +* The master provides reference clock and time synchronization to the slave. +* All data passing between the host and the slave is routed over the MIMO cable. +* Both master and slave must have different IPv4 addresses in the same subnet. +* The master and slave may be used individually or in a multi-device configuration. +* External clocking is optional, and should only be supplied to the master device. +* The role of slave and master may be switched with the "mimo_mode" device address (see dual ethernet mode). + +Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 (master) and 192.168.10.3 (slave) +:: + +    -- Multi-device example -- + +    addr0=192.168.10.2, addr1=192.168.10.3 + +    -- Two single devices example -- + +    addr=192.168.10.2 + +    addr=192.168.10.3 + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Dual ethernet mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In dual ethernet mode, +both devices in the configuration must be attached to the ethernet. +One of the devices in the configuration will be configured to provide synchronization. +This device will be referred to as the master, and the other device, the slave. + +* The master provides reference clock and time synchronization to the slave. +* The devices require the special device address argument "mimo_mode" set. +* Both master and slave must have different IPv4 addresses in different subnets. +* The master and slave may be used individually or in a multi-device configuration. +* External clocking is optional, and should only be supplied to the master device. + +Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 (master) and 192.168.20.2 (slave) +:: + +    -- Multi-device example -- + +    addr0=192.168.10.2, mimo_mode0=master, addr1=192.168.20.2, mimo_mode1=slave + +    -- Two single devices example -- + +    addr=192.168.10.2, mimo_mode=master + +    addr=192.168.20.2, mimo_mode=slave + +------------------------------------------------------------------------  Hardware setup notes  ------------------------------------------------------------------------ @@ -220,7 +280,7 @@ The LEDs on the front panel can be useful in debugging hardware and software iss  The LEDs reveal the following about the state of the device:  * **LED A:** transmitting -* **LED B:** serdes link +* **LED B:** mimo cable link  * **LED C:** receiving  * **LED D:** firmware loaded  * **LED E:** reference lock diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 9342fbb7b..5966dcf3a 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -32,12 +32,10 @@ namespace uhd{              REF_AUTO = 'a', //automatic (device specific)              REF_INT  = 'i', //internal reference              REF_SMA  = 's', //external sma port -            REF_MIMO = 'm'  //mimo cable (usrp2 only)          } ref_source;          enum pps_source_t {              PPS_INT  = 'i', //there is no internal              PPS_SMA  = 's', //external sma port -            PPS_MIMO = 'm'  //mimo cable (usrp2 only)          } pps_source;          enum pps_polarity_t {              PPS_NEG = 'n', //negative edge diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index afd69cae9..81b73fcc2 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -36,8 +36,6 @@ IF(ENABLE_USRP2)          ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.cpp          ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp          ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp -        ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp -        ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp          ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp          ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.hpp          ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 428d5539b..27ccefb2b 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -22,10 +22,13 @@  #include <uhd/utils/assert.hpp>  #include <boost/cstdint.hpp>  #include <boost/lexical_cast.hpp> +#include <boost/math/special_functions/round.hpp>  #include <iostream>  using namespace uhd; +static const bool enb_test_clk = false; +  /*!   * A usrp2 clock control specific to the ad9510 ic.   */ @@ -66,13 +69,12 @@ public:          this->enable_external_ref(false);          this->enable_rx_dboard_clock(false);          this->enable_tx_dboard_clock(false); +        this->enable_mimo_clock_out(false);          /* private clock enables, must be set here */          this->enable_dac_clock(true);          this->enable_adc_clock(true); - -        /* always driving the mimo reference */ -        this->enable_mimo_clock_out(true); +        this->enable_test_clock(enb_test_clk);      }      ~usrp2_clock_ctrl_impl(void){ @@ -83,6 +85,7 @@ public:          this->enable_dac_clock(false);          this->enable_adc_clock(false);          this->enable_mimo_clock_out(false); +        this->enable_test_clock(false);      }      void enable_mimo_clock_out(bool enb){ @@ -246,6 +249,54 @@ public:      double get_master_clock_rate(void){          return 100e6;      } +     +    void set_mimo_clock_delay(double delay) { +        //delay_val is a 5-bit value (0-31) for fine control +        //the equations below determine delay for a given ramp current, # of caps and fine delay register +        //delay range: +        //range_ns = 200*((caps+3)/i_ramp_ua)*1.3286 +        //offset (zero delay): +        //offset_ns = 0.34 + (1600 - i_ramp_ua)*1e-4 + ((caps-1)/ramp)*6 +        //delay_ns = offset_ns + range_ns * delay / 31 + +        int delay_val = boost::math::iround(delay/9.744e-9*31); + +        if(delay_val == 0) { +            switch(clk_regs.exp) { +            case 5: +                _ad9510_regs.delay_control_out5 = 1; +                break; +            case 6: +                _ad9510_regs.delay_control_out6 = 1; +                break; +            default: +                break; //delay not supported on U2 rev 3 +            } +        } else { +            switch(clk_regs.exp) { +            case 5: +                _ad9510_regs.delay_control_out5 = 0; +                _ad9510_regs.ramp_current_out5 = ad9510_regs_t::RAMP_CURRENT_OUT5_200UA; +                _ad9510_regs.ramp_capacitor_out5 = ad9510_regs_t::RAMP_CAPACITOR_OUT5_4CAPS; +                _ad9510_regs.delay_fine_adjust_out5 = delay_val; +                this->write_reg(0x34); +                this->write_reg(0x35); +                this->write_reg(0x36); +                break; +            case 6: +                _ad9510_regs.delay_control_out6 = 0; +                _ad9510_regs.ramp_current_out6 = ad9510_regs_t::RAMP_CURRENT_OUT6_200UA; +                _ad9510_regs.ramp_capacitor_out6 = ad9510_regs_t::RAMP_CAPACITOR_OUT6_4CAPS; +                _ad9510_regs.delay_fine_adjust_out6 = delay_val; +                this->write_reg(0x38); +                this->write_reg(0x39); +                this->write_reg(0x3A); +                break; +            default: +                break; +            } +        } +    }  private:      /*! diff --git a/host/lib/usrp/usrp2/clock_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp index db6c52c83..9ccbc959e 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.hpp +++ b/host/lib/usrp/usrp2/clock_ctrl.hpp @@ -91,8 +91,18 @@ public:      virtual void enable_test_clock(bool enb) = 0;      /*! -     * TODO other clock control api here.... +     * Enable/disable the ref clock output over the serdes cable. +     * \param enb true to enable +     */ +    virtual void enable_mimo_clock_out(bool enb) = 0; +     +    /*! +     * Set the output delay of the mimo clock +     * Used to synchronise daisy-chained USRPs over the MIMO cable +     * Can also be used to adjust delay for uneven reference cable lengths +     * \param delay the clock delay in seconds       */ +    virtual void set_mimo_clock_delay(double delay) = 0;  }; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index a9c39e650..efbb4b954 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -33,8 +33,8 @@ extern "C" {  #endif  //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 3 -#define USRP2_FW_COMPAT_NUM 7 +#define USRP2_FPGA_COMPAT_NUM 4 +#define USRP2_FW_COMPAT_NUM 8  //used to differentiate control packets over data port  #define USRP2_INVALID_VRT_HEADER 0 diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 766ea993c..b8ebd6030 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -27,6 +27,10 @@  #include <iostream>  #include <boost/date_time/posix_time/posix_time.hpp> +static const double mimo_clock_delay_usrp2_rev4 = 4.18e-9; +static const double mimo_clock_delay_usrp_n2xx = 0; //TODO +static const int mimo_clock_sync_delay_cycles = 134; +  using namespace uhd;  using namespace uhd::usrp;  using namespace boost::posix_time; @@ -38,8 +42,8 @@ usrp2_mboard_impl::usrp2_mboard_impl(      size_t index,      transport::udp_simple::sptr ctrl_transport,      transport::zero_copy_if::sptr data_transport, -    size_t recv_samps_per_packet, -    const device_addr_t &flow_control_hints +    const device_addr_t &device_args, +    size_t recv_samps_per_packet  ):      _index(index),      _iface(usrp2_iface::make(ctrl_transport)) @@ -58,7 +62,6 @@ usrp2_mboard_impl::usrp2_mboard_impl(      //contruct the interfaces to mboard perifs      _clock_ctrl = usrp2_clock_ctrl::make(_iface);      _codec_ctrl = usrp2_codec_ctrl::make(_iface); -    _serdes_ctrl = usrp2_serdes_ctrl::make(_iface);      //_gps_ctrl = usrp2_gps_ctrl::make(_iface);      //if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl; @@ -98,14 +101,14 @@ usrp2_mboard_impl::usrp2_mboard_impl(      _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET);      //setting the cycles per update (disabled by default) -    const double ups_per_sec = flow_control_hints.cast<double>("ups_per_sec", 0.0); +    const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0);      if (ups_per_sec > 0.0){          const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec);          _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up);      }      //setting the packets per update (enabled by default) -    const double ups_per_fifo = flow_control_hints.cast<double>("ups_per_fifo", 8.0); +    const double ups_per_fifo = device_args.cast<double>("ups_per_fifo", 8.0);      if (ups_per_fifo > 0.0){          const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size());          _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); @@ -118,6 +121,20 @@ usrp2_mboard_impl::usrp2_mboard_impl(      init_duc_config();      //initialize the clock configuration +    if (device_args.has_key("mimo_mode")){ +        if (device_args["mimo_mode"] == "master"){ +            _mimo_clocking_mode_is_master = true; +        } +        else if (device_args["mimo_mode"] == "slave"){ +            _mimo_clocking_mode_is_master = false; +        } +        else throw std::runtime_error( +            "mimo_mode must be set to master or slave" +        ); +    } +    else { +        _mimo_clocking_mode_is_master = bool(_iface->peek32(_iface->regs.status) & (1 << 8)); +    }      init_clock_config();      //init the codec before the dboard @@ -155,7 +172,6 @@ void usrp2_mboard_impl::update_clock_config(void){      //translate pps source enums      switch(_clock_config.pps_source){      case clock_config_t::PPS_SMA:  pps_flags |= U2_FLAG_TIME64_PPS_SMA;  break; -    case clock_config_t::PPS_MIMO: pps_flags |= U2_FLAG_TIME64_PPS_MIMO; break;      default: throw std::runtime_error("unhandled clock configuration pps source");      } @@ -176,7 +192,6 @@ void usrp2_mboard_impl::update_clock_config(void){          switch(_clock_config.ref_source){          case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break;          case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; -        case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break;          default: throw std::runtime_error("unhandled clock configuration reference source");          }          _clock_ctrl->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO @@ -187,7 +202,6 @@ void usrp2_mboard_impl::update_clock_config(void){          switch(_clock_config.ref_source){          case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break;          case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; -        case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break;          default: throw std::runtime_error("unhandled clock configuration reference source");          }          _clock_ctrl->enable_external_ref(_clock_config.ref_source != clock_config_t::REF_INT); @@ -195,6 +209,36 @@ void usrp2_mboard_impl::update_clock_config(void){      case usrp2_iface::USRP_NXXX: break;      } + +    //Handle the serdes clocking based on master/slave mode: +    //   - Masters always drive the clock over serdes. +    //   - Slaves always lock to this serdes clock. +    //   - Slaves lock their time over the serdes. +    if (_mimo_clocking_mode_is_master){ +        _clock_ctrl->enable_mimo_clock_out(true); +        switch(_iface->get_rev()){ +        case usrp2_iface::USRP_N200: +        case usrp2_iface::USRP_N210: +            _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx); +            break; + +        case usrp2_iface::USRP2_REV4: +            _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4); +            break; + +        default: break; //not handled +        } +        _iface->poke32(_iface->regs.time64_mimo_sync, 0); +    } +    else{ +        _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); +        _clock_ctrl->enable_external_ref(true); +        _clock_ctrl->enable_mimo_clock_out(false); +        _iface->poke32(_iface->regs.time64_mimo_sync, +            (1 << 8) | (mimo_clock_sync_delay_cycles & 0xff) +        ); +    } +  }  void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ diff --git a/host/lib/usrp/usrp2/serdes_ctrl.cpp b/host/lib/usrp/usrp2/serdes_ctrl.cpp deleted file mode 100644 index 1cda22f45..000000000 --- a/host/lib/usrp/usrp2/serdes_ctrl.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2010 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 -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// 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/>. -// - -#include "serdes_ctrl.hpp" -#include "usrp2_regs.hpp" - -using namespace uhd; - -/*! - * A usrp2 serdes control implementation - */ -class usrp2_serdes_ctrl_impl : public usrp2_serdes_ctrl{ -public: -    usrp2_serdes_ctrl_impl(usrp2_iface::sptr iface){ -        _iface = iface; -        _iface->poke32(_iface->regs.misc_ctrl_serdes, U2_FLAG_MISC_CTRL_SERDES_ENABLE | U2_FLAG_MISC_CTRL_SERDES_RXEN); -    } - -    ~usrp2_serdes_ctrl_impl(void){ -        _iface->poke32(_iface->regs.misc_ctrl_serdes, 0); //power-down -    } - -private: -    usrp2_iface::sptr _iface; -}; - -/*********************************************************************** - * Public make function for the usrp2 serdes control - **********************************************************************/ -usrp2_serdes_ctrl::sptr usrp2_serdes_ctrl::make(usrp2_iface::sptr iface){ -    return sptr(new usrp2_serdes_ctrl_impl(iface)); -} diff --git a/host/lib/usrp/usrp2/serdes_ctrl.hpp b/host/lib/usrp/usrp2/serdes_ctrl.hpp deleted file mode 100644 index 3c909c531..000000000 --- a/host/lib/usrp/usrp2/serdes_ctrl.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2010 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 -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// 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/>. -// - -#ifndef INCLUDED_SERDES_CTRL_HPP -#define INCLUDED_SERDES_CTRL_HPP - -#include "usrp2_iface.hpp" -#include <boost/shared_ptr.hpp> -#include <boost/utility.hpp> - -class usrp2_serdes_ctrl : boost::noncopyable{ -public: -    typedef boost::shared_ptr<usrp2_serdes_ctrl> sptr; - -    /*! -     * Make a serdes control object for the usrp2 serdes port. -     * \param _iface a pointer to the usrp2 interface object -     * \return a new serdes control object -     */ -    static sptr make(usrp2_iface::sptr iface); - -    //TODO fill me in with virtual methods - -}; - -#endif /* INCLUDED_SERDES_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index c3bbe4d65..133c39a35 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -201,8 +201,9 @@ sep_indexed_dev_addrs(device_addr);      //create a ctrl and data transport for each address      std::vector<udp_simple::sptr> ctrl_transports;      std::vector<zero_copy_if::sptr> data_transports; +    const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr); -    BOOST_FOREACH(const device_addr_t &dev_addr_i, sep_indexed_dev_addrs(device_addr)){ +    BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){          ctrl_transports.push_back(udp_simple::make_connected(              dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT)          )); @@ -213,7 +214,7 @@ sep_indexed_dev_addrs(device_addr);      //create the usrp2 implementation guts      return device::sptr( -        new usrp2_impl(ctrl_transports, data_transports, device_addr) +        new usrp2_impl(ctrl_transports, data_transports, device_addrs)      );  } @@ -227,7 +228,7 @@ UHD_STATIC_BLOCK(register_usrp2_device){  usrp2_impl::usrp2_impl(      std::vector<udp_simple::sptr> ctrl_transports,      std::vector<zero_copy_if::sptr> data_transports, -    const device_addr_t &flow_control_hints +    const device_addrs_t &device_args  ):      _data_transports(data_transports)  { @@ -244,11 +245,10 @@ usrp2_impl::usrp2_impl(      //!!!!! set the otw type here before continuing, its used below      //create a new mboard handler for each control transport -    for(size_t i = 0; i < ctrl_transports.size(); i++){ +    for(size_t i = 0; i < device_args.size(); i++){          _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( -            i, ctrl_transports[i], data_transports[i], -            this->get_max_recv_samps_per_packet(), -            flow_control_hints +            i, ctrl_transports[i], data_transports[i], device_args[i], +            this->get_max_recv_samps_per_packet()          )));          //use an empty name when there is only one mboard          std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : ""; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index aa8eb0155..85c00b079 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,7 +22,6 @@  #include "clock_ctrl.hpp"  #include "codec_ctrl.hpp"  #include "gps_ctrl.hpp" -#include "serdes_ctrl.hpp"  #include <uhd/device.hpp>  #include <uhd/utils/pimpl.hpp>  #include <uhd/types/dict.hpp> @@ -86,8 +85,8 @@ public:          size_t index,          uhd::transport::udp_simple::sptr,          uhd::transport::zero_copy_if::sptr, -        size_t recv_samps_per_packet, -        const uhd::device_addr_t &flow_control_hints +        const uhd::device_addr_t &device_args, +        size_t recv_samps_per_packet      );      ~usrp2_mboard_impl(void); @@ -100,12 +99,12 @@ public:  private:      size_t _index;      bool _continuous_streaming; +    bool _mimo_clocking_mode_is_master;      //interfaces      usrp2_iface::sptr _iface;      usrp2_clock_ctrl::sptr _clock_ctrl;      usrp2_codec_ctrl::sptr _codec_ctrl; -    usrp2_serdes_ctrl::sptr _serdes_ctrl;      usrp2_gps_ctrl::sptr _gps_ctrl;      //properties for this mboard @@ -192,7 +191,7 @@ public:      usrp2_impl(          std::vector<uhd::transport::udp_simple::sptr> ctrl_transports,          std::vector<uhd::transport::zero_copy_if::sptr> data_transports, -        const uhd::device_addr_t &flow_control_hints +        const uhd::device_addrs_t &device_args      );      ~usrp2_impl(void); diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index dd0433816..82ad30f08 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -57,6 +57,8 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {    x.time64_flags = sr_addr(misc_output_base, x.sr_time64 + 2);    x.time64_imm = sr_addr(misc_output_base, x.sr_time64 + 3);    x.time64_tps = sr_addr(misc_output_base, x.sr_time64 + 4); +  x.time64_mimo_sync = sr_addr(misc_output_base, x.sr_time64 + 5); +  x.status = bp_base + 4*8;    x.time64_secs_rb = bp_base + 4*10;    x.time64_ticks_rb = bp_base + 4*11;    x.compat_num_rb = bp_base + 4*12; diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 9936d634a..0311ac625 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -57,6 +57,8 @@ typedef struct {      int time64_flags; // flags -- see chart below      int time64_imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0)      int time64_tps; // ticks per second rollover count +    int time64_mimo_sync; +    int status;      int time64_secs_rb;      int time64_ticks_rb;      int compat_num_rb; | 
