Imported Upstream version 3.2.2
[debian/gnuradio] / usrp2 / firmware / apps / gen_eth_packets.c
1 /*
2  * Copyright 2007 Free Software Foundation, Inc.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 #include "u2_init.h"
22 #include "memory_map.h"
23 #include "spi.h"
24 #include "hal_io.h"
25 #include "buffer_pool.h"
26 #include "pic.h"
27 #include "bool.h"
28 #include "ethernet.h"
29 #include "nonstdio.h"
30 #include "usrp2_eth_packet.h"
31 #include "memcpy_wa.h"
32 #include "print_rmon_regs.h"
33 #include <stddef.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37
38 // ----------------------------------------------------------------
39
40 static u2_mac_addr_t dst_mac_addr =
41   {{  0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
42
43 // ----------------------------------------------------------------
44
45 // #define      PACKET_SIZE 1500                // bytes
46 // #define ETH_DATA_RATE 1000000                // 1MB/s
47 // #define      ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)     // 13,3333 pkts/s
48
49 // static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE;    // ticks between interrupts
50
51 static int timer_delta = (int)(MASTER_CLK_RATE * 1e-3);         // tick at 1 kHz
52 static int sim_timer_delta = (int)(MASTER_CLK_RATE * 100e-6);   // tick at 10 kHz
53
54 static volatile bool send_packet_now = false;   // timer handler sets this
55 static volatile bool link_is_up = false;        // eth handler sets this
56
57 int packet_number = 0;
58
59
60 #define CPU_TX_BUF      0       // cpu xmits ethernet frames from here
61 #define CPU_RX_BUF      1       // receive ethernet frames here
62
63 // ----------------------------------------------------------------
64
65 /*
66  * Called when eth phy state changes (w/ interrupts disabled)
67  */
68 void
69 link_changed_callback(int speed)
70 {
71   link_is_up = speed == 0 ? false : true;
72   hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
73   printf("\neth link changed: speed = %d\n", speed);
74 }
75
76 void
77 timer_irq_handler(unsigned irq)
78 {
79   hal_set_timeout(timer_delta); // schedule next timeout
80   send_packet_now = 1;
81 }
82
83
84 static void
85 init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
86 {
87   int i = 0;
88   int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
89
90   for (i = 0; i < BP_NLINES; i++){
91     buf[i] = mark | i;
92     mark ^= 0x00FF0000;
93   }
94
95   // copy header into buffer
96   memcpy_wa(buf, pkt, sizeof(*pkt));
97 }
98
99 static void
100 init_packets(void)
101 {
102   u2_eth_packet_t       pkt __attribute__((aligned (4)));
103
104   memset(&pkt, 0, sizeof(pkt));
105
106   pkt.ehdr.dst = dst_mac_addr;
107   // src address filled in by mac
108
109   pkt.ehdr.ethertype = U2_ETHERTYPE;
110   pkt.fixed.word0 = 0x01234567;
111   pkt.fixed.timestamp = 0xffffffff;
112
113   // init just the one we're using
114   init_packet((void *)buffer_ram(CPU_TX_BUF), &pkt, CPU_TX_BUF);
115 }
116
117 int
118 main(void)
119 {
120   int npackets_sent = 0;
121
122   u2_init();
123
124   // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
125   //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
126   //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
127
128   putstr("\ngen_eth_packets\n");
129   
130   hal_set_leds(0x0, 0x3);
131
132   init_packets();
133
134   pic_register_handler(IRQ_TIMER, timer_irq_handler);
135
136   if (hwconfig_simulation_p())
137     timer_delta = sim_timer_delta;
138
139   hal_set_timeout(timer_delta);
140
141   ethernet_register_link_changed_callback(link_changed_callback);
142   ethernet_init();
143
144   if (hwconfig_simulation_p()){
145     eth_mac->speed = 4; // hardcode mac speed to 1000
146     link_is_up = true;
147   }
148
149   // fire off a receive from the ethernet
150   bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
151
152   while(1){
153     uint32_t status = buffer_pool_status->status;
154
155     if (status & (BPS_DONE(CPU_RX_BUF) | BPS_ERROR(CPU_RX_BUF))){
156       bp_clear_buf(CPU_RX_BUF);
157       // ignore incoming ethernet packets; they were looped back in sim
158       bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
159     }
160
161     if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))){
162       bp_clear_buf(CPU_TX_BUF);
163       npackets_sent++;
164       if ((npackets_sent & 0xF) == 0)   // print after every 16 packets
165         print_rmon_regs();
166     }
167
168     if (link_is_up && send_packet_now && (status & BPS_IDLE(CPU_TX_BUF))){
169       send_packet_now = false;
170
171       // kick off the next packet
172       // FIXME set packet number in packet
173
174       bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, 255);        // 1KB total
175       hal_toggle_leds(0x1);
176     }
177   }
178
179   hal_finish();
180   return 1;
181 }