source: edk_user_repository/WARP/sw_services/WARPxilnet_v3_04_a/src/xilnet_eth.c

Last change on this file was 4459, checked in by welsh, 9 years ago

Minor update to TEMAC Ethernet driver.

File size: 48.7 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2004 Xilinx, Inc.  All rights reserved.
3//
4// Xilinx, Inc.
5// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS FOR A PARTICULAR PURPOSE.
16//
17// File   : eth.c
18// Date   : 2002, March 20.
19// Author : Sathya Thammanur
20// Company: Xilinx
21// Group  : Emerging Software Technologies
22//
23// Summary:
24// Ethernet layer specific functions
25//
26// $Id: eth.c,v 1.2.8.6 2005/11/15 23:41:10 salindac Exp $
27//
28////////////////////////////////////////////////////////////////////////////////
29
30////////////////////////////////////////////////////////////////////////////////
31// see copyright.txt for Rice University/Mango Communications modifications
32////////////////////////////////////////////////////////////////////////////////
33
34
35/***************************** Include Files *********************************/
36
37#include <string.h>
38#include <xilnet_config.h>
39#include <xilnet_xilsock.h>
40
41#include "xio.h"
42#include "stdio.h"
43
44
45/*************************** Constant Definitions ****************************/
46
47// Defines for consolidated error message function
48#define XILNET_ETH_ERR_NUM_DEV                             1
49#define XILNET_ETH_ERR_USES_DRIVER                         2
50#define XILNET_ETH_ERR_INF_DNE                             3
51#define XILNET_ETH_ERR_INF_NOT_CONFIG                      4
52
53// #define _DEBUG_XILNET_HW_TABLE_
54
55/*********************** Global Variable Definitions *************************/
56
57
58
59/*************************** Variable Definitions ****************************/
60
61
62// Xilnet HW Address Table
63//   Note:  There is only one address table to be shared among all the
64//       Ethernet devices.  This can be updated in the future.
65struct xilnet_hw_addr_table xilnet_hw_tbl[HW_ADDR_TBL_ENTRIES];
66
67
68// Flags
69unsigned char             ishwaddrinit = 0;
70static unsigned long long curr_age     = 0;
71
72
73/*************************** Function Prototypes *****************************/
74
75#ifdef _DEBUG_
76void print_pkt(unsigned char *buf, int size);
77
78#if 0
79void print_hw_tbl();
80#endif
81
82#ifdef  XILNET_AXI_DMA_INF_USED
83void print_XAxiDma_Bd( XAxiDma_Bd *BD_ptr );
84void print_XAxiDma_BdRing( XAxiDma_BdRing *BD_RING_ptr );
85void print_XAxiDma_Config( XAxiDma_Config * DMA_CFG_ptr );
86#endif
87
88#ifdef XILNET_AXI_FIFO_INF_USED
89void print_XLlFifo( XLlFifo * FIFO_ptr );
90#endif
91
92#endif
93
94
95/******************************** Functions **********************************/
96
97void xilnet_eth_print_err_msg( unsigned int msg_num, unsigned int eth_dev_num ) {
98
99    switch( msg_num ) {
100
101    case XILNET_ETH_ERR_NUM_DEV:
102        xil_printf("  **** ERROR:  Trying to use Ethernet device %c.  Only %d configured in the HW. \n", wn_conv_eth_dev_num(eth_dev_num), XILNET_NUM_ETH_DEVICES);   
103    break;
104   
105    case XILNET_ETH_ERR_USES_DRIVER:
106        xil_printf("  **** ERROR:  Ethernet device %c is not supported by the WARPxilnet library.  \n", wn_conv_eth_dev_num(eth_dev_num) );
107        xil_printf("               Please check library configuration in the BSP.   \n" );
108    break;
109
110    case XILNET_ETH_ERR_INF_DNE:
111        xil_printf("  **** ERROR:  Trying to use Ethernet device %c.  Interface %d does not exist. \n", wn_conv_eth_dev_num(eth_dev_num), eth_device[eth_dev_num].inf_type);
112    break;
113
114    case XILNET_ETH_ERR_INF_NOT_CONFIG:
115        xil_printf("  **** ERROR:  Trying to use Ethernet device %c.  Driver not configured to use ", wn_conv_eth_dev_num(eth_dev_num));   
116    break;
117    }
118}
119
120
121
122int xilnet_eth_device_init( unsigned int    eth_dev_num,
123                            unsigned int    base_addr,
124                            unsigned char * node_ip_addr,
125                            unsigned char * node_hw_addr
126                          ) {
127
128    int          status;
129
130#ifdef  XILNET_AXI_DMA_INF_USED
131    XAxiDma_Bd   BD_template;
132#endif
133
134    // Check to see if we are initializing a valid interface
135    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
136        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
137        return -1;
138    }
139   
140#ifdef _DEBUG_
141    xil_printf("xilnet_eth_device_init: Device %c \n", wn_conv_eth_dev_num(eth_dev_num) );
142#endif
143
144    // Initialize the Ethernet device structure
145    xilnet_init_eth_device_struct(eth_dev_num);
146
147    // Check to see if the xilnet driver uses the Ethernet instance
148    if ( !eth_device[eth_dev_num].uses_driver ) {
149        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
150        return -1;
151    }
152   
153    // Set up HW info
154    xilnet_eth_set_inf_hw_info(eth_dev_num, node_ip_addr, node_hw_addr);
155
156    // Depending on the interface type, set up the device
157    switch( eth_device[eth_dev_num].inf_type ) {
158
159    case XILNET_AXI_FIFO_INF:
160
161#ifdef XILNET_AXI_FIFO_INF_USED
162
163        xil_printf("  Configuring ETH %c for AXI FIFO mode with %d byte buffers (%d receive, 1 send)\n", wn_conv_eth_dev_num(eth_dev_num), eth_device[eth_dev_num].buf_size, eth_device[eth_dev_num].num_recvbuf );
164
165        XLlFifo_Initialize( eth_device[eth_dev_num].inf_ref, base_addr);
166
167#ifdef _DEBUG_
168        print_XLlFifo( eth_device[eth_dev_num].inf_ref );
169#endif
170
171#else
172        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
173        xil_printf("AXI FIFO. \n");
174        return -1;
175#endif
176        break;
177
178
179    case XILNET_AXI_DMA_INF:
180
181#ifdef XILNET_AXI_DMA_INF_USED
182        xil_printf("  Configuring ETH %c for AXI DMA mode with %d byte buffers (%d receive, 1 send)\n", wn_conv_eth_dev_num(eth_dev_num), eth_device[eth_dev_num].buf_size, eth_device[eth_dev_num].num_recvbuf );
183
184        // Initialize DMA pointers
185        eth_device[eth_dev_num].inf_cfg_ref      = (void *) XAxiDma_LookupConfig( eth_device[eth_dev_num].inf_id );
186        eth_device[eth_dev_num].dma_rx_ring_ref  = (void *) XAxiDma_GetRxRing( (XAxiDma *)eth_device[eth_dev_num].inf_ref );
187        eth_device[eth_dev_num].dma_tx_ring_ref  = (void *) XAxiDma_GetTxRing( (XAxiDma *)eth_device[eth_dev_num].inf_ref );
188
189#ifdef _DEBUG_
190        print_XAxiDma_Config( eth_device[eth_dev_num].inf_cfg_ref );
191#endif
192
193        // Initialize AXIDMA engine. AXIDMA engine must be initialized before AxiEthernet.
194        // During AXIDMA engine initialization, AXIDMA hardware is reset, and since AXIDMA
195        // reset line is connected to AxiEthernet, this would ensure a reset of AxiEthernet.
196
197        status = XAxiDma_CfgInitialize( (XAxiDma *)eth_device[eth_dev_num].inf_ref, eth_device[eth_dev_num].inf_cfg_ref);
198        if(status != XST_SUCCESS) {
199            xil_printf("*** Error initializing DMA\n");
200        }
201
202        // Setup RX BD space:
203        //   - RX_BD_space is a properly aligned area of memory
204        //   - No MMU is being used so the physical and virtual addresses are the same.
205        //   - Setup a BD template for the channel. This template will be copied to every BD.
206
207#ifdef _DEBUG_
208        xil_printf("RX BD Space    = 0x%x\n", eth_device[eth_dev_num].dma_rx_bd_ref);
209#endif
210
211        // Create the RX BD ring
212        status = XAxiDma_BdRingCreate( eth_device[eth_dev_num].dma_rx_ring_ref,
213                                 (u32) eth_device[eth_dev_num].dma_rx_bd_ref,
214                                 (u32) eth_device[eth_dev_num].dma_rx_bd_ref,
215                                       XILNET_BD_ALIGNMENT,
216                                       eth_device[eth_dev_num].dma_rx_bd_cnt);
217        if (status != XST_SUCCESS) {
218            xil_printf("*** Error setting up RX BD space\n");
219        }
220
221        XAxiDma_BdClear(&BD_template);
222
223        status = XAxiDma_BdRingClone(eth_device[eth_dev_num].dma_rx_ring_ref, &BD_template);
224        if (status != XST_SUCCESS) {
225            xil_printf("*** Error initializing RX BD space\n");
226        }
227
228        // Setup TX BD space:
229        //   - TX_BD_space is a properly aligned area of memory
230        //   - No MMU is being used so the physical and virtual addresses are the same.
231        //   - Setup a BD template for the channel. This template will be copied to every BD.
232
233#ifdef _DEBUG_
234        xil_printf("TX BD Space    = 0x%x\n", eth_device[eth_dev_num].dma_tx_bd_ref);
235#endif
236
237        // Create the TX BD ring
238        status = XAxiDma_BdRingCreate( eth_device[eth_dev_num].dma_tx_ring_ref,
239                                 (u32) eth_device[eth_dev_num].dma_tx_bd_ref,
240                                 (u32) eth_device[eth_dev_num].dma_tx_bd_ref,
241                                       XILNET_BD_ALIGNMENT,
242                                       eth_device[eth_dev_num].dma_tx_bd_cnt);
243        if (status != XST_SUCCESS) {
244            xil_printf("*** Error setting up TX BD space\n");
245        }
246
247        // We can re-use the BD_template from above
248        status = XAxiDma_BdRingClone(eth_device[eth_dev_num].dma_tx_ring_ref, &BD_template);
249        if (status != XST_SUCCESS) {
250            xil_printf("*** Error initializing TX BD space\n");
251        }
252
253#else
254        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
255        xil_printf("AXI DMA. \n");
256        return -1;
257#endif
258        break;
259
260    case XILNET_TEMAC_INF:
261
262#ifdef XILNET_TEMAC_INF_USED
263
264        xil_printf("  Configuring ETH %c for TEMAC mode with %d byte buffers (%d receive, 1 send)\n", wn_conv_eth_dev_num(eth_dev_num), eth_device[eth_dev_num].buf_size, eth_device[eth_dev_num].num_recvbuf );
265
266        // Initialize DMA pointers
267        eth_device[eth_dev_num].inf_dma_cfg_ref      = (void *) XDmaCentral_LookupConfig( eth_device[eth_dev_num].inf_dma_id );
268
269        //Initialize the config struct
270        status = XDmaCentral_CfgInitialize((XDmaCentral *)       eth_device[eth_dev_num].inf_dma_ref,
271                                           (XDmaCentral_Config *)eth_device[eth_dev_num].inf_dma_cfg_ref,
272                                          ((XDmaCentral_Config *)eth_device[eth_dev_num].inf_dma_cfg_ref)->BaseAddress );
273        if(status != XST_SUCCESS) {
274            xil_printf("*** Error initializing DMA\n");
275        }
276
277        //Disable Interrupts
278        XDmaCentral_InterruptEnableSet(eth_device[eth_dev_num].inf_dma_ref, 0);
279
280#ifdef _DEBUG_
281        xil_printf("Initializing FIFO: %x     %x    \n", eth_device[eth_dev_num].inf_ref, base_addr);
282#endif       
283
284        // Initialize the FIFO
285        XLlFifo_Initialize( eth_device[eth_dev_num].inf_ref, base_addr);
286
287
288#else
289        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
290        xil_printf("TEMAC. \n");
291        return -1;
292#endif
293        break;
294
295    default:
296        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_DNE, eth_dev_num );
297        return -1;
298        break;
299    }
300
301#ifdef _DEBUG_
302        xil_printf("xilnet_eth_device_init done\n");
303#endif       
304       
305    return 0;
306}
307
308
309
310int xilnet_eth_set_inf_hw_info( unsigned int eth_dev_num, unsigned char * node_ip_addr, unsigned char * node_hw_addr ) {
311
312    int i;
313
314    // Check to see if we are initializing a valid interface
315    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
316        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
317        return -1;
318    }
319
320    // Check to see if the xilnet driver uses the Ethernet instance
321    if ( !eth_device[eth_dev_num].uses_driver ) {
322        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
323        return -1;
324    }
325   
326#ifdef _DEBUG_
327    xil_printf("Setting IP Address:  %d.%d.%d.%d \n", node_ip_addr[0], node_ip_addr[1], node_ip_addr[2], node_ip_addr[3]);
328    xil_printf("Setting HW Address:  %2x-%2x-%2x-%2x-%2x-%2x \n", node_hw_addr[0], node_hw_addr[1], node_hw_addr[2], node_hw_addr[3], node_hw_addr[4], node_hw_addr[5]);
329#endif
330
331    // Update the IP Address
332    for ( i = 0; i < IP_VERSION; i++) {
333        eth_device[eth_dev_num].node_ip_addr[i] = node_ip_addr[i];
334    }
335
336    // Update the MAC Address
337    for ( i = 0; i < ETH_ADDR_LEN; i++ ) {
338        eth_device[eth_dev_num].node_hw_addr[i] = node_hw_addr[i];
339    }
340
341    return 0;
342}
343
344
345
346int xilnet_eth_get_inf_ip_addr( unsigned int eth_dev_num, unsigned char * node_ip_addr ) {
347
348    int i;
349
350    // Check to see if we are initializing a valid interface
351    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
352        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
353        return -1;
354    }
355
356    // Check to see if the xilnet driver uses the Ethernet instance
357    if ( !eth_device[eth_dev_num].uses_driver ) {
358        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
359        return -1;
360    }
361   
362    // Update the IP Address
363    for ( i = 0; i < IP_VERSION; i++) {
364        node_ip_addr[i] = eth_device[eth_dev_num].node_ip_addr[i];
365    }
366
367#ifdef _DEBUG_
368    xil_printf("Getting IP Address:  %d.%d.%d.%d \n", node_ip_addr[0], node_ip_addr[1], node_ip_addr[2], node_ip_addr[3]);
369#endif
370
371    return 0;
372}
373
374
375
376int xilnet_eth_get_inf_hw_addr( unsigned int eth_dev_num, unsigned char * node_hw_addr ) {
377
378    int i;
379
380    // Check to see if we are initializing a valid interface
381    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
382        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
383        return -1;
384    }
385
386    // Check to see if the xilnet driver uses the Ethernet instance
387    if ( !eth_device[eth_dev_num].uses_driver ) {
388        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
389        return -1;
390    }
391   
392    // Update the MAC Address
393    for ( i = 0; i < ETH_ADDR_LEN; i++ ) {
394        node_hw_addr[i] = eth_device[eth_dev_num].node_hw_addr[i];
395    }
396
397#ifdef _DEBUG_
398    xil_printf("Getting HW Address:  %2x-%2x-%2x-%2x-%2x-%2x \n", node_hw_addr[0], node_hw_addr[1], node_hw_addr[2], node_hw_addr[3], node_hw_addr[4], node_hw_addr[5]);
399#endif
400
401    return 0;
402}
403
404
405
406int xilnet_eth_device_start( unsigned int eth_dev_num ) {
407
408    int              status;
409    int              i;
410    int              free_BD_count;
411
412#ifdef  XILNET_AXI_DMA_INF_USED
413    unsigned int     rx_buffer_address;
414    XAxiDma_BdRing  *RX_RING_ptr;
415    XAxiDma_Bd      *BD_ptr;
416    XAxiDma_Bd      *BD_cur_ptr;
417#endif
418
419    // Check to see if we are initializing a valid interface
420    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
421        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
422        return -1;
423    }
424   
425    // Check to see if the xilnet driver uses the Ethernet instance
426    if ( !eth_device[eth_dev_num].uses_driver ) {
427        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
428        return -1;
429    }
430
431    // Depending on the interface type, set up the device
432    switch( eth_device[eth_dev_num].inf_type ) {
433
434    case XILNET_AXI_FIFO_INF:
435
436#ifdef XILNET_AXI_FIFO_INF_USED
437        // Do nothing, interface is already ready to go
438
439#ifdef _DEBUG_
440        xil_printf("Starting Ethernet Device %c with AXI FIFO\n", wn_conv_eth_dev_num(eth_dev_num) );
441#endif       
442       
443#else
444        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
445        xil_printf("AXI FIFO. \n");
446        return -1;
447#endif
448
449        break;
450
451
452    case XILNET_AXI_DMA_INF:
453
454#ifdef XILNET_AXI_DMA_INF_USED
455
456        // Get the TX Buffer Descriptor Ring pointer
457        RX_RING_ptr = (XAxiDma_BdRing *)eth_device[eth_dev_num].dma_rx_ring_ref;
458
459        // Initialize RX BD space:
460        //   - Configure buffer descriptors
461        free_BD_count = XAxiDma_BdRingGetFreeCnt(RX_RING_ptr);
462
463        // Allocate receive buffers
464        status = XAxiDma_BdRingAlloc(RX_RING_ptr, free_BD_count, &BD_ptr);
465        if (status != XST_SUCCESS) {
466            xil_printf("*** Error allocating RxBD\n");
467            return -1;
468        }
469
470#ifdef _DEBUG_
471        xil_printf("Recieve Buffer = 0x%x    size= %d \n", eth_device[eth_dev_num].recvbuf, sizeof(eth_device[eth_dev_num].recvbuf));
472        print_XAxiDma_Bd( BD_ptr );
473#endif
474
475        if ( eth_device[eth_dev_num].num_recvbuf != free_BD_count ) {
476            xil_printf("*** Error number of receive buffers %d not equal to number of buffer descriptors %d \n", eth_device[eth_dev_num].num_recvbuf, free_BD_count);
477            return -1;
478        }
479
480        // Setup the Buffer descriptors
481        BD_cur_ptr = BD_ptr;
482        for ( i = 0; i < free_BD_count; i++ ){
483            rx_buffer_address = (u32)((u32)(eth_device[eth_dev_num].recvbuf) + (u32)(i * eth_device[eth_dev_num].buf_size));
484       
485            XAxiDma_BdSetBufAddr(BD_cur_ptr, rx_buffer_address);
486            XAxiDma_BdSetLength(BD_cur_ptr, eth_device[eth_dev_num].buf_size, RX_RING_ptr->MaxTransferLen);
487            XAxiDma_BdSetCtrl(BD_cur_ptr, 0);
488            XAxiDma_BdSetId(BD_cur_ptr, rx_buffer_address);
489
490            BD_cur_ptr = XAxiDma_BdRingNext(RX_RING_ptr, BD_cur_ptr);
491        }
492
493
494        // Enqueue to HW
495        status = XAxiDma_BdRingToHw(RX_RING_ptr, free_BD_count, BD_ptr);
496        if (status != XST_SUCCESS) {
497            xil_printf("*** Error committing RxBD to HW\n");
498            return -1;
499        }
500
501#ifdef _DEBUG_
502        xil_printf("ETH_B_DMA_RX_RING_ptr: \n");
503        print_XAxiDma_BdRing( RX_RING_ptr );
504        print_XAxiDma_Bd( BD_ptr );
505#endif
506
507        // Start DMA RX channel. Now it's ready to receive data.
508        status = XAxiDma_BdRingStart( RX_RING_ptr );
509        if (status != XST_SUCCESS) {
510            xil_printf("*** Error starting RX channel\n");
511            return -1;
512        }
513
514#else
515        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
516        xil_printf("AXI DMA. \n");
517        return -1;
518#endif
519        break;
520
521
522    case XILNET_TEMAC_INF:
523
524#ifdef XILNET_TEMAC_INF_USED
525        // Do nothing, interface is already ready to go
526
527#ifdef _DEBUG_
528        xil_printf("Starting Ethernet Device %d with TEMAC\n", eth_dev_num);
529#endif       
530
531#else
532        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
533        xil_printf("TEMAC. \n");
534        return -1;
535#endif
536        break;
537
538    default:
539        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_DNE, eth_dev_num );
540        return -1;
541        break;
542    }
543
544    return 0;
545}
546
547
548
549/*
550 * initialize xilnet hardware address
551 */
552void xilnet_eth_init_hw_addr(int eth_dev_num, unsigned char* addr) {
553   int k = 0;
554   int j;
555   int sum = 0;
556   int val = 0;
557   
558   for (j = 0; j < 5; j++) {
559   
560      // parse input for colon separated hw address
561      while(addr[k] != ':') {
562         if (addr[k] >= 'a' && addr[k] <= 'f') 
563            val = addr[k] - 'a' + 10;
564         else if (addr[k] >= 'A' && addr[k] <= 'F')
565            val = addr[k] - 'A' + 10;
566         else
567            val = addr[k] - '0';
568         sum = sum * 16 + val;
569         k++;
570      }
571   
572      k++; // move over the colon
573      eth_device[eth_dev_num].node_hw_addr[j] = (unsigned char) sum;
574      sum = 0;   
575   }
576   
577   // read last byte of hw address
578   while (addr[k] != '\0') {
579      if (addr[k] >= 'a' && addr[k] <= 'f') 
580         val = addr[k] - 'a' + 10;
581      else if (addr[k] >= 'A' && addr[k] <= 'F')
582         val = addr[k] - 'A' + 10;
583      else
584         val = addr[k] - '0';
585      sum = sum * 16 + val;
586      k++;
587   } 
588   eth_device[eth_dev_num].node_hw_addr[5] = (unsigned char) sum;
589}
590
591
592#ifdef XILNET_TEMAC_INF_USED
593inline void waitForDMA( unsigned int eth_dev_num )
594{
595    int RegValue;
596
597    // Wait until the DMA transfer is done by checking the Status register
598    do {RegValue = XDmaCentral_GetStatus((XDmaCentral *)eth_device[eth_dev_num].inf_dma_ref);}
599    while ((RegValue & XDMC_DMASR_BUSY_MASK) == XDMC_DMASR_BUSY_MASK);
600
601    return;
602}
603#endif
604
605
606/*
607 * Receive frame
608 *
609 * Returns either -1 or a pointer to the buffer of the received frame
610 *
611 */
612unsigned int xilnet_eth_recv_frame( unsigned int eth_dev_num ) {
613
614    // TODO: FIX - NEEDS TO RETURN THE POINTER TO THE BUFFER
615
616    int status             = -1;
617    int processed_BD_count = 0;
618    int free_BD_count      = 0;
619    int size               = -1;
620    struct xilnet_eth_hdr *eth;
621    void                  *pktBufPtr;
622   
623#ifdef XILNET_AXI_DMA_INF_USED
624    int dma_error           = 0;
625
626    XAxiDma_BdRing        *RX_RING_ptr;
627    XAxiDma_BdRing        *TX_RING_ptr;
628    XAxiDma_Bd            *BD_ptr;
629#endif
630
631#ifdef _DEBUG_
632    unsigned char         *tmp_ptr;
633#endif
634
635    // Check to see if we are receiving on a valid interface
636    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
637        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
638        return -1;
639    }
640
641    // Check to see if the xilnet driver uses the Ethernet instance
642    if ( !eth_device[eth_dev_num].uses_driver ) {
643        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
644        return -1;
645    }
646   
647    // Device specific routine for getting a frame
648    switch( eth_device[eth_dev_num].inf_type ) {
649
650    case XILNET_AXI_FIFO_INF:
651
652#ifdef XILNET_AXI_FIFO_INF_USED
653
654#if 0
655        xil_printf("AXI ETHERNET FIFO:  \n");
656        xil_printf("FIFO_INST:  0x%x \n", eth_device[eth_dev_num].inf_ref);
657        xil_printf("Ethernet FIFO is empty: %d \n", XLlFifo_IsRxEmpty((XLlFifo *)eth_device[eth_dev_num].inf_ref));
658        xil_printf("Base Addr             : 0x%x \n", ((XLlFifo *)eth_device[eth_dev_num].inf_ref)->BaseAddress );
659        xil_printf("RX Occupancy value    : 0x%x \n", ((*(volatile u32 *)((((XLlFifo *)eth_device[eth_dev_num].inf_ref)->BaseAddress) + (0x0000001c)))) );
660#endif
661
662        pktBufPtr = eth_device[eth_dev_num].recvbuf;
663
664        if(XLlFifo_IsRxEmpty((XLlFifo *)eth_device[eth_dev_num].inf_ref)) {
665
666            size = -1;
667
668        } else {
669
670#ifdef _PERFORMANCE_MONITOR_
671            wl_setDebugGPIO(0x1);
672#endif
673
674            if(XLlFifo_RxOccupancy((XLlFifo *)eth_device[eth_dev_num].inf_ref)) {
675                size = XLlFifo_RxGetLen((XLlFifo *)eth_device[eth_dev_num].inf_ref);
676                XLlFifo_Read((XLlFifo *)eth_device[eth_dev_num].inf_ref, pktBufPtr, size);
677            }
678        }
679#else
680        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
681        xil_printf("AXI FIFO. \n");
682        return -1;
683#endif
684        break;
685
686
687    case XILNET_AXI_DMA_INF:
688
689#ifdef XILNET_AXI_DMA_INF_USED
690
691#if 0
692        xil_printf("AXI ETHERNET DMA:  \n");
693#endif
694
695        // Get the RX Buffer Descriptor Ring pointer
696        RX_RING_ptr = (XAxiDma_BdRing *)eth_device[eth_dev_num].dma_rx_ring_ref;
697
698        // Check to see that the HW is started (if it is not started, we must have gotten an error somewhere
699        if ( !XAxiDma_BdRingHwIsStarted( RX_RING_ptr ) ) {
700
701            // Get the TX Buffer Descriptor Ring pointer
702            TX_RING_ptr = (XAxiDma_BdRing *)eth_device[eth_dev_num].dma_tx_ring_ref;
703       
704            // Check to see if we have a RX error
705            if ( XAxiDma_BdRingGetError( RX_RING_ptr ) ) {
706#ifdef _DEBUG_
707                print_XAxiDma_BdRing( RX_RING_ptr );
708#endif
709                xil_printf("*** ERROR in RX DMA transfer: 0x%8x \n", XAxiDma_BdRingGetError( RX_RING_ptr ));
710                dma_error = 1;
711            }
712       
713            // Check to see if we have a TX error
714            if ( XAxiDma_BdRingGetError( TX_RING_ptr ) ) {
715#ifdef _DEBUG_
716                print_XAxiDma_BdRing( TX_RING_ptr );
717#endif
718                xil_printf("*** ERROR in TX DMA transfer: 0x%8x \n", XAxiDma_BdRingGetError( TX_RING_ptr ));
719                dma_error = 1;
720            }
721           
722            // If there is an error, reset the DMA
723            if ( dma_error ) {
724                xil_printf("*** Resetting DMA \n");
725                XAxiDma_Reset( (XAxiDma *)eth_device[eth_dev_num].inf_ref );
726            }
727
728            // If not, then start DMA RX channel
729            status = XAxiDma_BdRingStart( RX_RING_ptr );
730            if (status != XST_SUCCESS) {
731                xil_printf("*** Error starting RX channel\n");
732                return -1;
733            }
734        }
735       
736        // See if we have any data to process
737        // NOTE:  We will only process one buffer descriptor at a time in this function call
738        processed_BD_count = XAxiDma_BdRingFromHw(RX_RING_ptr, 0x1, &BD_ptr);
739
740        // If we have data, then we need process the buffer
741        if ( processed_BD_count > 0 ) {
742
743#ifdef _PERFORMANCE_MONITOR_
744            wl_setDebugGPIO(0x1);
745#endif
746
747            status = XAxiDma_BdGetSts(BD_ptr);
748
749            if ((status & XAXIDMA_BD_STS_ALL_ERR_MASK) || (!(status & XAXIDMA_BD_STS_COMPLETE_MASK))) {
750                xil_printf("*** Rx Error: 0x%8x\n", status);
751                return -1;
752            } else {
753                size = (XAxiDma_BdRead(BD_ptr, XAXIDMA_BD_USR4_OFFSET)) & 0x0000FFFF;
754            }
755
756            pktBufPtr = (void *)XAxiDma_BdGetId(BD_ptr);       // BD ID was set to the base address of the buffer
757        }
758#else
759        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
760        xil_printf("AXI DMA. \n");
761        return -1;
762#endif
763        break;
764
765
766    case XILNET_TEMAC_INF:
767
768#ifdef XILNET_TEMAC_INF_USED
769
770#if 0
771        xil_printf("TEMAC FIFO:  \n");
772        xil_printf("FIFO_INST:  0x%x \n", eth_device[eth_dev_num].inf_ref);
773        xil_printf("Ethernet FIFO is empty: %d \n", XLlFifo_IsRxEmpty((XLlFifo *)eth_device[eth_dev_num].inf_ref));
774        xil_printf("Base Addr             : 0x%x \n", ((XLlFifo *)eth_device[eth_dev_num].inf_ref)->BaseAddress );
775        xil_printf("RX Occupancy value    : 0x%x \n", ((*(volatile u32 *)((((XLlFifo *)eth_device[eth_dev_num].inf_ref)->BaseAddress) + (0x0000001c)))) );
776#endif
777
778        if( XLlFifo_IsRxEmpty( (XLlFifo *)eth_device[eth_dev_num].inf_ref ) ) {
779            size = -1;
780        } else {
781
782#ifdef _PERFORMANCE_MONITOR_
783            wl_setDebugGPIO(0x1);
784#endif
785            pktBufPtr = eth_device[eth_dev_num].recvbuf;
786
787            if( XLlFifo_RxOccupancy( (XLlFifo *)eth_device[eth_dev_num].inf_ref ) ) {
788           
789                waitForDMA(eth_dev_num);
790               
791                // Set DMA to non-increment source, increment dest addresses
792                XDmaCentral_SetControl( (XDmaCentral *)eth_device[eth_dev_num].inf_dma_ref, XDMC_DMACR_DEST_INCR_MASK );
793           
794                size = XLlFifo_RxGetLen( (XLlFifo *)eth_device[eth_dev_num].inf_ref );
795           
796                XDmaCentral_Transfer((XDmaCentral *)eth_device[eth_dev_num].inf_dma_ref,
797                                     (u8 *)(((XLlFifo *)eth_device[eth_dev_num].inf_ref)->BaseAddress + XLLF_RDFD_OFFSET),
798                                     (u8 *)pktBufPtr, size);
799            }
800        }
801#else
802        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
803        xil_printf("TEMAC. \n");
804        return -1;
805#endif
806        break;
807
808    default:
809        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_DNE, eth_dev_num );
810        return -1;
811        break;
812    }
813
814#if 0
815    xil_printf("Ethernet Recvd Frame of size %d...\n", size);
816    tmp_ptr = (unsigned char *)pktBufPtr;
817    xil_printf("src : %d%d%d%d%d%d...\n", tmp_ptr[0], tmp_ptr[1], tmp_ptr[2], tmp_ptr[3], tmp_ptr[4], tmp_ptr[5]);
818    xil_printf("dst : %d%d%d%d%d%d...\n", tmp_ptr[6], tmp_ptr[7], tmp_ptr[8], tmp_ptr[9], tmp_ptr[10], tmp_ptr[11]);
819    xil_printf("type : %d%d...\n", tmp_ptr[12], tmp_ptr[13]);
820#endif
821 
822    // Strip off the FCS (or CRC) from the received frame
823    size -= 4;
824 
825    // Process the packet
826    if ( size > 0 ) {
827
828#ifdef _DEBUG_
829        xil_printf("BEGIN xilnet_eth_recv_frame() \n" );
830        xil_printf("  Received %d bytes\n", size);
831        tmp_ptr = (unsigned char *)pktBufPtr;
832        xil_printf("  src  : %2x %2x %2x %2x %2x %2x \n", tmp_ptr[0], tmp_ptr[1], tmp_ptr[2], tmp_ptr[3], tmp_ptr[4], tmp_ptr[5]);
833        xil_printf("  dst  : %2x %2x %2x %2x %2x %2x \n", tmp_ptr[6], tmp_ptr[7], tmp_ptr[8], tmp_ptr[9], tmp_ptr[10], tmp_ptr[11]);
834        xil_printf("  type : %2x %2x \n\n", tmp_ptr[12], tmp_ptr[13]);
835        print_pkt((unsigned char *)pktBufPtr, size);
836#endif
837
838        eth = (struct xilnet_eth_hdr*) pktBufPtr;
839   
840        switch (Xil_Ntohs(eth->type)) {
841            case ETH_PROTO_IP:
842                status = (xilnet_ip(pktBufPtr, size, eth_dev_num));
843                break;
844            case ETH_PROTO_ARP:
845                status = (xilnet_arp(pktBufPtr, size, eth_dev_num));
846                break;
847            default:
848#ifdef _DEBUG_
849                xil_printf("Unknown protocol %x...\r\n", eth->type);
850#endif
851            break;
852        }
853
854
855#ifdef XILNET_AXI_DMA_INF_USED
856        // Post process the DMA buffer descriptors now that we are done with them
857        if (eth_device[eth_dev_num].inf_type == XILNET_AXI_DMA_INF) {
858
859            // Free all processed RX BDs for future transmission
860            status = XAxiDma_BdRingFree(RX_RING_ptr, processed_BD_count, BD_ptr);
861            if (status != XST_SUCCESS) {
862                xil_printf("*** Error freeing up %d RxBDs:  0x%8x\n", processed_BD_count, status);
863            }
864
865            // Return processed BDs to RX channel so we are ready to receive new packets:
866            //    - Allocate all free RX BDs
867            //    - Pass the BDs to RX channel
868            free_BD_count = XAxiDma_BdRingGetFreeCnt(RX_RING_ptr);
869
870            status = XAxiDma_BdRingAlloc(RX_RING_ptr, free_BD_count, &BD_ptr);
871            if (status != XST_SUCCESS) {
872                xil_printf("*** Error allocating %d RxBDs:  0x%8x\n", free_BD_count, status);
873            }
874
875            status = XAxiDma_BdRingToHw(RX_RING_ptr, free_BD_count, BD_ptr);
876            if (status != XST_SUCCESS) {
877                xil_printf("*** Error submiting %d rx BDs failed: 0x%8x\r\n", free_BD_count, status);
878            }
879        }
880#endif
881
882#ifdef _DEBUG_
883        xil_printf("END xilnet_eth_recv_frame() \n" );
884#endif
885
886#ifdef _PERFORMANCE_MONITOR_
887        wl_clearDebugGPIO(0x1);
888#endif
889    }
890
891    return status;
892}
893
894
895/*
896 * Send frame to peer ip addr, peer hw addr
897 */
898int xilnet_eth_send_frame(unsigned char *pkt, int len, unsigned char *dip_addr,
899                          void *dhw_addr, unsigned short type, unsigned int eth_dev_num)
900{
901    int i;
902    int hw_tbl_index = 0;
903
904    int status;
905    int size                = 0;
906    int transmit_flag       = 0;
907    unsigned char  *hw_addr = (unsigned char *)dhw_addr;
908
909#ifdef XILNET_AXI_DMA_INF_USED
910    int processed_BD_count  = 0;
911    int dma_status          = 0;
912    int dma_error           = 0;
913    int dma_hang_count      = 1000;
914
915    XAxiDma_BdRing *RX_RING_ptr;
916    XAxiDma_BdRing *TX_RING_ptr;
917    XAxiDma_Bd     *BD_ptr;
918#endif
919
920    // Check to see if we are sending on a valid interface
921    if ( eth_dev_num >= XILNET_NUM_ETH_DEVICES ) {
922        xilnet_eth_print_err_msg( XILNET_ETH_ERR_NUM_DEV, eth_dev_num );
923        return -1;
924    }
925   
926    // Check to see if the xilnet driver uses the Ethernet instance
927    if ( !eth_device[eth_dev_num].uses_driver ) {
928        xilnet_eth_print_err_msg( XILNET_ETH_ERR_USES_DRIVER, eth_dev_num );
929        return -1;
930    }
931   
932#ifdef _DEBUG_
933    xil_printf("BEGIN xilnet_eth_send_frame(): \n");
934    xil_printf("  pkt      = %x \n", pkt);
935    xil_printf("  len      = %d \n", len);
936    xil_printf("  dip_addr = %d.%d.%d.%d \n", dip_addr[0], dip_addr[1], dip_addr[2], dip_addr[3]);
937    xil_printf("  dhw_addr = %02x-%02x-%02x-%02x-%02x-%02x \n", hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3], hw_addr[4], hw_addr[5]);
938    xil_printf("  type     = %x \n", type);
939    xil_printf("  eth_dev  = %c \n", wn_conv_eth_dev_num(eth_dev_num) );
940#endif
941
942#ifdef _PERFORMANCE_MONITOR_
943    wl_setDebugGPIO(0x2);
944#endif
945
946    // Set the source MAC address
947    for (i = 0; i < ETH_ADDR_LEN; i++) {
948        ((struct xilnet_eth_hdr*)pkt)->src_addr[i] = eth_device[eth_dev_num].node_hw_addr[i];
949    }
950
951    // Set the destination MAC address
952    if (dhw_addr)
953        memcpy(((struct xilnet_eth_hdr*)pkt)->dest_addr, dhw_addr, ETH_ADDR_LEN);
954    else {
955        // find the hw tbl entry index corr to dip_addr
956        hw_tbl_index = xilnet_eth_get_hw_addr(dip_addr, eth_dev_num);
957     
958        for (i = 0; i < ETH_ADDR_LEN; i++) {
959            ((struct xilnet_eth_hdr*)pkt)->dest_addr[i] = xilnet_hw_tbl[hw_tbl_index].hw_addr[i];
960        }
961    }
962
963    // Convert Endianess of type
964    ((struct xilnet_eth_hdr*)pkt)->type = Xil_Htons(type);
965   
966    // pad the ethernet frame if < 60 bytes
967    if (len < 60) {
968        for(i = len; i < ETH_MIN_FRAME_LEN; i++) {
969            pkt[i] = 0;
970        }
971        len = ETH_MIN_FRAME_LEN;
972    }
973
974    // Device specific routine for sending a frame
975    switch( eth_device[eth_dev_num].inf_type ) {
976
977    case XILNET_AXI_FIFO_INF:
978
979#ifdef XILNET_AXI_FIFO_INF_USED
980        XLlFifo_Write((XLlFifo *) eth_device[eth_dev_num].inf_ref, pkt, len);
981
982        // Write the length to the LL_FIFO; this write initiates the TEMAC transmission
983        XLlFifo_TxSetLen((XLlFifo *) eth_device[eth_dev_num].inf_ref, len);
984#else
985        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
986        xil_printf("AXI FIFO. \n");
987        return -1;
988#endif
989        break;
990
991
992    case XILNET_AXI_DMA_INF:
993
994#ifdef XILNET_AXI_DMA_INF_USED
995
996        // Get the TX Buffer Descriptor Ring pointer
997        TX_RING_ptr = (XAxiDma_BdRing *)eth_device[eth_dev_num].dma_tx_ring_ref;
998       
999        // Get the RX Buffer Descriptor Ring pointer
1000        RX_RING_ptr = (XAxiDma_BdRing *)eth_device[eth_dev_num].dma_rx_ring_ref;
1001       
1002        // Check to see if we have a RX error
1003        if ( XAxiDma_BdRingGetError( RX_RING_ptr ) ) {
1004#ifdef _DEBUG_
1005            print_XAxiDma_BdRing( RX_RING_ptr );
1006#endif
1007            xil_printf("*** ERROR in RX DMA transfer: 0x%8x \n", XAxiDma_BdRingGetError( RX_RING_ptr ));
1008            dma_error = 1;
1009        }
1010   
1011        // Check to see if we have a TX error
1012        if ( XAxiDma_BdRingGetError( TX_RING_ptr ) ) {
1013#ifdef _DEBUG_
1014            print_XAxiDma_BdRing( TX_RING_ptr );
1015#endif
1016            xil_printf("*** ERROR in TX DMA transfer: 0x%8x \n", XAxiDma_BdRingGetError( TX_RING_ptr ));
1017            dma_error = 1;
1018        }
1019       
1020        // If there is an error, reset the DMA
1021        if ( dma_error ) {
1022            xil_printf("*** Resetting DMA \n");
1023            XAxiDma_Reset( (XAxiDma *)eth_device[eth_dev_num].inf_ref );
1024        }
1025
1026        // Allocate, setup and enqueue a TX BD for the Frame
1027        status = XAxiDma_BdRingAlloc(TX_RING_ptr, 1, &BD_ptr);
1028        if (status != XST_SUCCESS) {
1029            xil_printf("*** Error allocating TX BDs:  0x%8x\n", status);
1030        }
1031
1032        // Set the BD address to the start of the packet
1033        status = XAxiDma_BdSetBufAddr(BD_ptr, (u32) pkt);
1034        if (status != XST_SUCCESS) {
1035            xil_printf("*** Error setting TX Address:  status = 0x%8x;  BD = 0x%x;  addr = 0x%x\n", status, BD_ptr, (u32) pkt);
1036        }
1037
1038        // Set the BD length to the length field
1039        status = XAxiDma_BdSetLength(BD_ptr, len, TX_RING_ptr->MaxTransferLen);
1040        if (status != XST_SUCCESS) {
1041            xil_printf("*** Error setting TX Length:  status = 0x%8x;  BD = 0x%x;  len = %d;  max_len = %d\n", status, BD_ptr, len, TX_RING_ptr->MaxTransferLen);
1042        }
1043
1044        // Since this is a single descriptor, set both SOF and EOF
1045        XAxiDma_BdSetCtrl(BD_ptr, XAXIDMA_BD_CTRL_TXSOF_MASK | XAXIDMA_BD_CTRL_TXEOF_MASK);
1046
1047        // Set the Application specific words
1048        XAxiDma_BdSetAppWord( BD_ptr, 0, 0x00000000 );
1049        XAxiDma_BdSetAppWord( BD_ptr, 1, 0x00000000 );
1050        XAxiDma_BdSetAppWord( BD_ptr, 2, 0x00000000 );
1051        XAxiDma_BdSetAppWord( BD_ptr, 3, 0x00000000 );
1052        XAxiDma_BdSetAppWord( BD_ptr, 4, 0x00000000 );       
1053
1054#ifdef _DEBUG_
1055        print_XAxiDma_BdRing( TX_RING_ptr );
1056        print_XAxiDma_Bd( BD_ptr );
1057#endif
1058
1059        // Enqueue to the HW
1060        status = XAxiDma_BdRingToHw(TX_RING_ptr, 1, BD_ptr);
1061        if (status != XST_SUCCESS) {
1062             // Undo BD allocation and exit
1063            XAxiDma_BdRingUnAlloc(TX_RING_ptr, 1, BD_ptr);
1064            xil_printf("*** Error committing TX BD to HW:  0x%8x\n", status);
1065        }
1066
1067        // Start DMA TX channel. Transmission starts at once. 
1068        //   If the channel is already started, then the XAxiDma_BdRingToHw() call will start the transmission
1069        if (TX_RING_ptr->RunState == AXIDMA_CHANNEL_HALTED) {
1070            status = XAxiDma_BdRingStart(TX_RING_ptr);
1071            if (status != XST_SUCCESS) {
1072                xil_printf("*** Error starting TX BD:  0x%8x\n", status);
1073            }
1074        }
1075
1076        // Poll to find when we are done transmitting the packet
1077        // TODO:  We can change this to non-blocking by moving these checks above the allocate calls
1078        transmit_flag = 0;
1079
1080        while ( transmit_flag == 0 ) {
1081       
1082            processed_BD_count = XAxiDma_BdRingFromHw(TX_RING_ptr, 1, &BD_ptr);
1083
1084            if ( processed_BD_count > 0 ) {
1085
1086#ifdef _DEBUG_
1087                print_XAxiDma_BdRing( TX_RING_ptr );
1088                print_XAxiDma_Bd( BD_ptr );
1089#endif
1090                status = XAxiDma_BdGetSts(BD_ptr);
1091
1092                if ((status & XAXIDMA_BD_STS_ALL_ERR_MASK) || (!(status & XAXIDMA_BD_STS_COMPLETE_MASK))) {
1093                    xil_printf("*** TX Error: 0x%x\n", status);
1094                } else {
1095                    size = (XAxiDma_BdRead(BD_ptr, XAXIDMA_BD_STS_OFFSET)) & 0x0000FFFF;
1096                }
1097
1098                if ( size != len ) {
1099                    xil_printf("*** Size of transmission (0x%x) does not match length of packet (0x%x)\n", size, len);
1100                }
1101
1102                // Clear out all the control / status information before freeing the buffer descriptor
1103                XAxiDma_BdClear(BD_ptr);
1104
1105                // Free all processed RX BDs for future transmission
1106                status = XAxiDma_BdRingFree(TX_RING_ptr, processed_BD_count, BD_ptr);
1107                if (status != XST_SUCCESS) {
1108                    xil_printf("*** Error freeing up %d RxBDs:  0x%8x\n", processed_BD_count, status);
1109                }
1110
1111#ifdef _DEBUG_
1112                print_XAxiDma_BdRing( TX_RING_ptr );
1113                print_XAxiDma_Bd( BD_ptr );
1114#endif
1115
1116                transmit_flag = 1;
1117            }
1118            else {
1119
1120                if ( XAxiDma_BdRingBusy( TX_RING_ptr ) ) {
1121               
1122                    // HW is still busy with the transfer                   
1123                    if ( dma_hang_count == 0 ) {
1124                        xil_printf("  **** ERROR:  Trying to send on Ethernet device %c.  Driver timed out while device was busy.  Unknown ERROR. \n", wn_conv_eth_dev_num(eth_dev_num) );
1125                        return -1;
1126                    } else {
1127                        dma_hang_count--;
1128                    }
1129                } else {
1130
1131                    // Check to see if we have an error
1132                    dma_status = XAxiDma_BdRingGetError( TX_RING_ptr );
1133                   
1134                    if ( dma_status != 0 ) {
1135                        xil_printf("*** ERROR in DMA transfer: 0x%8x \n", dma_status);
1136#ifdef _DEBUG_
1137                        print_XAxiDma_BdRing( TX_RING_ptr );
1138                        print_XAxiDma_Bd( TX_RING_ptr->HwHead );
1139#endif
1140                        // Restart DMA TX channel.
1141                        xil_printf("*** Restarting transfer \n");
1142                        XAxiDma_Reset( (XAxiDma *)eth_device[eth_dev_num].inf_ref );
1143                       
1144                        status = XAxiDma_BdRingStart(TX_RING_ptr);
1145                        if (status != XST_SUCCESS) {
1146                            xil_printf("*** Error starting TX BD:  0x%8x\n", status);
1147                        }
1148                    } else {
1149                        // In the case of large packets, we can encounter a situation where we finish the processing of the
1150                        // packet between the XAxiDma_BdRingFromHw() function call and the XAxiDma_BdRingBusy() function call.
1151                        // In this case, we now have a situation where the DMA is not busy and does not have an error, but we
1152                        // just need to run through the loop one more time in order to finish the transaction.  However,
1153                        // to make sure we don't get stuck in this case (ie there is a packet to process, we are going to
1154                        // enforce a timeout.
1155                       
1156                        if ( dma_hang_count == 0 ) {
1157                            xil_printf("  **** ERROR:  Trying to send on Ethernet device %c.  Driver timed out while device was idle.  Unknown ERROR. \n", wn_conv_eth_dev_num(eth_dev_num) );
1158                            return -1;
1159                        } else {
1160                            dma_hang_count--;
1161                        }
1162                    }
1163                }
1164            }
1165        }
1166
1167#else
1168        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
1169        xil_printf("AXI DMA. \n");
1170        return -1;
1171#endif
1172        break;
1173
1174    case XILNET_TEMAC_INF:
1175
1176#ifdef XILNET_TEMAC_INF_USED
1177        waitForDMA(eth_dev_num);
1178
1179        // Set DMA to increment src, non-increment dest addresses
1180        XDmaCentral_SetControl((XDmaCentral *)eth_device[eth_dev_num].inf_dma_ref, XDMC_DMACR_SOURCE_INCR_MASK);
1181
1182        // Transfer the packet into the LLFIFO
1183        XDmaCentral_Transfer((XDmaCentral *)eth_device[eth_dev_num].inf_dma_ref, (u8 *)(pkt),
1184                             (u8 *)(((XLlFifo *)eth_device[eth_dev_num].inf_ref)->BaseAddress + XLLF_TDFD_OFFSET), len);
1185
1186        waitForDMA(eth_dev_num);
1187
1188        // Write the length to the LL_FIFO; this write initiates the TEMAC transmission
1189        XLlFifo_TxSetLen((XLlFifo *)eth_device[eth_dev_num].inf_ref, len);
1190
1191#else
1192        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_NOT_CONFIG, eth_dev_num );
1193        xil_printf("TEMAC. \n");
1194        return -1;
1195#endif
1196        break;
1197
1198    default:
1199        xilnet_eth_print_err_msg( XILNET_ETH_ERR_INF_DNE, eth_dev_num );
1200        return -1;
1201        break;
1202    }
1203
1204#ifdef _PERFORMANCE_MONITOR_
1205    wl_clearDebugGPIO(0x2);
1206#endif
1207   
1208#ifdef _DEBUG_
1209    xil_printf("  Sent %d bytes\n",len);
1210    xil_printf("END xilnet_eth_send_frame() \n\n");
1211#endif
1212
1213   return len;
1214}
1215
1216
1217/*
1218 * Update Hardware Address Table
1219 */
1220
1221void xilnet_eth_update_hw_tbl(unsigned char *buf, int proto, unsigned int eth_dev_num) {
1222   
1223   unsigned char ip[IP_VERSION];
1224   unsigned char hw[ETH_ADDR_LEN];
1225   int i, j;
1226
1227   // Update the current age
1228   curr_age++;
1229   
1230   // get hw addr
1231   for (i = 0; i < ETH_ADDR_LEN; i++) {
1232      hw[i] = ((struct xilnet_eth_hdr*)buf)->src_addr[i];
1233   }     
1234
1235   // get ip addr
1236   switch (proto) {
1237   case ETH_PROTO_ARP:
1238      for (i = 0; i < IP_VERSION; i++) {
1239         ip[i] = (buf+ETH_HDR_LEN)[ARP_SIP_OFFSET+i];
1240      }
1241      break;
1242   case ETH_PROTO_IP:
1243      for (i = 0; i < IP_VERSION; i++) {
1244         ip[i] = (buf+ETH_HDR_LEN)[IP_SADDR_BASE+i];
1245      }
1246      break;
1247   }
1248
1249   // update the hw addr table
1250   for (i = 0; i < HW_ADDR_TBL_ENTRIES; i++) {
1251      if (xilnet_hw_tbl[i].flag) {
1252         if ( (hw[0] == xilnet_hw_tbl[i].hw_addr[0]) &&
1253              (hw[1] == xilnet_hw_tbl[i].hw_addr[1]) &&
1254              (hw[2] == xilnet_hw_tbl[i].hw_addr[2]) &&
1255              (hw[3] == xilnet_hw_tbl[i].hw_addr[3]) &&
1256              (hw[4] == xilnet_hw_tbl[i].hw_addr[4]) &&
1257              (hw[5] == xilnet_hw_tbl[i].hw_addr[5])
1258              ) {
1259            for (j = 0; j < IP_VERSION; j++)
1260               xilnet_hw_tbl[i].ip_addr[j] = ip[j];;
1261            xilnet_hw_tbl[i].flag = HW_ADDR_ENTRY_IS_TRUE;
1262            xilnet_hw_tbl[i].age = curr_age;
1263            return;
1264         }
1265      }
1266   }
1267   xilnet_eth_add_hw_tbl_entry(ip, hw, eth_dev_num);
1268}
1269
1270
1271/*
1272 * Add an entry into Hw Addr table
1273 */
1274
1275void xilnet_eth_add_hw_tbl_entry(unsigned char *ip, unsigned char *hw, unsigned int eth_dev_num)
1276{
1277   int i, j;
1278   
1279   for (i = 0; i < HW_ADDR_TBL_ENTRIES; i++) {
1280      if (!xilnet_hw_tbl[i].flag) {
1281         for (j = 0; j < ETH_ADDR_LEN; j++) {
1282            xilnet_hw_tbl[i].hw_addr[j] = hw[j];
1283         }
1284         for (j = 0; j < IP_VERSION; j++)  {
1285            xilnet_hw_tbl[i].ip_addr[j] = ip[j];
1286         }
1287         xilnet_hw_tbl[i].flag = HW_ADDR_ENTRY_IS_TRUE;
1288         xilnet_hw_tbl[i].age = curr_age;
1289
1290#if _DEBUG_XILNET_HW_TABLE_
1291         xil_printf("xilnet_add_hw_tbl_entry: \n");
1292         print_hw_tbl();
1293#endif
1294         
1295         return;
1296      }
1297   }
1298   
1299   // Find an old entry to be eliminated from hw tbl
1300   i = xilnet_eth_find_old_entry(eth_dev_num);
1301   for (j = 0; j < ETH_ADDR_LEN; j++) {
1302      xilnet_hw_tbl[i].hw_addr[j] = hw[j];
1303   }
1304   for (j = 0; j < IP_VERSION; j++)  {
1305      xilnet_hw_tbl[i].ip_addr[j] = ip[j];
1306   }
1307   xilnet_hw_tbl[i].flag = HW_ADDR_ENTRY_IS_TRUE;
1308   xilnet_hw_tbl[i].age = curr_age;
1309
1310#if _DEBUG_XILNET_HW_TABLE_
1311   xil_printf("xilnet_add_hw_tbl_entry: \n");
1312   print_hw_tbl();
1313#endif
1314
1315}
1316
1317
1318/*
1319 * Get index into hw tbl for ip_addr
1320 */
1321
1322int xilnet_eth_get_hw_addr(unsigned char *ip, unsigned int eth_dev_num) {
1323   
1324   int i;
1325   
1326   for (i = 0; i < HW_ADDR_TBL_ENTRIES; i++) {
1327      if (xilnet_hw_tbl[i].flag) 
1328         if ( (ip[0] == xilnet_hw_tbl[i].ip_addr[0]) &&
1329              (ip[1] == xilnet_hw_tbl[i].ip_addr[1]) &&
1330              (ip[2] == xilnet_hw_tbl[i].ip_addr[2]) &&
1331              (ip[3] == xilnet_hw_tbl[i].ip_addr[3]) ) {
1332            return i;
1333         }
1334   }
1335
1336#if _DEBUG_XILNET_HW_TABLE_
1337   xil_printf("xilnet_eth_get_hw_addr: \n");
1338   print_hw_tbl();
1339#endif
1340   
1341   xil_printf("Hw Addr Not found for IP \r\n");
1342   return -1;
1343}
1344
1345
1346/* 
1347 * Init the hw addr table
1348 */
1349
1350void xilnet_eth_init_hw_addr_tbl(unsigned int eth_dev_num) {
1351   
1352  int i;
1353 
1354  for (i = 0; i < HW_ADDR_TBL_ENTRIES; i++) {
1355     xilnet_hw_tbl[i].flag = HW_ADDR_ENTRY_IS_FALSE;
1356     xilnet_hw_tbl[i].age = 0;
1357  }
1358 
1359  ishwaddrinit = 1;
1360
1361#if _DEBUG_XILNET_HW_TABLE_
1362  xil_printf("xilnet_eth_init_hw_addr_tbl: \n");
1363  print_hw_tbl();
1364#endif
1365
1366}
1367
1368
1369/*
1370 * Find the oldest entry in the Hw Table and
1371 * return its index
1372 */
1373
1374int xilnet_eth_find_old_entry(unsigned int eth_dev_num)
1375{
1376   int i;
1377   int oldest_age = 0;
1378   int oldest = 0;
1379   
1380   for (i = 0; i < HW_ADDR_TBL_ENTRIES; i++) {
1381     
1382      if (curr_age - xilnet_hw_tbl[i].age > HW_ADDR_TBL_MAXAGE) {
1383         oldest = i;
1384         break;
1385      }
1386      else {
1387         if (( curr_age - xilnet_hw_tbl[i].age) > oldest_age) {
1388            oldest_age = curr_age - xilnet_hw_tbl[i].age;
1389            oldest = i;
1390         }
1391      }
1392   }
1393   
1394   return oldest;
1395}
1396
1397
1398// Debug printing functions for various structures
1399
1400#if _DEBUG_XILNET_HW_TABLE_
1401void print_hw_tbl()
1402{
1403    int i, j;
1404
1405    xil_printf("Ethernet HW Table \n");
1406
1407    for (i=0; i<HW_ADDR_TBL_ENTRIES; i++) {
1408        xil_printf("  IP : ");
1409        for (j=0; j<IP_VERSION; j++) {
1410            xil_printf("%d.", xilnet_hw_tbl[i].ip_addr[j]);
1411        }
1412
1413        xil_printf("    HW : ");
1414        for (j=0; j<ETH_ADDR_LEN; j++) {
1415            xil_printf("%x ", xilnet_hw_tbl[i].hw_addr[j]);
1416        }
1417
1418        xil_printf("    \n");
1419    }
1420    xil_printf("\n");
1421}
1422#endif
1423
1424#ifdef _DEBUG_
1425
1426void print_pkt(unsigned char *buf, int size)
1427{
1428    int i;
1429
1430    xil_printf("Ethernet Packet: (0x%x bytes)\n", size);
1431
1432    for (i=0; i<size; i++) {
1433        xil_printf("%2x ", buf[i]);
1434        if ( (((i + 1) % 16) == 0) && ((i + 1) != size) ) {
1435            xil_printf("\n");
1436        }
1437    }
1438    xil_printf("\n\n");
1439}
1440
1441
1442#ifdef  XILNET_AXI_DMA_INF_USED
1443void print_XAxiDma_Bd( XAxiDma_Bd *BD_ptr ) {
1444
1445    int i;
1446
1447    xil_printf("Buffer Descriptor: 0x%x\n", BD_ptr);
1448    for ( i = 0; i < XAXIDMA_BD_NUM_WORDS; i++ ) {
1449        xil_printf("  Value[%2d]:        0x%x \n", i, (*BD_ptr)[i]);
1450    }
1451    xil_printf("\n");
1452}
1453
1454
1455void print_XAxiDma_BdRing( XAxiDma_BdRing *BD_RING_ptr ) {
1456
1457    xil_printf("Buffer Descriptor Ring Pointer: \n");
1458    xil_printf("  ChanBase:         0x%x \n", BD_RING_ptr->ChanBase);
1459    xil_printf("  IsRxChannel:      0x%x \n", BD_RING_ptr->IsRxChannel);
1460    xil_printf("  RunState:         0x%x \n", BD_RING_ptr->RunState);
1461    xil_printf("  HasStsCntrlStrm:  0x%x \n", BD_RING_ptr->HasStsCntrlStrm);
1462    xil_printf("  HasDRE:           0x%x \n", BD_RING_ptr->HasDRE);
1463    xil_printf("  DataWidth:        0x%x \n", BD_RING_ptr->DataWidth);
1464    xil_printf("  MaxTransferLen:   0x%x \n", BD_RING_ptr->MaxTransferLen);
1465    xil_printf("  FirstBdPhysAddr:  0x%x \n", BD_RING_ptr->FirstBdPhysAddr);
1466    xil_printf("  FirstBdAddr:      0x%x \n", BD_RING_ptr->FirstBdAddr);
1467    xil_printf("  LastBdAddr:       0x%x \n", BD_RING_ptr->LastBdAddr);
1468    xil_printf("  Length:           0x%x \n", BD_RING_ptr->Length);
1469    xil_printf("  Separation:       0x%x \n", BD_RING_ptr->Separation);
1470    xil_printf("  FreeHead:         0x%x \n", BD_RING_ptr->FreeHead);
1471    xil_printf("  PreHead:          0x%x \n", BD_RING_ptr->PreHead);
1472    xil_printf("  HwHead:           0x%x \n", BD_RING_ptr->HwHead);
1473    xil_printf("  HwTail:           0x%x \n", BD_RING_ptr->HwTail);
1474    xil_printf("  PostHead:         0x%x \n", BD_RING_ptr->PostHead);
1475    xil_printf("  BdaRestart:       0x%x \n", BD_RING_ptr->BdaRestart);
1476    xil_printf("  FreeCnt:          0x%x \n", BD_RING_ptr->FreeCnt);
1477    xil_printf("  PreCnt:           0x%x \n", BD_RING_ptr->PreCnt);
1478    xil_printf("  HwCnt:            0x%x \n", BD_RING_ptr->HwCnt);
1479    xil_printf("  PostCnt:          0x%x \n", BD_RING_ptr->PostCnt);
1480    xil_printf("  AllCnt:           0x%x \n", BD_RING_ptr->AllCnt);
1481    xil_printf("  RingIndex:        0x%x \n", BD_RING_ptr->RingIndex);
1482    xil_printf("\n");
1483}
1484
1485
1486void print_XAxiDma_Config( XAxiDma_Config * DMA_CFG_ptr ) {
1487
1488    xil_printf("DMA Config Pointer: \n");
1489    xil_printf("  DeviceId:         0x%x \n", DMA_CFG_ptr->DeviceId);
1490    xil_printf("  BaseAddr:         0x%x \n", DMA_CFG_ptr->BaseAddr);
1491    xil_printf("  HasStsCntrlStrm:  0x%x \n", DMA_CFG_ptr->HasStsCntrlStrm);
1492    xil_printf("  HasMm2S:          0x%x \n", DMA_CFG_ptr->HasMm2S);
1493    xil_printf("  HasMm2SDRE:       0x%x \n", DMA_CFG_ptr->HasMm2SDRE);
1494    xil_printf("  Mm2SDataWidth:    0x%x \n", DMA_CFG_ptr->Mm2SDataWidth);
1495    xil_printf("  HasS2Mm:          0x%x \n", DMA_CFG_ptr->HasS2Mm);
1496    xil_printf("  HasS2MmDRE:       0x%x \n", DMA_CFG_ptr->HasS2MmDRE);
1497    xil_printf("  S2MmDataWidth:    0x%x \n", DMA_CFG_ptr->S2MmDataWidth);
1498    xil_printf("  HasSg:            0x%x \n", DMA_CFG_ptr->HasSg);
1499    xil_printf("  Mm2sNumChannels:  0x%x \n", DMA_CFG_ptr->Mm2sNumChannels);
1500    xil_printf("  S2MmNumChannels:  0x%x \n", DMA_CFG_ptr->S2MmNumChannels);
1501    xil_printf("\n");
1502}
1503#endif
1504
1505#ifdef XILNET_AXI_FIFO_INF_USED
1506void print_XLlFifo( XLlFifo * FIFO_ptr ) {
1507
1508    xil_printf("FIFO Pointer: \n");
1509    xil_printf("  BaseAddress:       0x%x \n", FIFO_ptr->BaseAddress);
1510    xil_printf("  IsReady:           0x%x \n", FIFO_ptr->IsReady);
1511    xil_printf("  RX instance:       0x%x \n", FIFO_ptr->RxStreamer.FifoInstance);
1512    xil_printf("  RX width:          0x%x \n", FIFO_ptr->RxStreamer.FifoWidth);
1513    xil_printf("  RX HeadIndex:      0x%x \n", FIFO_ptr->RxStreamer.HeadIndex);
1514    xil_printf("  RX FrmByteCnt:     0x%x \n", FIFO_ptr->RxStreamer.FrmByteCnt);
1515    xil_printf("  TX instance:       0x%x \n", FIFO_ptr->TxStreamer.FifoInstance);
1516    xil_printf("  TX width:          0x%x \n", FIFO_ptr->TxStreamer.FifoWidth);
1517    xil_printf("  TX HeadIndex:      0x%x \n", FIFO_ptr->TxStreamer.TailIndex);
1518    xil_printf("\n");
1519}
1520#endif
1521
1522#endif
1523
1524
1525
Note: See TracBrowser for help on using the repository browser.