/* -*- 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 . */ #ifndef INCLUDED_USRP2_ETH_PACKET_H #define INCLUDED_USRP2_ETH_PACKET_H #include "usrp2_cdefs.h" #include "usrp2_bytesex.h" #include "usrp2_mac_addr.h" #include "usrp2_mimo_config.h" __U2_BEGIN_DECLS #define U2_ETHERTYPE 0xBEEF // used in our frames #define MAC_CTRL_ETHERTYPE 0x8808 // used in PAUSE frames /* * All these data structures are BIG-ENDIAN on the wire */ // FIXME gcc specific. Really ought to come from compiler.h #define _AL4 __attribute__((aligned (4))) /* * \brief The classic 14-byte ethernet header */ typedef struct { u2_mac_addr_t dst; u2_mac_addr_t src; uint16_t ethertype; } __attribute__((packed)) u2_eth_hdr_t; /*! * \brief USRP2 transport header * * This enables host->usrp2 flow control and dropped packet detection. */ typedef struct { uint16_t flags; // MBZ, may be used for channel in future uint16_t fifo_status; // free space in Rx fifo in 32-bit lines uint8_t seqno; // sequence number of this packet uint8_t ack; // sequence number of next packet expected } __attribute__((packed)) u2_transport_hdr_t; /* * The fixed payload header of a USRP2 ethernet packet... * * Basically there's 1 word of flags and routing info, and 1 word * of timestamp that specifies when the data was received, or * when it should be transmitted. The data samples follow immediately. * * Transmit packets (from host to U2) * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Chan | mbz |I|S|E| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Timestamp | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * * Received packets (from U2 to host) * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Chan | mbz | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Timestamp | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * mbz == must be zero */ typedef struct { uint32_t word0; // flags etc uint32_t timestamp; // time of rx or tx (100 MHz) } u2_fixed_hdr_t; #define U2P_CHAN_MASK 0x1f #define U2P_CHAN_SHIFT 27 #define U2P_TX_IMMEDIATE 0x00000004 // send samples NOW, else at timestamp #define U2P_TX_START_OF_BURST 0x00000002 // this frame is the start of a burst #define U2P_TX_END_OF_BURST 0x00000001 // this frame is the end of a burst #define U2P_ALL_FLAGS 0x00000007 #define CONTROL_CHAN 0x1f static inline int u2p_chan(u2_fixed_hdr_t *p) { return (ntohl(p->word0) >> U2P_CHAN_SHIFT) & U2P_CHAN_MASK; } inline static uint32_t u2p_word0(u2_fixed_hdr_t *p) { return ntohl(p->word0); } inline static uint32_t u2p_timestamp(u2_fixed_hdr_t *p) { return ntohl(p->timestamp); } inline static void u2p_set_word0(u2_fixed_hdr_t *p, int flags, int chan) { p->word0 = htonl((flags & U2P_ALL_FLAGS) | ((chan & U2P_CHAN_MASK) << U2P_CHAN_SHIFT)); } inline static void u2p_set_timestamp(u2_fixed_hdr_t *p, uint32_t ts) { p->timestamp = htonl(ts); } /*! * \brief consolidated packet: ethernet header + transport header + fixed header */ typedef struct { u2_eth_hdr_t ehdr; u2_transport_hdr_t thdr; u2_fixed_hdr_t fixed; } u2_eth_packet_t; /* * full load of samples: * ethernet header + transport header + fixed header + maximum number of samples. * sizeof(u2_eth_samples_t) == 1512 * (payload is 1498 bytes, two bytes shorter than 1500 byte MTU) */ #define U2_MAX_SAMPLES 371 typedef struct { u2_eth_packet_t hdrs; uint32_t samples[U2_MAX_SAMPLES]; } u2_eth_samples_t; /* * Opcodes for control channel * * Reply opcodes are the same as the request opcode with the OP_REPLY_BIT set (0x80). */ #define OP_REPLY_BIT 0x80 #define OP_EOP 0 // marks last subpacket in packet #define OP_ID 1 #define OP_ID_REPLY (OP_ID | OP_REPLY_BIT) #define OP_BURN_MAC_ADDR 2 #define OP_BURN_MAC_ADDR_REPLY (OP_BURN_MAC_ADDR | OP_REPLY_BIT) #define OP_READ_TIME 3 // What time is it? (100 MHz counter) #define OP_READ_TIME_REPLY (OP_READ_TIME | OP_REPLY_BIT) #define OP_CONFIG_RX_V2 4 #define OP_CONFIG_RX_REPLY_V2 (OP_CONFIG_RX_V2 | OP_REPLY_BIT) #define OP_CONFIG_TX_V2 5 #define OP_CONFIG_TX_REPLY_V2 (OP_CONFIG_TX_V2 | OP_REPLY_BIT) #define OP_START_RX_STREAMING 6 #define OP_START_RX_STREAMING_REPLY (OP_START_RX_STREAMING | OP_REPLY_BIT) #define OP_STOP_RX 7 #define OP_STOP_RX_REPLY (OP_STOP_RX | OP_REPLY_BIT) #define OP_CONFIG_MIMO 8 #define OP_CONFIG_MIMO_REPLY (OP_CONFIG_MIMO | OP_REPLY_BIT) //#define OP_WRITE_REG xx // not implemented //#define OP_WRITE_REG_MASKED xx //#define OP_READ_REG xx //#define OP_READ_REG_REPLY xx /* * All subpackets are a multiple of 4 bytes long. * All subpackets start with an 8-bit opcode, an 8-bit len and an 8-bit rid. */ /*! * \brief Generic request and reply packet * * Used by: * OP_EOP, OP_BURN_MAC_ADDR_REPLY, OP_START_RX_STREAMING_REPLY, * OP_STOP_RX_REPLY */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t ok; // bool } _AL4 op_generic_t; /*! * \brief Reply info from a USRP2 */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; u2_mac_addr_t addr; uint16_t hw_rev; uint8_t fpga_md5sum[16]; uint8_t sw_md5sum[16]; } _AL4 op_id_reply_t; typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; uint32_t items_per_frame; // # of 32-bit data items; MTU=1500: [9,371] } _AL4 op_start_rx_streaming_t; typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; u2_mac_addr_t addr; } _AL4 op_burn_mac_addr_t; typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; uint32_t time; } _AL4 op_read_time_reply_t; /*! * \brief Configure receiver */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; // bitmask indicating which of the following fields are valid uint16_t valid; uint16_t gain; // fxpt_db (Q9.7) uint32_t freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20) uint32_t freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20) uint32_t decim; // desired decimation factor (NOT -1) uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format] } _AL4 op_config_rx_v2_t; // bitmask for "valid" field. If the bit is set, there's // meaningful data in the corresonding field. #define CFGV_GAIN 0x0001 // gain field is valid #define CFGV_FREQ 0x0002 // target_freq field is valid #define CFGV_INTERP_DECIM 0x0004 // interp or decim is valid #define CFGV_SCALE_IQ 0x0008 // scale_iq is valid /*! * \brief Reply to receiver configuration */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; uint16_t ok; // config was successful (bool) uint16_t inverted; // spectrum is inverted (bool) // RF frequency that corresponds to DC in the IF (fxpt_freq) uint32_t baseband_freq_hi; uint32_t baseband_freq_lo; // DDC frequency (fxpt_freq) uint32_t ddc_freq_hi; uint32_t ddc_freq_lo; // residual frequency (fxpt_freq) uint32_t residual_freq_hi; uint32_t residual_freq_lo; } _AL4 op_config_rx_reply_v2_t; /*! * \brief Configure transmitter */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; // bitmask indicating which of the following fields are valid uint16_t valid; uint16_t gain; // fxpt_db (Q9.7) uint32_t freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20) uint32_t freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20) uint32_t interp; // desired interpolation factor (NOT -1) uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format] } _AL4 op_config_tx_v2_t; /*! * \brief Reply to configure transmitter */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t mbz; uint16_t ok; // config was successful (bool) uint16_t inverted; // spectrum is inverted (bool) // RF frequency that corresponds to DC in the IF (fxpt_freq) uint32_t baseband_freq_hi; uint32_t baseband_freq_lo; // DUC frequency (fxpt_freq) uint32_t duc_freq_hi; uint32_t duc_freq_lo; // residual frequency (fxpt_freq) uint32_t residual_freq_hi; uint32_t residual_freq_lo; } _AL4 op_config_tx_reply_v2_t; /*! * \brief Configure MIMO clocking, etc (uses generic reply) */ typedef struct { uint8_t opcode; uint8_t len; uint8_t rid; uint8_t flags; // from usrp_mimo_config.h } op_config_mimo_t; /* * ================================================================ * union of all of subpacket types * ================================================================ */ typedef union { op_generic_t op_generic; op_id_reply_t op_id_reply; op_start_rx_streaming_t op_start_rx_streaming; op_burn_mac_addr_t op_burn_mac_addr; op_read_time_reply_t op_read_time_reply; op_config_rx_v2_t op_config_rx_v2; op_config_rx_reply_v2_t op_config_rx_reply_v2; op_config_tx_v2_t op_config_tx_v2; op_config_tx_reply_v2_t op_config_tx_reply_v2; op_config_mimo_t op_config_mimo; } u2_subpkt_t; __U2_END_DECLS #endif /* INCLUDED_USRP2_ETH_PACKET_H */