Imported Upstream version 3.2.2
[debian/gnuradio] / usrp2 / firmware / apps / rcv_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 <stddef.h>
33 #include <stdlib.h>
34
35
36 // ----------------------------------------------------------------
37
38 static u2_mac_addr_t dst_mac_addr =
39   {{  0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
40
41
42 // ----------------------------------------------------------------
43
44 #define PACKET_SIZE 1500                // bytes
45 #define ETH_DATA_RATE 1000000           // 1MB/s
46 #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)     // 13,3333 pkts/s
47
48 #define TIMER_RATE 100000000            // 100 MHz clock
49
50 static int timer_delta = TIMER_RATE/ETH_PACKET_RATE;    // ticks between interrupts
51
52 static volatile bool send_packet_now = false;   // timer handler sets this
53 static volatile bool link_is_up = false;        // eth handler sets this
54
55 int packet_number = 0;
56
57 // ----------------------------------------------------------------
58
59 // debugging output on tx pins
60 #define LS_MASK  0xE0000
61 #define LS_1000  0x80000
62 #define LS_100   0x40000
63 #define LS_10    0x20000
64
65
66 /*
67  * Called when eth phy state changes (w/ interrupts disabled)
68  */
69 void
70 link_changed_callback(int speed)
71 {
72   int v = 0;
73   switch(speed){
74   case 10:
75     v = LS_10;
76     link_is_up = true;
77     break;
78     
79   case 100:
80     v = LS_100;
81     link_is_up = true;
82     break;
83     
84   case 1000:
85     v = LS_100;
86     link_is_up = true;
87     break;
88
89   default:
90     v = 0;
91     link_is_up = false;
92     break;
93   }
94
95   //hal_gpio_set_tx(v, LS_MASK);        /* set debug bits on d'board */
96
97   putstr("\neth link changed: speed = ");
98   puthex16_nl(speed);
99 }
100
101 void
102 timer_irq_handler(unsigned irq)
103 {
104   hal_set_timeout(timer_delta); // schedule next timeout
105   send_packet_now = 1;
106 }
107
108
109 void
110 buffer_irq_handler(unsigned irq)
111 {
112   // FIXME
113 }
114
115 static void
116 init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
117 {
118   int i = 0;
119   int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
120
121   for (i = 0; i < BP_NLINES; i++){
122     buf[i] = mark | i;
123     mark ^= 0x00FF0000;
124   }
125
126   // copy header into buffer
127   memcpy_wa(buf, pkt, sizeof(*pkt));
128 }
129
130 static void
131 init_packets(void)
132 {
133   int   i;
134   
135   u2_eth_packet_t       pkt __attribute__((aligned (4)));
136
137   pkt.ehdr.dst = dst_mac_addr;
138   // src filled in by mac
139   pkt.ehdr.ethertype = U2_ETHERTYPE;
140
141   // fill ALL buffers for debugging
142   for (i = 0; i < 8; i++)
143     init_packet((void *)buffer_ram(i), &pkt, i);
144 }
145
146 int
147 main(void)
148 {
149   u2_init();
150
151   int   prev_leds = -1;
152   int   new_leds  = 0x00;
153   output_regs->leds = 0x00;
154
155   int peak_hold_count = 0;
156
157   // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
158   //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
159   //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
160
161   putstr("\nrcv_eth_packets\n");
162   
163   init_packets();
164
165   // pic_register_handler(IRQ_BUFFER, buffer_irq_handler);  // poll for now
166
167   // FIXME turn off timer since I don't think MTS and MFS instructions are implemented
168   // pic_register_handler(IRQ_TIMER, timer_irq_handler);
169   // hal_set_timeout(timer_delta);
170
171   ethernet_register_link_changed_callback(link_changed_callback);
172
173   ethernet_init();
174
175   //eth_mac->speed = 4; // FIXME hardcode mac speed to 1000
176
177   // kick off a receive
178   bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
179
180   while(1){
181     // u2_eth_packet_t  pkt;
182
183     new_leds = 0;
184     if (link_is_up)
185       new_leds = 0x2;
186
187     if ((buffer_pool_status->status & (BPS_DONE_2|BPS_ERROR_2)) != 0){
188       // we've got a packet!
189
190 #if 0
191       // copy to stack buffer so we can byte address it
192       memcpy_wa(&pkt, (void *)buffer_ram(2), sizeof(pkt));
193       
194       putstr("Rx: src: ");
195       print_mac_addr(pkt.ehdr.dst_addr);
196       putstr(" dst: ");
197       print_mac_addr(pkt.ehdr.src_addr);
198       putstr(" ethtype: ");
199       puthex16(pkt.ehdr.ethertype);
200       putstr(" len: ");
201       int len = (buffer_pool_status->last_line[2] + 1) * 4;
202       puthex16_nl(len);
203 #else
204       volatile int *bp = buffer_ram(2);
205       int       i;
206       for (i = 0; i < 16; i++){
207         puthex8(i);
208         putchar(':');
209         puthex32_nl(bp[i]);
210       }
211 #endif
212       
213       // kick off next receive
214       bp_clear_buf(2);
215       bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
216
217       peak_hold_count = 2048 * 10;
218     }
219
220     if (peak_hold_count > 0){
221       peak_hold_count--;
222       new_leds |= 0x1;
223     }
224
225     if (new_leds != prev_leds){
226       prev_leds = new_leds;
227       output_regs->leds = new_leds;
228     }
229   }
230
231   hal_finish();
232   return 1;
233 }